Go GDB/MI interface
Go JavaScript HTML CSS Other
Latest commit 3c9651c Jun 14, 2016 @cyrus-and Avoid unnecessary argument quotation
Quoting blindly every argument causes GDB to misbehave in certain situations
(bug or intended behavior?) for example `-break-delete "1"` is different from
`-break-delete 1`. It seems that GDB uses the literal raw string for some
commands (like in the `break-delete` case) but not for others; for example
`-data-evaluate-expression asd` is equivalent to `-data-evaluate-expression

This should fix #4.
Failed to load latest commit information.
web Add WebSocket go get info May 6, 2015
.gitignore Add initial release May 1, 2015
LICENSE Add initial release May 1, 2015
Makefile Add initial release May 1, 2015
commands_test.go Fast-fail on errors during tests May 6, 2015
doc.go Highlight the main goals May 5, 2015
gdb.go Fix race condition when exiting gdb Feb 2, 2016
grammar.go Allow an alternative format for status records Feb 2, 2016
grammar.y Allow an alternative format for status records Feb 2, 2016
io_test.go Fast-fail on errors during tests May 6, 2015
lexer.go Add initial release May 1, 2015



Package gdb provides a convenient way to interact with the GDB/MI interface. The methods offered by this module are very low level, the main goals are:

  • avoid the tedious parsing of the MI2 line-based text interface;

  • bypass a known bug which prevents to distinguish the target program's output from MI2 records.

Web interface

This package comes with an additional HTTP/WebSocket interface which aims to provide a straightforward way to start developing web-based GDB front ends.

A dummy example can be found in the example folder.


package main

import (

func main() {
    // start a new instance and pipe the target output to stdout
    gdb, _ := gdb.New(nil)
    go io.Copy(os.Stdout, gdb)

    // evaluate an expression
    gdb.Send("var-create", "x", "@", "40 + 2")
    fmt.Println(gdb.Send("var-evaluate-expression", "x"))

    // load and run a program
    gdb.Send("file-exec-file", "wc")
    gdb.Send("exec-arguments", "-w")
    gdb.Write([]byte("This sentence has five words.\n\x04")) // EOT



go get github.com/cyrus-and/gdb



Data representation

The objects returned as a result of the commands or as asynchronous notifications are generic Go maps suitable to be converted to JSON format with json.Marshal(). The fields present in such objects are blindly added according to the records returned from GDB (see the command syntax): tuples are map[string]interface{} and lists are []interface{}.

Yet, some additional fields are added:

  • the record class, where present, is represented by the "class" field;

  • the record type is represented using the "type" field as follows:

    • +: "status"
    • =: "notify"
    • ~: "console"
    • @: "target"
    • &: "log"
  • the optional result list is stored into a tuple under the "payload" field.

For example, the notification:


becomes the Go map:

map[type:notify class:thread-group-exited payload:map[id:i1 exit-code:0]]

which can be converted to JSON with json.Marshal() obtaining:

    "class": "thread-group-exited",
    "payload": {
        "exit-code": "0",
        "id": "i1"
    "type": "notify"

Mac OS X

Setting up GDB on Darwin

To use this module is mandatory to have a working version of GDB installed, Mac OS X users may obtain a copy using Homebrew for example, then they may need to give GDB permission to control other processes as described here.


The Mac OS X support, though, is partial and buggy due to the following issues.


I/O operations on the target program happens through a pseudoterminal obtained using the pty package which basically uses the /dev/ptmx on *nix systems to request new terminal instances.

There are some unclear behaviors on Mac OS X. Calling gdb.Write() when the target program is not running is a no-op, on Linux instead writes are somewhat buffered and delivered later. Likewise, gdb.Read() may returns EOF even though there is actually data to read, a solution may be keep trying.


Sending a SIGINT signal to GDB has no effect on Mac OS X, on Linux instead this is equivalent to typing ^C, so gdb.Interrupt() will not work.