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

标签 c linux gcc static-libraries 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)

使用 glibc 的 dlsym(3) 实现,我们在 Linux 上尝试做的事情是否可行?

生成文件

(抱歉有空格)

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

测试.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可能很有趣。

关于c - 使用 dlsym() 在静态链接库中查找变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27523308/

相关文章:

c - 在循环链接列表中存储用户输入的名称

c - 确定什么 secret 握手导致他们只打印给定的行一次

windows - linux 和 windows 32 位系统的 int64_t 或 offset64 原型(prototype)

c - snprintf 错误。 sizeof 的参数与目标相同

python - 任意 C 项目的预处理

C99:复数的虚部能否为负零

c - 初始化大 vector 时出现段错误

c - 将指针返回到自身

使用 C 或 Visual Basic 以编程方式连接到 GMail

Python,脚本结束时关闭具有不同SID的子进程