Skip to Main Content

DevOps, CI/CD and Automation

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Undefined symbols with dynamically loaded library

807575Dec 9 2009 — edited Dec 10 2009
Hi,

Using Sun Studio for Linux. CC -v output:CC: Sun C++ 5.10 Linux_i386 2009/06/03

I have a library which is dynamically loaded (dlopen'ed) - the library accesses some symbols defined in another static library (.a) which is in turn linked to the main.

On Solaris 10, just compiling the code with -KPIC works and library gets dlopen'ed fine and symbols from the linked static library are accessible. On Linux, If I compile using g++, I can get it working after supplying an additional option to GNU linker -Wl,--whole-archive <my_static_library> -Wl,--no-whole-archive. However , with CC even after trying various options, I get "undefined symbol" in the dlopen'ed library for the symbols which belong to the static library.

As per documentation, similar option (-z allextract and -z defaultextract) are available for ld with Sun workshop) - but using them does not solve the error. doing ld help on Workshop ld shows whole-archive and --no-whole-archive instead of -z allextract/defaultextract, so tried those options as well.

Here are the details:
- I have a simple project with 3 files -
A.h/A.cpp -> compiled into static library libar.a - This has a single static function defined.
B.cpp -> compiled into dynamic library libB.so -> This will be dlopen'ed, has only one function which in turn calls A::func().
testdll.cpp -> main program which links with libar.a and dlopen's the libB.so, calls the single function there.

If I use RTLD_LAZY, the symbol error is postponed till the actuall call, if I use RTLD_NOW, the library libB.so can't be dlopen'ed - this behaviour is as expected.

My makefile looks like below (commented out lines are for g++ compilation which work)

--------------- Makefile
all: libar libdll testdll

libar: A.cpp
CC -m32 -KPIC -c A.cpp -o A.o
CC -xar A.o -o libar.a
# g++ -Wall -c A.cpp -o A.o
# ar cr libar.a A.o

testdll: testdll.cpp
CC -m32 -KPIC -c testdll.cpp -o testdll.o
CC -m32 testdll.o -L. -z allextract -lar -z defaultextract -ldl -o testdll
# CC -m32 testdll.o -L. -Qoption ld whole-archive -lar -Qoption ld no-whole-archive -ldl -o testdll
# g++ -rdynamic -Wall testdll.cpp -ldl -L . -Wl,--whole-archive libar.a -Wl,--no-whole-archive -o testdll
# g++ -Wall testdll.cpp -ldl -L . libar.a -o testdll

libdll: B.cpp
CC -m32 -G -KPIC B.cpp -o libB.so
# g++ -Wall -c -fPIC B.cpp -o B.o
# g++ -shared B.o -o libB.so

clean:
rm testdll libar.a libB.so

--------------- A.h:
#ifndef __A_H
#define __A_H

class A {
public:
static void func();
};

#endif

---------------- A.cpp
#include "A.h"
#include "stdio.h"

void A::func() {
printf("In static function of class A\n");
}

------------ B.cpp
#include <stdio.h>
#include "A.h"

extern "C" void GetInterface() {
printf("Interface function");
A::func();
}

---------- testdll.cpp
#include <dlfcn.h>
#include <stdio.h>
#include "A.h"

typedef void (*VOIDFUNC) (void);

int main(int argc, char* argv[]) {
//Direct call to A::func.
A::func();

void *handle = dlopen("libB.so",RTLD_LAZY);
if (handle == NULL) {
printf("unable to load libB :%s\n",dlerror());
} else {
printf("loaded libB %p\n", handle);
VOIDFUNC symbol = (VOIDFUNC) dlsym(handle,"GetInterface");
if ( !symbol) {
printf("unable to find GetInterface\n");
} else {
printf("found GetInterface\n");
//Indirect call to A::func().
(*symbol)();
}
}
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jan 7 2010
Added on Dec 9 2009
2 comments
501 views