Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -668,25 +668,37 @@ typename EhFrameHeader::uintX_t EhFrameHeader::getFdePc(uintX_t EhVA, const FdeData &F) { const endianness E = ELFT::TargetEndianness; - assert((F.Enc & 0xF0) != DW_EH_PE_datarel); - - uintX_t FdeOff = EhVA + F.Off + 8; + uint64_t PC = 0; switch (F.Enc & 0xF) { case DW_EH_PE_udata2: case DW_EH_PE_sdata2: - return FdeOff + read16(F.PCRel); + PC = read16(F.PCRel); + break; case DW_EH_PE_udata4: case DW_EH_PE_sdata4: - return FdeOff + read32(F.PCRel); + PC = read32(F.PCRel); + break; case DW_EH_PE_udata8: case DW_EH_PE_sdata8: - return FdeOff + read64(F.PCRel); + PC = read64(F.PCRel); + break; case DW_EH_PE_absptr: if (sizeof(uintX_t) == 8) - return FdeOff + read64(F.PCRel); - return FdeOff + read32(F.PCRel); + PC = read64(F.PCRel); + else + PC = read32(F.PCRel); + break; + default: + fatal("unknown FDE size encoding"); + } + switch (F.Enc & 0x70) { + case DW_EH_PE_absptr: + return PC; + case DW_EH_PE_pcrel: + return PC + EhVA + F.Off + 8; + default: + fatal("unknown FDE size relative encoding"); } - fatal("unknown FDE size encoding"); } template void EhFrameHeader::writeTo(uint8_t *Buf) { @@ -1084,8 +1096,10 @@ skipAugP(D); continue; } - if (C == 'L') + if (C == 'L') { + readByte(D); continue; + } fatal("unknown .eh_frame augmentation string: " + Aug); } return DW_EH_PE_absptr; Index: test/ELF/eh-frame-hdr-abs-fde.s =================================================================== --- /dev/null +++ test/ELF/eh-frame-hdr-abs-fde.s @@ -0,0 +1,49 @@ +# Check reading PC values of FDEs if augmentation string has 'L' token +# and PC values are encoded using DW_EH_PE_absptr format. + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: ld.lld --eh-frame-hdr %t.o -o %t +# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=REL %s +# RUN: llvm-objdump -s -dwarf=frames %t | FileCheck %s + +# REQUIRES: mips + +# REL: Relocations [ +# REL-NEXT: Section (8) .rel.eh_frame { +# REL-NEXT: 0x20 R_MIPS_32 .text 0x0 +# REL-NEXT: 0x29 R_MIPS_32 .data 0x0 +# REL-NEXT: } +# REL-NEXT: ] + +# CHECK: Contents of section .eh_frame: +# CHECK-NEXT: 10128 00000014 00000000 017a4c52 00017c1f +# CHECK-NEXT: 10138 02000b0c 1d000000 00000014 0000001c +# ^-- 'z' +# ^-- 'L' - LSDA encoding +# ^-- 'R' - FDE encoding +# 0xb == DW_EH_PE_udata4 | DW_EH_PE_signed +# CHECK-NEXT: 10148 00020000 00000004 04000300 00000000 +# ^-- .text ^-- .data +# CHECK-NEXT: Contents of section .eh_frame_hdr: +# CHECK-NEXT: 10158 011b033b ffffffcc 00000001 0000fea8 +# ^-- 0x20000 - 0x10158 +# .txet - .eh_frame_hdr +# CHECK-NEXT: 10168 ffffffe8 +# CHECK-NEXT: Contents of section .text: +# CHECK-NEXT: 20000 00000000 +# CHECK-NEXT: Contents of section .data: +# CHECK-NEXT: 30000 00000000 + +# CHECK: Augmentation: "zLR" + + .text + .globl __start +__start: + .cfi_startproc + .cfi_lsda 0, _ex + nop + .cfi_endproc + + .data +_ex: + .word 0