static binary, dlopen, and ifunc
Samuel Thibault
samuel.thibault@gnu.org
Fri Nov 13 00:00:51 GMT 2020
Hello,
I'm having an issue on GNU/Hurd with ifunc when a static binary dlopens
modules (in the inet/tst-idna_name_classify test, more precisely). The
backtrace is as the following:
Program terminated with signal SIGSEGV, Segmentation fault.
27 static inline void *
28 IFUNC_SELECTOR (void)
29 {
30 const struct cpu_features* cpu_features = __get_cpu_features ();
31
>>> 32 if (CPU_FEATURE_USABLE_P (cpu_features, SSE2)
33 && CPU_FEATURES_ARCH_P (cpu_features, Fast_Rep_String))
34 return OPTIMIZE (sse2);
35
36 if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3))
#0 0x0111f610 in stpncpy_ifunc_selector () at ../sysdeps/i386/i686/multiarch/ifunc-sse2-ssse3.h:32
#1 __stpncpy_ifunc () at ../sysdeps/i386/i686/multiarch/stpncpy.c:31
#2 0x080c7fd5 in elf_machine_rel (skip_ifunc=<optimized out>, reloc_addr_arg=<optimized out>, version=<optimized out>, sym=0x132418c, reloc=0x1326898, map=<optimized out>) at ../sysdeps/i386/dl-machine.h:352
#3 elf_dynamic_do_Rel (skip_ifunc=<optimized out>, lazy=<optimized out>, nrelative=<optimized out>, relsize=<optimized out>, reladdr=<optimized out>, map=<optimized out>) at do-rel.h:137
#4 _dl_relocate_object (l=<optimized out>, scope=<optimized out>, reloc_mode=<optimized out>, consider_profiling=<optimized out>) at dl-reloc.c:274
#5 0x080e607e in dl_open_worker (a=0x1001808) at dl-open.c:700
#6 0x0808c8f5 in _dl_catch_exception (exception=0x10017fc, operate=0x80e5e30 <dl_open_worker>, args=0x1001808) at dl-error-skeleton.c:208
#7 0x080e5a95 in _dl_open (file=0x1001f878 "/usr/src/glibc-upstream/build/iconvdata/ISO8859-1.so", mode=-2147483646, caller_dlopen=0x80a6f75 <__gconv_find_shlib+101>, nsid=-2, argc=2, argv=0x1001dd4, env=0x1001de0) at dl-open.c:864
#8 0x080cb885 in do_dlopen (ptr=0x1001960) at dl-libc.c:96
#9 0x0808c8f5 in _dl_catch_exception (exception=0x10018f4, operate=0x80cb850 <do_dlopen>, args=0x1001960) at dl-error-skeleton.c:208
#10 0x0808c985 in _dl_catch_error (objname=0x1001948, errstring=0x100194c, mallocedp=0x1001947, operate=0x80cb850 <do_dlopen>, args=0x1001960) at dl-error-skeleton.c:227
#11 0x080cb8bd in dlerror_run (operate=<optimized out>, args=<optimized out>) at dl-libc.c:46
#12 0x080cbc64 in __libc_dlopen_mode (name=0x1001f878 "/usr/src/glibc-upstream/build/iconvdata/ISO8859-1.so", mode=-2147483646) at dl-libc.c:197
#13 0x080a6f75 in __gconv_find_shlib (name=<optimized out>) at gconv_dl.c:115
#14 0x0809e29c in gen_steps (toset=0x8121930 "INTERNAL", nsteps=0x1001b58, handle=0x1001b5c, fromset=<optimized out>, best=<optimized out>) at gconv_db.c:287
#15 find_derivation (toset=toset@entry=0x8121930 "INTERNAL", toset_expand=0x0, fromset=fromset@entry=0x1001b10 "ISO-8859-1//", fromset_expand=<optimized out>, handle=0x1001b5c, nsteps=0x1001b58) at gconv_db.c:672
#16 0x0809e89c in __gconv_find_transform (toset=0x8121930 "INTERNAL", fromset=0x1001b10 "ISO-8859-1//", handle=0x1001b5c, nsteps=0x1001b58, flags=0) at gconv_db.c:767
#17 0x0807b8a4 in __wcsmbs_getfct (nstepsp=0x10003134, from=0x1001b10 "ISO-8859-1//", to=0x8121930 "INTERNAL") at wcsmbsload.c:186
#18 __wcsmbs_load_conv (new_category=<optimized out>) at wcsmbsload.c:186
#19 0x080bc817 in get_gconv_fcts (data=0x10001570) at ./wcsmbsload.h:74
#20 __mbrtowc (pwc=0x1001c14 L"", s=<optimized out>, n=<optimized out>, ps=0x1001c18) at mbrtowc.c:70
#21 0x0808a052 in __idna_name_classify (name=0x813038d <support_install_prefix> "") at idna_name_classify.c:37
#22 0x080488bb in locale_insensitive_tests () at tst-idna_name_classify.c:27
#23 0x08048b85 in do_test () at tst-idna_name_classify.c:49
#24 0x08049a9a in support_test_main (argc=1, argv=0x1001dd8, config=0x1001ce4) at support_test_main.c:402
#25 0x080486b2 in main (argc=2, argv=0x1001dd4) at ../support/test-driver.c:168
and more precisely:
(gdb) disassemble
Dump of assembler code for function __stpncpy_ifunc:
0x0111f600 <+0>: call 0x1218dab <__x86.get_pc_thunk.ax>
0x0111f605 <+5>: add $0x1bb9fb,%eax
(R_386_GOTPC _GLOBAL_OFFSET_TABLE_)
0x0111f60a <+10>: mov -0x148(%eax),%ecx
(R_386_GOT32X _rtld_global_ro)
=> 0x0111f610 <+16>: testb $0x4,0x7b(%ecx)
[...]
(gdb) p/x $ecx
$3 = 0x0
i.e. _rtld_global_ro is NULL (!?)
Also,
(gdb) info sharedlibrary
From To Syms Read Shared Object Library
0x0105d430 0x0105e254 Yes /usr/src/glibc-upstream/build/iconvdata/ISO8859-1.so
0x010812c0 0x012421e6 Yes /usr/src/glibc-upstream/build/libc.so.0.3
0x012e20f0 0x01304753 Yes /usr/src/glibc-upstream/build/elf/ld.so.1
0x01318990 0x01324a74 Yes /usr/src/glibc-upstream/build/mach/libmachuser.so.1
0x013356a0 0x01352684 Yes /usr/src/glibc-upstream/build/hurd/libhurduser.so.0.3
So we have the static binary loaded around 0x080486b2 with its
own static libc, and the dynamic libraries getting loaded around
0x01[0-3]00000. AIUI it's supposed to be supported, but it seems somehow
_rtld_global_ro is not getting relocated, or relocated too late (?)
compared to the elf_machine_rel call that calls the ifunc selectors for
stpncpy? Is there something somewhere that makes sure that symbols are
getting relocated in the proper order or is it working on Linux just by
luck? Perhaps a missing flag in the GNU/Hurd target host?
It happens that the output of the program is
info: C locale tests
info: en_US.ISO-8859-1 locale tests
tst-idna_name_classify: Relink `/usr/src/glibc-upstream/build/mach/libmachuser.so.1' with `/usr/src/glibc-upstream/build/libc.so.0.3' for IFUNC symbol `__stpncpy'
Segmentation fault
Is that perhaps what triggers the ifunc selection unexpectedly early?
I'm not sure what should be done about this warning actually, since
libmachuser.so was really linked after libc.so:
-rwxr-xr-x 1 samy samy 14511352 2020-11-12 00:59:09.000000000 +0000 libc.so
-rwxr-xr-x 1 samy samy 514352 2020-11-12 00:59:36.000000000 +0000 mach/libmachuser.so
lrwxr-xr-x 1 samy samy 14 2020-11-12 00:59:36.000000000 +0000 mach/libmachuser.so.1 -> libmachuser.so
And yes it has "NEEDED libc.so.0.3", and the link command does explicit
that libc.so, not the system's:
gcc -shared -static-libgcc -Wl,-O1 -Wl,-z,defs -Wl,-dynamic-linker=/lib/i386-gnu/ld.so.1 -B/usr/src/glibc-upstream/build/csu/ -Wl,-soname=libmachuser.so.1 -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -L/usr/src/glibc-upstream/build -L/usr/src/glibc-upstream/build/math -L/usr/src/glibc-upstream/build/elf -L/usr/src/glibc-upstream/build/dlfcn -L/usr/src/glibc-upstream/build/nss -L/usr/src/glibc-upstream/build/nis -L/usr/src/glibc-upstream/build/rt -L/usr/src/glibc-upstream/build/resolv -L/usr/src/glibc-upstream/build/mathvec -L/usr/src/glibc-upstream/build/support -L/usr/src/glibc-upstream/build/crypt -L/usr/src/glibc-upstream/build/htl -L/usr/src/glibc-upstream/build/mach -L/usr/src/glibc-upstream/build/hurd -Wl,-rpath-link=/usr/src/glibc-upstream/build:/usr/src/glibc-upstream/build/math:/usr/src/glibc-upstream/build/elf:/usr/src/glibc-upstream/build/dlfcn:/usr/src/glibc-upstream/build/nss:/usr/src/glibc-upstream/build/nis:/usr/src/glibc-upstream/build/rt:/usr/src/glibc-upstream/build/resolv:/usr/src/glibc-upstream/build/mathvec:/usr/src/glibc-upstream/build/support:/usr/src/glibc-upstream/build/crypt:/usr/src/glibc-upstream/build/htl:/usr/src/glibc-upstream/build/mach:/usr/src/glibc-upstream/build/hurd -o /usr/src/glibc-upstream/build/mach/libmachuser.so /usr/src/glibc-upstream/build/csu/abi-note.o -Wl,--whole-archive /usr/src/glibc-upstream/build/mach/libmachuser_pic.a -Wl,--no-whole-archive -Wl,--start-group /usr/src/glibc-upstream/build/libc.so /usr/src/glibc-upstream/build/libc_nonshared.a -Wl,--as-needed /usr/src/glibc-upstream/build/elf/ld.so -Wl,--no-as-needed -Wl,--end-group
The binaries show
€ objdump -T -R mach/libmachuser.so | grep stpncpy
00000000 F *UND* 00000000 __stpncpy@@GLIBC_2.2.6
00000000 DF *UND* 00000000 GLIBC_2.2.6 __stpncpy
00017020 R_386_JUMP_SLOT __stpncpy@GLIBC_2.2.6
€ objdump -x -T -R libc.so | grep stpncpy
00000000 l df *ABS* 00000000 stpncpy.c
000be600 l F .text 0000003b __stpncpy_ifunc
00000000 l df *ABS* 00000000 stpncpy_chk.c
000ceec0 l F .text 000010e6 __stpncpy_sse2
000d78e0 l F .text 00000091 __GI___stpncpy
000ca620 l F .text 00002c6f __stpncpy_ssse3
000d78e0 l F .text 00000091 __stpncpy_ia32
000be600 g i .text 0000003b __stpncpy
000be600 w i .text 0000003b stpncpy
0018cf40 g F .text 00000035 __stpncpy_chk
000be600 w iD .text 0000003b GLIBC_2.2.6 stpncpy
000be600 g iD .text 0000003b GLIBC_2.2.6 __stpncpy
0018cf40 g DF .text 00000035 GLIBC_2.4 __stpncpy_chk
Any further idea what oddity I should look for?
Samuel
More information about the Libc-alpha
mailing list