部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

gdb-反汇编指令(disassemble)应用

参考资料

disassemble command https://visualgdb.com/gdbreference/commands/disassemble
disassemble结果每一部分含义 https://cs61.seas.harvard.edu/site/2018/Asm1/
汇编指令解析 https://john-theo.github.io/2017/10/09/asm/
c++filt查看符号 https://zhuanlan.zhihu.com/p/42816743

disassemble

支持的参数

参数 解释
Function 指定要反汇编的函数。 如果指定,反汇编命令将产生整个函数的反汇编输出
Address 指定要反汇编的函数内的地址。 请注意,当仅指定一个地址时,此命令将反汇编包含给定地址的整个函数,包括其上方的指令
Start/End 指定要反汇编的起始地址和结束地址。 如果使用这种形式,该命令不会反汇编整个函数,而只会反汇编起始地址和结束地址之间的指令
Length 指定从给定地址或函数开始反汇编的字节数
/m 指定此选项时,反汇编命令将显示与反汇编指令对应的源代码行
/r 指定此选项时,反汇编命令将显示所有反汇编指令的原始字节值
Remarks GDB 使用的默认反汇编风格是 AT&T 风格(例如 mov 0xc(%ebp),%eax),这可能会让 Windows 用户感到困惑。 要切换到 Intel 反汇编风格(例如 mov eax,DWORD PTR [ebp+0xc]),请使用set disassembly-flavor 命令
请注意,反汇编命令仅适用于函数内部的代码。 如果要反汇编任何已知函数之外的内存,请使用 x 命令的 x/i 变体。

示例代码

int func(int a, int b)
{
    return a + b;
}

int main()
{
    return func(1, 2);
}

以下指令执行详情请参考 https://visualgdb.com/gdbreference/commands/disassemble
本文只列出指令可能的写法

(gdb) disassemble
(gdb) disassemble func
(gdb) disassemble func,+6
(gdb) disassemble func+3,func+7
(gdb) disassemble 0x80483f0
(gdb) disassemble /m func
(gdb) disassemble /r func
(gdb) disassembler $pc  //只显示我们关注的运行指针附近的汇编代码

c++ name mangling解释

先展示一部分代码反汇编的结果示例

disassemble

   0x0000xxxx <+340>:  mov    QWORD PTR [rbp-0x240],rax
   0x0000xxxx <+347>:  call   0x111d7f0 <_ZdlPv@plt>
   0x0000xxxx <+352>:  mov    rax,QWORD PTR [rbp-0x240]
   0x0000xxxx <+359>:  mov    r13,rax
   0x0000xxxx <+362>:  mov    rax,QWORD PTR [rbp-0x228]
   0x0000xxxx <+369>:  test   rax,rax

+347行有 _ZdlPv, 这个符号 是C++ name mangling之后的,demangle之后如下:

c++filt _ZdlPv

[root]$ c++filt _ZdlPv
operator delete(void*)

参考资料 https://blog.csdn.net/qq_33890670/article/details/80270355
name mangling它提供了在函数、结构体、类或其它的数据类型的名字中编码附加信息一种方法,用于从编译器中向链接器传递更多语义信息。
简单来说就是在编译阶段将函数名进行转换,加入域和参数信息,通过这种方式实现重载。

Name mangling的目的就是避免重复,原理就是:找到一种编码方法,使得
1)每一个名称经过转换后,要有唯一的名字;
2)这种编码必须简单,而且要可逆,就是能由全局名称很快的知道局部的名称

在g++下这种编码方式是:
1、所有编码后的符号都由_Z开头
2、如果有作用域符,则在_Z之后加上N
3、接下来是命名空间名字长度+命名空间名字和类名长度+类名
4、函数名字长度+函数名字
5、如果有作用域符,则以E结尾
6、最后加上函数形参符号,int就是i,float就是f,有几个形参就写几个符号

linux可以用 c++filt 命令查看转换之前的函数声明
具体的转换表参考:http://hipercomer.blog.51cto.com/4415661/855223

posted @ 2023-02-15 14:41  流了个火  阅读(1986)  评论(0编辑  收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats