ld unpredictable lookup failure building shared library

Ian Lance Taylor iant@google.com
Sun Apr 22 18:33:00 GMT 2012

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

> On Sat, 21 Apr 2012 11:29:37 -0700
> Ian Lance Taylor <iant@google.com> wrote:
>> "James K. Lowden" <jklowden@schemamania.org> writes:
>> > How to verify a .o file was compiled with -fPIC?
>> There is no simply way to tell, unfortunately.  It's a matter of the
>> relocations.  Some relocations can occur in a -fPIC object, some can
>> not.
> Thank you.  At least I understand the limit of what can be shown here.  
>> From your original message, the linker said this:
>> > $ /usr/pkg/bin/gnu-ld @linker.options
>> > /usr/pkg/bin/gnu-ld: /usr/pkgsrc/wip/clang/work/llvm/Release/lib/libLLVMCodeGen.a
>> > (ShrinkWrapping.o): relocation R_X86_64_PC32 against undefined
>> > symbol `_ZNSs4_Rep10_M_disposeERKSaIcE'
>> > can not be used when making a shared object; recompile with -fPIC
>> I assume that this is the GNU linker and that you introduced the line
>> breaks.  
> Yes. 
>> The linker is quite correct: a R_X86_64_PC32 relocation
>> against an undefined symbol can not be used in a shared object.  Such
>> a relocation should never be generated by the compiler when using
>> -fPIC. 
> I appreciate your help, Ian.  I hope to find a way to get you the
> information you need to isolate the cause of the problem. 
> This is not the only R_X86_64_PC32 in the file; it's just the only one
> the linker doesn't like:

As the error message says, it's a problem to have a R_X86_64_PC32
relocation against an undefined symbol.  It's not a problem to have such
a relocation against a defined symbol.

> Regarding this particular symbol, though, objdump finds it and readelf
> does not:
> $ objdump -x ../../lib/CodeGen/Release/ShrinkWrapping.o | grep
> _ZNSs4_Rep10_M_disposeERKSaIcE 
> 0000000000000000         *UND* 0000000000000000
> 	_ZNSs4_Rep10_M_disposeERKSaIcE 
> 000000000000004e R_X86_64_PC32
> 	_ZNSs4_Rep10_M_disposeERKSaIcE+0xfffffffffffffffc
> $ 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.

>> So something is wrong.  The most likely problem is that the
>> symbol is not defined in any object file included in the link.  
> That statement confuses me.  Either the compiler emitted incorrect code
> ("should never be generated") or the code is OK by the linker line is
> wrong ("not defined in any object file included in the link").  Unless  
> the compiler was supposed to generate code but mistakenly opted to punt
> over to the linker by emitting R_X86_64_PC32 instead?  Perhaps because
> it's a template we're talking about?  

The compiler generates single object files.  Having a R_X86_64_PC32
relocation in a single object file is neither right nor wrong.  When
using -fPIC it is normal to have a R_X86_64_PC32 relocation for a local
symbol or for a symbol with non-default visibility.  The linker sees all
the object files at the same time.  When the linker is generating a
shared library, there must be a definition for ever symbol referenced by
an R_X86_64_PC32 relocation.  If there is no definition, the linker will
reject the program, because the dynamic linker will be unable to resolve
the relocation at runtime.  Some dynamic relocations are OK at runtime,
but R_X86_64_PC32 is not, because the symbol definition is likely to be
out of range from the reference.

> We know where the symbol is defined i.e., where the object code is that
> we want the linker to find
> $ nm /usr/lib/libstdc++.so | grep _ZNSs4_Rep10_M_disposeERKSaIcE
> 000000000006f830 W _ZNSs4_Rep10_M_disposeERKSaIcE
> and we know where it's referenced, because that's in the linker message.
> What do you mean by "not defined in any object file"?  Does the library
> not count as "an object file"?  Does the symbol in ShrinkWrapping.o not
> count as a "definition"?   (I am not in the least trying to be
> flippant.  I hope that's clear.)  

I don't know whether you are linking libstdc++.so itself or not.  If you
are, then for some reason in your link the symbol is not defined.  If
you are not, then the definition in libstdc++.so does not count.  For an
R_X86_64_PC32 relocation to be resolvable, the symbol must be defined in
one of the object files passed to the linker, not in a shared library
included in the link.

Hope that makes more sense.


More information about the Binutils mailing list