summaryrefslogtreecommitdiff
path: root/libgo/go/exp/ogle/cmd.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/exp/ogle/cmd.go')
-rw-r--r--libgo/go/exp/ogle/cmd.go373
1 files changed, 0 insertions, 373 deletions
diff --git a/libgo/go/exp/ogle/cmd.go b/libgo/go/exp/ogle/cmd.go
deleted file mode 100644
index a8db523ea18..00000000000
--- a/libgo/go/exp/ogle/cmd.go
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package ogle is the beginning of a debugger for Go.
-package ogle
-
-import (
- "bufio"
- "debug/elf"
- "debug/proc"
- "exp/eval"
- "fmt"
- "go/scanner"
- "go/token"
- "os"
- "strconv"
- "strings"
-)
-
-var fset = token.NewFileSet()
-var world *eval.World
-var curProc *Process
-
-func Main() {
- world = eval.NewWorld()
- defineFuncs()
- r := bufio.NewReader(os.Stdin)
- for {
- print("; ")
- line, err := r.ReadSlice('\n')
- if err != nil {
- break
- }
-
- // Try line as a command
- cmd, rest := getCmd(line)
- if cmd != nil {
- err := cmd.handler(rest)
- if err != nil {
- scanner.PrintError(os.Stderr, err)
- }
- continue
- }
-
- // Try line as code
- code, err := world.Compile(fset, string(line))
- if err != nil {
- scanner.PrintError(os.Stderr, err)
- continue
- }
- v, err := code.Run()
- if err != nil {
- fmt.Fprintf(os.Stderr, err.String())
- continue
- }
- if v != nil {
- println(v.String())
- }
- }
-}
-
-// newScanner creates a new scanner that scans that given input bytes.
-func newScanner(input []byte) (*scanner.Scanner, *scanner.ErrorVector) {
- sc := new(scanner.Scanner)
- ev := new(scanner.ErrorVector)
- file := fset.AddFile("input", fset.Base(), len(input))
- sc.Init(file, input, ev, 0)
- return sc, ev
-}
-
-/*
- * Commands
- */
-
-// A UsageError occurs when a command is called with illegal arguments.
-type UsageError string
-
-func (e UsageError) String() string { return string(e) }
-
-// A cmd represents a single command with a handler.
-type cmd struct {
- cmd string
- handler func([]byte) os.Error
-}
-
-var cmds = []cmd{
- {"load", cmdLoad},
- {"bt", cmdBt},
-}
-
-// getCmd attempts to parse an input line as a registered command. If
-// successful, it returns the command and the bytes remaining after
-// the command, which should be passed to the command.
-func getCmd(line []byte) (*cmd, []byte) {
- sc, _ := newScanner(line)
- pos, tok, lit := sc.Scan()
- if sc.ErrorCount != 0 || tok != token.IDENT {
- return nil, nil
- }
-
- slit := string(lit)
- for i := range cmds {
- if cmds[i].cmd == slit {
- return &cmds[i], line[fset.Position(pos).Offset+len(lit):]
- }
- }
- return nil, nil
-}
-
-// cmdLoad starts or attaches to a process. Its form is similar to
-// import:
-//
-// load [sym] "path" [;]
-//
-// sym specifies the name to give to the process. If not given, the
-// name is derived from the path of the process. If ".", then the
-// packages from the remote process are defined into the current
-// namespace. If given, this symbol is defined as a package
-// containing the process' packages.
-//
-// path gives the path of the process to start or attach to. If it is
-// "pid:<num>", then attach to the given PID. Otherwise, treat it as
-// a file path and space-separated arguments and start a new process.
-//
-// load always sets the current process to the loaded process.
-func cmdLoad(args []byte) os.Error {
- ident, path, err := parseLoad(args)
- if err != nil {
- return err
- }
- if curProc != nil {
- return UsageError("multiple processes not implemented")
- }
- if ident != "." {
- return UsageError("process identifiers not implemented")
- }
-
- // Parse argument and start or attach to process
- var fname string
- var tproc proc.Process
- if len(path) >= 4 && path[0:4] == "pid:" {
- pid, err := strconv.Atoi(path[4:])
- if err != nil {
- return err
- }
- fname, err = os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
- if err != nil {
- return err
- }
- tproc, err = proc.Attach(pid)
- if err != nil {
- return err
- }
- println("Attached to", pid)
- } else {
- parts := strings.Split(path, " ", -1)
- if len(parts) == 0 {
- fname = ""
- } else {
- fname = parts[0]
- }
- tproc, err = proc.StartProcess(fname, parts, &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}})
- if err != nil {
- return err
- }
- println("Started", path)
- // TODO(austin) If we fail after this point, kill tproc
- // before detaching.
- }
-
- // Get symbols
- f, err := os.Open(fname)
- if err != nil {
- tproc.Detach()
- return err
- }
- defer f.Close()
- elf, err := elf.NewFile(f)
- if err != nil {
- tproc.Detach()
- return err
- }
- curProc, err = NewProcessElf(tproc, elf)
- if err != nil {
- tproc.Detach()
- return err
- }
-
- // Prepare new process
- curProc.OnGoroutineCreate().AddHandler(EventPrint)
- curProc.OnGoroutineExit().AddHandler(EventPrint)
-
- err = curProc.populateWorld(world)
- if err != nil {
- tproc.Detach()
- return err
- }
-
- return nil
-}
-
-func parseLoad(args []byte) (ident string, path string, err os.Error) {
- err = UsageError("Usage: load [sym] \"path\"")
- sc, ev := newScanner(args)
-
- var toks [4]token.Token
- var lits [4]string
- for i := range toks {
- _, toks[i], lits[i] = sc.Scan()
- }
- if sc.ErrorCount != 0 {
- err = ev.GetError(scanner.NoMultiples)
- return
- }
-
- i := 0
- switch toks[i] {
- case token.PERIOD, token.IDENT:
- ident = string(lits[i])
- i++
- }
-
- if toks[i] != token.STRING {
- return
- }
- path, uerr := strconv.Unquote(string(lits[i]))
- if uerr != nil {
- err = uerr
- return
- }
- i++
-
- if toks[i] == token.SEMICOLON {
- i++
- }
- if toks[i] != token.EOF {
- return
- }
-
- return ident, path, nil
-}
-
-// cmdBt prints a backtrace for the current goroutine. It takes no
-// arguments.
-func cmdBt(args []byte) os.Error {
- err := parseNoArgs(args, "Usage: bt")
- if err != nil {
- return err
- }
-
- if curProc == nil || curProc.curGoroutine == nil {
- return NoCurrentGoroutine{}
- }
-
- f := curProc.curGoroutine.frame
- if f == nil {
- fmt.Println("No frames on stack")
- return nil
- }
-
- for f.Inner() != nil {
- f = f.Inner()
- }
-
- for i := 0; i < 100; i++ {
- if f == curProc.curGoroutine.frame {
- fmt.Printf("=> ")
- } else {
- fmt.Printf(" ")
- }
- fmt.Printf("%8x %v\n", f.pc, f)
- f, err = f.Outer()
- if err != nil {
- return err
- }
- if f == nil {
- return nil
- }
- }
-
- fmt.Println("...")
- return nil
-}
-
-func parseNoArgs(args []byte, usage string) os.Error {
- sc, ev := newScanner(args)
- _, tok, _ := sc.Scan()
- if sc.ErrorCount != 0 {
- return ev.GetError(scanner.NoMultiples)
- }
- if tok != token.EOF {
- return UsageError(usage)
- }
- return nil
-}
-
-/*
- * Functions
- */
-
-// defineFuncs populates world with the built-in functions.
-func defineFuncs() {
- t, v := eval.FuncFromNativeTyped(fnOut, fnOutSig)
- world.DefineConst("Out", t, v)
- t, v = eval.FuncFromNativeTyped(fnContWait, fnContWaitSig)
- world.DefineConst("ContWait", t, v)
- t, v = eval.FuncFromNativeTyped(fnBpSet, fnBpSetSig)
- world.DefineConst("BpSet", t, v)
-}
-
-// printCurFrame prints the current stack frame, as it would appear in
-// a backtrace.
-func printCurFrame() {
- if curProc == nil || curProc.curGoroutine == nil {
- return
- }
- f := curProc.curGoroutine.frame
- if f == nil {
- return
- }
- fmt.Printf("=> %8x %v\n", f.pc, f)
-}
-
-// fnOut moves the current frame to the caller of the current frame.
-func fnOutSig() {}
-func fnOut(t *eval.Thread, args []eval.Value, res []eval.Value) {
- if curProc == nil {
- t.Abort(NoCurrentGoroutine{})
- }
- err := curProc.Out()
- if err != nil {
- t.Abort(err)
- }
- // TODO(austin) Only in the command form
- printCurFrame()
-}
-
-// fnContWait continues the current process and waits for a stopping event.
-func fnContWaitSig() {}
-func fnContWait(t *eval.Thread, args []eval.Value, res []eval.Value) {
- if curProc == nil {
- t.Abort(NoCurrentGoroutine{})
- }
- err := curProc.ContWait()
- if err != nil {
- t.Abort(err)
- }
- // TODO(austin) Only in the command form
- ev := curProc.Event()
- if ev != nil {
- fmt.Printf("%v\n", ev)
- }
- printCurFrame()
-}
-
-// fnBpSet sets a breakpoint at the entry to the named function.
-func fnBpSetSig(string) {}
-func fnBpSet(t *eval.Thread, args []eval.Value, res []eval.Value) {
- // TODO(austin) This probably shouldn't take a symbol name.
- // Perhaps it should take an interface that provides PC's.
- // Functions and instructions can implement that interface and
- // we can have something to translate file:line pairs.
- if curProc == nil {
- t.Abort(NoCurrentGoroutine{})
- }
- name := args[0].(eval.StringValue).Get(t)
- fn := curProc.syms.LookupFunc(name)
- if fn == nil {
- t.Abort(UsageError("no such function " + name))
- }
- curProc.OnBreakpoint(proc.Word(fn.Entry)).AddHandler(EventStop)
-}