aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-04-26 19:29:40 +0000
committerRui Ueyama <ruiu@google.com>2017-04-26 19:29:40 +0000
commitada5756959e1356d1911702872ba625b8ee67210 (patch)
treebc888dfc49cae6dff5b5016edc13a6cb9b14d7e5
parenta06ea07411c4b849b11126821847859538005f69 (diff)
Merge r298569: Force @{init,fini}_array if section name starts with ".{init,fini}_array.".
Related bug: http://bugs.llvm.org/show_bug.cgi?id=32599 git-svn-id: https://llvm.org/svn/llvm-project/lld/branches/release_40@301447 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--ELF/InputSection.cpp26
-rw-r--r--test/ELF/init-fini-progbits.s19
2 files changed, 41 insertions, 4 deletions
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index 6b1e92891..d89ac25f0 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -84,14 +84,32 @@ InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
this->Flags &= ~(SHF_MERGE | SHF_STRINGS);
}
+// GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of
+// March 2017) fail to infer section types for sections starting with
+// ".init_array." or ".fini_array.". They set SHT_PROGBITS instead of
+// SHF_INIT_ARRAY. As a result, the following assembler directive
+// creates ".init_array.100" with SHT_PROGBITS, for example.
+//
+// .section .init_array.100, "aw"
+//
+// This function forces SHT_{INIT,FINI}_ARRAY so that we can handle
+// incorrect inputs as if they were correct from the beginning.
+static uint64_t getType(uint64_t Type, StringRef Name) {
+ if (Type == SHT_PROGBITS && Name.startswith(".init_array."))
+ return SHT_INIT_ARRAY;
+ if (Type == SHT_PROGBITS && Name.startswith(".fini_array."))
+ return SHT_FINI_ARRAY;
+ return Type;
+}
+
template <class ELFT>
InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
const Elf_Shdr *Hdr, StringRef Name,
Kind SectionKind)
- : InputSectionBase(File, Hdr->sh_flags & ~SHF_INFO_LINK, Hdr->sh_type,
- Hdr->sh_entsize, Hdr->sh_link, Hdr->sh_info,
- Hdr->sh_addralign, getSectionContents(File, Hdr), Name,
- SectionKind) {
+ : InputSectionBase(File, Hdr->sh_flags & ~SHF_INFO_LINK,
+ getType(Hdr->sh_type, Name), Hdr->sh_entsize,
+ Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign,
+ getSectionContents(File, Hdr), Name, SectionKind) {
this->Offset = Hdr->sh_offset;
}
diff --git a/test/ELF/init-fini-progbits.s b/test/ELF/init-fini-progbits.s
new file mode 100644
index 000000000..a8749446f
--- /dev/null
+++ b/test/ELF/init-fini-progbits.s
@@ -0,0 +1,19 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t.exe
+// RUN: llvm-readobj -sections %t.exe | FileCheck %s
+
+// CHECK: Name: .init_array
+// CHECK-NEXT: Type: SHT_INIT_ARRAY
+// CHECK: Name: .fini_array
+// CHECK-NEXT: Type: SHT_FINI_ARRAY
+
+.globl _start
+_start:
+ nop
+
+.section .init_array.100, "aw", @progbits
+ .byte 0
+.section .fini_array.100, "aw", @progbits
+ .byte 0