-s: 去掉符号信息。
-w: 去掉DWARF调试信息。
runtime.Breakpoint():触发调试器断点。
runtime/debug.PrintStack():显示调试堆栈。
log:适合替代 print显示调试信息。
参数载入:gdb -d $GCROOT 。
手工载入:source $GCROOT/src/runtime/runtime-gdb.py。
}}}}}}}}}}}}}}}}}
$ go build -gcflags “-N -l” // 编译,关闭内联优化。$ go build -gcflags “-N -l” // 编译,关闭内联优化。$ go build -gcflags “-N -l” // 编译,关闭内联优化。
$ sudo gdb demo // 启动 gdb 调试器,手工载入 Go Runtime 。GNU gdb (GDB) 7.5.1Reading symbols from demo…done.(gdb) source /usr/local/go/src/pkg/runtime/runtime-gdb.pyLoading Go Runtime support.$ sudo gdb demo // 启动 gdb 调试器,手工载入 Go Runtime 。GNU gdb (GDB) 7.5.1Reading symbols from demo…done.(gdb) source /usr/local/go/src/pkg/runtime/runtime-gdb.pyLoading Go Runtime support.$ sudo gdb demo // 启动 gdb 调试器,手工载入 Go Runtime 。GNU gdb (GDB) 7.5.1Reading symbols from demo…done.(gdb) source /usr/local/go/src/pkg/runtime/runtime-gdb.pyLoading Go Runtime support.
(gdb) l main.main // 以 .方式查看源码。9 r = fmt.Sprintf(“test: %s %d”, s, x)10 runtime.Breakpoint()11 return r12 }1314 func main() {15 s := “haha”16 i := 123417 println(test(s, i))18 }(gdb) l main.main // 以 .方式查看源码。9 r = fmt.Sprintf(“test: %s %d”, s, x)10 runtime.Breakpoint()11 return r12 }1314 func main() {15 s := “haha”16 i := 123417 println(test(s, i))18 }(gdb) l main.main // 以 .方式查看源码。9 r = fmt.Sprintf(“test: %s %d”, s, x)10 runtime.Breakpoint()11 return r12 }1314 func main() {15 s := “haha”16 i := 123417 println(test(s, i))18 }
(gdb) l main.go:8 // 以 :方式查看源码。3 import (4 “fmt”5 “runtime”6 )78 func test(s string, x int) (r string) {9 r = fmt.Sprintf(“test: %s %d”, s, x)10 runtime.Breakpoint()11 return r12 }(gdb) l main.go:8 // 以 :方式查看源码。3 import (4 “fmt”5 “runtime”6 )78 func test(s string, x int) (r string) {9 r = fmt.Sprintf(“test: %s %d”, s, x)10 runtime.Breakpoint()11 return r12 }(gdb) l main.go:8 // 以 :方式查看源码。3 import (4 “fmt”5 “runtime”6 )78 func test(s string, x int) (r string) {9 r = fmt.Sprintf(“test: %s %d”, s, x)10 runtime.Breakpoint()11 return r12 }
(gdb) b main.main // 以 .方式设置断点。Breakpoint 1 at 0×2131: file main.go, line 14.(gdb) b main.main // 以 .方式设置断点。Breakpoint 1 at 0×2131: file main.go, line 14.(gdb) b main.main // 以 .方式设置断点。Breakpoint 1 at 0×2131: file main.go, line 14.
(gdb) b main.go:17 // 以 :方式设置断点。Breakpoint 2 at 0×2167: file main.go, line 17.(gdb) b main.go:17 // 以 :方式设置断点。Breakpoint 2 at 0×2167: file main.go, line 17.(gdb) b main.go:17 // 以 :方式设置断点。Breakpoint 2 at 0×2167: file main.go, line 17.
(gdb) info breakpoints // 查看所有断点。Num Type Disp Enb Address What1 breakpoint keep y 0×0000000000002131 in main.main at main.go:142 breakpoint keep y 0×0000000000002167 in main.main at main.go:17(gdb) info breakpoints // 查看所有断点。Num Type Disp Enb Address What1 breakpoint keep y 0×0000000000002131 in main.main at main.go:142 breakpoint keep y 0×0000000000002167 in main.main at main.go:17(gdb) info breakpoints // 查看所有断点。Num Type Disp Enb Address What1 breakpoint keep y 0×0000000000002131 in main.main at main.go:142 breakpoint keep y 0×0000000000002167 in main.main at main.go:17
(gdb) r // 启动进程,触发第一个断点。Starting program: demo[New Thread 0x1c03 of process 4088][Switching to Thread 0x1c03 of process 4088]Breakpoint 1, main.main () at main.go:1414 func main() {(gdb) r // 启动进程,触发第一个断点。Starting program: demo[New Thread 0x1c03 of process 4088][Switching to Thread 0x1c03 of process 4088]Breakpoint 1, main.main () at main.go:1414 func main() {(gdb) r // 启动进程,触发第一个断点。Starting program: demo[New Thread 0x1c03 of process 4088][Switching to Thread 0x1c03 of process 4088]Breakpoint 1, main.main () at main.go:1414 func main() {
(gdb) info goroutines // 查看 goroutines 信息。* 1 running runtime.gosched* 2 syscall runtime.entersyscall(gdb) info goroutines // 查看 goroutines 信息。* 1 running runtime.gosched* 2 syscall runtime.entersyscall(gdb) info goroutines // 查看 goroutines 信息。* 1 running runtime.gosched* 2 syscall runtime.entersyscall
(gdb) goroutine 1 bt // 查看指定序号的 goroutine 调用堆栈。#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) goroutine 1 bt // 查看指定序号的 goroutine 调用堆栈。#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) goroutine 1 bt // 查看指定序号的 goroutine 调用堆栈。#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()
(gdb) goroutine 2 bt // 这个 goroutine 貌似跟 GC 有关。#0 runtime.entersyscall () at pkg/runtime/proc.c:989#1 0x000000000000d01d in runtime.MHeap_Scavenger () at pkg/runtime/mheap.c:363#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) goroutine 2 bt // 这个 goroutine 貌似跟 GC 有关。#0 runtime.entersyscall () at pkg/runtime/proc.c:989#1 0x000000000000d01d in runtime.MHeap_Scavenger () at pkg/runtime/mheap.c:363#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) goroutine 2 bt // 这个 goroutine 貌似跟 GC 有关。#0 runtime.entersyscall () at pkg/runtime/proc.c:989#1 0x000000000000d01d in runtime.MHeap_Scavenger () at pkg/runtime/mheap.c:363#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()
(gdb) c / / 继续执行,触发下一个断点。Continuing.Breakpoint 2, main.main () at main.go:1717! ! println(test(s, i))(gdb) c / / 继续执行,触发下一个断点。Continuing.Breakpoint 2, main.main () at main.go:1717! ! println(test(s, i))(gdb) c / / 继续执行,触发下一个断点。Continuing.Breakpoint 2, main.main () at main.go:1717! ! println(test(s, i))
(gdb) info goroutines // 当前 goroutine 序号为 1。* 1 running runtime.gosched2 runnable runtime.gosched(gdb) info goroutines // 当前 goroutine 序号为 1。* 1 running runtime.gosched2 runnable runtime.gosched(gdb) info goroutines // 当前 goroutine 序号为 1。* 1 running runtime.gosched2 runnable runtime.gosched
(gdb) goroutine 1 bt // 当前 goroutine 调用堆栈。#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) goroutine 1 bt // 当前 goroutine 调用堆栈。#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) goroutine 1 bt // 当前 goroutine 调用堆栈。#0 0x000000000000f6c0 in runtime.gosched () at pkg/runtime/proc.c:927#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()
(gdb) bt // 查看当前调堆栈,可以与当前 goroutine 调用堆栈对比。#0 main.main () at main.go:17#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) bt // 查看当前调堆栈,可以与当前 goroutine 调用堆栈对比。#0 main.main () at main.go:17#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()(gdb) bt // 查看当前调堆栈,可以与当前 goroutine 调用堆栈对比。#0 main.main () at main.go:17#1 0x000000000000e44c in runtime.main () at pkg/runtime/proc.c:244#2 0x000000000000e4ef in schedunlock () at pkg/runtime/proc.c:267#3 0×0000000000000000 in ?? ()
(gdb) info frame // 堆栈帧信息。Stack level 0, frame at 0x442139f88:rip = 0×2167 in main.main (main.go:17); saved rip 0xe44ccalled by frame at 0x442139fb8source language go.Arglist at 0x442139f28, args:Locals at 0x442139f28, Previous frame’s sp is 0x442139f88Saved registers:rip at 0x442139f80(gdb) info frame // 堆栈帧信息。Stack level 0, frame at 0x442139f88:rip = 0×2167 in main.main (main.go:17); saved rip 0xe44ccalled by frame at 0x442139fb8source language go.Arglist at 0x442139f28, args:Locals at 0x442139f28, Previous frame’s sp is 0x442139f88Saved registers:rip at 0x442139f80(gdb) info frame // 堆栈帧信息。Stack level 0, frame at 0x442139f88:rip = 0×2167 in main.main (main.go:17); saved rip 0xe44ccalled by frame at 0x442139fb8source language go.Arglist at 0x442139f28, args:Locals at 0x442139f28, Previous frame’s sp is 0x442139f88Saved registers:rip at 0x442139f80
(gdb) info locals // 查看局部变量。i = 1234s = “haha”(gdb) info locals // 查看局部变量。i = 1234s = “haha”(gdb) info locals // 查看局部变量。i = 1234s = “haha”
(gdb) p s // 以 Pretty-Print 方式查看变量。$1 = “haha”(gdb) p s // 以 Pretty-Print 方式查看变量。$1 = “haha”(gdb) p s // 以 Pretty-Print 方式查看变量。$1 = “haha”
(gdb) p $len(s) // 获取对象长度($cap)$2 = 4(gdb) p $len(s) // 获取对象长度($cap)$2 = 4(gdb) p $len(s) // 获取对象长度($cap)$2 = 4
(gdb) whatis i // 查看对象类型。type = int(gdb) whatis i // 查看对象类型。type = int(gdb) whatis i // 查看对象类型。type = int
(gdb) c // 继续执行,触发 breakpoint() 断点。Continuing.Program received signal SIGTRAP, Trace/breakpoint trap.runtime.breakpoint () at pkg/runtime/asm_amd64.s:8181 RET(gdb) c // 继续执行,触发 breakpoint() 断点。Continuing.Program received signal SIGTRAP, Trace/breakpoint trap.runtime.breakpoint () at pkg/runtime/asm_amd64.s:8181 RET(gdb) c // 继续执行,触发 breakpoint() 断点。Continuing.Program received signal SIGTRAP, Trace/breakpoint trap.runtime.breakpoint () at pkg/runtime/asm_amd64.s:8181 RET
(gdb) n // 从 breakpoint() 中出来,执行源码下一行代码。main.test (s=”haha”, x=1234, r=”test: haha 1234″) at main.go:1111 return r(gdb) n // 从 breakpoint() 中出来,执行源码下一行代码。main.test (s=”haha”, x=1234, r=”test: haha 1234″) at main.go:1111 return r(gdb) n // 从 breakpoint() 中出来,执行源码下一行代码。main.test (s=”haha”, x=1234, r=”test: haha 1234″) at main.go:1111 return r
(gdb) info args // 从参数信息中,我们可以看到命名返回参数的值。s = “haha”x = 1234r = “test: haha 1234″(gdb) info args // 从参数信息中,我们可以看到命名返回参数的值。s = “haha”x = 1234r = “test: haha 1234″(gdb) info args // 从参数信息中,我们可以看到命名返回参数的值。s = “haha”x = 1234r = “test: haha 1234″
(gdb) x/3xw &r // 查看 r 内存数据。(指针 8 + 长度 4)0x442139f48: 0×42121240 0×00000000 0x0000000f(gdb) x/15xb 0×42121240 // 查看字符串字节数组0×42121240: 0×74 0×65 0×73 0×74 0x3a 0×20 0×68 0×610×42121248: 0×68 0×61 0×20 0×31 0×32 0×33 0×34(gdb) x/3xw &r // 查看 r 内存数据。(指针 8 + 长度 4)0x442139f48: 0×42121240 0×00000000 0x0000000f(gdb) x/15xb 0×42121240 // 查看字符串字节数组0×42121240: 0×74 0×65 0×73 0×74 0x3a 0×20 0×68 0×610×42121248: 0×68 0×61 0×20 0×31 0×32 0×33 0×34(gdb) x/3xw &r // 查看 r 内存数据。(指针 8 + 长度 4)0x442139f48: 0×42121240 0×00000000 0x0000000f(gdb) x/15xb 0×42121240 // 查看字符串字节数组0×42121240: 0×74 0×65 0×73 0×74 0x3a 0×20 0×68 0×610×42121248: 0×68 0×61 0×20 0×31 0×32 0×33 0×34
(gdb) c // 继续执行,进程结束。(gdb) c // 继续执行,进程结束。(gdb) c // 继续执行,进程结束。
Continuing.test: haha 1234[Inferior 1 (process 4088) exited normally]Continuing.test: haha 1234[Inferior 1 (process 4088) exited normally]Continuing.test: haha 1234[Inferior 1 (process 4088) exited normally]
(gdb) q // 退出 GDB。(gdb) q // 退出 GDB。(gdb) q // 退出 GDB。