I use the delve to debug galang code in vscode. I want to use the delve to see the the creation of the golang map,and I create a breakpoint when use the make function to init the map,but it just cannot step into.
You can use delve to debug the runtime, however you will need to get familiar with the dlv
command line interface(without using a GUI).
I will be using the following program as an example:
package main
func main() {
abc := make(map[string]int)
abc["a"] = 1
abc["b"] = 2
abc["c"] = 2
fmt.Println(abc)
}
We can ask delve to build and debug our program with the dlv debug
command. This will drop us into the interactive debugger.
One of the things that makes maps "fun" to debug is that the compiler can create maps in different ways. We first need to know which functions the compiler is using to create a map(can be several depending on map size). We will ask delve to disassemble the main func with the disassemble -l main.main
command:
(dlv) disassemble -l main.main
TEXT main.main(SB) /home/caveman/Downloads/test/main.go
main.go:7 0x4b6860 64488b0c25f8ffffff mov rcx, qword ptr fs:[0xfffffff8]
main.go:7 0x4b6869 488d4424f0 lea rax, ptr [rsp-0x10]
main.go:7 0x4b686e 483b4110 cmp rax, qword ptr [rcx+0x10]
main.go:7 0x4b6872 0f8668010000 jbe 0x4b69e0
main.go:7 0x4b6878 4881ec90000000 sub rsp, 0x90
main.go:7 0x4b687f 4889ac2488000000 mov qword ptr [rsp+0x88], rbp
main.go:7 0x4b6887 488dac2488000000 lea rbp, ptr [rsp+0x88]
main.go:8 0x4b688f e84c86f5ff call $runtime.makemap_small
main.go:8 0x4b6894 488b0424 mov rax, qword ptr [rsp]
main.go:8 0x4b6898 4889442430 mov qword ptr [rsp+0x30], rax
...
Now this looks complicated, but we just have to look for calls to the runtime. In this case call $runtime.makemap_small
a call to the makemap_small function.
Now that we know this, we need to make a breakpoint in this runtime function. We do this using the break mkSmallMap runtime.makemap_small
command:
(dlv) break mkSmallMap runtime.makemap_small
Breakpoint mkSmallMap set at 0x40eeef for runtime.makemap_small() /usr/local/go/src/runtime/map.go:292
Now we can start our program by executing the c
(continue) command:
(dlv) c
> [mkSmallMap] runtime.makemap_small() /usr/local/go/src/runtime/map.go:292 (hits goroutine(1):1 total:1) (PC: 0x40eeef)
Warning: debugging optimized function
287: }
288:
289: // makemap_small implements Go map creation for make(map[k]v) and
290: // make(map[k]v, hint) when hint is known to be at most bucketCnt
291: // at compile time and the map needs to be allocated on the heap.
=> 292: func makemap_small() *hmap {
293: h := new(hmap)
294: h.hash0 = fastrand()
295: return h
296: }
297:
We break in the runtime function itself. The help
command will help you get started with all the commands you need for debugging. A few basic ones:
If we change the map creation to abc := make(map[string]int, 100000)
you will see in the disassembly that the runtime function has changed to runtime.makemap
which is likely of more interest to you.
I hope this gets you going, please leave a comment if you need clarification on anything.