如何反解析readelf .symtable中的符号名及调用偏移含义?
C++ 修饰名反解析方法
有几种工具链自带的方式可直接完成反解析,不需要手动对照C++名称修饰规则推导:
- 直接使用GNU binutils自带的
c++filt工具,传入修饰后的符号名作为参数即可输出原始C++符号,例如执行c++filt _ZNSirsERi就能直接得到对应的函数原型 - 反汇编时给objdump添加
-C(即--demangle)参数,反汇编输出会自动对所有C++修饰名做反解析,不需要手动逐个转换 - 使用gdb加载目标文件时默认开启符号反解析,查看反汇编、符号表时都会直接显示可读的原始符号名
列出的三个修饰符号对应含义
通过标准反解析可以得到三个符号的实际定义:
_ZSt3cin:即你已知的std::cin,C++标准库的全局标准输入流对象_ZNSirsERi:std::istream::operator>>(int&),是istream类针对int类型重载的输入运算符,也就是代码中写cin >> int类型变量时实际调用的成员函数_ZNSolsEi:std::ostream::operator<<(int),是ostream类针对int类型重载的输出运算符,对应代码中cout << int类型变量的输出操作
调用指令中
-0x4偏移的本质 这个偏移不是指调用_ZNSirsERi对应函数前4字节的位置,是未链接目标文件的重定位状态导致的反汇编显示偏差:
你当前持有的是还没经过链接步骤的.o可重定位目标文件,readelf输出里这几个符号都是UND(未定义)类型,说明它们不属于当前编译单元,实际内存地址需要链接阶段才会分配。x86-64架构下对这类外部跨模块函数的调用会走PLT(过程链接表)桩指令中转,未完成重定位时这些PLT桩没有分配最终地址,也没有生成对应的专属符号,反汇编器生成符号标注时,会找距离调用目标地址最近的符号,再计算相对偏移拼到标注里。这里的_ZNSirsERi-0x4就是反汇编器就近匹配到_ZNSirsERi符号后算出偏移为-0x4的显示结果,这条call指令的实际跳转目标就是std::istream::operator>>(int&)对应的PLT桩,不存在偏移4字节调用的逻辑。
内容的提问来源于stack exchange,提问作者Troutt025
相关产品推荐
相关产品推荐

