diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-10-02 19:37:55 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-10-02 19:37:55 +0000 |
| commit | 7757224466a224e7bf19d506b2bf460ac285884d (patch) | |
| tree | 591688e9ea86036af4e02d93ec032d737e55cf91 | |
| parent | d57f4b901195bc89200e46a75f78133454fefa19 (diff) | |
| download | bcm5719-llvm-7757224466a224e7bf19d506b2bf460ac285884d.tar.gz bcm5719-llvm-7757224466a224e7bf19d506b2bf460ac285884d.zip | |
Add static initialization/finalization array support.
This adds entries in the dynamic table for .init_array, .fini_array and
.preinit_array.
llvm-svn: 249175
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 18 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.h | 6 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 10 | ||||
| -rw-r--r-- | lld/test/elf2/init_array.s | 61 |
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 |

