[ARM] Generation of .ARM.exidx/.ARM.extab sections

This patch provides generation of .ARM.exidx & .ARM.extab sections which are
used for unwinding. The patch adds new content type typeARMExidx for atoms from
.ARM.exidx section and integration of atoms with such type to the ELF
ReaderWriter. exidx.test has been added with checking of contents of .ARM.exidx
section and .ARM.extab section.

Differential Revision: http://reviews.llvm.org/D9324

llvm-svn: 236873
This commit is contained in:
Leny Kholodov 2015-05-08 16:04:11 +00:00
parent d916dbb726
commit bde4144338
9 changed files with 378 additions and 21 deletions

View File

@ -151,6 +151,7 @@ public:
typeNoAlloc, // Identifies non allocatable sections [ELF]
typeGroupComdat, // Identifies a section group [ELF, COFF]
typeGnuLinkOnce, // Identifies a gnu.linkonce section [ELF]
typeARMExidx, // Identifies a ARM_EXIDX section [ELF/ARM]
};
// Permission bits for atoms and segments. The order of these values are

View File

@ -43,6 +43,7 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
case typeProcessedUnwindInfo:
case typeRONote:
case typeNoAlloc:
case typeARMExidx:
return permR__;
case typeData:

View File

@ -67,7 +67,13 @@ void ARMExecutableWriter::finalizeDefaultAtomValues() {
else
gotAtom->_virtualAddr = 0;
}
// TODO: resolve addresses of __exidx_start/_end atoms
// Set required by gcc libc __ehdr_start symbol with pointer to ELF header
if (auto ehdr = _armLayout.findAbsoluteAtom("__ehdr_start"))
ehdr->_virtualAddr = _elfHeader->virtualAddr();
// Set required by gcc libc symbols __exidx_start/__exidx_end
updateScopeAtomValues("exidx", ".ARM.exidx");
}
unique_bump_ptr<SymbolTable<ELF32LE>> ARMExecutableWriter::createSymbolTable() {
@ -82,6 +88,8 @@ void ARMExecutableWriter::processUndefinedSymbol(
} else if (symName.startswith("__exidx")) {
file.addAbsoluteAtom("__exidx_start");
file.addAbsoluteAtom("__exidx_end");
} else if (symName == "__ehdr_start") {
file.addAbsoluteAtom("__ehdr_start");
}
}

View File

