https://sourceware.org/bugzilla/show_bug.cgi?id=31395

--- Comment #2 from Brooks Davis <brooks at freebsd dot org> ---
(In reply to Nick Clifton from comment #1)
> (In reply to Brooks Davis from comment #0)
> Hi Brooks,

Thank your for your reply, sorry I didn't notice it when you made it.

> > 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 ?

Yes and no.  It should targeting an i386 system from an amd64 host where /lib,
/usr/lib, etc are for 64-bit things.

> > 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.

The system linker does however know that it is executing a 32-bit binary within
a mostly 64-bit userspace and adjusts paths accordingly.  It's a bit weird to
me that there's no communication of this between the compiler and linker.

> > 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.

I presume it doesn't set LD_LIBRARY_PATH as that could have surprising effects
on ld's operation.

Mostly as an aside: Somewhat to my surprise, it appears that lld does obey
LIBRARY_PATH with the comment: "LIBRARY_PATH are included before user inputs
and only supported on native toolchains."  Oddly clang doesn't seem to set it
and the commits I've looked at don't really explain why it's supported.  It's
quite surprising that lld appears to support a variable set by gcc, but not by
clang and not used by bfd ld.

> 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*)

I've confirmed that a slight variant works in the cases I'd ran into before:

--- ld/configure.tgt.orig       2024-07-18 19:15:53.355228000 +0100
+++ ld/configure.tgt    2024-07-18 19:17:43.053568000 +0100
@@ -1102,7 +1106,7 @@
   ;;

 *-*-freebsd*)
-  NATIVE_LIB_DIRS='/lib /usr/lib /usr/local/lib'
+  NATIVE_LIB_DIRS='/lib /usr/lib /usr/local/lib /usr/lib32'
   ;;

 hppa*64*-*-hpux11*)


I'm not sure this is the best approach, but it's easy and should be harmless.

> 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

With a patched linker I get:

SEARCH_DIR("=/usr/local/x86_64-unknown-freebsd14.0/lib"); SEARCH_DIR("=/lib");
SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/local/lib");
SEARCH_DIR("=/usr/lib32");

Thanks,
Brooks

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to