dlsym
函数是 Linux 下动态链接库(shared library)编程中的一个重要函数。它用于在运行时获取动态链接库中符号的地址,通常用于获取函数指针或变量的地址。
以下是 dlsym
函数的基本用法和示例。
1. 函数原型
c
void *dlsym(void *handle, const char *symbol);
handle
:通过dlopen
函数获取的库句柄。symbol
:要查找的符号的名称(通常是函数名或变量名)。- 返回:返回符号的地址,失败时返回
NULL
。
2.疑惑
创建一个可执行程序和一个so文件
1.c
c
#include <stdio.h>
#include <dlfcn.h>
extern void a();
int main()
{
void *p = dlsym(NULL, "a");
void *q = printf;
void *r = dlsym(NULL, "printf");
void *s = a;
a();
}
2.c
c
#include <stdio.h>
void a()
{
void *b = printf;
printf("hahahaha\n");
}
编译为共享库:
bash
gcc -g -fPIC -shared 2.c -o liba.so
编译可执行程序:
bash
gcc -g 1.c -I. -L. -la -ldl
不注释掉1.c中void *s = a;
使用gdb查看
可以看出使用dlsym查找的是a在内存中的绝对地址
注释掉1.c中void *s = a;
使用gdb查看
发现dlsym查找的符号是plt表中a的地址,反汇编p
3.原因猜测
注释掉1.c中void *s = a;这句代码,1.c中没有对a的引用,意味着got plt标准不在在关于a的表项,不注释时,存在关于a的plt和got表项,dlsym从模块对应的表项开始搜索,所有不注释时查到到的地址时plt地址,注释后查找的是真实地址。