Linux dlsym符号查找疑惑分析

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地址,注释后查找的是真实地址。

相关推荐
w***Q3503 小时前
Git工作流自动化
运维·git·自动化
qq_401700413 小时前
嵌入式用Unix时间的优势及其C语言转换
服务器·c语言·unix
xu_yule5 小时前
Linux_12(进程信号)内核态和用户态+处理信号+不可重入函数+volatile
linux·运维·服务器
虾..5 小时前
Linux 环境变量&&进程优先级
linux·运维·服务器
i***t9195 小时前
Linux下MySQL的简单使用
linux·mysql·adb
偶像你挑的噻5 小时前
11-Linux驱动开发-I2C子系统–mpu6050简单数据透传驱动
linux·驱动开发·stm32·嵌入式硬件
稚辉君.MCA_P8_Java6 小时前
DeepSeek 插入排序
linux·后端·算法·架构·排序算法
数据库学啊7 小时前
团队小希望运维简单,时序数据库选型有什么推荐?
运维·数据库·时序数据库
霍格沃兹软件测试开发7 小时前
Playwright MCP浏览器自动化指南:让AI精准理解你的命令
运维·人工智能·自动化
郝学胜-神的一滴8 小时前
Linux命名管道:创建与原理详解
linux·运维·服务器·开发语言·c++·程序人生·个人开发