You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何查找.so动态库文件中符号(如函数名)的绝对地址

动态库.so符号地址获取方法

你看到的地址为0的符号都标记了UND属性,属于该动态库依赖的外部符号(比如glibc、libstdc++提供的库函数),本身并不在当前.so中实现,因此没有对应地址。你输出中第66行的_ZN4test13overwriteFuncEiml是当前.so自身实现的函数,第一列的0xfe0就是该函数在.so文件内的相对偏移地址。

静态获取符号相对偏移

如果仅需要获取符号在.so文件中的相对偏移,可使用以下方法:

  • 优先使用readelf命令读取符号表,结果更准确:
    readelf -s myLib.so | grep 目标符号名
    输出结果的Value字段即为符号的相对偏移。
  • 也可使用nm命令,若要查看C++脱修饰后的函数名,添加-C参数:
    nm -gDC myLib.so | grep 目标函数名
    非UND条目的第一列就是符号相对偏移。

注意:如果.so文件已经被strip过,符号表会被删除,静态工具无法查询到符号信息。

运行时获取符号绝对地址

动态库默认编译为位置无关代码(PIC),加载到进程虚拟地址空间的基址是运行时动态分配的,因此绝对地址 = 动态库加载基址 + 符号相对偏移,可通过两种方式获取:

方法1:程序内通过dlsym直接获取

调用dlopen系列函数可直接拿到符号的绝对地址,示例代码如下:

#include <dlfcn.h>
#include <stdio.h>

int main() {
    // 加载目标动态库
    void* handle = dlopen("./myLib.so", RTLD_LAZY);
    if (!handle) {
        printf("加载动态库失败: %s\n", dlerror());
        return 1;
    }
    // 查找目标符号地址,C++符号需要传入修饰后的名称,或加extern "C"修饰函数
    void* sym_addr = dlsym(handle, "目标符号名");
    if (!sym_addr) {
        printf("查找符号失败: %s\n", dlerror());
        dlclose(handle);
        return 1;
    }
    printf("符号绝对地址为: %p\n", sym_addr);
    dlclose(handle);
    return 0;
}

编译时添加-ldl参数链接动态加载库即可运行。

方法2:通过进程maps文件计算

如果目标动态库已经被加载到某进程中,可通过进程的maps文件计算地址:

  1. 先查询目标进程的PID,执行cat /proc/<PID>/maps | grep myLib.so,输出第一列的起始地址就是该动态库的加载基址。
  2. 将加载基址加上之前静态查询到的符号相对偏移,得到的结果就是该符号在当前进程中的绝对地址。

额外注意事项

C++函数默认会开启名字修饰,直接用原函数名无法查找到符号,有两种解决方案:

  • 函数定义时添加extern "C"修饰,关闭名字修饰。
  • 查询符号时使用修饰后的名称,可通过nm -DC命令先查询到修饰名和原函数的对应关系。

内容的提问来源于stack exchange,提问作者Qiyang Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:12:02