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

如何获取C++函数的被修饰符号?适配dlmopen加载的不可修改库

C++闭源共享库dlmopen后的符号获取方案

你遇到的核心问题是C的名字修饰(Name Mangling)——C编译器会将函数名、参数类型、名字空间等信息编码成唯一的修饰符号,而dlsym只能识别这种修饰后的符号。以下是具体解决步骤:

1. 获取库中的修饰后符号

首先需要从目标共享库中提取出目标函数对应的修饰符号,可通过以下命令实现:

  • 使用nm命令:
    nm -D /myLib.so | grep <原函数名>
    
    例如原函数是void test(int),输出可能类似0000000000001234 T _Z4testi(GCC/Clang的修饰格式)。
  • 使用objdump命令(信息更详细):
    objdump -T /myLib.so | grep <原函数名>
    

注意:如果共享库被strip处理过(移除了符号表),上述命令无法获取符号。这种情况下只能联系库提供者获取符号信息,或使用调试版本的库。

2. 调用dlsym获取函数指针

拿到修饰后的符号后,直接将其传入dlsym,并通过reinterpret_cast转换为正确的函数指针类型(必须保证签名完全匹配,包括返回值、参数类型、const修饰、引用/值传递等,否则会触发未定义行为)。

示例代码:

// 假设拿到的修饰符号是_Z4testi,原函数签名为void test(int)
void (*test_func)(int) = reinterpret_cast<void(*)(int)>(
    dlsym(handle, "_Z4testi")
);

// 调用函数(如果指针有效)
if (test_func) {
    test_func(123);
}

3. 兼容不同编译器/名字空间的情况

  • 如果库由其他编译器编译(如MSVC,但Linux场景下少见),需要用相同编译器编写测试代码来匹配修饰规则:
    新建一个测试文件test_sym.cpp:
    // 完全复刻目标函数的签名、名字空间
    namespace myns {
        void test(int);
    }
    int main() { return 0; }
    
    编译后查看符号:
    g++ -c test_sym.cpp && nm test_sym.o
    
    得到的符号就是该编译器下的修饰结果,再去库中查找匹配项。
  • 若函数属于某个名字空间,修饰符号会包含名字空间信息,必须保证测试代码的名字空间与库中一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 06:06:20