GDB中反汇编的命令是disassemble
,在《使用GDB(二):调试程序常用命令》——反汇编相关操作中有具体介绍,其中也有对GDB常用命令的总结。
如果想要反汇编当前正在执行的函数,可使用:
(gdb) bt
#0 main.max (num1=100, num2=200, ~r0=0)
#1 0x000000000009b95c in main.main ()
(gdb) disassemble // 反汇编 main.max 函数
...
如果想反汇编指定的某个函数,可使用:
(gdb) bt
#0 main.max (num1=100, num2=200, ~r0=0)
#1 0x000000000009b95c in main.main ()
(gdb) disassemble main.main // 反汇编 main.main 函数
...
如果想反汇编某一行源码,可使用:
(gdb) l
22 if (num1 > num2) {
23 result = num1
24 } else {
(gdb) info line 23
Line 23 starts at address 0x9ba5c <main.max+68> and ends at 0x9ba68 <main.max+80>.
(gdb) disassemble 0x9ba5c, 0x9ba68
如果想反汇编指定的某个函数,且让每行源码与反汇编的结果对应,且显示出每条汇编指令的具体值,可使用:
(gdb) disassemble /mr main.main
...
7 var a int = 100
0x000000000009b930 <+40>: 04 90 c1 02 addi.d $r4,$r0,100(0x64)
0x000000000009b934 <+44>: 64 60 c1 29 st.d $r4,$r3,88(0x58)
8 var b int = 200
0x000000000009b938 <+48>: 04 20 c3 02 addi.d $r4,$r0,200(0xc8)
0x000000000009b93c <+52>: 64 40 c1 29 st.d $r4,$r3,80(0x50)
9 var ret int
0x000000000009b940 <+56>: 04 00 15 00 move $r4,$r0
0x000000000009b944 <+60>: 64 20 c1 29 st.d $r4,$r3,72(0x48)
最后还有一个自动反汇编,程序每次一执行,都将执行所在行的源码反汇编,在反汇编相关操作中已经说的很详细了。
这个主要就是借助x
和display
命令,常用的方法就是以下三种。
如果我们现在知道某一处地址中存放的就是机器指令,但是不知道具体的指令是什么且我们还想知道时,可使用:
9 var ret int
0x000000000009b940 <+56>: 04 00 15 00 move $r4,$r0
0x000000000009b944 <+60>: 64 20 c1 29 st.d $r4,$r3,72(0x48)
...
(gdb) x/3i 0x000000000009b944 // 3表示显示该地值后面的三条指令
0x9b944 <main.main+60>: st.d $r4,$r3,72(0x48)
0x9b948 <main.main+64>: ld.d $r4,$r3,80(0x50)
0x9b94c <main.main+68>: ld.d $r5,$r3,88(0x58)
PC寄存器中存放的都是当前将要执行的指令的地址,如果我们想要查看将要执行的指令,可使用:
(gdb) x/i $pc
=> 0x9ba48 <main.max+48>: ld.d $r4,$r3,32(0x20)
如果我们每次执行时都想知道将要执行的指令,可使用:
(gdb) display/i $pc
4: x/i $pc
=> 0x9ba50 <main.max+56>: slt $r4,$r4,$r5
(gdb) si
0x000000000009ba54 22 if (num1 > num2) {
4: x/i $pc
=> 0x9ba54 <main.max+60>: bne $r4,$r0,8(0x8) # 0x9ba5c <main.max+68>
(gdb) si
0x000000000009ba58 22 if (num1 > num2) {
4: x/i $pc
=> 0x9ba58 <main.max+64>: beq $r0,$r0,16(0x10) # 0x9ba68 <main.max+80
如果我们知道指令存放的地址,可以通过上面x/ni
命令很容易反汇编出来具体的指令。但是若我们只知道汇编指令的值,不知道其存放的位置,该怎么将其反汇编呢?
用print/i
是不行的,这玩意不支持。但是咋有办法!
假设下面一堆值就是汇编指令的具体值,一行有4个值,每个值之间用4个空格键分割,总共有5行。
0x00155013 0x0010a9ad 0x13c4c014 0x00494294
0x381c5353 0x28c001ae 0x13c7c014 0x00494294
0x381c5357 0x28c161ce 0x13c56014 0x00494294
0x381c535b 0x11c1e014 0x00494294 0x0010d356
0x4c0001c0 0x0044854c 0x029ffc13 0x00409673
将上面的值存放到一个ass.s
汇编文件中,修改成如下的格式,修改方式非常简单,使用vim替换操作即可。文件中.long
是伪汇编操作,^@
是换行符\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