go调试工具

go调试工具

1 概念

Delve是一个用于Go程序的源码级调试器,通过控制程序的执行与你的程序互动,评估变量,并提供线程/goroutine状态、CPU寄存器状态等信息,目标是为调试Go程序提供一个简单而强大的接口。

使用方法:

dlv [command]

可用的命令:
  attach    连接到正在运行的进程并开始调试。
  connect   连接到一个无头调试服务器。
  core      检查一个核心转储。
  dap       [EXPERIMENTAL] 启动一个通过Debug Adaptor Protocol (DAP)通信的TCP服务器。
  debug     编译并开始调试当前目录下的主包,或指定的包。
  exec      执行一个预编译的二进制文件,并开始调试会话。
  help      关于任何命令的帮助
  run       已废弃的命令。使用'debug'代替。
  test      编译测试二进制文件并开始调试程序。
  trace     编译并开始追踪程序。
  version   打印版本。

可用标志:
      --accept-multiclient 允许无头服务器接受多个客户端连接。
      --api-version int 选择无头时的API版本。(默认为1)
      --backend string 后台选择(见'dlv help backend')。(默认为 "default")
      --build-flags string 构建标志,将被传递给编译器。
      --check-go-version 检查正在使用的Go的版本是否与Delve兼容。(默认为true)
      --headless 只运行调试服务器,在无头模式下。
      --init string 启动文件,由终端客户端执行。
  -l, --listen string 调试服务器监听地址。(默认为 "127.0.0.1:0")
      --log 启用调试服务器的日志记录。
      --log-dest string 将日志写到指定的文件或文件描述符(见'dlv help log')。
      --log-output string 逗号分隔的应该产生调试输出的组件列表(见'dlv help log')
      --only-same-user 只允许启动这个Delve实例的同一个用户的连接。(默认为true)
      --wd string 运行程序的工作目录。(默认为".")



2 debug和exec命令

使用debug命令是从源码编译成二进制后进入调试会话,在本地目录下编译出来的__debug_bin临时文件,结束调试会话会自动删除临时文件__debug_bin,debug命令进入调试会话:

dlv debug –check-go-version=false

使用exec命令指定编译后的二进制文件进入调试会话,也就是比debug少了编译过程,exec 命令进入调试交互会话:

dlv exec <binary file> –check-go-version=false


调试会话命令说明:

运行程序命令:
    call ------------------------ 恢复进程,注入一个函数调用(实验性的!!)。
    continue (alias: c) --------- 运行到断点或程序终止。
    next (alias: n) ------------- 跨越到下一个源代码行。
    restart (alias: r) ---------- 重新启动程序。
    step (alias: s) ------------- 单个程序的步骤。
    step-instruction (alias: si)  单步执行一条cpu指令。
    stepout (alias: so) --------- 走出当前函数。

操纵断点命令:
    break (alias: b) ------- 设置一个断点。
    breakpoints (alias: bp)  打印出活动断点的信息。
    clear ------------------ 删除断点。
    clearall --------------- 删除多个断点。
    condition (alias: cond)  设置断点条件。
    on --------------------- 当断点被击中时,执行一条命令。
    trace (alias: t) ------- 设置跟踪点。

查看程序变量和内存命令:
    args ----------------- 打印函数参数。
    display -------------- 每次程序停止时打印表达式的值。
    examinemem (alias: x)  检查内存。
    locals --------------- 打印本地变量。
    print (alias: p) ----- 评估一个表达式。
    regs ----------------- 打印CPU寄存器的内容。
    set ------------------ 改变一个变量的值。
    vars ----------------- 打印软件包变量。
    whatis --------------- 打印一个表达式的类型。

列出并在线程和goroutine之间切换命令:
    goroutine (alias: gr) -- 显示或改变当前的goroutine
    goroutines (alias: grs)  列出程序的goroutine。
    thread (alias: tr) ----- 切换到指定的线程。
    threads ---------------- 打印出每个被追踪的线程的信息。

