Recently I 'm studying the linking process and when it comes to weak symbol, my textbook give a code below to demonstrate how to use __attribute__((weakref))
to declare a weak reference to external function:
//pthread.c
#include <stdio.h>
#include <pthread.h>
int pthread_create(
pthread_t*,
const pthread_attr_t*,
void* (*)(void*),
void*
)__attribute__((weak));
int main()
{
if(pthread_create){
printf("This is multi-thread version\n");
}else{
printf("This is single-thread version!\n");
}
}
Then the author use different ways of linking ,which gives the result:
$ gcc pthread.c -o pt
$ ./pt
This is single-thread version!
$ gcc pthread.c -lpthread -o pt
$ ./pt
This is multi-thread version!
I reproduced the same procedure on my machine, but both results give This is single-thread version!
I tried to find out what 's going on here, but I quickly stuck into two problem :
I think it might be that the author mistakenly write
__attribute((weak))__
instead of__attribute__((weakref))__
here. Because if one module declare a weak symbol, the linker would not find the definition of the symbol in the library during the static linking process. Considering that GCC use dynamic linking by default, I use static linking to verify that :$ gcc -c pthread.c $ nm pthread.o U _GLOBAL_OFFSET_TABLE_ 0000000000000000 T main w pthread_create U puts $ gcc -static pthread.c -lpthread -o pt $ nm pt | grep 'pthread_create' $
the symbol 'pthread_create' do not appear in the symbol table.
Now I use
__attribute((weakref))__
to reproduce the procedures.//pthread.c modified #include <stdio.h> #include <pthread.h> static int pthread_create_dup( pthread_t*, const pthread_attr_t*, void* (*)(void*), void* )__attribute__((weakref,alias("pthread_create"))); int main() { if(pthread_create_dup){ printf("This is multi-thread version!\n"); }else{ printf("This is single-thread version!\n"); } }
still, after compiling and linking, the result is
This is single-thread version!
$ gcc -static pthread.c -lpthread -o pt $ nm pt | grep 'pthread_create' $
I make another sample to simulate above:
test.c:
extern int foo(int a,int b);
static int foo_dup(int a,int b) __attribute__((weakref,alias("foo")));
int main(){
if(foo_dup){
printf("foo is linked\n");
}else{
printf("foo isn't linked\n");
}
}
ref_foo.c
int foo(int a ,int b){
return a+b;
}
Then compile those two:
$ gcc -c ref_foo.c test.c
$ ar rcs libfoo.a ref_foo.o
$ gcc -static test.o libfoo.a -o test_withlib
$ ./test_withlib
foo isn't linked
$ gcc -static test.o ref_foo.o -o test_withoutlib
$ ./test_withoutlib
foo is linked
So why would this happen? It's apparently I cannot extract pthread_create.o from libpthread.o and simply gcc pthread.c pthread_create.o -o pt
.How to correctly implement pthread.c so it will print This is multi-thread version!
when linking to the libpthread ?