diff --git a/cmd/dlv/cmds/commands.go b/cmd/dlv/cmds/commands.go index 6c1ac4ef..467c4999 100644 --- a/cmd/dlv/cmds/commands.go +++ b/cmd/dlv/cmds/commands.go @@ -255,7 +255,7 @@ func traceCmd(cmd *cobra.Command, args []string) { return 1 } for i := range funcs { - _, err := client.CreateBreakpoint(&api.Breakpoint{FunctionName: funcs[i], Tracepoint: true, Line: -1, Stacktrace: traceStackDepth}) + _, err = client.CreateBreakpoint(&api.Breakpoint{FunctionName: funcs[i], Tracepoint: true, Line: -1, Stacktrace: traceStackDepth}) if err != nil { fmt.Fprintln(os.Stderr, err) return 1 diff --git a/config/config.go b/config/config.go index 7381c5d9..58eb5c9f 100644 --- a/config/config.go +++ b/config/config.go @@ -24,7 +24,7 @@ type Config struct { func LoadConfig() *Config { err := createConfigPath() if err != nil { - fmt.Printf("Could not create config directory: %v.") + fmt.Printf("Could not create config directory: %v.", err) return nil } fullConfigFile, err := GetConfigFilePath(configFile) diff --git a/proc/breakpoints.go b/proc/breakpoints.go index c604bd75..235f2633 100644 --- a/proc/breakpoints.go +++ b/proc/breakpoints.go @@ -25,8 +25,8 @@ type Breakpoint struct { // Breakpoint information Tracepoint bool // Tracepoint flag - Stacktrace int // Number of stack frames to retrieve Goroutine bool // Retrieve goroutine information + Stacktrace int // Number of stack frames to retrieve Variables []string // Variables to evaluate HitCount map[int]uint64 // Number of times a breakpoint has been reached in a certain goroutine TotalHitCount uint64 // Number of times a breakpoint has been reached diff --git a/proc/eval.go b/proc/eval.go index 9719432f..1297c045 100644 --- a/proc/eval.go +++ b/proc/eval.go @@ -9,10 +9,10 @@ import ( "go/parser" "go/printer" "go/token" - "golang.org/x/debug/dwarf" "reflect" "github.com/derekparker/delve/dwarf/reader" + "golang.org/x/debug/dwarf" ) // EvalExpression returns the value of the given expression. @@ -430,25 +430,26 @@ func (scope *EvalScope) evalIdent(node *ast.Ident) (*Variable, error) { // try to interpret this as a local variable v, err := scope.extractVarInfo(node.Name) - if err != nil { - origErr := err - // workaround: sometimes go inserts an entry for '&varname' instead of varname - v, err = scope.extractVarInfo("&" + node.Name) - if err != nil { - // if it's not a local variable then it could be a package variable w/o explicit package name - _, _, fn := scope.Thread.dbp.PCToLine(scope.PC) - if fn != nil { - if v, err := scope.packageVarAddr(fn.PackageName() + "." + node.Name); err == nil { - v.Name = node.Name - return v, nil - } - } - return nil, origErr - } + if err == nil { + return v, nil + } + origErr := err + // workaround: sometimes go inserts an entry for '&varname' instead of varname + v, err = scope.extractVarInfo("&" + node.Name) + if err == nil { v = v.maybeDereference() v.Name = node.Name + return v, nil } - return v, nil + // if it's not a local variable then it could be a package variable w/o explicit package name + _, _, fn := scope.Thread.dbp.PCToLine(scope.PC) + if fn != nil { + if v, err = scope.packageVarAddr(fn.PackageName() + "." + node.Name); err == nil { + v.Name = node.Name + return v, nil + } + } + return nil, origErr } // Evaluates expressions . where subexpr is not a package name diff --git a/proc/proc.go b/proc/proc.go index 5f1d3d0e..d329b978 100644 --- a/proc/proc.go +++ b/proc/proc.go @@ -49,11 +49,11 @@ type Process struct { goSymTable *gosym.Table frameEntries frame.FrameDescriptionEntries lineInfo line.DebugLines - firstStart bool os *OSProcessDetails arch Arch breakpointIDCounter int tempBreakpointIDCounter int + firstStart bool halt bool exited bool ptraceChan chan func() diff --git a/proc/stack.go b/proc/stack.go index 280aae72..f0a0226a 100644 --- a/proc/stack.go +++ b/proc/stack.go @@ -84,9 +84,9 @@ func (n NullAddrError) Error() string { type StackIterator struct { pc, sp uint64 top bool + atend bool frame Stackframe dbp *Process - atend bool err error } diff --git a/proc/threads.go b/proc/threads.go index d3904b55..47d872a3 100644 --- a/proc/threads.go +++ b/proc/threads.go @@ -396,16 +396,16 @@ func (thread *Thread) onRuntimeBreakpoint() bool { return loc.Fn != nil && loc.Fn.Name == "runtime.breakpoint" } -// Returns true if this thread is on the goroutine requested by the current 'next' command -func (th *Thread) onNextGoroutine() (bool, error) { +// onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command +func (thread *Thread) onNextGoroutine() (bool, error) { var bp *Breakpoint - for i := range th.dbp.Breakpoints { - if th.dbp.Breakpoints[i].Temp { - bp = th.dbp.Breakpoints[i] + for i := range thread.dbp.Breakpoints { + if thread.dbp.Breakpoints[i].Temp { + bp = thread.dbp.Breakpoints[i] } } if bp == nil { return false, nil } - return bp.checkCondition(th) + return bp.checkCondition(thread) } diff --git a/proc/variables.go b/proc/variables.go index a6856cf5..373c1fa0 100644 --- a/proc/variables.go +++ b/proc/variables.go @@ -8,11 +8,12 @@ import ( "go/constant" "go/parser" "go/token" - "golang.org/x/debug/dwarf" "reflect" "strings" "unsafe" + "golang.org/x/debug/dwarf" + "github.com/derekparker/delve/dwarf/op" "github.com/derekparker/delve/dwarf/reader" ) diff --git a/service/api/prettyprint.go b/service/api/prettyprint.go index 17d916dc..38f48891 100644 --- a/service/api/prettyprint.go +++ b/service/api/prettyprint.go @@ -3,6 +3,7 @@ package api import ( "bytes" "fmt" + "io" "reflect" ) @@ -13,14 +14,14 @@ const ( indentString = "\t" ) -// Returns a representation of v on a single line +// SinglelineString returns a representation of v on a single line. func (v *Variable) SinglelineString() string { var buf bytes.Buffer v.writeTo(&buf, true, false, true, "") return buf.String() } -// Returns a representation of v on multiple lines +// MultilineString returns a representation of v on multiple lines. func (v *Variable) MultilineString(indent string) string { var buf bytes.Buffer buf.WriteString(indent) @@ -28,7 +29,7 @@ func (v *Variable) MultilineString(indent string) string { return buf.String() } -func (v *Variable) writeTo(buf *bytes.Buffer, top, newlines, includeType bool, indent string) { +func (v *Variable) writeTo(buf io.Writer, top, newlines, includeType bool, indent string) { if v.Unreadable != "" { fmt.Fprintf(buf, "(unreadable %s)", v.Unreadable) return @@ -101,7 +102,7 @@ func (v *Variable) writeTo(buf *bytes.Buffer, top, newlines, includeType bool, i } } -func (v *Variable) writeStringTo(buf *bytes.Buffer) { +func (v *Variable) writeStringTo(buf io.Writer) { s := v.Value if len(s) != int(v.Len) { s = fmt.Sprintf("%s...+%d more", s, int(v.Len)-len(s)) @@ -109,21 +110,21 @@ func (v *Variable) writeStringTo(buf *bytes.Buffer) { fmt.Fprintf(buf, "%q", s) } -func (v *Variable) writeSliceTo(buf *bytes.Buffer, newlines, includeType bool, indent string) { +func (v *Variable) writeSliceTo(buf io.Writer, newlines, includeType bool, indent string) { if includeType { fmt.Fprintf(buf, "%s len: %d, cap: %d, ", v.Type, v.Len, v.Cap) } v.writeSliceOrArrayTo(buf, newlines, indent) } -func (v *Variable) writeArrayTo(buf *bytes.Buffer, newlines, includeType bool, indent string) { +func (v *Variable) writeArrayTo(buf io.Writer, newlines, includeType bool, indent string) { if includeType { fmt.Fprintf(buf, "%s ", v.Type) } v.writeSliceOrArrayTo(buf, newlines, indent) } -func (v *Variable) writeStructTo(buf *bytes.Buffer, newlines, includeType bool, indent string) { +func (v *Variable) writeStructTo(buf io.Writer, newlines, includeType bool, indent string) { if int(v.Len) != len(v.Children) { fmt.Fprintf(buf, "(*%s)(0x%x)", v.Type, v.Addr) return @@ -157,7 +158,7 @@ func (v *Variable) writeStructTo(buf *bytes.Buffer, newlines, includeType bool, fmt.Fprintf(buf, "}") } -func (v *Variable) writeMapTo(buf *bytes.Buffer, newlines, includeType bool, indent string) { +func (v *Variable) writeMapTo(buf io.Writer, newlines, includeType bool, indent string) { if includeType { fmt.Fprintf(buf, "%s ", v.Type) } @@ -261,7 +262,7 @@ func (v *Variable) shouldNewlineStruct(newlines bool) bool { return false } -func (v *Variable) writeSliceOrArrayTo(buf *bytes.Buffer, newlines bool, indent string) { +func (v *Variable) writeSliceOrArrayTo(buf io.Writer, newlines bool, indent string) { nl := v.shouldNewlineArray(newlines) fmt.Fprintf(buf, "[") diff --git a/service/api/types.go b/service/api/types.go index f8dea74a..f619a3b5 100644 --- a/service/api/types.go +++ b/service/api/types.go @@ -3,10 +3,11 @@ package api import ( "errors" "fmt" - "github.com/derekparker/delve/proc" "reflect" "strconv" "unicode" + + "github.com/derekparker/delve/proc" ) // DebuggerState represents the current context of the debugger. @@ -46,10 +47,10 @@ type Breakpoint struct { // tracepoint flag Tracepoint bool `json:"continue"` - // number of stack frames to retrieve - Stacktrace int `json:"stacktrace"` // retrieve goroutine information Goroutine bool `json:"goroutine"` + // number of stack frames to retrieve + Stacktrace int `json:"stacktrace"` // variables to evaluate Variables []string `json:"variables,omitempty"` // number of times a breakpoint has been reached in a certain goroutine diff --git a/terminal/command.go b/terminal/command.go index e0499311..f069b7dc 100644 --- a/terminal/command.go +++ b/terminal/command.go @@ -311,24 +311,23 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error { } if args[0] == "" { return printscope(t) - } else { - gid, err := strconv.Atoi(argstr) - if err != nil { - return err - } - - oldState, err := t.client.GetState() - if err != nil { - return err - } - newState, err := t.client.SwitchGoroutine(gid) - if err != nil { - return err - } - - fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID) - return nil } + gid, err := strconv.Atoi(argstr) + if err != nil { + return err + } + + oldState, err := t.client.GetState() + if err != nil { + return err + } + newState, err := t.client.SwitchGoroutine(gid) + if err != nil { + return err + } + + fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID) + return nil case 2: args = append(args, "") } @@ -345,8 +344,6 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error { func (c *Commands) frame(t *Term, ctx callContext, args string) error { v := strings.SplitN(args, " ", 3) - var err error - switch len(v) { case 0, 1: return errors.New("not enough arguments") @@ -354,6 +351,7 @@ func (c *Commands) frame(t *Term, ctx callContext, args string) error { v = append(v, "") } + var err error ctx.Prefix = scopePrefix ctx.Scope.Frame, err = strconv.Atoi(v[0]) if err != nil { @@ -592,7 +590,7 @@ func setBreakpoint(t *Term, tracepoint bool, argstr string) error { requestedBp.Name = "" locspec = argstr var err2 error - locs, err2 = t.client.FindLocation(api.EvalScope{-1, 0}, locspec) + locs, err2 = t.client.FindLocation(api.EvalScope{GoroutineID: -1, Frame: 0}, locspec) if err2 != nil { return err } @@ -1051,13 +1049,11 @@ func exitCommand(t *Term, ctx callContext, args string) error { return ExitRequestError{} } -func getBreakpointByIDOrName(t *Term, arg string) (bp *api.Breakpoint, err error) { +func getBreakpointByIDOrName(t *Term, arg string) (*api.Breakpoint, error) { if id, err := strconv.Atoi(arg); err == nil { - bp, err = t.client.GetBreakpoint(id) - } else { - bp, err = t.client.GetBreakpointByName(arg) + return t.client.GetBreakpoint(id) } - return + return t.client.GetBreakpointByName(arg) } func (c *Commands) onCmd(t *Term, ctx callContext, argstr string) error { @@ -1154,7 +1150,6 @@ func formatBreakpointLocation(bp *api.Breakpoint) string { p := ShortenFilePath(bp.File) if bp.FunctionName != "" { return fmt.Sprintf("%#v for %s() %s:%d", bp.Addr, bp.FunctionName, p, bp.Line) - } else { - return fmt.Sprintf("%#v for %s:%d", bp.Addr, p, bp.Line) } + return fmt.Sprintf("%#v for %s:%d", bp.Addr, p, bp.Line) } diff --git a/terminal/terminal.go b/terminal/terminal.go index 7ca55cfc..3668a399 100644 --- a/terminal/terminal.go +++ b/terminal/terminal.go @@ -102,7 +102,6 @@ func (t *Term) Run() (int, error) { } } - var status int for { cmdstr, err := t.promptForInput() if err != nil { @@ -110,8 +109,7 @@ func (t *Term) Run() (int, error) { fmt.Println("exit") return t.handleExit() } - err, status = fmt.Errorf("Prompt for input failed.\n"), 1 - break + return 1, fmt.Errorf("Prompt for input failed.\n") } cmdstr, args := parseCommand(cmdstr) @@ -129,8 +127,6 @@ func (t *Term) Run() (int, error) { } } } - - return status, nil } // Println prints a line to the terminal. @@ -158,10 +154,10 @@ func (t *Term) promptForInput() (string, error) { func (t *Term) handleExit() (int, error) { fullHistoryFile, err := config.GetConfigFilePath(historyFile) if err != nil { - fmt.Println("Error saving history file:", err) + fmt.Println("Error saving history file: ", err) } else { if f, err := os.OpenFile(fullHistoryFile, os.O_RDWR, 0666); err == nil { - _, err := t.line.WriteHistory(f) + _, err = t.line.WriteHistory(f) if err != nil { fmt.Println("readline history error: ", err) } @@ -183,8 +179,7 @@ func (t *Term) handleExit() (int, error) { answer = strings.ToLower(strings.TrimSpace(answer)) kill = (answer != "n" && answer != "no") } - err = t.client.Detach(kill) - if err != nil { + if err := t.client.Detach(kill); err != nil { return 1, err } }