gdb

package module
v0.0.0-...-9424cb2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 21, 2023 License: MIT Imports: 11 Imported by: 11

README

gdb

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.

Example

package main

import (
	"fmt"
	"github.com/cyrus-and/gdb"
	"io"
	"os"
)

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
	gdb.Send("exec-run")

	gdb.Exit()
}

Installation

go get -u github.com/cyrus-and/gdb

Documentation

GoDoc.

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:

=thread-group-exited,id="i1",exit-code="0"

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.

Issues

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

Pseudoterminals

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.

Interrupt

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.

Development

The goyacc tool is needed to generate the grammar.go file. Install it with:

go install golang.org/x/tools/cmd/goyacc@latest

After that use the following to update the grammar.go file:

go generate -x

Resources

Documentation

Overview

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;

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.Unmarshal(). The fields present in such objects are blindly added according to the records returned from GDB (see https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Output-Syntax.html): tuples are map[string]interface{} and lists are []interface{}. There are a couple of exceptions to this:

- 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.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Gdb

type Gdb struct {
	io.ReadWriter
	// contains filtered or unexported fields
}

Gdb represents a GDB instance. It implements the ReadWriter interface to read/write data from/to the target program's TTY.

func New

func New(onNotification NotificationCallback) (*Gdb, error)

New creates and starts a new GDB instance. onNotification if not nil is the callback used to deliver to the client the asynchronous notifications sent by GDB. It returns a pointer to the newly created instance handled or an error.

func NewCmd

func NewCmd(cmd []string, onNotification NotificationCallback) (*Gdb, error)

NewCmd creates a new GDB instance like New, but allows explicitely passing the gdb command to run (including all arguments). cmd is passed as-is to exec.Command, so the first element should be the command to run, and the remaining elements should each contain a single argument.

func NewCustom

func NewCustom(gdbCmd []string, onNotification NotificationCallback) (*Gdb, error)

Like New, but allows to specify the GDB executable path and arguments.

func (*Gdb) CheckedSend

func (gdb *Gdb) CheckedSend(operation string, arguments ...string) (map[string]interface{}, error)

CheckedSend works like Send, except that if the result returned by gdb has class=error, CheckedSend returns a non-nil error value (containing the gdb error message)

func (*Gdb) Exit

func (gdb *Gdb) Exit() error

Exit sends the exit command to GDB and waits for the process to exit.

func (*Gdb) Interrupt

func (gdb *Gdb) Interrupt() error

Interrupt sends a signal (SIGINT) to GDB so it can stop the target program and resume the processing of commands.

func (*Gdb) Read

func (gdb *Gdb) Read(p []byte) (n int, err error)

Read reads a number of bytes from the target program's output.

func (*Gdb) Send

func (gdb *Gdb) Send(operation string, arguments ...string) (map[string]interface{}, error)

Send issues a command to GDB. Operation is the name of the MI2 command to execute without the leading "-" (this means that it is impossible send a CLI command), arguments is an optional list of arguments, in GDB parlance the can be: options, parameters or "--". It returns a generic object which represents the reply of GDB or an error in case the command cannot be delivered to GDB.

func (*Gdb) Write

func (gdb *Gdb) Write(p []byte) (n int, err error)

Write writes a number of bytes to the target program's input.

type NotificationCallback

type NotificationCallback func(notification map[string]interface{})

NotificationCallback is a callback used to report the notifications that GDB send asynchronously through the MI2 interface. Responses to the commands are not part of these notifications. The notification generic object contains the notification sent by GDB.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL