Bug 31302 - glibc issue about reloc-type R_X86_64_TPOFF64 when llvm build golang project with cgo
Summary: glibc issue about reloc-type R_X86_64_TPOFF64 when llvm build golang project ...
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.38
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-01-28 00:45 UTC by luofeng14
Modified: 2024-03-15 21:04 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description luofeng14 2024-01-28 00:45:35 UTC
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
Comment 1 luofeng14 2024-01-28 00:51:25 UTC
if go build doesnt use -static-pie, it runs success.
Comment 2 luofeng14 2024-01-28 01:23:38 UTC
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()
Comment 3 Florian Weimer 2024-01-28 19:30:35 UTC
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).
Comment 4 luofeng14 2024-01-29 01:16:37 UTC
(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
Comment 5 luofeng14 2024-01-29 01:23:56 UTC
(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
Comment 6 luofeng14 2024-01-29 01:33:14 UTC
(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
Comment 7 luofeng14 2024-01-29 01:39:16 UTC
(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;
Comment 8 Florian Weimer 2024-01-29 05:50:26 UTC
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).
Comment 9 luofeng14 2024-01-29 11:41:11 UTC
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
Comment 10 Florian Weimer 2024-01-29 11:43:38 UTC
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.
Comment 11 luofeng14 2024-01-30 01:05:56 UTC
(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.
Comment 12 Fangrui Song 2024-03-15 21:04:54 UTC
Not glibc issue.

lld 18 supports R_X86_64_TPOFF64
https://github.com/llvm/llvm-project/issues/85349