diff options
author | Rui Ueyama <ruiu@google.com> | 2017-04-26 19:29:40 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2017-04-26 19:29:40 +0000 |
commit | ada5756959e1356d1911702872ba625b8ee67210 (patch) | |
tree | bc888dfc49cae6dff5b5016edc13a6cb9b14d7e5 | |
parent | a06ea07411c4b849b11126821847859538005f69 (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.cpp | 26 | ||||
-rw-r--r-- | test/ELF/init-fini-progbits.s | 19 |
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 |