diff options
| author | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-04-09 09:59:18 +0000 |
|---|---|---|
| committer | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-04-09 09:59:18 +0000 |
| commit | 6b3a33ff006550dac0fdd9b03cc76ae6ef3780e6 (patch) | |
| tree | dbd9b4cda7ee28ce6a5d3c27578bbaa393264665 | |
| parent | 2aa8c8fd1765defaa13443fc59d00a4ab4337f81 (diff) | |
| download | bcm5719-llvm-6b3a33ff006550dac0fdd9b03cc76ae6ef3780e6.tar.gz bcm5719-llvm-6b3a33ff006550dac0fdd9b03cc76ae6ef3780e6.zip | |
[ARM] Add mapping symbols to veneers
This required splitting up veneer atoms into pieces,
where every piece is paired with mapping atom of
the corresponding type.
llvm-svn: 234473
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp | 165 | ||||
| -rw-r--r-- | lld/test/elf/ARM/veneer-mapping.test | 94 |
2 files changed, 221 insertions, 38 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp index 9889f1fc33c..e64a6d5507a 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp @@ -32,17 +32,21 @@ namespace { // ARM B/BL instructions of static relocation veneer. // TODO: consider different instruction set for archs below ARMv5 // (one as for Thumb may be used though it's less optimal). -static const uint8_t Veneer_ARM_B_BL_StaticAtomContent[8] = { - 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4] +static const uint8_t Veneer_ARM_B_BL_Static_a_AtomContent[4] = { + 0x04, 0xf0, 0x1f, 0xe5 // ldr pc, [pc, #-4] +}; +static const uint8_t Veneer_ARM_B_BL_Static_d_AtomContent[4] = { 0x00, 0x00, 0x00, 0x00 // <target_symbol_address> }; // Thumb B/BL instructions of static relocation veneer. // TODO: consider different instruction set for archs above ARMv5 // (one as for ARM may be used since it's more optimal). -static const uint8_t Veneer_THM_B_BL_StaticAtomContent[8] = { +static const uint8_t Veneer_THM_B_BL_Static_t_AtomContent[4] = { 0x78, 0x47, // bx pc - 0x00, 0x00, // nop + 0x00, 0x00 // nop +}; +static const uint8_t Veneer_THM_B_BL_Static_a_AtomContent[4] = { 0xfe, 0xff, 0xff, 0xea // b <target_symbol_address> }; @@ -62,7 +66,6 @@ static const uint8_t ARMPltVeneerAtomContent[4] = { 0x00, 0x00 // nop }; -#ifdef NDEBUG // Determine proper names for mapping symbols. static std::string getMappingAtomName(DefinedAtom::CodeModel model, const std::string &part) { @@ -77,15 +80,14 @@ static std::string getMappingAtomName(DefinedAtom::CodeModel model, llvm_unreachable("Wrong code model of mapping atom"); } } -#endif /// \brief Atoms that hold veneer code. class VeneerAtom : public SimpleELFDefinedAtom { StringRef _section; public: - VeneerAtom(const File &f, StringRef secName) - : SimpleELFDefinedAtom(f), _section(secName) {} + VeneerAtom(const File &f, StringRef secName, const std::string &name = "") + : SimpleELFDefinedAtom(f), _section(secName), _name(name) {} Scope scope() const override { return DefinedAtom::scopeTranslationUnit; } @@ -106,35 +108,77 @@ public: Alignment alignment() const override { return 4; } StringRef name() const override { return _name; } + +private: std::string _name; }; /// \brief Atoms that hold veneer for statically relocated /// ARM B/BL instructions. -class Veneer_ARM_B_BL_StaticAtom : public VeneerAtom { +class Veneer_ARM_B_BL_Static_a_Atom : public VeneerAtom { public: - Veneer_ARM_B_BL_StaticAtom(const File &f, StringRef secName) + Veneer_ARM_B_BL_Static_a_Atom(const File &f, StringRef secName, + const std::string &name) + : VeneerAtom(f, secName, name) {} + + ArrayRef<uint8_t> rawContent() const override { + return llvm::makeArrayRef(Veneer_ARM_B_BL_Static_a_AtomContent); + } +}; + +class Veneer_ARM_B_BL_Static_d_Atom : public VeneerAtom { +public: + Veneer_ARM_B_BL_Static_d_Atom(const File &f, StringRef secName) : VeneerAtom(f, secName) {} ArrayRef<uint8_t> rawContent() const override { - return llvm::makeArrayRef(Veneer_ARM_B_BL_StaticAtomContent); + return llvm::makeArrayRef(Veneer_ARM_B_BL_Static_d_AtomContent); } }; /// \brief Atoms that hold veneer for statically relocated /// Thumb B/BL instructions. -class Veneer_THM_B_BL_StaticAtom : public VeneerAtom { +class Veneer_THM_B_BL_Static_t_Atom : public VeneerAtom { public: - Veneer_THM_B_BL_StaticAtom(const File &f, StringRef secName) - : VeneerAtom(f, secName) {} + Veneer_THM_B_BL_Static_t_Atom(const File &f, StringRef secName, + const std::string &name) + : VeneerAtom(f, secName, name) {} DefinedAtom::CodeModel codeModel() const override { return DefinedAtom::codeARMThumb; } ArrayRef<uint8_t> rawContent() const override { - return llvm::makeArrayRef(Veneer_THM_B_BL_StaticAtomContent); + return llvm::makeArrayRef(Veneer_THM_B_BL_Static_t_AtomContent); + } +}; + +class Veneer_THM_B_BL_Static_a_Atom : public VeneerAtom { +public: + Veneer_THM_B_BL_Static_a_Atom(const File &f, StringRef secName) + : VeneerAtom(f, secName) {} + + ArrayRef<uint8_t> rawContent() const override { + return llvm::makeArrayRef(Veneer_THM_B_BL_Static_a_AtomContent); + } +}; + +template <DefinedAtom::CodeModel Model> +class ARMVeneerMappingAtom : public VeneerAtom { +public: + ARMVeneerMappingAtom(const File &f, StringRef secName, StringRef name) + : VeneerAtom(f, secName, getMappingAtomName(Model, name)) { + static_assert((Model == DefinedAtom::codeARM_a || + Model == DefinedAtom::codeARM_d || + Model == DefinedAtom::codeARM_t), + "Only mapping atom types are allowed"); } + + uint64_t size() const override { return 0; } + + ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); } + + DefinedAtom::CodeModel codeModel() const override { return Model; } }; /// \brief Atoms that are used by ARM dynamic linking @@ -353,6 +397,20 @@ protected: return g; } + /// \brief Add veneer with mapping symbol. + template <DefinedAtom::CodeModel Model> + void addVeneerWithMapping(const DefinedAtom *da, VeneerAtom *va, + const std::string &name) { + assert(_veneerAtoms.lookup(da).empty() && + "Veneer or mapping already exists"); + auto *ma = new (_file._alloc) + ARMVeneerMappingAtom<Model>(_file, va->customSectionName(), name); + + // Fake reference to show connection between the mapping symbol and veneer. + va->addReferenceELF_ARM(R_ARM_NONE, 0, ma, 0); + _veneerAtoms[da] = VeneerWithMapping(va, ma); + } + /// \brief get a veneer for a PLT entry. const PLTAtom *getPLTVeneer(const DefinedAtom *da, PLTAtom *pa, StringRef source) { @@ -539,8 +597,12 @@ public: } for (auto &veneerKV : _veneerAtoms) { auto &veneer = veneerKV.second; - veneer->setOrdinal(ordinal++); - mf->addAtom(*veneer); + auto *m = veneer._mapping; + m->setOrdinal(ordinal++); + mf->addAtom(*m); + auto *v = veneer._veneer; + v->setOrdinal(ordinal++); + mf->addAtom(*v); } } @@ -568,7 +630,20 @@ protected: llvm::MapVector<const Atom *, PLTWithVeneer> _pltAtoms; /// \brief Map Atoms to their veneers. - llvm::MapVector<const Atom *, VeneerAtom *> _veneerAtoms; + struct VeneerWithMapping { + VeneerWithMapping(VeneerAtom *v = nullptr, VeneerAtom *m = nullptr) + : _veneer(v), _mapping(m) {} + + bool empty() const { + assert(((bool)_veneer == (bool)_mapping) && + "Mapping symbol should always be paired with veneer"); + return !_veneer && !_mapping; + } + + VeneerAtom *_veneer; + VeneerAtom *_mapping; + }; + llvm::MapVector<const Atom *, VeneerWithMapping> _veneerAtoms; /// \brief GOT entry that is always 0. Used for undefined weaks. GOTAtom *_null = nullptr; @@ -589,33 +664,47 @@ public: /// \brief Get the veneer for ARM B/BL instructions. const VeneerAtom *getVeneer_ARM_B_BL(const DefinedAtom *da, StringRef secName) { - if (auto veneer = _veneerAtoms.lookup(da)) - return veneer; - auto v = new (_file._alloc) Veneer_ARM_B_BL_StaticAtom(_file, secName); - v->addReferenceELF_ARM(R_ARM_ABS32, 4, da, 0); + auto veneer = _veneerAtoms.lookup(da); + if (!veneer.empty()) + return veneer._veneer; - v->_name = "__"; - v->_name += da->name(); - v->_name += "_from_arm"; - - _veneerAtoms[da] = v; - return v; + std::string name = "__"; + name += da->name(); + name += "_from_arm"; + // Create parts of veneer with mapping symbols. + auto v_a = new (_file._alloc) Veneer_ARM_B_BL_Static_a_Atom(_file, secName, name); + addVeneerWithMapping<DefinedAtom::codeARM_a>(da, v_a, name); + auto v_d = new (_file._alloc) Veneer_ARM_B_BL_Static_d_Atom(_file, secName); + addVeneerWithMapping<DefinedAtom::codeARM_d>(v_a, v_d, name); + + // Fake reference to show connection between parts of veneer. + v_a->addReferenceELF_ARM(R_ARM_NONE, 0, v_d, 0); + // Real reference to fixup. + v_d->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0); + return v_a; } /// \brief Get the veneer for Thumb B/BL instructions. const VeneerAtom *getVeneer_THM_B_BL(const DefinedAtom *da, StringRef secName) { - if (auto veneer = _veneerAtoms.lookup(da)) - return veneer; - auto v = new (_file._alloc) Veneer_THM_B_BL_StaticAtom(_file, secName); - v->addReferenceELF_ARM(R_ARM_JUMP24, 4, da, 0); + auto veneer = _veneerAtoms.lookup(da); + if (!veneer.empty()) + return veneer._veneer; - v->_name = "__"; - v->_name += da->name(); - v->_name += "_from_thumb"; - - _veneerAtoms[da] = v; - return v; + std::string name = "__"; + name += da->name(); + name += "_from_thumb"; + // Create parts of veneer with mapping symbols. + auto v_t = new (_file._alloc) Veneer_THM_B_BL_Static_t_Atom(_file, secName, name); + addVeneerWithMapping<DefinedAtom::codeARM_t>(da, v_t, name); + auto v_a = new (_file._alloc) Veneer_THM_B_BL_Static_a_Atom(_file, secName); + addVeneerWithMapping<DefinedAtom::codeARM_a>(v_t, v_a, name); + + // Fake reference to show connection between parts of veneer. + v_t->addReferenceELF_ARM(R_ARM_NONE, 0, v_a, 0); + // Real reference to fixup. + v_a->addReferenceELF_ARM(R_ARM_JUMP24, 0, da, 0); + return v_t; } /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc. diff --git a/lld/test/elf/ARM/veneer-mapping.test b/lld/test/elf/ARM/veneer-mapping.test new file mode 100644 index 00000000000..6449ff64896 --- /dev/null +++ b/lld/test/elf/ARM/veneer-mapping.test @@ -0,0 +1,94 @@ +# Check that mapping symbols are properly generated for veneers. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o +# RUN: lld -flavor gnu -target arm-linux-gnu --defsym=main=fa \ +# RUN: -Bstatic --noinhibit-exec %t-arm.o %t-thm.o -o %t +# RUN: llvm-readobj -symbols %t | FileCheck %s + +# CHECK: Name: $a.__ft_from_arm +# CHECK: Name: $d.__ft_from_arm +# CHECK: Name: $t.__fa_from_thumb +# CHECK: Name: $a.__fa_from_thumb + +# 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: 00482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000008 + Symbol: ft + 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: + Global: + - Name: fa + Type: STT_FUNC + Section: .text + - Name: ft + +# 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: 80B500AFFFF7FEBF0346184680BD00BF + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: fa + 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: + Global: + - Name: ft + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + - Name: fa +... |

