2

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?

searchengine27
  • 1,449
  • 11
  • 26
  • Please update your question with the output from `readelf -d bin/main` for binaries built by both compilers. I expect the difference to be in `DT_RPATH` vs. `DT_RUNPATH`, but it would be nice to not guess. – Employed Russian Mar 19 '20 at 01:51
  • 1
    I updated. The rpath does seem to exist even though I never explicitly specified it. I still don't understand the how or the why though, if you have any insight into that. – searchengine27 Mar 19 '20 at 13:01

1 Answers1

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.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Well both (to my knowledge - not my system, I just do work on it) were installed separate from the Linux distro install. It's a strange environment that I'm working in (let's just say **lots** of cross mounting, to keep that explanation short), so it's certainly possible that 8.2.0 came with the system, I just have no feasible way to know for sure. Either way, I can see how this answer makes sense and some configuration on install would have caused this. – searchengine27 Mar 19 '20 at 19:12