Build GDB debugging go program
- preface
- GDB installation
-
- Update the brew
- Check whether GDB mirroring exists
- Install the GDB
- Go build to compile
- GDB executive
- GDB commands
- GDB debugging
- Problems to sort out
- reference
preface
Learn to use GDB for golang debugging, through a simple go program for simple access to the source code call sequence view.
GDB installation
The development environment is Mac and BREW can be used for GDB installation
Update the brew
brew update
Copy the code
Check whether GDB mirroring exists
brew search gdb
Copy the code
Install the GDB
brew install gdb
Copy the code
Go build to compile
For help with the go build command, see the go help build command parameters.
Go build-gcflags =all=” -n-l “-ldFlags =-compressdwarf=false” -ldflags=-compressdwarf=false “-ldflags=-compressdwarf=false” -ldflags=-compressdwarf=false
The meanings of parameters used in compilation are described as follows:
Compile parameters | meaning |
---|---|
-gcflags=all=”-N -l” | Turn off inline optimization; Turn off compiler function optimization |
-ldflags=-compressdwarf=false | Generate compressed adjustable information |
GDB executive
Run the GDB main command to enter the GDB environment. Then you can debug and use the GDB environment
$ gdb program
Reading symbols from program...
Loading Go Runtime support.
Copy the code
GDB commands
Before entering GDB debugging, popular GDB debugging commands are as follows
The command | instructions |
---|---|
File < file name > | Loads the debugged executable file |
run | Restart the file, r for short |
start | Step, running the program, stopping at the first execution statement |
list | View the source code, abbreviated L |
set | Sets the value of a variable |
next | Step by step debugging – n |
step | Step by step debugging (statement by statement: jumping into a custom function), short for S |
backtrace | View the stack frame and hierarchy of function calls, abbreviated BT |
frame | Switch function stack frame, short f |
info | View the value of the local variable inside the function, I |
finish | Terminates the current function and returns to the point of function call |
continue | Keep going, c for short |
Print the value and address, p for short | |
quit | Exit GDB, q |
The following parameters of the above command can be viewed by running help [command] in the GDB environment
GDB debugging
Next, GDB debugging is performed based on a simple Golang program, in order to understand the initialization process of the Golang program.
Execute the list to see the source code for the current file. Here you see the original GO program file we wrote
(gdb) list
1 package main
2
3 import "fmt"
4
5 func main() {
6 fmt.Println("hello world"7})Copy the code
Execute info files to view the values of local variables inside the function, as shown below
(gdb) info files
Symbols from "/Users/guanjian/workspace/go/program/program".
Local exec file:
`/Users/guanjian/workspace/go/program/program', file type mach-o-x86-64. Entry point: 0x10701e0: 0x0000000001001000 - 0x00000000010cbc53 is .text 0x00000000010cbc60 - 0x00000000010cbd62 is __TEXT.__symbol_stub1 0x00000000010cbd80 - 0x0000000001100b19 is __TEXT.__rodata 0x0000000001100b20 - 0x00000000011012bc is __TEXT.__typelink 0x00000000011012c0 - 0x0000000001101328 is __TEXT.__itablink 0x0000000001101328 - 0x0000000001101328 is __TEXT.__gosymtab 0x0000000001101340 - 0x000000000115dae8 is __TEXT.__gopclntab 0x000000000115e000 - 0x000000000115e020 is __DATA.__go_buildinfo 0x000000000115e020 - 0x000000000115e178 is __DATA.__nl_symbol_ptr 0x000000000115e180 - 0x000000000116c4a4 is __DATA.__noptrdata 0x000000000116c4c0 - 0x00000000011738f0 is .data 0x0000000001173900 - 0x00000000011a1170 is .bss 0x00000000011a1180 - 0x00000000011a62f0 is __DATA.__noptrbss (gdb)Copy the code
The top Entry point is Entry Point: 0x10701e0:, where we set the breakpoint to debug the program. Break *0x10701e0:
(gdb) break *0x10701e0
Breakpoint 1 at 0x10701e0: file /usr/local/go/src/runtime/rt0_darwin_amd64.s, line 8.
Copy the code
Can see already add the breakpoint is successful, then saw the current compilation go program entry in the/usr/local/go/SRC/runtime/rt0_darwin_amd64 s file, we enter into that directory for files starting all rt0 is full. The s at the end of the assembly language implementation, as follows:
$ ls /usr/local/go/src/runtime/rt0_ rt0_aix_ppc64.s rt0_ios_arm64.s rt0_netbsd_arm.s rt0_android_386.s rt0_js_wasm.s rt0_netbsd_arm64.s rt0_android_amd64.s rt0_linux_386.s rt0_openbsd_386.s rt0_android_arm.s rt0_linux_amd64.s rt0_openbsd_amd64.s rt0_android_arm64.s rt0_linux_arm.s rt0_openbsd_arm.s rt0_darwin_amd64.s rt0_linux_arm64.s rt0_openbsd_arm64.s rt0_darwin_arm64.s rt0_linux_mips64x.s rt0_openbsd_mips64.s rt0_dragonfly_amd64.s rt0_linux_mipsx.s rt0_plan9_386.s rt0_freebsd_386.s rt0_linux_ppc64.s rt0_plan9_amd64.s rt0_freebsd_amd64.s rt0_linux_ppc64le.s rt0_plan9_arm.s rt0_freebsd_arm.s rt0_linux_riscv64.s rt0_solaris_amd64.s rt0_freebsd_arm64.s rt0_linux_s390x.s rt0_windows_386.s rt0_illumos_amd64.s rt0_netbsd_386.s rt0_windows_amd64.s rt0_ios_amd64.s rt0_netbsd_amd64.s rt0_windows_arm.sCopy the code
Let’s look at the rt0_darwin_amd64.s file as follows:
% cat -n rt0_darwin_amd64.s
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "textflag.h"7 TEXT _rt0_amd64_darwin(SB),NOSPLIT,$-8 8 JMP _rt0_amd64(SB) // When linking with-shared, this symbol is called when the shared library 11 // is loaded. 12 TEXT _rt0_amd64_darwin_lib(SB),NOSPLIT,$0
13 JMP _rt0_amd64_lib(SB)
Copy the code
Line 8 _rt0_amd64(SB) here is the call entry, i.e
Breakpoint 1 at 0x10701e0: file /usr/local/go/src/runtime/rt0_darwin_amd64.s, line 8.
Copy the code
Now we need to find_rt0_amd64
The location of this assembly method, the search method can be viewed according to their own way, I here in order to facilitate the view, download golang SDK, and then import IDE global search, locate the fileruntime/asm_amd64.s
That is as follows:
And then, let’s look it upThe runtime, rt0_go (SB)
The method is as follows
The runtime, rt0_go (SB)
Method contains a number of initialization methods. Here is an example of picking rain marks in the article:
The TEXT, the runtime rt0_go (SB), NOSPLIT,$0. // ===== calls the initialization function ===== CALL Runtime ·args(SB) CALL Runtime ·osinit(SB) CALL Runtime ·schedinit(SB) // ===== creates main Goroutine is used to execute runtime.main ===== MOVQ$runtime·mainPC(SB), AX
PUSHQ AX
PUSHQ $0CALL Runtime ·newproc(SB) POPQ AX POPQ AX // ===== Let the current thread start main goroutine ===== CALL Runtime ·mstart(SB) RET DATA The runtime mainPC + 0/8 (SB),$runtime, the main (SB) GLOBL runtime · mainPC (SB), RODATA.$8
Copy the code
$runtime·main(SB) $runtime·main(SB) $runtime·main(SB) We look at the call through the GDB breakpoint as follows:
(gdb) b runtime.main
Breakpoint 1 at 0x103b4c0: file /usr/local/go/src/runtime/proc.go, line 115.
Copy the code
So far, we’ve set up a DEBUGGING environment for GDB and some practices for viewing the golang function code.
Problems to sort out
- Problem 1: GDB signature limitation in macOs
(gdb) run
Starting program: /xxx/main
Unable to find Mach task port for process-id 35564: (os/kern) failure (0x5).
(please check gdb is codesigned - see taskgated(8))
Copy the code
A simple way to solve the signature limitation problem is to use root, but this debugging program is very risky
- Problem 2: (No debugging symbols found in./main
(gdb) list
The debug file cannot be found
(gdb) list
No symbol table is loaded. Use the "file" command.
Copy the code
My solution is to add the go build-ldFlags =-compressdwarf=false parameter when compiling Go to output debugging information
- Problem 3: Function call lookup methods
- IDE imports go’s SDK for global search (more convenient, but not necessarily accurate, need to fully understand the call link)
- Enter the GDB environment, and pass
b [file].[method]
To mark breakpoints, you can display the current breakpoint source file location contains line number, can also passinfo breakpoints
Viewing breakpoint Information
-
Question 4: the number of rows in the GDB breakpoint display in the IDE is not accurate Can open the command line in the system view, general is accurate, use the cat – n file | head -n [number] command
-
Error 5: GDB is stuck after executing run & Possible causes of invalid break point [New Thread 0x1103 of process 843]
reference
Debugging Go Code with GDB Debugging Go Code with GDB Debugging Go Code with GDB Debugging Go Code with GDB Debugging Go Code with GDB Debugging Go Code with GDB Debugging Go Code with GDB Starting program: [New Thread 0x1103 of Process 843]