diff options
-rw-r--r-- | lld/lib/ReaderWriter/ELF/AtomsELF.h | 6 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/WriterELF.cpp | 43 | ||||
-rw-r--r-- | lld/test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lld/test/elf/Inputs/init_array.x86-64 | bin | 0 -> 3440 bytes | |||
-rw-r--r-- | lld/test/elf/init_array.test | 5 |
5 files changed, 54 insertions, 2 deletions
diff --git a/lld/lib/ReaderWriter/ELF/AtomsELF.h b/lld/lib/ReaderWriter/ELF/AtomsELF.h index 1c48ef8e3c2..3a8e83ddcb4 100644 --- a/lld/lib/ReaderWriter/ELF/AtomsELF.h +++ b/lld/lib/ReaderWriter/ELF/AtomsELF.h @@ -283,6 +283,9 @@ public: || _symbol->st_shndx == llvm::ELF::SHN_COMMON) ret = typeZeroFill; break; + case llvm::ELF::SHT_INIT_ARRAY: + ret = typeData; + break; } return ret; @@ -356,6 +359,9 @@ public: case llvm::ELF::SHT_NOBITS: return permRW_; + case llvm::ELF::SHT_INIT_ARRAY: + return permRW_; + default: return perm___; } diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp index 6c1a633c9b0..467db99c81a 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -1457,6 +1457,8 @@ public: ORDER_EH_FRAMEHDR, ORDER_CTORS, ORDER_DTORS, + ORDER_INIT_ARRAY, + ORDER_FINI_ARRAY, ORDER_DYNAMIC, ORDER_GOT, ORDER_GOT_PLT, @@ -1565,7 +1567,9 @@ public: return ORDER_RODATA; case DefinedAtom::typeData: - return ORDER_DATA; + return llvm::StringSwitch<Reference::Kind>(name) + .StartsWith(".init_array", ORDER_INIT_ARRAY) + .Default(ORDER_DATA); case DefinedAtom::typeZeroFill: return ORDER_BSS; @@ -1624,6 +1628,8 @@ public: case ORDER_GOT_PLT: case ORDER_DATA: case ORDER_BSS: + case ORDER_INIT_ARRAY: + case ORDER_FINI_ARRAY: return llvm::ELF::PT_LOAD; default: @@ -1654,6 +1660,8 @@ public: case ORDER_GOT: case ORDER_GOT_PLT: case ORDER_DATA: + case ORDER_INIT_ARRAY: + case ORDER_FINI_ARRAY: case ORDER_BSS: return true; @@ -1708,6 +1716,25 @@ public: return error_code::success(); } + /// \biref Find an output Section given a section name. + /// + /// \todo Make this not O(n). We can't use _mergedSectionMap because it + /// doesn't get virtual addresses set :( + Chunk<target_endianness, max_align, is64Bits> * + findOutputSection(StringRef name) { + for (auto seg : _segments) { + for (auto sliceI = seg->slices_begin(), + sliceE = seg->slices_end(); sliceI != sliceE; ++sliceI) { + for (auto secI = (*sliceI)->sections_begin(), + secE = (*sliceI)->sections_end(); secI != secE; ++secI) { + if ((*secI)->name() == name) + return *secI; + } + } + } + return nullptr; + } + /// \brief find a absolute atom given a name AbsoluteAtomIterT findAbsoluteAtom(const StringRef name) { return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(), @@ -2211,6 +2238,8 @@ void ELFExecutableWriter<target_endianness, max_align, is64Bits> _runtimeFile.addAbsoluteAtom("__bss_end"); _runtimeFile.addAbsoluteAtom("_end"); _runtimeFile.addAbsoluteAtom("end"); + _runtimeFile.addAbsoluteAtom("__init_array_start"); + _runtimeFile.addAbsoluteAtom("__init_array_end"); } /// \brief Hook in lld to add CRuntime file @@ -2234,6 +2263,18 @@ void ELFExecutableWriter<target_endianness, max_align, is64Bits> auto bssEndAtomIter = _layout->findAbsoluteAtom("__bss_end"); auto underScoreEndAtomIter = _layout->findAbsoluteAtom("_end"); auto endAtomIter = _layout->findAbsoluteAtom("end"); + auto initArrayStartIter = _layout->findAbsoluteAtom("__init_array_start"); + auto initArrayEndIter = _layout->findAbsoluteAtom("__init_array_end"); + + auto section = _layout->findOutputSection(".init_array"); + if (section) { + initArrayStartIter->setValue(section->virtualAddr()); + initArrayEndIter->setValue(section->virtualAddr() + + section->memSize()); + } else { + initArrayStartIter->setValue(0); + initArrayEndIter->setValue(0); + } assert(!(bssStartAtomIter == _layout->absAtomsEnd() || bssEndAtomIter == _layout->absAtomsEnd() || diff --git a/lld/test/CMakeLists.txt b/lld/test/CMakeLists.txt index cb8882a9d8d..460e6f8c14d 100644 --- a/lld/test/CMakeLists.txt +++ b/lld/test/CMakeLists.txt @@ -20,7 +20,7 @@ if ( NOT LLD_BUILT_STANDALONE ) set(LLD_TEST_DEPS lld-core lld-test.deps FileCheck not llvm-nm - lld + lld llvm-objdump ) set(LLD_TEST_PARAMS lld_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg diff --git a/lld/test/elf/Inputs/init_array.x86-64 b/lld/test/elf/Inputs/init_array.x86-64 Binary files differnew file mode 100644 index 00000000000..2425c227fd4 --- /dev/null +++ b/lld/test/elf/Inputs/init_array.x86-64 diff --git a/lld/test/elf/init_array.test b/lld/test/elf/init_array.test new file mode 100644 index 00000000000..8a3b1354150 --- /dev/null +++ b/lld/test/elf/init_array.test @@ -0,0 +1,5 @@ +RUN: lld -flavor ld -target x86_64-linux -o %t %p/Inputs/init_array.x86-64 +RUN: llvm-objdump -t -section-headers %t | FileCheck %s + +CHECK: .init_array {{[0-9]+}} [[ADDR:[0-9]+]] +CHECK: [[ADDR]] g *ABS* {{[0-9]+}} __init_array_start |