Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using dlsym() to look for a variable in a statically linked library

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;
}
like image 347
Peter T.B. Brett Avatar asked Sep 29 '22 04:09

Peter T.B. Brett


1 Answers

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.

like image 175
Basile Starynkevitch Avatar answered Oct 02 '22 14:10

Basile Starynkevitch