From: Rui Ueyama Date: Wed, 10 Feb 2016 23:20:42 +0000 (+0000) Subject: ELF: Implement __attribute__((init_priority(N)) support. X-Git-Tag: llvmorg-3.9.0-rc1~14509 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c418570db52c06ea798aa00849b6f825fdd7bb4a;p=platform%2Fupstream%2Fllvm.git ELF: Implement __attribute__((init_priority(N)) support. llvm-svn: 260460 --- diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 86c45bf..c1a05ac 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -750,6 +750,44 @@ void OutputSection::addSection(InputSectionBase *C) { this->Header.sh_size = Off; } +// If an input string is in the form of "foo.N" where N is a number, +// return N. Otherwise, returns 65536, which is one greater than the +// lowest priority. +static int getPriority(StringRef S) { + size_t Pos = S.rfind('.'); + if (Pos == StringRef::npos) + return 65536; + int V; + if (S.substr(Pos + 1).getAsInteger(10, V)) + return 65536; + return V; +} + +// Sorts input sections by section name suffixes, so that .foo.N comes +// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections. +// For more detail, read the section of the GCC's manual about init_priority. +template void OutputSection::sortByPriority() { + // Sort sections by priority. + typedef std::pair *> Pair; + std::vector V; + for (InputSection *S : Sections) + V.push_back({getPriority(S->getSectionName()), S}); + std::sort(V.begin(), V.end(), + [](const Pair &A, const Pair &B) { return A.first < B.first; }); + Sections.clear(); + for (Pair &P : V) + Sections.push_back(P.second); + + // Reassign section addresses. + uintX_t Off = 0; + for (InputSection *S : Sections) { + Off = alignTo(Off, S->getAlign()); + S->OutSecOff = Off; + Off += S->getSize(); + } + this->Header.sh_size = Off; +} + // Returns a VA which a relocatin RI refers to. Used only for local symbols. // For non-local symbols, use SymbolBody::getVA instead. template diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 78e66dc..c392b1a 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -279,6 +279,7 @@ public: typedef typename llvm::object::ELFFile::uintX_t uintX_t; OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags); void addSection(InputSectionBase *C) override; + void sortByPriority(); void writeTo(uint8_t *Buf) override; private: diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 4b7118f..92a9890 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -735,6 +735,10 @@ StringRef Writer::getOutputSectionName(StringRef S) const { return ".data"; if (S.startswith(".bss.")) return ".bss"; + if (S.startswith(".init_array.")) + return ".init_array"; + if (S.startswith(".fini_array.")) + return ".fini_array"; return S; } @@ -915,6 +919,13 @@ template void Writer::addReservedSymbols() { Symtab.addAbsolute("end", ElfSym::End); } +// Sort input sections by section name suffixes for +// __attribute__((init_priority(N))). +template static void sortByPriority(OutputSectionBase *S) { + if (S) + reinterpret_cast *>(S)->sortByPriority(); +} + // Create output section objects and add them to OutputSections. template bool Writer::createSections() { OutputSections.push_back(Out::ElfHeader); @@ -962,6 +973,10 @@ template bool Writer::createSections() { Out::Dynamic->FiniArraySec = Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC); + // Sort section contents for __attribute__((init_priority(N)). + sortByPriority(Out::Dynamic->InitArraySec); + sortByPriority(Out::Dynamic->FiniArraySec); + // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop // symbols for sections, so that the runtime can get the start and end // addresses of each section by section name. Add such symbols. diff --git a/lld/test/ELF/init_fini_priority.s b/lld/test/ELF/init_fini_priority.s new file mode 100644 index 0000000..d46ae6f --- /dev/null +++ b/lld/test/ELF/init_fini_priority.s @@ -0,0 +1,29 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +// RUN: ld.lld %t -o %t.exe +// RUN: llvm-objdump -s %t.exe | FileCheck %s +// REQUIRES: x86 + +.globl _start +_start: + nop + +.section .init_array, "aw", @init_array + .align 8 + .byte 1 +.section .init_array.100, "aw", @init_array + .long 2 +.section .init_array.5, "aw", @init_array + .byte 3 + +.section .fini_array, "aw", @fini_array + .align 8 + .byte 4 +.section .fini_array.100, "aw", @fini_array + .long 5 +.section .fini_array.5, "aw", @fini_array + .byte 6 + +// CHECK: Contents of section .init_array: +// CHECK-NEXT: 03020000 00000000 01 +// CHECK: Contents of section .fini_array: +// CHECK-NEXT: 06050000 00000000 04