Skip to content

Commit

Permalink
[ELF] Read ARM BuildAttributes section to determine supported features.
Browse files Browse the repository at this point in the history
lld assumes some ARM features that are not available in all Arm
processors. In particular:
- The blx instruction present for interworking.
- The movt/movw instructions are used in Thunks.
- The J1=1 J2=1 encoding of branch immediates to improve Thumb wide
  branch range are assumed to be present.

This patch reads the ARM Attributes section to check for the
architecture the object file was compiled with. If none of the objects
have an architecture that supports either of these features a warning
will be given. This is most likely to affect armv6 as used in the first
Raspberry Pi.

Differential Revision: https://reviews.llvm.org/D36823

llvm-svn: 319169
  • Loading branch information
smithp35 committed Nov 28, 2017
1 parent 9d419d3 commit 57eb046
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 5 deletions.
3 changes: 3 additions & 0 deletions lld/ELF/Config.h
Expand Up @@ -105,6 +105,9 @@ struct Configuration {
std::vector<uint8_t> BuildIdVector;
bool AllowMultipleDefinition;
bool AndroidPackDynRelocs = false;
bool ARMHasBlx = false;
bool ARMHasMovtMovw = false;
bool ARMJ1J2BranchEncoding = false;
bool AsNeeded = false;
bool Bsymbolic;
bool BsymbolicFunctions;
Expand Down
15 changes: 15 additions & 0 deletions lld/ELF/Driver.cpp
Expand Up @@ -1118,6 +1118,21 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {

Config->EFlags = Target->calcEFlags();

if (Config->EMachine == EM_ARM) {
// FIXME: These warnings can be removed when lld only uses these features
// when the input objects have been compiled with an architecture that
// supports them.
if (Config->ARMHasBlx == false)
warn("lld uses blx instruction, no object with architecture supporting "
"feature detected.");
if (Config->ARMJ1J2BranchEncoding == false)
warn("lld uses extended branch encoding, no object with architecture "
"supporting feature detected.");
if (Config->ARMHasMovtMovw == false)
warn("lld may use movt/movw, no object with architecture supporting "
"feature detected.");
}

// This adds a .comment section containing a version string. We have to add it
// before decompressAndMergeSections because the .comment section is a
// mergeable section.
Expand Down
58 changes: 53 additions & 5 deletions lld/ELF/InputFiles.cpp
Expand Up @@ -23,6 +23,8 @@
#include "llvm/LTO/LTO.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TarWriter.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -394,6 +396,48 @@ void ObjFile<ELFT>::initializeSections(
}
}

