summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/OutputSections.cpp18
-rw-r--r--lld/ELF/OutputSections.h6
-rw-r--r--lld/ELF/Writer.cpp10
-rw-r--r--lld/test/elf2/init_array.s61
4 files changed, 82 insertions, 13 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 91839150f9b..7e7ad4990ca 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -211,6 +211,13 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
DynStrSec.add(Config->SoName);
}
+ if (PreInitArraySec)
+ NumEntries += 2;
+ if (InitArraySec)
+ NumEntries += 2;
+ if (FiniArraySec)
+ NumEntries += 2;
+
const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
SymTab.getSharedFiles();
for (const std::unique_ptr<SharedFileBase> &File : SharedFiles)
@@ -257,6 +264,17 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
if (!Config->SoName.empty())
WriteVal(DT_SONAME, DynStrSec.getFileOff(Config->SoName));
+ auto WriteArray = [&](int32_t T1, int32_t T2,
+ const OutputSection<ELFT> *Sec) {
+ if (!Sec)
+ return;
+ WritePtr(T1, Sec->getVA());
+ WriteVal(T2, Sec->getSize());
+ };
+ WriteArray(DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ, PreInitArraySec);
+ WriteArray(DT_INIT_ARRAY, DT_INIT_ARRAYSZ, InitArraySec);
+ WriteArray(DT_FINI_ARRAY, DT_FINI_ARRAYSZ, FiniArraySec);
+
const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
SymTab.getSharedFiles();
for (const std::unique_ptr<SharedFileBase> &File : SharedFiles)
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 3f0022bd7be..e36ac9eee7c 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -70,7 +70,7 @@ public:
void setSectionIndex(unsigned I) { SectionIndex = I; }
// Returns the size of the section in the output file.
- uintX_t getSize() { return Header.sh_size; }
+ uintX_t getSize() const { return Header.sh_size; }
void setSize(uintX_t Val) { Header.sh_size = Val; }
uintX_t getFlags() { return Header.sh_flags; }
uintX_t getFileOff() { return Header.sh_offset; }
@@ -324,6 +324,10 @@ public:
void finalize() override;
void writeTo(uint8_t *Buf) override;
+ OutputSection<ELFT> *PreInitArraySec = nullptr;
+ OutputSection<ELFT> *InitArraySec = nullptr;
+ OutputSection<ELFT> *FiniArraySec = nullptr;
+
private:
HashTableSection<ELFT> &HashSec;
SymbolTableSection<ELFT> &DynSymSec;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 7ffa6d2b9cc..43a92b04c2e 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -328,8 +328,14 @@ template <class ELFT> void Writer<ELFT>::createSections() {
}
}
- if (OutputSection<ELFT> *OS =
- Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC})) {
+ DynamicSec.PreInitArraySec =
+ Map.lookup({".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC});
+ DynamicSec.InitArraySec =
+ Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC});
+ DynamicSec.FiniArraySec =
+ Map.lookup({".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC});
+
+ if (OutputSection<ELFT> *OS = DynamicSec.InitArraySec) {
Symtab.addSyntheticSym<ELFT>("__init_array_start", *OS, 0);
Symtab.addSyntheticSym<ELFT>("__init_array_end", *OS, OS->getSize());
} else {
diff --git a/lld/test/elf2/init_array.s b/lld/test/elf2/init_array.s
index a4ce24b650b..c2d1b672642 100644
--- a/lld/test/elf2/init_array.s
+++ b/lld/test/elf2/init_array.s
@@ -1,6 +1,8 @@
// 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-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2
+// RUN: lld -flavor gnu2 %t2 -o t2.so -shared
+// RUN: lld -flavor gnu2 %t t2.so -o %t2
+// RUN: llvm-readobj -symbols -sections -dynamic-table %t2 | FileCheck %s
// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s
// REQUIRES: x86
@@ -13,6 +15,13 @@ _start:
.section .init_array,"aw",@init_array
.quad 0
+.section .preinit_array,"aw",@preinit_array
+ .quad 0
+ .byte 0
+
+.section .fini_array,"aw",@fini_array
+ .quad 0
+ .short 0
// CHECK: Name: .init_array
// CHECK-NEXT: Type: SHT_INIT_ARRAY
@@ -20,12 +29,34 @@ _start:
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x12000
+// CHECK-NEXT: Address: [[INIT_ADDR:.*]]
// CHECK-NEXT: Offset:
-// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Size: [[INIT_SIZE:.*]]
+
+
+// CHECK: Name: .preinit_array
+// CHECK-NEXT: Type: SHT_PREINIT_ARRAY
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[PREINIT_ADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[PREINIT_SIZE:.*]]
+
+
+// CHECK: Name: .fini_array
+// CHECK-NEXT: Type: SHT_FINI_ARRAY
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[FINI_ADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[FINI_SIZE:.*]]
// CHECK: Name: __init_array_end
-// CHECK-NEXT: Value: 0x12008
+// CHECK-NEXT: Value: 0x13008
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
@@ -34,7 +65,7 @@ _start:
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: __init_array_start
-// CHECK-NEXT: Value: 0x12000
+// CHECK-NEXT: Value: [[INIT_ADDR]]
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
@@ -42,8 +73,18 @@ _start:
// CHECK-NEXT: Section: .init_array
// CHECK-NEXT: }
-// 0x12000 - (0x11000 + 5) = 4091
-// 0x12008 - (0x11005 + 5) = 4094
+
+// CHECK: DynamicSection
+// CHECK: PREINIT_ARRAY [[PREINIT_ADDR]]
+// CHECK: PREINIT_ARRAYSZ [[PREINIT_SIZE]] (bytes)
+// CHECK: INIT_ARRAY [[INIT_ADDR]]
+// CHECK: INIT_ARRAYSZ [[INIT_SIZE]] (bytes)
+// CHECK: FINI_ARRAY [[FINI_ADDR]]
+// CHECK: FINI_ARRAYSZ [[FINI_SIZE]] (bytes)
+
+
+// 0x13000 - (0x12000 + 5) = 4091
+// 0x13008 - (0x12005 + 5) = 4094
// DISASM: _start:
-// DISASM-NEXT: 11000: e8 fb 0f 00 00 callq 4091
-// DISASM-NEXT: 11005: e8 fe 0f 00 00 callq 4094
+// DISASM-NEXT: 12000: e8 fb 0f 00 00 callq 4091
+// DISASM-NEXT: 12005: e8 fe 0f 00 00 callq 4094
OpenPOWER on IntegriCloud