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 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_amd64The 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.sThat 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) listThe 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
  1. IDE imports go’s SDK for global search (more convenient, but not necessarily accurate, need to fully understand the call link)
  2. 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 breakpointsViewing 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]