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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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,26 +430,27 @@ 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 {
return v, nil
}
origErr := err origErr := err
// workaround: sometimes go inserts an entry for '&varname' instead of varname // workaround: sometimes go inserts an entry for '&varname' instead of varname
v, err = scope.extractVarInfo("&" + node.Name) v, err = scope.extractVarInfo("&" + node.Name)
if err != nil { if err == nil {
v = v.maybeDereference()
v.Name = node.Name
return v, nil
}
// if it's not a local variable then it could be a package variable w/o explicit package name // 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) _, _, fn := scope.Thread.dbp.PCToLine(scope.PC)
if fn != nil { if fn != nil {
if v, err := scope.packageVarAddr(fn.PackageName() + "." + node.Name); err == nil { if v, err = scope.packageVarAddr(fn.PackageName() + "." + node.Name); err == nil {
v.Name = node.Name v.Name = node.Name
return v, nil return v, nil
} }
} }
return nil, origErr return nil, origErr
} }
v = v.maybeDereference()
v.Name = node.Name
}
return v, nil
}
// Evaluates expressions <subexpr>.<field name> where subexpr is not a package name // Evaluates expressions <subexpr>.<field name> where subexpr is not a package name
func (scope *EvalScope) evalStructSelector(node *ast.SelectorExpr) (*Variable, error) { func (scope *EvalScope) evalStructSelector(node *ast.SelectorExpr) (*Variable, error) {

View File

@ -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()

View File

@ -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
} }

View File

@ -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)
} }

View File

@ -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"
) )

View File

@ -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, "[")

View File

@ -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

View File

@ -311,7 +311,7 @@ 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) gid, err := strconv.Atoi(argstr)
if err != nil { if err != nil {
return err return err
@ -328,7 +328,6 @@ func (c *Commands) goroutine(t *Term, ctx callContext, argstr string) error {
fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID) fmt.Printf("Switched from %d to %d (thread %d)\n", oldState.SelectedGoroutine.ID, gid, newState.CurrentThread.ID)
return nil 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)
} }
}

View File

@ -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.
@ -161,7 +157,7 @@ func (t *Term) handleExit() (int, error) {
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
} }
} }