2014-05-20 21:29:01 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2014-05-23 20:27:08 +00:00
|
|
|
"runtime"
|
2014-05-20 23:11:00 +00:00
|
|
|
"strconv"
|
2014-05-20 21:29:01 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/Dparker1990/dbg/command"
|
2014-05-20 23:11:00 +00:00
|
|
|
"github.com/Dparker1990/dbg/proctl"
|
2014-05-20 21:29:01 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type term struct {
|
|
|
|
stdin *bufio.Reader
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2014-05-23 20:27:08 +00:00
|
|
|
// We must ensure here that we are running on the same thread during
|
|
|
|
// the execution of dbg. This is due to the fact that ptrace(2) expects
|
2014-05-24 00:01:56 +00:00
|
|
|
// all commands after PTRACE_ATTACH to come from the same thread.
|
2014-05-23 20:27:08 +00:00
|
|
|
runtime.LockOSThread()
|
|
|
|
|
2014-05-20 23:11:00 +00:00
|
|
|
t := newTerm()
|
|
|
|
|
|
|
|
if len(os.Args) == 1 {
|
|
|
|
printStderrAndDie("You must provide a pid\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
pid, err := strconv.Atoi(os.Args[1])
|
|
|
|
if err != nil {
|
|
|
|
printStderrAndDie(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dbgproc, err := proctl.NewDebugProcess(pid)
|
|
|
|
if err != nil {
|
|
|
|
printStderrAndDie("Could not start debugging process:", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cmds := command.DebugCommands()
|
|
|
|
registerProcessCommands(cmds, dbgproc)
|
2014-05-20 21:29:01 +00:00
|
|
|
|
|
|
|
for {
|
|
|
|
cmdstr, err := t.promptForInput()
|
|
|
|
if err != nil {
|
2014-05-20 23:11:00 +00:00
|
|
|
printStderrAndDie("Prompt for input failed.\n")
|
2014-05-20 21:29:01 +00:00
|
|
|
}
|
|
|
|
|
2014-05-27 15:44:29 +00:00
|
|
|
cmdstr, args := parseCommand(cmdstr)
|
|
|
|
|
2014-05-20 21:29:01 +00:00
|
|
|
cmd := cmds.Find(cmdstr)
|
2014-05-27 15:44:29 +00:00
|
|
|
err = cmd(args...)
|
2014-05-20 21:29:01 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "Command failed: %s\n", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-20 23:11:00 +00:00
|
|
|
func printStderrAndDie(args ...interface{}) {
|
|
|
|
fmt.Fprint(os.Stderr, args)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func registerProcessCommands(cmds *command.Commands, proc *proctl.DebuggedProcess) {
|
2014-05-27 15:44:29 +00:00
|
|
|
cmds.Register("step", command.CommandFunc(proc.Step))
|
|
|
|
cmds.Register("continue", command.CommandFunc(proc.Continue))
|
|
|
|
cmds.Register("break", func(args ...string) error {
|
|
|
|
fname := args[0]
|
|
|
|
bp, err := proc.Break(fname)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("Breakpoint set at %#v for %s %s:%d\n", bp.Addr, bp.FunctionName, bp.File, bp.Line)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
2014-05-20 23:11:00 +00:00
|
|
|
}
|
|
|
|
|
2014-05-20 21:29:01 +00:00
|
|
|
func newTerm() *term {
|
|
|
|
return &term{
|
|
|
|
stdin: bufio.NewReader(os.Stdin),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-27 15:44:29 +00:00
|
|
|
func parseCommand(cmdstr string) (string, []string) {
|
|
|
|
vals := strings.Split(cmdstr, " ")
|
|
|
|
return vals[0], vals[1:]
|
|
|
|
}
|
|
|
|
|
2014-05-20 21:29:01 +00:00
|
|
|
func (t *term) promptForInput() (string, error) {
|
|
|
|
fmt.Print("dbg> ")
|
|
|
|
|
|
|
|
line, err := t.stdin.ReadString('\n')
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2014-05-20 21:31:25 +00:00
|
|
|
return strings.TrimSuffix(line, "\n"), nil
|
2014-05-20 21:29:01 +00:00
|
|
|
}
|