We have a program that links in a number of static libraries, which may or may not define a number of symbols depending on compilation options. On OS X, we use dlsym(3)
with a NULL handle to obtain the symbol addresses. However, on Linux, dlsym(3)
always returns NULL.
Consider a trivial program (sources below) that links in a static library containing a function and a variable and tries to print their addresses. We can check that the program contains the symbols:
$ nm -C test | grep "test\(func\|var\)"
0000000000400715 T testFunc
0000000000601050 B testVar
However, when the program is run, neither can be located:
$ ./test
testVar: (nil)
testFunc: (nil)
Is what we are trying to do possible on Linux, using glibc's implementation of dlsym(3)
?
(Sorry about the spaces)
LDFLAGS=-L.
LDLIBS=-Wl,--whole-archive -ltest -Wl,--no-whole-archive -ldl
libtest.o: libtest.c libtest.h
libtest.a: libtest.o
test: test.o libtest.a
clean:
-rm -f test test.o libtest.o libtest.a
#pragma once
extern void *testVar;
extern int testFunc(int);
#include "libtest.h"
void *testVar;
int testFunc(int x) { return x + 42; }
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char *argv[]) {
void *handle = dlopen(NULL, 0);
void *symbol = dlsym(handle, "testVar");
printf("testVar: %p\n", symbol);
symbol = dlsym(handle, "testFunc");
printf("testFunc: %p\n", symbol);
return 0;
}
You should link your program with -rdynamic
(or --export-dynamic
for ld(1)) so
LDFLAGS += -rdynamic -L.
Then all the symbols are in the dynamic symbol table, the one used by dlsym
BTW, the visibility
attribute could be of interest.
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