Index: lld/trunk/include/lld/Core/DefinedAtom.h =================================================================== --- lld/trunk/include/lld/Core/DefinedAtom.h +++ lld/trunk/include/lld/Core/DefinedAtom.h @@ -151,6 +151,7 @@ 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 Index: lld/trunk/lib/Core/DefinedAtom.cpp =================================================================== --- lld/trunk/lib/Core/DefinedAtom.cpp +++ lld/trunk/lib/Core/DefinedAtom.cpp @@ -43,6 +43,7 @@ case typeProcessedUnwindInfo: case typeRONote: case typeNoAlloc: + case typeARMExidx: return permR__; case typeData: Index: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h +++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h @@ -67,7 +67,13 @@ 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> ARMExecutableWriter::createSymbolTable() { @@ -82,6 +88,8 @@ } else if (symName.startswith("__exidx")) { file.addAbsoluteAtom("__exidx_start"); file.addAbsoluteAtom("__exidx_end"); + } else if (symName == "__ehdr_start") { + file.addAbsoluteAtom("__ehdr_start"); } } Index: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h +++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h @@ -31,6 +31,9 @@ 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()) Index: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h +++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h @@ -20,10 +20,89 @@ namespace elf { +/// \brief ARM specific section (.ARM.exidx) with indexes to exception handlers +class ARMExidxSection : public AtomSection { + typedef AtomSection 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(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 { 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(inputSectionName) + .StartsWith(".ARM.exidx", ".ARM.exidx") + .StartsWith(".ARM.extab", ".ARM.extab") + .Default(TargetLayout::getOutputSectionName(archivePath, memberPath, + inputSectionName)); + } + + SegmentType getSegmentType(Section *section) const override { + switch (section->order()) { + case ORDER_ARM_EXIDX: + return llvm::ELF::PT_ARM_EXIDX; + default: + return TargetLayout::getSegmentType(section); + } + } + + AtomSection * + 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_")) Index: lld/trunk/lib/ReaderWriter/ELF/Atoms.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/Atoms.cpp +++ lld/trunk/lib/ReaderWriter/ELF/Atoms.cpp @@ -84,6 +84,8 @@ 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 @@ case llvm::ELF::SHT_FINI_ARRAY: return _permissions = permRW_; + case llvm::ELF::SHT_ARM_EXIDX: + return _permissions = permR__; + default: return _permissions = perm___; } Index: lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h +++ lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h @@ -26,6 +26,7 @@ : OutputELFWriter(ctx, layout) {} protected: + void updateScopeAtomValues(StringRef sym, StringRef sec); void buildDynamicSymbolTable(const File &file) override; void createImplicitFiles(std::vector> &) override; void finalizeDefaultAtomValues() override; @@ -44,6 +45,25 @@ //===----------------------------------------------------------------------===// // ExecutableWriter //===----------------------------------------------------------------------===// +template +void ExecutableWriter::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 *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 void ExecutableWriter::buildDynamicSymbolTable(const File &file) { for (auto sec : this->_layout.sections()) @@ -127,28 +147,13 @@ 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 *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"); Index: lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h +++ lld/trunk/lib/ReaderWriter/ELF/TargetLayout.h @@ -52,6 +52,7 @@ ORDER_FINI = 90, ORDER_REL = 95, ORDER_RODATA = 100, + ORDER_ARM_EXIDX = 105, ORDER_EH_FRAME = 110, ORDER_EH_FRAMEHDR = 120, ORDER_TDATA = 124, Index: lld/trunk/test/elf/ARM/exidx.test =================================================================== --- lld/trunk/test/elf/ARM/exidx.test +++ lld/trunk/test/elf/ARM/exidx.test @@ -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 +...