使用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>:
处开始比较的。