I encountered an odd difference between the binary produced by a 4.9.2 G++ and a 8.2.0 G++ on a Linux, when upgrading from the former to the latter. I was able to narrow it down to the below minimized snippet
//main.cpp
int main(){}
//emptylib.cpp
#!/bin/sh
#to build and verify output
rm -rf bin lib *.o
gcc_bin=/path/to/gcc_4.9.2/bin
#gcc_bin=/path/to/gcc_8.2.0/bin
${gcc_bin}/g++ -B${gcc_bin} -c main.cpp
${gcc_bin}/g++ -B${gcc_bin} -c emptylib.cpp
${gcc_bin}/g++ -B${gcc_bin} -shared emptylib.o -o libemptylib.so
${gcc_bin}/g++ -B${gcc_bin} main.o -o main -L. -lemptylib
mkdir bin
mkdir lib
mv libemptylib.so lib/
mv main bin/
ldd bin/main
The result is a bit strange, because I have provided no -rpath=../lib
, but all the same, with the 4.9.2 compiler driver I end up with (in the output of ldd):
libemptylib.so => /path/to/bin/../lib/libemptylib.so
and with 8.2.0
libemptylib.so => not found
the lib does not resolve, as I would expect. I haven't been able to see any documentation that hints at a search for ../lib
in any version, but I would not expect this to be a behavior by any version. Was this a bug in 4.9.2 or some earlier version or something that shouldn't have happened in the first place?
As a side note, the 8.2.0 and the 4.9.2 don't have an ld
inside of their bin directory (despite me putting the -B
in the code snippet), so both compiler drivers are using the /usr/bin/ld (I've verified as much) and producing different results based on the compiler driver alone.
Update:
On request, I ran readelf -d bin/main
on both binaries and I did receive different output for rpath. GCC 4.9.2 gave me:
0x000000000000000f (RPATH) Library rpath: [$ORIGIN:$ORIGIN/../lib64:$ORIGIN/../lib:/path/to/gcc_libs/lib64:/path/to/gcc_libs/lib:/path/to/gcc_4.9.2/lib64:/path/to/gcc_4.9.2/lib]
where 8.2.0 did not have that
0x0000000000000001 (NEEDED) Shared Library: [libemptylib.so]
So I guess I have an answer to what happened. So how did this end up in my binary in 4.9.2, and why did it change between the two versions where now it doesn't in 8.2.0?
I did receive different output for rpath.
rpath: [$ORIGIN:$ORIGIN/../lib64:$ORIGIN/../lib:/path/to/gcc_libs/lib64:/path/to/gcc_libs/lib:/path/to/gcc_4.9.2/lib64:/path/to/gcc_4.9.2/lib]
So the difference is in how GCC 4.9.2 vs. 8.2.0 were configured.
I am guessing that 8.2 came from your distribution (or at least was configured with default installation paths), whereas 4.9 was configured to be installed into /path/to/gcc_4.9.2
.
That explains why 4.9 adds -rpath
with /path/to/gcc_4.9.2/lib64
for a 64-bit builds. It does not however explain where $ORIGIN
of /path/to/gcc_4.9.2/lib
(the latter shouldn't be part of a 64-bit build) come from.
Configuring GCC so that it puts exactly what's necessary, no more and no less, is a bit of a black magic. I wouldn't be surprised if 4.9 had some bugs in that area.