Created
September 25, 2015 16:18
-
-
Save matthijskooijman/89152be7c5a5040df245 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
// "os/exec" | |
"github.com/cyrus-and/gdb" | |
"log" | |
"os" | |
"bufio" | |
"strings" | |
"fmt" | |
"encoding/json" | |
) | |
const openocdPath = "/home/matthijs/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/bin/openocd" | |
const gdbPath = "/home/matthijs/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gdb" | |
const openocdScripts = "/home/matthijs/.arduino15/packages/arduino/tools/openocd/0.9.0-arduino/share/openocd/scripts/" | |
const openocdConfig = "/home/matthijs/.arduino15/packages/arduino/hardware/samd/1.6.1/variants/arduino_zero/openocd_scripts/arduino_zero.cfg" | |
const elf = "/tmp/build8600053f19645e2961d8ec07ec4ee74e.tmp/Blink.ino.elf" | |
func logLines(str string) { | |
lines := strings.Split(str, "\n") | |
for i, line := range lines { | |
if line != "" || i == 0 || i < len(lines) - 1 { | |
log.Println(line) | |
} | |
} | |
} | |
func logThing(thing interface{}) { | |
pretty, _ := json.MarshalIndent(thing, "", " ") | |
logLines(string(pretty)) | |
} | |
func onNotification(notification map[string]interface{}) { | |
switch notification["type"] { | |
case "console", "log": | |
logLines(fmt.Sprint(notification["payload"])) | |
default: | |
logThing(notification) | |
} | |
} | |
func main() { | |
/* | |
openocd := exec.Command(openocdPath, "-s", openocdScripts, "-f", openocdConfig) | |
openocd.Stdout = os.Stdout | |
openocd.Stderr = os.Stderr | |
err := openocd.Start() | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer openocd.Process.Kill() | |
*/ | |
gdb.GdbCommand = gdbPath | |
gdb, err := gdb.New(onNotification) | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer gdb.Exit() | |
_, err = gdb.Send("file-exec-and-symbols", elf) | |
if err != nil { | |
log.Fatal(err) | |
} | |
_, err = gdb.Send("gdb-set remotelogfile /tmp/golog") | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Let gdb start openocd and connect to it through its | |
// stdin/stdout. This prevents the need for openocd to listen on | |
// a network port, and the associated security risks. | |
// | |
// All arguments to gdb.Send (except the first commandname) will | |
// be quoted before sending them to gdb. Since target-select is | |
// not implemented as a proper mi command inside gdb, but simply | |
// executes the "target" CLI passing the arguments as-is, adding | |
// quotes to "remote" and the pipe breaks their processing. | |
// | |
// Anything sent after the pipe is passed as-is to /bin/sh by | |
// gdb, so the actual openocd command and its arguments are | |
// passed to gdb.Send separately, so it will apply quoting to | |
// them (which can then be unquoted by sh). | |
// | |
// TODO: gdb.Send uses simple quoting, which leaves in special | |
// characters such as $ and ` which can still be executed by the | |
// shell. Ideally, gdb would have a specific MI command for | |
// executing the pipe, where each MI argument becomes a | |
// commandline argument and doesn't involve the shell at all, | |
// but without that we should make sure to apply more thorough | |
// escaping to the openocd command. | |
_, err = gdb.Send("target-select remote | ", openocdPath, "-c", "gdb_port pipe", "--search", openocdScripts, "--file", openocdConfig) | |
if err != nil { | |
log.Fatal(err) | |
} | |
bio := bufio.NewReader(os.Stdin) | |
for { | |
line, _, err := bio.ReadLine() | |
if err != nil { | |
log.Fatal(err) | |
} | |
if string(line) == "int" { | |
fmt.Fprintln(os.Stderr, ">>> Sending interrupt...") | |
gdb.Interrupt() | |
continue | |
} | |
fmt.Fprintln(os.Stderr, ">>> ", string(line)) | |
result, err := gdb.Send(string(line)) | |
switch { | |
case err != nil: | |
log.Print(err) | |
case result["class"] == "done" || result["class"] == "running": | |
if payload, ok := result["payload"]; ok { | |
logThing(payload) | |
} | |
default: | |
logThing(result) | |
} | |
} | |
} | |
func gdb_connect_tcp(gdb gdb.Gdb) { | |
// Giving arguments to gdb.Send separately causes them to be | |
// quoted. Since target-select is not implemented as a proper mi | |
// command inside gdb, but simply executes the "target" CLI | |
// passing the arguments as-is, adding quotes breaks the | |
// processing of these arguments. By putting them in the command | |
// argument to gdb.Send, the values are passed unquoted, making | |
// this command work. | |
result, err := gdb.Send("target-select remote localhost:3333") | |
log.Print(result) | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
// TODO: http://openocd.org/doc/html/GDB-and-OpenOCD.html#Configuring-GDB-for-OpenOCD |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment