| # REQUIRES: x86 && llvm-64-bits |
| |
| ## Test that .eh_frame_hdr uses DW_EH_PE_sdata8 instead of DW_EH_PE_sdata4 when |
| ## eh_frame_ptr or a table entry exceeds the 32-bit range. |
| |
| # RUN: rm -rf %t && split-file %s %t && cd %t |
| # RUN: llvm-mc -filetype=obj -triple=x86_64 a.s --large-code-model -o a.o |
| # RUN: llvm-mc -filetype=obj -triple=x86_64 bad.s -o bad.o |
| |
| ## Case 1: .text at high address - pcRel exceeds 32-bit range. |
| # RUN: ld.lld --eh-frame-hdr -T 1.lds a.o -o out1 |
| # RUN: llvm-objdump -s -j .eh_frame_hdr out1 | FileCheck %s --check-prefix=CHECK1 |
| |
| ## Case 2: .eh_frame at high address - eh_frame_ptr exceeds 32-bit range. |
| # RUN: ld.lld --eh-frame-hdr -T 2.lds a.o -o out2 |
| # RUN: llvm-objdump -s -j .eh_frame_hdr out2 | FileCheck %s --check-prefix=CHECK2 |
| |
| ## Case 3: .eh_frame_hdr and .relr.dyn sizes are coupled, requiring multiple iterations |
| ## to stabilize. |
| # RUN: ld.lld -pie --eh-frame-hdr -z pack-relative-relocs -T 3.lds a.o -o out3 |
| # RUN: llvm-objdump -s -j .eh_frame_hdr out3 | FileCheck %s --check-prefix=CHECK3 |
| |
| ## Header: version=1, eh_frame_ptr_enc=0x1C (pcrel|sdata8), |
| ## fde_count_enc=0x03 (udata4), table_enc=0x3C (datarel|sdata8) |
| ## Layout: header (4) + eh_frame_ptr (8) + fde_count (4) + table entries (16 each) |
| ## Each table entry: pcRel (8) + fdeVARel (8), relative to .eh_frame_hdr address |
| # CHECK1: section .eh_frame_hdr: |
| # CHECK1-NEXT: 011c033c 2c000000 00000000 02000000 |
| # CHECK1-NEXT: 00100000 01000000 48000000 00000000 |
| # CHECK1-NEXT: 01100000 01000000 68000000 00000000 |
| # CHECK1-EMPTY: |
| # CHECK2: section .eh_frame_hdr: |
| # CHECK2-NEXT: 011c033c f80f0000 01000000 02000000 |
| # CHECK2-NEXT: fcffffff ffffffff 14100000 01000000 |
| # CHECK2-NEXT: fdffffff ffffffff 34100000 01000000 |
| # CHECK2-EMPTY: |
| # CHECK3: 011c033c 2c000000 00000000 02000000 |
| # CHECK3-NEXT: 00800000 01000000 48000000 00000000 |
| |
| ## A corrupted .eh_frame reports exactly one error (not duplicated by the loop). |
| # RUN: not ld.lld --eh-frame-hdr -T 1.lds a.o bad.o 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error: |
| # ERR: error: corrupted .eh_frame: unexpected end of CIE |
| |
| #--- a.s |
| .text |
| .global _start |
| _start: |
| .cfi_startproc |
| nop |
| .cfi_endproc |
| .cfi_startproc |
| nop |
| .cfi_endproc |
| |
| .data |
| .balign 8 |
| ## Two adjacent relocations use 2 RELR entries (1 address + 1 bitmap). |
| .dc.a __ehdr_start |
| .dc.a __ehdr_start |
| |
| .section .data.1,"aw" |
| .balign 8 |
| ## A RELR bitmap entry can encode up to 63 relocations with word-sized stride. |
| ## If .data.1 is >= 63*8 bytes from end(.data), this relocation cannot reuse |
| ## the previous bitmap entry, requiring a third RELR entry. |
| .dc.a __ehdr_start |
| |
| #--- 1.lds |
| ## Use AT() to place output sections with huge addresses in separate PT_LOAD |
| ## segments, avoiding a huge PT_LOAD whose sparse file size would exceed 4GiB. |
| SECTIONS { |
| . = 0x1000; |
| .eh_frame_hdr : {} |
| .eh_frame : {} |
| .text 0x100002000 : AT(0x2000) {} |
| } |
| |
| #--- 2.lds |
| SECTIONS { |
| . = 0x1000; |
| .text : {} |
| .eh_frame_hdr : {} |
| .eh_frame 0x100002000 : AT(0x2000) {} |
| } |
| |
| #--- 3.lds |
| SECTIONS { |
| ## Test that .eh_frame_hdr and .relr.dyn sizes are coupled, requiring |
| ## multiple finalizeAddressDependentContent iterations to converge. |
| ## |
| ## The padding before .data.1 is set so that switching .eh_frame_hdr from |
| ## sdata4 (18 bytes) to sdata8 (48 bytes) pushes .data.1 past the 63*8-byte |
| ## RELR bitmap threshold, growing .relr.dyn from 16 to 24 bytes. |
| ## The .text address depends on SIZEOF(.relr.dyn), creating the coupling. |
| .eh_frame_hdr : {} |
| .eh_frame : {} |
| .relr.dyn : {} |
| .data : { *(.data) . += 63*8-40 + SIZEOF(.eh_frame_hdr); *(.data.*) } |
| . = SIZEOF(.relr.dyn) > 16 ? 0x100008000 : 0x3000; |
| .text : AT(0x2000) {} |
| ASSERT(SIZEOF(.relr.dyn) > 16, ".relr.dyn size should increase from 16 to 24") |
| } |
| |
| #--- bad.s |
| ## Malformed CIE: length says 8 bytes but content is truncated. |
| .section .eh_frame,"a",@unwind |
| .long 8 # length |
| .long 0 # CIE id |
| .byte 1 # version |
| .byte 0 # augmentation string (empty) |
| ## Missing: code/data alignment, return column, etc. |
| .space 2 |