summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2015-09-25 18:56:53 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2015-09-25 18:56:53 +0000
commit0e604f913ada479925e4f6106867b3c5d3646e32 (patch)
tree03b9d748f98170d6f50e9143f8e7b0983555da0b
parent33d6c0bbc59e600115eb83cdcb27b8d5e0e8f177 (diff)
downloadbcm5719-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.cpp5
-rw-r--r--lld/ELF/OutputSections.h2
-rw-r--r--lld/ELF/SymbolTable.cpp28
-rw-r--r--lld/ELF/SymbolTable.h4
-rw-r--r--lld/ELF/Symbols.h25
-rw-r--r--lld/ELF/Writer.cpp8
-rw-r--r--lld/test/elf2/init_array.s49
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
OpenPOWER on IntegriCloud