diff --git a/_fixtures/fncall.go b/_fixtures/fncall.go index 9937e5301dc1069f31d6c60a012a168ad063dbd6..ba001be495050cd2c43981c89b2078147b2ddd03 100644 --- a/_fixtures/fncall.go +++ b/_fixtures/fncall.go @@ -193,7 +193,7 @@ func main() { d := &Derived{3, Base{4}} - runtime.Breakpoint() + runtime.Breakpoint() // breakpoint here call1(one, two) fn2clos(2) strings.LastIndexByte(stringslice[1], 'w') diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go index 2d3d0a68460946d4c6e46aeab0ed21a7b31575ab..e5422a46a8e605816dc91339df6f4f9b8611ac2d 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -316,6 +316,7 @@ func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) { fncallLog("function call initiated %v frame size %d goroutine %d (thread %d)", fncall.fn, fncall.argFrameSize, scope.g.ID, thread.ThreadID()) + thread.Breakpoint().Clear() // since we moved address in PC the thread is no longer stopped at a breakpoint, leaving the breakpoint set will confuse Continue p.fncallForG[scope.g.ID].startThreadID = thread.ThreadID() spoff := int64(scope.Regs.Uint64Val(scope.Regs.SPRegNum)) - int64(scope.g.stack.hi) @@ -946,6 +947,10 @@ func isCallInjectionStop(t *Target, thread Thread, loc *Location) bool { if !strings.HasPrefix(loc.Fn.Name, debugCallFunctionNamePrefix1) && !strings.HasPrefix(loc.Fn.Name, debugCallFunctionNamePrefix2) { return false } + if loc.PC == loc.Fn.Entry { + // call injection just started, did not make any progress before being interrupted by a concurrent breakpoint. + return false + } text, err := disassembleCurrentInstruction(t, thread, -1) if err != nil || len(text) <= 0 { return false diff --git a/service/test/variables_test.go b/service/test/variables_test.go index 3860b700ed1dca091a286bbb4637fc655f74538d..adb69fe8f2561b165cf72c2a848e4eb0acf26a53 100644 --- a/service/test/variables_test.go +++ b/service/test/variables_test.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "go/constant" + "io/ioutil" "path/filepath" "runtime" "sort" @@ -1269,6 +1270,9 @@ func TestCallFunction(t *testing.T) { if err != nil { t.Skip("function calls not supported on this version of go") } + + testCallFunctionSetBreakpoint(t, p, fixture) + assertNoError(p.Continue(), t, "Continue()") for _, tc := range testcases { testCallFunction(t, p, tc) @@ -1302,6 +1306,17 @@ func TestCallFunction(t *testing.T) { }) } +func testCallFunctionSetBreakpoint(t *testing.T, p *proc.Target, fixture protest.Fixture) { + buf, err := ioutil.ReadFile(fixture.Source) + assertNoError(err, t, "ReadFile") + for i, line := range strings.Split(string(buf), "\n") { + if strings.Contains(line, "// breakpoint here") { + setFileBreakpoint(p, t, fixture, i+1) + return + } + } +} + func testCallFunction(t *testing.T, p *proc.Target, tc testCaseCallFunction) { const unsafePrefix = "-unsafe "