// The ARM support in lld makes some use of instructions that are not available
// on all ARM architectures. Namely:
// - Use of BLX instruction for interworking between ARM and Thumb state.
// - Use of the extended Thumb branch encoding in relocation.
// - Use of the MOVT/MOVW instructions in Thumb Thunks.
// The ARM Attributes section contains information about the architecture chosen
// at compile time. We follow the convention that if at least one input object
// is compiled with an architecture that supports these features then lld is
// permitted to use them.
static void updateSupportedARMFeatures(const ARMAttributeParser &Attributes) {
if (!Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
return;
auto Arch = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
switch (Arch) {
case ARMBuildAttrs::Pre_v4:
case ARMBuildAttrs::v4:
case ARMBuildAttrs::v4T:
// Architectures prior to v5 do not support BLX instruction
break;
case ARMBuildAttrs::v5T:
case ARMBuildAttrs::v5TE:
case ARMBuildAttrs::v5TEJ:
case ARMBuildAttrs::v6:
case ARMBuildAttrs::v6KZ:
case ARMBuildAttrs::v6K:
Config->ARMHasBlx = true;
// Architectures used in pre-Cortex processors do not support
// The J1 = 1 J2 = 1 Thumb branch range extension, with the exception
// of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do.
break;
default:
// All other Architectures have BLX and extended branch encoding
Config->ARMHasBlx = true;
Config->ARMJ1J2BranchEncoding = true;
if (Arch != ARMBuildAttrs::v6_M && Arch != ARMBuildAttrs::v6S_M)
// All Architectures used in Cortex processors with the exception
// of v6-M and v6S-M have the MOVT and MOVW instructions.
Config->ARMHasMovtMovw = true;
break;
}
}

template <class ELFT>
InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
uint32_t Idx = Sec.sh_info;
Expand Down Expand Up @@ -426,16 +470,20 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
StringRef Name = getSectionName(Sec);

switch (Sec.sh_type) {
case SHT_ARM_ATTRIBUTES:
// FIXME: ARM meta-data section. Retain the first attribute section
// we see. The eglibc ARM dynamic loaders require the presence of an
// attribute section for dlopen to work.
// In a full implementation we would merge all attribute sections.
case SHT_ARM_ATTRIBUTES: {
ARMAttributeParser Attributes;
ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec));
Attributes.Parse(Contents, /*isLittle*/Config->EKind == ELF32LEKind);
updateSupportedARMFeatures(Attributes);
// FIXME: Retain the first attribute section we see. The eglibc ARM
// dynamic loaders require the presence of an attribute section for dlopen
// to work. In a full implementation we would merge all attribute sections.
if (InX::ARMAttributes == nullptr) {
InX::ARMAttributes = make<InputSection>(this, &Sec, Name);
return InX::ARMAttributes;
}
return &InputSection::Discarded;
}
case SHT_RELA:
case SHT_REL: {
// Find the relocation target section and associate this
Expand Down
51 changes: 51 additions & 0 deletions lld/test/ELF/arm-bl-v6.s
@@ -0,0 +1,51 @@
// RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t
// RUN: ld.lld %t -o %t2 2>&1 | FileCheck %s
// Requires: arm

// On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the
// extended range encoding is not supported. The following example has a Thumb
// BL that is out of range on ARM v6 and requires a range extension thunk.
// As v6 does not support MOVT or MOVW instructions the Thunk must not
// use these instructions either. At present we don't support v6 so we give a
// warning for unsupported features.

// CHECK: warning: lld uses extended branch encoding, no object with architecture supporting feature detected.
// CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected.
// ARM v6 supports blx so we shouldn't see the blx not supported warning.
// CHECK-NOT: warning: lld uses blx instruction, no object with architecture supporting feature detected.
.text
.syntax unified
.cpu arm1176jzf-s
.eabi_attribute 6, 6 @ Tag_CPU_arch
.globl _start
.type _start,%function
.balign 0x1000
_start:
bl thumbfunc
bx lr

.thumb
.section .text.2, "ax", %progbits
.globl thumbfunc
.type thumbfunc,%function
thumbfunc:
bl farthumbfunc

// 6 Megabytes, enough to make farthumbfunc out of range of caller on a v6
// Arm, but not on a v7 Arm.
.section .text.3, "ax", %progbits
.space 0x200000

.section .text.4, "ax", %progbits
.space 0x200000

.section .text.5, "ax", %progbits
.space 0x200000

.thumb
.section .text.6, "ax", %progbits
.balign 0x1000
.globl farthumbfunc
.type farthumbfunc,%function
farthumbfunc:
bx lr
30 changes: 30 additions & 0 deletions lld/test/ELF/arm-blx-v4t.s
@@ -0,0 +1,30 @@
// RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t
// RUN: ld.lld %t -o %t2 2>&1 | FileCheck %s
// REQUIRES: arm

// On Arm v4t there is no blx instruction so all interworking must go via
// a thunk. At present we don't support v4t so we give a warning for unsupported
// features.

// CHECK: warning: lld uses blx instruction, no object with architecture supporting feature detected.
// CHECK-NEXT: warning: lld uses extended branch encoding, no object with architecture supporting feature detected.
// CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected.

.text
.syntax unified
.cpu arm7tdmi
.eabi_attribute 6, 2 @ Tag_CPU_arch
.arm
.globl _start
.type _start,%function
.p2align 2
_start:
bl thumbfunc
bx lr

.thumb
.section .text.2, "ax", %progbits
.globl thumbfunc
.type thumbfunc,%function
thumbfunc:
bx lr

0 comments on commit 57eb046

Please sign in to comment.