使用GDB调试程序反汇编方法

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

上一篇:JAVA修饰符类型(public,protected,private,friendly)


下一篇:使用gdb调试C++程序