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