ld could search 64-bit subdir for path specified with -L
Our multi-ISA support installs libraries using extended instruction sets alongside their basic 32-bit equivalents in subdirectories named after their ISA (see isalist(5)). This allows $ISALIST expansion in rtld (among other things), and is similar to isaexec(3C) for executables. This applies to 64-bit objects as well, which end up in amd64 or sparcv9 subdirectories (e.g. /usr/lib/amd64), sometimes with 64 as a symlink.
The default library search path for 64-bit ld is "/lib/64:/usr/lib/64" so the 64-bit copies of many system libraries are located transparently. However, libraries that require specifying search paths with -L and -R would produce a link error if the same paths were used for 32- and 64-bit builds, since those paths are used literally.
This usually means the person building the software has to explicitly specify the 64-bit subdirectories to locate those libraries, which is at best inconvenient. Many build systems exist which construct linker search paths automatically, and these are almost always incorrect for the 64-bit libraries (pkg-config helps somewhat, if the definitions from /usr/lib/64/pkgconfig are used, but even selecting that requires additional effort). These may be difficult to override, resulting in a considerable amount of trial and error to produce a working linker configuration.I can think of two approaches in the linker that may alleviate this:
- When linking a 64-bit object, always implicitly try search paths with "/64" (or an arch-specific path like "/amd64") appended to the searched directory, before trying the parent. This has a potential for unintended side effects, although I don't believe it should cause problems in reality.
- When linking a 64-bit object, if a 32-bit library is located (which would normally abort linking with an ELFCLASS error), close it and retry locating the library in a "64"/"amd64" subdirectory. This is less risky since it only covers cases which would currently fail to link, but relies on the existence of a 32-bit library.
This applies to -L only; the RPATHs specified with -R are not resolved until runtime by rtld, and is potentially a more difficult problem since the paths specified with -R need not exist at link time.
Updated by Rich Lowe about 8 years ago
This should not be difficult to implement, the challenge would be thoroughily evaluating the possibilities for unintended behaviour.
You should also be aware that, for much this reason, 3rd party software has an unfortunate habit of dumping 64bit libraries into /usr/lib (sans /64), so any approach which caused the linker to silently expand that would thus also be bad.
This, I believe, necessitates a hybrid of your proposed approaches whereby for each path in the search path we:
attempt to use $PATH/libfoo.so if that failed: if the failure was due to absence or ELFCLASS mismatch: try $PATH/64/libfoo.so otherwise: fail properly
And also, as a hedge, add -z auto64 / -z noauto64 to allow the behaviour to be escaped (or require it be enabled explicitly, whichever seems less risky.
The precise "Only automatically descend on errors we know to expect" is a hedge against us continuing to process libraries later in the search path if we fail instead because of, for eg, missing symbols, bad files, etc. We only want to descend (or continue) if we fail due to absence or wrong class.