summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/ReaderWriter/ELF/AtomsELF.h6
-rw-r--r--lld/lib/ReaderWriter/ELF/WriterELF.cpp43
-rw-r--r--lld/test/CMakeLists.txt2
-rw-r--r--lld/test/elf/Inputs/init_array.x86-64bin0 -> 3440 bytes
-rw-r--r--lld/test/elf/init_array.test5
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
new file mode 100644
index 00000000000..2425c227fd4
--- /dev/null
+++ b/lld/test/elf/Inputs/init_array.x86-64
Binary files differ
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
OpenPOWER on IntegriCloud