diff --git a/_fixtures/issue3310.go b/_fixtures/issue3310.go new file mode 100644 index 000000000..2b8108618 --- /dev/null +++ b/_fixtures/issue3310.go @@ -0,0 +1,18 @@ +package main + +import ( + "fmt" + "reflect" +) + +var i = 2 +var val = reflect.ValueOf(i) + +func reflectFunc(value reflect.Value) { + fmt.Printf("%s\n", value.Type().Name()) +} + +func main() { + reflectFunc(val) + fmt.Println(&i) +} diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index 770204758..e6e215840 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -946,6 +946,20 @@ func (stack *evalStack) resume(g *G) { } // call injection protocol suspended or concluded, resume normal opcode execution + if len(stack.fncalls) == 0 && g.Thread != nil { + // The function call protocol concluded, recover the thread's registers so + // we can use them to evaluate variables. + so := scope.image() + if regs, err := g.Thread.Registers(); err == nil { + cfa := scope.Regs.CFA + frameBase := scope.Regs.FrameBase + dwarfRegs := *(scope.BinInfo.Arch.RegistersToDwarfRegisters(so.StaticBase, regs)) + dwarfRegs.ChangeFunc = g.Thread.SetReg + scope.Regs = dwarfRegs + scope.Regs.CFA = cfa + scope.Regs.FrameBase = frameBase + } + } stack.run() } diff --git a/pkg/proc/variables_test.go b/pkg/proc/variables_test.go index 84f79420a..277eb5d17 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -1946,3 +1946,15 @@ func TestClassicMap(t *testing.T) { } }) } + +func TestCallFunctionRegisterArg(t *testing.T) { + protest.MustSupportFunctionCalls(t, testBackend) + if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 23) { + t.Skip("not supported") + } + withTestProcessArgs("issue3310", t, ".", []string{}, protest.AllNonOptimized, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { + setFileBreakpoint(p, t, fixture.Source, 12) + assertNoError(grp.Continue(), t, "Continue()") + assertNoError(proc.EvalExpressionWithCalls(grp, p.SelectedGoroutine(), "value.Type()", pnormalLoadConfig, true), t, "EvalExpressionWithCalls") + }) +}