查看调用栈和选择帧命令:
    deferred --------- 在一个延迟调用的背景下执行命令。
    down ------------- 将当前帧向下移动。
    frame ------------ 设置当前帧,或在不同的帧上执行命令。
    stack (alias: bt)  打印堆栈跟踪。
    up --------------- 将当前帧向上移动。

其他命令:
    config --------------------- 更改配置参数。
    disassemble (alias: disass)  反汇编程序。
    edit (alias: ed) ----------- 打开你在$DELVE_EDITOR或$EDITOR中的位置
    exit (alias: quit | q) ----- 退出调试器。
    funcs ---------------------- 打印函数的列表。
    help (alias: h) ------------ 打印帮助信息。
    libraries ------------------ 列出加载的动态库
    list (alias: ls | l) ------- 显示源代码。
    source --------------------- 执行一个包含delve命令列表的文件
    sources -------------------- 打印源文件的列表。
    types ---------------------- 打印类型列表


3 简单调试示例

文件列表

.
├── cal
│   └── cal.go
└── main.go


main.go代码

package main

import (
        "demo/calculators/cal"
        "fmt"
    "time"
)

func main() {
        v := cal.Cal{12, 3}

        go func() {
                time.Sleep(time.Minute)
        }()

        fmt.Println(v.Add())
        fmt.Println(v.Sub())
        fmt.Println(v.Mul())
        fmt.Println(v.Div())

    time.Sleep(time.Second * 5)
}


cal.go代码

package cal

type Cal struct {
        X1 int
        X2 int
}

func (c *Cal)Add() int {
        return c.X1 +c.X2
}
func (c *Cal)Sub() int {
        return c.X1 -c.X2
}

func (c *Cal)Mul() int {
        return c.X1 *c.X2
}

func (c *Cal)Div() int {
        return c.X1 / c.X2
}


进入调试会话

dlv debug main.go

(1) 打断点

Type 'help' for list of commands.
(dlv) b main.main
Breakpoint 1 set at 0x494b2f for main.main() ./main.go:9
(dlv) b main.go:16
Breakpoint 2 set at 0x494b6c for main.main() ./main.go:16
(dlv) b main.go:17
Breakpoint 3 set at 0x494bff for main.main() ./main.go:17
(dlv) b main.go:18
Breakpoint 4 set at 0x494c90 for main.main() ./main.go:18
(dlv) b main.go:19
Breakpoint 5 set at 0x494d25 for main.main() ./main.go:19

查看断点列表

(dlv) bp
Breakpoint runtime-fatal-throw at 0x432f00 for runtime.fatalthrow() /usr/local/go/src/runtime/panic.go:1244 (0)
Breakpoint unrecovered-panic at 0x433000 for runtime.fatalpanic() /usr/local/go/src/runtime/panic.go:1271 (0)
        print runtime.curg._panic.arg
Breakpoint 1 at 0x494b2f for main.main() ./main.go:9 (0)
Breakpoint 2 at 0x494b6c for main.main() ./main.go:16 (0)
Breakpoint 3 at 0x494bff for main.main() ./main.go:17 (0)
Breakpoint 4 at 0x494c90 for main.main() ./main.go:18 (0)
Breakpoint 5 at 0x494d25 for main.main() ./main.go:19 (0)

清除断点使用 clearall命令


(2) 执行到断点或结束位置

(dlv) c
> main.main() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x494b2f)
     4:         "demo/calculators/cal"
     5:         "fmt"
     6:     "time"
     7: )
     8:
