dlv: Misc refactors

This commit is contained in:
Hubert Krauze 2016-03-09 15:11:58 +00:00 committed by Derek Parker
parent ff0ec8ce00
commit 37f124817d
12 changed files with 71 additions and 77 deletions

@ -255,7 +255,7 @@ func traceCmd(cmd *cobra.Command, args []string) {
return 1 return 1
} }
for i := range funcs { 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 { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
return 1 return 1

@ -24,7 +24,7 @@ type Config struct {
func LoadConfig() *Config { func LoadConfig() *Config {
err := createConfigPath() err := createConfigPath()
if err != nil { if err != nil {
fmt.Printf("Could not create config directory: %v.") fmt.Printf("Could not create config directory: %v.", err)
return nil return nil
} }
fullConfigFile, err := GetConfigFilePath(configFile) fullConfigFile, err := GetConfigFilePath(configFile)

@ -25,8 +25,8 @@ type Breakpoint struct {
// Breakpoint information // Breakpoint information
Tracepoint bool // Tracepoint flag Tracepoint bool // Tracepoint flag
Stacktrace int // Number of stack frames to retrieve
Goroutine bool // Retrieve goroutine information Goroutine bool // Retrieve goroutine information
Stacktrace int // Number of stack frames to retrieve
Variables []string // Variables to evaluate Variables []string // Variables to evaluate
HitCount map[int]uint64 // Number of times a breakpoint has been reached in a certain goroutine 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 TotalHitCount uint64 // Number of times a breakpoint has been reached

@ -9,10 +9,10 @@ import (
"go/parser" "go/parser"
"go/printer" "go/printer"
"go/token" "go/token"
"golang.org/x/debug/dwarf"
"reflect" "reflect"
"github.com/derekparker/delve/dwarf/reader" "github.com/derekparker/delve/dwarf/reader"
"golang.org/x/debug/dwarf"
) )
// EvalExpression returns the value of the given expression. // 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 // try to interpret this as a local variable
v, err := scope.extractVarInfo(node.Name) v, err := scope.extractVarInfo(node.Name)
if err != nil { if err == nil {
origErr := err return v, nil
// workaround: sometimes go inserts an entry for '&varname' instead of varname }
v, err = scope.extractVarInfo("&" + node.Name) origErr := err
if err != nil { // workaround: sometimes go inserts an entry for '&varname' instead of varname
// if it's not a local variable then it could be a package variable w/o explicit package name v, err = scope.extractVarInfo("&" + node.Name)
_, _, fn := scope.Thread.dbp.PCToLine(scope.PC) if err == nil {
if fn != nil {
if v, err := scope.packageVarAddr(fn.PackageName() + "." + node.Name); err == nil {
v.Name = node.Name
return v, nil
}
}
return nil, origErr
}
v = v.maybeDereference() v = v.maybeDereference()
v.Name = node.Name 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 <subexpr>.<field name> where subexpr is not a package name // Evaluates expressions <subexpr>.<field name> where subexpr is not a package name

@ -49,11 +49,11 @@ type Process struct {
goSymTable *gosym.Table goSymTable *gosym.Table
frameEntries frame.FrameDescriptionEntries frameEntries frame.FrameDescriptionEntries
lineInfo line.DebugLines lineInfo line.DebugLines
firstStart bool
os *OSProcessDetails os *OSProcessDetails
arch Arch arch Arch
breakpointIDCounter int breakpointIDCounter int
tempBreakpointIDCounter int tempBreakpointIDCounter int
firstStart bool
halt bool halt bool
exited bool exited bool
ptraceChan chan func() ptraceChan chan func()

@ -84,9 +84,9 @@ func (n NullAddrError) Error() string {
type StackIterator struct { type StackIterator struct {
pc, sp uint64 pc, sp uint64
top bool top bool
atend bool
frame Stackframe frame Stackframe
dbp *Process dbp *Process
atend bool
err error err error
} }

@ -396,16 +396,16 @@ func (thread *Thread) onRuntimeBreakpoint() bool {
return loc.Fn != nil && loc.Fn.Name == "runtime.breakpoint" return loc.Fn != nil && loc.Fn.Name == "runtime.breakpoint"
} }
// Returns true if this thread is on the goroutine requested by the current 'next' command // onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command
func (th *Thread) onNextGoroutine() (bool, error) { func (thread *Thread) onNextGoroutine() (bool, error) {
var bp *Breakpoint var bp *Breakpoint
for i := range th.dbp.Breakpoints { for i := range thread.dbp.Breakpoints {
if th.dbp.Breakpoints[i].Temp { if thread.dbp.Breakpoints[i].Temp {
bp = th.dbp.Breakpoints[i] bp = thread.dbp.Breakpoints[i]
} }
} }
if bp == nil { if bp == nil {
return false, nil return false, nil
} }
return bp.checkCondition(th) return bp.checkCondition(thread)
} }

@ -8,11 +8,12 @@ import (
"go/constant" "go/constant"
"go/parser" "go/parser"
"go/token" "go/token"
"golang.org/x/debug/dwarf"
"reflect" "reflect"
"strings" "strings"
"unsafe" "unsafe"
"golang.org/x/debug/dwarf"
"github.com/derekparker/delve/dwarf/op" "github.com/derekparker/delve/dwarf/op"
"github.com/derekparker/delve/dwarf/reader" "github.com/derekparker/delve/dwarf/reader"
) )

@ -3,6 +3,7 @@ package api
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"reflect" "reflect"
) )
@ -13,14 +14,14 @@ const (
indentString = "\t" 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 { func (v *Variable) SinglelineString() string {
var buf bytes.Buffer var buf bytes.Buffer
v.writeTo(&buf, true, false, true, "") v.writeTo(&buf, true, false, true, "")
return buf.String() 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 { func (v *Variable) MultilineString(indent string) string {
var buf bytes.Buffer var buf bytes.Buffer
buf.WriteString(indent) buf.WriteString(indent)
@ -28,7 +29,7 @@ func (v *Variable) MultilineString(indent string) string {
return buf.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 != "" { if v.Unreadable != "" {
fmt.Fprintf(buf, "(unreadable %s)", v.Unreadable) fmt.Fprintf(buf, "(unreadable %s)", v.Unreadable)
return 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 s := v.Value
if len(s) != int(v.Len) { if len(s) != int(v.Len) {
s = fmt.Sprintf("%s...+%d more", s, int(v.Len)-len(s)) 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) 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 { if includeType {
fmt.Fprintf(buf, "%s len: %d, cap: %d, ", v.Type, v.Len, v.Cap) fmt.Fprintf(buf, "%s len: %d, cap: %d, ", v.Type, v.Len, v.Cap)
} }
v.writeSliceOrArrayTo(buf, newlines, indent) 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 { if includeType {
fmt.Fprintf(buf, "%s ", v.Type) fmt.Fprintf(buf, "%s ", v.Type)
} }
v.writeSliceOrArrayTo(buf, newlines, indent) 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) { if int(v.Len) != len(v.Children) {
fmt.Fprintf(buf, "(*%s)(0x%x)", v.Type, v.Addr) fmt.Fprintf(buf, "(*%s)(0x%x)", v.Type, v.Addr)
return return
@ -157,7 +158,7 @@ func (v *Variable) writeStructTo(buf *bytes.Buffer, newlines, includeType bool,
fmt.Fprintf(buf, "}") 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 { if includeType {
fmt.Fprintf(buf, "%s ", v.Type) fmt.Fprintf(buf, "%s ", v.Type)
} }
@ -261,7 +262,7 @@ func (v *Variable) shouldNewlineStruct(newlines bool) bool {
return false 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) nl := v.shouldNewlineArray(newlines)
fmt.Fprintf(buf, "[") fmt.Fprintf(buf, "[")

@ -3,10 +3,11 @@ package api
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/derekparker/delve/proc"
"reflect" "reflect"
"strconv" "strconv"
"unicode" "unicode"
"github.com/derekparker/delve/proc"
) )
// DebuggerState represents the current context of the debugger. // DebuggerState represents the current context of the debugger.
@ -46,10 +47,10 @@ type Breakpoint struct {
// tracepoint flag // tracepoint flag
Tracepoint bool `json:"continue"` Tracepoint bool `json:"continue"`
// number of stack frames to retrieve
Stacktrace int `json:"stacktrace"`
// retrieve goroutine information // retrieve goroutine information
Goroutine bool `json:"goroutine"` Goroutine bool `json:"goroutine"`
// number of stack frames to retrieve
Stacktrace int `json:"stacktrace"`
// variables to evaluate // variables to evaluate
Variables []string `json:"variables,omitempty"` Variables []string `json:"variables,omitempty"`
// number of times a breakpoint has been reached in a certain goroutine // number of times a breakpoint has been reached in a certain goroutine

@ -311,24 +311,23 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error {
} }
if args[0] == "" { if args[0] == "" {
return printscope(t) 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: case 2:
args = append(args, "") 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 { func (c *Commands) frame(t *Term, ctx callContext, args string) error {
v := strings.SplitN(args, " ", 3) v := strings.SplitN(args, " ", 3)
var err error
switch len(v) { switch len(v) {
case 0, 1: case 0, 1:
return errors.New("not enough arguments") return errors.New("not enough arguments")
@ -354,6 +351,7 @@ func (c *Commands) frame(t *Term, ctx callContext, args string) error {
v = append(v, "") v = append(v, "")
} }
var err error
ctx.Prefix = scopePrefix ctx.Prefix = scopePrefix
ctx.Scope.Frame, err = strconv.Atoi(v[0]) ctx.Scope.Frame, err = strconv.Atoi(v[0])
if err != nil { if err != nil {
@ -592,7 +590,7 @@ func setBreakpoint(t *Term, tracepoint bool, argstr string) error {
requestedBp.Name = "" requestedBp.Name = ""
locspec = argstr locspec = argstr
var err2 error 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 { if err2 != nil {
return err return err
} }
@ -1051,13 +1049,11 @@ func exitCommand(t *Term, ctx callContext, args string) error {
return ExitRequestError{} 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 { if id, err := strconv.Atoi(arg); err == nil {
bp, err = t.client.GetBreakpoint(id) return t.client.GetBreakpoint(id)
} else {
bp, err = t.client.GetBreakpointByName(arg)
} }
return return t.client.GetBreakpointByName(arg)
} }
func (c *Commands) onCmd(t *Term, ctx callContext, argstr string) error { 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) p := ShortenFilePath(bp.File)
if bp.FunctionName != "" { if bp.FunctionName != "" {
return fmt.Sprintf("%#v for %s() %s:%d", bp.Addr, bp.FunctionName, p, bp.Line) 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)
} }

@ -102,7 +102,6 @@ func (t *Term) Run() (int, error) {
} }
} }
var status int
for { for {
cmdstr, err := t.promptForInput() cmdstr, err := t.promptForInput()
if err != nil { if err != nil {
@ -110,8 +109,7 @@ func (t *Term) Run() (int, error) {
fmt.Println("exit") fmt.Println("exit")
return t.handleExit() return t.handleExit()
} }
err, status = fmt.Errorf("Prompt for input failed.\n"), 1 return 1, fmt.Errorf("Prompt for input failed.\n")
break
} }
cmdstr, args := parseCommand(cmdstr) cmdstr, args := parseCommand(cmdstr)
@ -129,8 +127,6 @@ func (t *Term) Run() (int, error) {
} }
} }
} }
return status, nil
} }
// Println prints a line to the terminal. // Println prints a line to the terminal.
@ -158,10 +154,10 @@ func (t *Term) promptForInput() (string, error) {
func (t *Term) handleExit() (int, error) { func (t *Term) handleExit() (int, error) {
fullHistoryFile, err := config.GetConfigFilePath(historyFile) fullHistoryFile, err := config.GetConfigFilePath(historyFile)
if err != nil { if err != nil {
fmt.Println("Error saving history file:", err) fmt.Println("Error saving history file: ", err)
} else { } else {
if f, err := os.OpenFile(fullHistoryFile, os.O_RDWR, 0666); err == nil { 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 { if err != nil {
fmt.Println("readline history error: ", err) fmt.Println("readline history error: ", err)
} }
@ -183,8 +179,7 @@ func (t *Term) handleExit() (int, error) {
answer = strings.ToLower(strings.TrimSpace(answer)) answer = strings.ToLower(strings.TrimSpace(answer))
kill = (answer != "n" && answer != "no") kill = (answer != "n" && answer != "no")
} }
err = t.client.Detach(kill) if err := t.client.Detach(kill); err != nil {
if err != nil {
return 1, err return 1, err
} }
} }