https://sourceware.org/bugzilla/show_bug.cgi?id=19249
Bug ID: 19249 Summary: ld.so not properly linked in with ld --no-allow-shlib-undefined Product: binutils Version: unspecified Status: NEW Severity: normal Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: pjones at redhat dot com Target Milestone: --- Some time ago I decided to try to enforce some hygiene on one of the libraries I maintain, and started linking it with -Wl,--fatal-warnings,--no-allow-shlib-undefined . Then yesterday I tried to build this tree on an aarch64 machine, and I got this error while building a .so: gcc -O2 -g -Werror -Wall -Wsign-compare -Wstrict-aliasing -std=gnu11 \ -fshort-wchar -fPIC -flto -fvisibility=hidden -D_GNU_SOURCE \ -I/root/efivar/src/include/efivar/ -Wmaybe-uninitialized \ -fno-merge-constants \ -Wl,--fatal-warnings,--no-allow-shlib-undefined,--default-symver \ -Wl,-O2 -Wl,--no-undefined-version -shared \ -Wl,-soname,libefivar.so.0 \ -o libefivar.so dp.o dp-acpi.o dp-hw.o dp-media.o dp-message.o \ efivarfs.o export.o guid.o guids.o guid-symbols.o lib.o vars.o \ -ldl /lib64/libc.so.6: undefined reference to `_dl_argv@GLIBC_PRIVATE' /lib64/libc.so.6: undefined reference to `__libc_enable_secure@GLIBC_PRIVATE' /lib64/libc.so.6: undefined reference to `__pointer_chk_guard@GLIBC_PRIVATE' /lib64/libc.so.6: undefined reference to `__tls_get_addr@GLIBC_2.17' /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/libdl.so: undefined reference to `_dl_rtld_di_serinfo@GLIBC_PRIVATE' /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/libdl.so: undefined reference to `_rtld_global@GLIBC_PRIVATE' /usr/lib/gcc/aarch64-redhat-linux/4.8.5/../../../../lib64/libdl.so: undefined reference to `_rtld_global_ro@GLIBC_PRIVATE' collect2: error: ld returned 1 exit status Now, I'm not using those symbols directly, but I am using dlopen()/dlsym()/dlclose(), and no other libraries. To me it looks like a couple of things are happening - one is that --no-allow-shlib-undefined is being applied to all the symbols in the link map, rather than just the symbols going in to the target. That's a bit unexpected, but not normally insurmountable. But the other thing, I eventually traced down to this: [root@pjones2 ~]# for x in /usr/lib/debug/lib64/*.so.debug ; do \ echo -n "${x}: " ; grep -c _dl_argv ${x} ; done /usr/lib/debug/lib64/ld-2.17.so.debug: 3 /usr/lib/debug/lib64/libBrokenLocale-2.17.so.debug: 0 /usr/lib/debug/lib64/libSegFault.so.debug: 0 /usr/lib/debug/lib64/libanl-2.17.so.debug: 0 /usr/lib/debug/lib64/libc-2.17.so.debug: 2 /usr/lib/debug/lib64/libcidn-2.17.so.debug: 0 /usr/lib/debug/lib64/libcrypt-2.17.so.debug: 0 /usr/lib/debug/lib64/libdl-2.17.so.debug: 0 /usr/lib/debug/lib64/libm-2.17.so.debug: 0 /usr/lib/debug/lib64/libnsl-2.17.so.debug: 0 /usr/lib/debug/lib64/libnss_compat-2.17.so.debug: 0 /usr/lib/debug/lib64/libnss_db-2.17.so.debug: 0 /usr/lib/debug/lib64/libnss_dns-2.17.so.debug: 0 /usr/lib/debug/lib64/libnss_files-2.17.so.debug: 0 /usr/lib/debug/lib64/libnss_hesiod-2.17.so.debug: 0 /usr/lib/debug/lib64/libnss_nis-2.17.so.debug: 0 /usr/lib/debug/lib64/libnss_nisplus-2.17.so.debug: 0 /usr/lib/debug/lib64/libpthread-2.17.so.debug: 0 /usr/lib/debug/lib64/libresolv-2.17.so.debug: 0 /usr/lib/debug/lib64/librt-2.17.so.debug: 0 /usr/lib/debug/lib64/libthread_db-1.0.so.debug: 0 /usr/lib/debug/lib64/libutil-2.17.so.debug: 0 [root@pjones2 ~]# nm /usr/lib/debug/lib64/ld-2.17.so.debug | grep _dl_argv 0000000000031060 B _dl_argv 0000000000031060 b _dl_argv_internal [root@pjones2 ~]# nm /usr/lib/debug/lib64/libc-2.17.so.debug | grep _dl_argv U _dl_argv@@GLIBC_PRIVATE (The same basic outcome applies to e.g. __tls_get_addr as well.) So that, I assume, is because large amounts of libdl are really shared code from ld.so's version. If I add --add-needed, this all works - but I wouldn't think it would be necessary, since libc.so has "AS_NEEDED ( /lib/ld-linux-aarch64.so.1 )". So to me it looks like libdl gets those symbols from the dl implementation in ld.so, and libc.so tells it to add them automatically, but unless I manually specify --add-needed that doesn't happen. The result is that using --no-allow-shlib-undefined to guarantee hygiene in a DSO being built won't work unless you also use --add-needed, which doesn't seem right. If I use --add-needed, DT_NEEDED just winds up with: NEEDED Shared library: [libdl.so.2] NEEDED Shared library: [libc.so.6] which is the same thing it would be without -Wl,--add-needed,--no-allow-shlib-undefined Somewhat confusingly, if I add /lib/ld-linux-aarch64.so.1 to my gcc command line it works fine (as you'd expect), but changing libdl.so to be: OUTPUT_FORMAT(elf64-littleaarch64) GROUP ( /lib64/libdl.so.2 AS_NEEDED ( /lib/ld-linux-aarch64.so.1 ) ) it doesn't help. Are the AS_NEEDED()'s there and in libc.so being ignored when --add-needed isn't there? Anyway - I can make it work, but I don't really like using --add-needed , and the result there isn't really obviously meaningful either. I asked Carlos O'Donell and Nick Clifton about this, and they said: > On Fri, Nov 13, 2015 at 01:26:16PM -0500, Carlos O'Donell wrote: >> On 11/13/2015 11:56 AM, Peter Jones wrote: >>> So that, I assume, is because large amounts of libdl are really shared >>> code from ld.so's version. If I add --add-needed, this all works - but I >>> wouldn't think it would be necessary, since libc.so has "AS_NEEDED ( >>> /lib/ld-linux-aarch64.so.1 )". >>> Your analysis is correct. I don't know why AS_NEEDED is not enough. >> >> In general ld.so is always treated as a "special case" and doesn't always >> filter well through the various options to the static linker. Similarly >> debugging ld.so is always a "special case", again, because it's not >> "normal" and gdb developers rarely debug it. >> >> I think you need to file a bug here because your use case is very sane >> and the behaviour is not sane and we should fix that. > > I would definitely recommend doing this. Although you found the problem on > RHEL, I suspect that it is generic (at least as far as the AArch64 is > concerned). So I would recommend filing a bug report with the FSF binutils > project here: > > https://sourceware.org/bugzilla/ > > It also helps that there are quite a few ARM engineers who examine these > bugs and take a special interest in AArch64 problems... So here I am, filing the bug. All that said, I'm not at all sure this is Aarch64-specific - it may well be that it's just the first platform on which I've hit the particular set of configuration defaults that leads to this. FYI, the versions of binutils and gcc in question: binutils-2.23.52.0.1-55.el7.aarch64 gcc-4.8.5-4.el7.aarch64 -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils