1.6.2 Go语言的反汇编方法

Go语言提供了多种反汇编方法,具体如下。

使用objdump工具实现,命令为“objdump -S Go二进制文件”。

使用gdb的反汇编实现,命令为disassemble/disass。

将Go代码编译成汇编代码,命令为go tool compile。

将Go语言的二进制文件反编译成汇编代码,命令为go tool objdump。

在构建Go程序的同时生成汇编代码文件,命令为go build -gcflags。

在上述反汇编方法中,前两种主要用在操作系统层面,我们常用的是后面三种,下面具体介绍这三种。

1.使用go tool compile命令将Go代码编译成汇编代码

将Go代码编译成汇编代码时,输出的汇编代码没有链接,呈现的地址都是偏移量。go tool compile命令的使用方式如下。

$ go tool compile -N -l -S main.go
"".plan9ExampleFunc STEXT size=80 args=0x0 locals=0x28 funcid=0x0 align=0x0
    0x0000 00000 (main.go:3)  TEXT   "".plan9ExampleFunc(SB), ABIInternal, $40-0
    0x0000 00000 (main.go:3)  CMPQ   SP, 16(R14)
    ...
    0x0024 00036 (main.go:4)  CALL   runtime.newobject(SB)
    ...
"".main STEXT size=86 args=0x0 locals=0x20 funcid=0x0 align=0x0
    0x0000 00000 (main.go:8)  TEXT "".main(SB), ABIInternal, $32-0
    0x0000 00000 (main.go:8)  CMPQ   SP, 16(R14)
    ...
    0x004f 00079 (main.go:8)  CALL   runtime.morestack_noctxt(SB)
    0x0054 00084 (main.go:8)  PCDATA $0, $-1
    0x0054 00084 (main.go:8)  JMP    0

2.使用go tool objdump命令将Go语言的二进制文件反汇编成汇编代码

go tool objdump命令的使用方式如下。

$ go tool objdump main.o
TEXT "".plan9ExampleFunc(SB) gofile..../main.go
  main.go:3   0x723   493b6610    CMPQ 0x10(R14), SP
  ...
  main.go:5   0x76b   c3          RET
  main.go:3   0x76c   e800000000  CALL 0x771   [1:5]R_CALL:runtime.morestack_noctxt
  main.go:3   0x771   ebb0        JMP "".plan9ExampleFunc(SB)
TEXT "".main(SB) gofile...../main.go
  main.go:8   0x773   493b6610    CMPQ 0x10(R14), SP
  ...
  main.go:8   0x7c2   e800000000  CALL 0x7c7   [1:5]R_CALL:runtime.morestack_noctxt
  main.go:8   0x7c7   ebaa        JMP "".main(SB)         

要说明的是,反编译Go二进制文件成汇编代码时会丢失很多信息。

3.在构建Go程序的同时使用go build -gcflags命令生成汇编代码

go build -gcflags命令的使用方式如下。

$ go build -gcflags -S main.go
"".plan9ExampleFunc STEXT size=61 args=0x0 locals=0x18 funcid=0x0 align=0x0
       0x0000 00000 (..../main.go:3)   TEXT   "".plan9ExampleFunc(SB), ABIInternal, $24-0
       0x0000 00000 (..../main.go:3)    CMPQ   SP, 16(R14)
       ...
       0x0036 00054 (..../main.go:3)    CALL   runtime.morestack_noctxt(SB)
       0x003b 00059 (..../main.go:3)    PCDATA  $0, $-1
       0x003b 00059 (..../main.go:3)    JMP    0
 
"".main STEXT size=66 args=0x0 locals=0x10 funcid=0x0 align=0x0
       0x0000 00000 (..../main.go:8)    TEXT   "".main(SB), ABIInternal, $16-0
       0x0000 00000 (..../main.go:8)    CMPQ   SP, 16(R14)
       ...
       0x0040 00064 (..../main.go:8)    JMP    0

也可以使用上述命令查看某个具体的函数。

$ go build -gcflags '-l' -o main main.go
$ go tool objdump -s "main\.plan9ExampleFunc" main
TEXT main.plan9ExampleFunc(SB) ..../main.go
main.go:3    0x1053f60      493b6610CMPQ 0x10(R14), SP
...
main.go:3    0x1053f96      e865d0ffff     CALL runtime.morestack_noctxt.abi0(SB)
main.go:3    0x1053f9b      ebc3    JMP main.plan9ExampleFunc(SB)   

小技巧:命令go build -gcflags -S用于生成正在处理的汇编代码,命令go tool objdump则用于生成最终机器码的汇编代码。