[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
This commit is contained in:
Denis Protivensky 2015-04-09 09:59:18 +00:00
parent 2aa8c8fd17
commit 6b3a33ff00
2 changed files with 219 additions and 36 deletions

View File

@ -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,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_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
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);
auto veneer = _veneerAtoms.lookup(da);
if (!veneer.empty())
return veneer._veneer;
v->_name = "__";
v->_name += da->name();
v->_name += "_from_arm";
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);
_veneerAtoms[da] = v;
return v;
// 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";
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);
_veneerAtoms[da] = v;
return v;
// 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.

View File

@ -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
...