From 34e3d50d18fa8ad9f63d98731cb585d91d2349ca Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 23 Mar 2017 01:00:41 +0000 Subject: [PATCH] Force @{init,fini}_array if section name starts with ".{init,fini}_array.". Fixes https://bugs.llvm.org/show_bug.cgi?id=32307. Differential Revision: https://reviews.llvm.org/D31255 llvm-svn: 298569 --- lld/ELF/InputSection.cpp | 26 ++++++++++++++++++++++---- lld/test/ELF/init-fini-progbits.s | 19 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 lld/test/ELF/init-fini-progbits.s diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 92b2e57..7d542db 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -71,14 +71,32 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, this->Alignment = V; } +// 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 InputSectionBase::InputSectionBase(elf::ObjectFile *File, const typename ELFT::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) { // We reject object files having insanely large alignments even though // they are allowed by the spec. I think 4GB is a reasonable limitation. // We might want to relax this in the future. diff --git a/lld/test/ELF/init-fini-progbits.s b/lld/test/ELF/init-fini-progbits.s new file mode 100644 index 0000000..a874944 --- /dev/null +++ b/lld/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 -- 2.7.4