Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -746,11 +746,13 @@ Buf += 12; // InitialPC -> Offset in .eh_frame, sorted by InitialPC. - std::map PcToOffset; + // We use a multimap in order to handle duplicate PCs, which can happen if ICF + // was able to merge functions with FDEs. + std::multimap PcToOffsets; for (const FdeData &F : FdeList) - PcToOffset[getFdePc(EhVA, F)] = F.Off; + PcToOffsets.insert({getFdePc(EhVA, F), F.Off}); - for (auto &I : PcToOffset) { + for (auto &I : PcToOffsets) { // The first four bytes are an offset to the initial PC value for the FDE. write32(Buf, I.first - VA); // The last four bytes are an offset to the FDE data itself. Index: test/ELF/eh-frame-hdr-icf.s =================================================================== --- /dev/null +++ test/ELF/eh-frame-hdr-icf.s @@ -0,0 +1,26 @@ +# 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 02000000 600e0000 +# CHECK-NEXT: 101b0 d0ffffff 600e0000 e8ffffff +# ^ FDE for f1 ^ 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