On i686, the following steps show that ld.so --library-path doesn't always work: 1. Checkout release/2.26/master and build glibc for i686. 2. Checkout release/2.25/master and configure glibc for i686 with --prefix=/usr --without-cvs --without-selinux --target=i686-linux --build=i686-linux --host=i686-linux --enable-check-abi --enable-hardcoded-path-in-tests "--enable-hardcoded-path-in-tests" is the key. 3. Build glibc 2.25 and run "make check". 4. Run test binaries in glibc 2.25 with ld.so from glibc 2.26: (gdb) r --library-path /export/build/gnu/glibc-32bit-test-2/build-i686-linux:/export/build/gnu/glibc-32bit-test-2/build-i686-linux/nptl:. /export/build/gnu/glibc-32bit-test/build-i686-linux/string/tst-strlen Starting program: /export/build/gnu/glibc-32bit-test-2/build-i686-linux/elf/ld-linux.so.2 --library-path /export/build/gnu/glibc-32bit-test-2/build-i686-linux:/export/build/gnu/glibc-32bit-test-2/build-i686-linux/nptl:. /export/build/gnu/glibc-32bit-test/build-i686-linux/string/tst-strlen Program received signal SIGSEGV, Segmentation fault. 0xffffffff in ?? () (gdb) bt #0 0xffffffff in ?? () #1 0xf7f37dda in _dl_vdso_vsym ( name=name@entry=0xf7f74762 "__vdso_clock_gettime", vers=vers@entry=0xffffcf50) at ../sysdeps/unix/sysv/linux/dl-vdso.c:40 #2 0xf7e2e2fc in __vdso_platform_setup () at ../sysdeps/unix/sysv/linux/i386/init-first.c:40 #3 _init (argc=1, argv=0xffffd010, envp=0xffffd018) at ../csu/init-first.c:81 #4 0xf7fe67bd in call_init (l=0xf7fd0de0, argc=argc@entry=1, argv=argv@entry=0xffffd010, env=0xffffd018) at dl-init.c:58 #5 0xf7fe6907 in call_init (env=0xffffd018, argv=0xffffd010, argc=1, l=<optimized out>) at dl-init.c:30 #6 _dl_init (main_map=<optimized out>, argc=1, argv=0xffffd010, env=0xffffd018) at dl-init.c:120 #7 0xf7fd7b5f in _dl_start_user () from /export/build/gnu/glibc-32bit-test-2/build-i686-linux/elf/ld-linux.so.2 (gdb) r --library-path /export/build/gnu/glibc-32bit-test-2/build-i686-linux:/export/build/gnu/glibc-32bit-test-2/build-i686-linux/nptl:. /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/sprof The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /export/build/gnu/glibc-32bit-test-2/build-i686-linux/elf/ld-linux.so.2 --library-path /export/build/gnu/glibc-32bit-test-2/build-i686-linux:/export/build/gnu/glibc-32bit-test-2/build-i686-linux/nptl:. /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/sprof Try `sprof --help' or `sprof --usage' for more information. [Inferior 1 (process 221985) exited with code 01] Missing separate debuginfos, use: dnf debuginfo-install glibc-2.26-25.0.fc27.i686 (gdb) The differences are [hjl@gnu-skx-1 glibc]$ readelf -l /export/build/gnu/glibc-32bit-test/build-i686linux/elf/sprof Elf file type is EXEC (Executable file) Entry point 0x8049f02 There are 9 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R 0x4 INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x04070 0x04070 R E 0x1000 LOAD 0x004ef4 0x0804def4 0x0804def4 0x00204 0x002a0 RW 0x1000 DYNAMIC 0x004f04 0x0804df04 0x0804df04 0x000f8 0x000f8 RW 0x4 NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4 GNU_EH_FRAME 0x003cdc 0x0804bcdc 0x0804bcdc 0x0008c 0x0008c R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 GNU_RELRO 0x004ef4 0x0804def4 0x0804def4 0x0010c 0x0010c R 0x1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .data.rel.ro .dynamic .got [hjl@gnu-skx-1 glibc]$ readelf -l /export/build/gnu/glibc-32bit-test/build-i686-linux/string/tst-strlen Elf file type is EXEC (Executable file) Entry point 0x8048efe There are 9 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R 0x4 INTERP 0x000154 0x08048154 0x08048154 0x0003e 0x0003e R 0x1 [Requesting program interpreter: /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so] LOAD 0x000000 0x08048000 0x08048000 0x027d0 0x027d0 R E 0x1000 LOAD 0x002e98 0x0804be98 0x0804be98 0x001f0 0x00208 RW 0x1000 DYNAMIC 0x002ee0 0x0804bee0 0x0804bee0 0x000f8 0x000f8 RW 0x4 NOTE 0x000194 0x08048194 0x08048194 0x00044 0x00044 R 0x4 GNU_EH_FRAME 0x0021ac 0x0804a1ac 0x0804a1ac 0x0005c 0x0005c R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 GNU_RELRO 0x002e98 0x0804be98 0x0804be98 0x00168 0x00168 R 0x1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .data.rel.ro .dynamic .got [hjl@gnu-skx-1 glibc]$ /export/build/gnu/glibc-32bit-test/build-i686-linux/string/tst-strlen [hjl@gnu-skx-1 glibc]$
If you use --enable-hardcoded-path-in-tests the tests are built with -Wl,-rpath and this embeds the library search path into DT_RPATH/DT_RUNPATH, both of which take precedence over ld.so's --library-path which is equivalent to setting LD_LIBRARY_PATH IIRC. To prove this you could try using LD_PRELOAD to preload the required libraries and that would certainly force them to be loaded before DT_RPATH/DT_RUNPATH. Therefore I don't think there is a bug here. (a) ld.so --library-path is equivalent to LD_LIBRARY_PATH. (b) If you use DT_RPATH/DT_RUNPATH in a binary, like is done with --enable-hardcoded-path-in-tests, you must use LD_PRELOAD to get a different set of loaded libraries that match the ld.so you're using to run the test. Does that make sense?
Only DT_RPATH should take precedence over LD_LIBRARY_PATH, not DT_RUNPATH. (So unless --enable-hardcoded-path-in-tests is made to use --enable-new-dtags, and I don't know if that would be a good idea or not[*], it's incompatible with running an old glibc's test binaries against a new glibc - and if that change were made, of course it would only help if the old glibc postdated that change.) [*] I don't know if any tests, using --enable-hardcoded-path-in-tests, rely on the executable's RPATH being used to find indirect shared library dependencies, which only works with RPATH not RUNPATH.
--enable-hardcoded-path-in-tests doesn't change the behavior of ld.so on x86-64. Only i686 has this issue. This may be related to: INTERP 0x000154 0x08048154 0x08048154 0x0003e 0x0003e R 0x1 [Requesting program interpreter: /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so]
(In reply to H.J. Lu from comment #3) > --enable-hardcoded-path-in-tests doesn't change the behavior of ld.so > on x86-64. Only i686 has this issue. This may be related to: > > INTERP 0x000154 0x08048154 0x08048154 0x0003e 0x0003e R 0x1 > [Requesting program interpreter: > /export/build/gnu/glibc-32bit-test/build-i686-linux/elf/ld.so] I think this is an x86_64 bug. Using --enable-hardcoded-paths-in-tests sets PT_INTERP to the newly built ld.so and DT_RPATH to the library paths. IMO these *should* override --library-paths, which should behave as LD_LIBRARY_PATH.
x86-64 also crashes. DT_RPATH overrides --library-path. ld.so already overrides DT_INTERP. Shouldn't ld.so --library-path prepend DT_RPATH?
(In reply to H.J. Lu from comment #5) > x86-64 also crashes. DT_RPATH overrides --library-path. ld.so already > overrides DT_INTERP. Shouldn't ld.so --library-path prepend DT_RPATH? No. --library-path should behave like LD_LIBRARY_PATH IMO. We could add a new option to override DT_RPATH, or DT_RUNPATH.