使用GDB调试程序的时候经常会遇到这样的情况,键入s
或者c
命令,进入某个函数,然后键入l
命令想看这个函数的代码,发现无法查看,但是在这个函数的内部,又发生了错误,此时我们就想到了利用反汇编disassemble
命令查看汇编代码:
(gdb) c
Breakpoint 2, 0x000000012003b020 in lj_BC_JLOOP ()
(gdb) l
570 }
571
572 int main(int argc, char **argv)
573 {
574 int status;
575 lua_State *L = lua_open();
576 if (L == NULL) {
577 l_message(argv[0], "cannot create state: not enough memory");
578 return EXIT_FAILURE;
579 }
(gdb) bt
#0 0x000000012003b020 in lj_BC_JLOOP ()
Backtrace stopped: Cannot access memory at address 0x8a
(gdb) disassemble
Dump of assembler code for function lj_BC_JLOOP:
0x000000012003b00c <+0>: addu16i.d $r20,$r0,-2856(0xf4d8)
0x000000012003b010 <+4>: srai.d $r20,$r20,0x10
0x000000012003b014 <+8>: ldx.d $r13,$r26,$r20
0x000000012003b018 <+12>: addu16i.d $r20,$r0,0
0x000000012003b01c <+16>: srai.d $r20,$r20,0x10
=> 0x000000012003b020 <+20>: or $r19,$r0,$r20
0x000000012003b024 <+24>: add.d $r13,$r13,$r10
0x000000012003b028 <+28>: addu16i.d $r20,$r0,-3792(0xf130)
0x000000012003b02c <+32>: srai.d $r20,$r20,0x10
0x000000012003b030 <+36>: stx.d $r19,$r26,$r20
0x000000012003b034 <+40>: ld.d $r14,$r13,0
0x000000012003b038 <+44>: addu16i.d $r20,$r0,-3600(0xf1f0)
0x000000012003b03c <+48>: srai.d $r20,$r20,0x10
0x000000012003b040 <+52>: stx.d $r23,$r26,$r20
0x000000012003b044 <+56>: ld.d $r14,$r14,88(0x58)
0x000000012003b048 <+60>: addu16i.d $r20,$r0,-3752(0xf158)
0x000000012003b04c <+64>: srai.d $r20,$r20,0x10
0x000000012003b050 <+68>: stx.d $r27,$r26,$r20
0x000000012003b054 <+72>: addu16i.d $r20,$r0,28792(0x7078)
0x000000012003b058 <+76>: srai.d $r20,$r20,0x10
0x000000012003b05c <+80>: add.d $r22,$r26,$r20
0x000000012003b060 <+84>: jirl $r0,$r14,0
End of assembler dump.
(gdb)
除了使用disassemble
命令,还可以取出程序PC所指代码段的那一块内存中的值,再对其反汇编生成汇编代码。首先由下面信息可知,当前PC值为0x000000012003b020
。
(gdb) c
Breakpoint 2, 0x000000012003b020 in lj_BC_JLOOP ()
(gdb) bt
#0 0x000000012003b020 in lj_BC_JLOOP ()
查看内存0x000000012003b020
周围存放的内容,x /20xw 0x000000012003b020
命令是从0x000000012003b020
处开始向后查找20个单位内存中的值,以十六进制显示,每个单位的长度是一个字(4字节)。
(gdb) x /20xw 0x000000012003b020
0x12003b020 <lj_BC_JLOOP+20>: 0x00155013 0x0010a9ad 0x13c4c014 0x00494294
0x12003b030 <lj_BC_JLOOP+36>: 0x381c5353 0x28c001ae 0x13c7c014 0x00494294
0x12003b040 <lj_BC_JLOOP+52>: 0x381c5357 0x28c161ce 0x13c56014 0x00494294
0x12003b050 <lj_BC_JLOOP+68>: 0x381c535b 0x11c1e014 0x00494294 0x0010d356
0x12003b060 <lj_BC_JLOOP+84>: 0x4c0001c0 0x0044854c 0x029ffc13 0x00409673
将上面查到的值存放到一个.s
汇编文件中,修改格式,去掉没有用的内容,^@
是换行符\n
。
.long 0x00155013^@.long 0x0010a9ad^@.long 0x13c4c014^@.long 0x00494294
.long 0x381c5353^@.long 0x28c001ae^@.long 0x13c7c014^@.long 0x00494294
.long 0x381c5357^@.long 0x28c161ce^@.long 0x13c56014^@.long 0x00494294
.long 0x381c535b^@.long 0x11c1e014^@.long 0x00494294^@.long 0x0010d356
.long 0x4c0001c0^@.long 0x0044854c^@.long 0x029ffc13^@.long 0x00409673
然后再对汇编文件进行汇编,汇编完后生成一个.o
文件,最后再对.o
文件反汇编:
[loongson@localhost workfile]$ vim ass.s
[loongson@localhost workfile]$ gcc -c ass.s -o ass.o
[loongson@localhost workfile]$ objdump -d ass.o
ass.o: 文件格式 elf64-loongarch
Disassembly of section .text:
0000000000000000 <.text>:
0: 00155013 or $r19,$r0,$r20
4: 0010a9ad add.d $r13,$r13,$r10
8: 13c4c014 addu16i.d $r20,$r0,-3792(0xf130)
c: 00494294 srai.d $r20,$r20,0x10
10: 381c5353 stx.d $r19,$r26,$r20
14: 28c001ae ld.d $r14,$r13,0
18: 13c7c014 addu16i.d $r20,$r0,-3600(0xf1f0)
1c: 00494294 srai.d $r20,$r20,0x10
20: 381c5357 stx.d $r23,$r26,$r20
24: 28c161ce ld.d $r14,$r14,88(0x58)
28: 13c56014 addu16i.d $r20,$r0,-3752(0xf158)
2c: 00494294 srai.d $r20,$r20,0x10
30: 381c535b stx.d $r27,$r26,$r20
34: 11c1e014 addu16i.d $r20,$r0,28792(0x7078)
38: 00494294 srai.d $r20,$r20,0x10
3c: 0010d356 add.d $r22,$r26,$r20
40: 4c0001c0 jirl $r0,$r14,0
44: 0044854c srli.w $r12,$r10,0x1
48: 029ffc13 addi.w $r19,$r0,2047(0x7ff)
4c: 00409673 slli.w $r19,$r19,0x5
将第二次反汇编生成的汇编代码和第一次生成的汇编代码比较,两次内容完全一样。比较的时候注意位置,是从第一次的=> 0x000000012003b020 <+20>:
处开始比较的。