使用dlsym()在静态链接库中查找变量

我们有一个程序链接在许多静态库中,这些静态库可能会也可能不会根据编译选项定义多个符号.在OS X上,我们使用带有NULL句柄的dlsym(3)来获取符号地址.但是,在Linux上,dlsym(3)总是返回NULL.

考虑一个简单的程序(下面的源代码),它链接在包含函数和变量的静态库中,并尝试打印它们的地址.我们可以检查程序是否包含符号:

$nm -C test | grep "test\(func\|var\)"
0000000000400715 T testFunc
0000000000601050 B testVar

但是,当程序运行时,两者都不能找到:

$./test
testVar: (nil)
testFunc: (nil)

我们在Linux上尝试做什么,使用glibc实现的dlsym(3)?

Makefile文件

(抱歉这个空格)

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;
}

解决方法:

您应该将程序与-rdynamic(或–export-dynamic for ld(1))链接起来

LDFLAGS += -rdynamic -L.

然后所有符号都在动态符号表中,即dlsym使用的符号表

顺便说一句,visibility attribute可能会引起关注.

上一篇:为什么这个简单的Linux C程序在运行时加载.so会崩溃?


下一篇:JAVA设计模式之装饰器模式