[lld] r234473 - [ARM] Add mapping symbols to veneers
Denis Protivensky
dprotivensky at accesssoftek.com
Thu Apr 9 02:59:18 PDT 2015
Author: denis-protivensky
Date: Thu Apr 9 04:59:18 2015
New Revision: 234473
URL: http://llvm.org/viewvc/llvm-project?rev=234473&view=rev
Log:
[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.
Added:
lld/trunk/test/elf/ARM/veneer-mapping.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp?rev=234473&r1=234472&r2=234473&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp Thu Apr 9 04:59:18 2015
@@ -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 ARMPltVeneerAtomCon
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(De
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,37 +108,79 @@ 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_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_StaticAtom(const File &f, StringRef secName)
+ 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
class ARMGOTAtom : public GOTAtom {
public:
@@ -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);
-
- v->_name = "__";
- v->_name += da->name();
- v->_name += "_from_arm";
+ auto veneer = _veneerAtoms.lookup(da);
+ if (!veneer.empty())
+ return veneer._veneer;
- _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);
-
- v->_name = "__";
- v->_name += da->name();
- v->_name += "_from_thumb";
+ auto veneer = _veneerAtoms.lookup(da);
+ if (!veneer.empty())
+ return veneer._veneer;
- _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.
Added: lld/trunk/test/elf/ARM/veneer-mapping.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/veneer-mapping.test?rev=234473&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/veneer-mapping.test (added)
+++ lld/trunk/test/elf/ARM/veneer-mapping.test Thu Apr 9 04:59:18 2015
@@ -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
+...
More information about the llvm-commits
mailing list