I have a simple test program calling pthread_cond_broadcast
.
When linked with the ld
linker, this shows:
Case 1:
$ nm ld-test | grep cond_broadcast
U pthread_cond_broadcast@@GLIBC_2.3.2
When linked with the gold
linker it shows:
Case 2:
$ nm gold-test | grep cond_broadcast
U pthread_cond_broadcast
pthread/libc contains several pthread_cond_broadcast symbols with different version symbols presumably since the ABI has been changed.
$ nm /lib64/libc.so.6 |grep cond_broadca
00000036b84f7d30 t __pthread_cond_broadcast
00000036b85278f0 t __pthread_cond_broadcast_2_0
00000036b84f7d30 T pthread_cond_broadcast@@GLIBC_2.3.2
00000036b85278f0 T pthread_cond_broadcast@GLIBC_2.2.5
$ nm /lib64/libpthread.so.0 |grep cond_broadcast
00000036b880bee0 t __pthread_cond_broadcast
00000036b880c250 t __pthread_cond_broadcast_2_0
00000036b880bee0 T pthread_cond_broadcast@@GLIBC_2.3.2
00000036b880c250 T pthread_cond_broadcast@GLIBC_2.2.5
So the questions are:
gold
and the old/normal ld
.pthread_cond_broadcast
symbol. The newest implementation of pthread_cond_broadcast ? The oldest ?This is using gcc 4.9.2 and the gold/ld linker from binutils 2.24 (as part of devtoolset-3 from Red Hat.)
first a clarification: ELF files often have two symbol tables. there's the "fat" or "full" one that contains all the internal symbols (usually in a section named .symtab
of type SHT_SYMTAB
), and there's the "slim" one that only contains runtime details (usually in a section named .dynsym
of type SHT_DYNSYM
). nm
only parses the first one, so it's often not a good indicator of runtime behavior. you want to use readelf -s
instead and look at the .dynsym
table to see what actually matters at runtime.
(1) i don't know why the debug symbol table doesn't include the full symbol versioning when using gold. seems like a bug to me.
(2) once you look at the runtime symbol table, your answer appears by itself: pthread_cond_broadcast@GLIBC_2.3.2
will be used.
(2a) as for which library that symbol will be loaded from, that depends entirely on how the ELF was linked and its runtime environment. let's ignore all the possibilities and focus on the common one: if you linked with -lpthread, then the version in libpthread.so will be used. if you didn't, then the version in libc.so will be used.
(2b) why does a single library have more than one version (e.g. libc.so
has pthread_cond_broadcast@@GLIBC_2.2.5
and pthread_cond_broadcast@@GLIBC_2.3.2
) ? you correctly guessed that it's for backwards compatibility. at some point in the past, the ABI was changed, so rather than break all existing apps, they updated the version. all programs that were linked against an old glibc version will use the old symbol versions while new programs will use the new symbols. as a matter of policy, glibc exposes the latest symbol version as the default one, so when you use pthread_cond_broadcast
, you'll be linked against the pthread_cond_broadcast@@GLIBC_2.3.2
one. this is purely a convention most everyone uses ... although it is technically possible to expose any of them as the default version.
(2c) why does the symbol exist in both libc.so & libpthread.so ? this allows libraries to support multithreaded environments w/out being penalized in a singlethreaded environment, or w/out having to write two different libs, e.g. one named libfoo.so and one named libfoo_thread.so. the symbols in libc.so are dummy symbols -- they always return "success". so if your main program isn't multithreaded, all the calls in libfoo.so will be stubbed out. but if your main program is multithreaded (i.e. links against -lpthread), then the symbols will be transparently & automatically routed to libpthread.so and all the calls in libfoo.so will DTRT (i.e. grab mutexes/etc...).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With