Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -727,23 +727,25 @@ template void EhFrameHeader::writeTo(uint8_t *Buf) { const endianness E = ELFT::TargetEndianness; + uintX_t EhVA = Sec->getVA(); + uintX_t VA = this->getVA(); + + // InitialPC -> Offset in .eh_frame, sorted by InitialPC, and deduplicate PCs. + // FIXME: Deduplication leaves unneeded null bytes at the end of the section. + std::map PcToOffset; + for (const FdeData &F : FdeList) + PcToOffset[getFdePc(EhVA, F)] = F.Off; + const uint8_t Header[] = {1, DW_EH_PE_pcrel | DW_EH_PE_sdata4, DW_EH_PE_udata4, DW_EH_PE_datarel | DW_EH_PE_sdata4}; memcpy(Buf, Header, sizeof(Header)); - uintX_t EhVA = Sec->getVA(); - uintX_t VA = this->getVA(); uintX_t EhOff = EhVA - VA - 4; write32(Buf + 4, EhOff); - write32(Buf + 8, this->FdeList.size()); + write32(Buf + 8, PcToOffset.size()); Buf += 12; - // InitialPC -> Offset in .eh_frame, sorted by InitialPC. - std::map PcToOffset; - for (const FdeData &F : FdeList) - PcToOffset[getFdePc(EhVA, F)] = F.Off; - for (auto &I : PcToOffset) { // The first four bytes are an offset to the initial PC value for the FDE. write32(Buf, I.first - VA); Index: lld/trunk/test/ELF/eh-frame-hdr-icf.s =================================================================== --- lld/trunk/test/ELF/eh-frame-hdr-icf.s +++ lld/trunk/test/ELF/eh-frame-hdr-icf.s @@ -0,0 +1,27 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr +# RUN: llvm-objdump -s %t2 | FileCheck %s + +# CHECK: Contents of section .eh_frame_hdr: +# CHECK-NEXT: 101a0 011b033b b4ffffff 01000000 600e0000 +# ^ FDE count +# CHECK-NEXT: 101b0 e8ffffff 00000000 00000000 +# ^ FDE for f2 + +.globl _start, f1, f2 +_start: + ret + +.section .text.f1, "ax" +f1: + .cfi_startproc + ret + .cfi_endproc + +.section .text.f2, "ax" +f2: + .cfi_startproc + ret + .cfi_endproc