diff options
| author | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-03-26 07:47:16 +0000 |
|---|---|---|
| committer | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-03-26 07:47:16 +0000 |
| commit | 9e473d0929c86a425bcfd7065912182fb60bb608 (patch) | |
| tree | e2f2bb81c92df386f8c1a9b9ea340033e1151b4e | |
| parent | c7efd564bb07977db15949ee72a7a3369e870c2a (diff) | |
| download | bcm5719-llvm-9e473d0929c86a425bcfd7065912182fb60bb608.tar.gz bcm5719-llvm-9e473d0929c86a425bcfd7065912182fb60bb608.zip | |
[ARM] Handle mapping symbols
Mapping symbols should have their own code models,
and in some places must be treated in a specific way.
Make $t denote Thumb code, and $a and $d denote ARM code.
Set size, binding and type of mapping symbols to what the specification says.
Differential Revision: http://reviews.llvm.org/D8601
llvm-svn: 233259
| -rw-r--r-- | lld/include/lld/Core/DefinedAtom.h | 5 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h | 50 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp | 17 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h | 7 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h | 11 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Atoms.h | 6 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp | 3 | ||||
| -rw-r--r-- | lld/test/elf/ARM/mapping-code-model.test | 163 | ||||
| -rw-r--r-- | lld/test/elf/ARM/mapping-symbols.test | 123 |
11 files changed, 373 insertions, 16 deletions
diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h index 986c7ff5ad1..6c6d1f9ef9b 100644 --- a/lld/include/lld/Core/DefinedAtom.h +++ b/lld/include/lld/Core/DefinedAtom.h @@ -190,11 +190,16 @@ public: // Attributes describe a code model used by the atom. enum CodeModel { codeNA, // no specific code model + // MIPS code models codeMipsPIC, // PIC function in a PIC / non-PIC mixed file codeMipsMicro, // microMIPS instruction encoding codeMipsMicroPIC, // microMIPS instruction encoding + PIC codeMips16, // MIPS-16 instruction encoding + // ARM code models codeARMThumb, // ARM Thumb instruction set + codeARM_a, // $a-like mapping symbol (for ARM code) + codeARM_d, // $d-like mapping symbol (for data) + codeARM_t, // $t-like mapping symbol (for Thumb code) }; struct Alignment { diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h b/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h index 84af660565f..060dccbd372 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMELFFile.h @@ -17,31 +17,39 @@ namespace elf { class ARMLinkingContext; -template <class ELFT> class ARMELFDefinedAtom : public ELFDefinedAtom<ELFT> { - typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; - typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; +template <class ELFT, DefinedAtom::CodeModel Model> +class ARMELFMappingAtom : public ELFDefinedAtom<ELFT> { +public: + template<typename... T> + ARMELFMappingAtom(T&&... args) + : ELFDefinedAtom<ELFT>(std::forward<T>(args)...) {} + DefinedAtom::CodeModel codeModel() const override { + return Model; + } +}; + +template <class ELFT> class ARMELFDefinedAtom : public ELFDefinedAtom<ELFT> { public: template<typename... T> ARMELFDefinedAtom(T&&... args) : ELFDefinedAtom<ELFT>(std::forward<T>(args)...) {} - bool isThumbFunc(const Elf_Sym *symbol) const { + bool isThumbFunc() const { + const auto* symbol = this->_symbol; return symbol->getType() == llvm::ELF::STT_FUNC && (static_cast<uint64_t>(symbol->st_value) & 0x1); } /// Correct st_value for symbols addressing Thumb instructions /// by removing its zero bit. - uint64_t getSymbolValue(const Elf_Sym *symbol) const override { - const auto value = static_cast<uint64_t>(symbol->st_value); - return isThumbFunc(symbol) ? value & ~0x1 : value; + uint64_t getSymbolValue() const override { + const auto value = static_cast<uint64_t>(this->_symbol->st_value); + return isThumbFunc() ? value & ~0x1 : value; } DefinedAtom::CodeModel codeModel() const override { - if (isThumbFunc(this->_symbol)) - return DefinedAtom::codeARMThumb; - return DefinedAtom::codeNA; + return isThumbFunc() ? DefinedAtom::codeARMThumb : DefinedAtom::codeNA; } }; @@ -74,6 +82,28 @@ private: ArrayRef<uint8_t> contentData, unsigned int referenceStart, unsigned int referenceEnd, std::vector<ELFReference<ELFT> *> &referenceList) override { + if (symName.size() >= 2 && symName[0] == '$') { + switch (symName[1]) { + case 'a': + return new (this->_readerStorage) + ARMELFMappingAtom<ELFT, DefinedAtom::codeARM_a>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + case 'd': + return new (this->_readerStorage) + ARMELFMappingAtom<ELFT, DefinedAtom::codeARM_d>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + case 't': + return new (this->_readerStorage) + ARMELFMappingAtom<ELFT, DefinedAtom::codeARM_t>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + default: + // Fall through and create regular defined atom. + break; + } + } return new (this->_readerStorage) ARMELFDefinedAtom<ELFT>( *this, symName, sectionName, sym, sectionHdr, contentData, referenceStart, referenceEnd, referenceList); diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp index 5f243667426..cc138ddf656 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp @@ -32,3 +32,20 @@ void elf::ARMLinkingContext::addPasses(PassManager &pm) { pm.add(std::move(pass)); ELFLinkingContext::addPasses(pm); } + +bool elf::isARMCode(const DefinedAtom *atom) { + return isARMCode(atom->codeModel()); +} + +bool elf::isARMCode(DefinedAtom::CodeModel codeModel) { + return !isThumbCode(codeModel); +} + +bool elf::isThumbCode(const DefinedAtom *atom) { + return isThumbCode(atom->codeModel()); +} + +bool elf::isThumbCode(DefinedAtom::CodeModel codeModel) { + return codeModel == DefinedAtom::codeARMThumb || + codeModel == DefinedAtom::codeARM_t; +} diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h index 249b79c4f07..ebb9e1595ad 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h @@ -30,6 +30,13 @@ public: return _baseAddress; } }; + +// Special methods to check code model of atoms. +bool isARMCode(const DefinedAtom *atom); +bool isARMCode(DefinedAtom::CodeModel codeModel); +bool isThumbCode(const DefinedAtom *atom); +bool isThumbCode(DefinedAtom::CodeModel codeModel); + } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp index d24fdf0fa41..3032a98f798 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -432,7 +432,7 @@ std::error_code ARMTargetRelocationHandler::applyRelocation( bool addressesThumb = false; if (const auto *definedAtom = dyn_cast<DefinedAtom>(ref.target())) { - addressesThumb = (DefinedAtom::codeARMThumb == definedAtom->codeModel()); + addressesThumb = isThumbCode(definedAtom); } switch (ref.kindValue()) { diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp index 83c21c12eb1..9882df996b3 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp @@ -155,7 +155,7 @@ protected: // Target symbol and relocated place should have different // instruction sets in order a veneer to be generated in between. const auto *target = dyn_cast<DefinedAtom>(ref.target()); - if (!target || target->codeModel() == atom.codeModel()) + if (!target || isThumbCode(target) == isThumbCode(&atom)) return std::error_code(); // TODO: For unconditional jump instructions (R_ARM_CALL and R_ARM_THM_CALL) diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h b/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h index 540a480421a..5c9fec5d550 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h @@ -35,9 +35,18 @@ void ARMSymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da, int64_t addr) { SymbolTable<ELFT>::addDefinedAtom(sym, da, addr); - // Set zero bit to distinguish symbols addressing Thumb instructions + // Set zero bit to distinguish real symbols addressing Thumb instructions. + // Don't care about mapping symbols like $t and others. if (DefinedAtom::codeARMThumb == da->codeModel()) sym.st_value = static_cast<int64_t>(sym.st_value) | 0x1; + + // Mapping symbols should have special values of binding, type and size set. + if ((DefinedAtom::codeARM_a == da->codeModel()) || + (DefinedAtom::codeARM_d == da->codeModel()) || + (DefinedAtom::codeARM_t == da->codeModel())) { + sym.setBindingAndType(llvm::ELF::STB_LOCAL, llvm::ELF::STT_NOTYPE); + sym.st_size = 0; + } } } // elf diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h index bf80ebf0a69..df9f38858c8 100644 --- a/lld/lib/ReaderWriter/ELF/Atoms.h +++ b/lld/lib/ReaderWriter/ELF/Atoms.h @@ -293,7 +293,7 @@ public: return 1; // Obtain proper value of st_value field. - const auto symValue = getSymbolValue(_symbol); + const auto symValue = getSymbolValue(); // Unallocated common symbols specify their alignment constraints in // st_value. @@ -429,8 +429,8 @@ public: protected: /// Returns correct st_value for the symbol depending on the architecture. /// For most architectures it's just a regular st_value with no changes. - virtual uint64_t getSymbolValue(const Elf_Sym *symbol) const { - return symbol->st_value; + virtual uint64_t getSymbolValue() const { + return _symbol->st_value; } protected: diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index 66f5ba810d0..d33c06bad76 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -377,6 +377,9 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> { io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC); io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16); io.enumCase(value, "arm-thumb", lld::DefinedAtom::codeARMThumb); + io.enumCase(value, "arm-a", lld::DefinedAtom::codeARM_a); + io.enumCase(value, "arm-d", lld::DefinedAtom::codeARM_d); + io.enumCase(value, "arm-t", lld::DefinedAtom::codeARM_t); } }; diff --git a/lld/test/elf/ARM/mapping-code-model.test b/lld/test/elf/ARM/mapping-code-model.test new file mode 100644 index 00000000000..a9cdb989f4a --- /dev/null +++ b/lld/test/elf/ARM/mapping-code-model.test @@ -0,0 +1,163 @@ +# Check that mapping symbols are treated as ARM or Thumb code properly. +# +# 1. ARM <=> Thumb generates both veneers. +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-a-arm.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t-t-thm.o +# RUN: lld -flavor gnu -target arm-linux-gnu --defsym=main=f_a \ +# RUN: -Bstatic --noinhibit-exec %t-a-arm.o %t-t-thm.o -o %t +# RUN: llvm-objdump -t %t | FileCheck -check-prefix=INTER %s + +# INTER: SYMBOL TABLE: +# INTER: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_t_from_arm +# INTER: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_a_from_thumb + +# 2. Thumb <=> Thumb doesn't generate veneers. +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-a-thm.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t-t-thm.o +# RUN: lld -flavor gnu -target arm-linux-gnu --defsym=main=f_t \ +# RUN: -Bstatic --noinhibit-exec %t-t-thm.o %t-a-thm.o -o %t +# RUN: llvm-objdump -t %t | FileCheck -check-prefix=THUMB %s + +# THUMB: SYMBOL TABLE: +# THUMB-NOT: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_t_from_thumb +# THUMB-NOT: {{[0-9a-f]+}} l F .text {{[0-9a-f]+}} __f_a_from_thumb + +# f-a-arm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 00482DE904B08DE2FEFFFFEBFEFFFFEA0030A0E10300A0E10088BDE8 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000008 + Symbol: f_t + Type: R_ARM_CALL + - Offset: 0x000000000000000C + Symbol: f_t + Type: R_ARM_JUMP24 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: '$a' + Section: .text + Size: 0x0000000000000002 + - Name: '$a.f_a' + Section: .text + Value: 0x0000000000000002 + Global: + - Name: f_a + Type: STT_FUNC + Section: .text + - Name: f_t + +# f-a-thm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B400AF00231846BD465DF8047B7047 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: '$t' + Section: .text + Size: 0x0000000000000002 + - Name: '$t.f_a' + Section: .text + Value: 0x0000000000000002 + Global: + - Name: f_a + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + +# f-t-thm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B500AFFFF7FEFFFFF7FEBF0346184680BD00BF + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: f_a + Type: R_ARM_THM_CALL + - Offset: 0x0000000000000008 + Symbol: f_a + Type: R_ARM_THM_JUMP24 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: '$t' + Section: .text + Size: 0x0000000000000002 + - Name: '$t.f_t' + Section: .text + Value: 0x0000000000000002 + Global: + - Name: f_t + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + - Name: f_a +... diff --git a/lld/test/elf/ARM/mapping-symbols.test b/lld/test/elf/ARM/mapping-symbols.test new file mode 100644 index 00000000000..c4f560bb157 --- /dev/null +++ b/lld/test/elf/ARM/mapping-symbols.test @@ -0,0 +1,123 @@ +# Check that mapping symbols have zero size, local binding and none type. +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-a.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-t.o +# RUN: lld -flavor gnu -target arm-linux-gnu \ +# RUN: -Bstatic --noinhibit-exec %t-a.o %t-t.o -o %t +# RUN: llvm-readobj -symbols %t | FileCheck %s + +# CHECK: Name: $a (1) +# CHECK-NEXT: Value: 0x{{[0-9a-f]+}} +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# +# CHECK: Name: $t (9) +# CHECK-NEXT: Value: 0x{{[0-9a-f]+}} +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# +# CHECK: Name: $d (24) +# CHECK-NEXT: Value: 0x{{[0-9a-f]+}} +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 + +# arm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 00482DE904B08DE2FEFFFFEB0030A0E10300A0E10088BDE8 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000008 + Symbol: _Z1fv + Type: R_ARM_CALL + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: '$a' + Section: .text + Global: + - Name: main + Type: STT_FUNC + Section: .text + - Name: _Z1fv + +# thm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B400AF40F20003C0F200031B681846BD465DF8047B7047 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: _ZL1i + Type: R_ARM_THM_MOVW_ABS_NC + - Offset: 0x0000000000000008 + Symbol: _ZL1i + Type: R_ARM_THM_MOVT_ABS + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: 411C0000 +Symbols: + Local: + - Name: _ZL1i + Type: STT_OBJECT + Section: .bss + Size: 0x0000000000000004 + - Name: '$d' + Section: .bss + - Name: '$t' + Section: .text + Global: + - Name: _Z1fv + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 +... |

