ld unpredictable lookup failure building shared library

Ian Lance Taylor iant@google.com
Mon Apr 23 01:58:00 GMT 2012

"James K. Lowden" <jklowden@schemamania.org> writes:

> 1.  With -fPIC, the compiler may generate R_X86_64_PC32.  It is
> "normal" to have an R_X86_64_PC32 against *defined* symbols, but not
> strictly necessary.  
> 2.  Such defined symbols must  be local or have non-default
> visibility.  (As a C programmer, I think that means such symbols have
> no external linkage i.e. they are declared static.  But that
> contradicts #1.)
> 3.  The object file in question was compiled with -fPIC and furthermore
> contains artifacts of being compiled with -fPIC.  
> 4.  When the linker is generating a shared library, every R_X86_64_PC32
> relocation (directive? instruction?) must refer to a symbol defined in
> an object file passed to the linker, not in any shared library.  
> 5.  The linker reports finding a symbol with an R_X86_64_PC32
> relocation for an undefined symbol.  That appears to be correct,
> insofar as I have been unable to find a definition for that symbol
> among the object files mentioned on the linker command line using
> objdump and readelf.  
> 6.  Ergo, the the build is in error.  
> If I could generate one tiny .o with a definition for
> _ZNSs4_Rep10_M_disposeERKSaIcE, the link would work. But that should
> not be necessary because the compiler should never have emitted a file
> lacking that definition in the first place.  (Although the symbol can
> be defined in another .o, the compiler has no right to assume there
> will be another .o.  It's possible to build a .so using just one .cpp
> file.)
> Or the compiler is in error?  Much rests on the meaning of "normal"
> above.  It is unclear to me why the compiler would sometimes not define
> a symbol that cannot be drawn from a library.  

That all looks basically right.  I would say that the compiler is in
error here.  The compiler is certainly permitted to refer to a symbol
drawn from a library.  But when compiling with -fPIC, any such reference
must not use a R_X86_64_PC32 relocation (it should use a R_X86_64_PLT32
relocation instead).  So the error is that compiler emitted a PC32
relocation when it should have emitted a PLT32 relocation.

>> > $ readelf -rw  ../../lib/CodeGen/Release/ShrinkWrapping.o \
>> > 	| grep -c '_ZNSs4_Rep10_M_disposeERKSaIcE' 
>> > 0
>> The readelf program is (in my opinion) broken in that you have to use
>> the --wide option to get reliable results.
> That's what -rw was meant to do but didn't.  Here it is corrected
> (wrapped for email):
> $ readelf -rW  ../../lib/CodeGen/Release/ShrinkWrapping.o \
> 	| grep '_ZNSs4_Rep10_M_disposeERKSaIcE' 
> 000000000000004e  0000013300000002
> R_X86_64_PC32          0000000000000000 _ZNSs4_Rep10_M_disposeERKSaIcE
> + fffffffffffffffc
> Apart from truncating symbols by default, the readelf program has
> another serious flaw: the documentation is long on inputs and silent on
> the meaning of the outputs.  
> I'm guessing that the zeros for the "value" in column 3 indicate the
> symbol appears at offset 0x4E but is not defined.  That of course
> is consistent with the linker message.  

That's not quite right.  The 0x4e is the address of the relocation.  The
readelf -r option just dumps the relocation information, and the
relocation refers to the symbol table.  To see the entry in the symbol
table, you need to use the readelf -s option.


More information about the Binutils mailing list