=>   9: func main() {
    10:         v := cal.Cal{12, 3}
    11:
    12:         go func() {
    13:                 time.Sleep(time.Minute)
    14:         }()


(3) 执行下一个代码行

(dlv) n
> main.main() ./main.go:12 (PC: 0x494b5e)
     7: )
     8:
     9: func main() {
    10:         v := cal.Cal{12, 3}
    11:
=>  12:         go func() {
    13:                 time.Sleep(time.Minute)
    14:         }()
    15:
    16:         fmt.Println(v.Add())
    17:         fmt.Println(v.Sub())


(4) 查看和修改变量

(dlv) locals
v = demo/calculators/cal.Cal {X1: 12, X2: 3}

(dlv) set v.X2=4

(dlv) locals
v = demo/calculators/cal.Cal {X1: 12, X2: 4}

(dlv) print v
demo/calculators/cal.Cal {X1: 12, X2: 4}


(5) 查看调用栈信息

(dlv) bt
0  0x0000000000494bff in main.main
   at ./main.go:17
1  0x0000000000435273 in runtime.main
   at /usr/local/go/src/runtime/proc.go:255
2  0x000000000045f961 in runtime.goexit
   at /usr/local/go/src/runtime/asm_amd64.s:1581


(5) 查看goroutine

# 当前goroutine
(dlv) goroutine
Thread 67537 at ./main.go:16
Goroutine 1:
        Runtime: ./main.go:16 main.main (0x494b6c)
        User: ./main.go:16 main.main (0x494b6c)
        Go: <autogenerated>:1 runtime.newproc (0x461e29)
        Start: /usr/local/go/src/runtime/proc.go:145 runtime.main (0x435080)

# 所有goroutine
(dlv) goroutines
* Goroutine 1 - User: ./main.go:16 main.main (0x494b6c) (thread 67537)
  Goroutine 2 - User: /usr/local/go/src/runtime/proc.go:367 runtime.gopark (0x435692)
  Goroutine 3 - User: /usr/local/go/src/runtime/proc.go:367 runtime.gopark (0x435692)
  Goroutine 4 - User: /usr/local/go/src/runtime/proc.go:367 runtime.gopark (0x435692)
  Goroutine 5 - User: /usr/local/go/src/runtime/proc.go:367 runtime.gopark (0x435692)
  Goroutine 6 - User: ./main.go:12 main.main.func1 (0x494e00)
[6 goroutines]


(6) 打印每个被追踪的线程的信息

(dlv) threads
* Thread 67537 at 0x494b6c ./main.go:16 main.main
  Thread 67667 at 0x46119d /usr/local/go/src/runtime/sys_linux_amd64.s:146 runtime.usleep
  Thread 67668 at 0x46119d /usr/local/go/src/runtime/sys_linux_amd64.s:146 runtime.usleep
  Thread 67669 at 0x461723 /usr/local/go/src/runtime/sys_linux_amd64.s:520 runtime.futex
  Thread 67670 at 0x461723 /usr/local/go/src/runtime/sys_linux_amd64.s:520 runtime.futex


(7) 反汇编

(dlv) disassemble
TEXT main.main(SB) /home/vison/work/golang/project/src/demo/calculators/main.go
        main.go:9       0x494b20        4c8d642498                      lea r12, ptr [rsp-0x68]
        main.go:9       0x494b25        4d3b6610                        cmp r12, qword ptr [r14+0x10]
        main.go:9       0x494b29        0f86a8020000                    jbe 0x494dd7
        main.go:9       0x494b2f*       4881ece8000000                  sub rsp, 0xe8
        main.go:9       0x494b36        4889ac24e0000000                mov qword ptr [rsp+0xe0], rbp
        main.go:9       0x494b3e        488dac24e0000000                lea rbp, ptr [rsp+0xe0]
        main.go:10      0x494b46        440f117c2420                    movups xmmword ptr [rsp+0x20], xmm15
        main.go:10      0x494b4c        48c74424200c000000              mov qword ptr [rsp+0x20], 0xc
        main.go:10      0x494b55        48c744242803000000              mov qword ptr [rsp+0x28], 0x3
        main.go:12      0x494b5e        31c0                            xor eax, eax
        main.go:12      0x494b60        488d1d89dd0100                  lea rbx, ptr [rip+0x1dd89]
        main.go:12      0x494b67        e81484faff                      call $runtime.newproc
=>      main.go:16      0x494b6c*       488d442420                      lea rax, ptr [rsp+0x20]
        main.go:16      0x494b71        e80ae5fcff                      call $demo/calculators/cal.(*Cal).Add
        main.go:16      0x494b76        4889442418                      mov qword ptr [rsp+0x18], rax
        main.go:16      0x494b7b        440f117c2470                    movups xmmword ptr [rsp+0x70], xmm15
        main.go:16      0x494b81        488d4c2470                      lea rcx, ptr [rsp+0x70]
        main.go:16      0x494b86        48894c2448                      mov qword ptr [rsp+0x48], rcx
        main.go:16      0x494b8b        488b442418                      mov rax, qword ptr [rsp+0x18]
        main.go:16      0x494b90        e80b52f7ff                      call $runtime.convT64
        main.go:16      0x494b95        4889442440                      mov qword ptr [rsp+0x40], rax
        main.go:16      0x494b9a        488b4c2448                      mov rcx, qword ptr [rsp+0x48]
        main.go:16      0x494b9f        8401                            test byte ptr [rcx], al
        main.go:16      0x494ba1        488d15f86d0000                  lea rdx, ptr [rip+0x6df8]
        main.go:16      0x494ba8        488911                          mov qword ptr [rcx], rdx
        main.go:16      0x494bab        488d7908                        lea rdi, ptr [rcx+0x8]
        main.go:16      0x494baf        833deab30c0000                  cmp dword ptr [runtime.writeBarrier], 0x0
        main.go:16      0x494bb6        7402                            jz 0x494bba
        main.go:16      0x494bb8        eb08                            jmp 0x494bc2
        main.go:16      0x494bba        48894108                        mov qword ptr [rcx+0x8], rax
        main.go:16      0x494bbe        6690                            data16 nop
        main.go:16      0x494bc0        eb07                            jmp 0x494bc9
        main.go:16      0x494bc2        e8d9adfcff                      call $runtime.gcWriteBarrier
        main.go:16      0x494bc7        eb00                            jmp 0x494bc9
        main.go:16      0x494bc9        488b442448                      mov rax, qword ptr [rsp+0x48]
        main.go:16      0x494bce        8400                            test byte ptr [rax], al
        main.go:16      0x494bd0        eb00                            jmp 0x494bd2
        main.go:16      0x494bd2        48898424b0000000                mov qword ptr [rsp+0xb0], rax
        main.go:16      0x494bda        48c78424b800000001000000        mov qword ptr [rsp+0xb8], 0x1
        main.go:16      0x494be6        48c78424c000000001000000        mov qword ptr [rsp+0xc0], 0x1
        main.go:16      0x494bf2        bb01000000                      mov ebx, 0x1
        main.go:16      0x494bf7        4889d9                          mov rcx, rbx
        main.go:16      0x494bfa        e8c1a8ffff                      call $fmt.Println
        main.go:17      0x494bff*       488d442420                      lea rax, ptr [rsp+0x20]
        main.go:17      0x494c04        e8b7e4fcff                      call $demo/calculators/cal.(*Cal).Sub
        main.go:17      0x494c09        4889442418                      mov qword ptr [rsp+0x18], rax
        main.go:17      0x494c0e        440f117c2470                    movups xmmword ptr [rsp+0x70], xmm15
        main.go:17      0x494c14        488d542470                      lea rdx, ptr [rsp+0x70]
        main.go:17      0x494c19        4889542438                      mov qword ptr [rsp+0x38], rdx
        main.go:17      0x494c1e        488b442418                      mov rax, qword ptr [rsp+0x18]
        main.go:17      0x494c23        e87851f7ff                      call $runtime.convT64
        main.go:17      0x494c28        4889442430                      mov qword ptr [rsp+0x30], rax
        main.go:17      0x494c2d        488b542438                      mov rdx, qword ptr [rsp+0x38]
        main.go:17      0x494c32        8402                            test byte ptr [rdx], al
        main.go:17      0x494c34        488d35656d0000                  lea rsi, ptr [rip+0x6d65]
        main.go:17      0x494c3b        488932                          mov qword ptr [rdx], rsi
        main.go:17      0x494c3e        488d7a08                        lea rdi, ptr [rdx+0x8]
        main.go:17      0x494c42        833d57b30c0000                  cmp dword ptr [runtime.writeBarrier], 0x0
        main.go:17      0x494c49        7402                            jz 0x494c4d
        main.go:17      0x494c4b        eb06                            jmp 0x494c53
        main.go:17      0x494c4d        48894208                        mov qword ptr [rdx+0x8], rax
        main.go:17      0x494c51        eb07                            jmp 0x494c5a
        main.go:17      0x494c53        e848adfcff                      call $runtime.gcWriteBarrier
        main.go:17      0x494c58        eb00                            jmp 0x494c5a
        main.go:17      0x494c5a        488b442438                      mov rax, qword ptr [rsp+0x38]
        main.go:17      0x494c5f        8400                            test byte ptr [rax], al
        main.go:17      0x494c61        eb00                            jmp 0x494c63
        main.go:17      0x494c63        4889842498000000                mov qword ptr [rsp+0x98], rax
        main.go:17      0x494c6b        48c78424a000000001000000        mov qword ptr [rsp+0xa0], 0x1
        main.go:17      0x494c77        48c78424a800000001000000        mov qword ptr [rsp+0xa8], 0x1
        main.go:17      0x494c83        bb01000000                      mov ebx, 0x1
        main.go:17      0x494c88        4889d9                          mov rcx, rbx
        main.go:17      0x494c8b        e830a8ffff                      call $fmt.Println
        main.go:18      0x494c90*       488d442420                      lea rax, ptr [rsp+0x20]
        main.go:18      0x494c95        e866e4fcff                      call $demo/calculators/cal.(*Cal).Mul
        main.go:18      0x494c9a        4889442418                      mov qword ptr [rsp+0x18], rax
        main.go:18      0x494c9f        440f117c2470                    movups xmmword ptr [rsp+0x70], xmm15
        main.go:18      0x494ca5        488d542470                      lea rdx, ptr [rsp+0x70]
        main.go:18      0x494caa        4889542468                      mov qword ptr [rsp+0x68], rdx
        main.go:18      0x494caf        488b442418                      mov rax, qword ptr [rsp+0x18]
        main.go:18      0x494cb4        e8e750f7ff                      call $runtime.convT64
        main.go:18      0x494cb9        4889442460                      mov qword ptr [rsp+0x60], rax
        main.go:18      0x494cbe        488b542468                      mov rdx, qword ptr [rsp+0x68]
        main.go:18      0x494cc3        8402                            test byte ptr [rdx], al
        main.go:18      0x494cc5        488d35d46c0000                  lea rsi, ptr [rip+0x6cd4]
        main.go:18      0x494ccc        488932                          mov qword ptr [rdx], rsi
        main.go:18      0x494ccf        488d7a08                        lea rdi, ptr [rdx+0x8]
        main.go:18      0x494cd3        833dc6b20c0000                  cmp dword ptr [runtime.writeBarrier], 0x0
        main.go:18      0x494cda        7402                            jz 0x494cde
        main.go:18      0x494cdc        eb06                            jmp 0x494ce4
        main.go:18      0x494cde        48894208                        mov qword ptr [rdx+0x8], rax
        main.go:18      0x494ce2        eb07                            jmp 0x494ceb
        main.go:18      0x494ce4        e8b7acfcff                      call $runtime.gcWriteBarrier
        main.go:18      0x494ce9        eb00                            jmp 0x494ceb
        main.go:18      0x494ceb        488b442468                      mov rax, qword ptr [rsp+0x68]
        main.go:18      0x494cf0        8400                            test byte ptr [rax], al
        main.go:18      0x494cf2        eb00                            jmp 0x494cf4
        main.go:18      0x494cf4        4889842480000000                mov qword ptr [rsp+0x80], rax
        main.go:18      0x494cfc        48c784248800000001000000        mov qword ptr [rsp+0x88], 0x1
        main.go:18      0x494d08        48c784249000000001000000        mov qword ptr [rsp+0x90], 0x1
        main.go:18      0x494d14        bb01000000                      mov ebx, 0x1
        main.go:18      0x494d19        4889d9                          mov rcx, rbx
        main.go:18      0x494d1c        0f1f4000                        nop dword ptr [rax], eax
        main.go:18      0x494d20        e89ba7ffff                      call $fmt.Println
        main.go:19      0x494d25*       488d442420                      lea rax, ptr [rsp+0x20]
        main.go:19      0x494d2a        e831e4fcff                      call $demo/calculators/cal.(*Cal).Div
        main.go:19      0x494d2f        4889442418                      mov qword ptr [rsp+0x18], rax
        main.go:19      0x494d34        440f117c2470                    movups xmmword ptr [rsp+0x70], xmm15
        main.go:19      0x494d3a        488d542470                      lea rdx, ptr [rsp+0x70]
        main.go:19      0x494d3f        4889542458                      mov qword ptr [rsp+0x58], rdx
        main.go:19      0x494d44        488b442418                      mov rax, qword ptr [rsp+0x18]
        main.go:19      0x494d49        e85250f7ff                      call $runtime.convT64
        main.go:19      0x494d4e        4889442450                      mov qword ptr [rsp+0x50], rax
        main.go:19      0x494d53        488b542458                      mov rdx, qword ptr [rsp+0x58]
        main.go:19      0x494d58        8402                            test byte ptr [rdx], al
        main.go:19      0x494d5a        488d353f6c0000                  lea rsi, ptr [rip+0x6c3f]
        main.go:19      0x494d61        488932                          mov qword ptr [rdx], rsi
        main.go:19      0x494d64        488d7a08                        lea rdi, ptr [rdx+0x8]
        main.go:19      0x494d68        833d31b20c0000                  cmp dword ptr [runtime.writeBarrier], 0x0
        main.go:19      0x494d6f        7402                            jz 0x494d73
        main.go:19      0x494d71        eb06                            jmp 0x494d79
        main.go:19      0x494d73        48894208                        mov qword ptr [rdx+0x8], rax
        main.go:19      0x494d77        eb09                            jmp 0x494d82
        main.go:19      0x494d79        e822acfcff                      call $runtime.gcWriteBarrier
        main.go:19      0x494d7e        6690                            data16 nop
        main.go:19      0x494d80        eb00                            jmp 0x494d82
        main.go:19      0x494d82        488b442458                      mov rax, qword ptr [rsp+0x58]
        main.go:19      0x494d87        8400                            test byte ptr [rax], al
        main.go:19      0x494d89        eb00                            jmp 0x494d8b
        main.go:19      0x494d8b        48898424c8000000                mov qword ptr [rsp+0xc8], rax
        main.go:19      0x494d93        48c78424d000000001000000        mov qword ptr [rsp+0xd0], 0x1
        main.go:19      0x494d9f        48c78424d800000001000000        mov qword ptr [rsp+0xd8], 0x1
        main.go:19      0x494dab        bb01000000                      mov ebx, 0x1
        main.go:19      0x494db0        4889d9                          mov rcx, rbx
        main.go:19      0x494db3        e808a7ffff                      call $fmt.Println
        main.go:21      0x494db8        48b800f2052a01000000            mov rax, 0x12a05f200
        main.go:21      0x494dc2        e8997afcff                      call $time.Sleep
        main.go:22      0x494dc7        488bac24e0000000                mov rbp, qword ptr [rsp+0xe0]
        main.go:22      0x494dcf        4881c4e8000000                  add rsp, 0xe8
        main.go:22      0x494dd6        c3                              ret
        main.go:9       0x494dd7        e8048cfcff                      call $runtime.morestack_noctxt
        main.go:9       0x494ddc        0f1f4000                        nop dword ptr [rax], eax
        main.go:9       0x494de0        e93bfdffff                      jmp $main.main


其他命令使用方法使用help查看。



专题「golang相关」的其它文章 »