gcc objdump 汇编调试
gcc objdump assembly debugging
我正在尝试将 C 代码更改为汇编代码。
起初,我使用gcc和objdump函数从c代码中提取汇编代码。
C 代码只是简单的 printf 代码。
#include <stdio.h>
int main(){
printf("this\n");
return 0;
}
gcc -c -S -O0 test.c
objdump -dS test.o > test.txt
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov [=10=]x0,%edi
9: e8 00 00 00 00 callq e <main+0xe>
e: b8 00 00 00 00 mov [=10=]x0,%eax
13: 5d pop %rbp
14: c3 retq
在此汇编代码中,
我很好奇为什么 callq 指令的目的地是 e
所以我 运行 gdb 中的这段代码使用
disas main
(gdb) disas main
Dump of assembler code for function main:
0x0000000000400526 <+0>: push %rbp
0x0000000000400527 <+1>: mov %rsp,%rbp
0x000000000040052a <+4>: mov [=11=]x4005c4,%edi
0x000000000040052f <+9>: callq 0x400400 <puts@plt>
0x0000000000400534 <+14>: mov [=11=]x0,%eax
0x0000000000400539 <+19>: pop %rbp
0x000000000040053a <+20>: retq
在这段代码中,我假定 0x400400 是 printf 函数的地址。
为什么objdump和gdb的汇编代码显示不同的结果?
如何使 objdump 结果显示正确的 callq 目的地?
当您 运行 使用 objdump
命令时,您不是在反汇编最终的可执行文件,而是在反汇编编译器 (test.o
) 生成的目标文件。我对你执行了类似的步骤(使用你的代码)(在 GDB 中编译和 运行ning objdump
和 dissas
)除了我在链接的可执行文件 [=25] 上执行了 objdump
=]not 在目标文件上(这意味着我没有使用 -c
标志进行编译)。输出如下:
objdump -dS a.out:
1140: 55 push %rbp
1141: 48 89 e5 mov %rsp,%rbp
1144: 48 83 ec 10 sub [=10=]x10,%rsp
1148: 48 8d 3d b5 0e 00 00 lea 0xeb5(%rip),%rdi # 2004 <_IO_stdin_used+0x4>
114f: c7 45 fc 00 00 00 00 movl [=10=]x0,-0x4(%rbp)
1156: b0 00 mov [=10=]x0,%al
1158: e8 d3 fe ff ff callq 1030 <printf@plt>
115d: 31 c9 xor %ecx,%ecx
115f: 89 45 f8 mov %eax,-0x8(%rbp)
1162: 89 c8 mov %ecx,%eax
1164: 48 83 c4 10 add [=10=]x10,%rsp
1168: 5d pop %rbp
1169: c3 retq
116a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
GDB:
(gdb) disas main
Dump of assembler code for function main:
0x0000000000001140 <+0>: push %rbp
0x0000000000001141 <+1>: mov %rsp,%rbp
0x0000000000001144 <+4>: sub [=11=]x10,%rsp
0x0000000000001148 <+8>: lea 0xeb5(%rip),%rdi # 0x2004
0x000000000000114f <+15>: movl [=11=]x0,-0x4(%rbp)
0x0000000000001156 <+22>: mov [=11=]x0,%al
0x0000000000001158 <+24>: callq 0x1030 <printf@plt>
0x000000000000115d <+29>: xor %ecx,%ecx
0x000000000000115f <+31>: mov %eax,-0x8(%rbp)
0x0000000000001162 <+34>: mov %ecx,%eax
0x0000000000001164 <+36>: add [=11=]x10,%rsp
0x0000000000001168 <+40>: pop %rbp
0x0000000000001169 <+41>: retq
End of assembler dump.
如您所见,这两个反汇编是相同的,除了一些细微的语法差异(例如,GDB 在其地址前加上 0x
前缀)。
默认情况下 objdump
缺少的是重定位。
运行 objdump
和 -r
标志让你看到这些。例如
objdump -Sr foo.o
foo.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov [=10=]x0,%edi
5: R_X86_64_32 .rodata
9: e8 00 00 00 00 callq e <main+0xe>
a: R_X86_64_PC32 puts-0x4
e: b8 00 00 00 00 mov [=10=]x0,%eax
13: 5d pop %rbp
14: c3 retq
向我们展示调用将使用 PC 相对地址,指向 puts
我正在尝试将 C 代码更改为汇编代码。
起初,我使用gcc和objdump函数从c代码中提取汇编代码。
C 代码只是简单的 printf 代码。
#include <stdio.h>
int main(){
printf("this\n");
return 0;
}
gcc -c -S -O0 test.c
objdump -dS test.o > test.txt
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov [=10=]x0,%edi
9: e8 00 00 00 00 callq e <main+0xe>
e: b8 00 00 00 00 mov [=10=]x0,%eax
13: 5d pop %rbp
14: c3 retq
在此汇编代码中, 我很好奇为什么 callq 指令的目的地是 e
所以我 运行 gdb 中的这段代码使用
disas main
(gdb) disas main
Dump of assembler code for function main:
0x0000000000400526 <+0>: push %rbp
0x0000000000400527 <+1>: mov %rsp,%rbp
0x000000000040052a <+4>: mov [=11=]x4005c4,%edi
0x000000000040052f <+9>: callq 0x400400 <puts@plt>
0x0000000000400534 <+14>: mov [=11=]x0,%eax
0x0000000000400539 <+19>: pop %rbp
0x000000000040053a <+20>: retq
在这段代码中,我假定 0x400400 是 printf 函数的地址。
为什么objdump和gdb的汇编代码显示不同的结果?
如何使 objdump 结果显示正确的 callq 目的地?
当您 运行 使用 objdump
命令时,您不是在反汇编最终的可执行文件,而是在反汇编编译器 (test.o
) 生成的目标文件。我对你执行了类似的步骤(使用你的代码)(在 GDB 中编译和 运行ning objdump
和 dissas
)除了我在链接的可执行文件 [=25] 上执行了 objdump
=]not 在目标文件上(这意味着我没有使用 -c
标志进行编译)。输出如下:
objdump -dS a.out:
1140: 55 push %rbp
1141: 48 89 e5 mov %rsp,%rbp
1144: 48 83 ec 10 sub [=10=]x10,%rsp
1148: 48 8d 3d b5 0e 00 00 lea 0xeb5(%rip),%rdi # 2004 <_IO_stdin_used+0x4>
114f: c7 45 fc 00 00 00 00 movl [=10=]x0,-0x4(%rbp)
1156: b0 00 mov [=10=]x0,%al
1158: e8 d3 fe ff ff callq 1030 <printf@plt>
115d: 31 c9 xor %ecx,%ecx
115f: 89 45 f8 mov %eax,-0x8(%rbp)
1162: 89 c8 mov %ecx,%eax
1164: 48 83 c4 10 add [=10=]x10,%rsp
1168: 5d pop %rbp
1169: c3 retq
116a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
GDB:
(gdb) disas main
Dump of assembler code for function main:
0x0000000000001140 <+0>: push %rbp
0x0000000000001141 <+1>: mov %rsp,%rbp
0x0000000000001144 <+4>: sub [=11=]x10,%rsp
0x0000000000001148 <+8>: lea 0xeb5(%rip),%rdi # 0x2004
0x000000000000114f <+15>: movl [=11=]x0,-0x4(%rbp)
0x0000000000001156 <+22>: mov [=11=]x0,%al
0x0000000000001158 <+24>: callq 0x1030 <printf@plt>
0x000000000000115d <+29>: xor %ecx,%ecx
0x000000000000115f <+31>: mov %eax,-0x8(%rbp)
0x0000000000001162 <+34>: mov %ecx,%eax
0x0000000000001164 <+36>: add [=11=]x10,%rsp
0x0000000000001168 <+40>: pop %rbp
0x0000000000001169 <+41>: retq
End of assembler dump.
如您所见,这两个反汇编是相同的,除了一些细微的语法差异(例如,GDB 在其地址前加上 0x
前缀)。
默认情况下 objdump
缺少的是重定位。
运行 objdump
和 -r
标志让你看到这些。例如
objdump -Sr foo.o
foo.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov [=10=]x0,%edi
5: R_X86_64_32 .rodata
9: e8 00 00 00 00 callq e <main+0xe>
a: R_X86_64_PC32 puts-0x4
e: b8 00 00 00 00 mov [=10=]x0,%eax
13: 5d pop %rbp
14: c3 retq
向我们展示调用将使用 PC 相对地址,指向 puts