hi i want to report glibc issue when i use llvm, the following is detail: when clang build golang on x86 arch, and use cgo function, build to static linked exec, exec will segment fault. this is demo.go: package main // #cgo LDFLAGS: -ldl // #include <stdlib.h> // #include <dlfcn.h> import "C" import ( "fmt" ) func main() { fmt.Printf("This is go demo\n") C.CString("libsystemd-login.so.0") return } build static exec command : export CC=clang CGO_ENABLED=1 CGO_CFLAGS="-fstack-protector-strong -fPIE" CGO_CPPFLAGS="-fstack-protector-strong -fPIE" CGO_LDFLAGS_ALLOW='-Wl,-z,relro,-z,now' CGO_LDFLAGS="-Wl,-z,relro,-z,now -Wl,-z,noexecstack" go build -buildmode=pie -o demo -ldflags '-buildid=none -tmpdir=. -extldflags=-ftrapv -extldflags=-Wl,-z,relro,-z,now -linkmode=external -extldflags=-static-pie' demo.go and gdb segment fault stack, indicate crash in glibc Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7e835dc in _dl_signal_error () (gdb) bt #0 0x00007ffff7e835dc in _dl_signal_error () #1 0x00007ffff7ebf6f3 in _dl_allocate_static_tls () #2 0x00007ffff7e843d0 in _dl_relocate_static_pie () #3 0x00007ffff7e46b59 in __libc_start_main_impl () #4 0x00007ffff7dc4665 in _start () when debug, i found clang change the sym relocate type from R_X86_64_GOTTPOFF to R_X86_64_TPOFF64 readelf -a glibc/dl-error.o | grep R_X86_64_GOTTPOFF readelf -a demo | grep R_X86_64_TPOFF64 i want to know why glibc does not match this relocation type. thank you
if go build doesnt use -static-pie, it runs success.
in glibc function _dl_relocate_static_pie(),it will check the tls size,but tls size has initialed yet related macro and function: CHECK_STATIC_TLS() init_tls_size()
Which linker are you using? It is possible that for static PIE, we assume that the link editor is able to fully relax TLS relocations, that is, compute fixed constants and put them into the data segment or directly into the code (after instruction relaxation).
(In reply to Florian Weimer from comment #3) > Which linker are you using? > > It is possible that for static PIE, we assume that the link editor is able > to fully relax TLS relocations, that is, compute fixed constants and put > them into the data segment or directly into the code (after instruction > relaxation). i use go build -x, it print the extld is clang, when i chang extld = gcc, it runs success. /usr/lib/golang/pkg/tool/linux_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -installsuffix shared -buildmode=pie -buildid=d4xaXJFWrXP2j7-zXtDh/3XIk6UDso2SczQsnY03H/wEC6IRgel1j8WkFVdesn/d4xaXJFWrXP2j7-zXtDh -buildid=none -tmpdir=. -extldflags=-ftrapv -extldflags=-Wl,-z,relro,-z,now -linkmode=external -extldflags=-static-pie -extld=clang /root/.cache/go-build/39/399acc4b7bd65f1480c7c9fa0834a2240dfb9d7dc277b62a787491dbd1b64ed3-d
(In reply to Florian Weimer from comment #3) > Which linker are you using? > > It is possible that for static PIE, we assume that the link editor is able > to fully relax TLS relocations, that is, compute fixed constants and put > them into the data segment or directly into the code (after instruction > relaxation). and it show some dlerror.o function .rela.dyn section sym relocate type cause the problem. not the constant Relocation section '.rela.dyn' at offset 0x85e0 contains 13252 entries: 00000023df28 010b00000012 R_X86_64_TPOFF64 0000000000000078 __libc_dlerror_result + 0 00000023df70 011100000012 R_X86_64_TPOFF64 0000000000000058 __libc_tsd_CTYPE_[...] + 0 00000023dfc0 025700000012 R_X86_64_TPOFF64 0000000000000068 __libc_tsd_CTYPE_B + 0 00000023dfc8 002400000012 R_X86_64_TPOFF64 0000000000000018 __libc_tsd_LOCALE + 0 00000023dfe0 023b00000012 R_X86_64_TPOFF64 0000000000000060 __libc_tsd_CTYPE_[...] + 0
(In reply to luofeng14 from comment #5) > (In reply to Florian Weimer from comment #3) > > Which linker are you using? > > > > It is possible that for static PIE, we assume that the link editor is able > > to fully relax TLS relocations, that is, compute fixed constants and put > > them into the data segment or directly into the code (after instruction > > relaxation). > > and it show some dlerror.o function .rela.dyn section sym relocate type > cause the problem. not the constant > > Relocation section '.rela.dyn' at offset 0x85e0 contains 13252 entries: > 00000023df28 010b00000012 R_X86_64_TPOFF64 0000000000000078 > __libc_dlerror_result + 0 > 00000023df70 011100000012 R_X86_64_TPOFF64 0000000000000058 > __libc_tsd_CTYPE_[...] + 0 > 00000023dfc0 025700000012 R_X86_64_TPOFF64 0000000000000068 > __libc_tsd_CTYPE_B + 0 > 00000023dfc8 002400000012 R_X86_64_TPOFF64 0000000000000018 > __libc_tsd_LOCALE + 0 > 00000023dfe0 023b00000012 R_X86_64_TPOFF64 0000000000000060 > __libc_tsd_CTYPE_[...] + 0 sorry, ____libc_dlerror_result is var not function; thread struct dl_action_result *__libc_dlerror_result
(In reply to luofeng14 from comment #6) > (In reply to luofeng14 from comment #5) > > (In reply to Florian Weimer from comment #3) > > > Which linker are you using? > > > > > > It is possible that for static PIE, we assume that the link editor is able > > > to fully relax TLS relocations, that is, compute fixed constants and put > > > them into the data segment or directly into the code (after instruction > > > relaxation). > > > > and it show some dlerror.o function .rela.dyn section sym relocate type > > cause the problem. not the constant > > > > Relocation section '.rela.dyn' at offset 0x85e0 contains 13252 entries: > > 00000023df28 010b00000012 R_X86_64_TPOFF64 0000000000000078 > > __libc_dlerror_result + 0 > > 00000023df70 011100000012 R_X86_64_TPOFF64 0000000000000058 > > __libc_tsd_CTYPE_[...] + 0 > > 00000023dfc0 025700000012 R_X86_64_TPOFF64 0000000000000068 > > __libc_tsd_CTYPE_B + 0 > > 00000023dfc8 002400000012 R_X86_64_TPOFF64 0000000000000018 > > __libc_tsd_LOCALE + 0 > > 00000023dfe0 023b00000012 R_X86_64_TPOFF64 0000000000000060 > > __libc_tsd_CTYPE_[...] + 0 > > > sorry, ____libc_dlerror_result is var not function; > > thread struct dl_action_result *__libc_dlerror_result (In reply to luofeng14 from comment #6) > (In reply to luofeng14 from comment #5) > > (In reply to Florian Weimer from comment #3) > > > Which linker are you using? > > > > > > It is possible that for static PIE, we assume that the link editor is able > > > to fully relax TLS relocations, that is, compute fixed constants and put > > > them into the data segment or directly into the code (after instruction > > > relaxation). > > > > and it show some dlerror.o function .rela.dyn section sym relocate type > > cause the problem. not the constant > > > > Relocation section '.rela.dyn' at offset 0x85e0 contains 13252 entries: > > 00000023df28 010b00000012 R_X86_64_TPOFF64 0000000000000078 > > __libc_dlerror_result + 0 > > 00000023df70 011100000012 R_X86_64_TPOFF64 0000000000000058 > > __libc_tsd_CTYPE_[...] + 0 > > 00000023dfc0 025700000012 R_X86_64_TPOFF64 0000000000000068 > > __libc_tsd_CTYPE_B + 0 > > 00000023dfc8 002400000012 R_X86_64_TPOFF64 0000000000000018 > > __libc_tsd_LOCALE + 0 > > 00000023dfe0 023b00000012 R_X86_64_TPOFF64 0000000000000060 > > __libc_tsd_CTYPE_[...] + 0 > > > sorry, ____libc_dlerror_result is var not function; > > thread struct dl_action_result *__libc_dlerror_result and __libc_dlerror_result is not constant glibc/glibc-2.34/dlfcn/dlerror.c 49,7: __libc_dlerror_result = NULL; 62,7: __libc_dlerror_result = NULL; 120,4: __libc_dlerror_result = NULL; 153,4: __libc_dlerror_result = NULL; 175,8: __libc_dlerror_result = dl_action_result_malloc_failed; 178,4: __libc_dlerror_result = result; glibc/glibc-2.34/dlfcn/libc_dlerror_result.c 37,7: __libc_dlerror_result = NULL;
What I meant with constant is that the offset from the thread pointer/%fs is constant for static PIE, and there is no need for a run-time relocation. This looks like a missed optimization in lld (if that's what clang is using).
this is glibc main function, the function init_static_tls is after the _dl_try_allocate_static_tls, this results in CHECK_STATIC_TLS failure,because dl_tls_static_size not initialled yet: LIBC_START_MAIN _dl_relocate_static_pie (); ELF_DYNAMIC_RELOCATE - ELF_DYNAMIC_DO_REL - _ELF_DYNAMIC_DO_RELOC - elf_dynamic_do_reloc # elf_dynamic_do_##reloc - elf_dynamic_do_Rela - elf_dynamic_do_Rel - elf_machine_rel - elf_machine_rela case R_X86_64_TPOFF64: CHECK_STATIC_TLS _dl_allocate_static_tls _dl_try_allocate_static_tls /* Perform IREL{,A} relocations. */ ARCH_SETUP_IREL (); /* The stack guard goes into the TCB, so initialize it early. */ ARCH_SETUP_TLS (); x86_setup_tls # define ARCH_SETUP_TLS() x86_setup_tls __libc_setup_tls init_static_tls
There should not be any R_X86_64_TPOFF64 relocations left in static PIE because the link editor can fully resolve them. This is an lld bug.
(In reply to Florian Weimer from comment #10) > There should not be any R_X86_64_TPOFF64 relocations left in static PIE > because the link editor can fully resolve them. This is an lld bug. sorry, i'm not familiar with relocation type. i would like to ask in which case R_X86_64_TPOFF64 relocation type would be used.
Not glibc issue. lld 18 supports R_X86_64_TPOFF64 https://github.com/llvm/llvm-project/issues/85349