提交 b5903251 编写于 作者: A aarzilli 提交者: Derek Parker

proc,service,terminal: eval expressions in the scope of a deferred call

Add ability to evaluate variables on the scope of a deferred call's
argument frame.
上级 d2904322
......@@ -14,6 +14,7 @@ Command | Description
[condition](#condition) | Set breakpoint condition.
[config](#config) | Changes configuration parameters.
[continue](#continue) | Run until breakpoint or program termination.
[deferred](#deferred) | Executes command in the context of a deferred call.
[disassemble](#disassemble) | Disassembler.
[down](#down) | Move the current frame down.
[edit](#edit) | Open where you are in $DELVE_EDITOR or $EDITOR
......@@ -161,6 +162,14 @@ Run until breakpoint or program termination.
Aliases: c
## deferred
Executes command in the context of a deferred call.
deferred <n> <command>
Executes the specified command (print, args, locals) in the context of the n-th deferred call in the current frame.
## disassemble
Disassembler.
......@@ -341,10 +350,11 @@ If regex is specified only the source files matching it will be returned.
## stack
Print stack trace.
[goroutine <n>] [frame <m>] stack [<depth>] [-full] [-g] [-s] [-offsets]
[goroutine <n>] [frame <m>] stack [<depth>] [-full] [-offsets] [-defer]
-full every stackframe is decorated with the value of its local variables and arguments.
-offsets prints frame offset of each frame
-offsets prints frame offset of each frame.
-defer prints deferred function call stack for each frame.
Aliases: bt
......
......@@ -5,21 +5,21 @@ import "runtime"
func f1() {
}
func f2() {
func f2(a int8, b int32) {
}
func f3() {
}
func call1() {
defer f2()
defer f2(1, -1)
defer f1()
call2()
}
func call2() {
defer f3()
defer f2()
defer f2(42, 61)
call3()
}
......
......@@ -544,7 +544,8 @@ func FindGoroutine(dbp Process, gid int) (*G, error) {
// ConvertEvalScope returns a new EvalScope in the context of the
// specified goroutine ID and stack frame.
func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) {
// If deferCall is > 0 the eval scope will be relative to the specified deferred call.
func ConvertEvalScope(dbp Process, gid, frame, deferCall int) (*EvalScope, error) {
if _, err := dbp.Valid(); err != nil {
return nil, err
}
......@@ -564,7 +565,7 @@ func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) {
thread = g.Thread
}
locs, err := g.Stacktrace(frame+1, false)
locs, err := g.Stacktrace(frame+1, deferCall > 0)
if err != nil {
return nil, err
}
......@@ -573,6 +574,19 @@ func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) {
return nil, fmt.Errorf("Frame %d does not exist in goroutine %d", frame, gid)
}
if deferCall > 0 {
if deferCall-1 >= len(locs[frame].Defers) {
return nil, fmt.Errorf("Frame %d only has %d deferred calls", frame, len(locs[frame].Defers))
}
d := locs[frame].Defers[deferCall-1]
if d.Unreadable != nil {
return nil, d.Unreadable
}
return d.EvalScope(ct)
}
return FrameToScope(dbp.BinInfo(), thread, g, locs[frame:]...), nil
}
......
......@@ -1263,7 +1263,7 @@ func TestFrameEvaluation(t *testing.T) {
continue
}
scope, err := proc.ConvertEvalScope(p, g.ID, frame)
scope, err := proc.ConvertEvalScope(p, g.ID, frame, 0)
assertNoError(err, t, "ConvertEvalScope()")
t.Logf("scope = %v", scope)
v, err := scope.EvalVariable("i", normalLoadConfig)
......@@ -1288,7 +1288,7 @@ func TestFrameEvaluation(t *testing.T) {
assertNoError(err, t, "GetG()")
for i := 0; i <= 3; i++ {
scope, err := proc.ConvertEvalScope(p, g.ID, i+1)
scope, err := proc.ConvertEvalScope(p, g.ID, i+1, 0)
assertNoError(err, t, fmt.Sprintf("ConvertEvalScope() on frame %d", i+1))
v, err := scope.EvalVariable("n", normalLoadConfig)
assertNoError(err, t, fmt.Sprintf("EvalVariable() on frame %d", i+1))
......@@ -4041,3 +4041,46 @@ func TestNextUnknownInstr(t *testing.T) {
assertNoError(proc.Next(p), t, "Next()")
})
}
func TestReadDeferArgs(t *testing.T) {
var tests = []struct {
frame, deferCall int
a, b int64
}{
{1, 1, 42, 61},
{2, 2, 1, -1},
}
withTestProcess("deferstack", t, func(p proc.Process, fixture protest.Fixture) {
assertNoError(proc.Continue(p), t, "Continue()")
for _, test := range tests {
scope, err := proc.ConvertEvalScope(p, -1, test.frame, test.deferCall)
assertNoError(err, t, fmt.Sprintf("ConvertEvalScope(-1, %d, %d)", test.frame, test.deferCall))
if scope.Fn.Name != "main.f2" {
t.Fatalf("expected function \"main.f2\" got %q", scope.Fn.Name)
}
avar, err := scope.EvalVariable("a", normalLoadConfig)
if err != nil {
t.Fatal(err)
}
bvar, err := scope.EvalVariable("b", normalLoadConfig)
if err != nil {
t.Fatal(err)
}
a, _ := constant.Int64Val(avar.Value)
b, _ := constant.Int64Val(bvar.Value)
if a != test.a {
t.Errorf("value of argument 'a' at frame %d, deferred call %d: %d (expected %d)", test.frame, test.deferCall, a, test.a)
}
if b != test.b {
t.Errorf("value of argument 'b' at frame %d, deferred call %d: %d (expected %d)", test.frame, test.deferCall, b, test.b)
}
}
})
}
......@@ -594,6 +594,7 @@ type Defer struct {
DeferPC uint64 // PC address of instruction that added this defer
SP uint64 // Value of SP register when this function was deferred (this field gets adjusted when the stack is moved to match the new stack space)
link *Defer // Next deferred function
argSz int64
variable *Variable
Unreadable error
......@@ -660,6 +661,7 @@ func (d *Defer) load() {
d.DeferPC, _ = constant.Uint64Val(d.variable.fieldVariable("pc").Value)
d.SP, _ = constant.Uint64Val(d.variable.fieldVariable("sp").Value)
d.argSz, _ = constant.Int64Val(d.variable.fieldVariable("siz").Value)
linkvar := d.variable.fieldVariable("link").maybeDereference()
if linkvar.Addr != 0 {
......@@ -685,3 +687,40 @@ func (d *Defer) Next() *Defer {
}
return d.link
}
// EvalScope returns an EvalScope relative to the argument frame of this deferred call.
// The argument frame of a deferred call is stored in memory immediately
// after the deferred header.
func (d *Defer) EvalScope(thread Thread) (*EvalScope, error) {
scope, err := GoroutineScope(thread)
if err != nil {
return nil, fmt.Errorf("could not get scope: %v", err)
}
bi := thread.BinInfo()
scope.PC = d.DeferredPC
scope.File, scope.Line, scope.Fn = bi.PCToLine(d.DeferredPC)
if scope.Fn == nil {
return nil, fmt.Errorf("could not find function at %#x", d.DeferredPC)
}
// The arguments are stored immediately after the defer header struct, i.e.
// addr+sizeof(_defer). Since CFA in go is always the address of the first
// argument, that's what we use for the value of CFA.
// For SP we use CFA minus the size of one pointer because that would be
// the space occupied by pushing the return address on the stack during the
// CALL.
scope.Regs.CFA = (int64(d.variable.Addr) + d.variable.RealType.Common().ByteSize)
scope.Regs.Regs[scope.Regs.SPRegNum].Uint64Val = uint64(scope.Regs.CFA - int64(bi.Arch.PtrSize()))
bi.dwarfReader.Seek(scope.Fn.offset)
e, err := bi.dwarfReader.Next()
if err != nil {
return nil, fmt.Errorf("could not read DWARF function entry: %v", err)
}
scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs)
scope.Mem = cacheMemory(scope.Mem, uintptr(scope.Regs.CFA), int(d.argSz))
return scope, nil
}
......@@ -32,6 +32,7 @@ type cmdPrefix int
const (
noPrefix = cmdPrefix(0)
onPrefix = cmdPrefix(1 << iota)
deferredPrefix
)
type callContext struct {
......@@ -188,7 +189,7 @@ Called without arguments it will show information about the current goroutine.
Called with a single argument it will switch to the specified goroutine.
Called with more arguments it will execute a command on the specified goroutine.`},
{aliases: []string{"breakpoints", "bp"}, cmdFn: breakpoints, helpMsg: "Print out info for active breakpoints."},
{aliases: []string{"print", "p"}, allowedPrefixes: onPrefix, cmdFn: printVar, helpMsg: `Evaluate an expression.
{aliases: []string{"print", "p"}, allowedPrefixes: onPrefix | deferredPrefix, cmdFn: printVar, helpMsg: `Evaluate an expression.
[goroutine <n>] [frame <m>] print <expression>
......@@ -216,12 +217,12 @@ If regex is specified only the functions matching it will be returned.`},
types [<regex>]
If regex is specified only the types matching it will be returned.`},
{aliases: []string{"args"}, allowedPrefixes: onPrefix, cmdFn: args, helpMsg: `Print function arguments.
{aliases: []string{"args"}, allowedPrefixes: onPrefix | deferredPrefix, cmdFn: args, helpMsg: `Print function arguments.
[goroutine <n>] [frame <m>] args [-v] [<regex>]
If regex is specified only function arguments with a name matching it will be returned. If -v is specified more information about each function argument will be shown.`},
{aliases: []string{"locals"}, allowedPrefixes: onPrefix, cmdFn: locals, helpMsg: `Print local variables.
{aliases: []string{"locals"}, allowedPrefixes: onPrefix | deferredPrefix, cmdFn: locals, helpMsg: `Print local variables.
[goroutine <n>] [frame <m>] locals [-v] [<regex>]
......@@ -250,10 +251,11 @@ When connected to a headless instance started with the --accept-multiclient, pas
Show source around current point or provided linespec.`},
{aliases: []string{"stack", "bt"}, allowedPrefixes: onPrefix, cmdFn: stackCommand, helpMsg: `Print stack trace.
[goroutine <n>] [frame <m>] stack [<depth>] [-full] [-g] [-s] [-offsets]
[goroutine <n>] [frame <m>] stack [<depth>] [-full] [-offsets] [-defer]
-full every stackframe is decorated with the value of its local variables and arguments.
-offsets prints frame offset of each frame
-offsets prints frame offset of each frame.
-defer prints deferred function call stack for each frame.
`},
{aliases: []string{"frame"},
cmdFn: func(t *Term, ctx callContext, arg string) error {
......@@ -286,6 +288,11 @@ Move the current frame up by <m>. The second form runs the command on the given
down [<m>] <command>
Move the current frame down by <m>. The second form runs the command on the given frame.`},
{aliases: []string{"deferred"}, cmdFn: c.deferredCommand, helpMsg: `Executes command in the context of a deferred call.
deferred <n> <command>
Executes the specified command (print, args, locals) in the context of the n-th deferred call in the current frame.`},
{aliases: []string{"source"}, cmdFn: c.sourceCommand, helpMsg: `Executes a file containing a list of delve commands
source <path>`},
......@@ -428,7 +435,7 @@ func (c *Commands) CallWithContext(cmdstr string, t *Term, ctx callContext) erro
// Call takes a command to execute.
func (c *Commands) Call(cmdstr string, t *Term) error {
ctx := callContext{Prefix: noPrefix, Scope: api.EvalScope{GoroutineID: -1, Frame: c.frame}}
ctx := callContext{Prefix: noPrefix, Scope: api.EvalScope{GoroutineID: -1, Frame: c.frame, DeferredCall: 0}}
return c.CallWithContext(cmdstr, t, ctx)
}
......@@ -716,6 +723,22 @@ func (c *Commands) frameCommand(t *Term, ctx callContext, argstr string, directi
return nil
}
func (c *Commands) deferredCommand(t *Term, ctx callContext, argstr string) error {
ctx.Prefix = deferredPrefix
space := strings.Index(argstr, " ")
var err error
ctx.Scope.DeferredCall, err = strconv.Atoi(argstr[:space])
if err != nil {
return err
}
if ctx.Scope.DeferredCall <= 0 {
return errors.New("argument of deferred must be a number greater than 0 (use 'stack -defer' to see the list of deferred calls)")
}
return c.CallWithContext(argstr[space:], t, ctx)
}
func printscope(t *Term) error {
state, err := t.client.GetState()
if err != nil {
......@@ -1573,7 +1596,7 @@ func printStack(stack []api.Stackframe, ind string, offsets bool) {
}
for j, d := range stack[i].Defers {
deferHeader := fmt.Sprintf("%s defer %d: ", s, j)
deferHeader := fmt.Sprintf("%s defer %d: ", s, j+1)
s2 := strings.Repeat(" ", len(deferHeader))
if d.Unreadable != "" {
fmt.Printf("%s(unreadable defer: %s)\n", deferHeader, d.Unreadable)
......
......@@ -324,8 +324,9 @@ type BreakpointInfo struct {
// EvalScope is the scope a command should
// be evaluated in. Describes the goroutine and frame number.
type EvalScope struct {
GoroutineID int
Frame int
GoroutineID int
Frame int
DeferredCall int // when DeferredCall is n > 0 this eval scope is relative to the n-th deferred call in the current frame
}
const (
......
......@@ -825,7 +825,7 @@ func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]a
d.processMutex.Lock()
defer d.processMutex.Unlock()
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame)
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
if err != nil {
return nil, err
}
......@@ -841,7 +841,7 @@ func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) (
d.processMutex.Lock()
defer d.processMutex.Unlock()
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame)
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
if err != nil {
return nil, err
}
......@@ -858,7 +858,7 @@ func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg p
d.processMutex.Lock()
defer d.processMutex.Unlock()
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame)
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
if err != nil {
return nil, err
}
......@@ -875,7 +875,7 @@ func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string)
d.processMutex.Lock()
defer d.processMutex.Unlock()
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame)
s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
if err != nil {
return err
}
......@@ -1009,7 +1009,7 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat
return nil, err
}
s, _ := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame)
s, _ := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
locs, err := loc.Find(d, s, locStr)
for i := range locs {
......
......@@ -76,7 +76,7 @@ type LocationFinder interface {
}
func findLocationHelper(t *testing.T, c LocationFinder, loc string, shouldErr bool, count int, checkAddr uint64) []uint64 {
locs, err := c.FindLocation(api.EvalScope{-1, 0}, loc)
locs, err := c.FindLocation(api.EvalScope{-1, 0, 0}, loc)
t.Logf("FindLocation(\"%s\") → %v\n", loc, locs)
if shouldErr {
......
......@@ -433,7 +433,7 @@ func Test1ClientServer_infoLocals(t *testing.T) {
if state.Err != nil {
t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
}
locals, err := c.ListLocalVariables(api.EvalScope{-1, 0})
locals, err := c.ListLocalVariables(api.EvalScope{-1, 0, 0})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
......@@ -461,7 +461,7 @@ func Test1ClientServer_infoArgs(t *testing.T) {
if regs == "" {
t.Fatal("Expected string showing registers values, got empty string")
}
locals, err := c.ListFunctionArgs(api.EvalScope{-1, 0})
locals, err := c.ListFunctionArgs(api.EvalScope{-1, 0, 0})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
......@@ -687,7 +687,7 @@ func Test1ClientServer_EvalVariable(t *testing.T) {
t.Fatalf("Continue(): %v\n", state.Err)
}
var1, err := c.EvalVariable(api.EvalScope{-1, 0}, "a1")
var1, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "a1")
assertNoError(err, t, "EvalVariable")
t.Logf("var1: %s", var1.SinglelineString())
......@@ -706,9 +706,9 @@ func Test1ClientServer_SetVariable(t *testing.T) {
t.Fatalf("Continue(): %v\n", state.Err)
}
assertNoError(c.SetVariable(api.EvalScope{-1, 0}, "a2", "8"), t, "SetVariable()")
assertNoError(c.SetVariable(api.EvalScope{-1, 0, 0}, "a2", "8"), t, "SetVariable()")
a2, err := c.EvalVariable(api.EvalScope{-1, 0}, "a2")
a2, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "a2")
if err != nil {
t.Fatalf("Could not evaluate variable: %v", err)
}
......@@ -835,10 +835,10 @@ func Test1Issue355(t *testing.T) {
assertError(err, t, "ListThreads()")
_, err = c.GetThread(tid)
assertError(err, t, "GetThread()")
assertError(c.SetVariable(api.EvalScope{gid, 0}, "a", "10"), t, "SetVariable()")
_, err = c.ListLocalVariables(api.EvalScope{gid, 0})
assertError(c.SetVariable(api.EvalScope{gid, 0, 0}, "a", "10"), t, "SetVariable()")
_, err = c.ListLocalVariables(api.EvalScope{gid, 0, 0})
assertError(err, t, "ListLocalVariables()")
_, err = c.ListFunctionArgs(api.EvalScope{gid, 0})
_, err = c.ListFunctionArgs(api.EvalScope{gid, 0, 0})
assertError(err, t, "ListFunctionArgs()")
_, err = c.ListRegisters()
assertError(err, t, "ListRegisters()")
......@@ -846,9 +846,9 @@ func Test1Issue355(t *testing.T) {
assertError(err, t, "ListGoroutines()")
_, err = c.Stacktrace(gid, 10, false)
assertError(err, t, "Stacktrace()")
_, err = c.FindLocation(api.EvalScope{gid, 0}, "+1")
_, err = c.FindLocation(api.EvalScope{gid, 0, 0}, "+1")
assertError(err, t, "FindLocation()")
_, err = c.DisassemblePC(api.EvalScope{-1, 0}, 0x40100, api.IntelFlavour)
_, err = c.DisassemblePC(api.EvalScope{-1, 0, 0}, 0x40100, api.IntelFlavour)
assertError(err, t, "DisassemblePC()")
})
}
......@@ -863,12 +863,12 @@ func Test1Disasm(t *testing.T) {
state := <-ch
assertNoError(state.Err, t, "Continue()")
locs, err := c.FindLocation(api.EvalScope{-1, 0}, "main.main")
locs, err := c.FindLocation(api.EvalScope{-1, 0, 0}, "main.main")
assertNoError(err, t, "FindLocation()")
if len(locs) != 1 {
t.Fatalf("wrong number of locations for main.main: %d", len(locs))
}
d1, err := c.DisassemblePC(api.EvalScope{-1, 0}, locs[0].PC, api.IntelFlavour)
d1, err := c.DisassemblePC(api.EvalScope{-1, 0, 0}, locs[0].PC, api.IntelFlavour)
assertNoError(err, t, "DisassemblePC()")
if len(d1) < 2 {
t.Fatalf("wrong size of disassembly: %d", len(d1))
......@@ -876,7 +876,7 @@ func Test1Disasm(t *testing.T) {
pcstart := d1[0].Loc.PC
pcend := d1[len(d1)-1].Loc.PC + uint64(len(d1[len(d1)-1].Bytes))
d2, err := c.DisassembleRange(api.EvalScope{-1, 0}, pcstart, pcend, api.IntelFlavour)
d2, err := c.DisassembleRange(api.EvalScope{-1, 0, 0}, pcstart, pcend, api.IntelFlavour)
assertNoError(err, t, "DisassembleRange()")
if len(d1) != len(d2) {
......@@ -885,7 +885,7 @@ func Test1Disasm(t *testing.T) {
t.Fatal("mismatched length between disassemble pc and disassemble range")
}
d3, err := c.DisassemblePC(api.EvalScope{-1, 0}, state.CurrentThread.PC, api.IntelFlavour)
d3, err := c.DisassemblePC(api.EvalScope{-1, 0, 0}, state.CurrentThread.PC, api.IntelFlavour)
assertNoError(err, t, "DisassemblePC() - second call")
if len(d1) != len(d3) {
......@@ -929,7 +929,7 @@ func Test1Disasm(t *testing.T) {
state, err := c.StepInstruction()
assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
d3, err = c.DisassemblePC(api.EvalScope{-1, 0}, state.CurrentThread.PC, api.IntelFlavour)
d3, err = c.DisassemblePC(api.EvalScope{-1, 0, 0}, state.CurrentThread.PC, api.IntelFlavour)
assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
curinstr := getCurinstr(d3)
......@@ -992,7 +992,7 @@ func Test1ClientServer_CondBreakpoint(t *testing.T) {
state := <-c.Continue()
assertNoError(state.Err, t, "Continue()")
nvar, err := c.EvalVariable(api.EvalScope{-1, 0}, "n")
nvar, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "n")
assertNoError(err, t, "EvalVariable()")
if nvar.SinglelineString() != "7" {
......@@ -1096,14 +1096,14 @@ func Test1TypesCommand(t *testing.T) {
func Test1Issue406(t *testing.T) {
withTestClient1("issue406", t, func(c *rpc1.RPCClient) {
locs, err := c.FindLocation(api.EvalScope{-1, 0}, "issue406.go:146")
locs, err := c.FindLocation(api.EvalScope{-1, 0, 0}, "issue406.go:146")
assertNoError(err, t, "FindLocation()")
_, err = c.CreateBreakpoint(&api.Breakpoint{Addr: locs[0].PC})
assertNoError(err, t, "CreateBreakpoint()")
ch := c.Continue()
state := <-ch
assertNoError(state.Err, t, "Continue()")
v, err := c.EvalVariable(api.EvalScope{-1, 0}, "cfgtree")
v, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "cfgtree")
assertNoError(err, t, "EvalVariable()")
vs := v.MultilineString("")
t.Logf("cfgtree formats to: %s\n", vs)
......
......@@ -484,7 +484,7 @@ func TestClientServer_infoLocals(t *testing.T) {
if state.Err != nil {
t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
}
locals, err := c.ListLocalVariables(api.EvalScope{-1, 0}, normalLoadConfig)
locals, err := c.ListLocalVariables(api.EvalScope{-1, 0, 0}, normalLoadConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
......@@ -513,7 +513,7 @@ func TestClientServer_infoArgs(t *testing.T) {
if len(regs) == 0 {
t.Fatal("Expected string showing registers values, got empty string")
}
locals, err := c.ListFunctionArgs(api.EvalScope{-1, 0}, normalLoadConfig)
locals, err := c.ListFunctionArgs(api.EvalScope{-1, 0, 0}, normalLoadConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
......@@ -755,7 +755,7 @@ func TestClientServer_EvalVariable(t *testing.T) {
t.Fatalf("Continue(): %v\n", state.Err)
}
var1, err := c.EvalVariable(api.EvalScope{-1, 0}, "a1", normalLoadConfig)
var1, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "a1", normalLoadConfig)
assertNoError(err, t, "EvalVariable")
t.Logf("var1: %s", var1.SinglelineString())
......@@ -774,9 +774,9 @@ func TestClientServer_SetVariable(t *testing.T) {
t.Fatalf("Continue(): %v\n", state.Err)
}
assertNoError(c.SetVariable(api.EvalScope{-1, 0}, "a2", "8"), t, "SetVariable()")
assertNoError(c.SetVariable(api.EvalScope{-1, 0, 0}, "a2", "8"), t, "SetVariable()")
a2, err := c.EvalVariable(api.EvalScope{-1, 0}, "a2", normalLoadConfig)
a2, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "a2", normalLoadConfig)
if err != nil {
t.Fatalf("Could not evaluate variable: %v", err)
}
......@@ -909,10 +909,10 @@ func TestIssue355(t *testing.T) {
assertError(err, t, "ListThreads()")
_, err = c.GetThread(tid)
assertError(err, t, "GetThread()")
assertError(c.SetVariable(api.EvalScope{gid, 0}, "a", "10"), t, "SetVariable()")
_, err = c.ListLocalVariables(api.EvalScope{gid, 0}, normalLoadConfig)
assertError(c.SetVariable(api.EvalScope{gid, 0, 0}, "a", "10"), t, "SetVariable()")
_, err = c.ListLocalVariables(api.EvalScope{gid, 0, 0}, normalLoadConfig)
assertError(err, t, "ListLocalVariables()")
_, err = c.ListFunctionArgs(api.EvalScope{gid, 0}, normalLoadConfig)
_, err = c.ListFunctionArgs(api.EvalScope{gid, 0, 0}, normalLoadConfig)
assertError(err, t, "ListFunctionArgs()")
_, err = c.ListRegisters(0, false)
assertError(err, t, "ListRegisters()")
......@@ -920,9 +920,9 @@ func TestIssue355(t *testing.T) {
assertError(err, t, "ListGoroutines()")
_, err = c.Stacktrace(gid, 10, false, &normalLoadConfig)
assertError(err, t, "Stacktrace()")
_, err = c.FindLocation(api.EvalScope{gid, 0}, "+1")
_, err = c.FindLocation(api.EvalScope{gid, 0, 0}, "+1")
assertError(err, t, "FindLocation()")
_, err = c.DisassemblePC(api.EvalScope{-1, 0}, 0x40100, api.IntelFlavour)
_, err = c.DisassemblePC(api.EvalScope{-1, 0, 0}, 0x40100, api.IntelFlavour)
assertError(err, t, "DisassemblePC()")
})
}
......@@ -937,12 +937,12 @@ func TestDisasm(t *testing.T) {
state := <-ch
assertNoError(state.Err, t, "Continue()")
locs, err := c.FindLocation(api.EvalScope{-1, 0}, "main.main")
locs, err := c.FindLocation(api.EvalScope{-1, 0, 0}, "main.main")
assertNoError(err, t, "FindLocation()")
if len(locs) != 1 {
t.Fatalf("wrong number of locations for main.main: %d", len(locs))
}
d1, err := c.DisassemblePC(api.EvalScope{-1, 0}, locs[0].PC, api.IntelFlavour)
d1, err := c.DisassemblePC(api.EvalScope{-1, 0, 0}, locs[0].PC, api.IntelFlavour)
assertNoError(err, t, "DisassemblePC()")
if len(d1) < 2 {
t.Fatalf("wrong size of disassembly: %d", len(d1))
......@@ -950,7 +950,7 @@ func TestDisasm(t *testing.T) {
pcstart := d1[0].Loc.PC
pcend := d1[len(d1)-1].Loc.PC + uint64(len(d1[len(d1)-1].Bytes))
d2, err := c.DisassembleRange(api.EvalScope{-1, 0}, pcstart, pcend, api.IntelFlavour)
d2, err := c.DisassembleRange(api.EvalScope{-1, 0, 0}, pcstart, pcend, api.IntelFlavour)
assertNoError(err, t, "DisassembleRange()")
if len(d1) != len(d2) {
......@@ -959,7 +959,7 @@ func TestDisasm(t *testing.T) {
t.Fatal("mismatched length between disassemble pc and disassemble range")
}
d3, err := c.DisassemblePC(api.EvalScope{-1, 0}, state.CurrentThread.PC, api.IntelFlavour)
d3, err := c.DisassemblePC(api.EvalScope{-1, 0, 0}, state.CurrentThread.PC, api.IntelFlavour)
assertNoError(err, t, "DisassemblePC() - second call")
if len(d1) != len(d3) {
......@@ -1003,7 +1003,7 @@ func TestDisasm(t *testing.T) {
state, err := c.StepInstruction()
assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
d3, err = c.DisassemblePC(api.EvalScope{-1, 0}, state.CurrentThread.PC, api.IntelFlavour)
d3, err = c.DisassemblePC(api.EvalScope{-1, 0, 0}, state.CurrentThread.PC, api.IntelFlavour)
assertNoError(err, t, fmt.Sprintf("StepInstruction() %d", count))
curinstr := getCurinstr(d3)
......@@ -1068,7 +1068,7 @@ func TestClientServer_CondBreakpoint(t *testing.T) {
state := <-c.Continue()
assertNoError(state.Err, t, "Continue()")
nvar, err := c.EvalVariable(api.EvalScope{-1, 0}, "n", normalLoadConfig)
nvar, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "n", normalLoadConfig)
assertNoError(err, t, "EvalVariable()")
if nvar.SinglelineString() != "7" {
......@@ -1174,14 +1174,14 @@ func TestTypesCommand(t *testing.T) {
func TestIssue406(t *testing.T) {
protest.AllowRecording(t)
withTestClient2("issue406", t, func(c service.Client) {
locs, err := c.FindLocation(api.EvalScope{-1, 0}, "issue406.go:146")
locs, err := c.FindLocation(api.EvalScope{-1, 0, 0}, "issue406.go:146")
assertNoError(err, t, "FindLocation()")
_, err = c.CreateBreakpoint(&api.Breakpoint{Addr: locs[0].PC})
assertNoError(err, t, "CreateBreakpoint()")
ch := c.Continue()
state := <-ch
assertNoError(state.Err, t, "Continue()")
v, err := c.EvalVariable(api.EvalScope{-1, 0}, "cfgtree", normalLoadConfig)
v, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "cfgtree", normalLoadConfig)
assertNoError(err, t, "EvalVariable()")
vs := v.MultilineString("")
t.Logf("cfgtree formats to: %s\n", vs)
......@@ -1193,7 +1193,7 @@ func TestEvalExprName(t *testing.T) {
state := <-c.Continue()
assertNoError(state.Err, t, "Continue()")
var1, err := c.EvalVariable(api.EvalScope{-1, 0}, "i1+1", normalLoadConfig)
var1, err := c.EvalVariable(api.EvalScope{-1, 0, 0}, "i1+1", normalLoadConfig)
assertNoError(err, t, "EvalVariable")
const name = "i1+1"
......@@ -1511,7 +1511,7 @@ func TestAcceptMulticlient(t *testing.T) {
}
func mustHaveDebugCalls(t *testing.T, c service.Client) {
locs, err := c.FindLocation(api.EvalScope{-1, 0}, "runtime.debugCallV1")
locs, err := c.FindLocation(api.EvalScope{-1, 0, 0}, "runtime.debugCallV1")
if len(locs) == 0 || err != nil {
t.Skip("function calls not supported on this version of go")
}
......@@ -1552,7 +1552,7 @@ func TestClientServerFunctionCallBadPos(t *testing.T) {
protest.MustSupportFunctionCalls(t, testBackend)
withTestClient2("fncall", t, func(c service.Client) {
mustHaveDebugCalls(t, c)
loc, err := c.FindLocation(api.EvalScope{-1, 0}, "fmt/print.go:649")
loc, err := c.FindLocation(api.EvalScope{-1, 0, 0}, "fmt/print.go:649")
assertNoError(err, t, "could not find location")
_, err = c.CreateBreakpoint(&api.Breakpoint{File: loc[0].File, Line: loc[0].Line})
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册