Reputation: 2594
I have a library CandData such that (relevant) $ nm libCandData.so
:
U _ZN10CandHandle13SetCandRecordEP10CandRecord
U _ZN10CandHandle7SetLockEv
000000011610 T _ZNK10CandRecord13GetCandHeaderEv
U _ZTI10CandHandle
And a library Candidate such that $ nm libCandidate.so
:
00000001f018 T _ZN10CandHandle13SetCandRecordEP10CandRecord
00000001f270 T _ZN10CandHandle7SetLockEv
U _ZNK10CandRecord13GetCandHeaderEv
000000241500 V _ZTI10CandHandle
So, they have circular dependencies. I can load these by lazy loading Candidate first, in this order with everything working:
dlopen("libCandidate.so", RTLD_LAZY | RTLD_GLOBAL);
dlopen("libCandData.so", RTLD_NOW | RTLD_GLOBAL);
But attempting to lazy-load CandData first:
dlopen("libCandData.so", RTLD_LAZY | RTLD_GLOBAL);
dlopen("libCandidate.so", RTLD_NOW | RTLD_GLOBAL);
causes dlopen to report:
dlopen Error: libCandData.so: undefined symbol: _ZTI10CandHandle
What I don't understand is why this order matters? By my understanding, V
means
that the symbol is weakly linked but has a default definition, so can see how that might not be necessary to resolve immediately. But both libraries have a U->T
dependence in them.
Why does one order work, but not the other?
Upvotes: 4
Views: 682
Reputation: 213375
What I don't understand is why this order matters?
The order matters because while unresolved function references can be lazily resolved, data references can not (and _ZTI10CandHandle
is not a function).
Instead of looking at the nm
output, you should look at the relocations (with readelf -Wr
). You will observe that the relocation type in libCandidate.so
for symbol _ZTI10CandHandle
is different from relocation type in libCandData.so
for symbol _ZN10CandHandle7SetLockEv
.
Upvotes: 2