Implementing a Golang Debugger (part One)

Source: Internet
Author: User
Tags docker run
This is a creation in Article, where the information may have evolved or changed. The purpose of writing this series is not to list all the features of the debugger for the Golang programming language. If you want to see these things, you can look at [Delve] (https://github.com/derekparker/delve). In this article we try to explore how the debugger usually works, how to do a basic debugging on Linux, Linux is more concerned about the function of Golang, such as [Goroutine] (https://golang.org/ref/spec#Go_ statements). Creating a debugger is not that simple. On this topic we can not finish a single article. Instead, this blog post is a start, and the ultimate goal of this series is to find a solution to handle the most common scenarios. During the period we will discuss similar [ELF] (Https://pl.wikipedia.org/wiki/Executable_and_Linkable_Format), [DWARF] (https://en.wikipedia.org/ WIKI/DWARF), there are also some architectural-related issues to be contacted. # # Environment # #整个系列文章中, we'll use [Docker] (https://www.docker.com/) to get a copy of the playground based on Debian Jessie. I'm using [x86-64] (https://en.wikipedia.org/wiki/X86-64), which can be a bit of a starting point for us to do some bottom-up discussions. The project structure is as follows: "' > Tree.├──dockerfile└──src└──github.com└──mlowicki├──debugger│└──debugger.go└──hello└──hello.go '" The main file of the debugger we're going to use right away is the *debugger.go*,*hello.go* file that contains the sample program source code that we debugged throughout our process. Now you can write the simplest of things: "' gopackage mainfunc Main () {}" We'll write a very simple Dockerfile: ' from Golang:1.8.1run apt-get update & & Apt-get install-y Tree "to compile the Docker image to (DockerThe outermost directory where file is located, run: ' > Docker build-t godebugger. ' To container acceleration, execute: ' > Docker run--rm-it-v "$PWD"/src:/go/src--secu rity-opt seccomp=unconfined Godebugger "[here] (https://docs.docker.com/engine/security/seccomp/) There is a description of the safe operation mode (SECCOMP). Now all that is left is to compile these two programs in the container. The first one can do this: "> Go install--gcflags="-n-l "Github.com/mlowicki/hello" logo--gcflag used to suppress [inline function] (https:// En.wikipedia.org/wiki/inline_expansion) (-L), compile-optimized (-N) to make debugging easier. The debugger compiles as follows: ' > Go install Github.com/mlowicki/debugger ' contains '/go/bin ' in the container's environment variable *path*, so that you can run any newly compiled program without using the full path. Whether it's ' hello ' or ' debugger '. [] (https://raw.githubusercontent.com/studygolang/gctt-images/master/making-debugger/1_ Lkltdwon2t9n4melhrdvag.jpeg) # # # The first step # #我们的第一个任务很简单. Stop the program before executing any instructions, and then run it again until the program stops (whether it is automatically stopped or an error stop occurs). Most debuggers you can start with. Set some tracking points (breakpoints), and then perform a command like ' continue ' to actually run until you stop where you want to stop. Let's see how [Delve] (Https://github.com/derekparker/delve) works: "Shell> cat hello.gopackage Mainimport" FMT "Func f () int {var n intn = 1n = 2return N}func main () {FMT. Println (f ())}> DLV debugbreak Type ' help ' for list of commands. (DLV) Break Main.fbreakpoint 1 SET @ 0x1087050 for MAIN.F ()./hello.go:5 (DLV) continue> main.f ()./hello.go:5 (hits Go Routine (1): 1 total:1) (pc:0x1087050) 1:package main 2:3: Import "FMT" 4:=> 5:func f () int {6:var n int 7:n = 1 8 : n = 2 9:return N10:} (DLV) next> main.f ()./hello.go:6 (pc:0x1087067) 1:package main 2:3: Import "FMT" 4:5: Func f () int {=> 6:var n int 7:n = 1 8:n = 2 9:return n10:}11: (DLV) print n842350461344 (DLV) next> main.f ()./hello . Go:7 (pc:0x108706f) 2:3: Import "FMT" 4:5: Func f () int {6:var n int=> 7:n = 1 8:n = 2 9:return n10:}11:12:f UNC Main () {(DLV) print n0 (DLV) next> main.f ()./hello.go:8 (pc:0x1087077) 3:import "FMT" 4:5: Func f () int {6:var n int 7:n = 1=> 8:n = 2 9:return N10:}11:12:func main () {13:fmt. Println (f ()) (DLV) Print N1 "Let's see how we do it ourselves." The first step is to find a mechanism for the process (our debugger) to control the other processes (the process we are debugging). Fortunately on Linux we have this--[Ptrace] (http://man7.org/linux/man-pages/man2/ptrace.2.html). That's not the count. Golang's [Syscall] (https://golang.org/pkg/syscall/) package provides a similar [Ptracecont] (https://golang.org/pkg/syscall/# Ptracecont) interface, you can restart the process being traced. So here's the second part, but in order to have the opportunity to set breakpoints before the program starts executing, we have to do something else. When creating a new process we can specify the process behavior by setting properties-[Sysprocattr] (https://golang.org/pkg/syscall/#SysProcAttr). One is that *ptrace* can track the process, and then the process stops and sends a [SIGSTOP signal] (http://man7.org/linux/man-pages/man7/signal.7.html) to the parent process before it is opened. We have just learned the content into a workflow ... ' shell> cat src/github.com/mlowicki/hello/hello.gopackage mainimport "FMT" Func Main () { Fmt. Println ("Hello World")}> cat Src/github.com/mlowicki/debugger/debugger.gopackage mainimport ("Flag" "Log" "OS" "os/ Exec "" Syscall ") func main () {flag. Parse () Input: = flag. ARG (0) cmd: = exec. Command (input) cmd. Args = []string{input}cmd. Stdout = OS. Stdoutcmd.stderr = OS. Stderrcmd.sysprocattr = &syscall. Sysprocattr{ptrace:true}err: = cmd. Start () if err! = Nil {log. Fatal (err)}err = cmd. Wait () log. Printf ("state:%v\n", err) log. PRINTLN ("Restarting ...") Err = Syscall. Ptracecont (cmd. ProcEss. Pid, 0) if err! = Nil {log. Panic (err)}var ws syscall. Waitstatus_, err = Syscall. WAIT4 (cmd. Process.pid, &ws, Syscall. WALL, nil) if err! = Nil {log. Fatal (Err)}log. Printf ("Exited:%v\n", WS. Exited ()) log. Printf ("Exit Status:%v\n", WS. Exitstatus ())}> go install-gcflags= "-n-l" github.com/mlowicki/hello> Go install Github.com/mlowicki/debugger > debugger/go/bin/hello2017/05/05 20:09:38 state:stop signal:trace/breakpoint trap2017/05/05 20:09:38 Restarting ... hello world2017/05/05 20:09:38 exited:true2017/05/05 20:09:38 Exit status:0 ' The first version of the debugger is implemented in a simple way. A tracked process is started, and then the process stops before executing the first instruction and sends a signal to the parent process. The parent process waits for this signal and logs ' log '. Printf ("state:%v\n", err) '. After the program restarts, the parent process waits for it to terminate. This way we have the opportunity to set breakpoints ahead of time, start the program, wait for the specified track point, look at the current value like the Stack or registry, check the status of the process. [] (Https://raw.githubusercontent.com/studygolang/gctt-images/master/making-debugger/1_qysN9I7NtfurG2K7kT_ 1SW.JPEG) Even if we know a little bit, we can do some great things. These will lay the groundwork for future improvements and practices (in the near future). Give us some praise, so that more people can see this article. If you want to get post updates or get improved at work, follow us.

Via:https://medium.com/golangspec/making-debugger-for-golang-part-i-53124284b7c8

Author: Michałłowicki Translator: arisaries proofreading: polaris1119

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

628 Reads ∙1 likes
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.