Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different symbols from glibc/pthreads used when using gold vs ld linker

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:

  1. Why the different behavior between gold and the old/normal ld.
  2. Which pthread_cond_broadcast symbol is being used at runtime in the Case 2, when the binary is linked to an unversioned 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.)

like image 743
binary01 Avatar asked Feb 02 '16 10:02

binary01


1 Answers

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...).

like image 162
Mike Frysinger Avatar answered Nov 06 '22 09:11

Mike Frysinger