5

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

 Makefile

(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

libtest.h

#pragma once
extern void *testVar;
extern int testFunc(int);

libtest.c

#include "libtest.h"
void *testVar;
int testFunc(int x) { return x + 42; }

test.c

#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;
}
2
  • 6
    Totally unrelated, but naming a program test in a POSIX environment is a big source of problems, as there is a standard command also named test, often built into modern shells. Commented Dec 17, 2014 at 10:28
  • 3
    True! However, if you have . in your PATH then you deserve what you get. :P Commented Dec 17, 2014 at 10:30

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

For those, like me, who didn't know (from the manual): -rdynamic: Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the dynamic symbol table. This option is needed for some uses of dlopen or to allow obtaining backtraces from within a program.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.