dlv go调试
dlv模式的几种方式
1、dlv attach pid
2、dlv run|debug run命令已被debug命令取代,运行dlv debug test.go会先编译go源文件,同时执行attach命令进入调试模式,该命令会在当前目录下生成一个名为debug的可执行二进制文件,退出调试模式会自动被删除。
3、 dlv exec executable_file:直接从二进制文件启动调试模式。
4、 dlv core executable_file core_file:以core文件启动调试,通常进行dlv的目的就是为了找出可执行文件core的原因,通过core文件可直接找出具体进程异常的信息。
5、dlv trace:该命令最直接的用途是可以追踪代码里函数的调用轨迹,可通过help查看其调用方式。
dlv trace main.go Test
dlv help
(dlv) help
The following commands are available:
Running the program:
call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!)
continue (alias: c) --------- Run until breakpoint or program termination.
next (alias: n) ------------- Step over to next source line.
rebuild --------------------- Rebuild the target executable and restarts it. It does not work if the executable was not built by delve.
restart (alias: r) ---------- Restart process.
step (alias: s) ------------- Single step through program.
step-instruction (alias: si) Single step a single cpu instruction.
stepout (alias: so) --------- Step out of the current function.
Manipulating breakpoints:
break (alias: b) ------- Sets a breakpoint.
breakpoints (alias: bp) Print out info for active breakpoints.
clear ------------------ Deletes breakpoint.
clearall --------------- Deletes multiple breakpoints.
condition (alias: cond) Set breakpoint condition.
on --------------------- Executes a command when a breakpoint is hit.
toggle ----------------- Toggles on or off a breakpoint.
trace (alias: t) ------- Set tracepoint.
watch ------------------ Set watchpoint.
Viewing program variables and memory:
args ----------------- Print function arguments.
display -------------- Print value of an expression every time the program stops.
examinemem (alias: x) Examine raw memory at the given address.
locals --------------- Print local variables.
print (alias: p) ----- Evaluate an expression.
regs ----------------- Print contents of CPU registers.
set ------------------ Changes the value of a variable.
vars ----------------- Print package variables.
whatis --------------- Prints type of an expression.
Listing and switching between threads and goroutines:
goroutine (alias: gr) -- Shows or changes current goroutine
goroutines (alias: grs) List program goroutines.
thread (alias: tr) ----- Switch to the specified thread.
threads ---------------- Print out info for every traced thread.
Viewing the call stack and selecting frames:
deferred --------- Executes command in the context of a deferred call.
down ------------- Move the current frame down.
frame ------------ Set the current frame, or execute command on a different frame.
stack (alias: bt) Print stack trace.
up --------------- Move the current frame up.
Other commands:
config --------------------- Changes configuration parameters.
disassemble (alias: disass) Disassembler.
dump ----------------------- Creates a core dump from the current process state
edit (alias: ed) ----------- Open where you are in $DELVE_EDITOR or $EDITOR
exit (alias: quit | q) ----- Exit the debugger.
funcs ---------------------- Print list of functions.
help (alias: h) ------------ Prints the help message.
libraries ------------------ List loaded dynamic libraries
list (alias: ls | l) ------- Show source code.
source --------------------- Executes a file containing a list of delve commands
sources -------------------- Print list of source files.
transcript ----------------- Appends command output to a file.
types ---------------------- Print list of types
Type help followed by a command for full documentation.
常用的指令
设置断点
b test main.go:11
查看所有断点
(dlv) bp
Breakpoint runtime-fatal-throw (enabled) at 0x4366c0 for runtime.throw() c:/program files/go/src/runtime/panic.go:1188 (0)
Breakpoint unrecovered-panic (enabled) at 0x436a20 for runtime.fatalpanic() c:/program files/go/src/runtime/panic.go:1271 (0)
print runtime.curg._panic.arg
Breakpoint 1 (enabled) at 0x4b65b4 for main.Bar() d:/go/src/demo/string/main.go:9 (1)
Breakpoint 2 (enabled) at 0x4b6606 for main.Bar() d:/go/src/demo/string/main.go:11 (1)
在断点处加打印
on 1 p name
删除断点
clear 1
clearall
list:打印当前断点位置的源代码,list后面加行号可以展示该行附近的源代码,如list test.go:10将会展示test.go文件第10行附近的代码,值得注意的是该行必须是代码行而不能是空行。
list main.go:18
condition :有条件的中断断点,当expression为true时指定的断点将被中断,程序将继续执行。
conditon 2 a==105
# 断点2在a==105条件下中断
toggle:打开或者关闭一个断点
toggle 2
next|step:逐行执行代码,区别和gdb类似,next遇到函数调用时不会进入该函数,step则会进入函数,如果需要查看函数的具体执行过程则用step,否则用next
locals:查看局部变量
11: func main() {
12:
13: var a = 100
14: for i := 0; i < 3; i++ {
15: a++
=> 16: Print(i)
17: }
18: }
(dlv) locals
a = 103
i = 2
(dlv) locals a
a = 103
args:查看函数参数
4:
=> 5: func Print(i int) {
6: fmt.Println(i)
7: }
8:
(dlv) args
i = 2
(dlv) args i
i = 2
bt:打印栈信息
(dlv) bt
0 0x00000000004a2c7f in main.main
at d:/go/src/demo/string/main.go:22
1 0x00000000004384d7 in runtime.main
at c:/program files/go/src/runtime/proc.go:255
2 0x00000000004605a1 in runtime.goexit
at c:/program files/go/src/runtime/asm_amd64.s:1581
frame:切换栈
frame 0
regs:打印寄存器内容
(dlv) regs
Rip = 0x00000000004a2bd4
Rsp = 0x000000c00007be90
Rax = 0x0000000000000004
Rbx = 0x0000000000000000
Rcx = 0x0000000000000000
Rdx = 0x0000000000000004
Rsi = 0x000000c000022b60
Rdi = 0x000000c00007e008
Rbp = 0x000000c00007bed8
R8 = 0x0000000000000000
R9 = 0x0000000000000004
R10 = 0x0000000000000000
R11 = 0x0000000000000004
goroutines:打印goroutines
func Fuc(value int, wg *sync.WaitGroup) {
fmt.Println(value)
wg.Done()
}
func main() {
wg := sync.WaitGroup{}
for i := 0; i < 10; i++ {
wg.Add(1)
go Fuc(i, &wg)
}
wg.Wait()
fmt.Println("finish")
}
(dlv) goroutines
Goroutine 1 - User: d:/go/src/demo/string/main.go:28 main.main (0x4a30b8) (thread 6764)
Goroutine 2 - User: c:/program files/go/src/runtime/proc.go:367 runtime.gopark (0x4388d2) [force gc (idle)]
Goroutine 3 - User: c:/program files/go/src/runtime/proc.go:367 runtime.gopark (0x4388d2) [GC sweep wait]
Goroutine 4 - User: c:/program files/go/src/runtime/proc.go:367 runtime.gopark (0x4388d2) [GC scavenge wait]
Goroutine 5 - User: c:/program files/go/src/runtime/proc.go:367 runtime.gopark (0x4388d2) [finalizer wait]
* Goroutine 6 - User: d:/go/src/demo/string/main.go:20 main.Fuc (0x4a2f22) (thread 11840)
Goroutine 7 - User: d:/go/src/demo/string/main.go:28 main.main·dwrap·1 (0x4a3140)
Goroutine 8 - User: d:/go/src/demo/string/main.go:28 main.main·dwrap·1 (0x4a3140)
[8 goroutines]
goroutine:协程切换。dlv默认会一直在主协程上执,为打印Func函数中的临时变量a,需要进行协程切换,先执行goroutine 5表示切换到5号协程上,然后bt命令查看当前协程的栈状态,执行frame 3 locals切换到3号栈上并打印栈上的变量。
(dlv) goroutine 7
Switched from 8 to 7 (thread 12920)
(dlv) bt
0 0x00000000004388d2 in runtime.gopark
at c:/program files/go/src/runtime/proc.go:367
1 0x000000000045d57b in time.Sleep
at c:/program files/go/src/runtime/time.go:193
2 0x00000000004a31eb in main.Fuc
at d:/go/src/demo/string/main.go:21
3 0x00000000004a33d9 in main.main·dwrap·1
at d:/go/src/demo/string/main.go:29
4 0x0000000000460841 in runtime.goexit
at c:/program files/go/src/runtime/asm_amd64.s:1581
(dlv) frame 2
> runtime.gopark() c:/program files/go/src/runtime/proc.go:367 (PC: 0x4388d2)
Warning: debugging optimized function
Frame 2: d:/go/src/demo/string/main.go:21 (PC: 4a31eb)
Warning: listing may not match stale executable
16: fmt.Println("b")
17: }
18:
19: func Fuc(value int, wg *sync.WaitGroup) {
20: fmt.Println(value)
=> 21: time.Sleep(time.Second * 10)
22: wg.Done()
23: }
24:
25: func main() {
26: wg := sync.WaitGroup{}
(dlv) args
value = 1
wg = (*sync.WaitGroup)(0xc00000a0d0)
sources:打印所有源代码路径
threads:显示所有线程,thread:线程切换,这两个命令与goroutines、goroutine类似,不过在go语言中一般很少使用。
trace:跟踪,类似于打断点,但是代码不会中断继续执行,同时打印一行信息。