When invoked via gcc -m32 on a FreeBSD amd64 system, ld searches for DT_NEEDED libraries as though it were on an i386 system and thus fails to find them. (This is likely also true for aarch64 and powerpc64, but I have not verified this is the case.) I think there is a communication breakdown between gcc and ld that I'm hoping can be resolved in ld because we maintain a single binutils package and 9 modern-ish gcc packages. On FreeBSD we've recently added a libsys which contains system call implementations and is linked into libc and libthr/libpthread. This has caused problems when building 32-bit binaries on 64-bit systems using gcc -m32 because ld fails to find libsys.so.7 unless it is listed explicitly on the command line. Confusingly that is true even though gcc passes -L/usr/lib/../lib32 to ld. I belive this is due to this logic: https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/ldelf.c;h=04045acbf3dc56947edb15effff5818dd5b69fd9;hb=HEAD#l1091 Tracing of the gcc -m32 command performed by configure as part of a gcc12 multilib build confirms that ld tries a number of locations before failing to find libsys.so.7 and subsequently encountering unresolved symbols: ... 82890 ld NAMI "/usr/lib/libsys.so.7" 82890 ld NAMI "/usr/lib/compat/libsys.so.7" 82890 ld NAMI "/usr/local/lib/libsys.so.7" 82890 ld NAMI "/usr/local/lib/compat/pkg/libsys.so.7" 82890 ld NAMI "/usr/local/lib/perl5/5.36/mach/CORE/libsys.so.7" 82890 ld NAMI "/usr/local/i386-portbld-freebsd15.0/lib/libsys.so.7" 82890 ld NAMI "/lib/libsys.so.7" 82890 ld NAMI "/usr/lib/libsys.so.7" 82890 ld NAMI "/usr/local/lib/libsys.so.7" 82890 ld NAMI "/lib/libsys.so.7" 82890 ld NAMI "/usr/lib/libsys.so.7" 82890 ld NAMI "/usr/lib/compat/libsys.so.7" 82890 ld NAMI "/usr/local/lib/libsys.so.7" 82890 ld NAMI "/usr/local/lib/compat/pkg/libsys.so.7" 82890 ld NAMI "/usr/local/lib/perl5/5.36/mach/CORE/libsys.so.7" 82890 ld NAMI "/usr/local/i386-portbld-freebsd15.0/lib/libsys.so.7" 82890 ld NAMI "/lib/libsys.so.7" 82890 ld NAMI "/usr/lib/libsys.so.7" 82890 ld NAMI "/usr/local/lib/libsys.so.7" ... ("/lib/libsys.so.7" is found and opened, but presumably rejected due to the ABI mismatch.) Further tracing shows that gcc attempts to communicate the correct paths via a LIBRARY_PATH variable, but I don't think binutils looks for that at all: LIBRARY_PATH=/wrkdirs/usr/ports/lang/gcc12/work/.build/./gcc/32/:/usr/lib/../lib 32/:/wrkdirs/usr/ports/lang/gcc12/work/.build/./gcc/:/usr/local/x86_64-portbld-f reebsd15.0/bin/:/usr/local/x86_64-portbld-freebsd15.0/lib/:/lib/:/usr/lib/ (The presence of x86_64-portbld-freebsd15.0 suggests that gcc isn't getting this quite right either...) It seems like the current model is that ld knows nothing about -m32 which is fine to a point, but seems pretty broken here as at most one of the searched paths contain libaries of the wrong ABI. I don't know if ld should be honoring LIBRARY_PATH, searching /usr/lib32 unconditionally on 32-bit FreeBSD platforms, or something else? It's not really practical to add -lsys to the command line because that needs to happen places like inside gcc's multilib configure scripts that use the bootstrapped xgcc. I'm currently working around this issue by linking libc and libthr for 32-bit compat with --rpath=/usr/lib32, but this seems wrong as I'd ideally be able to use native i386 binaries to populate /usr/lib32.
(In reply to Brooks Davis from comment #0) Hi Brooks, > When invoked via gcc -m32 on a FreeBSD amd64 system, ld searches for > DT_NEEDED libraries as though it were on an i386 system and thus fails > to find them. Err, maybe I am misunderstanding this, but doesn't using -m32 imply that the linker should act as if it is building for an i386 system ? > Confusingly that is true even though > gcc passes -L/usr/lib/../lib32 to ld. I belive this is due to this > logic: > > https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/ldelf.c; > h=04045acbf3dc56947edb15effff5818dd5b69fd9;hb=HEAD#l1091 Which makes sense. That logic is duplicating how the system loader works, and since the system loader does not have access to the -L options generated by gcc, that code also ignores them. > Further tracing shows that gcc attempts to communicate the correct paths > via a LIBRARY_PATH variable, but I don't think binutils looks for that > at all: It doesn't - and nor does the system loader. But if gcc used LD_LIBRARY_PATH, that might work. Does FreeBSD support cross linking ? If not, then would a patch like this solve your problem: diff --git a/ld/configure.tgt b/ld/configure.tgt index f937f78b876..a68f2313850 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -1113,7 +1113,7 @@ case "${target}" in ;; *-*-freebsd*) - NATIVE_LIB_DIRS='/lib /usr/lib /usr/local/lib' + NATIVE_LIB_DIRS='/lib /usr/lib /usr/local/lib /lib/lib32' ;; hppa*64*-*-hpux11*) How is the linker configured ? In particular does it support the elf_i386_fsbd emulation ? If it does, what shows up the SEARCH_DIR entries for that emulation's built in script ? ie: ld -m elf_i386_bfd --verbose | grep SEARCH_DIR On my (cross-hosted) build I get: SEARCH_DIR("/usr/local/i386-pc-freebsd/lib32"); SEARCH_DIR("/usr/local/i386-pc-freebsd/lib"); Which implies to me that the linker already knows about the /lib32 directory, but since I am running a cross-hosted linker, it prepends /usr/local/i386-pc-freebsd/ to the path. Cheers Nick