duplicate symbol in dynamic library
(21时29分58秒) smellydog: Hi, I have a liba.so which has function libfuncA(), and libb.so which has function libfuncB(), libfuncB calls libfuncA(). In my main.c, I define another libfuncA(), it calls libfuncB(). All this is compiled smoothly, but when run, I got segment fault, what's wrong?
(21时31分24秒) smellydog: All commands to compile is below:
(21时31分24秒) smellydog: gcc --share -o liba.so liba.c
(21时31分24秒) smellydog: gcc --share -o libb.so libb.c
(21时31分24秒) smellydog: gcc -c -o test.o test.c
(21时31分24秒) smellydog: gcc -o test test.o -L. -lb
(21时32分18秒) smellydog: I'll give you source if you need. Thanks!
(21时33分20秒) davidr_: smellydog: have you localised where the segfault is? e.g. compile all your objects with -g and run via gdb?
(21时38分14秒) smellydog: davidr: It seems be the program call the libfuncA() defined in main.c instead of libfuncA() in liba.so, which make a infinite recursion.
(21时40分49秒) smellydog: I solved the segment fault by renaming libfuncA() in main.c to funcA(), as long as different from function name in liba.so.
(21时43分21秒) smellydog: But I don't know how to avoid such problem, because I link my program to some libxxx.so, I don't know whether libxxx.so refering some function with the same func name as my function in other library.
(21时44分32秒) davidr_: smellydog: ok; so the way symbol resolution in shared objects works by default is as follows: if the symbol is defined in the main executable; then then symbol takes prescidence
(21时45分28秒) davidr_: smellydog: you need to mark libfuncA() with __attribute__ ((visi-bility ("hidden")))
(21时45分44秒) davidr_: (drop that hypen in visibility; was a typo)
(22时18分06秒) smellydog: davidr_: I followed your instruction, add __attribute__ ((visibility ("hidden"))) to libfuncA() in test.c, but I got some error:"hidden symbol `libfuncA' in test.o is referenced by DSO" while linking.
(22时23分39秒) davidr_: smellydog: so I think you might have another problem - how as libbfunc() expecting to load liba? are you doing a dlopen() on it?
(22时26分10秒) smellydog: davidr_: I didnot call dlopen(), just include <liba.h> and compile it with -lb
(22时26分47秒) davidr_: smellydog: ok, so the problem you have is how does libb know to open liba? they have no defined relation ship at the moment
(22时27分01秒) smellydog: davidr_: sorry, the compile command line is :gcc --share -o libb.so libb.c
(22时27分20秒) davidr_: smellydog: sure, but there's no mention of liba there
(22时28分00秒) davidr_: so you have test.exe, which is explicityly linked to libb.so. but when you run text.exe, it doesn't know to load liba
(22时28分26秒) davidr_: if you run ldd <test> you'll see which libraries are linked in at compile time
(22时28分42秒) davidr_: to get access to any other libraries, you'll have to explicitiy load them at runtime
(22时28分59秒) smellydog: but I did not get test.exe, got error while link.
(22时30分26秒) davidr_: smellydog: sure, if you revert the visibility change you'll see what I mean. I didn't understand your full problem at the beginning, the visibility thing isn't the (full) solution
(22时33分50秒) smellydog: davidr_:yes, after revert the visibility change and link, I get test.exe, which links to libb.so, no liba.so
(22时40分20秒) smellydog: davidr_: how to aviod such problem? Do I must know every symbol the library used?
(22时40分44秒) davidr_: smellydog: ok you've got a couple of options; but you should probably go and read up on shared libraries
(22时41分05秒) davidr_: smellydog: why have liba and libb in seperate libraries for a start?
(22时49分34秒) smellydog: davidr_: It's just an example, Actually this problem is from my working, I write a program main.c which defined a connect() function, and I compile main.c and link it to Oracle oci library libclntsh.so.10 with -lclntsh. But I got segment fault while running, after debug, I found it is caused by a infinite recursion. I guess the connect() in main.c is called from other lib. So I do this test.
(22时50分53秒) noshadow: smellydog: connect is a standard library functions. of course things might segfault if you replace it with a function with other call semantics....
(22时51分19秒) davidr_: smellydog: ok. So in terms of what you are doing (in the test program); you need to explicity load liba from libb; so in libbfunc() have something like:- {handle = dlopen("liba); myfunc = dlsym(handle, libafunc); myfunc() }
(22时57分10秒) smellydog: davidr_: Thanks! Now I know connect() is a standard library functions, and I should not "rewrite" it ever, but what about other standard library functions I don't know and "rewrite" them by mistake. can gcc give me some waring? such problem is hard to debug.
(23时00分31秒) noshadow: smellydog: only way I see it could warn is when the appropiate header is installed. Then it will usually warn as the function will have different prototypes. But all the headers are quite big.
(23时01分04秒) noshadow: A way to avoid such problems is to make all functions static you do not need outside the file.
(23时02分02秒) noshadow: And to check names you use between files (under linux installing development manpages and looking there) or using names unlikely to be default (like modulename_function)...
(23时04分22秒) smellydog: noshadow: Thanks for reply! Is there some tools to check names between files?
(23时06分52秒) noshadow: smellydog: perhaps splint or co might do so..
(23时09分19秒) smellydog: noshadow: Thanks! I'm go for them. I learn much about shared library and its loading, and can you suggest some readings about it?
Test codes:
-----------------------------------------------------------
/*liba.h:*/
int libfuncA();
-----------------------------------------------------------
/*liba.c*/
#include <stdio.h>
int libfuncA()
{
printf("from lib A\n");
return 0;
}
-----------------------------------------------------------
/*libb.h*/
int libfuncB();
-----------------------------------------------------------
/*libb.c*/
#include <stdio.h>
#include "liba.h"
int libfuncB()
{
printf("from lib B\n");
libfuncA();
return 0;
}
-----------------------------------------------------------
/*test.c*/
#include <stdio.h>
#include "libb.h"
int libfuncA(){
printf("from funcA in main\n");
libfuncB();
}
int main()
{
libfuncA();
return 0;
}
-----------------------------------------------------------
My solutions is:
-----------------------------------------------------------
in test.c
- int libfuncA(){
+ static int libfuncA(){
-----------------------------------------------------------
compile:
gcc --share -o liba.so liba.c
gcc --share -o libb.so -L. -la libb.c
gcc -c -o test.o test.c
gcc -o test test.o -L. -lb
-----------------------------------------------------------