@ -31,6 +31,9 @@ void ARMSymbolTable::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
int64_t addr) {
SymbolTable::addDefinedAtom(sym, da, addr);
if (da->contentType() == DefinedAtom::typeARMExidx)
sym.st_value = addr;
// 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())

View File

@ -20,10 +20,89 @@ class ELFLinkingContext;
namespace elf {
/// \brief ARM specific section (.ARM.exidx) with indexes to exception handlers
class ARMExidxSection : public AtomSection<ELF32LE> {
typedef AtomSection<ELF32LE> Base;
public:
ARMExidxSection(const ELFLinkingContext &ctx, StringRef sectionName,
int32_t permissions, int32_t order)
: Base(ctx, sectionName, DefinedAtom::typeARMExidx, permissions, order) {
this->_type = SHT_ARM_EXIDX;
this->_isLoadedInMemory = true;
}
bool hasOutputSegment() const override { return true; }
const AtomLayout *appendAtom(const Atom *atom) override {
const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
assert(atom->contentType() == DefinedAtom::typeARMExidx &&
"atom content type for .ARM.exidx section has to be typeARMExidx");
DefinedAtom::Alignment atomAlign = definedAtom->alignment();
uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
_atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0));
this->_fsize = fOffset + definedAtom->size();
this->_msize = mOffset + definedAtom->size();
DEBUG_WITH_TYPE("Section", llvm::dbgs()
<< "[" << this->name() << " " << this << "] "
<< "Adding atom: " << atom->name() << "@"
<< fOffset << "\n");
uint64_t alignment = atomAlign.value;
if (this->_alignment < alignment)
this->_alignment = alignment;
return _atoms.back();
}
};
class ARMTargetLayout : public TargetLayout<ELF32LE> {
public:
ARMTargetLayout(ELFLinkingContext &ctx) : TargetLayout(ctx) {}
SectionOrder getSectionOrder(StringRef name, int32_t contentType,
int32_t contentPermissions) override {
switch (contentType) {
case DefinedAtom::typeARMExidx:
return ORDER_ARM_EXIDX;
default:
return TargetLayout::getSectionOrder(name, contentType,
contentPermissions);
}
}
StringRef getOutputSectionName(StringRef archivePath, StringRef memberPath,
StringRef inputSectionName) const override {
return llvm::StringSwitch<StringRef>(inputSectionName)
.StartsWith(".ARM.exidx", ".ARM.exidx")
.StartsWith(".ARM.extab", ".ARM.extab")
.Default(TargetLayout::getOutputSectionName(archivePath, memberPath,
inputSectionName));
}
SegmentType getSegmentType(Section<ELF32LE> *section) const override {
switch (section->order()) {
case ORDER_ARM_EXIDX:
return llvm::ELF::PT_ARM_EXIDX;
default:
return TargetLayout::getSegmentType(section);
}
}
AtomSection<ELF32LE> *
createSection(StringRef name, int32_t contentType,
DefinedAtom::ContentPermissions contentPermissions,
SectionOrder sectionOrder) override {
if (contentType == DefinedAtom::typeARMExidx)
return new ARMExidxSection(_ctx, name, contentPermissions, sectionOrder);
return TargetLayout::createSection(name, contentType, contentPermissions,
sectionOrder);
}
uint64_t getGOTSymAddr() {
std::call_once(_gotSymOnce, [this]() {
if (AtomLayout *gotAtom = findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"))

View File

@ -84,6 +84,8 @@ DefinedAtom::ContentType ELFDefinedAtom<ELFT>::doContentType() const {
if (_symbol->st_shndx == SHN_COMMON)
return _contentType = typeZeroFill;
if (_section->sh_type == SHT_ARM_EXIDX)
return typeARMExidx;
if (_section->sh_type == SHT_PROGBITS) {
flags &= ~SHF_ALLOC;
flags &= ~SHF_GROUP;
@ -216,6 +218,9 @@ DefinedAtom::ContentPermissions ELFDefinedAtom<ELFT>::permissions() const {
case llvm::ELF::SHT_FINI_ARRAY:
return _permissions = permRW_;
case llvm::ELF::SHT_ARM_EXIDX:
return _permissions = permR__;
default:
return _permissions = perm___;
}

View File

@ -26,6 +26,7 @@ public:
: OutputELFWriter<ELFT>(ctx, layout) {}
protected:
void updateScopeAtomValues(StringRef sym, StringRef sec);
void buildDynamicSymbolTable(const File &file) override;
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
void finalizeDefaultAtomValues() override;
@ -44,6 +45,25 @@ private:
//===----------------------------------------------------------------------===//
// ExecutableWriter
//===----------------------------------------------------------------------===//
template <class ELFT>
void ExecutableWriter<ELFT>::updateScopeAtomValues(StringRef sym,
StringRef sec) {
std::string start = ("__" + sym + "_start").str();
std::string end = ("__" + sym + "_end").str();
AtomLayout *s = this->_layout.findAbsoluteAtom(start);
AtomLayout *e = this->_layout.findAbsoluteAtom(end);
OutputSection<ELFT> *section = this->_layout.findOutputSection(sec);
if (!s || !e)
return;
if (section) {
s->_virtualAddr = section->virtualAddr();
e->_virtualAddr = section->virtualAddr() + section->memSize();
} else {
s->_virtualAddr = 0;
e->_virtualAddr = 0;
}
}
template<class ELFT>
void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
for (auto sec : this->_layout.sections())
@ -127,28 +147,13 @@ template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
assert((bssStartAtom || bssEndAtom || underScoreEndAtom || endAtom) &&
"Unable to find the absolute atoms that have been added by lld");
auto startEnd = [&](StringRef sym, StringRef sec) -> void {
std::string start = ("__" + sym + "_start").str();
std::string end = ("__" + sym + "_end").str();
AtomLayout *s = this->_layout.findAbsoluteAtom(start);
AtomLayout *e = this->_layout.findAbsoluteAtom(end);
OutputSection<ELFT> *section = this->_layout.findOutputSection(sec);
if (section) {
s->_virtualAddr = section->virtualAddr();
e->_virtualAddr = section->virtualAddr() + section->memSize();
} else {
s->_virtualAddr = 0;
e->_virtualAddr = 0;
}
};
startEnd("preinit_array", ".preinit_array");
startEnd("init_array", ".init_array");
updateScopeAtomValues("preinit_array", ".preinit_array");
updateScopeAtomValues("init_array", ".init_array");
if (this->_ctx.isRelaOutputFormat())
startEnd("rela_iplt", ".rela.plt");
updateScopeAtomValues("rela_iplt", ".rela.plt");
else
startEnd("rel_iplt", ".rel.plt");
startEnd("fini_array", ".fini_array");
updateScopeAtomValues("rel_iplt", ".rel.plt");
updateScopeAtomValues("fini_array", ".fini_array");
auto bssSection = this->_layout.findOutputSection(".bss");

View File

@ -52,6 +52,7 @@ public:
ORDER_FINI = 90,
ORDER_REL = 95,
ORDER_RODATA = 100,
ORDER_ARM_EXIDX = 105,
ORDER_EH_FRAME = 110,
ORDER_EH_FRAMEHDR = 120,
ORDER_TDATA = 124,

254
lld/test/elf/ARM/exidx.test Normal file
View File

@ -0,0 +1,254 @@
# .ARM.exidx contents checking
# RUN: yaml2obj -format=elf %s > %t.o
# RUN: lld -flavor gnu -target arm-none-linux-eabi -static -o %t %t.o
# RUN: llvm-objdump -s -t -section-headers %t | FileCheck %s
#
# CHECK: Sections:
# CHECK: Idx Name Size Address Type
# CHECK: 2 .ARM.extab 0000000c 00000000004000b4 DATA
# CHECK: 3 .ARM.exidx 00000018 00000000004000c0
# CHECK: Contents of section .text:
# CHECK: 4000a4 1846aff3 00801846 0837bd46 80bd00bf
# ^
# 4000b0: bd80 pop {r7, pc}
# CHECK: Contents of section .ARM.extab:
# CHECK: 4000b4 01970181 b0b00884 00000000
# CHECK: Contents of section .ARM.exidx:
# CHECK: 4000c0 b4ffff7f 08809780 bcffff7f 08809780
# ^ offset to 400074 (__aeabi_unwind_cpp_pr0)
# CHECK: 4000d0 c4ffff7f e0ffff7f
# ^ ^
# offset to 400094 (_start) handler at 4000B0
#
# CHECK: SYMBOL TABLE:
# CHECK: 004000b4 .ARM.extab 00000000 $d.2
# CHECK: 004000c0 .ARM.exidx 00000000 $d.1
# CHECK: 00400074 g F .text 00000010 __aeabi_unwind_cpp_pr0
# CHECK: 00400094 g F .text 00000020 _start
---
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: 80B400AF00231846BD465DF8047B704780B400AF00231846BD465DF8047B704780B582B000AF3B1D1846FFF7FEFF3B1D1846FFF7FEFF18460837BD4680BD00BF
- Name: .rel.text
Type: SHT_REL
Link: .symtab
AddressAlign: 0x0000000000000004
Info: .text
Relocations:
- Offset: 0x000000000000002A
Symbol: _ZN1AILi1EEC1Ev
Type: R_ARM_THM_CALL
- Offset: 0x0000000000000032
Symbol: _ZN1AILi1EED1Ev
Type: R_ARM_THM_CALL
- Name: .ARM.extab
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
AddressAlign: 0x0000000000000004
Content: 01970181B0B0088400000000
- Name: .ARM.exidx
Type: SHT_ARM_EXIDX
Flags: [ SHF_ALLOC, SHF_LINK_ORDER ]
Link: .text
AddressAlign: 0x0000000000000004
Content: '000000000880978010000000088097802000000000000000'
- Name: .rel.ARM.exidx
Type: SHT_REL
Link: .symtab
AddressAlign: 0x0000000000000004
Info: .ARM.exidx
Relocations:
- Offset: 0x0000000000000000
Symbol: .text
Type: R_ARM_PREL31
- Offset: 0x0000000000000000
Symbol: __aeabi_unwind_cpp_pr0
Type: R_ARM_NONE
- Offset: 0x0000000000000008
Symbol: .text
Type: R_ARM_PREL31
- Offset: 0x0000000000000010
Symbol: .text
Type: R_ARM_PREL31
- Offset: 0x0000000000000010
Symbol: __aeabi_unwind_cpp_pr1
Type: R_ARM_NONE
- Offset: 0x0000000000000014
Symbol: .ARM.extab
Type: R_ARM_PREL31
- Name: .text._ZN1AILi1EEC2Ev
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000004
Content: 80B582B000AF78600120FFF7FEFF7B6818460837BD4680BD
- Name: .rel.text._ZN1AILi1EEC2Ev
Type: SHT_REL
Link: .symtab
AddressAlign: 0x0000000000000004
Info: .text._ZN1AILi1EEC2Ev
Relocations:
- Offset: 0x000000000000000A
Symbol: f
Type: R_ARM_THM_CALL
- Name: .ARM.extab.text._ZN1AILi1EEC2Ev
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_GROUP ]
AddressAlign: 0x0000000000000004
Content: 01970181B0B0088400000000
- Name: .ARM.exidx.text._ZN1AILi1EEC2Ev
Type: SHT_ARM_EXIDX
Flags: [ SHF_ALLOC, SHF_LINK_ORDER, SHF_GROUP ]
Link: .text._ZN1AILi1EEC2Ev
AddressAlign: 0x0000000000000004
Content: '0000000000000000'
- Name: .rel.ARM.exidx.text._ZN1AILi1EEC2Ev
Type: SHT_REL
Link: .symtab
AddressAlign: 0x0000000000000004
Info: .ARM.exidx.text._ZN1AILi1EEC2Ev
Relocations:
- Offset: 0x0000000000000000
Symbol: .text._ZN1AILi1EEC2Ev
Type: R_ARM_PREL31
- Offset: 0x0000000000000000
Symbol: __aeabi_unwind_cpp_pr1
Type: R_ARM_NONE
- Offset: 0x0000000000000004
Symbol: .ARM.extab.text._ZN1AILi1EEC2Ev
Type: R_ARM_PREL31
- Name: .text._ZN1AILi1EED2Ev
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000004
Content: 80B582B000AF78604FF0FF30FFF7FEFF7B6818460837BD4680BD00BF
- Name: .rel.text._ZN1AILi1EED2Ev
Type: SHT_REL
Link: .symtab
AddressAlign: 0x0000000000000004
Info: .text._ZN1AILi1EED2Ev
Relocations:
- Offset: 0x000000000000000C
Symbol: f
Type: R_ARM_THM_CALL
- Name: .ARM.extab.text._ZN1AILi1EED2Ev
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_GROUP ]
AddressAlign: 0x0000000000000004
Content: 01970181B0B0088400000000
- Name: .ARM.exidx.text._ZN1AILi1EED2Ev
Type: SHT_ARM_EXIDX
Flags: [ SHF_ALLOC, SHF_LINK_ORDER, SHF_GROUP ]
Link: .text._ZN1AILi1EED2Ev
AddressAlign: 0x0000000000000004
Content: '0000000000000000'
- Name: .rel.ARM.exidx.text._ZN1AILi1EED2Ev
Type: SHT_REL
Link: .symtab
AddressAlign: 0x0000000000000004
Info: .ARM.exidx.text._ZN1AILi1EED2Ev
Relocations:
- Offset: 0x0000000000000000
Symbol: .text._ZN1AILi1EED2Ev
Type: R_ARM_PREL31
- Offset: 0x0000000000000000
Symbol: __aeabi_unwind_cpp_pr1
Type: R_ARM_NONE
- Offset: 0x0000000000000004
Symbol: .ARM.extab.text._ZN1AILi1EED2Ev
Type: R_ARM_PREL31
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: '$t.1'
Section: .text
- Name: .ARM.extab
Type: STT_SECTION
Section: .ARM.extab
- Name: .ARM.exidx
Type: STT_SECTION
Section: .ARM.exidx
- Name: '$d.1'
Section: .ARM.exidx
- Name: '$d.2'
Section: .ARM.extab
- Name: .text._ZN1AILi1EEC2Ev
Type: STT_SECTION
Section: .text._ZN1AILi1EEC2Ev
- Name: '$t.2'
Section: .text._ZN1AILi1EEC2Ev
- Name: .ARM.extab.text._ZN1AILi1EEC2Ev
Type: STT_SECTION
Section: .ARM.extab.text._ZN1AILi1EEC2Ev
- Name: '$d.3'
Section: .ARM.extab.text._ZN1AILi1EEC2Ev
- Name: .ARM.exidx.text._ZN1AILi1EEC2Ev
Type: STT_SECTION
Section: .ARM.exidx.text._ZN1AILi1EEC2Ev
- Name: '$d.4'
Section: .ARM.exidx.text._ZN1AILi1EEC2Ev
- Name: .text._ZN1AILi1EED2Ev
Type: STT_SECTION
Section: .text._ZN1AILi1EED2Ev
- Name: '$t.3'
Section: .text._ZN1AILi1EED2Ev
- Name: .ARM.extab.text._ZN1AILi1EED2Ev
Type: STT_SECTION
Section: .ARM.extab.text._ZN1AILi1EED2Ev
- Name: '$d.5'
Section: .ARM.extab.text._ZN1AILi1EED2Ev
- Name: .ARM.exidx.text._ZN1AILi1EED2Ev
Type: STT_SECTION
Section: .ARM.exidx.text._ZN1AILi1EED2Ev
- Name: '$d.6'
Section: .ARM.exidx.text._ZN1AILi1EED2Ev
Global:
- Name: __aeabi_unwind_cpp_pr0
Type: STT_FUNC
Section: .text
Value: 0x0000000000000001
Size: 0x0000000000000010
- Name: __aeabi_unwind_cpp_pr1
Type: STT_FUNC
Section: .text
Value: 0x0000000000000011
Size: 0x0000000000000010
- Name: _start
Type: STT_FUNC
Section: .text
Value: 0x0000000000000021
Size: 0x000000000000001E
Weak:
- Name: _ZN1AILi1EEC1Ev
Type: STT_FUNC
Section: .text._ZN1AILi1EEC2Ev
Value: 0x0000000000000001
Size: 0x0000000000000018
- Name: _ZN1AILi1EED1Ev
Type: STT_FUNC
Section: .text._ZN1AILi1EED2Ev
Value: 0x0000000000000001
Size: 0x000000000000001A
- Name: _ZN1AILi1EEC2Ev
Type: STT_FUNC
Section: .text._ZN1AILi1EEC2Ev
Value: 0x0000000000000001
Size: 0x0000000000000018
- Name: f
- Name: _ZN1AILi1EED2Ev
Type: STT_FUNC
Section: .text._ZN1AILi1EED2Ev
Value: 0x0000000000000001
Size: 0x000000000000001A
...