diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 51bbcd49f304..6bc31fcff7aa 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -60,6 +60,7 @@ private: void addPredefinedSections(); std::vector createPhdrs(); + void addPtArmExid(std::vector &Phdrs); void assignAddresses(); void assignFileOffsets(); void assignFileOffsetsBinary(); @@ -181,6 +182,7 @@ template void Writer::run() { } else { Phdrs = Script::X->hasPhdrsCommands() ? Script::X->createPhdrs() : createPhdrs(); + addPtArmExid(Phdrs); fixHeaders(); if (ScriptConfig->HasSections) { Script::X->assignAddresses(Phdrs); @@ -1129,7 +1131,6 @@ template std::vector> Writer::createPhdrs() { Phdr TlsHdr(PT_TLS, PF_R); Phdr RelRo(PT_GNU_RELRO, PF_R); Phdr Note(PT_NOTE, PF_R); - Phdr ARMExidx(PT_ARM_EXIDX, PF_R); for (OutputSectionBase *Sec : OutputSections) { if (!(Sec->Flags & SHF_ALLOC)) break; @@ -1160,8 +1161,6 @@ template std::vector> Writer::createPhdrs() { RelRo.add(Sec); if (Sec->Type == SHT_NOTE) Note.add(Sec); - if (Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX) - ARMExidx.add(Sec); } // Add the TLS segment unless it's empty. @@ -1194,10 +1193,6 @@ template std::vector> Writer::createPhdrs() { Hdr.add(Sec); } - // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME - if (ARMExidx.First) - Ret.push_back(std::move(ARMExidx)); - // PT_GNU_STACK is a special section to tell the loader to make the // pages for the stack non-executable. if (!Config->ZExecstack) { @@ -1218,6 +1213,22 @@ template std::vector> Writer::createPhdrs() { return Ret; } +template +void Writer::addPtArmExid(std::vector> &Phdrs) { + if (Config->EMachine != EM_ARM) + return; + auto I = std::find_if( + OutputSections.begin(), OutputSections.end(), + [](OutputSectionBase *Sec) { return Sec->Type == SHT_ARM_EXIDX; }); + if (I == OutputSections.end()) + return; + + // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME + Phdr ARMExidx(PT_ARM_EXIDX, PF_R); + ARMExidx.add(*I); + Phdrs.push_back(ARMExidx); +} + // The first section of each PT_LOAD and the first section after PT_GNU_RELRO // have to be page aligned so that the dynamic linker can set the permissions. template void Writer::fixSectionAlignments() { diff --git a/lld/test/ELF/linkerscript/arm-exidx-phdrs.s b/lld/test/ELF/linkerscript/arm-exidx-phdrs.s new file mode 100644 index 000000000000..971702f55d7b --- /dev/null +++ b/lld/test/ELF/linkerscript/arm-exidx-phdrs.s @@ -0,0 +1,16 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +// RUN: echo "PHDRS { ph_text PT_LOAD; } \ +// RUN: SECTIONS { \ +// RUN: . = SIZEOF_HEADERS; \ +// RUN: .text : { *(.text) } : ph_text \ +// RUN: }" > %t.script +// RUN: ld.lld -T %t.script %t.o -shared -o %t.so +// RUN: llvm-readobj --program-headers %t.so | FileCheck %s + +// CHECK: Type: PT_ARM_EXIDX + +.fnstart +bx lr +.cantunwind +.fnend