`ld` segfaults on getting the address of __GNU_EH_FRAME_HDR

Hello!

ld segfaults when compiling a simple Rust program that tries to read the address of the __GNU_EH_FRAME_HDR symbol.

$ tree
.
├── Cargo.toml
└── src
    └── main.rs
# Cargo.toml
[package]
name = "ldtest"
version = "0.1.0"
edition = "2021"
[dependencies]
// src/main.rs
use std::ptr::addr_of;

extern "C" {
    #[link_name = "__GNU_EH_FRAME_HDR"]
    static GNU_EH_FRAME_HDR: u8;
}

fn main() {
    let a = unsafe { addr_of!(GNU_EH_FRAME_HDR) };
}
$ cargo run
   Compiling ldtest v0.1.0 (/home/kevin/prog/rust/ldtest)
warning: unused variable: `a`
 --> src/main.rs:9:9
  |
9 |     let a = unsafe { addr_of!(GNU_EH_FRAME_HDR) };
  |         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `#[warn(unused_variables)]` on by default

error: linking with `cc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/kevin/.bin:/usr/local/bin:/home/kevin/.cargo/bin:/home/kevin/.local/share/gem/ruby/3.0.0/bin:/home/kevin/.bin:/usr/local/bin:/home/kevin/.cargo/bin:/home/kevin/.local/share/gem/ruby/3.0.0/bin:/home/kevin/.local/share/gem/ruby/3.0.0/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl" VSLANG="1033" "cc" "-m64" "/tmp/rustcfkzz5x/symbols.o" "/home/kevin/prog/rust/ldtest/target/debug/deps/ldtest-961e9308a2035796.16lmxsyeg832u97f.rcgu.o" "/home/kevin/prog/rust/ldtest/target/debug/deps/ldtest-961e9308a2035796.4m17l7xcbg989cwr.rcgu.o" "/home/kevin/prog/rust/ldtest/target/debug/deps/ldtest-961e9308a2035796.4nmemx29kp8fqedz.rcgu.o" "/home/kevin/prog/rust/ldtest/target/debug/deps/ldtest-961e9308a2035796.4ubsw870xaod9eey.rcgu.o" "/home/kevin/prog/rust/ldtest/target/debug/deps/ldtest-961e9308a2035796.5dxfasi0dqx5lzfo.rcgu.o" "/home/kevin/prog/rust/ldtest/target/debug/deps/ldtest-961e9308a2035796.2kns0bemnc80b4yo.rcgu.o" "-Wl,--as-needed" "-L" "/home/kevin/prog/rust/ldtest/target/debug/deps" "-L" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-4b09079a7bab0bca.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-bb8ecf2d12ff34d8.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-ee4cb885c61af390.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libmemchr-85f0b39601e84cf1.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-bb2ae63087325cc4.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-937f9fa236f59f7a.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-b76d0b892f101097.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-a04902bd34b34b51.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-806d1d695746defd.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-4ffcab78590ac59a.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-90ca7ec42e1a96c1.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-c3087aeb03eb9272.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-d640894e8a5f43af.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-d2878f15527c694a.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-d8ed80f6feadedd9.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-967646bb1cd56baf.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-ec55025f042d85cd.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-93d94d809edf4095.rlib" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-f99f4eaa4a87789a.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "/home/kevin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/kevin/prog/rust/ldtest/target/debug/deps/ldtest-961e9308a2035796" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro,-znow" "-nodefaultlibs"
  = note: collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped
          compilation terminated.
          

warning: `ldtest` (bin "ldtest") generated 1 warning
error: could not compile `ldtest` due to previous error; 1 warning emitted

This works fine though in C:

#include <stdio.h>

extern char __GNU_EH_FRAME_HDR;

int main() {
    printf("hdr = %p\n", &__GNU_EH_FRAME_HDR);

    return 0;
}
$ rustc -V
rustc 1.68.1 (8460ca823 2023-03-20)
$ cargo -V
cargo 1.68.1 (115f34552 2023-02-26)
$ ld -v
GNU ld (GNU Binutils) 2.40
$ uname -a
Linux kevin-desktop 6.2.7-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 18 Mar 2023 01:06:36 +0000 x86_64 GNU/Linux

I don't know how to diagnose the issue, nor how to workaround it. My goal is to retrieve the virtual address of the .eh_frame_hdr section.

EDIT: Here is a stacktrace I was able to get through gdb:

Thread 4.1 "ld" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff7adb740 (LWP 694725)]
bfd_getl32 (p=0x556d56ccfbe8) at /usr/src/debug/binutils/binutils-gdb/bfd/libbfd.c:731
Downloading source file /usr/src/debug/binutils/binutils-gdb/bfd/libbfd.c
731       return v;                                                                                                                                                        
(gdb) bt
#0  bfd_getl32 (p=0x556d56ccfbe8) at /usr/src/debug/binutils/binutils-gdb/bfd/libbfd.c:731
#1  0x00007ffff7e730f4 in bfd_elf64_swap_symbol_in (abfd=0x5555556990f0, psrc=0x556d56ccfbe8, pshn=0x0, dst=0x7fffffffbe60)
    at /usr/src/debug/binutils/binutils-gdb/bfd/elfcode.h:183
#2  0x00007ffff7e64bea in elf_x86_64_reloc_type_class (info=<optimized out>, rel_sec=<optimized out>, rela=0x555556d21168)
    at /usr/src/debug/binutils/binutils-gdb/bfd/elf64-x86-64.c:4737
#3  0x00007ffff7f2adf5 in elf_link_sort_relocs.constprop.0 (abfd=abfd@entry=0x5555556990f0, info=info@entry=0x555555675c00 <link_info>, psec=psec@entry=0x7fffffffc090)
    at /usr/src/debug/binutils/binutils-gdb/bfd/elflink.c:9884
#4  0x00007ffff7eb18b2 in bfd_elf_final_link (abfd=<optimized out>, info=<optimized out>) at /usr/src/debug/binutils/binutils-gdb/bfd/elflink.c:13108
#5  0x0000555555598aab in ldwrite () at /usr/src/debug/binutils/binutils-gdb/ld/ldwrite.c:545
#6  main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/binutils/binutils-gdb/ld/ldmain.c:524

Thank you for your help.

I found a workaround by defining another symbol as a copy:

// build.rs
fn main() {
    println!("cargo:rustc-link-arg=-Wl,--defsym,GNU_EH_FRAME_HDR=__GNU_EH_FRAME_HDR");
}

and linking with GNU_EH_FRAME_HDR instead.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.