https://sourceware.org/bugzilla/show_bug.cgi?id=33864

            Bug ID: 33864
           Summary: ld --eh-frame-hdr: Support DW_EH_PE_sdata8 encoding
           Product: binutils
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: i at maskray dot me
  Target Milestone: ---

When generating the .eh_frame_hdr section, GNU ld currently hardcodes
`DW_EH_PE_pcrel | DW_EH_PE_sdata4` for the `eh_frame_ptr_enc` field and
`DW_EH_PE_datarel | DW_EH_PE_sdata4` for the table_enc field.
This limits all offsets in the binary search table (and the eh_frame pointer)
to the signed 32-bit range (±2 GiB).

When linking executables that use the medium or large code model (e.g.,
-mcmodel=large on x86-64), the distance between .eh_frame_hdr and .text (or
.eh_frame) can easily exceed this 32-bit range.

The following linker script (which works with both GNU ld and LLVM linker) can
be utilized to move .eh_frame_hdr far away .text to simulate a large executable
without actually creating a large file.

% /tmp/Rel/bin/clang++ -mcmodel=large a.cc -o a -fuse-ld=bfd -Wl,-T,a.lds
/usr/bin/ld.bfd: .eh_frame_hdr entry overflow
/usr/bin/ld.bfd: final link failed: bad value
clang++: error: linker command failed with exit code 1 (use -v to see
invocation)

% cat a.cc
#include <stdio.h>
int main() { try { throw 1; } catch (...) { puts("a"); } }

% cat a.lds
SECTIONS
{
  . = SIZEOF_HEADERS;

  .eh_frame : { *(.eh_frame) }
  .rodata.cst4 : {}
  .text : { *(.text .text.*) }

  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
  .init_array    :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*)))
    KEEP (*(.init_array))
    PROVIDE_HIDDEN (__init_array_end = .);
  }
  .fini_array    :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*)))
    KEEP (*(.fini_array))
    PROVIDE_HIDDEN (__fini_array_end = .);
  }
  . = DATA_SEGMENT_RELRO_END (0, .);
  .data           : { *(.data .data.*) }
  . = .;
  .bss            : { *(.bss .bss.*) *(COMMON) }
  . = DATA_SEGMENT_END (.);

  /// Comment out the following line to avoid the error
  .eh_frame_hdr 0x200000000 : {}
}

Adopting the DW_EH_PE_sdata8 encoding would fix the linker error.
I've tested that libgcc has a working DW_EH_PE_sdata8 decoder support.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to