diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-09-25 18:56:53 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-09-25 18:56:53 +0000 |
| commit | 0e604f913ada479925e4f6106867b3c5d3646e32 (patch) | |
| tree | 03b9d748f98170d6f50e9143f8e7b0983555da0b | |
| parent | 33d6c0bbc59e600115eb83cdcb27b8d5e0e8f177 (diff) | |
| download | bcm5719-llvm-0e604f913ada479925e4f6106867b3c5d3646e32.tar.gz bcm5719-llvm-0e604f913ada479925e4f6106867b3c5d3646e32.zip | |
Add support for creating the symbols __init_array_start and __init_array_end.
llvm-svn: 248604
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 5 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.h | 2 | ||||
| -rw-r--r-- | lld/ELF/SymbolTable.cpp | 28 | ||||
| -rw-r--r-- | lld/ELF/SymbolTable.h | 4 | ||||
| -rw-r--r-- | lld/ELF/Symbols.h | 25 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 8 | ||||
| -rw-r--r-- | lld/test/elf2/init_array.s | 49 |
7 files changed, 115 insertions, 6 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index e497d255c90..2bc1fa991b9 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -295,6 +295,8 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const ELFSymbolBody<ELFT> &S, const OutputSection<ELFT> &BssSec) { switch (S.kind()) { + case SymbolBody::DefinedSyntheticKind: + return cast<DefinedSynthetic<ELFT>>(S).Section.getVA() + S.Sym.st_value; case SymbolBody::DefinedAbsoluteKind: return S.Sym.st_value; case SymbolBody::DefinedRegularKind: { @@ -434,6 +436,9 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { const InputSection<ELFT> *Section = nullptr; switch (EBody.kind()) { + case SymbolBody::DefinedSyntheticKind: + Out = &cast<DefinedSynthetic<ELFT>>(Body)->Section; + break; case SymbolBody::DefinedRegularKind: Section = &cast<DefinedRegular<ELFT>>(EBody).Section; break; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index dc843500b38..7ce35b05597 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -165,7 +165,7 @@ public: void writeTo(uint8_t *Buf) override; - const SymbolTable &getSymTable() const { return Table; } + SymbolTable &getSymTable() const { return Table; } void addSymbol(StringRef Name, bool isLocal = false) { StrTabSec.add(Name); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 80b2eaac626..38bec5f2b12 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -55,6 +55,17 @@ static TargetInfo *createTarget(uint16_t EMachine) { error("Unknown target machine"); } +template <class ELFT> +void SymbolTable::addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section, + typename ELFFile<ELFT>::uintX_t Value) { + typedef typename DefinedSynthetic<ELFT>::Elf_Sym Elf_Sym; + auto ESym = new (Alloc) Elf_Sym; + memset(ESym, 0, sizeof(Elf_Sym)); + ESym->st_value = Value; + auto Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, *ESym, Section); + resolve<ELFT>(Sym); +} + template <class ELFT> void SymbolTable::init(uint16_t EMachine) { Target.reset(createTarget(EMachine)); if (Config->Shared) @@ -205,3 +216,20 @@ void SymbolTable::addMemberFile(Lazy *Body) { addFile(std::move(File)); } + +namespace lld { +namespace elf2 { +template void SymbolTable::addSyntheticSym(StringRef Name, + OutputSection<ELF32LE> &Section, + ELFFile<ELF32LE>::uintX_t Value); +template void SymbolTable::addSyntheticSym(StringRef Name, + OutputSection<ELF32BE> &Section, + ELFFile<ELF32BE>::uintX_t Value); +template void SymbolTable::addSyntheticSym(StringRef Name, + OutputSection<ELF64LE> &Section, + ELFFile<ELF64LE>::uintX_t Value); +template void SymbolTable::addSyntheticSym(StringRef Name, + OutputSection<ELF64BE> &Section, + ELFFile<ELF64BE>::uintX_t Value); +} +} diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 6cf4c531700..4ba1fb041f7 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -61,6 +61,10 @@ public: return EntrySym->getReplacement(); } + template <class ELFT> + void addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section, + typename llvm::object::ELFFile<ELFT>::uintX_t Value); + private: Symbol *insert(SymbolBody *New); template <class ELFT> void addELFFile(ELFFileBase *File); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 8eef8cd2428..3698f2ca22d 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -41,10 +41,11 @@ public: DefinedRegularKind = 0, DefinedAbsoluteKind = 1, DefinedCommonKind = 2, - SharedKind = 3, - DefinedLast = 3, - UndefinedKind = 4, - LazyKind = 5, + DefinedSyntheticKind = 3, + SharedKind = 4, + DefinedLast = 4, + UndefinedKind = 5, + LazyKind = 6, }; Kind kind() const { return static_cast<Kind>(SymbolKind); } @@ -213,6 +214,22 @@ public: const InputSection<ELFT> &Section; }; +template <class ELFT> class DefinedSynthetic : public Defined<ELFT> { + typedef Defined<ELFT> Base; + +public: + typedef typename Base::Elf_Sym Elf_Sym; + explicit DefinedSynthetic(StringRef N, const Elf_Sym &Sym, + OutputSection<ELFT> &Section) + : Defined<ELFT>(Base::DefinedSyntheticKind, N, Sym), Section(Section) {} + + static bool classof(const SymbolBody *S) { + return S->kind() == Base::DefinedSyntheticKind; + } + + const OutputSection<ELFT> &Section; +}; + // Undefined symbol. template <class ELFT> class Undefined : public ELFSymbolBody<ELFT> { typedef ELFSymbolBody<ELFT> Base; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index de6fc2f6de4..61d72b2734b 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -295,7 +295,7 @@ template <class ELFT> void Writer<ELFT>::createSections() { OutputSections.push_back(&BssSec); Map[{BssSec.getName(), BssSec.getType(), BssSec.getFlags()}] = &BssSec; - const SymbolTable &Symtab = SymTabSec.getSymTable(); + SymbolTable &Symtab = SymTabSec.getSymTable(); for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.getObjectFiles()) { auto &File = cast<ObjectFile<ELFT>>(*FileB); if (!Config->DiscardAll) { @@ -323,6 +323,12 @@ template <class ELFT> void Writer<ELFT>::createSections() { } } + if (OutputSection<ELFT> *OS = + Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC})) { + Symtab.addSyntheticSym<ELFT>("__init_array_start", *OS, 0); + Symtab.addSyntheticSym<ELFT>("__init_array_end", *OS, OS->getSize()); + } + // FIXME: Try to avoid the extra walk over all global symbols. std::vector<DefinedCommon<ELFT> *> CommonSymbols; for (auto &P : Symtab.getSymbols()) { diff --git a/lld/test/elf2/init_array.s b/lld/test/elf2/init_array.s new file mode 100644 index 00000000000..a4ce24b650b --- /dev/null +++ b/lld/test/elf2/init_array.s @@ -0,0 +1,49 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +// RUN: lld -flavor gnu2 %t -o %t2 +// RUN: llvm-readobj -symbols -sections %t2 | FileCheck %s +// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s +// REQUIRES: x86 + +.globl _start +_start: + call __init_array_start + call __init_array_end + + +.section .init_array,"aw",@init_array + .quad 0 + + +// CHECK: Name: .init_array +// CHECK-NEXT: Type: SHT_INIT_ARRAY +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x12000 +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 8 + +// CHECK: Name: __init_array_end +// CHECK-NEXT: Value: 0x12008 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .init_array +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: __init_array_start +// CHECK-NEXT: Value: 0x12000 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .init_array +// CHECK-NEXT: } + +// 0x12000 - (0x11000 + 5) = 4091 +// 0x12008 - (0x11005 + 5) = 4094 +// DISASM: _start: +// DISASM-NEXT: 11000: e8 fb 0f 00 00 callq 4091 +// DISASM-NEXT: 11005: e8 fe 0f 00 00 callq 4094 |

