Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -79,7 +79,7 @@ size_t NumFdes = 0; struct FdeData { - uint32_t Pc; + uint64_t Pc; uint32_t FdeVA; }; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -502,14 +502,16 @@ uint8_t *Buf = getParent()->Loc + OutSecOff; std::vector Ret; + uint64_t VA = InX::EhFrameHdr->getVA(); for (CieRecord *Rec : CieRecords) { uint8_t Enc = getFdeEncoding(Rec->Cie); for (EhSectionPiece *Fde : Rec->Fdes) { uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); - if (Pc > UINT32_MAX) - fatal(toString(Fde->Sec) + ": PC address is too large: " + Twine(Pc)); + if (Pc - VA != (uint64_t)signExtend(Pc - VA, 32)) + fatal(toString(Fde->Sec) + ": PC offset is too large: 0x" + + Twine::utohexstr(Pc - VA)); uint32_t FdeVA = getParent()->Addr + Fde->OutputOff; - Ret.push_back({(uint32_t)Pc, FdeVA}); + Ret.push_back({Pc, FdeVA}); } } return Ret; Index: test/ELF/eh-frame-pcaddr-overflow.s =================================================================== --- test/ELF/eh-frame-pcaddr-overflow.s +++ test/ELF/eh-frame-pcaddr-overflow.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: not ld.lld --eh-frame-hdr --section-start .text=0x1000000000000000 \ # RUN: %t.o -o /dev/null 2>&1 | FileCheck %s -# CHECK: error: {{.*}}.o:(.eh_frame): PC address is too large: 2387527121043355528 +# CHECK: error: {{.*}}.o:(.eh_frame): PC offset is too large: 0x1122334455666788 .text .global foo @@ -14,19 +14,19 @@ .long 12 # Size .long 0x00 # ID .byte 0x01 # Version. - + .byte 0x52 # Augmentation string: 'R','\0' .byte 0x00 - + .byte 0x01 - + .byte 0x01 # LEB128 .byte 0x01 # LEB128 .byte 0x00 # DW_EH_PE_absptr .byte 0xFF - + .long 12 # Size .long 0x14 # ID .quad foo + 0x1122334455667788