From f7e111619de310d51a2ce2d9fdf37afd63151218 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 13 Oct 2021 13:25:31 +0100 Subject: [PATCH 01/29] Improve coverage of record-replay backends by allowing recording. --- pkg/proc/proc_test.go | 40 +++++++++++++++++++++++++++++++ pkg/proc/scope_test.go | 2 ++ pkg/proc/variables_test.go | 3 +++ pkg/terminal/command_test.go | 10 ++++++++ service/test/integration1_test.go | 19 +++++++++++++++ service/test/integration2_test.go | 16 +++++++++++++ 6 files changed, 90 insertions(+) diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 4fdf77ade..20f674f87 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -371,6 +371,7 @@ func TestBreakpointWithNonExistantFunction(t *testing.T) { } func TestClearBreakpointBreakpoint(t *testing.T) { + protest.AllowRecording(t) withTestProcess("testprog", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { bp := setFunctionBreakpoint(p, t, "main.sleepytime") @@ -1085,6 +1086,7 @@ func testGSupportFunc(name string, t *testing.T, p *proc.Target, grp *proc.Targe } func TestGetG(t *testing.T) { + protest.AllowRecording(t) withTestProcess("testprog", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { testGSupportFunc("nocgo", t, p, grp, fixture) }) @@ -1383,6 +1385,7 @@ func TestThreadFrameEvaluation(t *testing.T) { if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) { t.SkipNow() } + protest.AllowRecording(t) withTestProcess("testdeadlock", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") @@ -1785,6 +1788,7 @@ func TestCondBreakpointError(t *testing.T) { } func TestHitCondBreakpointEQ(t *testing.T) { + protest.AllowRecording(t) withTestProcess("break", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { bp := setFileBreakpoint(p, t, fixture.Source, 7) bp.Logical.HitCond = &struct { @@ -2025,6 +2029,7 @@ func TestIssue149(t *testing.T) { return } // setting breakpoint on break statement + protest.AllowRecording(t) withTestProcess("break", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { findFileLocation(p, t, fixture.Source, 8) }) @@ -2066,6 +2071,7 @@ func TestCmdLineArgs(t *testing.T) { } } + protest.AllowRecording(t) // make sure multiple arguments (including one with spaces) are passed to the binary correctly withTestProcessArgs("testargs", t, ".", []string{"test"}, 0, expectSuccess) withTestProcessArgs("testargs", t, ".", []string{"-test"}, 0, expectPanic) @@ -2263,6 +2269,7 @@ func TestIssue573(t *testing.T) { } func TestTestvariables2Prologue(t *testing.T) { + protest.AllowRecording(t) withTestProcess("testvariables2", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { addrEntry := p.BinInfo().LookupFunc()["main.main"][0].Entry addrPrologue := findFunctionLocation(p, t, "main.main") @@ -3014,6 +3021,7 @@ func TestIssue877(t *testing.T) { } const envval = "/usr/local/lib" os.Setenv("DYLD_LIBRARY_PATH", envval) + protest.AllowRecording(t) withTestProcess("issue877", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") v := evalVariable(p, t, "dyldenv") @@ -3211,6 +3219,7 @@ func TestAttachStripped(t *testing.T) { func TestIssue844(t *testing.T) { // Conditional breakpoints should not prevent next from working if their // condition isn't met. + protest.AllowRecording(t) withTestProcess("nextcond", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFileBreakpoint(p, t, fixture.Source, 9) condbp := setFileBreakpoint(p, t, fixture.Source, 10) @@ -3446,6 +3455,7 @@ func TestCgoSources(t *testing.T) { protest.MustHaveCgo(t) + protest.AllowRecording(t) withTestProcess("cgostacktest/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { sources := p.BinInfo().Sources for _, needle := range []string{"main.go", "hello.c"} { @@ -3465,6 +3475,7 @@ func TestCgoSources(t *testing.T) { func TestSystemstackStacktrace(t *testing.T) { // check that we can follow a stack switch initiated by runtime.systemstack() + protest.AllowRecording(t) withTestProcess("panic", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "runtime.startpanic_m") assertNoError(grp.Continue(), t, "first continue") @@ -3520,6 +3531,7 @@ func TestIssue1034(t *testing.T) { // The external linker on macOS produces an abbrev for DW_TAG_subprogram // without the "has children" flag, we should support this. + protest.AllowRecording(t) withTestProcess("cgostacktest/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.main") assertNoError(grp.Continue(), t, "Continue()") @@ -3540,6 +3552,7 @@ func TestIssue1008(t *testing.T) { // The external linker on macOS inserts "end of sequence" extended opcodes // in debug_line. which we should support correctly. + protest.AllowRecording(t) withTestProcess("cgostacktest/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.main") assertNoError(grp.Continue(), t, "Continue()") @@ -3585,6 +3598,7 @@ func TestDeclLine(t *testing.T) { t.Skip("go 1.9 and prior versions do not emit DW_AT_decl_line") } + protest.AllowRecording(t) withTestProcess("decllinetest", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFileBreakpoint(p, t, fixture.Source, 8) setFileBreakpoint(p, t, fixture.Source, 9) @@ -3618,6 +3632,7 @@ func TestDeclLine(t *testing.T) { } func TestIssue1137(t *testing.T) { + protest.AllowRecording(t) withTestProcess("dotpackagesiface", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") v := evalVariable(p, t, "iface") @@ -3721,6 +3736,7 @@ func TestDisassembleGlobalVars(t *testing.T) { if runtime.GOARCH == "386" && runtime.GOOS == "linux" && buildMode == "pie" { t.Skip("On 386 linux when pie, symLookup can't look up global variables") } + protest.AllowRecording(t) withTestProcess("teststepconcurrent", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { mainfn := p.BinInfo().LookupFunc()["main.main"][0] regs, _ := p.CurrentThread().Registers() @@ -3762,6 +3778,7 @@ func TestAllPCsForFileLines(t *testing.T) { // Versions of go before 1.10 do not have DWARF information for inlined calls t.Skip("inlining not supported") } + protest.AllowRecording(t) withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { l2pcs := p.BinInfo().AllPCsForFileLines(fixture.Source, []int{7, 20}) if len(l2pcs) != 2 { @@ -3826,6 +3843,7 @@ func TestInlinedStacktraceAndVariables(t *testing.T) { }, } + protest.AllowRecording(t) withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { pcs, err := proc.FindFileLocation(p, fixture.Source, 7) assertNoError(err, t, "LineToPC") @@ -3963,6 +3981,7 @@ func TestInlineFunctionList(t *testing.T) { // TODO(qmuntal): seems to be an upstream issue, investigate. t.Skip("inlining not supported") } + protest.AllowRecording(t) withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining|protest.EnableOptimization, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { var found bool for _, fn := range p.BinInfo().Functions { @@ -3983,6 +4002,7 @@ func TestInlineBreakpoint(t *testing.T) { // Versions of go before 1.10 do not have DWARF information for inlined calls t.Skip("inlining not supported") } + protest.AllowRecording(t) withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining|protest.EnableOptimization, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { pcs, err := proc.FindFileLocation(p, fixture.Source, 17) if err != nil { @@ -4103,6 +4123,7 @@ func TestStepOutReturn(t *testing.T) { if ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) { t.Skip("return variables aren't marked on 1.9 or earlier") } + protest.AllowRecording(t) withTestProcess("stepoutret", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.stepout") assertNoError(grp.Continue(), t, "Continue") @@ -4151,6 +4172,7 @@ func TestStepOutReturn(t *testing.T) { } func TestOptimizationCheck(t *testing.T) { + protest.AllowRecording(t) withTestProcess("continuetestprog", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { fn := p.BinInfo().LookupFunc()["main.main"][0] if fn.Optimized() { @@ -4171,6 +4193,7 @@ func TestOptimizationCheck(t *testing.T) { func TestIssue1264(t *testing.T) { // It should be possible to set a breakpoint condition that consists only // of evaluating a single boolean variable. + protest.AllowRecording(t) withTestProcess("issue1264", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { bp := setFileBreakpoint(p, t, fixture.Source, 8) bp.UserBreaklet().Cond = &ast.Ident{Name: "equalsTwo"} @@ -4243,6 +4266,7 @@ func TestNextUnknownInstr(t *testing.T) { if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 10) { t.Skip("versions of Go before 1.10 can't assemble the instruction VPUNPCKLWD") } + protest.AllowRecording(t) withTestProcess("nodisasm/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.asmFunc") assertNoError(grp.Continue(), t, "Continue()") @@ -4346,6 +4370,7 @@ func TestIssue1432(t *testing.T) { } func TestGoroutinesInfoLimit(t *testing.T) { + protest.AllowRecording(t) withTestProcess("teststepconcurrent", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFileBreakpoint(p, t, fixture.Source, 37) assertNoError(grp.Continue(), t, "Continue()") @@ -4375,6 +4400,7 @@ func TestGoroutinesInfoLimit(t *testing.T) { } func TestIssue1469(t *testing.T) { + protest.AllowRecording(t) withTestProcess("issue1469", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFileBreakpoint(p, t, fixture.Source, 13) assertNoError(grp.Continue(), t, "Continue()") @@ -4412,6 +4438,7 @@ func TestDeadlockBreakpoint(t *testing.T) { if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 11) { deadlockBp = proc.UnrecoveredPanic } + protest.AllowRecording(t) withTestProcess("testdeadlock", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") @@ -4485,6 +4512,7 @@ func TestAncestors(t *testing.T) { savedGodebug := os.Getenv("GODEBUG") os.Setenv("GODEBUG", "tracebackancestors=100") defer os.Setenv("GODEBUG", savedGodebug) + protest.AllowRecording(t) withTestProcess("testnextprog", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.testgoroutine") assertNoError(grp.Continue(), t, "Continue()") @@ -4601,6 +4629,7 @@ func TestPluginStepping(t *testing.T) { func TestIssue1601(t *testing.T) { protest.MustHaveCgo(t) // Tests that recursive types involving C qualifiers and typedefs are parsed correctly + protest.AllowRecording(t) withTestProcess("issue1601", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue") evalVariable(p, t, "C.globalq") @@ -4610,6 +4639,7 @@ func TestIssue1601(t *testing.T) { func TestIssue1615(t *testing.T) { // A breakpoint condition that tests for string equality with a constant string shouldn't fail with 'string too long for comparison' error + protest.AllowRecording(t) withTestProcess("issue1615", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { bp := setFileBreakpoint(p, t, fixture.Source, 19) bp.UserBreaklet().Cond = &ast.BinaryExpr{ @@ -4630,6 +4660,7 @@ func TestCgoStacktrace2(t *testing.T) { protest.MustHaveCgo(t) // If a panic happens during cgo execution the stacktrace should show the C // function that caused the problem. + protest.AllowRecording(t) withTestProcess("cgosigsegvstack", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { grp.Continue() frames, err := proc.ThreadStacktrace(p.CurrentThread(), 100) @@ -4644,6 +4675,7 @@ func TestCgoStacktrace2(t *testing.T) { func TestIssue1656(t *testing.T) { skipUnlessOn(t, "amd64 only", "amd64") + protest.AllowRecording(t) withTestProcess("issue1656/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFileBreakpoint(p, t, filepath.ToSlash(filepath.Join(fixture.BuildDir, "main.s")), 5) assertNoError(grp.Continue(), t, "Continue()") @@ -4662,6 +4694,7 @@ func TestBreakpointConfusionOnResume(t *testing.T) { // stopped at. // This test checks for a regression introduced when fixing Issue #1656 skipUnlessOn(t, "amd64 only", "amd64") + protest.AllowRecording(t) withTestProcess("nopbreakpoint/", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { maindots := filepath.ToSlash(filepath.Join(fixture.BuildDir, "main.s")) maindotgo := filepath.ToSlash(filepath.Join(fixture.BuildDir, "main.go")) @@ -4679,6 +4712,7 @@ func TestBreakpointConfusionOnResume(t *testing.T) { } func TestIssue1736(t *testing.T) { + protest.AllowRecording(t) withTestProcess("testvariables2", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") ch1BufVar := evalVariable(p, t, "*(ch1.buf)") @@ -4694,12 +4728,14 @@ func TestIssue1736(t *testing.T) { func TestIssue1817(t *testing.T) { // Setting a breakpoint on a line that doesn't have any PC addresses marked // is_stmt should work. + protest.AllowRecording(t) withTestProcess("issue1817", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFileBreakpoint(p, t, fixture.Source, 16) }) } func TestListPackagesBuildInfo(t *testing.T) { + protest.AllowRecording(t) withTestProcess("pkgrenames", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { pkgs := p.BinInfo().ListPackagesBuildInfo(true) t.Logf("returned %d", len(pkgs)) @@ -5058,6 +5094,7 @@ func TestRequestManualStopWhileStopped(t *testing.T) { func TestStepOutPreservesGoroutine(t *testing.T) { // Checks that StepOut preserves the currently selected goroutine. rand.Seed(time.Now().Unix()) + protest.AllowRecording(t) withTestProcess("issue2113", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") @@ -5395,6 +5432,7 @@ func TestVariablesWithExternalLinking(t *testing.T) { // See: // https://github.com/golang/go/issues/25841 // https://github.com/go-delve/delve/issues/2346 + protest.AllowRecording(t) withTestProcessArgs("testvariables2", t, ".", []string{}, protest.BuildModeExternalLinker, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") str1Var := evalVariable(p, t, "str1") @@ -5559,6 +5597,7 @@ func TestManualStopWhileStopped(t *testing.T) { func TestDwrapStartLocation(t *testing.T) { // Tests that the start location of a goroutine is unwrapped in Go 1.17 and later. + protest.AllowRecording(t) withTestProcess("goroutinestackprog", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.stacktraceme") assertNoError(grp.Continue(), t, "Continue()") @@ -5718,6 +5757,7 @@ func TestWatchpointStackBackwardsOutOfScope(t *testing.T) { func TestSetOnFunctions(t *testing.T) { // The set command between function variables should fail with an error // Issue #2691 + protest.AllowRecording(t) withTestProcess("goroutinestackprog", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "main.main") assertNoError(grp.Continue(), t, "Continue()") diff --git a/pkg/proc/scope_test.go b/pkg/proc/scope_test.go index 8ca4665f0..52e9d645a 100644 --- a/pkg/proc/scope_test.go +++ b/pkg/proc/scope_test.go @@ -23,6 +23,7 @@ func TestScopeWithEscapedVariable(t *testing.T) { return } + protest.AllowRecording(t) withTestProcess("scopeescapevareval", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue") @@ -72,6 +73,7 @@ func TestScope(t *testing.T) { scopeChecks := getScopeChecks(scopetestPath, t) + protest.AllowRecording(t) withTestProcess("scopetest", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { for i := range scopeChecks { setFileBreakpoint(p, t, fixture.Source, scopeChecks[i].line) diff --git a/pkg/proc/variables_test.go b/pkg/proc/variables_test.go index 77b8677a5..5782cefd3 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -1110,6 +1110,7 @@ func TestConstants(t *testing.T) { // Not supported on 1.9 or earlier t.Skip("constants added in go 1.10") } + protest.AllowRecording(t) withTestProcess("consts", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue") for _, testcase := range testcases { @@ -1121,6 +1122,7 @@ func TestConstants(t *testing.T) { } func TestIssue1075(t *testing.T) { + protest.AllowRecording(t) withTestProcess("clientdo", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { setFunctionBreakpoint(p, t, "net/http.(*Client).Do") assertNoError(grp.Continue(), t, "Continue()") @@ -1398,6 +1400,7 @@ func testCallFunction(t *testing.T, grp *proc.TargetGroup, p *proc.Target, tc te func TestIssue1531(t *testing.T) { // Go 1.12 introduced a change to the map representation where empty cells can be marked with 1 instead of just 0. + protest.AllowRecording(t) withTestProcess("issue1531", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) { assertNoError(grp.Continue(), t, "Continue()") diff --git a/pkg/terminal/command_test.go b/pkg/terminal/command_test.go index ee9c60515..fb4add22f 100644 --- a/pkg/terminal/command_test.go +++ b/pkg/terminal/command_test.go @@ -292,6 +292,7 @@ func TestTraceOnNonFunctionEntry(t *testing.T) { } func TestExitStatus(t *testing.T) { + test.AllowRecording(t) withTestTerminal("continuetestprog", t, func(term *FakeTerminal) { term.Exec("continue") status, err := term.handleExit() @@ -794,6 +795,7 @@ func TestConfig(t *testing.T) { func TestIssue1090(t *testing.T) { // Exit while executing 'next' should report the "Process exited" error // message instead of crashing. + test.AllowRecording(t) withTestTerminal("math", t, func(term *FakeTerminal) { term.MustExec("break main.main") term.MustExec("continue") @@ -807,6 +809,7 @@ func TestIssue1090(t *testing.T) { } func TestPrintContextParkedGoroutine(t *testing.T) { + test.AllowRecording(t) withTestTerminal("goroutinestackprog", t, func(term *FakeTerminal) { term.MustExec("break stacktraceme") term.MustExec("continue") @@ -846,6 +849,7 @@ func TestStepOutReturn(t *testing.T) { if ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) { t.Skip("return variables aren't marked on 1.9 or earlier") } + test.AllowRecording(t) withTestTerminal("stepoutret", t, func(term *FakeTerminal) { term.MustExec("break main.stepout") term.MustExec("continue") @@ -858,6 +862,7 @@ func TestStepOutReturn(t *testing.T) { } func TestOptimizationCheck(t *testing.T) { + test.AllowRecording(t) withTestTerminal("continuetestprog", t, func(term *FakeTerminal) { term.MustExec("break main.main") out := term.MustExec("continue") @@ -881,6 +886,7 @@ func TestOptimizationCheck(t *testing.T) { func TestTruncateStacktrace(t *testing.T) { const stacktraceTruncatedMessage = "(truncated)" + test.AllowRecording(t) withTestTerminal("stacktraceprog", t, func(term *FakeTerminal) { term.MustExec("break main.stacktraceme") term.MustExec("continue") @@ -1031,6 +1037,7 @@ func TestExamineMemoryCmd(t *testing.T) { } func TestPrintOnTracepoint(t *testing.T) { + test.AllowRecording(t) withTestTerminal("increment", t, func(term *FakeTerminal) { term.MustExec("trace main.Increment") term.MustExec("on 1 print y+1") @@ -1097,6 +1104,7 @@ func TestParseNewArgv(t *testing.T) { } func TestContinueUntil(t *testing.T) { + test.AllowRecording(t) withTestTerminal("continuetestprog", t, func(term *FakeTerminal) { if runtime.GOARCH != "386" { listIsAt(t, term, "continue main.main", 16, -1, -1) @@ -1108,6 +1116,7 @@ func TestContinueUntil(t *testing.T) { } func TestContinueUntilExistingBreakpoint(t *testing.T) { + test.AllowRecording(t) withTestTerminal("continuetestprog", t, func(term *FakeTerminal) { term.MustExec("break main.main") if runtime.GOARCH != "386" { @@ -1130,6 +1139,7 @@ func TestPrintFormat(t *testing.T) { } func TestHitCondBreakpoint(t *testing.T) { + test.AllowRecording(t) withTestTerminal("break", t, func(term *FakeTerminal) { term.MustExec("break bp1 main.main:4") term.MustExec("condition -hitcount bp1 > 2") diff --git a/service/test/integration1_test.go b/service/test/integration1_test.go index dfd006b6d..1f7b55d9a 100644 --- a/service/test/integration1_test.go +++ b/service/test/integration1_test.go @@ -104,6 +104,7 @@ func Test1Restart_afterExit(t *testing.T) { } func Test1Restart_breakpointPreservation(t *testing.T) { + protest.AllowRecording(t) withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "firstbreakpoint", Tracepoint: true}) assertNoError(err, t, "CreateBreakpoint()") @@ -160,6 +161,7 @@ func Test1Restart_duringStop(t *testing.T) { } func Test1ClientServer_exit(t *testing.T) { + protest.AllowRecording(t) withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) { state, err := c.GetState() if err != nil { @@ -183,6 +185,7 @@ func Test1ClientServer_exit(t *testing.T) { } func Test1ClientServer_step(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testprog", t, func(c *rpc1.RPCClient) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld", Line: -1}) if err != nil { @@ -206,6 +209,7 @@ func Test1ClientServer_step(t *testing.T) { } func testnext(testcases []nextTest, initialLocation string, t *testing.T) { + protest.AllowRecording(t) withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) { bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: initialLocation, Line: -1}) if err != nil { @@ -297,6 +301,7 @@ func Test1NextFunctionReturn(t *testing.T) { } func Test1ClientServer_breakpointInMainThread(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testprog", t, func(c *rpc1.RPCClient) { bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.helloworld", Line: 1}) if err != nil { @@ -318,6 +323,7 @@ func Test1ClientServer_breakpointInMainThread(t *testing.T) { } func Test1ClientServer_breakpointInSeparateGoroutine(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testthreads", t, func(c *rpc1.RPCClient) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.anotherthread", Line: 1}) if err != nil { @@ -337,6 +343,7 @@ func Test1ClientServer_breakpointInSeparateGoroutine(t *testing.T) { } func Test1ClientServer_breakAtNonexistentPoint(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testprog", t, func(c *rpc1.RPCClient) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "nowhere", Line: 1}) if err == nil { @@ -346,6 +353,7 @@ func Test1ClientServer_breakAtNonexistentPoint(t *testing.T) { } func Test1ClientServer_clearBreakpoint(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testprog", t, func(c *rpc1.RPCClient) { bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sleepytime", Line: 1}) if err != nil { @@ -372,6 +380,7 @@ func Test1ClientServer_clearBreakpoint(t *testing.T) { } func Test1ClientServer_switchThread(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) { // With invalid thread id _, err := c.SwitchThread(-1) @@ -415,6 +424,7 @@ func Test1ClientServer_switchThread(t *testing.T) { } func Test1ClientServer_infoLocals(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) { fp := testProgPath(t, "testnextprog") _, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 24}) @@ -436,6 +446,7 @@ func Test1ClientServer_infoLocals(t *testing.T) { } func Test1ClientServer_infoArgs(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testnextprog", t, func(c *rpc1.RPCClient) { fp := testProgPath(t, "testnextprog") _, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 47}) @@ -464,6 +475,7 @@ func Test1ClientServer_infoArgs(t *testing.T) { } func Test1ClientServer_traceContinue(t *testing.T) { + protest.AllowRecording(t) withTestClient1("integrationprog", t, func(c *rpc1.RPCClient) { fp := testProgPath(t, "integrationprog") _, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 15, Tracepoint: true, Goroutine: true, Stacktrace: 5, Variables: []string{"i"}}) @@ -521,6 +533,7 @@ func Test1ClientServer_traceContinue(t *testing.T) { } func Test1ClientServer_traceContinue2(t *testing.T) { + protest.AllowRecording(t) withTestClient1("integrationprog", t, func(c *rpc1.RPCClient) { bp1, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Tracepoint: true}) if err != nil { @@ -564,6 +577,7 @@ func Test1ClientServer_traceContinue2(t *testing.T) { } func Test1ClientServer_FindLocations(t *testing.T) { + protest.AllowRecording(t) withTestClient1("locationsprog", t, func(c *rpc1.RPCClient) { someFunctionCallAddr := findLocationHelper(t, c, "locationsprog.go:26", false, 1, 0)[0] someFunctionLine1 := findLocationHelper(t, c, "locationsprog.go:27", false, 1, 0)[0] @@ -725,6 +739,7 @@ func Test1ClientServer_FullStacktrace(t *testing.T) { lenient = true } + protest.AllowRecording(t) withTestClient1("goroutinestackprog", t, func(c *rpc1.RPCClient) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.stacktraceme", Line: -1}) assertNoError(err, t, "CreateBreakpoint()") @@ -968,6 +983,7 @@ func Test1Disasm(t *testing.T) { } func Test1NegativeStackDepthBug(t *testing.T) { + protest.AllowRecording(t) // After the target process has terminated should return an error but not crash withTestClient1("continuetestprog", t, func(c *rpc1.RPCClient) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: -1}) @@ -981,6 +997,7 @@ func Test1NegativeStackDepthBug(t *testing.T) { } func Test1ClientServer_CondBreakpoint(t *testing.T) { + protest.AllowRecording(t) withTestClient1("parallel_next", t, func(c *rpc1.RPCClient) { bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sayhi", Line: 1}) assertNoError(err, t, "CreateBreakpoint()") @@ -1028,6 +1045,7 @@ func Test1Issue419(t *testing.T) { } func Test1TypesCommand(t *testing.T) { + protest.AllowRecording(t) withTestClient1("testvariables2", t, func(c *rpc1.RPCClient) { state := <-c.Continue() assertNoError(state.Err, t, "Continue()") @@ -1054,6 +1072,7 @@ func Test1TypesCommand(t *testing.T) { } func Test1Issue406(t *testing.T) { + protest.AllowRecording(t) withTestClient1("issue406", t, func(c *rpc1.RPCClient) { locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "issue406.go:146") assertNoError(err, t, "FindLocation()") diff --git a/service/test/integration2_test.go b/service/test/integration2_test.go index 4ea1dd1df..0be6c279a 100644 --- a/service/test/integration2_test.go +++ b/service/test/integration2_test.go @@ -474,6 +474,7 @@ func TestClientServer_breakpointInSeparateGoroutine(t *testing.T) { } func TestClientServer_breakAtNonexistentPoint(t *testing.T) { + protest.AllowRecording(t) withTestClient2("testprog", t, func(c service.Client) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "nowhere", Line: 1}) if err == nil { @@ -483,6 +484,7 @@ func TestClientServer_breakAtNonexistentPoint(t *testing.T) { } func TestClientServer_clearBreakpoint(t *testing.T) { + protest.AllowRecording(t) withTestClient2("testprog", t, func(c service.Client) { bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.sleepytime", Line: 1}) if err != nil { @@ -509,6 +511,7 @@ func TestClientServer_clearBreakpoint(t *testing.T) { } func TestClientServer_toggleBreakpoint(t *testing.T) { + protest.AllowRecording(t) withTestClient2("testtoggle", t, func(c service.Client) { toggle := func(bp *api.Breakpoint) { t.Helper() @@ -582,6 +585,7 @@ func TestClientServer_toggleBreakpoint(t *testing.T) { } func TestClientServer_toggleAmendedBreakpoint(t *testing.T) { + protest.AllowRecording(t) withTestClient2("testtoggle", t, func(c service.Client) { toggle := func(bp *api.Breakpoint) { dbp, err := c.ToggleBreakpoint(bp.ID) @@ -944,6 +948,7 @@ func TestClientServer_traceContinue2(t *testing.T) { } func TestClientServer_FindLocations(t *testing.T) { + protest.AllowRecording(t) withTestClient2("locationsprog", t, func(c service.Client) { someFunctionCallAddr := findLocationHelper(t, c, "locationsprog.go:26", false, 1, 0)[0] someFunctionLine1 := findLocationHelper(t, c, "locationsprog.go:27", false, 1, 0)[0] @@ -1148,6 +1153,7 @@ func TestClientServer_FindLocationsAddr(t *testing.T) { } func TestClientServer_FindLocationsExactMatch(t *testing.T) { + protest.AllowRecording(t) // if an expression matches multiple functions but one of them is an exact // match it should be used anyway. // In this example "math/rand.Intn" would normally match "math/rand.Intn" @@ -1542,6 +1548,7 @@ func TestSkipPrologue(t *testing.T) { } func TestSkipPrologue2(t *testing.T) { + protest.AllowRecording(t) withTestClient2("callme", t, func(c service.Client) { callme := findLocationHelper(t, c, "main.callme", false, 1, 0)[0] callmeZ := uint64(clientEvalVariable(t, c, "main.callme").Addr) @@ -1672,6 +1679,7 @@ func TestClientServer_Issue528(t *testing.T) { return } + protest.AllowRecording(t) withTestClient2("issue528", t, func(c service.Client) { findLocationHelper(t, c, "State.Close", false, 1, 0) }) @@ -1984,6 +1992,7 @@ func TestClientServer_StepOutReturn(t *testing.T) { if ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}) { t.Skip("return variables aren't marked on 1.9 or earlier") } + protest.AllowRecording(t) withTestClient2("stepoutret", t, func(c service.Client) { c.SetReturnValuesLoadConfig(&normalLoadConfig) _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.stepout", Line: -1}) @@ -2186,6 +2195,7 @@ func TestAncestors(t *testing.T) { savedGodebug := os.Getenv("GODEBUG") os.Setenv("GODEBUG", "tracebackancestors=100") defer os.Setenv("GODEBUG", savedGodebug) + protest.AllowRecording(t) withTestClient2("testnextprog", t, func(c service.Client) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.testgoroutine", Line: -1}) assertNoError(err, t, "CreateBreakpoin") @@ -2240,6 +2250,7 @@ func TestUnknownMethodCall(t *testing.T) { } func TestIssue1703(t *testing.T) { + protest.AllowRecording(t) // Calling Disassemble when there is no current goroutine should work. withTestClient2("testnextprog", t, func(c service.Client) { locs, err := c.FindLocation(api.EvalScope{GoroutineID: -1}, "main.main", true, nil) @@ -2305,6 +2316,7 @@ func TestRerecord(t *testing.T) { func TestIssue1787(t *testing.T) { // Calling FunctionReturnLocations without a selected goroutine should // work. + protest.AllowRecording(t) withTestClient2("testnextprog", t, func(c service.Client) { if c, _ := c.(*rpc2.RPCClient); c != nil { c.FunctionReturnLocations("main.main") @@ -2313,6 +2325,7 @@ func TestIssue1787(t *testing.T) { } func TestDoubleCreateBreakpoint(t *testing.T) { + protest.AllowRecording(t) withTestClient2("testnextprog", t, func(c service.Client) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "firstbreakpoint", Tracepoint: true}) assertNoError(err, t, "CreateBreakpoint 1") @@ -2371,6 +2384,7 @@ func TestClearLogicalBreakpoint(t *testing.T) { // Clearing a logical breakpoint should clear all associated physical // breakpoints. // Issue #1955. + protest.AllowRecording(t) withTestClient2Extended("testinline", t, protest.EnableInlining, [3]string{}, nil, func(c service.Client, fixture protest.Fixture) { bp, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.inlineThis"}) assertNoError(err, t, "CreateBreakpoint()") @@ -2514,6 +2528,7 @@ func assertNoDuplicateBreakpoints(t *testing.T, c service.Client) { func TestToggleBreakpointRestart(t *testing.T) { // Checks that breakpoints IDs do not overlap after Restart if there are disabled breakpoints. + protest.AllowRecording(t) withTestClient2("testtoggle", t, func(c service.Client) { bp1, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: 1, Name: "firstbreakpoint"}) assertNoError(err, t, "CreateBreakpoint 1") @@ -2590,6 +2605,7 @@ func TestGoroutinesGrouping(t *testing.T) { func TestLongStringArg(t *testing.T) { // Test the ability to load more elements of a string argument, this could // be broken if registerized variables are not handled correctly. + protest.AllowRecording(t) withTestClient2("morestringarg", t, func(c service.Client) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.f"}) assertNoError(err, t, "CreateBreakpoint") From 3ce877a23116ffb035e01e5f4f1fd5587ef46f21 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 13 Jan 2022 14:12:36 +0000 Subject: [PATCH 02/29] Rename import paths to point to our fork. --- .deepsource.toml | 2 +- Documentation/KnownBugs.md | 2 +- Documentation/api/ClientHowto.md | 10 +-- Documentation/api/dap/README.md | 9 +- Documentation/api/json-rpc/README.md | 4 +- Documentation/cli/README.md | 6 +- Documentation/cli/expr.md | 2 +- Documentation/cli/starlark.md | 94 ++++++++++----------- Documentation/installation/README.md | 18 ++-- README.md | 2 +- _fixtures/consts.go | 2 +- _fixtures/dotpackagesiface.go | 4 +- _fixtures/pkgrenames.go | 8 +- _fixtures/plugin2/plugin2.go | 2 +- _fixtures/plugintest2.go | 2 +- _scripts/gen-cli-docs.go | 2 +- _scripts/gen-starlark-bindings.go | 16 ++-- _scripts/gen-travis.go | 2 +- _scripts/gen-usage-docs.go | 2 +- _scripts/make.go | 10 +-- _scripts/rtype.go | 4 +- cmd/dlv/cmds/commands.go | 24 +++--- cmd/dlv/dlv_test.go | 26 +++--- cmd/dlv/main.go | 4 +- go.mod | 2 +- pkg/config/config.go | 2 +- pkg/dwarf/dwarfbuilder/info.go | 4 +- pkg/dwarf/dwarfbuilder/loc.go | 4 +- pkg/dwarf/frame/parser.go | 4 +- pkg/dwarf/frame/table.go | 2 +- pkg/dwarf/godwarf/addr.go | 2 +- pkg/dwarf/godwarf/type.go | 2 +- pkg/dwarf/line/line_parser.go | 4 +- pkg/dwarf/line/line_parser_test.go | 4 +- pkg/dwarf/line/parse_util.go | 4 +- pkg/dwarf/line/state_machine.go | 4 +- pkg/dwarf/line/state_machine_test.go | 4 +- pkg/dwarf/loclist/dwarf2_loclist.go | 2 +- pkg/dwarf/loclist/dwarf5_loclist.go | 6 +- pkg/dwarf/loclist/loclist5_test.go | 2 +- pkg/dwarf/op/op.go | 4 +- pkg/dwarf/parseutil_test.go | 2 +- pkg/dwarf/reader/reader.go | 4 +- pkg/dwarf/reader/variables.go | 2 +- pkg/gobuild/gobuild.go | 2 +- pkg/goversion/compat.go | 2 +- pkg/locspec/locations.go | 4 +- pkg/locspec/locations_test.go | 12 +-- pkg/proc/amd64_arch.go | 6 +- pkg/proc/amd64_disasm.go | 4 +- pkg/proc/amd64util/xsave.go | 2 +- pkg/proc/arch.go | 4 +- pkg/proc/arm64_arch.go | 8 +- pkg/proc/arm64_disasm.go | 4 +- pkg/proc/bininfo.go | 22 ++--- pkg/proc/breakpoints.go | 10 +-- pkg/proc/core/core.go | 8 +- pkg/proc/core/core_test.go | 6 +- pkg/proc/core/delve_core.go | 6 +- pkg/proc/core/linux_core.go | 8 +- pkg/proc/core/minidump/minidump.go | 2 +- pkg/proc/core/windows_amd64_minidump.go | 8 +- pkg/proc/disasm.go | 2 +- pkg/proc/dump.go | 4 +- pkg/proc/dwarf_export_test.go | 2 +- pkg/proc/dwarf_expr_test.go | 10 +-- pkg/proc/eval.go | 10 +-- pkg/proc/fbsdutil/regs.go | 8 +- pkg/proc/fncall.go | 12 +-- pkg/proc/gdbserial/gdbserver.go | 14 +-- pkg/proc/gdbserial/gdbserver_conn.go | 4 +- pkg/proc/gdbserial/rr.go | 4 +- pkg/proc/gdbserial/rr_test.go | 8 +- pkg/proc/i386_arch.go | 6 +- pkg/proc/i386_disasm.go | 4 +- pkg/proc/interface.go | 4 +- pkg/proc/internal/ebpf/context.go | 4 +- pkg/proc/internal/ebpf/dummy.go | 4 +- pkg/proc/internal/ebpf/helpers.go | 4 +- pkg/proc/internal/ebpf/helpers_test.go | 2 +- pkg/proc/linutil/dynamic.go | 2 +- pkg/proc/linutil/regs_amd64_arch.go | 8 +- pkg/proc/linutil/regs_arm64_arch.go | 6 +- pkg/proc/linutil/regs_i386_arch.go | 4 +- pkg/proc/mem.go | 2 +- pkg/proc/native/dump_linux.go | 2 +- pkg/proc/native/dump_linux_amd64.go | 4 +- pkg/proc/native/dump_linux_other.go | 2 +- pkg/proc/native/dump_other.go | 4 +- pkg/proc/native/dump_windows_amd64.go | 4 +- pkg/proc/native/hwbreak_amd64.go | 4 +- pkg/proc/native/hwbreak_other.go | 2 +- pkg/proc/native/nonative_darwin.go | 8 +- pkg/proc/native/proc.go | 2 +- pkg/proc/native/proc_darwin.go | 6 +- pkg/proc/native/proc_freebsd.go | 4 +- pkg/proc/native/proc_linux.go | 6 +- pkg/proc/native/proc_windows.go | 4 +- pkg/proc/native/ptrace_freebsd_amd64.go | 2 +- pkg/proc/native/ptrace_linux_386.go | 2 +- pkg/proc/native/ptrace_linux_amd64.go | 2 +- pkg/proc/native/register_linux_386.go | 10 +-- pkg/proc/native/registers_darwin_amd64.go | 6 +- pkg/proc/native/registers_freebsd_amd64.go | 8 +- pkg/proc/native/registers_linux_amd64.go | 8 +- pkg/proc/native/registers_linux_arm64.go | 6 +- pkg/proc/native/registers_windows.go | 2 +- pkg/proc/native/syscall_windows_amd64.go | 2 +- pkg/proc/native/syscall_windows_arm64.go | 2 +- pkg/proc/native/threads.go | 2 +- pkg/proc/native/threads_darwin.go | 4 +- pkg/proc/native/threads_freebsd.go | 6 +- pkg/proc/native/threads_linux.go | 2 +- pkg/proc/native/threads_linux_386.go | 2 +- pkg/proc/native/threads_linux_amd64.go | 6 +- pkg/proc/native/threads_linux_arm64.go | 4 +- pkg/proc/native/threads_windows.go | 2 +- pkg/proc/native/threads_windows_amd64.go | 6 +- pkg/proc/native/threads_windows_arm64.go | 4 +- pkg/proc/proc_general_test.go | 30 +++---- pkg/proc/proc_linux_test.go | 4 +- pkg/proc/proc_test.go | 22 ++--- pkg/proc/proc_unix_test.go | 6 +- pkg/proc/registers.go | 2 +- pkg/proc/scope_test.go | 6 +- pkg/proc/stack.go | 6 +- pkg/proc/stackwatch.go | 4 +- pkg/proc/target.go | 8 +- pkg/proc/target_exec.go | 4 +- pkg/proc/target_group.go | 2 +- pkg/proc/test/support.go | 2 +- pkg/proc/threads.go | 2 +- pkg/proc/types.go | 4 +- pkg/proc/variable_test.go | 4 +- pkg/proc/variables.go | 8 +- pkg/proc/variables_fuzz_test.go | 8 +- pkg/proc/variables_test.go | 42 ++++----- pkg/proc/winutil/regs_amd64_arch.go | 6 +- pkg/proc/winutil/regs_arm64_arch.go | 6 +- pkg/proc/x86_disasm.go | 2 +- pkg/terminal/colorize/colorize_test.go | 4 +- pkg/terminal/command.go | 12 +-- pkg/terminal/command_test.go | 18 ++-- pkg/terminal/config.go | 2 +- pkg/terminal/disasmprint.go | 2 +- pkg/terminal/docgen.go | 2 +- pkg/terminal/out.go | 2 +- pkg/terminal/starbind/conv.go | 2 +- pkg/terminal/starbind/starlark.go | 4 +- pkg/terminal/starbind/starlark_mapping.go | 4 +- pkg/terminal/starlark.go | 6 +- pkg/terminal/terminal.go | 12 +-- pkg/terminal/terminal_test.go | 2 +- service/api/conversions.go | 6 +- service/api/types.go | 2 +- service/client.go | 2 +- service/config.go | 2 +- service/dap/command.go | 2 +- service/dap/config.go | 2 +- service/dap/handles.go | 4 +- service/dap/server.go | 22 ++--- service/dap/server_test.go | 24 +++--- service/debugger/debugger.go | 20 ++--- service/debugger/debugger_test.go | 6 +- service/debugger/debugger_unix_test.go | 6 +- service/internal/sameuser/sameuser_linux.go | 2 +- service/rpc1/client.go | 2 +- service/rpc1/server.go | 8 +- service/rpc2/client.go | 6 +- service/rpc2/server.go | 14 +-- service/rpccommon/server.go | 18 ++-- service/test/common_test.go | 6 +- service/test/integration1_test.go | 16 ++-- service/test/integration2_test.go | 24 +++--- 174 files changed, 575 insertions(+), 576 deletions(-) diff --git a/.deepsource.toml b/.deepsource.toml index 5f2b68ef2..5211dbe05 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -9,5 +9,5 @@ name = "go" enabled = true [analyzers.meta] - import_path = "github.com/go-delve/delve" + import_path = "github.com/undoio/delve" dependencies_vendored = true diff --git a/Documentation/KnownBugs.md b/Documentation/KnownBugs.md index 3b0545dbd..6024dbce9 100644 --- a/Documentation/KnownBugs.md +++ b/Documentation/KnownBugs.md @@ -1,5 +1,5 @@ # Known Bugs -- When Delve is compiled with versions of go prior to 1.7.0 it is not possible to set a breakpoint on a function in a remote package using the `Receiver.MethodName` syntax. See [Issue #528](https://github.com/go-delve/delve/issues/528). +- When Delve is compiled with versions of go prior to 1.7.0 it is not possible to set a breakpoint on a function in a remote package using the `Receiver.MethodName` syntax. See [Issue #528](https://github.com/undoio/delve/issues/528). - When running Delve on binaries compiled with a version of go prior to 1.9.0 `locals` will print all local variables, including ones that are out of scope, the shadowed flag will be applied arbitrarily. If there are multiple variables defined with the same name in the current function `print` will not be able to select the correct one for the current line. - `reverse step` will not reverse step into functions called by deferred calls. diff --git a/Documentation/api/ClientHowto.md b/Documentation/api/ClientHowto.md index 3bc85dad3..3848ec4a7 100644 --- a/Documentation/api/ClientHowto.md +++ b/Documentation/api/ClientHowto.md @@ -27,7 +27,7 @@ Command line arguments that should be handed to the inferior process should be s dlv exec --headless ./somebinary -- these arguments are for the inferior process ``` -Specifying a static port number, like in the [README](//github.com/go-delve/Delve/tree/master/Documentation/README.md) example, can be done using `--listen=127.0.0.1:portnumber`. +Specifying a static port number, like in the [README](//github.com/undoio/Delve/tree/master/Documentation/README.md) example, can be done using `--listen=127.0.0.1:portnumber`. This will, however, cause problems if you actually spawn multiple instances of the debugger. @@ -39,11 +39,11 @@ The `--log-dest` option can be used to redirect the "API server listening at:" m Once you have a running headless instance you can connect to it and start sending commands. Delve's protocol is built on top of the [JSON-RPC 1.0 specification](https://www.jsonrpc.org/specification_v1). -The methods of a `service/rpc2.RPCServer` are exposed through this connection, to find out which requests you can send see the documentation of RPCServer on [godoc](https://godoc.org/github.com/go-delve/Delve/service/rpc2#RPCServer). +The methods of a `service/rpc2.RPCServer` are exposed through this connection, to find out which requests you can send see the documentation of RPCServer on [godoc](https://godoc.org/github.com/undoio/Delve/service/rpc2#RPCServer). ### Example -Let's say you are trying to create a breakpoint. By looking at [godoc](https://godoc.org/github.com/go-delve/Delve/service/rpc2#RPCServer) you'll find that there is a `CreateBreakpoint` method in `RPCServer`. +Let's say you are trying to create a breakpoint. By looking at [godoc](https://godoc.org/github.com/undoio/Delve/service/rpc2#RPCServer) you'll find that there is a `CreateBreakpoint` method in `RPCServer`. This method, like all other methods of RPCServer that you can call through the API, has two arguments: `args` and `out`: `args` contains all the input arguments of `CreateBreakpoint`, while `out` is what `CreateBreakpoint` will return to you. @@ -190,7 +190,7 @@ If you want to let your users specify a breakpoint on a function selected from a list of all functions you should specify the name of the function in the FunctionName field of Breakpoint. -If you want to support the [same language as dlv's break and trace commands](//github.com/go-delve/Delve/tree/master/Documentation/cli/locspec.md) +If you want to support the [same language as dlv's break and trace commands](//github.com/undoio/Delve/tree/master/Documentation/cli/locspec.md) you should call RPCServer.FindLocation and then use the returned slice of Location objects to create Breakpoints to pass to CreateBreakpoint: just fill each Breakpoint.Addr with the @@ -244,7 +244,7 @@ are interested in the topmost stack frame of the current goroutine (or thread) use: `EvalScope{ GoroutineID: -1, Frame: 0 }`. More information on the expression language interpreted by RPCServer.Eval -can be found [here](//github.com/go-delve/Delve/tree/master/Documentation/cli/expr.md). +can be found [here](//github.com/undoio/Delve/tree/master/Documentation/cli/expr.md). ### Variable shadowing diff --git a/Documentation/api/dap/README.md b/Documentation/api/dap/README.md index 74565d07b..cc2e2c52b 100644 --- a/Documentation/api/dap/README.md +++ b/Documentation/api/dap/README.md @@ -17,7 +17,7 @@ detailed [debugging documentation](https://github.com/golang/vscode-go/blob/mast [DAP](https://microsoft.github.io/debug-adapter-protocol/specification) is a general debugging protocol supported by many [tools](https://microsoft.github.io/debug-adapter-protocol/implementors/tools/) and [programming languages](https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/). We tailored it to Go specifics, such as mapping [threads request](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Threads) to communicate goroutines and [exceptionInfo request](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo) to support panics and fatal errors. -See [dap.Server.handleRequest](https://github.com/go-delve/delve/search?q=handleRequest) and capabilities set in [dap.Server.onInitializeRequest](https://github.com/go-delve/delve/search?q=onInitializeRequest) for an up-to-date list of supported requests and options. +See [dap.Server.handleRequest](https://github.com/undoio/delve/search?q=handleRequest) and capabilities set in [dap.Server.onInitializeRequest](https://github.com/undoio/delve/search?q=onInitializeRequest) for an up-to-date list of supported requests and options. ## Launch and Attach Configurations @@ -25,7 +25,7 @@ In addition to the general [DAP spec](https://microsoft.github.io/debug-adapter- - -
requestmoderequiredoptional
launch
godoc +
launch
godoc
debugprogram dlvCwdenvbackendargscwdbuildFlagsoutputnoDebug substitutePath
@@ -44,13 +44,12 @@ In addition to the general [DAP spec](https://microsoft.github.io/debug-adapter-
coreprogram
corefilePath
dlvCwdenv
replaytraceDirPath dlvCwdenv
attach
godoc +
attach
godoc
localprocessId backend
remote
- Not all of the configurations are supported by each of the two available DAP servers: @@ -143,4 +142,4 @@ one must first update the [go-dap](https://github.com/google/go-dap) dependency. \ No newline at end of file +---> diff --git a/Documentation/api/json-rpc/README.md b/Documentation/api/json-rpc/README.md index 4c1fb2ea8..db20369e7 100644 --- a/Documentation/api/json-rpc/README.md +++ b/Documentation/api/json-rpc/README.md @@ -7,11 +7,11 @@ Note that this JSON-RPC interface is served over a streaming socket, *not* over # API versions Delve currently supports two versions of its API. By default a headless instance of `dlv` will serve APIv1 for backward compatibility with old clients, however new clients should use APIv2 as new features will only be made available through version 2. To select APIv2 use `--api-version=2` command line argument. -Clients can also select APIv2 by sending a [SetApiVersion](https://godoc.org/github.com/go-delve/delve/service/rpccommon#RPCServer.SetApiVersion) request specifying `APIVersion = 2` after connecting to the headless instance. +Clients can also select APIv2 by sending a [SetApiVersion](https://godoc.org/github.com/undoio/delve/service/rpccommon#RPCServer.SetApiVersion) request specifying `APIVersion = 2` after connecting to the headless instance. # API version 2 documentation -All the methods of the type `service/rpc2.RPCServer` can be called using JSON-RPC, the documentation for these calls is [available on godoc](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer). +All the methods of the type `service/rpc2.RPCServer` can be called using JSON-RPC, the documentation for these calls is [available on godoc](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer). Note that all exposed methods take one single input parameter (usually called `args`) of a struct type and also return a result of a struct type. Also note that the method name should be prefixed with `RPCServer.` in JSON-RPC. diff --git a/Documentation/cli/README.md b/Documentation/cli/README.md index ec14bea19..c02fa815f 100644 --- a/Documentation/cli/README.md +++ b/Documentation/cli/README.md @@ -107,7 +107,7 @@ Sets a breakpoint. break [name] [locspec] -See [Documentation/cli/locspec.md](//github.com/go-delve/delve/tree/master/Documentation/cli/locspec.md) for the syntax of locspec. If locspec is omitted a breakpoint will be set on the current line. +See [Documentation/cli/locspec.md](//github.com/undoio/delve/tree/master/Documentation/cli/locspec.md) for the syntax of locspec. If locspec is omitted a breakpoint will be set on the current line. See also: "help on", "help cond" and "help clear" @@ -577,7 +577,7 @@ Executes a file containing a list of delve commands source -If path ends with the .star extension it will be interpreted as a starlark script. See [Documentation/cli/starlark.md](//github.com/go-delve/delve/tree/master/Documentation/cli/starlark.md) for the syntax. +If path ends with the .star extension it will be interpreted as a starlark script. See [Documentation/cli/starlark.md](//github.com/undoio/delve/tree/master/Documentation/cli/starlark.md) for the syntax. If path is a single '-' character an interactive starlark interpreter will start instead. Type 'exit' to exit. @@ -645,7 +645,7 @@ Set tracepoint. trace [name] [locspec] -A tracepoint is a breakpoint that does not stop the execution of the program, instead when the tracepoint is hit a notification is displayed. See [Documentation/cli/locspec.md](//github.com/go-delve/delve/tree/master/Documentation/cli/locspec.md) for the syntax of locspec. If locspec is omitted a tracepoint will be set on the current line. +A tracepoint is a breakpoint that does not stop the execution of the program, instead when the tracepoint is hit a notification is displayed. See [Documentation/cli/locspec.md](//github.com/undoio/delve/tree/master/Documentation/cli/locspec.md) for the syntax of locspec. If locspec is omitted a tracepoint will be set on the current line. See also: "help on", "help cond" and "help clear" diff --git a/Documentation/cli/expr.md b/Documentation/cli/expr.md index cf40df260..368f90ab0 100644 --- a/Documentation/cli/expr.md +++ b/Documentation/cli/expr.md @@ -63,7 +63,7 @@ To see more values use the slice operator: For this purpose delve allows use of the slice operator on maps, `m[64:]` will return the key/value pairs of map `m` that follow the first 64 key/value pairs (note that delve iterates over maps using a fixed ordering). -These limits can be configured with `max-string-len` and `max-array-values`. See [config](https://github.com/go-delve/delve/tree/master/Documentation/cli#config) for usage. +These limits can be configured with `max-string-len` and `max-array-values`. See [config](https://github.com/undoio/delve/tree/master/Documentation/cli#config) for usage. # Interfaces diff --git a/Documentation/cli/starlark.md b/Documentation/cli/starlark.md index 4f7990021..e1eaf91d0 100644 --- a/Documentation/cli/starlark.md +++ b/Documentation/cli/starlark.md @@ -17,52 +17,52 @@ Global functions with a name that begins with a capital letter will be available Function | API Call ---------|--------- -amend_breakpoint(Breakpoint) | Equivalent to API call [AmendBreakpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.AmendBreakpoint) -ancestors(GoroutineID, NumAncestors, Depth) | Equivalent to API call [Ancestors](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Ancestors) -attached_to_existing_process() | Equivalent to API call [AttachedToExistingProcess](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.AttachedToExistingProcess) -build_id() | Equivalent to API call [BuildID](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.BuildID) -cancel_next() | Equivalent to API call [CancelNext](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.CancelNext) -checkpoint(Where) | Equivalent to API call [Checkpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Checkpoint) -clear_breakpoint(Id, Name) | Equivalent to API call [ClearBreakpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ClearBreakpoint) -clear_checkpoint(ID) | Equivalent to API call [ClearCheckpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ClearCheckpoint) -raw_command(Name, ThreadID, GoroutineID, ReturnInfoLoadConfig, Expr, UnsafeCall) | Equivalent to API call [Command](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Command) -create_breakpoint(Breakpoint, LocExpr, SubstitutePathRules, Suspended) | Equivalent to API call [CreateBreakpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.CreateBreakpoint) -create_ebpf_tracepoint(FunctionName) | Equivalent to API call [CreateEBPFTracepoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.CreateEBPFTracepoint) -create_watchpoint(Scope, Expr, Type) | Equivalent to API call [CreateWatchpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.CreateWatchpoint) -detach(Kill) | Equivalent to API call [Detach](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Detach) -disassemble(Scope, StartPC, EndPC, Flavour) | Equivalent to API call [Disassemble](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Disassemble) -dump_cancel() | Equivalent to API call [DumpCancel](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.DumpCancel) -dump_start(Destination) | Equivalent to API call [DumpStart](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.DumpStart) -dump_wait(Wait) | Equivalent to API call [DumpWait](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.DumpWait) -eval(Scope, Expr, Cfg) | Equivalent to API call [Eval](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Eval) -examine_memory(Address, Length) | Equivalent to API call [ExamineMemory](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ExamineMemory) -find_location(Scope, Loc, IncludeNonExecutableLines, SubstitutePathRules) | Equivalent to API call [FindLocation](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.FindLocation) -function_return_locations(FnName) | Equivalent to API call [FunctionReturnLocations](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.FunctionReturnLocations) -get_breakpoint(Id, Name) | Equivalent to API call [GetBreakpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.GetBreakpoint) -get_buffered_tracepoints() | Equivalent to API call [GetBufferedTracepoints](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.GetBufferedTracepoints) -get_thread(Id) | Equivalent to API call [GetThread](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.GetThread) -is_multiclient() | Equivalent to API call [IsMulticlient](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.IsMulticlient) -last_modified() | Equivalent to API call [LastModified](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.LastModified) -breakpoints(All) | Equivalent to API call [ListBreakpoints](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListBreakpoints) -checkpoints() | Equivalent to API call [ListCheckpoints](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListCheckpoints) -dynamic_libraries() | Equivalent to API call [ListDynamicLibraries](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListDynamicLibraries) -function_args(Scope, Cfg) | Equivalent to API call [ListFunctionArgs](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListFunctionArgs) -functions(Filter) | Equivalent to API call [ListFunctions](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListFunctions) -goroutines(Start, Count, Filters, GoroutineGroupingOptions) | Equivalent to API call [ListGoroutines](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListGoroutines) -local_vars(Scope, Cfg) | Equivalent to API call [ListLocalVars](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListLocalVars) -package_vars(Filter, Cfg) | Equivalent to API call [ListPackageVars](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListPackageVars) -packages_build_info(IncludeFiles) | Equivalent to API call [ListPackagesBuildInfo](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListPackagesBuildInfo) -registers(ThreadID, IncludeFp, Scope) | Equivalent to API call [ListRegisters](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListRegisters) -sources(Filter) | Equivalent to API call [ListSources](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListSources) -threads() | Equivalent to API call [ListThreads](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListThreads) -types(Filter) | Equivalent to API call [ListTypes](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ListTypes) -process_pid() | Equivalent to API call [ProcessPid](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ProcessPid) -recorded() | Equivalent to API call [Recorded](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Recorded) -restart(Position, ResetArgs, NewArgs, Rerecord, Rebuild, NewRedirects) | Equivalent to API call [Restart](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Restart) -set_expr(Scope, Symbol, Value) | Equivalent to API call [Set](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Set) -stacktrace(Id, Depth, Full, Defers, Opts, Cfg) | Equivalent to API call [Stacktrace](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Stacktrace) -state(NonBlocking) | Equivalent to API call [State](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.State) -toggle_breakpoint(Id, Name) | Equivalent to API call [ToggleBreakpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ToggleBreakpoint) +amend_breakpoint(Breakpoint) | Equivalent to API call [AmendBreakpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.AmendBreakpoint) +ancestors(GoroutineID, NumAncestors, Depth) | Equivalent to API call [Ancestors](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Ancestors) +attached_to_existing_process() | Equivalent to API call [AttachedToExistingProcess](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.AttachedToExistingProcess) +build_id() | Equivalent to API call [BuildID](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.BuildID) +cancel_next() | Equivalent to API call [CancelNext](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.CancelNext) +checkpoint(Where) | Equivalent to API call [Checkpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Checkpoint) +clear_breakpoint(Id, Name) | Equivalent to API call [ClearBreakpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ClearBreakpoint) +clear_checkpoint(ID) | Equivalent to API call [ClearCheckpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ClearCheckpoint) +raw_command(Name, ThreadID, GoroutineID, ReturnInfoLoadConfig, Expr, UnsafeCall) | Equivalent to API call [Command](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Command) +create_breakpoint(Breakpoint, LocExpr, SubstitutePathRules, Suspended) | Equivalent to API call [CreateBreakpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.CreateBreakpoint) +create_ebpf_tracepoint(FunctionName) | Equivalent to API call [CreateEBPFTracepoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.CreateEBPFTracepoint) +create_watchpoint(Scope, Expr, Type) | Equivalent to API call [CreateWatchpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.CreateWatchpoint) +detach(Kill) | Equivalent to API call [Detach](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Detach) +disassemble(Scope, StartPC, EndPC, Flavour) | Equivalent to API call [Disassemble](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Disassemble) +dump_cancel() | Equivalent to API call [DumpCancel](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.DumpCancel) +dump_start(Destination) | Equivalent to API call [DumpStart](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.DumpStart) +dump_wait(Wait) | Equivalent to API call [DumpWait](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.DumpWait) +eval(Scope, Expr, Cfg) | Equivalent to API call [Eval](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Eval) +examine_memory(Address, Length) | Equivalent to API call [ExamineMemory](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ExamineMemory) +find_location(Scope, Loc, IncludeNonExecutableLines, SubstitutePathRules) | Equivalent to API call [FindLocation](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.FindLocation) +function_return_locations(FnName) | Equivalent to API call [FunctionReturnLocations](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.FunctionReturnLocations) +get_breakpoint(Id, Name) | Equivalent to API call [GetBreakpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.GetBreakpoint) +get_buffered_tracepoints() | Equivalent to API call [GetBufferedTracepoints](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.GetBufferedTracepoints) +get_thread(Id) | Equivalent to API call [GetThread](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.GetThread) +is_multiclient() | Equivalent to API call [IsMulticlient](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.IsMulticlient) +last_modified() | Equivalent to API call [LastModified](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.LastModified) +breakpoints(All) | Equivalent to API call [ListBreakpoints](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListBreakpoints) +checkpoints() | Equivalent to API call [ListCheckpoints](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListCheckpoints) +dynamic_libraries() | Equivalent to API call [ListDynamicLibraries](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListDynamicLibraries) +function_args(Scope, Cfg) | Equivalent to API call [ListFunctionArgs](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListFunctionArgs) +functions(Filter) | Equivalent to API call [ListFunctions](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListFunctions) +goroutines(Start, Count, Filters, GoroutineGroupingOptions) | Equivalent to API call [ListGoroutines](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListGoroutines) +local_vars(Scope, Cfg) | Equivalent to API call [ListLocalVars](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListLocalVars) +package_vars(Filter, Cfg) | Equivalent to API call [ListPackageVars](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListPackageVars) +packages_build_info(IncludeFiles) | Equivalent to API call [ListPackagesBuildInfo](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListPackagesBuildInfo) +registers(ThreadID, IncludeFp, Scope) | Equivalent to API call [ListRegisters](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListRegisters) +sources(Filter) | Equivalent to API call [ListSources](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListSources) +threads() | Equivalent to API call [ListThreads](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListThreads) +types(Filter) | Equivalent to API call [ListTypes](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ListTypes) +process_pid() | Equivalent to API call [ProcessPid](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ProcessPid) +recorded() | Equivalent to API call [Recorded](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Recorded) +restart(Position, ResetArgs, NewArgs, Rerecord, Rebuild, NewRedirects) | Equivalent to API call [Restart](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Restart) +set_expr(Scope, Symbol, Value) | Equivalent to API call [Set](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Set) +stacktrace(Id, Depth, Full, Defers, Opts, Cfg) | Equivalent to API call [Stacktrace](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.Stacktrace) +state(NonBlocking) | Equivalent to API call [State](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.State) +toggle_breakpoint(Id, Name) | Equivalent to API call [ToggleBreakpoint](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.ToggleBreakpoint) dlv_command(command) | Executes the specified command as if typed at the dlv_prompt read_file(path) | Reads the file as a string write_file(path, contents) | Writes string to a file @@ -93,7 +93,7 @@ If the command function has a doc string it will be used as a help message. # Working with variables -Variables of the target program can be accessed using `local_vars`, `function_args` or the `eval` functions. Each variable will be returned as a [Variable](https://godoc.org/github.com/go-delve/delve/service/api#Variable) struct, with one special field: `Value`. +Variables of the target program can be accessed using `local_vars`, `function_args` or the `eval` functions. Each variable will be returned as a [Variable](https://godoc.org/github.com/undoio/delve/service/api#Variable) struct, with one special field: `Value`. ## Variable.Value diff --git a/Documentation/installation/README.md b/Documentation/installation/README.md index d0204fa63..b16c89a97 100644 --- a/Documentation/installation/README.md +++ b/Documentation/installation/README.md @@ -4,23 +4,23 @@ The following instructions are known to work on Linux, macOS, Windows and FreeBS Clone the git repository and build: ``` -$ git clone https://github.com/go-delve/delve +$ git clone https://github.com/undoio/delve $ cd delve -$ go install github.com/go-delve/delve/cmd/dlv +$ go install github.com/undoio/delve/cmd/dlv ``` Alternatively, on Go version 1.16 or later: ``` # Install the latest release: -$ go install github.com/go-delve/delve/cmd/dlv@latest +$ go install github.com/undoio/delve/cmd/dlv@latest # Install at tree head: -$ go install github.com/go-delve/delve/cmd/dlv@master +$ go install github.com/undoio/delve/cmd/dlv@master # Install at a specific version or pseudo-version: -$ go install github.com/go-delve/delve/cmd/dlv@v1.7.3 -$ go install github.com/go-delve/delve/cmd/dlv@v1.7.4-0.20211208103735-2f13672765fe +$ go install github.com/undoio/delve/cmd/dlv@v1.7.3 +$ go install github.com/undoio/delve/cmd/dlv@v1.7.4-0.20211208103735-2f13672765fe ``` See [Versions](https://go.dev/ref/mod#versions) and [Pseudo-versions](https://go.dev/ref/mod#pseudo-versions) for how to format the version suffixes. @@ -29,7 +29,7 @@ See `go help install` for details on where the `dlv` executable is saved. If during the install step you receive an error similar to this: ``` -found packages native (proc.go) and your_operating_system_and_architecture_combination_is_not_supported_by_delve (support_sentinel.go) in /home/pi/go/src/github.com/go-delve/delve/pkg/proc/native +found packages native (proc.go) and your_operating_system_and_architecture_combination_is_not_supported_by_delve (support_sentinel.go) in /home/pi/go/src/github.com/undoio/delve/pkg/proc/native ``` It means that your combination of operating system and CPU architecture is not supported, check the output of `go version`. @@ -56,11 +56,11 @@ sudo dscl . append /Groups/_developer GroupMembership $(whoami) ## Compiling macOS native backend -You do not need the macOS native backend and it [has known problems](https://github.com/go-delve/delve/issues/1112). If you still want to build it: +You do not need the macOS native backend and it [has known problems](https://github.com/undoio/delve/issues/1112). If you still want to build it: 1. Run `xcode-select --install` 2. On macOS 10.14 manually install the legacy include headers by running `/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg` -3. Clone the repo into `$GOPATH/src/github.com/go-delve/delve` +3. Clone the repo into `$GOPATH/src/github.com/undoio/delve` 4. Run `make install` in that directory (on some versions of macOS this requires being root, the first time you run it, to install a new certificate) The makefile will take care of creating and installing a self-signed certificate automatically. diff --git a/README.md b/README.md index 597cef12b..3807a8774 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![Delve](https://raw.githubusercontent.com/go-delve/delve/master/assets/delve_horizontal.png) [![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/go-delve/delve/master/LICENSE) -[![GoDoc](https://godoc.org/github.com/go-delve/delve?status.svg)](https://godoc.org/github.com/go-delve/delve) +[![GoDoc](https://godoc.org/github.com/undoio/delve?status.svg)](https://godoc.org/github.com/undoio/delve) [![Build Status](https://delve.teamcity.com/app/rest/builds/buildType:(id:Delve_AggregatorBuild)/statusIcon.svg)](https://delve.teamcity.com/viewType.html?buildTypeId=Delve_AggregatorBuild&guest=1) The GitHub issue tracker is for **bugs** only. Please use the [developer mailing list](https://groups.google.com/forum/#!forum/delve-dev) for any feature proposals and discussions. diff --git a/_fixtures/consts.go b/_fixtures/consts.go index e343bdcf4..ae40a09ed 100644 --- a/_fixtures/consts.go +++ b/_fixtures/consts.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/go-delve/delve/_fixtures/internal/dir0/pkg" + "github.com/undoio/delve/_fixtures/internal/dir0/pkg" "runtime" ) diff --git a/_fixtures/dotpackagesiface.go b/_fixtures/dotpackagesiface.go index 2f3ddb682..67af771ee 100644 --- a/_fixtures/dotpackagesiface.go +++ b/_fixtures/dotpackagesiface.go @@ -2,8 +2,8 @@ package main import ( "fmt" - "github.com/go-delve/delve/_fixtures/internal/dir.io" - "github.com/go-delve/delve/_fixtures/internal/dir.io/io.io" + "github.com/undoio/delve/_fixtures/internal/dir.io" + "github.com/undoio/delve/_fixtures/internal/dir.io/io.io" "runtime" ) diff --git a/_fixtures/pkgrenames.go b/_fixtures/pkgrenames.go index 2f31d3054..18f8e3742 100644 --- a/_fixtures/pkgrenames.go +++ b/_fixtures/pkgrenames.go @@ -8,10 +8,10 @@ import ( pkg1 "go/ast" pkg2 "net/http" - "github.com/go-delve/delve/_fixtures/internal/dir.io" - "github.com/go-delve/delve/_fixtures/internal/dir0/pkg" - "github.com/go-delve/delve/_fixtures/internal/dir0/renamedpackage" - dir1pkg "github.com/go-delve/delve/_fixtures/internal/dir1/pkg" + "github.com/undoio/delve/_fixtures/internal/dir.io" + "github.com/undoio/delve/_fixtures/internal/dir0/pkg" + "github.com/undoio/delve/_fixtures/internal/dir0/renamedpackage" + dir1pkg "github.com/undoio/delve/_fixtures/internal/dir1/pkg" ) func main() { diff --git a/_fixtures/plugin2/plugin2.go b/_fixtures/plugin2/plugin2.go index d195c1cac..ff30c8655 100644 --- a/_fixtures/plugin2/plugin2.go +++ b/_fixtures/plugin2/plugin2.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/go-delve/delve/_fixtures/internal/pluginsupport" + "github.com/undoio/delve/_fixtures/internal/pluginsupport" ) func Fn2() string { diff --git a/_fixtures/plugintest2.go b/_fixtures/plugintest2.go index 6a81b99fb..781911dea 100644 --- a/_fixtures/plugintest2.go +++ b/_fixtures/plugintest2.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/go-delve/delve/_fixtures/internal/pluginsupport" + "github.com/undoio/delve/_fixtures/internal/pluginsupport" "os" "plugin" ) diff --git a/_scripts/gen-cli-docs.go b/_scripts/gen-cli-docs.go index 63b00c000..46a8f6542 100644 --- a/_scripts/gen-cli-docs.go +++ b/_scripts/gen-cli-docs.go @@ -8,7 +8,7 @@ import ( "log" "os" - "github.com/go-delve/delve/pkg/terminal" + "github.com/undoio/delve/pkg/terminal" ) func main() { diff --git a/_scripts/gen-starlark-bindings.go b/_scripts/gen-starlark-bindings.go index 25d4c8d55..7b30c0bb8 100644 --- a/_scripts/gen-starlark-bindings.go +++ b/_scripts/gen-starlark-bindings.go @@ -158,7 +158,7 @@ func genMapping(bindings []binding) []byte { fmt.Fprintf(buf, "// DO NOT EDIT: auto-generated using _scripts/gen-starlark-bindings.go\n\n") fmt.Fprintf(buf, "package starbind\n\n") - fmt.Fprintf(buf, "import ( \"go.starlark.net/starlark\" \n \"github.com/go-delve/delve/service/api\" \n \"github.com/go-delve/delve/service/rpc2\" \n \"fmt\" )\n\n") + fmt.Fprintf(buf, "import ( \"go.starlark.net/starlark\" \n \"github.com/undoio/delve/service/api\" \n \"github.com/undoio/delve/service/rpc2\" \n \"fmt\" )\n\n") fmt.Fprintf(buf, "func (env *Env) starlarkPredeclare() starlark.StringDict {\n") fmt.Fprintf(buf, "r := starlark.StringDict{}\n\n") @@ -173,15 +173,15 @@ func genMapping(bindings []binding) []byte { fmt.Fprintf(buf, "if len(args) > %d && args[%d] != starlark.None { err := unmarshalStarlarkValue(args[%d], &rpcArgs.%s, %q); if err != nil { return starlark.None, decorateError(thread, err) } }", i, i, i, binding.argNames[i], binding.argNames[i]) switch binding.argTypes[i] { - case "*github.com/go-delve/delve/service/api.LoadConfig": + case "*github.com/undoio/delve/service/api.LoadConfig": if binding.fn.Name() != "Stacktrace" { fmt.Fprintf(buf, "else { cfg := env.ctx.LoadConfig(); rpcArgs.%s = &cfg }", binding.argNames[i]) } - case "github.com/go-delve/delve/service/api.LoadConfig": + case "github.com/undoio/delve/service/api.LoadConfig": fmt.Fprintf(buf, "else { rpcArgs.%s = env.ctx.LoadConfig() }", binding.argNames[i]) - case "*github.com/go-delve/delve/service/api.EvalScope": + case "*github.com/undoio/delve/service/api.EvalScope": fmt.Fprintf(buf, "else { scope := env.ctx.Scope(); rpcArgs.%s = &scope }", binding.argNames[i]) - case "github.com/go-delve/delve/service/api.EvalScope": + case "github.com/undoio/delve/service/api.EvalScope": fmt.Fprintf(buf, "else { rpcArgs.%s = env.ctx.Scope() }", binding.argNames[i]) } @@ -225,7 +225,7 @@ func genDocs(bindings []binding) []byte { for _, binding := range bindings { argNames := strings.Join(binding.argNames, ", ") - fmt.Fprintf(&buf, "%s(%s) | Equivalent to API call [%s](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.%s)\n", binding.name, argNames, binding.fn.Name(), binding.fn.Name()) + fmt.Fprintf(&buf, "%s(%s) | Equivalent to API call [%s](https://godoc.org/github.com/undoio/delve/service/rpc2#RPCServer.%s)\n", binding.name, argNames, binding.fn.Name(), binding.fn.Name()) } fmt.Fprintf(&buf, "dlv_command(command) | Executes the specified command as if typed at the dlv_prompt\n") @@ -295,14 +295,14 @@ func main() { Mode: packages.LoadSyntax, Fset: fset, } - pkgs, err := packages.Load(cfg, "github.com/go-delve/delve/service/rpc2") + pkgs, err := packages.Load(cfg, "github.com/undoio/delve/service/rpc2") if err != nil { log.Fatalf("could not load packages: %v", err) } var serverMethods []*types.Func packages.Visit(pkgs, func(pkg *packages.Package) bool { - if pkg.PkgPath == "github.com/go-delve/delve/service/rpc2" { + if pkg.PkgPath == "github.com/undoio/delve/service/rpc2" { serverMethods = getSuitableMethods(pkg.Types, "RPCServer") } return true diff --git a/_scripts/gen-travis.go b/_scripts/gen-travis.go index a6028c92e..7d10bd2b3 100644 --- a/_scripts/gen-travis.go +++ b/_scripts/gen-travis.go @@ -9,7 +9,7 @@ import ( "os" "text/template" - "github.com/go-delve/delve/pkg/goversion" + "github.com/undoio/delve/pkg/goversion" ) type arguments struct { diff --git a/_scripts/gen-usage-docs.go b/_scripts/gen-usage-docs.go index 02c9b4a9d..6543150a8 100644 --- a/_scripts/gen-usage-docs.go +++ b/_scripts/gen-usage-docs.go @@ -9,7 +9,7 @@ import ( "os" "path/filepath" - "github.com/go-delve/delve/cmd/dlv/cmds" + "github.com/undoio/delve/cmd/dlv/cmds" "github.com/spf13/cobra/doc" ) diff --git a/_scripts/make.go b/_scripts/make.go index 3b2fc299b..21ca7f5ca 100644 --- a/_scripts/make.go +++ b/_scripts/make.go @@ -11,11 +11,11 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/goversion" + "github.com/undoio/delve/pkg/goversion" "github.com/spf13/cobra" ) -const DelveMainPackagePath = "github.com/go-delve/delve/cmd/dlv" +const DelveMainPackagePath = "github.com/undoio/delve/cmd/dlv" var Verbose bool var NOTimeout bool @@ -98,7 +98,7 @@ Use the flags -s, -r and -b to specify which tests to run. Specifying nothing wi test.PersistentFlags().StringVarP(&TestSet, "test-set", "s", "", `Select the set of tests to run, one of either: all tests all packages basic tests proc, integration and terminal - integration tests github.com/go-delve/delve/service/test + integration tests github.com/undoio/delve/service/test package-name test the specified package only `) test.PersistentFlags().StringVarP(&TestRegex, "test-run", "r", "", `Only runs the tests matching the specified regex. This option can only be specified if testset is a single package`) @@ -473,10 +473,10 @@ func testSetToPackages(testSet string) []string { return allPackages() case "basic": - return []string{"github.com/go-delve/delve/pkg/proc", "github.com/go-delve/delve/service/test", "github.com/go-delve/delve/pkg/terminal"} + return []string{"github.com/undoio/delve/pkg/proc", "github.com/undoio/delve/service/test", "github.com/undoio/delve/pkg/terminal"} case "integration": - return []string{"github.com/go-delve/delve/service/test"} + return []string{"github.com/undoio/delve/service/test"} default: for _, pkg := range allPackages() { diff --git a/_scripts/rtype.go b/_scripts/rtype.go index 5ba8b9c9c..3ca9c371e 100644 --- a/_scripts/rtype.go +++ b/_scripts/rtype.go @@ -164,7 +164,7 @@ func main() { // setup parses the proc package, extracting all +rtype comments and // converting them into rules. func setup() { - pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax, Fset: fset}, "github.com/go-delve/delve/pkg/proc") + pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax, Fset: fset}, "github.com/undoio/delve/pkg/proc") if err != nil { log.Fatalf("could not load proc package: %v", err) } @@ -313,7 +313,7 @@ func isProcVariableDecl(stmt ast.Stmt, tinfo *types.Info) *ast.Ident { if typ == nil { return nil } - if typ == nil || typ.String() != "*github.com/go-delve/delve/pkg/proc.Variable" { + if typ == nil || typ.String() != "*github.com/undoio/delve/pkg/proc.Variable" { return nil } return ident diff --git a/cmd/dlv/cmds/commands.go b/cmd/dlv/cmds/commands.go index c98c047b5..db2a735dd 100644 --- a/cmd/dlv/cmds/commands.go +++ b/cmd/dlv/cmds/commands.go @@ -15,20 +15,20 @@ import ( "strings" "syscall" - "github.com/go-delve/delve/pkg/config" - "github.com/go-delve/delve/pkg/gobuild" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/terminal" - "github.com/go-delve/delve/pkg/version" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/dap" - "github.com/go-delve/delve/service/debugger" - "github.com/go-delve/delve/service/rpc2" - "github.com/go-delve/delve/service/rpccommon" "github.com/mattn/go-isatty" "github.com/spf13/cobra" + "github.com/undoio/delve/pkg/config" + "github.com/undoio/delve/pkg/gobuild" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/terminal" + "github.com/undoio/delve/pkg/version" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/dap" + "github.com/undoio/delve/service/debugger" + "github.com/undoio/delve/service/rpc2" + "github.com/undoio/delve/service/rpccommon" ) var ( diff --git a/cmd/dlv/dlv_test.go b/cmd/dlv/dlv_test.go index e1c300652..f344702ef 100644 --- a/cmd/dlv/dlv_test.go +++ b/cmd/dlv/dlv_test.go @@ -21,14 +21,14 @@ import ( "testing" "time" - "github.com/go-delve/delve/pkg/goversion" - protest "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/pkg/terminal" - "github.com/go-delve/delve/service/dap" - "github.com/go-delve/delve/service/dap/daptest" - "github.com/go-delve/delve/service/debugger" - "github.com/go-delve/delve/service/rpc2" godap "github.com/google/go-dap" + "github.com/undoio/delve/pkg/goversion" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/terminal" + "github.com/undoio/delve/service/dap" + "github.com/undoio/delve/service/dap/daptest" + "github.com/undoio/delve/service/debugger" + "github.com/undoio/delve/service/rpc2" "golang.org/x/tools/go/packages" ) @@ -224,11 +224,11 @@ func getDlvBinEBPF(t *testing.T) string { func getDlvBinInternal(t *testing.T, goflags ...string) string { dlvbin := filepath.Join(t.TempDir(), "dlv.exe") args := append([]string{"build", "-o", dlvbin}, goflags...) - args = append(args, "github.com/go-delve/delve/cmd/dlv") + args = append(args, "github.com/undoio/delve/cmd/dlv") out, err := exec.Command("go", args...).CombinedOutput() if err != nil { - t.Fatalf("go build -o %v github.com/go-delve/delve/cmd/dlv: %v\n%s", dlvbin, err, string(out)) + t.Fatalf("go build -o %v github.com/undoio/delve/cmd/dlv: %v\n%s", dlvbin, err, string(out)) } return dlvbin @@ -555,7 +555,7 @@ func TestTypecheckRPC(t *testing.T) { Mode: packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedName | packages.NeedCompiledGoFiles | packages.NeedTypes, Fset: fset, } - pkgs, err := packages.Load(cfg, "github.com/go-delve/delve/service/rpc2") + pkgs, err := packages.Load(cfg, "github.com/undoio/delve/service/rpc2") if err != nil { t.Fatal(err) } @@ -563,7 +563,7 @@ func TestTypecheckRPC(t *testing.T) { var serverMethods map[string]*types.Func var info *types.Info packages.Visit(pkgs, func(pkg *packages.Package) bool { - if pkg.PkgPath != "github.com/go-delve/delve/service/rpc2" { + if pkg.PkgPath != "github.com/undoio/delve/service/rpc2" { return true } t.Logf("package found: %v", pkg.PkgPath) @@ -1299,7 +1299,7 @@ func TestVersion(t *testing.T) { if err != nil { t.Fatalf("error executing `dlv version`: %v\n%s\n", err, got) } - want1 := []byte("mod\tgithub.com/go-delve/delve") + want1 := []byte("mod\tgithub.com/undoio/delve") want2 := []byte("dep\tgithub.com/google/go-dap") if !bytes.Contains(got, want1) || !bytes.Contains(got, want2) { t.Errorf("got %s\nwant %v and %v in the output", got, want1, want2) @@ -1312,7 +1312,7 @@ func TestStaticcheck(t *testing.T) { t.Skip("staticcheck not installed") } // default checks minus SA1019 which complains about deprecated identifiers, which change between versions of Go. - args := []string{"-tests=false", "-checks=all,-SA1019,-ST1000,-ST1003,-ST1016,-S1021,-ST1023", "github.com/go-delve/delve/..."} + args := []string{"-tests=false", "-checks=all,-SA1019,-ST1000,-ST1003,-ST1016,-S1021,-ST1023", "github.com/undoio/delve/..."} // * SA1019 is disabled because new deprecations get added on every version // of Go making the output of staticcheck inconsistent depending on the // version of Go used to run it. diff --git a/cmd/dlv/main.go b/cmd/dlv/main.go index 34df91db4..e1643c16e 100644 --- a/cmd/dlv/main.go +++ b/cmd/dlv/main.go @@ -3,9 +3,9 @@ package main import ( "os" - "github.com/go-delve/delve/cmd/dlv/cmds" - "github.com/go-delve/delve/pkg/version" "github.com/sirupsen/logrus" + "github.com/undoio/delve/cmd/dlv/cmds" + "github.com/undoio/delve/pkg/version" ) // Build is the git sha of this binaries build. diff --git a/go.mod b/go.mod index 2be8c4d5b..8cbf15d2a 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/go-delve/delve +module github.com/undoio/delve go 1.16 diff --git a/pkg/config/config.go b/pkg/config/config.go index 035b137df..eba147f49 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -9,7 +9,7 @@ import ( "path" "runtime" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service/api" "gopkg.in/yaml.v2" ) diff --git a/pkg/dwarf/dwarfbuilder/info.go b/pkg/dwarf/dwarfbuilder/info.go index 7cc5b94fb..6c9522323 100644 --- a/pkg/dwarf/dwarfbuilder/info.go +++ b/pkg/dwarf/dwarfbuilder/info.go @@ -5,8 +5,8 @@ import ( "debug/dwarf" "encoding/binary" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) // Form represents a DWARF form kind (see Figure 20, page 160 and following, diff --git a/pkg/dwarf/dwarfbuilder/loc.go b/pkg/dwarf/dwarfbuilder/loc.go index f89e6e7ca..c73837d17 100644 --- a/pkg/dwarf/dwarfbuilder/loc.go +++ b/pkg/dwarf/dwarfbuilder/loc.go @@ -3,8 +3,8 @@ package dwarfbuilder import ( "bytes" - "github.com/go-delve/delve/pkg/dwarf/leb128" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf/op" ) // LocEntry represents one entry of debug_loc. diff --git a/pkg/dwarf/frame/parser.go b/pkg/dwarf/frame/parser.go index e789239c4..0e455a638 100644 --- a/pkg/dwarf/frame/parser.go +++ b/pkg/dwarf/frame/parser.go @@ -9,8 +9,8 @@ import ( "fmt" "io" - "github.com/go-delve/delve/pkg/dwarf" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) type parsefunc func(*parseContext) parsefunc diff --git a/pkg/dwarf/frame/table.go b/pkg/dwarf/frame/table.go index c49d2115b..287502335 100644 --- a/pkg/dwarf/frame/table.go +++ b/pkg/dwarf/frame/table.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "fmt" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf/leb128" ) // DWRule wrapper of rule defined for register values. diff --git a/pkg/dwarf/godwarf/addr.go b/pkg/dwarf/godwarf/addr.go index 2dff81de0..a1b38354c 100644 --- a/pkg/dwarf/godwarf/addr.go +++ b/pkg/dwarf/godwarf/addr.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "errors" - "github.com/go-delve/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf" ) // DebugAddrSection represents the debug_addr section of DWARFv5. diff --git a/pkg/dwarf/godwarf/type.go b/pkg/dwarf/godwarf/type.go index 5b6df937b..f67c5355c 100644 --- a/pkg/dwarf/godwarf/type.go +++ b/pkg/dwarf/godwarf/type.go @@ -16,7 +16,7 @@ import ( "reflect" "strconv" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/op" ) const ( diff --git a/pkg/dwarf/line/line_parser.go b/pkg/dwarf/line/line_parser.go index 030689a3a..4f6f76cb7 100644 --- a/pkg/dwarf/line/line_parser.go +++ b/pkg/dwarf/line/line_parser.go @@ -6,8 +6,8 @@ import ( "path" "strings" - "github.com/go-delve/delve/pkg/dwarf" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) // DebugLinePrologue prologue of .debug_line data. diff --git a/pkg/dwarf/line/line_parser_test.go b/pkg/dwarf/line/line_parser_test.go index 043a16bfe..a0d1c8ef8 100644 --- a/pkg/dwarf/line/line_parser_test.go +++ b/pkg/dwarf/line/line_parser_test.go @@ -17,8 +17,8 @@ import ( "time" "unsafe" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/goversion" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/goversion" ) var userTestFile string diff --git a/pkg/dwarf/line/parse_util.go b/pkg/dwarf/line/parse_util.go index b1f22e545..bbb726453 100644 --- a/pkg/dwarf/line/parse_util.go +++ b/pkg/dwarf/line/parse_util.go @@ -5,8 +5,8 @@ import ( "encoding/binary" "errors" - "github.com/go-delve/delve/pkg/dwarf" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) const ( diff --git a/pkg/dwarf/line/state_machine.go b/pkg/dwarf/line/state_machine.go index 6c31fb461..601443d4c 100644 --- a/pkg/dwarf/line/state_machine.go +++ b/pkg/dwarf/line/state_machine.go @@ -7,8 +7,8 @@ import ( "fmt" "io" - "github.com/go-delve/delve/pkg/dwarf" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) type Location struct { diff --git a/pkg/dwarf/line/state_machine_test.go b/pkg/dwarf/line/state_machine_test.go index 0effee88d..b3aa49940 100644 --- a/pkg/dwarf/line/state_machine_test.go +++ b/pkg/dwarf/line/state_machine_test.go @@ -12,8 +12,8 @@ import ( "os" "testing" - pdwarf "github.com/go-delve/delve/pkg/dwarf" - "github.com/go-delve/delve/pkg/dwarf/leb128" + pdwarf "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) func slurpGzip(path string) ([]byte, error) { diff --git a/pkg/dwarf/loclist/dwarf2_loclist.go b/pkg/dwarf/loclist/dwarf2_loclist.go index e9859cd7f..40df07957 100644 --- a/pkg/dwarf/loclist/dwarf2_loclist.go +++ b/pkg/dwarf/loclist/dwarf2_loclist.go @@ -3,7 +3,7 @@ package loclist import ( "encoding/binary" - "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/godwarf" ) // Reader represents a loclist reader. diff --git a/pkg/dwarf/loclist/dwarf5_loclist.go b/pkg/dwarf/loclist/dwarf5_loclist.go index 666f42f5e..772140803 100644 --- a/pkg/dwarf/loclist/dwarf5_loclist.go +++ b/pkg/dwarf/loclist/dwarf5_loclist.go @@ -5,9 +5,9 @@ import ( "encoding/binary" "fmt" - "github.com/go-delve/delve/pkg/dwarf" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) // Dwarf5Reader parses and presents DWARF loclist information for DWARF version 5 and later. diff --git a/pkg/dwarf/loclist/loclist5_test.go b/pkg/dwarf/loclist/loclist5_test.go index 5bf692cbc..1a3f8106b 100644 --- a/pkg/dwarf/loclist/loclist5_test.go +++ b/pkg/dwarf/loclist/loclist5_test.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "testing" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "github.com/undoio/delve/pkg/dwarf/leb128" ) func TestLoclist5(t *testing.T) { diff --git a/pkg/dwarf/op/op.go b/pkg/dwarf/op/op.go index a3269f201..797ba5ff6 100644 --- a/pkg/dwarf/op/op.go +++ b/pkg/dwarf/op/op.go @@ -7,8 +7,8 @@ import ( "fmt" "io" - "github.com/go-delve/delve/pkg/dwarf/leb128" - "github.com/go-delve/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/leb128" ) // Opcode represent a DWARF stack program instruction. diff --git a/pkg/dwarf/parseutil_test.go b/pkg/dwarf/parseutil_test.go index c8ea66ca9..a5221c0da 100644 --- a/pkg/dwarf/parseutil_test.go +++ b/pkg/dwarf/parseutil_test.go @@ -4,7 +4,7 @@ import ( "bytes" "testing" - "github.com/go-delve/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf" ) func TestReadString(t *testing.T) { diff --git a/pkg/dwarf/reader/reader.go b/pkg/dwarf/reader/reader.go index d0a869117..5e7fffb67 100644 --- a/pkg/dwarf/reader/reader.go +++ b/pkg/dwarf/reader/reader.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" ) type Reader struct { diff --git a/pkg/dwarf/reader/variables.go b/pkg/dwarf/reader/variables.go index d39f9d68a..c9e507d5f 100644 --- a/pkg/dwarf/reader/variables.go +++ b/pkg/dwarf/reader/variables.go @@ -3,7 +3,7 @@ package reader import ( "debug/dwarf" - "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/godwarf" ) type Variable struct { diff --git a/pkg/gobuild/gobuild.go b/pkg/gobuild/gobuild.go index c42318e89..b054ef108 100644 --- a/pkg/gobuild/gobuild.go +++ b/pkg/gobuild/gobuild.go @@ -10,7 +10,7 @@ import ( "strings" "time" - "github.com/go-delve/delve/pkg/config" + "github.com/undoio/delve/pkg/config" ) // Remove the file at path and issue a warning to stderr if this fails. diff --git a/pkg/goversion/compat.go b/pkg/goversion/compat.go index 5524ac9b5..d5aff8896 100644 --- a/pkg/goversion/compat.go +++ b/pkg/goversion/compat.go @@ -3,7 +3,7 @@ package goversion import ( "fmt" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/logflags" ) var ( diff --git a/pkg/locspec/locations.go b/pkg/locspec/locations.go index c16a5b24d..deb3334bd 100644 --- a/pkg/locspec/locations.go +++ b/pkg/locspec/locations.go @@ -11,8 +11,8 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/service/api" ) const maxFindLocationCandidates = 5 diff --git a/pkg/locspec/locations_test.go b/pkg/locspec/locations_test.go index f83f513f1..634b0ff56 100644 --- a/pkg/locspec/locations_test.go +++ b/pkg/locspec/locations_test.go @@ -58,14 +58,14 @@ func TestFunctionLocationParsing(t *testing.T) { assertNormalLocationSpec(t, "Continue:10", NormalLocationSpec{"Continue", &FuncLocationSpec{BaseName: "Continue"}, 10}) // Function locations, package paths, no line offsets - assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.(*Process).Continue", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.(*Process).Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, -1}) - assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Process.Continue", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Process.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, -1}) - assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Continue", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", BaseName: "Continue"}, -1}) + assertNormalLocationSpec(t, "github.com/undoio/delve/pkg/proc.(*Process).Continue", NormalLocationSpec{"github.com/undoio/delve/pkg/proc.(*Process).Continue", &FuncLocationSpec{PackageName: "github.com/undoio/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, -1}) + assertNormalLocationSpec(t, "github.com/undoio/delve/pkg/proc.Process.Continue", NormalLocationSpec{"github.com/undoio/delve/pkg/proc.Process.Continue", &FuncLocationSpec{PackageName: "github.com/undoio/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, -1}) + assertNormalLocationSpec(t, "github.com/undoio/delve/pkg/proc.Continue", NormalLocationSpec{"github.com/undoio/delve/pkg/proc.Continue", &FuncLocationSpec{PackageName: "github.com/undoio/delve/pkg/proc", BaseName: "Continue"}, -1}) // Function locations, package paths, line offsets - assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.(*Process).Continue:10", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.(*Process).Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, 10}) - assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Process.Continue:10", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Process.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, 10}) - assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Continue:10", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", BaseName: "Continue"}, 10}) + assertNormalLocationSpec(t, "github.com/undoio/delve/pkg/proc.(*Process).Continue:10", NormalLocationSpec{"github.com/undoio/delve/pkg/proc.(*Process).Continue", &FuncLocationSpec{PackageName: "github.com/undoio/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, 10}) + assertNormalLocationSpec(t, "github.com/undoio/delve/pkg/proc.Process.Continue:10", NormalLocationSpec{"github.com/undoio/delve/pkg/proc.Process.Continue", &FuncLocationSpec{PackageName: "github.com/undoio/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, 10}) + assertNormalLocationSpec(t, "github.com/undoio/delve/pkg/proc.Continue:10", NormalLocationSpec{"github.com/undoio/delve/pkg/proc.Continue", &FuncLocationSpec{PackageName: "github.com/undoio/delve/pkg/proc", BaseName: "Continue"}, 10}) } func assertSubstitutePathEqual(t *testing.T, expected string, substituted string) { diff --git a/pkg/proc/amd64_arch.go b/pkg/proc/amd64_arch.go index 1d4ab4b9d..6991b18da 100644 --- a/pkg/proc/amd64_arch.go +++ b/pkg/proc/amd64_arch.go @@ -8,9 +8,9 @@ import ( "math" "strings" - "github.com/go-delve/delve/pkg/dwarf/frame" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" ) var amd64BreakInstruction = []byte{0xCC} diff --git a/pkg/proc/amd64_disasm.go b/pkg/proc/amd64_disasm.go index a27366bb9..1e67b367d 100644 --- a/pkg/proc/amd64_disasm.go +++ b/pkg/proc/amd64_disasm.go @@ -5,8 +5,8 @@ package proc import ( - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" "golang.org/x/arch/x86/x86asm" ) diff --git a/pkg/proc/amd64util/xsave.go b/pkg/proc/amd64util/xsave.go index 16e621fd7..566164eac 100644 --- a/pkg/proc/amd64util/xsave.go +++ b/pkg/proc/amd64util/xsave.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "fmt" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) // AMD64Xstate represents amd64 XSAVE area. See Section 13.1 (and diff --git a/pkg/proc/arch.go b/pkg/proc/arch.go index 22de6b168..96b27a386 100644 --- a/pkg/proc/arch.go +++ b/pkg/proc/arch.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" - "github.com/go-delve/delve/pkg/dwarf/frame" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/op" ) // Arch represents a CPU architecture. diff --git a/pkg/proc/arm64_arch.go b/pkg/proc/arm64_arch.go index 46ddd463b..bd71013c0 100644 --- a/pkg/proc/arm64_arch.go +++ b/pkg/proc/arm64_arch.go @@ -7,10 +7,10 @@ import ( "runtime" "strings" - "github.com/go-delve/delve/pkg/dwarf/frame" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/goversion" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/goversion" ) var arm64BreakInstruction = []byte{0x0, 0x0, 0x20, 0xd4} diff --git a/pkg/proc/arm64_disasm.go b/pkg/proc/arm64_disasm.go index 517c9a257..02a933712 100644 --- a/pkg/proc/arm64_disasm.go +++ b/pkg/proc/arm64_disasm.go @@ -5,8 +5,8 @@ package proc import ( - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" "golang.org/x/arch/arm64/arm64asm" ) diff --git a/pkg/proc/bininfo.go b/pkg/proc/bininfo.go index 5f862a9ef..49bd7ac6f 100644 --- a/pkg/proc/bininfo.go +++ b/pkg/proc/bininfo.go @@ -23,17 +23,17 @@ import ( "sync" "time" - pdwarf "github.com/go-delve/delve/pkg/dwarf" - "github.com/go-delve/delve/pkg/dwarf/frame" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/line" - "github.com/go-delve/delve/pkg/dwarf/loclist" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/reader" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc/debuginfod" "github.com/hashicorp/golang-lru/simplelru" + pdwarf "github.com/undoio/delve/pkg/dwarf" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/line" + "github.com/undoio/delve/pkg/dwarf/loclist" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc/debuginfod" ) const ( @@ -79,7 +79,7 @@ type BinaryInfo struct { // PackageMap maps package names to package paths, needed to lookup types inside DWARF info. // On Go1.12 this mapping is determined by using the last element of a package path, for example: - // github.com/go-delve/delve + // github.com/undoio/delve // will map to 'delve' because it ends in '/delve'. // Starting with Go1.13 debug_info will contain a special attribute // (godwarf.AttrGoPackageName) containing the canonical package name for diff --git a/pkg/proc/breakpoints.go b/pkg/proc/breakpoints.go index fb35aba28..d6dabc9fc 100644 --- a/pkg/proc/breakpoints.go +++ b/pkg/proc/breakpoints.go @@ -10,11 +10,11 @@ import ( "go/token" "reflect" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/reader" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/proc/internal/ebpf" ) const ( diff --git a/pkg/proc/core/core.go b/pkg/proc/core/core.go index 734dbd415..ff48fa34b 100644 --- a/pkg/proc/core/core.go +++ b/pkg/proc/core/core.go @@ -5,10 +5,10 @@ import ( "fmt" "io" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/internal/ebpf" ) // ErrNoThreads core file did not contain any threads. diff --git a/pkg/proc/core/core_test.go b/pkg/proc/core/core_test.go index 3444fdc34..cff2103f2 100644 --- a/pkg/proc/core/core_test.go +++ b/pkg/proc/core/core_test.go @@ -15,9 +15,9 @@ import ( "strings" "testing" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/test" ) var buildMode string diff --git a/pkg/proc/core/delve_core.go b/pkg/proc/core/delve_core.go index 9a8d146cf..4e6cd7541 100644 --- a/pkg/proc/core/delve_core.go +++ b/pkg/proc/core/delve_core.go @@ -7,9 +7,9 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/proc" ) func platformFromNotes(notes []*note) (goos, goarch string, err error) { diff --git a/pkg/proc/core/linux_core.go b/pkg/proc/core/linux_core.go index 4dd94f648..0c9c191ab 100644 --- a/pkg/proc/core/linux_core.go +++ b/pkg/proc/core/linux_core.go @@ -9,10 +9,10 @@ import ( "os" "strings" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/linutil" ) // Copied from golang.org/x/sys/unix.Timeval since it's not available on all diff --git a/pkg/proc/core/minidump/minidump.go b/pkg/proc/core/minidump/minidump.go index e0e3e5ed3..491e352a1 100644 --- a/pkg/proc/core/minidump/minidump.go +++ b/pkg/proc/core/minidump/minidump.go @@ -24,7 +24,7 @@ import ( "unicode/utf16" "unsafe" - "github.com/go-delve/delve/pkg/proc/winutil" + "github.com/undoio/delve/pkg/proc/winutil" ) type minidumpBuf struct { diff --git a/pkg/proc/core/windows_amd64_minidump.go b/pkg/proc/core/windows_amd64_minidump.go index 0bcb5e4ec..ef2925a93 100644 --- a/pkg/proc/core/windows_amd64_minidump.go +++ b/pkg/proc/core/windows_amd64_minidump.go @@ -1,10 +1,10 @@ package core import ( - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/core/minidump" - "github.com/go-delve/delve/pkg/proc/winutil" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/core/minidump" + "github.com/undoio/delve/pkg/proc/winutil" ) func readAMD64Minidump(minidumpPath, exePath string) (*process, proc.Thread, error) { diff --git a/pkg/proc/disasm.go b/pkg/proc/disasm.go index 92c5b3b6c..8b850adbf 100644 --- a/pkg/proc/disasm.go +++ b/pkg/proc/disasm.go @@ -3,7 +3,7 @@ package proc import ( "fmt" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/op" ) // AsmInstruction represents one assembly instruction. diff --git a/pkg/proc/dump.go b/pkg/proc/dump.go index bfa29cc9b..254bce218 100644 --- a/pkg/proc/dump.go +++ b/pkg/proc/dump.go @@ -9,8 +9,8 @@ import ( "runtime" "sync" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/version" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/version" ) var ( diff --git a/pkg/proc/dwarf_export_test.go b/pkg/proc/dwarf_export_test.go index 191fde56d..07277ee95 100644 --- a/pkg/proc/dwarf_export_test.go +++ b/pkg/proc/dwarf_export_test.go @@ -1,7 +1,7 @@ package proc import ( - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/op" "golang.org/x/arch/x86/x86asm" ) diff --git a/pkg/proc/dwarf_expr_test.go b/pkg/proc/dwarf_expr_test.go index 88c9a46eb..9f1f63fd4 100644 --- a/pkg/proc/dwarf_expr_test.go +++ b/pkg/proc/dwarf_expr_test.go @@ -13,11 +13,11 @@ import ( "testing" "unsafe" - "github.com/go-delve/delve/pkg/dwarf/dwarfbuilder" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/dwarf/dwarfbuilder" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/linutil" ) func ptrSizeByRuntimeArch() int { diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index 83ff7d3dc..805503f85 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -16,11 +16,11 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/reader" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" ) var errOperationOnSpecialFloat = errors.New("operations on non-finite floats not implemented") diff --git a/pkg/proc/fbsdutil/regs.go b/pkg/proc/fbsdutil/regs.go index 0ca24b1ec..a50b8bb83 100644 --- a/pkg/proc/fbsdutil/regs.go +++ b/pkg/proc/fbsdutil/regs.go @@ -3,10 +3,10 @@ package fbsdutil import ( "fmt" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" ) // AMD64Registers implements the proc.Registers interface for the native/freebsd diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go index f5dd79a95..f0550e27d 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -13,12 +13,12 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/reader" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" ) // This file implements the function call injection introduced in go1.11. diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 2bb871991..92fb06e4a 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -77,14 +77,14 @@ import ( "sync" "time" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" - "github.com/go-delve/delve/pkg/proc/linutil" - "github.com/go-delve/delve/pkg/proc/macutil" isatty "github.com/mattn/go-isatty" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/proc/macutil" ) const ( diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go index f6bde758e..e1d229861 100644 --- a/pkg/proc/gdbserial/gdbserver_conn.go +++ b/pkg/proc/gdbserial/gdbserver_conn.go @@ -15,8 +15,8 @@ import ( "strings" "time" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" ) type gdbConn struct { diff --git a/pkg/proc/gdbserial/rr.go b/pkg/proc/gdbserial/rr.go index ca70850b6..b3fbdbd42 100644 --- a/pkg/proc/gdbserial/rr.go +++ b/pkg/proc/gdbserial/rr.go @@ -12,8 +12,8 @@ import ( "strings" "syscall" - "github.com/go-delve/delve/pkg/config" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/config" + "github.com/undoio/delve/pkg/proc" ) // RecordAsync configures rr to record the execution of the specified diff --git a/pkg/proc/gdbserial/rr_test.go b/pkg/proc/gdbserial/rr_test.go index 9c96280f6..835af3d81 100644 --- a/pkg/proc/gdbserial/rr_test.go +++ b/pkg/proc/gdbserial/rr_test.go @@ -9,10 +9,10 @@ import ( "runtime" "testing" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/gdbserial" - protest "github.com/go-delve/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/gdbserial" + protest "github.com/undoio/delve/pkg/proc/test" ) func TestMain(m *testing.M) { diff --git a/pkg/proc/i386_arch.go b/pkg/proc/i386_arch.go index aaafad0ec..89d03174f 100644 --- a/pkg/proc/i386_arch.go +++ b/pkg/proc/i386_arch.go @@ -5,9 +5,9 @@ import ( "fmt" "strings" - "github.com/go-delve/delve/pkg/dwarf/frame" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" ) var i386BreakInstruction = []byte{0xCC} diff --git a/pkg/proc/i386_disasm.go b/pkg/proc/i386_disasm.go index bebcb9f77..562e96bca 100644 --- a/pkg/proc/i386_disasm.go +++ b/pkg/proc/i386_disasm.go @@ -5,8 +5,8 @@ package proc import ( - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" "golang.org/x/arch/x86/x86asm" ) diff --git a/pkg/proc/interface.go b/pkg/proc/interface.go index d2a0ef355..4efcb9a4b 100644 --- a/pkg/proc/interface.go +++ b/pkg/proc/interface.go @@ -3,8 +3,8 @@ package proc import ( "sync" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/proc/internal/ebpf" ) // ProcessGroup is a group of processes that are resumed at the same time. diff --git a/pkg/proc/internal/ebpf/context.go b/pkg/proc/internal/ebpf/context.go index 10ae46190..be6fe28db 100644 --- a/pkg/proc/internal/ebpf/context.go +++ b/pkg/proc/internal/ebpf/context.go @@ -3,8 +3,8 @@ package ebpf import ( "reflect" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" ) type UProbeArgMap struct { diff --git a/pkg/proc/internal/ebpf/dummy.go b/pkg/proc/internal/ebpf/dummy.go index 9ef6e6d3f..77436b1b9 100644 --- a/pkg/proc/internal/ebpf/dummy.go +++ b/pkg/proc/internal/ebpf/dummy.go @@ -9,6 +9,6 @@ package ebpf import ( - _ "github.com/go-delve/delve/pkg/proc/internal/ebpf/bpf" - _ "github.com/go-delve/delve/pkg/proc/internal/ebpf/bpf/include" + _ "github.com/undoio/delve/pkg/proc/internal/ebpf/bpf" + _ "github.com/undoio/delve/pkg/proc/internal/ebpf/bpf/include" ) diff --git a/pkg/proc/internal/ebpf/helpers.go b/pkg/proc/internal/ebpf/helpers.go index d9b5e7dfc..6a381828b 100644 --- a/pkg/proc/internal/ebpf/helpers.go +++ b/pkg/proc/internal/ebpf/helpers.go @@ -12,8 +12,8 @@ import ( "sync" "unsafe" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" "github.com/cilium/ebpf" "github.com/cilium/ebpf/link" diff --git a/pkg/proc/internal/ebpf/helpers_test.go b/pkg/proc/internal/ebpf/helpers_test.go index 8843ecb35..3205bcff4 100644 --- a/pkg/proc/internal/ebpf/helpers_test.go +++ b/pkg/proc/internal/ebpf/helpers_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/go-delve/delve/pkg/proc/internal/ebpf/testhelper" + "github.com/undoio/delve/pkg/proc/internal/ebpf/testhelper" ) func compareStructTypes(t *testing.T, gostructVal, cstructVal interface{}) { diff --git a/pkg/proc/linutil/dynamic.go b/pkg/proc/linutil/dynamic.go index 2e02a7741..476f08f30 100644 --- a/pkg/proc/linutil/dynamic.go +++ b/pkg/proc/linutil/dynamic.go @@ -7,7 +7,7 @@ import ( "fmt" "io" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) const ( diff --git a/pkg/proc/linutil/regs_amd64_arch.go b/pkg/proc/linutil/regs_amd64_arch.go index a15e56512..746d0c5d7 100644 --- a/pkg/proc/linutil/regs_amd64_arch.go +++ b/pkg/proc/linutil/regs_amd64_arch.go @@ -3,10 +3,10 @@ package linutil import ( "fmt" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" ) // AMD64Registers implements the proc.Registers interface for the native/linux diff --git a/pkg/proc/linutil/regs_arm64_arch.go b/pkg/proc/linutil/regs_arm64_arch.go index 05fb48e9c..7bcbe0946 100644 --- a/pkg/proc/linutil/regs_arm64_arch.go +++ b/pkg/proc/linutil/regs_arm64_arch.go @@ -3,9 +3,9 @@ package linutil import ( "fmt" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/proc" ) // ARM64Registers is a wrapper for sys.PtraceRegs. diff --git a/pkg/proc/linutil/regs_i386_arch.go b/pkg/proc/linutil/regs_i386_arch.go index dac34b3dc..26c2fc98d 100644 --- a/pkg/proc/linutil/regs_i386_arch.go +++ b/pkg/proc/linutil/regs_i386_arch.go @@ -1,8 +1,8 @@ package linutil import ( - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" ) // I386Registers implements the proc.Registers interface for the native/linux diff --git a/pkg/proc/mem.go b/pkg/proc/mem.go index cb2a35f67..beba65441 100644 --- a/pkg/proc/mem.go +++ b/pkg/proc/mem.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/op" ) const cacheEnabled = true diff --git a/pkg/proc/native/dump_linux.go b/pkg/proc/native/dump_linux.go index bbf57acbf..17725e3eb 100644 --- a/pkg/proc/native/dump_linux.go +++ b/pkg/proc/native/dump_linux.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) func (p *nativeProcess) MemoryMap() ([]proc.MemoryMapEntry, error) { diff --git a/pkg/proc/native/dump_linux_amd64.go b/pkg/proc/native/dump_linux_amd64.go index 0e36b3b48..7ba392e2b 100644 --- a/pkg/proc/native/dump_linux_amd64.go +++ b/pkg/proc/native/dump_linux_amd64.go @@ -8,8 +8,8 @@ import ( "io/ioutil" "path/filepath" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/proc/linutil" "golang.org/x/sys/unix" ) diff --git a/pkg/proc/native/dump_linux_other.go b/pkg/proc/native/dump_linux_other.go index d74491af8..67175137e 100644 --- a/pkg/proc/native/dump_linux_other.go +++ b/pkg/proc/native/dump_linux_other.go @@ -4,7 +4,7 @@ package native import ( - "github.com/go-delve/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/elfwriter" ) func (p *nativeProcess) DumpProcessNotes(notes []elfwriter.Note, threadDone func()) (threadsDone bool, out []elfwriter.Note, err error) { diff --git a/pkg/proc/native/dump_other.go b/pkg/proc/native/dump_other.go index e4ebf4421..174eda1b7 100644 --- a/pkg/proc/native/dump_other.go +++ b/pkg/proc/native/dump_other.go @@ -4,8 +4,8 @@ package native import ( - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/proc" ) func (p *nativeProcess) MemoryMap() ([]proc.MemoryMapEntry, error) { diff --git a/pkg/proc/native/dump_windows_amd64.go b/pkg/proc/native/dump_windows_amd64.go index 084de02fe..5ddaa52df 100644 --- a/pkg/proc/native/dump_windows_amd64.go +++ b/pkg/proc/native/dump_windows_amd64.go @@ -5,8 +5,8 @@ import ( "fmt" "unsafe" - "github.com/go-delve/delve/pkg/elfwriter" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/elfwriter" + "github.com/undoio/delve/pkg/proc" ) func (p *nativeProcess) MemoryMap() ([]proc.MemoryMapEntry, error) { diff --git a/pkg/proc/native/hwbreak_amd64.go b/pkg/proc/native/hwbreak_amd64.go index e15652a36..9abe5ec6e 100644 --- a/pkg/proc/native/hwbreak_amd64.go +++ b/pkg/proc/native/hwbreak_amd64.go @@ -1,8 +1,8 @@ package native import ( - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" ) func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error { diff --git a/pkg/proc/native/hwbreak_other.go b/pkg/proc/native/hwbreak_other.go index 261448303..aa5478337 100644 --- a/pkg/proc/native/hwbreak_other.go +++ b/pkg/proc/native/hwbreak_other.go @@ -6,7 +6,7 @@ package native import ( "errors" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) { diff --git a/pkg/proc/native/nonative_darwin.go b/pkg/proc/native/nonative_darwin.go index d0f7b19a5..599533db7 100644 --- a/pkg/proc/native/nonative_darwin.go +++ b/pkg/proc/native/nonative_darwin.go @@ -7,10 +7,10 @@ import ( "errors" "sync" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/internal/ebpf" ) var ErrNativeBackendDisabled = errors.New("native backend disabled during compilation") diff --git a/pkg/proc/native/proc.go b/pkg/proc/native/proc.go index c3d6c8643..bb5eba37d 100644 --- a/pkg/proc/native/proc.go +++ b/pkg/proc/native/proc.go @@ -4,7 +4,7 @@ import ( "os" "runtime" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) // Process represents all of the information the debugger diff --git a/pkg/proc/native/proc_darwin.go b/pkg/proc/native/proc_darwin.go index c8eca1da2..f8c82ba95 100644 --- a/pkg/proc/native/proc_darwin.go +++ b/pkg/proc/native/proc_darwin.go @@ -18,9 +18,9 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" - "github.com/go-delve/delve/pkg/proc/macutil" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/proc/macutil" ) // osProcessDetails holds Darwin specific information. diff --git a/pkg/proc/native/proc_freebsd.go b/pkg/proc/native/proc_freebsd.go index 40581e5ae..034c9cd16 100644 --- a/pkg/proc/native/proc_freebsd.go +++ b/pkg/proc/native/proc_freebsd.go @@ -14,8 +14,8 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/internal/ebpf" isatty "github.com/mattn/go-isatty" ) diff --git a/pkg/proc/native/proc_linux.go b/pkg/proc/native/proc_linux.go index e549928b5..ef5c1e422 100644 --- a/pkg/proc/native/proc_linux.go +++ b/pkg/proc/native/proc_linux.go @@ -19,9 +19,9 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/proc/linutil" isatty "github.com/mattn/go-isatty" ) diff --git a/pkg/proc/native/proc_windows.go b/pkg/proc/native/proc_windows.go index 705fe6e50..18b19932d 100644 --- a/pkg/proc/native/proc_windows.go +++ b/pkg/proc/native/proc_windows.go @@ -8,8 +8,8 @@ import ( sys "golang.org/x/sys/windows" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/internal/ebpf" ) // osProcessDetails holds Windows specific information. diff --git a/pkg/proc/native/ptrace_freebsd_amd64.go b/pkg/proc/native/ptrace_freebsd_amd64.go index 462d9aebd..435de3849 100644 --- a/pkg/proc/native/ptrace_freebsd_amd64.go +++ b/pkg/proc/native/ptrace_freebsd_amd64.go @@ -10,7 +10,7 @@ import ( "fmt" "unsafe" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/amd64util" ) var ( diff --git a/pkg/proc/native/ptrace_linux_386.go b/pkg/proc/native/ptrace_linux_386.go index 3139e3d3d..34f791469 100644 --- a/pkg/proc/native/ptrace_linux_386.go +++ b/pkg/proc/native/ptrace_linux_386.go @@ -7,7 +7,7 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/amd64util" ) // ptraceGetRegset returns floating point registers of the specified thread diff --git a/pkg/proc/native/ptrace_linux_amd64.go b/pkg/proc/native/ptrace_linux_amd64.go index b60c09c00..933d2ba86 100644 --- a/pkg/proc/native/ptrace_linux_amd64.go +++ b/pkg/proc/native/ptrace_linux_amd64.go @@ -6,7 +6,7 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/amd64util" ) // ptraceGetRegset returns floating point registers of the specified thread diff --git a/pkg/proc/native/register_linux_386.go b/pkg/proc/native/register_linux_386.go index 906b34fc7..b359b9a78 100644 --- a/pkg/proc/native/register_linux_386.go +++ b/pkg/proc/native/register_linux_386.go @@ -5,11 +5,11 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/linutil" ) // setPC sets EIP to the value specified by 'pc'. diff --git a/pkg/proc/native/registers_darwin_amd64.go b/pkg/proc/native/registers_darwin_amd64.go index c8246d7f7..e026675c5 100644 --- a/pkg/proc/native/registers_darwin_amd64.go +++ b/pkg/proc/native/registers_darwin_amd64.go @@ -11,9 +11,9 @@ import ( "golang.org/x/arch/x86/x86asm" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/proc" ) // Regs represents CPU registers on an AMD64 processor. diff --git a/pkg/proc/native/registers_freebsd_amd64.go b/pkg/proc/native/registers_freebsd_amd64.go index 2e7449b5b..c82bc5cd3 100644 --- a/pkg/proc/native/registers_freebsd_amd64.go +++ b/pkg/proc/native/registers_freebsd_amd64.go @@ -5,10 +5,10 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/fbsdutil" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/fbsdutil" ) // SetPC sets RIP to the value specified by 'pc'. diff --git a/pkg/proc/native/registers_linux_amd64.go b/pkg/proc/native/registers_linux_amd64.go index 676d89649..ab2aeb1b0 100644 --- a/pkg/proc/native/registers_linux_amd64.go +++ b/pkg/proc/native/registers_linux_amd64.go @@ -7,10 +7,10 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/linutil" ) // SetPC sets RIP to the value specified by 'pc'. diff --git a/pkg/proc/native/registers_linux_arm64.go b/pkg/proc/native/registers_linux_arm64.go index 0b797cc03..80127a042 100644 --- a/pkg/proc/native/registers_linux_arm64.go +++ b/pkg/proc/native/registers_linux_arm64.go @@ -7,9 +7,9 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/linutil" ) const ( diff --git a/pkg/proc/native/registers_windows.go b/pkg/proc/native/registers_windows.go index aa998f3f0..3b147d7ae 100644 --- a/pkg/proc/native/registers_windows.go +++ b/pkg/proc/native/registers_windows.go @@ -1,6 +1,6 @@ package native -import "github.com/go-delve/delve/pkg/dwarf/op" +import "github.com/undoio/delve/pkg/dwarf/op" // SetPC sets the RIP register to the value specified by `pc`. func (thread *nativeThread) setPC(pc uint64) error { diff --git a/pkg/proc/native/syscall_windows_amd64.go b/pkg/proc/native/syscall_windows_amd64.go index 713a5244a..db7b61d49 100644 --- a/pkg/proc/native/syscall_windows_amd64.go +++ b/pkg/proc/native/syscall_windows_amd64.go @@ -1,6 +1,6 @@ package native -import "github.com/go-delve/delve/pkg/proc/winutil" +import "github.com/undoio/delve/pkg/proc/winutil" const ( _CONTEXT_AMD64 = 0x100000 diff --git a/pkg/proc/native/syscall_windows_arm64.go b/pkg/proc/native/syscall_windows_arm64.go index 8b550f32c..bc422b0a9 100644 --- a/pkg/proc/native/syscall_windows_arm64.go +++ b/pkg/proc/native/syscall_windows_arm64.go @@ -1,6 +1,6 @@ package native -import "github.com/go-delve/delve/pkg/proc/winutil" +import "github.com/undoio/delve/pkg/proc/winutil" const ( _CONTEXT_ARM64 = 0x00400000 diff --git a/pkg/proc/native/threads.go b/pkg/proc/native/threads.go index 5cf570d60..740e3f75c 100644 --- a/pkg/proc/native/threads.go +++ b/pkg/proc/native/threads.go @@ -3,7 +3,7 @@ package native import ( "fmt" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) // Thread represents a single thread in the traced process diff --git a/pkg/proc/native/threads_darwin.go b/pkg/proc/native/threads_darwin.go index b338ff373..49d4bbb65 100644 --- a/pkg/proc/native/threads_darwin.go +++ b/pkg/proc/native/threads_darwin.go @@ -13,8 +13,8 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" ) // waitStatus is a synonym for the platform-specific WaitStatus diff --git a/pkg/proc/native/threads_freebsd.go b/pkg/proc/native/threads_freebsd.go index 241455be5..5ea745795 100644 --- a/pkg/proc/native/threads_freebsd.go +++ b/pkg/proc/native/threads_freebsd.go @@ -5,9 +5,9 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/fbsdutil" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/fbsdutil" ) type waitStatus sys.WaitStatus diff --git a/pkg/proc/native/threads_linux.go b/pkg/proc/native/threads_linux.go index 5d5572abd..c7945fb8f 100644 --- a/pkg/proc/native/threads_linux.go +++ b/pkg/proc/native/threads_linux.go @@ -5,7 +5,7 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) type waitStatus sys.WaitStatus diff --git a/pkg/proc/native/threads_linux_386.go b/pkg/proc/native/threads_linux_386.go index 338a166ba..c457201b3 100644 --- a/pkg/proc/native/threads_linux_386.go +++ b/pkg/proc/native/threads_linux_386.go @@ -2,7 +2,7 @@ package native import ( "fmt" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error { diff --git a/pkg/proc/native/threads_linux_amd64.go b/pkg/proc/native/threads_linux_amd64.go index 95147e47b..c1b3eb886 100644 --- a/pkg/proc/native/threads_linux_amd64.go +++ b/pkg/proc/native/threads_linux_amd64.go @@ -6,9 +6,9 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/linutil" ) func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error { diff --git a/pkg/proc/native/threads_linux_arm64.go b/pkg/proc/native/threads_linux_arm64.go index 151cbe0c9..325372ab4 100644 --- a/pkg/proc/native/threads_linux_arm64.go +++ b/pkg/proc/native/threads_linux_arm64.go @@ -9,8 +9,8 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/linutil" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/linutil" ) func (thread *nativeThread) fpRegisters() ([]proc.Register, []byte, error) { diff --git a/pkg/proc/native/threads_windows.go b/pkg/proc/native/threads_windows.go index 7fc45ea93..f7e471641 100644 --- a/pkg/proc/native/threads_windows.go +++ b/pkg/proc/native/threads_windows.go @@ -6,7 +6,7 @@ import ( sys "golang.org/x/sys/windows" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) const enableHardwareBreakpoints = false // see https://github.com/go-delve/delve/issues/2768 diff --git a/pkg/proc/native/threads_windows_amd64.go b/pkg/proc/native/threads_windows_amd64.go index e5273f3f5..3b0e0af7e 100644 --- a/pkg/proc/native/threads_windows_amd64.go +++ b/pkg/proc/native/threads_windows_amd64.go @@ -5,9 +5,9 @@ import ( "fmt" "unsafe" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/winutil" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/winutil" ) func newContext() *winutil.AMD64CONTEXT { diff --git a/pkg/proc/native/threads_windows_arm64.go b/pkg/proc/native/threads_windows_arm64.go index cbd8948f9..74d3bd521 100644 --- a/pkg/proc/native/threads_windows_arm64.go +++ b/pkg/proc/native/threads_windows_arm64.go @@ -1,8 +1,8 @@ package native import ( - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/winutil" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/winutil" ) func newContext() *winutil.ARM64CONTEXT { diff --git a/pkg/proc/proc_general_test.go b/pkg/proc/proc_general_test.go index 872b79b60..55fa26f53 100644 --- a/pkg/proc/proc_general_test.go +++ b/pkg/proc/proc_general_test.go @@ -7,7 +7,7 @@ import ( "testing" "unsafe" - protest "github.com/go-delve/delve/pkg/proc/test" + protest "github.com/undoio/delve/pkg/proc/test" ) func ptrSizeByRuntimeArch() int { @@ -141,20 +141,20 @@ func TestGenericFunctionParser(t *testing.T) { // Normal parsing var testCases = []struct{ name, pkg, rcv, base string }{ - {"github.com/go-delve/delve.afunc", "github.com/go-delve/delve", "", "afunc"}, - {"github.com/go-delve/delve..afunc", "github.com/go-delve/delve", "", "afunc"}, // malformed - {"github.com/go-delve/delve.afunc[some/[thing].el se]", "github.com/go-delve/delve", "", "afunc[some/[thing].el se]"}, - {"github.com/go-delve/delve.Receiver.afunc", "github.com/go-delve/delve", "Receiver", "afunc"}, - {"github.com/go-delve/delve.(*Receiver).afunc", "github.com/go-delve/delve", "(*Receiver)", "afunc"}, - {"github.com/go-delve/delve.Receiver.afunc[some/[thing].el se]", "github.com/go-delve/delve", "Receiver", "afunc[some/[thing].el se]"}, // malformed - {"github.com/go-delve/delve.(*Receiver).afunc[some/[thing].el se]", "github.com/go-delve/delve", "(*Receiver)", "afunc[some/[thing].el se]"}, // malformed - {"github.com/go-delve/delve.Receiver[some/[thing].el se].afunc", "github.com/go-delve/delve", "Receiver[some/[thing].el se]", "afunc"}, - {"github.com/go-delve/delve.(*Receiver[some/[thing].el se]).afunc", "github.com/go-delve/delve", "(*Receiver[some/[thing].el se])", "afunc"}, - - {"github.com/go-delve/delve.afunc[.some/[thing].el se]", "github.com/go-delve/delve", "", "afunc[.some/[thing].el se]"}, - {"github.com/go-delve/delve.Receiver.afunc[.some/[thing].el se]", "github.com/go-delve/delve", "Receiver", "afunc[.some/[thing].el se]"}, // malformed - {"github.com/go-delve/delve.Receiver[.some/[thing].el se].afunc", "github.com/go-delve/delve", "Receiver[.some/[thing].el se]", "afunc"}, - {"github.com/go-delve/delve.(*Receiver[.some/[thing].el se]).afunc", "github.com/go-delve/delve", "(*Receiver[.some/[thing].el se])", "afunc"}, + {"github.com/undoio/delve.afunc", "github.com/undoio/delve", "", "afunc"}, + {"github.com/undoio/delve..afunc", "github.com/undoio/delve", "", "afunc"}, // malformed + {"github.com/undoio/delve.afunc[some/[thing].el se]", "github.com/undoio/delve", "", "afunc[some/[thing].el se]"}, + {"github.com/undoio/delve.Receiver.afunc", "github.com/undoio/delve", "Receiver", "afunc"}, + {"github.com/undoio/delve.(*Receiver).afunc", "github.com/undoio/delve", "(*Receiver)", "afunc"}, + {"github.com/undoio/delve.Receiver.afunc[some/[thing].el se]", "github.com/undoio/delve", "Receiver", "afunc[some/[thing].el se]"}, // malformed + {"github.com/undoio/delve.(*Receiver).afunc[some/[thing].el se]", "github.com/undoio/delve", "(*Receiver)", "afunc[some/[thing].el se]"}, // malformed + {"github.com/undoio/delve.Receiver[some/[thing].el se].afunc", "github.com/undoio/delve", "Receiver[some/[thing].el se]", "afunc"}, + {"github.com/undoio/delve.(*Receiver[some/[thing].el se]).afunc", "github.com/undoio/delve", "(*Receiver[some/[thing].el se])", "afunc"}, + + {"github.com/undoio/delve.afunc[.some/[thing].el se]", "github.com/undoio/delve", "", "afunc[.some/[thing].el se]"}, + {"github.com/undoio/delve.Receiver.afunc[.some/[thing].el se]", "github.com/undoio/delve", "Receiver", "afunc[.some/[thing].el se]"}, // malformed + {"github.com/undoio/delve.Receiver[.some/[thing].el se].afunc", "github.com/undoio/delve", "Receiver[.some/[thing].el se]", "afunc"}, + {"github.com/undoio/delve.(*Receiver[.some/[thing].el se]).afunc", "github.com/undoio/delve", "(*Receiver[.some/[thing].el se])", "afunc"}, } for _, tc := range testCases { diff --git a/pkg/proc/proc_linux_test.go b/pkg/proc/proc_linux_test.go index d10e17ff4..97edf0731 100644 --- a/pkg/proc/proc_linux_test.go +++ b/pkg/proc/proc_linux_test.go @@ -6,8 +6,8 @@ import ( "path/filepath" "testing" - "github.com/go-delve/delve/pkg/proc/native" - protest "github.com/go-delve/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/proc/native" + protest "github.com/undoio/delve/pkg/proc/test" ) func TestLoadingExternalDebugInfo(t *testing.T) { diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 20f674f87..912a1ce11 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -24,17 +24,17 @@ import ( "text/tabwriter" "time" - "github.com/go-delve/delve/pkg/dwarf/frame" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/core" - "github.com/go-delve/delve/pkg/proc/gdbserial" - "github.com/go-delve/delve/pkg/proc/native" - protest "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/core" + "github.com/undoio/delve/pkg/proc/gdbserial" + "github.com/undoio/delve/pkg/proc/native" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service/api" ) var normalLoadConfig = proc.LoadConfig{true, 1, 64, 64, -1, 0} diff --git a/pkg/proc/proc_unix_test.go b/pkg/proc/proc_unix_test.go index 0404995be..45c1c6262 100644 --- a/pkg/proc/proc_unix_test.go +++ b/pkg/proc/proc_unix_test.go @@ -14,9 +14,9 @@ import ( "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/native" - protest "github.com/go-delve/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/native" + protest "github.com/undoio/delve/pkg/proc/test" ) type errIssue419 struct { diff --git a/pkg/proc/registers.go b/pkg/proc/registers.go index 185d0615c..246ab251b 100644 --- a/pkg/proc/registers.go +++ b/pkg/proc/registers.go @@ -6,7 +6,7 @@ import ( "math" "strings" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/op" ) // Registers is an interface for a generic register type. The diff --git a/pkg/proc/scope_test.go b/pkg/proc/scope_test.go index 52e9d645a..0d9f6390e 100644 --- a/pkg/proc/scope_test.go +++ b/pkg/proc/scope_test.go @@ -13,9 +13,9 @@ import ( "strings" "testing" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/proc" - protest "github.com/go-delve/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/proc" + protest "github.com/undoio/delve/pkg/proc/test" ) func TestScopeWithEscapedVariable(t *testing.T) { diff --git a/pkg/proc/stack.go b/pkg/proc/stack.go index 3ad7f2c4e..97ea13fc5 100644 --- a/pkg/proc/stack.go +++ b/pkg/proc/stack.go @@ -7,9 +7,9 @@ import ( "go/constant" "reflect" - "github.com/go-delve/delve/pkg/dwarf/frame" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/reader" ) // This code is partly adapted from runtime.gentraceback in diff --git a/pkg/proc/stackwatch.go b/pkg/proc/stackwatch.go index a092bd674..4bc01cf7f 100644 --- a/pkg/proc/stackwatch.go +++ b/pkg/proc/stackwatch.go @@ -3,8 +3,8 @@ package proc import ( "errors" - "github.com/go-delve/delve/pkg/astutil" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/astutil" + "github.com/undoio/delve/pkg/logflags" ) // This file implements most of the details needed to support stack diff --git a/pkg/proc/target.go b/pkg/proc/target.go index e1fafda0c..604894bc5 100644 --- a/pkg/proc/target.go +++ b/pkg/proc/target.go @@ -8,10 +8,10 @@ import ( "sort" "strings" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc/internal/ebpf" ) var ( diff --git a/pkg/proc/target_exec.go b/pkg/proc/target_exec.go index 6f45d588d..580d9efd4 100644 --- a/pkg/proc/target_exec.go +++ b/pkg/proc/target_exec.go @@ -10,8 +10,8 @@ import ( "path/filepath" "strings" - "github.com/go-delve/delve/pkg/astutil" - "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/astutil" + "github.com/undoio/delve/pkg/dwarf/reader" ) const maxSkipAutogeneratedWrappers = 5 // maximum recursion depth for skipAutogeneratedWrappers diff --git a/pkg/proc/target_group.go b/pkg/proc/target_group.go index 66ed9e735..4466005c5 100644 --- a/pkg/proc/target_group.go +++ b/pkg/proc/target_group.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/logflags" ) // TargetGroup represents a group of target processes being debugged that diff --git a/pkg/proc/test/support.go b/pkg/proc/test/support.go index d58c93381..cccce92da 100644 --- a/pkg/proc/test/support.go +++ b/pkg/proc/test/support.go @@ -14,7 +14,7 @@ import ( "sync" "testing" - "github.com/go-delve/delve/pkg/goversion" + "github.com/undoio/delve/pkg/goversion" ) // EnableRace allows to configure whether the race detector is enabled on target process. diff --git a/pkg/proc/threads.go b/pkg/proc/threads.go index e078966b2..be95a8c50 100644 --- a/pkg/proc/threads.go +++ b/pkg/proc/threads.go @@ -2,7 +2,7 @@ package proc import ( "errors" - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/op" ) // Thread represents a thread. diff --git a/pkg/proc/types.go b/pkg/proc/types.go index 1940b26a5..1507ca298 100644 --- a/pkg/proc/types.go +++ b/pkg/proc/types.go @@ -7,8 +7,8 @@ import ( "go/constant" "reflect" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/reader" ) // The kind field in runtime._type is a reflect.Kind value plus diff --git a/pkg/proc/variable_test.go b/pkg/proc/variable_test.go index 747616c3b..da5d0260c 100644 --- a/pkg/proc/variable_test.go +++ b/pkg/proc/variable_test.go @@ -4,8 +4,8 @@ import ( "path/filepath" "testing" - "github.com/go-delve/delve/pkg/proc" - protest "github.com/go-delve/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/proc" + protest "github.com/undoio/delve/pkg/proc/test" ) func TestGoroutineCreationLocation(t *testing.T) { diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index a41dac86a..1c55449cb 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -16,10 +16,10 @@ import ( "time" "unsafe" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" ) const ( diff --git a/pkg/proc/variables_fuzz_test.go b/pkg/proc/variables_fuzz_test.go index 07e28d373..0d66b969f 100644 --- a/pkg/proc/variables_fuzz_test.go +++ b/pkg/proc/variables_fuzz_test.go @@ -10,11 +10,11 @@ import ( "strings" "testing" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/core" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/core" - protest "github.com/go-delve/delve/pkg/proc/test" + protest "github.com/undoio/delve/pkg/proc/test" ) var fuzzEvalExpressionSetup = flag.Bool("fuzzevalexpressionsetup", false, "Performs setup for FuzzEvalExpression") diff --git a/pkg/proc/variables_test.go b/pkg/proc/variables_test.go index 5782cefd3..57f5e46c4 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -11,11 +11,11 @@ import ( "strings" "testing" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/service/api" - protest "github.com/go-delve/delve/pkg/proc/test" + protest "github.com/undoio/delve/pkg/proc/test" ) var pnormalLoadConfig = proc.LoadConfig{ @@ -1033,18 +1033,18 @@ func TestPackageRenames(t *testing.T) { {"req", true, `interface {}(*net/http.Request) *{Method: "amethod", …`, "", "interface {}", nil}, // Package name that doesn't match import path - {"iface3", true, `interface {}(*github.com/go-delve/delve/_fixtures/internal/dir0/renamedpackage.SomeType) *{A: true}`, "", "interface {}", nil}, + {"iface3", true, `interface {}(*github.com/undoio/delve/_fixtures/internal/dir0/renamedpackage.SomeType) *{A: true}`, "", "interface {}", nil}, // Interfaces to anonymous types - {"dir0someType", true, "interface {}(*github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType) *{X: 3}", "", "interface {}", nil}, - {"dir1someType", true, "interface {}(github.com/go-delve/delve/_fixtures/internal/dir1/pkg.SomeType) {X: 1, Y: 2}", "", "interface {}", nil}, - {"amap3", true, "interface {}(map[github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType]github.com/go-delve/delve/_fixtures/internal/dir1/pkg.SomeType) [{X: 4}: {X: 5, Y: 6}, ]", "", "interface {}", nil}, - {"anarray", true, `interface {}([2]github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType) [{X: 1},{X: 2}]`, "", "interface {}", nil}, - {"achan", true, `interface {}(chan github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType) chan github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType 0/0`, "", "interface {}", nil}, - {"aslice", true, `interface {}([]github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType) [{X: 3},{X: 4}]`, "", "interface {}", nil}, - {"afunc", true, `interface {}(func(github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType, github.com/go-delve/delve/_fixtures/internal/dir1/pkg.SomeType)) main.main.func1`, "", "interface {}", nil}, - {"astruct", true, `interface {}(*struct { A github.com/go-delve/delve/_fixtures/internal/dir1/pkg.SomeType; B github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType }) *{A: github.com/go-delve/delve/_fixtures/internal/dir1/pkg.SomeType {X: 1, Y: 2}, B: github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType {X: 3}}`, "", "interface {}", nil}, - {"iface2iface", true, `interface {}(*interface { AMethod(int) int; AnotherMethod(int) int }) **github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType {X: 4}`, "", "interface {}", nil}, + {"dir0someType", true, "interface {}(*github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType) *{X: 3}", "", "interface {}", nil}, + {"dir1someType", true, "interface {}(github.com/undoio/delve/_fixtures/internal/dir1/pkg.SomeType) {X: 1, Y: 2}", "", "interface {}", nil}, + {"amap3", true, "interface {}(map[github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType]github.com/undoio/delve/_fixtures/internal/dir1/pkg.SomeType) [{X: 4}: {X: 5, Y: 6}, ]", "", "interface {}", nil}, + {"anarray", true, `interface {}([2]github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType) [{X: 1},{X: 2}]`, "", "interface {}", nil}, + {"achan", true, `interface {}(chan github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType) chan github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType 0/0`, "", "interface {}", nil}, + {"aslice", true, `interface {}([]github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType) [{X: 3},{X: 4}]`, "", "interface {}", nil}, + {"afunc", true, `interface {}(func(github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType, github.com/undoio/delve/_fixtures/internal/dir1/pkg.SomeType)) main.main.func1`, "", "interface {}", nil}, + {"astruct", true, `interface {}(*struct { A github.com/undoio/delve/_fixtures/internal/dir1/pkg.SomeType; B github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType }) *{A: github.com/undoio/delve/_fixtures/internal/dir1/pkg.SomeType {X: 1, Y: 2}, B: github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType {X: 3}}`, "", "interface {}", nil}, + {"iface2iface", true, `interface {}(*interface { AMethod(int) int; AnotherMethod(int) int }) **github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType {X: 4}`, "", "interface {}", nil}, {`"dir0/pkg".A`, false, "0", "", "int", nil}, {`"dir1/pkg".A`, false, "1", "", "int", nil}, @@ -1061,7 +1061,7 @@ func TestPackageRenames(t *testing.T) { } testcases1_9 := []varTest{ - {"astruct2", true, `interface {}(*struct { github.com/go-delve/delve/_fixtures/internal/dir1/pkg.SomeType; X int }) *{SomeType: github.com/go-delve/delve/_fixtures/internal/dir1/pkg.SomeType {X: 1, Y: 2}, X: 10}`, "", "interface {}", nil}, + {"astruct2", true, `interface {}(*struct { github.com/undoio/delve/_fixtures/internal/dir1/pkg.SomeType; X int }) *{SomeType: github.com/undoio/delve/_fixtures/internal/dir1/pkg.SomeType {X: 1, Y: 2}, X: 10}`, "", "interface {}", nil}, } testcases1_13 := []varTest{ @@ -1468,9 +1468,9 @@ func TestPluginVariables(t *testing.T) { setFileBreakpoint(p, t, fixture.Source, 41) assertNoError(grp.Continue(), t, "Continue 1") - bp := setFunctionBreakpoint(p, t, "github.com/go-delve/delve/_fixtures/plugin2.TypesTest") + bp := setFunctionBreakpoint(p, t, "github.com/undoio/delve/_fixtures/plugin2.TypesTest") t.Logf("bp.Addr = %#x", bp.Addr) - setFunctionBreakpoint(p, t, "github.com/go-delve/delve/_fixtures/plugin2.aIsNotNil") + setFunctionBreakpoint(p, t, "github.com/undoio/delve/_fixtures/plugin2.aIsNotNil") for _, image := range p.BinInfo().Images { t.Logf("%#x %s\n", image.StaticBase, image.Path) @@ -1486,7 +1486,7 @@ func TestPluginVariables(t *testing.T) { var plugin2AFound, mainExeGlobalFound bool for _, v := range allvars { switch v.Name { - case "github.com/go-delve/delve/_fixtures/plugin2.A": + case "github.com/undoio/delve/_fixtures/plugin2.A": plugin2AFound = true case "main.ExeGlobal": mainExeGlobalFound = true @@ -1502,12 +1502,12 @@ func TestPluginVariables(t *testing.T) { // read interface variable, inside plugin code, with a concrete type defined in the executable vs, err := evalVariableWithCfg(p, "s", pnormalLoadConfig) assertNoError(err, t, "Eval(s)") - assertVariable(t, vs, varTest{"s", true, `github.com/go-delve/delve/_fixtures/internal/pluginsupport.Something(*main.asomething) *{n: 2}`, ``, `github.com/go-delve/delve/_fixtures/internal/pluginsupport.Something`, nil}) + assertVariable(t, vs, varTest{"s", true, `github.com/undoio/delve/_fixtures/internal/pluginsupport.Something(*main.asomething) *{n: 2}`, ``, `github.com/undoio/delve/_fixtures/internal/pluginsupport.Something`, nil}) // test that the concrete type -> interface{} conversion works across plugins (mostly tests proc.dwarfToRuntimeType) assertNoError(setVariable(p, "plugin2.A", "main.ExeGlobal"), t, "setVariable(plugin2.A = main.ExeGlobal)") assertNoError(grp.Continue(), t, "Continue 3") - assertCurrentLocationFunction(p, t, "github.com/go-delve/delve/_fixtures/plugin2.aIsNotNil") + assertCurrentLocationFunction(p, t, "github.com/undoio/delve/_fixtures/plugin2.aIsNotNil") vstr, err := evalVariableWithCfg(p, "str", pnormalLoadConfig) assertNoError(err, t, "Eval(str)") assertVariable(t, vstr, varTest{"str", true, `"success"`, ``, `string`, nil}) @@ -1519,7 +1519,7 @@ func TestPluginVariables(t *testing.T) { // read interface variable, inside executable code, with a concrete type defined in a plugin vb, err := evalVariableWithCfg(p, "b", pnormalLoadConfig) assertNoError(err, t, "Eval(b)") - assertVariable(t, vb, varTest{"b", true, `github.com/go-delve/delve/_fixtures/internal/pluginsupport.SomethingElse(*github.com/go-delve/delve/_fixtures/plugin2.asomethingelse) *{x: 1, y: 4}`, ``, `github.com/go-delve/delve/_fixtures/internal/pluginsupport.SomethingElse`, nil}) + assertVariable(t, vb, varTest{"b", true, `github.com/undoio/delve/_fixtures/internal/pluginsupport.SomethingElse(*github.com/undoio/delve/_fixtures/plugin2.asomethingelse) *{x: 1, y: 4}`, ``, `github.com/undoio/delve/_fixtures/internal/pluginsupport.SomethingElse`, nil}) }) } diff --git a/pkg/proc/winutil/regs_amd64_arch.go b/pkg/proc/winutil/regs_amd64_arch.go index 4bd193055..1374d4c8a 100644 --- a/pkg/proc/winutil/regs_amd64_arch.go +++ b/pkg/proc/winutil/regs_amd64_arch.go @@ -6,9 +6,9 @@ import ( "fmt" "unsafe" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/proc" ) // AMD64Registers represents CPU registers on an AMD64 processor. diff --git a/pkg/proc/winutil/regs_arm64_arch.go b/pkg/proc/winutil/regs_arm64_arch.go index 4c0b044c8..adabd4c4d 100644 --- a/pkg/proc/winutil/regs_arm64_arch.go +++ b/pkg/proc/winutil/regs_arm64_arch.go @@ -6,9 +6,9 @@ import ( "fmt" "unsafe" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/proc" ) const ( diff --git a/pkg/proc/x86_disasm.go b/pkg/proc/x86_disasm.go index 96e207019..66181a217 100644 --- a/pkg/proc/x86_disasm.go +++ b/pkg/proc/x86_disasm.go @@ -1,7 +1,7 @@ package proc import ( - "github.com/go-delve/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/op" "golang.org/x/arch/x86/x86asm" ) diff --git a/pkg/terminal/colorize/colorize_test.go b/pkg/terminal/colorize/colorize_test.go index 9ff9e89cc..5a15e5e5b 100644 --- a/pkg/terminal/colorize/colorize_test.go +++ b/pkg/terminal/colorize/colorize_test.go @@ -8,8 +8,8 @@ import ( "path/filepath" "testing" - "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/pkg/terminal/colorize" + "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/pkg/terminal/colorize" ) const terminalHighlightEscapeCode string = "\033[%2dm" diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go index 5d92d9f9f..777368078 100644 --- a/pkg/terminal/command.go +++ b/pkg/terminal/command.go @@ -25,12 +25,12 @@ import ( "text/tabwriter" "github.com/cosiner/argv" - "github.com/go-delve/delve/pkg/config" - "github.com/go-delve/delve/pkg/locspec" - "github.com/go-delve/delve/pkg/proc/debuginfod" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/rpc2" + "github.com/undoio/delve/pkg/config" + "github.com/undoio/delve/pkg/locspec" + "github.com/undoio/delve/pkg/proc/debuginfod" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/rpc2" ) const optimizedFunctionWarning = "Warning: debugging optimized function" diff --git a/pkg/terminal/command_test.go b/pkg/terminal/command_test.go index fb4add22f..784789e0a 100644 --- a/pkg/terminal/command_test.go +++ b/pkg/terminal/command_test.go @@ -17,15 +17,15 @@ import ( "testing" "time" - "github.com/go-delve/delve/pkg/config" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/debugger" - "github.com/go-delve/delve/service/rpc2" - "github.com/go-delve/delve/service/rpccommon" + "github.com/undoio/delve/pkg/config" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/debugger" + "github.com/undoio/delve/service/rpc2" + "github.com/undoio/delve/service/rpccommon" ) var testBackend, buildMode string diff --git a/pkg/terminal/config.go b/pkg/terminal/config.go index 3584f9b0c..c4a39a2e0 100644 --- a/pkg/terminal/config.go +++ b/pkg/terminal/config.go @@ -6,7 +6,7 @@ import ( "reflect" "text/tabwriter" - "github.com/go-delve/delve/pkg/config" + "github.com/undoio/delve/pkg/config" ) func configureCmd(t *Term, ctx callContext, args string) error { diff --git a/pkg/terminal/disasmprint.go b/pkg/terminal/disasmprint.go index 1bd532296..235310239 100644 --- a/pkg/terminal/disasmprint.go +++ b/pkg/terminal/disasmprint.go @@ -7,7 +7,7 @@ import ( "path/filepath" "text/tabwriter" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service/api" ) func disasmPrint(dv api.AsmInstructions, out io.Writer, showHeader bool) { diff --git a/pkg/terminal/docgen.go b/pkg/terminal/docgen.go index a3a22fc0a..334394a19 100644 --- a/pkg/terminal/docgen.go +++ b/pkg/terminal/docgen.go @@ -29,7 +29,7 @@ func replaceDocPath(s string) string { } text := s[start:end] - s = s[:start] + fmt.Sprintf("[%s](//github.com/go-delve/delve/tree/master/%s)", text, text) + s[end:] + s = s[:start] + fmt.Sprintf("[%s](//github.com/undoio/delve/tree/master/%s)", text, text) + s[end:] i0 = end + 1 } } diff --git a/pkg/terminal/out.go b/pkg/terminal/out.go index 79dd73f9a..0cc4bbb8c 100644 --- a/pkg/terminal/out.go +++ b/pkg/terminal/out.go @@ -7,8 +7,8 @@ import ( "os/exec" "strings" - "github.com/go-delve/delve/pkg/terminal/colorize" "github.com/mattn/go-isatty" + "github.com/undoio/delve/pkg/terminal/colorize" ) // transcriptWriter writes to a pagingWriter and also, optionally, to a diff --git a/pkg/terminal/starbind/conv.go b/pkg/terminal/starbind/conv.go index 595409a95..53c922ada 100644 --- a/pkg/terminal/starbind/conv.go +++ b/pkg/terminal/starbind/conv.go @@ -9,7 +9,7 @@ import ( "go.starlark.net/starlark" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service/api" ) // autoLoadConfig is the load configuration used to automatically load more from a variable diff --git a/pkg/terminal/starbind/starlark.go b/pkg/terminal/starbind/starlark.go index de37879e4..481b27079 100644 --- a/pkg/terminal/starbind/starlark.go +++ b/pkg/terminal/starbind/starlark.go @@ -12,8 +12,8 @@ import ( "go.starlark.net/resolve" "go.starlark.net/starlark" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" ) //go:generate go run ../../../_scripts/gen-starlark-bindings.go go ./starlark_mapping.go diff --git a/pkg/terminal/starbind/starlark_mapping.go b/pkg/terminal/starbind/starlark_mapping.go index ae892b348..fd6a8a526 100644 --- a/pkg/terminal/starbind/starlark_mapping.go +++ b/pkg/terminal/starbind/starlark_mapping.go @@ -4,8 +4,8 @@ package starbind import ( "fmt" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/rpc2" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/rpc2" "go.starlark.net/starlark" ) diff --git a/pkg/terminal/starlark.go b/pkg/terminal/starlark.go index 9134a2760..5837c6e96 100644 --- a/pkg/terminal/starlark.go +++ b/pkg/terminal/starlark.go @@ -1,9 +1,9 @@ package terminal import ( - "github.com/go-delve/delve/pkg/terminal/starbind" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/terminal/starbind" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" ) type starlarkContext struct { diff --git a/pkg/terminal/terminal.go b/pkg/terminal/terminal.go index 4b62625ed..d51c32844 100644 --- a/pkg/terminal/terminal.go +++ b/pkg/terminal/terminal.go @@ -15,12 +15,12 @@ import ( "github.com/derekparker/trie" "github.com/go-delve/liner" - "github.com/go-delve/delve/pkg/config" - "github.com/go-delve/delve/pkg/locspec" - "github.com/go-delve/delve/pkg/terminal/colorize" - "github.com/go-delve/delve/pkg/terminal/starbind" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/config" + "github.com/undoio/delve/pkg/locspec" + "github.com/undoio/delve/pkg/terminal/colorize" + "github.com/undoio/delve/pkg/terminal/starbind" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" ) const ( diff --git a/pkg/terminal/terminal_test.go b/pkg/terminal/terminal_test.go index fee23b7cf..279ede674 100644 --- a/pkg/terminal/terminal_test.go +++ b/pkg/terminal/terminal_test.go @@ -6,7 +6,7 @@ import ( "runtime" "testing" - "github.com/go-delve/delve/pkg/config" + "github.com/undoio/delve/pkg/config" ) type tRule struct { diff --git a/service/api/conversions.go b/service/api/conversions.go index 9c66fac47..e1fc09fb4 100644 --- a/service/api/conversions.go +++ b/service/api/conversions.go @@ -11,9 +11,9 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" ) // ConvertLogicalBreakpoint converts a proc.LogicalBreakpoint into an API breakpoint. diff --git a/service/api/types.go b/service/api/types.go index 2e980ef91..96a4824d7 100644 --- a/service/api/types.go +++ b/service/api/types.go @@ -8,7 +8,7 @@ import ( "strconv" "unicode" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) // ErrNotExecutable is an error returned when trying diff --git a/service/client.go b/service/client.go index 4e066511b..89cb2eb4d 100644 --- a/service/client.go +++ b/service/client.go @@ -3,7 +3,7 @@ package service import ( "time" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service/api" ) // Client represents a debugger service client. All client methods are diff --git a/service/config.go b/service/config.go index ce99487ad..5426a902f 100644 --- a/service/config.go +++ b/service/config.go @@ -3,7 +3,7 @@ package service import ( "net" - "github.com/go-delve/delve/service/debugger" + "github.com/undoio/delve/service/debugger" ) // Config provides the configuration to start a Debugger and expose it with a diff --git a/service/dap/command.go b/service/dap/command.go index ab318e095..d4cdc565b 100644 --- a/service/dap/command.go +++ b/service/dap/command.go @@ -7,8 +7,8 @@ import ( "sort" "strings" - "github.com/go-delve/delve/pkg/config" "github.com/google/go-dap" + "github.com/undoio/delve/pkg/config" ) func (s *Session) delveCmd(goid, frame int, cmdstr string) (string, error) { diff --git a/service/dap/config.go b/service/dap/config.go index 3a13c12d1..edccf31d9 100644 --- a/service/dap/config.go +++ b/service/dap/config.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - "github.com/go-delve/delve/pkg/config" + "github.com/undoio/delve/pkg/config" ) func listConfig(args *launchAttachArgs) string { diff --git a/service/dap/handles.go b/service/dap/handles.go index 8c1f94970..dc9678a0e 100644 --- a/service/dap/handles.go +++ b/service/dap/handles.go @@ -1,6 +1,6 @@ package dap -import "github.com/go-delve/delve/pkg/proc" +import "github.com/undoio/delve/pkg/proc" const startHandle = 1000 @@ -19,7 +19,7 @@ type fullyQualifiedVariable struct { // A way to load this variable by either using all names in the hierarchic // sequence above this variable (most readable when referenced by the UI) // if available or a special expression based on: - // https://github.com/go-delve/delve/blob/master/Documentation/api/ClientHowto.md#loading-more-of-a-variable + // https://github.com/undoio/delve/blob/master/Documentation/api/ClientHowto.md#loading-more-of-a-variable // Empty if the variable cannot or should not be reloaded. fullyQualifiedNameOrExpr string // True if this represents variable scope diff --git a/service/dap/server.go b/service/dap/server.go index e505bab7a..6ba535c5d 100644 --- a/service/dap/server.go +++ b/service/dap/server.go @@ -32,17 +32,17 @@ import ( "sync" "time" - "github.com/go-delve/delve/pkg/gobuild" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/locspec" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/debugger" - "github.com/go-delve/delve/service/internal/sameuser" + "github.com/undoio/delve/pkg/gobuild" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/locspec" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + "github.com/google/go-dap" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/debugger" + "github.com/undoio/delve/service/internal/sameuser" ) // Server implements a DAP server that can accept a single client for @@ -2468,7 +2468,7 @@ func (s *Session) convertVariableWithOpts(v *proc.Variable, qualifiedNameOrExpr var reloadVariable = func(v *proc.Variable, qualifiedNameOrExpr string) (value string) { // We might be loading variables from the frame that's not topmost, so use // frame-independent address-based expression, not fully-qualified name as per - // https://github.com/go-delve/delve/blob/master/Documentation/api/ClientHowto.md#looking-into-variables. + // https://github.com/undoio/delve/blob/master/Documentation/api/ClientHowto.md#looking-into-variables. // TODO(polina): Get *proc.Variable object from debugger instead. Export a function to set v.loaded to false // and call v.loadValue gain with a different load config. It's more efficient, and it's guaranteed to keep // working with generics. diff --git a/service/dap/server_test.go b/service/dap/server_test.go index 8b775487c..d0510cf47 100644 --- a/service/dap/server_test.go +++ b/service/dap/server_test.go @@ -20,15 +20,15 @@ import ( "testing" "time" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - protest "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/dap/daptest" - "github.com/go-delve/delve/service/debugger" "github.com/google/go-dap" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/dap/daptest" + "github.com/undoio/delve/service/debugger" ) const stopOnEntry bool = true @@ -2440,19 +2440,19 @@ func TestGlobalScopeAndVariables(t *testing.T) { client.ScopesRequest(1000) scopes = client.ExpectScopesResponse(t) checkScope(t, scopes, 0, "Locals", localsScope) - checkScope(t, scopes, 1, "Globals (package github.com/go-delve/delve/_fixtures/internal/dir0/pkg)", globalsScope) + checkScope(t, scopes, 1, "Globals (package github.com/undoio/delve/_fixtures/internal/dir0/pkg)", globalsScope) client.VariablesRequest(globalsScope) globals := client.ExpectVariablesResponse(t) checkChildren(t, globals, "Globals", 1) - ref := checkVarExact(t, globals, 0, "SomeVar", "github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeVar", "github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType {X: 0}", "github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType", hasChildren) + ref := checkVarExact(t, globals, 0, "SomeVar", "github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeVar", "github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType {X: 0}", "github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeType", hasChildren) if ref > 0 { client.VariablesRequest(ref) somevar := client.ExpectVariablesResponse(t) checkChildren(t, somevar, "SomeVar", 1) // TODO(polina): unlike main.p, this prefix won't work - checkVarExact(t, somevar, 0, "X", "github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeVar.X", "0", "float64", noChildren) + checkVarExact(t, somevar, 0, "X", "github.com/undoio/delve/_fixtures/internal/dir0/pkg.SomeVar.X", "0", "float64", noChildren) } }, disconnect: false, @@ -5545,7 +5545,7 @@ func TestLaunchTestRequest(t *testing.T) { testFile, []int{14}, []onBreakpoint{{ execute: func() { - checkStop(t, client, -1, "github.com/go-delve/delve/_fixtures/buildtest.TestCurrentDirectory", 14) + checkStop(t, client, -1, "github.com/undoio/delve/_fixtures/buildtest.TestCurrentDirectory", 14) client.VariablesRequest(1001) // Locals locals := client.ExpectVariablesResponse(t) checkChildren(t, locals, "Locals", 1) diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index c58eeb2b9..8c6a2bc24 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -21,16 +21,16 @@ import ( "sync" "time" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/gobuild" - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/locspec" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/pkg/proc/core" - "github.com/go-delve/delve/pkg/proc/gdbserial" - "github.com/go-delve/delve/pkg/proc/native" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/gobuild" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/locspec" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/core" + "github.com/undoio/delve/pkg/proc/gdbserial" + "github.com/undoio/delve/pkg/proc/native" + "github.com/undoio/delve/service/api" ) var ( diff --git a/service/debugger/debugger_test.go b/service/debugger/debugger_test.go index b8b05ece5..687c0ed1c 100644 --- a/service/debugger/debugger_test.go +++ b/service/debugger/debugger_test.go @@ -8,9 +8,9 @@ import ( "strings" "testing" - "github.com/go-delve/delve/pkg/gobuild" - protest "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/gobuild" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service/api" ) func TestDebugger_LaunchNoMain(t *testing.T) { diff --git a/service/debugger/debugger_unix_test.go b/service/debugger/debugger_unix_test.go index bb90dbd04..7372a9879 100644 --- a/service/debugger/debugger_unix_test.go +++ b/service/debugger/debugger_unix_test.go @@ -14,9 +14,9 @@ import ( "testing" "github.com/creack/pty" - "github.com/go-delve/delve/pkg/gobuild" - protest "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/gobuild" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service/api" ) func TestDebugger_LaunchNoExecutablePerm(t *testing.T) { diff --git a/service/internal/sameuser/sameuser_linux.go b/service/internal/sameuser/sameuser_linux.go index 4aeeb5e44..eb7dcd572 100644 --- a/service/internal/sameuser/sameuser_linux.go +++ b/service/internal/sameuser/sameuser_linux.go @@ -13,7 +13,7 @@ import ( "os" "strings" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/logflags" ) // for testing diff --git a/service/rpc1/client.go b/service/rpc1/client.go index 06dfec60b..5a484e1c5 100644 --- a/service/rpc1/client.go +++ b/service/rpc1/client.go @@ -9,7 +9,7 @@ import ( "sync" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service/api" ) // RPCClient is a RPC service.Client. diff --git a/service/rpc1/server.go b/service/rpc1/server.go index fc6dd7824..69e71d788 100644 --- a/service/rpc1/server.go +++ b/service/rpc1/server.go @@ -4,10 +4,10 @@ import ( "errors" "fmt" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/debugger" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/debugger" ) var defaultLoadConfig = proc.LoadConfig{ diff --git a/service/rpc2/client.go b/service/rpc2/client.go index 56438ff01..2763e5105 100644 --- a/service/rpc2/client.go +++ b/service/rpc2/client.go @@ -8,8 +8,8 @@ import ( "net/rpc/jsonrpc" "time" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" ) // RPCClient is a RPC service.Client. @@ -242,7 +242,7 @@ func (c *RPCClient) GetBreakpointByName(name string) (*api.Breakpoint, error) { // CreateBreakpoint will send a request to the RPC server to create a breakpoint. // Please refer to the documentation for `Debugger.CreateBreakpoint` for a description of how // the requested breakpoint parameters are interpreted and used: -// https://pkg.go.dev/github.com/go-delve/delve/service/debugger#Debugger.CreateBreakpoint +// https://pkg.go.dev/github.com/undoio/delve/service/debugger#Debugger.CreateBreakpoint func (c *RPCClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoint, error) { var out CreateBreakpointOut err := c.call("CreateBreakpoint", CreateBreakpointIn{*breakPoint, "", nil, false}, &out) diff --git a/service/rpc2/server.go b/service/rpc2/server.go index 4f0760719..6fdc56892 100644 --- a/service/rpc2/server.go +++ b/service/rpc2/server.go @@ -6,11 +6,11 @@ import ( "sort" "time" - "github.com/go-delve/delve/pkg/dwarf/op" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/debugger" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/debugger" ) type RPCServer struct { @@ -255,7 +255,7 @@ type CreateBreakpointOut struct { // CreateBreakpoint creates a new breakpoint. The client is expected to populate `CreateBreakpointIn` // with an `api.Breakpoint` struct describing where to set the breakpoing. For more information on // how to properly request a breakpoint via the `api.Breakpoint` struct see the documentation for -// `debugger.CreateBreakpoint` here: https://pkg.go.dev/github.com/go-delve/delve/service/debugger#Debugger.CreateBreakpoint. +// `debugger.CreateBreakpoint` here: https://pkg.go.dev/github.com/undoio/delve/service/debugger#Debugger.CreateBreakpoint. func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpointOut) error { if err := api.ValidBreakpointName(arg.Breakpoint.Name); err != nil { return err @@ -527,7 +527,7 @@ type EvalOut struct { // Eval returns a variable in the specified context. // -// See https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md +// See https://github.com/undoio/delve/blob/master/Documentation/cli/expr.md // for a description of acceptable values of arg.Expr. func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error { cfg := arg.Cfg diff --git a/service/rpccommon/server.go b/service/rpccommon/server.go index d7916cb5c..890df6856 100644 --- a/service/rpccommon/server.go +++ b/service/rpccommon/server.go @@ -16,15 +16,15 @@ import ( "unicode" "unicode/utf8" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/version" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/dap" - "github.com/go-delve/delve/service/debugger" - "github.com/go-delve/delve/service/internal/sameuser" - "github.com/go-delve/delve/service/rpc1" - "github.com/go-delve/delve/service/rpc2" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/version" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/dap" + "github.com/undoio/delve/service/debugger" + "github.com/undoio/delve/service/internal/sameuser" + "github.com/undoio/delve/service/rpc1" + "github.com/undoio/delve/service/rpc2" ) // ServerImpl implements a JSON-RPC server that can switch between two diff --git a/service/test/common_test.go b/service/test/common_test.go index ef6338e0f..8568f091e 100644 --- a/service/test/common_test.go +++ b/service/test/common_test.go @@ -8,9 +8,9 @@ import ( "strings" "testing" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/rpc1" - "github.com/go-delve/delve/service/rpc2" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/rpc1" + "github.com/undoio/delve/service/rpc2" ) func assertNoError(err error, t *testing.T, s string) { diff --git a/service/test/integration1_test.go b/service/test/integration1_test.go index 1f7b55d9a..1d66a5bb7 100644 --- a/service/test/integration1_test.go +++ b/service/test/integration1_test.go @@ -11,14 +11,14 @@ import ( "testing" "time" - protest "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/service/debugger" - - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/rpc1" - "github.com/go-delve/delve/service/rpccommon" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service/debugger" + + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/rpc1" + "github.com/undoio/delve/service/rpccommon" ) func withTestClient1(name string, t *testing.T, fn func(c *rpc1.RPCClient)) { diff --git a/service/test/integration2_test.go b/service/test/integration2_test.go index 0be6c279a..1ad39cc37 100644 --- a/service/test/integration2_test.go +++ b/service/test/integration2_test.go @@ -18,16 +18,16 @@ import ( "testing" "time" - protest "github.com/go-delve/delve/pkg/proc/test" - "github.com/go-delve/delve/service/debugger" - - "github.com/go-delve/delve/pkg/goversion" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" - "github.com/go-delve/delve/service/rpc2" - "github.com/go-delve/delve/service/rpccommon" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service/debugger" + + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" + "github.com/undoio/delve/service/rpc2" + "github.com/undoio/delve/service/rpccommon" ) var normalLoadConfig = api.LoadConfig{ @@ -1064,7 +1064,7 @@ func TestClientServer_FindLocations(t *testing.T) { if goversion.VersionAfterOrEqual(runtime.Version(), 1, 13) { withTestClient2("pkgrenames", t, func(c service.Client) { - someFuncLoc := findLocationHelper(t, c, "github.com/go-delve/delve/_fixtures/internal/dir%2eio.SomeFunction:0", false, 1, 0)[0] + someFuncLoc := findLocationHelper(t, c, "github.com/undoio/delve/_fixtures/internal/dir%2eio.SomeFunction:0", false, 1, 0)[0] findLocationHelper(t, c, "dirio.SomeFunction:0", false, 1, someFuncLoc) }) } @@ -2878,7 +2878,7 @@ func TestPluginSuspendedBreakpoint(t *testing.T) { assertNoError(err, t, "filepath.Abs") withTestClient2Extended("plugintest", t, protest.AllNonOptimized, [3]string{}, []string{pluginFixtures[0].Path, pluginFixtures[1].Path}, func(c service.Client, f protest.Fixture) { - _, err := c.CreateBreakpointWithExpr(&api.Breakpoint{FunctionName: "github.com/go-delve/delve/_fixtures/plugin1.Fn1", Line: 1}, "", nil, true) + _, err := c.CreateBreakpointWithExpr(&api.Breakpoint{FunctionName: "github.com/undoio/delve/_fixtures/plugin1.Fn1", Line: 1}, "", nil, true) assertNoError(err, t, "CreateBreakpointWithExpr(Fn1) (suspended)") _, err = c.CreateBreakpointWithExpr(&api.Breakpoint{File: filepath.Join(dir, "plugin2", "plugin2.go"), Line: 9}, "", nil, true) From 2f47dc64d8c4da362fbd98eb1ecb55e508d15d7c Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Mon, 29 Jul 2019 12:39:07 +0100 Subject: [PATCH 03/29] Remove build status information from README. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3807a8774..828537bf8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/go-delve/delve/master/LICENSE) [![GoDoc](https://godoc.org/github.com/undoio/delve?status.svg)](https://godoc.org/github.com/undoio/delve) -[![Build Status](https://delve.teamcity.com/app/rest/builds/buildType:(id:Delve_AggregatorBuild)/statusIcon.svg)](https://delve.teamcity.com/viewType.html?buildTypeId=Delve_AggregatorBuild&guest=1) The GitHub issue tracker is for **bugs** only. Please use the [developer mailing list](https://groups.google.com/forum/#!forum/delve-dev) for any feature proposals and discussions. From f6af7074281b61b25835496b71e4353ec3077d3e Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 13 Jan 2022 15:07:49 +0000 Subject: [PATCH 04/29] Improved method for reading the G pointer on x86. In Undo, debuggee state is immutable during replay, so reading the G pointer via code injection won't work; and in any case, this approach is simpler. --- pkg/proc/gdbserial/gdbserver.go | 241 ++++++-------------------------- 1 file changed, 45 insertions(+), 196 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 92fb06e4a..09b204739 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -62,7 +62,6 @@ package gdbserial import ( - "bytes" "debug/macho" "encoding/binary" "errors" @@ -159,8 +158,6 @@ type gdbProcess struct { threadStopInfo bool // true if the stub supports qThreadStopInfo tracedir string // if attached to rr the path to the trace directory - loadGInstrAddr uint64 // address of the g loading instruction, zero if we couldn't allocate it - breakpointKind int // breakpoint kind to pass to 'z' and 'Z' when creating software breakpoints process *os.Process @@ -350,24 +347,6 @@ func (p *gdbProcess) Connect(conn net.Conn, path string, pid int, debugInfoDirs return nil, err } - if p.bi.Arch.Name != "arm64" { - // None of the stubs we support returns the value of fs_base or gs_base - // along with the registers, therefore we have to resort to executing a MOV - // instruction on the inferior to find out where the G struct of a given - // thread is located. - // Here we try to allocate some memory on the inferior which we will use to - // store the MOV instruction. - // If the stub doesn't support memory allocation reloadRegisters will - // overwrite some existing memory to store the MOV. - if ginstr, err := p.loadGInstr(); err == nil { - if addr, err := p.conn.allocMemory(256); err == nil { - if _, err := p.conn.writeMemory(addr, ginstr); err == nil { - p.loadGInstrAddr = addr - } - } - } - } - return tgt, nil } @@ -1570,31 +1549,6 @@ func (t *gdbThread) Blocked() bool { } } -// loadGInstr returns the correct MOV instruction for the current -// OS/architecture that can be executed to load the address of G from an -// inferior's thread. -func (p *gdbProcess) loadGInstr() ([]byte, error) { - var op []byte - switch p.bi.GOOS { - case "windows", "darwin", "freebsd": - // mov rcx, QWORD PTR gs:{uint32(off)} - op = []byte{0x65, 0x48, 0x8b, 0x0c, 0x25} - case "linux": - // mov rcx,QWORD PTR fs:{uint32(off)} - op = []byte{0x64, 0x48, 0x8B, 0x0C, 0x25} - default: - panic("unsupported operating system attempting to find Goroutine on Thread") - } - offset, err := p.bi.GStructOffset(p.Memory()) - if err != nil { - return nil, err - } - buf := &bytes.Buffer{} - buf.Write(op) - binary.Write(buf, binary.LittleEndian, uint32(offset)) - return buf.Bytes(), nil -} - func (p *gdbProcess) MemoryMap() ([]proc.MemoryMapEntry, error) { r := []proc.MemoryMapEntry{} addr := uint64(0) @@ -1675,15 +1629,6 @@ func (t *gdbThread) reloadRegisters() error { } } - if t.p.bi.GOOS == "linux" { - if reg, hasFsBase := t.regs.regs[t.p.regnames.FsBase]; hasFsBase { - t.regs.gaddr = 0 - t.regs.tls = binary.LittleEndian.Uint64(reg.value) - t.regs.hasgaddr = false - return nil - } - } - if t.p.bi.Arch.Name == "arm64" { // no need to play around with the GInstr on ARM64 because // the G addr is stored in a register @@ -1692,10 +1637,7 @@ func (t *gdbThread) reloadRegisters() error { t.regs.hasgaddr = true t.regs.tls = 0 } else { - if t.p.loadGInstrAddr > 0 { - return t.reloadGAlloc() - } - return t.reloadGAtPC() + return t.readG() } return nil @@ -1747,143 +1689,6 @@ func (t *gdbThread) readSomeRegisters(regNames ...string) error { return nil } -// reloadGAtPC overwrites the instruction that the thread is stopped at with -// the MOV instruction used to load current G, executes this single -// instruction and then puts everything back the way it was. -func (t *gdbThread) reloadGAtPC() error { - movinstr, err := t.p.loadGInstr() - if err != nil { - return err - } - - if t.Blocked() { - t.regs.tls = 0 - t.regs.gaddr = 0 - t.regs.hasgaddr = true - return nil - } - - cx := t.regs.CX() - pc := t.regs.PC() - - // We are partially replicating the code of GdbserverThread.stepInstruction - // here. - // The reason is that lldb-server has a bug with writing to memory and - // setting/clearing breakpoints to that same memory which we must work - // around by clearing and re-setting the breakpoint in a specific sequence - // with the memory writes. - // Additionally all breakpoints in [pc, pc+len(movinstr)] need to be removed - for addr, bp := range t.p.breakpoints.M { - if bp.WatchType != 0 { - continue - } - if addr >= pc && addr <= pc+uint64(len(movinstr)) { - err := t.p.conn.clearBreakpoint(addr, swBreakpoint, t.p.breakpointKind) - if err != nil { - return err - } - defer t.p.conn.setBreakpoint(addr, swBreakpoint, t.p.breakpointKind) - } - } - - savedcode := make([]byte, len(movinstr)) - _, err = t.p.ReadMemory(savedcode, pc) - if err != nil { - return err - } - - _, err = t.p.WriteMemory(pc, movinstr) - if err != nil { - return err - } - - defer func() { - _, err0 := t.p.WriteMemory(pc, savedcode) - if err == nil { - err = err0 - } - t.regs.setPC(pc) - t.regs.setCX(cx) - err1 := t.writeSomeRegisters(t.p.regnames.PC, t.p.regnames.CX) - if err == nil { - err = err1 - } - }() - - err = t.p.conn.step(t, nil, true) - if err != nil { - if err == errThreadBlocked { - t.regs.tls = 0 - t.regs.gaddr = 0 - t.regs.hasgaddr = true - return nil - } - return err - } - - if err := t.readSomeRegisters(t.p.regnames.PC, t.p.regnames.CX); err != nil { - return err - } - - t.regs.gaddr = t.regs.CX() - t.regs.hasgaddr = true - - return err -} - -// reloadGAlloc makes the specified thread execute one instruction stored at -// t.p.loadGInstrAddr then restores the value of the thread's registers. -// t.p.loadGInstrAddr must point to valid memory on the inferior, containing -// a MOV instruction that loads the address of the current G in the RCX -// register. -func (t *gdbThread) reloadGAlloc() error { - if t.Blocked() { - t.regs.tls = 0 - t.regs.gaddr = 0 - t.regs.hasgaddr = true - return nil - } - - cx := t.regs.CX() - pc := t.regs.PC() - - t.regs.setPC(t.p.loadGInstrAddr) - if err := t.writeSomeRegisters(t.p.regnames.PC); err != nil { - return err - } - - var err error - - defer func() { - t.regs.setPC(pc) - t.regs.setCX(cx) - err1 := t.writeSomeRegisters(t.p.regnames.PC, t.p.regnames.CX) - if err == nil { - err = err1 - } - }() - - err = t.p.conn.step(t, nil, true) - if err != nil { - if err == errThreadBlocked { - t.regs.tls = 0 - t.regs.gaddr = 0 - t.regs.hasgaddr = true - return nil - } - return err - } - - if err := t.readSomeRegisters(t.p.regnames.CX); err != nil { - return err - } - - t.regs.gaddr = t.regs.CX() - t.regs.hasgaddr = true - - return err -} - func (t *gdbThread) clearBreakpointState() { t.setbp = false t.CurrentBreakpoint.Clear() @@ -2141,3 +1946,47 @@ func machTargetExcToError(sig uint8) error { } return nil } + +// readG reads the G pointer on x86 by peeking the word before the TLS pointer. +func (t *gdbThread) readG() error { + var regnum int + + switch t.p.bi.GOOS { + case "windows": + case "darwin": + regnum = 59 // gs_base + case "linux": + regnum = 58 // fs_base + default: + panic("unsupported operating system attempting to find Goroutine on Thread") + } + + wordSize := t.p.bi.Arch.PtrSize() + tls := make([]byte, wordSize) + err := t.p.conn.readRegister(t.strID, regnum, tls) + if err != nil { + return err + } + + data := make([]byte, wordSize) + tlsaddr := binary.LittleEndian.Uint64(tls) + if tlsaddr == 0 { + t.regs.tls = 0 + t.regs.gaddr = 0 + t.regs.hasgaddr = true + return nil + } + + len, err := t.p.ReadMemory(data, tlsaddr-uint64(wordSize)) + if err != nil { + return err + } + if len != wordSize { + return fmt.Errorf("too little data: only %d bytes", len) + } + + t.regs.tls = tlsaddr + t.regs.gaddr = binary.LittleEndian.Uint64(data) + t.regs.hasgaddr = true + return nil +} From 991b8170b13c67937914a7f9284c2511e7b0de27 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Tue, 28 May 2019 19:00:04 +0100 Subject: [PATCH 05/29] Support for Undo record/replay backend. * Update the documentation to mention UDB or LiveRecorder alongside rr. * Add makefile support for testing the Undo backend. * Add DLV_RECORD_REPLAY_BACKEND environment variable which overrides the record-replay backend, for use in GoLand. * Implement checkpoints as a map from checkpoint number to time. * Suppress resume call after restart. * Implement "when" command using "get_time" serial command. * Implement call injection using "set_debuggee_volatile". * Implement "restart" using "goto_time". * Enable or disable Undo backend appropriately in test cases. --- Documentation/usage/dlv.md | 2 +- Documentation/usage/dlv_replay.md | 12 +- _scripts/make.go | 8 + cmd/dlv/cmds/commands.go | 33 +++- cmd/dlv/main.go | 47 ++++++ pkg/proc/gdbserial/gdbserver.go | 87 +++++++++- pkg/proc/gdbserial/gdbserver_conn.go | 55 ++++++- pkg/proc/gdbserial/undo.go | 160 ++++++++++++++++++ pkg/proc/gdbserial/undo_test.go | 235 +++++++++++++++++++++++++++ pkg/proc/proc_test.go | 35 ++-- pkg/proc/proc_unix_test.go | 2 +- pkg/proc/variables_test.go | 6 +- pkg/terminal/command_test.go | 6 +- service/debugger/debugger.go | 14 +- service/test/integration1_test.go | 2 +- service/test/integration2_test.go | 17 +- 16 files changed, 664 insertions(+), 57 deletions(-) create mode 100644 pkg/proc/gdbserial/undo.go create mode 100644 pkg/proc/gdbserial/undo_test.go diff --git a/Documentation/usage/dlv.md b/Documentation/usage/dlv.md index 5e75d2a3e..8d32a0fbd 100644 --- a/Documentation/usage/dlv.md +++ b/Documentation/usage/dlv.md @@ -45,7 +45,7 @@ Pass flags to the program you are debugging using `--`, for example: * [dlv dap](dlv_dap.md) - Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP). * [dlv debug](dlv_debug.md) - Compile and begin debugging main package in current directory, or the package specified. * [dlv exec](dlv_exec.md) - Execute a precompiled binary, and begin a debug session. -* [dlv replay](dlv_replay.md) - Replays a rr trace. +* [dlv replay](dlv_replay.md) - Replays a rr trace or LiveRecorder recording. * [dlv run](dlv_run.md) - Deprecated command. Use 'debug' instead. * [dlv test](dlv_test.md) - Compile test binary and begin debugging program. * [dlv trace](dlv_trace.md) - Compile and begin tracing program. diff --git a/Documentation/usage/dlv_replay.md b/Documentation/usage/dlv_replay.md index 8cec2ef92..20f98ef4c 100644 --- a/Documentation/usage/dlv_replay.md +++ b/Documentation/usage/dlv_replay.md @@ -1,17 +1,19 @@ ## dlv replay -Replays a rr trace. +Replays a rr trace or a LiveRecorder recording. ### Synopsis -Replays a rr trace. +Replays a rr trace or a LiveRecorder recording. -The replay command will open a trace generated by mozilla rr. Mozilla rr must be installed: -https://github.com/mozilla/rr +The replay command will open a trace generated by Mozilla rr or a LiveRecorder +recording. Mozilla rr must be installed to open an rr trace: +https://github.com/mozilla/rr; and UDB must be installed to open a LiveRecorder +recording. ``` -dlv replay [trace directory] [flags] +dlv replay [trace directory or LiveRecorder recording] [flags] ``` ### Options diff --git a/_scripts/make.go b/_scripts/make.go index 21ca7f5ca..b259596b3 100644 --- a/_scripts/make.go +++ b/_scripts/make.go @@ -391,6 +391,10 @@ func testStandard() { fmt.Println("\nTesting RR backend") testCmdIntl("basic", "", "rr", "normal") } + if inpath("udb") { + fmt.Println("\nTesting Undo backend") + testCmdIntl("basic", "", "undo", "normal") + } if TestIncludePIE { dopie := false switch runtime.GOOS { @@ -421,6 +425,10 @@ func testStandard() { fmt.Println("\nTesting PIE buildmode, RR backend") testCmdIntl("basic", "", "rr", "pie") } + if runtime.GOOS == "linux" && inpath("udb") { + fmt.Println("\nTesting PIE buildmode, Undo backend") + testCmdIntl("basic", "", "undo", "pie") + } } func testCmdIntl(testSet, testRegex, testBackend, testBuildMode string) { diff --git a/cmd/dlv/cmds/commands.go b/cmd/dlv/cmds/commands.go index db2a735dd..20b2d2f3b 100644 --- a/cmd/dlv/cmds/commands.go +++ b/cmd/dlv/cmds/commands.go @@ -21,6 +21,7 @@ import ( "github.com/undoio/delve/pkg/gobuild" "github.com/undoio/delve/pkg/goversion" "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc/gdbserial" "github.com/undoio/delve/pkg/terminal" "github.com/undoio/delve/pkg/version" "github.com/undoio/delve/service" @@ -350,23 +351,39 @@ Currently supports linux/amd64 and linux/arm64 core files, windows/amd64 minidum versionCommand.Flags().BoolVarP(&versionVerbose, "verbose", "v", false, "print verbose version info") rootCommand.AddCommand(versionCommand) - if path, _ := exec.LookPath("rr"); path != "" || docCall { + // Check for existence of replay tools + path, _ := exec.LookPath("rr") + rrAvailable := path != "" + undoAvailable := gdbserial.UndoIsAvailable() == nil + + if docCall { + // Display replay documentation regardless of availability + rrAvailable = true + undoAvailable = true + } + + if rrAvailable || undoAvailable { replayCommand := &cobra.Command{ - Use: "replay [trace directory]", - Short: "Replays a rr trace.", - Long: `Replays a rr trace. + Use: "replay [trace directory or LiveRecorder recording]", + Short: "Replays a rr trace or LiveRecorder recording.", + Long: `Replays a rr trace or LiveRecorder recording. + +The replay command will open a trace generated by Mozilla rr or a LiveRecorder recording. +Either Mozilla rr (https://github.com/mozilla/rr) or UDB (https://undo.io) must be installed. -The replay command will open a trace generated by mozilla rr. Mozilla rr must be installed: -https://github.com/mozilla/rr `, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { - return errors.New("you must provide a path to a binary") + return errors.New("you must provide a path to a recording") } return nil }, Run: func(cmd *cobra.Command, args []string) { - backend = "rr" + if isUndo, _ := gdbserial.UndoIsRecording(args[0]); isUndo { + backend = "undo" + } else { + backend = "rr" + } os.Exit(execute(0, []string{}, conf, args[0], debugger.ExecutingOther, args, buildFlags)) }, } diff --git a/cmd/dlv/main.go b/cmd/dlv/main.go index e1643c16e..7cd0ee3a8 100644 --- a/cmd/dlv/main.go +++ b/cmd/dlv/main.go @@ -1,7 +1,9 @@ package main import ( + "fmt" "os" + "strings" "github.com/sirupsen/logrus" "github.com/undoio/delve/cmd/dlv/cmds" @@ -21,5 +23,50 @@ func main() { } else { logrus.WithFields(logrus.Fields{"layer": "dlv"}).Warnln("CGO_CFLAGS already set, Cgo code could be optimized.") } + + // XXX: There is currently no way to enforce the record/replay backend + // from within GoLand. Until this is resolved, introduce an environment + // variable to override the backend. + newArgs := make([]string, len(os.Args)) + dlvBackend := os.Getenv("DLV_RECORD_REPLAY_BACKEND") + if dlvBackend != "" { + if dlvBackend != "rr" && dlvBackend != "undo" { + fmt.Fprintf(os.Stderr, "Unknown dlv record/replay backend: %s\n", + dlvBackend) + os.Exit(1) + } + + replaceOptArg := false + for i, arg := range os.Args { + if replaceOptArg { + if strings.Compare(arg, "rr") == 0 || + strings.Compare(arg, "undo") == 0 { + newArgs[i] = dlvBackend + } else { + newArgs[i] = os.Args[i] + } + replaceOptArg = false + continue + } + + /* Handle --option XXX case */ + if strings.Compare(arg, "--backend") == 0 { + newArgs[i] = arg + replaceOptArg = true + continue + } + + /* Handle --option=XXX case */ + if strings.Compare(arg, "--backend=rr") == 0 || + strings.Compare(arg, "--backend=undo") == 0 { + newArgs[i] = "--backend=" + dlvBackend + continue + } + + newArgs[i] = os.Args[i] + } + os.Args = newArgs + } + cmds.New(false).Execute() } diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 09b204739..7261634df 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -23,6 +23,8 @@ // macOS. // * mozilla rr: a stub that records the full execution of a program // and can then play it back. +// * undo: a stub that records the full execution of a program +// and can then play it back. // // Implementations of the protocol vary wildly between stubs, while there is // a command to query the stub about supported features (qSupported) this @@ -164,6 +166,9 @@ type gdbProcess struct { waitChan chan *os.ProcessState onDetach func() // called after a successful detach + + localCheckpointLastId int + localCheckpoints map[int]proc.Checkpoint } var _ proc.RecordingManipulationInternal = &gdbProcess{} @@ -237,6 +242,9 @@ func newProcess(process *os.Process) *gdbProcess { gcmdok: true, threadStopInfo: true, process: process, + + localCheckpointLastId: 1, + localCheckpoints: make(map[int]proc.Checkpoint), } switch p.bi.Arch.Name { @@ -1054,6 +1062,16 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T return nil, proc.ErrNotRecorded } + // Is this a checkpoint on a server using local checkpoints? + if len(pos) > 1 && pos[:1] == "c" && p.conn.isUndoServer { + cpid, _ := strconv.Atoi(pos[1:]) + checkpoint, exists := p.localCheckpoints[cpid] + if !exists { + return nil, errors.New("Checkpoint not found") + } + pos = checkpoint.When + } + p.exited = false p.almostExited = false @@ -1070,9 +1088,11 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T // for some reason we have to send a vCont;c after a vRun to make rr behave // properly, because that's what gdb does. - _, err = p.conn.resume(cctx, nil, nil) - if err != nil { - return nil, err + if !p.conn.isUndoServer { + _, err = p.conn.resume(cctx, nil, nil) + if err != nil { + return nil, err + } } err = p.updateThreadList(&threadUpdater{p: p}) @@ -1089,17 +1109,27 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T return p.currentThread, p.setCurrentBreakpoints() } -// When executes the 'when' command for the Mozilla RR backend. +// When executes the 'when' command for the Mozilla RR/Undo backends. // This command will return rr's internal event number. func (p *gdbProcess) When() (string, error) { if p.tracedir == "" { return "", proc.ErrNotRecorded } - event, err := p.conn.qRRCmd("when") - if err != nil { - return "", err + result := "" + if p.conn.isUndoServer { + extent, err := p.conn.undoCmd("get_time") + if err != nil { + return "", err + } + result = extent + } else { + event, err := p.conn.qRRCmd("when") + if err != nil { + return "", err + } + result = strings.TrimSpace(event) } - return strings.TrimSpace(event), nil + return result, nil } const ( @@ -1111,6 +1141,19 @@ func (p *gdbProcess) Checkpoint(where string) (int, error) { if p.tracedir == "" { return -1, proc.ErrNotRecorded } + + // Handle locally managed checkpoints first + if p.conn.isUndoServer { + cpid := p.localCheckpointLastId + p.localCheckpointLastId++ + when, err := p.conn.undoCmd("get_time") + if err != nil { + return -1, err + } + p.localCheckpoints[cpid] = proc.Checkpoint{ID: cpid, When: when, Where: where} + return cpid, nil + } + resp, err := p.conn.qRRCmd("checkpoint", where) if err != nil { return -1, err @@ -1139,6 +1182,16 @@ func (p *gdbProcess) Checkpoints() ([]proc.Checkpoint, error) { if p.tracedir == "" { return nil, proc.ErrNotRecorded } + + // Handle locally managed checkpoints first + if p.conn.isUndoServer { + r := make([]proc.Checkpoint, 0, len(p.localCheckpoints)) + for _, cp := range p.localCheckpoints { + r = append(r, cp) + } + return r, nil + } + resp, err := p.conn.qRRCmd("info checkpoints") if err != nil { return nil, err @@ -1169,6 +1222,14 @@ func (p *gdbProcess) ClearCheckpoint(id int) error { if p.tracedir == "" { return proc.ErrNotRecorded } + + // Handle locally managed checkpoints first + if p.conn.isUndoServer { + delete(p.localCheckpoints, id) + // We don't care if it didn't exist + return nil + } + resp, err := p.conn.qRRCmd("delete checkpoint", strconv.Itoa(id)) if err != nil { return err @@ -1212,6 +1273,16 @@ func (p *gdbProcess) StartCallInjection() (func(), error) { return nil, ErrStartCallInjectionBackwards } + if p.conn.isUndoServer { + _, err := p.conn.undoCmd("set_debuggee_volatile", "1") + if err != nil { + return nil, err + } + return func() { + _, _ = p.conn.undoCmd("set_debuggee_volatile", "0") + }, nil + } + // Normally it's impossible to inject function calls in a recorded target // because the sequence of instructions that the target will execute is // predetermined. diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go index e1d229861..1c9c7fb7c 100644 --- a/pkg/proc/gdbserial/gdbserver_conn.go +++ b/pkg/proc/gdbserial/gdbserver_conn.go @@ -13,6 +13,7 @@ import ( "os" "strconv" "strings" + "syscall" "time" "github.com/undoio/delve/pkg/logflags" @@ -48,6 +49,8 @@ type gdbConn struct { useXcmd bool // forces writeMemory to use the 'X' command + isUndoServer bool // true if using an Undo backend + log logflags.Logger } @@ -804,6 +807,10 @@ func (conn *gdbConn) parseStopPacket(resp []byte, threadID string, tu *threadUpd } } + if syscall.Signal(sig) == syscall.SIGCHLD { + // FIXME get exit code + return false, stopPacket{}, proc.ErrProcessExited{Pid: conn.pid, Status: 0} + } return false, sp, nil case 'W', 'X': @@ -1132,10 +1139,33 @@ func (conn *gdbConn) threadStopInfo(threadID string) (sp stopPacket, err error) // restart executes a 'vRun' command. func (conn *gdbConn) restart(pos string) error { conn.outbuf.Reset() - fmt.Fprint(&conn.outbuf, "$vRun;") - if pos != "" { - fmt.Fprint(&conn.outbuf, ";") - writeAsciiBytes(&conn.outbuf, []byte(pos)) + + if conn.isUndoServer { + if pos != "" { + fmt.Fprintf(&conn.outbuf, "$vUDB;goto_time;%s", pos) + } else { + // Find the actual min BB count. + // TODO: is defaulting to zero if we can't get it correct? + minBbCount := "0" + + extent, err := conn.undoCmd("get_log_extent") + if err != nil { + return err + } + index := strings.Index(extent, ",") + if index > 0 { + minBbCount = extent[:index] + } + + conn.outbuf.Reset() + fmt.Fprintf(&conn.outbuf, "$vUDB;goto_time;%s;0", minBbCount) + } + } else { + fmt.Fprint(&conn.outbuf, "$vRun;") + if pos != "" { + fmt.Fprint(&conn.outbuf, ";") + writeAsciiBytes(&conn.outbuf, []byte(pos)) + } } _, err := conn.exec(conn.outbuf.Bytes(), "restart") return err @@ -1164,6 +1194,23 @@ func (conn *gdbConn) qRRCmd(args ...string) (string, error) { return string(data), nil } +// undoCmd executes a vUDB command +func (conn *gdbConn) undoCmd(args ...string) (string, error) { + if len(args) == 0 { + panic("must specify at least one argument for undoCmd") + } + conn.outbuf.Reset() + fmt.Fprint(&conn.outbuf, "$vUDB") + for _, arg := range args { + fmt.Fprint(&conn.outbuf, ";", arg) + } + resp, err := conn.exec(conn.outbuf.Bytes(), "undoCmd") + if err != nil { + return "", err + } + return string(resp), nil +} + type imageList struct { Images []imageDescription `json:"images"` } diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go new file mode 100644 index 000000000..ccef6df02 --- /dev/null +++ b/pkg/proc/gdbserial/undo.go @@ -0,0 +1,160 @@ +package gdbserial + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "runtime" + + "github.com/undoio/delve/pkg/proc" +) + +func serverFile() (string, error) { + switch runtime.GOARCH { + case "amd64": + return "udbserver_x64", nil + case "arm64": + return "udbserver_arm64", nil + case "386": + return "udbserver_x32", nil + default: + return "", &ErrBackendUnavailable{} + } +} + +func UndoIsAvailable() error { + server, err := serverFile() + if err != nil { + return err + } + + cmds := []string{server, "live-record"} + + for _, cmd := range cmds { + if _, err := exec.LookPath(cmd); err != nil { + return &ErrBackendUnavailable{} + } + } + return nil +} + +func UndoRecord(cmd []string, wd string, quiet bool, redirects [3]string) (recording string, err error) { + if err := UndoIsAvailable(); err != nil { + return "", err + } + + file, err := ioutil.TempFile("/tmp", "undo") + if err != nil { + return "", err + } + + recording = file.Name() + args := make([]string, 0) + args = append(args, "-o", recording) + args = append(args, cmd...) + lrcmd := exec.Command("live-record", args...) + var closefn func() + // FIXME: pass quiet to openRedirects(), not false. + lrcmd.Stdin, lrcmd.Stdout, lrcmd.Stderr, closefn, err = openRedirects(redirects, false) + if err != nil { + return "", err + } + if wd != "" { + lrcmd.Dir = wd + } + lrcmd.Env = os.Environ() + + // Ignore failures from Run - it could be the target failing + _ = lrcmd.Run() + closefn() + + if isRecording, err := UndoIsRecording(recording); !isRecording { + // Recording apparently failed to put anything in the file + os.Remove(recording) + if err == nil { + err = fmt.Errorf("Recording failed") + } + return "", err + } + + return recording, err +} + +func UndoReplay(recording string, path string, quiet bool, debugInfoDirs []string) (tgt *proc.TargetGroup, err error) { + if err := UndoIsAvailable(); err != nil { + return nil, err + } + + if isRecording, err := UndoIsRecording(recording); !isRecording || err != nil { + if err == nil { + err = fmt.Errorf("%s is not a LiveRecorder recording", recording) + } + return nil, err + } + + port := unusedPort() + + args := make([]string, 0) + args = append(args, "--load-file", recording, "--connect-port", port[1:]) + server, err := serverFile() + if err != nil { + return nil, err + } + servercmd := exec.Command(server, args...) + + if !quiet { + servercmd.Env = os.Environ() + // servercmd.Env = append(servercmd.Env, "UNDO_debug_filename=/dev/stderr") + // servercmd.Env = append(servercmd.Env, "UNDO_debug_level=1") + servercmd.Stdout = os.Stdout + servercmd.Stderr = os.Stderr + } + + if err := servercmd.Start(); err != nil { + return nil, err + } + + p := newProcess(servercmd.Process) + p.tracedir = recording + tgt, err = p.Dial(port, path, 0, debugInfoDirs, proc.StopAttached) + if err != nil { + servercmd.Process.Kill() + return nil, err + } + + // set to cause gdbserver.go to treat incoming signal numbers according + // to the GDB mapping, not the Linux mapping (the binutils-gdb repo + // defines the GDB mapping in include/gdb/signals.def) + p.conn.isUndoServer = true + return tgt, nil +} + +// RecordAndReplay acts like calling Record and then Replay. +func UndoRecordAndReplay(cmd []string, wd string, quiet bool, debugInfoDirs []string, redirects [3]string) (tgt *proc.TargetGroup, recording string, err error) { + recording, err = UndoRecord(cmd, wd, quiet, redirects) + if err != nil || recording == "" { + return nil, "", err + } + tgt, err = UndoReplay(recording, cmd[0], quiet, debugInfoDirs) + return tgt, recording, err +} + +func UndoIsRecording(recordingFile string) (result bool, err error) { + marker := []byte("HD\x10\x00\x00\x00UndoDB recording") + + f, err := os.Open(recordingFile) + if err != nil { + return false, err + } + defer f.Close() + + data := make([]byte, len(marker)) + c, err := f.Read(data) + if err != nil || c != len(marker) { + return false, err + } + + return bytes.Equal(marker, data), nil +} diff --git a/pkg/proc/gdbserial/undo_test.go b/pkg/proc/gdbserial/undo_test.go new file mode 100644 index 000000000..da4dbf8c2 --- /dev/null +++ b/pkg/proc/gdbserial/undo_test.go @@ -0,0 +1,235 @@ +package gdbserial_test + +import ( + "fmt" + "os" + "testing" + + "github.com/undoio/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc/gdbserial" + protest "github.com/undoio/delve/pkg/proc/test" +) + +func withUndoRecording(name string, t testing.TB, fn func(grp *proc.TargetGroup, fixture protest.Fixture)) { + fixture := protest.BuildFixture(name, 0) + protest.MustHaveRecordingAllowed(t) + if err := gdbserial.UndoIsAvailable(); err != nil { + t.Skip("test skipped, Undo tools not found") + } + t.Log("recording") + grp, recording, err := gdbserial.UndoRecordAndReplay([]string{fixture.Path}, ".", true, []string{}, [3]string{}) + if err != nil { + t.Fatal("Launch():", err) + } + t.Logf("replaying %q", recording) + + defer func() { + grp.Detach(true) + if recording != "" { + os.Remove(recording) + } + }() + + fn(grp, fixture) +} + +func TestUndoRestartAfterExit(t *testing.T) { + protest.AllowRecording(t) + withUndoRecording("testnextprog", t, func(grp *proc.TargetGroup, fixture protest.Fixture) { + p := grp.Selected + setFunctionBreakpoint(p, t, "main.main") + assertNoError(grp.Continue(), t, "Continue") + loc, err := p.CurrentThread().Location() + assertNoError(err, t, "CurrentThread().Location()") + err = grp.Continue() + if _, isexited := err.(proc.ErrProcessExited); err == nil || !isexited { + t.Fatalf("program did not exit: %v", err) + } + + assertNoError(grp.Restart(""), t, "Restart") + + assertNoError(grp.Continue(), t, "Continue (after restart)") + loc2, err := p.CurrentThread().Location() + assertNoError(err, t, "CurrentThread().Location() (after restart)") + if loc2.Line != loc.Line { + t.Fatalf("stopped at %d (expected %d)", loc2.Line, loc.Line) + } + err = grp.Continue() + if _, isexited := err.(proc.ErrProcessExited); err == nil || !isexited { + t.Fatalf("program did not exit (after exit): %v", err) + } + }) +} + +func TestUndoRestartDuringStop(t *testing.T) { + protest.AllowRecording(t) + withUndoRecording("testnextprog", t, func(grp *proc.TargetGroup, fixture protest.Fixture) { + p := grp.Selected + setFunctionBreakpoint(p, t, "main.main") + assertNoError(grp.Continue(), t, "Continue") + loc, err := p.CurrentThread().Location() + assertNoError(err, t, "CurrentThread().Location()") + + assertNoError(grp.Restart(""), t, "Restart") + + assertNoError(grp.Continue(), t, "Continue (after restart)") + loc2, err := p.CurrentThread().Location() + assertNoError(err, t, "CurrentThread().Location() (after restart)") + if loc2.Line != loc.Line { + t.Fatalf("stopped at %d (expected %d)", loc2.Line, loc.Line) + } + err = grp.Continue() + if _, isexited := err.(proc.ErrProcessExited); err == nil || !isexited { + t.Fatalf("program did not exit (after exit): %v", err) + } + }) +} + +func TestUndoReverseBreakpointCounts(t *testing.T) { + protest.AllowRecording(t) + withUndoRecording("bpcountstest", t, func(grp *proc.TargetGroup, fixture protest.Fixture) { + p := grp.Selected + endbp := setFileBreakpoint(p, t, fixture, 28) + assertNoError(grp.Continue(), t, "Continue()") + loc, _ := p.CurrentThread().Location() + if loc.PC != endbp.Addr { + t.Fatalf("did not reach end of main.main function: %s:%d (%#x)", loc.File, loc.Line, loc.PC) + } + + p.ClearBreakpoint(endbp.Addr) + assertNoError(grp.ChangeDirection(proc.Backward), t, "Switching to backward direction") + bp := setFileBreakpoint(p, t, fixture, 12) + startbp := setFileBreakpoint(p, t, fixture, 20) + + countLoop: + for { + assertNoError(grp.Continue(), t, "Continue()") + loc, _ := p.CurrentThread().Location() + switch loc.PC { + case startbp.Addr: + break countLoop + case bp.Addr: + // ok + default: + t.Fatalf("unexpected stop location %s:%d %#x", loc.File, loc.Line, loc.PC) + } + } + + t.Logf("TotalHitCount: %d", bp.Logical.TotalHitCount) + if bp.Logical.TotalHitCount != 200 { + t.Fatalf("Wrong TotalHitCount for the breakpoint (%d)", bp.Logical.TotalHitCount) + } + + if len(bp.Logical.HitCount) != 2 { + t.Fatalf("Wrong number of goroutines for breakpoint (%d)", len(bp.Logical.HitCount)) + } + + for _, v := range bp.Logical.HitCount { + if v != 100 { + t.Fatalf("Wrong HitCount for breakpoint (%v)", bp.Logical.HitCount) + } + } + }) +} + +func TestUndoCheckpoints(t *testing.T) { + protest.AllowRecording(t) + withUndoRecording("continuetestprog", t, func(grp *proc.TargetGroup, fixture protest.Fixture) { + // Continues until start of main.main, record output of 'when' + p := grp.Selected + bp := setFunctionBreakpoint(p, t, "main.main") + assertNoError(grp.Continue(), t, "Continue") + when0, loc0 := getPosition(grp, t) + t.Logf("when0: %q (%#x) %x", when0, loc0.PC, p.CurrentThread().ThreadID()) + + // Create a checkpoint and check that the list of checkpoints reflects this + cpid, err := grp.Checkpoint("checkpoint1") + if cpid != 1 { + t.Errorf("unexpected checkpoint id %d", cpid) + } + assertNoError(err, t, "Checkpoint") + checkpoints, err := grp.Checkpoints() + assertNoError(err, t, "Checkpoints") + if len(checkpoints) != 1 { + t.Fatalf("wrong number of checkpoints %v (one expected)", checkpoints) + } + + // Move forward with next, check that the output of 'when' changes + assertNoError(grp.Next(), t, "First Next") + assertNoError(grp.Next(), t, "Second Next") + when1, loc1 := getPosition(grp, t) + t.Logf("when1: %q (%#x) %x", when1, loc1.PC, p.CurrentThread().ThreadID()) + if loc0.PC == loc1.PC { + t.Fatalf("next did not move process %#x", loc0.PC) + } + if when0 == when1 { + t.Fatalf("output of when did not change after next: %q", when0) + } + + // Move back to checkpoint, check that the output of 'when' is the same as + // what it was when we set the breakpoint + grp.Restart(fmt.Sprintf("c%d", cpid)) + g, _ := proc.FindGoroutine(p, 1) + p.SwitchGoroutine(g) + when2, loc2 := getPosition(grp, t) + t.Logf("when2: %q (%#x) %x", when2, loc2.PC, p.CurrentThread().ThreadID()) + if loc2.PC != loc0.PC { + t.Fatalf("PC address mismatch %#x != %#x", loc0.PC, loc2.PC) + } + if when0 != when2 { + t.Fatalf("output of when mismatched %q != %q", when0, when2) + } + + // Move forward with next again, check that the output of 'when' matches + assertNoError(grp.Next(), t, "First Next") + assertNoError(grp.Next(), t, "Second Next") + when3, loc3 := getPosition(grp, t) + t.Logf("when3: %q (%#x)", when3, loc3.PC) + if loc3.PC != loc1.PC { + t.Fatalf("PC address mismatch %#x != %#x", loc1.PC, loc3.PC) + } + if when3 != when1 { + t.Fatalf("when output mismatch %q != %q", when1, when3) + } + + // Delete breakpoint, move back to checkpoint then next twice and check + // output of 'when' again + err = p.ClearBreakpoint(bp.Addr) + assertNoError(err, t, "ClearBreakpoint") + grp.Restart(fmt.Sprintf("c%d", cpid)) + g, _ = proc.FindGoroutine(p, 1) + p.SwitchGoroutine(g) + assertNoError(grp.Next(), t, "First Next") + assertNoError(grp.Next(), t, "Second Next") + when4, loc4 := getPosition(grp, t) + t.Logf("when4: %q (%#x)", when4, loc4.PC) + if loc4.PC != loc1.PC { + t.Fatalf("PC address mismatch %#x != %#x", loc1.PC, loc4.PC) + } + if when4 != when1 { + t.Fatalf("when output mismatch %q != %q", when1, when4) + } + + // Delete checkpoint, check that the list of checkpoints is updated + assertNoError(grp.ClearCheckpoint(cpid), t, "ClearCheckpoint") + checkpoints, err = grp.Checkpoints() + assertNoError(err, t, "Checkpoints") + if len(checkpoints) != 0 { + t.Fatalf("wrong number of checkpoints %v (zero expected)", checkpoints) + } + }) +} + +func TestUndoIssue1376(t *testing.T) { + // Backward Continue should terminate when it encounters the start of the process. + protest.AllowRecording(t) + withUndoRecording("continuetestprog", t, func(grp *proc.TargetGroup, fixture protest.Fixture) { + p := grp.Selected + bp := setFunctionBreakpoint(p, t, "main.main") + assertNoError(grp.Continue(), t, "Continue (forward)") + err := p.ClearBreakpoint(bp.Addr) + assertNoError(err, t, "ClearBreakpoint") + assertNoError(grp.ChangeDirection(proc.Backward), t, "Switching to backward direction") + assertNoError(grp.Continue(), t, "Continue (backward)") + }) +} diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 912a1ce11..de793f18d 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -100,6 +100,7 @@ func withTestProcessArgs(name string, t testing.TB, wd string, args []string, bu var grp *proc.TargetGroup var err error var tracedir string + var recording string switch testBackend { case "native": @@ -111,6 +112,11 @@ func withTestProcessArgs(name string, t testing.TB, wd string, args []string, bu t.Log("recording") grp, tracedir, err = gdbserial.RecordAndReplay(append([]string{fixture.Path}, args...), wd, true, []string{}, [3]string{}) t.Logf("replaying %q", tracedir) + case "undo": + protest.MustHaveRecordingAllowed(t) + t.Log("recording") + grp, recording, err = gdbserial.UndoRecordAndReplay(append([]string{fixture.Path}, args...), wd, true, []string{}, [3]string{}) + t.Logf("replaying") default: t.Fatal("unknown backend") } @@ -120,6 +126,9 @@ func withTestProcessArgs(name string, t testing.TB, wd string, args []string, bu defer func() { grp.Detach(true) + if recording != "" { + os.Remove(recording) + } }() fn(grp.Selected, grp, fixture) @@ -1177,7 +1186,7 @@ func evalVariableOrError(p *proc.Target, symbol string) (*proc.Variable, error) var scope *proc.EvalScope var err error - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { var frame proc.Stackframe frame, err = findFirstNonRuntimeFrame(p) if err == nil { @@ -2717,7 +2726,7 @@ func TestIssue594(t *testing.T) { assertNoError(grp.Continue(), t, "Continue()") var f string var ln int - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { frame, err := findFirstNonRuntimeFrame(p) assertNoError(err, t, "findFirstNonRuntimeFrame") f, ln = frame.Current.File, frame.Current.Line @@ -2859,7 +2868,7 @@ func TestAttachDetach(t *testing.T) { return } } - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { return } var buildFlags protest.BuildFlags @@ -3072,7 +3081,7 @@ func TestIssue871(t *testing.T) { var scope *proc.EvalScope var err error - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { var frame proc.Stackframe frame, err = findFirstNonRuntimeFrame(p) if err == nil { @@ -3159,7 +3168,7 @@ func TestAttachStripped(t *testing.T) { return } } - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { return } if runtime.GOOS == "darwin" { @@ -4814,8 +4823,8 @@ func BenchmarkConditionalBreakpoints(b *testing.B) { } func TestBackwardNextGeneral(t *testing.T) { - if testBackend != "rr" { - t.Skip("Reverse stepping test needs rr") + if testBackend != "rr" && testBackend != "undo" { + t.Skip("Reverse stepping test needs rr or undo") } testseq2(t, "testnextprog", "main.helloworld", []seqTest{ {contContinue, 13}, @@ -4845,8 +4854,8 @@ func TestBackwardNextGeneral(t *testing.T) { } func TestBackwardStepOutGeneral(t *testing.T) { - if testBackend != "rr" { - t.Skip("Reverse stepping test needs rr") + if testBackend != "rr" && testBackend != "undo" { + t.Skip("Reverse stepping test needs rr or undo") } testseq2(t, "testnextprog", "main.helloworld", []seqTest{ {contContinue, 13}, @@ -4857,8 +4866,8 @@ func TestBackwardStepOutGeneral(t *testing.T) { } func TestBackwardStepGeneral(t *testing.T) { - if testBackend != "rr" { - t.Skip("Reverse stepping test needs rr") + if testBackend != "rr" && testBackend != "undo" { + t.Skip("Reverse stepping test needs rr or undo") } testseq2(t, "testnextprog", "main.helloworld", []seqTest{ {contContinue, 13}, @@ -4896,8 +4905,8 @@ func TestBackwardStepGeneral(t *testing.T) { } func TestBackwardNextDeferPanic(t *testing.T) { - if testBackend != "rr" { - t.Skip("Reverse stepping test needs rr") + if testBackend != "rr" && testBackend != "undo" { + t.Skip("Reverse stepping test needs rr or undo") } if goversion.VersionAfterOrEqual(runtime.Version(), 1, 18) { testseq2(t, "defercall", "", []seqTest{ diff --git a/pkg/proc/proc_unix_test.go b/pkg/proc/proc_unix_test.go index 45c1c6262..bc6eb9173 100644 --- a/pkg/proc/proc_unix_test.go +++ b/pkg/proc/proc_unix_test.go @@ -29,7 +29,7 @@ func (npe errIssue419) Error() string { } func TestIssue419(t *testing.T) { - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { return } diff --git a/pkg/proc/variables_test.go b/pkg/proc/variables_test.go index 57f5e46c4..721a6951d 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -69,7 +69,7 @@ func assertVariable(t testing.TB, variable *proc.Variable, expected varTest) { } func evalScope(p *proc.Target) (*proc.EvalScope, error) { - if testBackend != "rr" { + if testBackend != "rr" && testBackend != "undo" { return proc.GoroutineScope(p, p.CurrentThread()) } frame, err := findFirstNonRuntimeFrame(p) @@ -158,7 +158,7 @@ func TestVariableEvaluation2(t *testing.T) { } } - if tc.alternate != "" && testBackend != "rr" { + if tc.alternate != "" && testBackend != "rr" && testBackend != "undo" { assertNoError(setVariable(p, tc.name, tc.alternate), t, "SetVariable()") variable, err = evalVariableWithCfg(p, tc.name, pnormalLoadConfig) assertNoError(err, t, "EvalVariable()") @@ -407,7 +407,7 @@ func TestLocalVariables(t *testing.T) { var scope *proc.EvalScope var err error - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { var frame proc.Stackframe frame, err = findFirstNonRuntimeFrame(p) if err == nil { diff --git a/pkg/terminal/command_test.go b/pkg/terminal/command_test.go index 784789e0a..2f40ff9ed 100644 --- a/pkg/terminal/command_test.go +++ b/pkg/terminal/command_test.go @@ -119,7 +119,7 @@ func withTestTerminal(name string, t testing.TB, fn func(*FakeTerminal)) { } func withTestTerminalBuildFlags(name string, t testing.TB, buildFlags test.BuildFlags, fn func(*FakeTerminal)) { - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { test.MustHaveRecordingAllowed(t) } os.Setenv("TERM", "dumb") @@ -621,7 +621,7 @@ func TestListCmd(t *testing.T) { func TestReverseContinue(t *testing.T) { test.AllowRecording(t) - if testBackend != "rr" { + if testBackend != "rr" && testBackend != "undo" { return } withTestTerminal("continuetestprog", t, func(term *FakeTerminal) { @@ -635,7 +635,7 @@ func TestReverseContinue(t *testing.T) { func TestCheckpoints(t *testing.T) { test.AllowRecording(t) - if testBackend != "rr" { + if testBackend != "rr" && testBackend != "undo" { return } withTestTerminal("continuetestprog", t, func(term *FakeTerminal) { diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index 8c6a2bc24..26e5e5552 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -177,6 +177,9 @@ func New(config *Config, processArgs []string) (*Debugger, error) { case "rr": d.log.Infof("opening trace %s", d.config.CoreFile) d.target, err = gdbserial.Replay(d.config.CoreFile, false, false, d.config.DebugInfoDirectories, d.config.RrOnProcessPid) + case "undo": + d.log.Infof("opening recording %s", d.config.CoreFile) + d.target, err = gdbserial.UndoReplay(d.config.CoreFile, "", false, d.config.DebugInfoDirectories) default: d.log.Infof("opening core file %s (executable %s)", d.config.CoreFile, d.processArgs[0]) d.target, err = core.OpenCore(d.config.CoreFile, d.processArgs[0], d.config.DebugInfoDirectories) @@ -300,6 +303,9 @@ func (d *Debugger) Launch(processArgs []string, wd string) (*proc.TargetGroup, e } }() return nil, nil + case "undo": + tgt, _, err := gdbserial.UndoRecordAndReplay(processArgs, wd, false, d.config.DebugInfoDirectories, d.config.Redirects) + return tgt, err case "default": if runtime.GOOS == "darwin" { @@ -500,7 +506,7 @@ func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs [] } } - if recorded { + if recorded && d.config.Backend == "rr" { run, stop, err2 := gdbserial.RecordAsync(d.processArgs, d.config.WorkingDir, false, d.config.Redirects) if err2 != nil { return nil, err2 @@ -509,6 +515,8 @@ func (d *Debugger) Restart(rerecord bool, pos string, resetArgs bool, newArgs [] d.recordingStart(stop) grp, err = d.recordingRun(run) d.recordingDone() + } else if recorded && d.config.Backend == "undo" { + grp, _, err = gdbserial.UndoRecordAndReplay(d.processArgs, d.config.WorkingDir, false, d.config.DebugInfoDirectories, d.config.Redirects) } else { grp, err = d.Launch(d.processArgs, d.config.WorkingDir) } @@ -2067,8 +2075,8 @@ func (d *Debugger) ExamineMemory(address uint64, length int) ([]byte, error) { func (d *Debugger) GetVersion(out *api.GetVersionOut) error { if d.config.CoreFile != "" { - if d.config.Backend == "rr" { - out.Backend = "rr" + if d.config.Backend == "rr" || d.config.Backend == "undo" { + out.Backend = d.config.Backend } else { out.Backend = "core" } diff --git a/service/test/integration1_test.go b/service/test/integration1_test.go index 1d66a5bb7..dea081bfe 100644 --- a/service/test/integration1_test.go +++ b/service/test/integration1_test.go @@ -28,7 +28,7 @@ func withTestClient1(name string, t *testing.T, fn func(c *rpc1.RPCClient)) { } func withTestClient1Extended(name string, t *testing.T, fn func(c *rpc1.RPCClient, fixture protest.Fixture)) { - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { protest.MustHaveRecordingAllowed(t) } listener, err := net.Listen("tcp", "127.0.0.1:0") diff --git a/service/test/integration2_test.go b/service/test/integration2_test.go index 1ad39cc37..fc6770d8a 100644 --- a/service/test/integration2_test.go +++ b/service/test/integration2_test.go @@ -62,7 +62,7 @@ func withTestClient2(name string, t *testing.T, fn func(c service.Client)) { } func startServer(name string, buildFlags protest.BuildFlags, t *testing.T, redirects [3]string, args []string) (clientConn net.Conn, fixture protest.Fixture) { - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { protest.MustHaveRecordingAllowed(t) } listener, clientConn := service.ListenerPipe() @@ -1686,6 +1686,9 @@ func TestClientServer_Issue528(t *testing.T) { } func TestClientServer_FpRegisters(t *testing.T) { + if testBackend == "undo" { + t.Skip("undo backend doesn't report floating-point registers [#19]") + } if runtime.GOARCH != "amd64" { t.Skip("test is valid only on AMD64") } @@ -1863,8 +1866,8 @@ func TestClientServer_SelectedGoroutineLoc(t *testing.T) { func TestClientServer_ReverseContinue(t *testing.T) { protest.AllowRecording(t) - if testBackend != "rr" { - t.Skip("backend is not rr") + if testBackend != "rr" && testBackend != "undo" { + t.Skip("only valid for recorded targets") } withTestClient2("continuetestprog", t, func(c service.Client) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main", Line: -1}) @@ -2033,7 +2036,7 @@ func TestClientServer_StepOutReturn(t *testing.T) { } func TestAcceptMulticlient(t *testing.T) { - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { t.Skip("recording not allowed for TestAcceptMulticlient") } listener, err := net.Listen("tcp", "127.0.0.1:0") @@ -2264,7 +2267,7 @@ func TestIssue1703(t *testing.T) { func TestRerecord(t *testing.T) { protest.AllowRecording(t) - if testBackend != "rr" { + if testBackend != "rr" && testBackend != "undo" { t.Skip("only valid for recorded targets") } withTestClient2("testrerecord", t, func(c service.Client) { @@ -2421,7 +2424,7 @@ func TestRedirects(t *testing.T) { t.Fatalf("Wrong output %q", string(buf)) } os.Remove(outpath) - if testBackend != "rr" { + if testBackend != "rr" && testBackend != "undo" { _, err = c.Restart(false) assertNoError(err, t, "Restart") <-c.Continue() @@ -2463,7 +2466,7 @@ func TestIssue2162(t *testing.T) { func TestDetachLeaveRunning(t *testing.T) { // See https://github.com/go-delve/delve/issues/2259 - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { return } From 251763597cc7a04f20a947167096b48f4bf5ac13 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 30 Mar 2022 10:16:09 +0100 Subject: [PATCH 06/29] Exclude TestCallFunction cases that fail with the Undo backend. --- pkg/proc/variables_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/proc/variables_test.go b/pkg/proc/variables_test.go index 721a6951d..ae0569fd1 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -1187,7 +1187,7 @@ func TestCallFunction(t *testing.T) { {`fn2glob(10, 20)`, []string{":int:30"}, nil}, // indirect call of func value / set to top-level func {`fn2clos(11)`, []string{`:string:"1 + 6 + 11 = 18"`}, nil}, // indirect call of func value / set to func literal - {`fn2clos(12)`, []string{`:string:"2 + 6 + 12 = 20"`}, nil}, + // UNDO [#30]: {`fn2clos(12)`, []string{`:string:"2 + 6 + 12 = 20"`}, nil}, {`fn2valmeth(13)`, []string{`:string:"13 + 6 = 19"`}, nil}, // indirect call of func value / set to value method {`fn2ptrmeth(14)`, []string{`:string:"14 - 6 = 8"`}, nil}, // indirect call of func value / set to pointer method @@ -1208,7 +1208,7 @@ func TestCallFunction(t *testing.T) { {`onetwothree(intcallpanic("not a number"))`, nil, errors.New("error evaluating \"intcallpanic(\\\"not a number\\\")\" as argument n in function main.onetwothree: can not convert \"not a number\" constant to int")}, // Variable setting tests - {`pa2 = getAStructPtr(8); pa2`, []string{`pa2:*main.astruct:*main.astruct {X: 8}`}, nil}, + // UNDO [#30]: {`pa2 = getAStructPtr(8); pa2`, []string{`pa2:*main.astruct:*main.astruct {X: 8}`}, nil}, // Escape tests @@ -1226,7 +1226,7 @@ func TestCallFunction(t *testing.T) { var testcases112 = []testCaseCallFunction{ // string allocation requires trusted argument order, which we don't have in Go 1.11 {`stringsJoin(stringslice, ",")`, []string{`:string:"one,two,three"`}, nil}, - {`str = "a new string"; str`, []string{`str:string:"a new string"`}, nil}, + // UNDO [#30]: {`str = "a new string"; str`, []string{`str:string:"a new string"`}, nil}, // support calling optimized functions {`strings.Join(nil, "")`, []string{`:string:""`}, nil}, From cc9fb865e5f93fbbe5ee73ebb2ef79a1e5a5f9ec Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Thu, 25 May 2023 12:13:20 +0100 Subject: [PATCH 07/29] Handle end of history correctly for udbserver backend. This changeset fixes a bug in which, after continuing to the end of a loaded LiveRecorder recording, it became impossible to reverse into the debug session. By using the same technique already implemented for rr support it is now possible to reach the end of time and then continue debugging. In addition, the exit code (where available) be reported correctly - although it will be reported as zero at the end of time if no exit was recorded. A workaround for apparent SIGCHILD handling (actually SIGSTOP, due to how the gdbserial protocol encodes signals) is removed as it is not required with this new implementation. --- pkg/proc/gdbserial/gdbserver.go | 14 ++++- pkg/proc/gdbserial/gdbserver_conn.go | 11 ++-- pkg/proc/gdbserial/undo.go | 92 ++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 7261634df..ea86ab06b 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -872,7 +872,17 @@ continueLoop: trapthread, atstart, shouldStop, shouldExitErr = p.handleThreadSignals(cctx, trapthread) if shouldExitErr { p.almostExited = true - return nil, proc.StopExited, proc.ErrProcessExited{Pid: p.conn.pid} + + exit_code := 0 + if p.conn.isUndoServer { + // Retrieve the exit code of the recorded process (if applicable) + // from udbserver. + exit_code, err = undoGetExitCode(&p.conn) + if err != nil { + return nil, proc.StopUnknown, err + } + } + return nil, proc.StopExited, proc.ErrProcessExited{Pid: p.conn.pid, Status: exit_code} } if shouldStop { break continueLoop @@ -941,7 +951,7 @@ func (p *gdbProcess) handleThreadSignals(cctx *proc.ContinueOnceContext, trapthr } case breakpointSignal: // breakpoint isStopSignal = true - case childSignal: // stop on debugserver but SIGCHLD on lldb-server/linux + case childSignal: // stop on debugserver or udbserver but SIGCHLD on lldb-server/linux if p.conn.isDebugserver { isStopSignal = true } diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go index 1c9c7fb7c..9dab7a8d4 100644 --- a/pkg/proc/gdbserial/gdbserver_conn.go +++ b/pkg/proc/gdbserial/gdbserver_conn.go @@ -13,7 +13,6 @@ import ( "os" "strconv" "strings" - "syscall" "time" "github.com/undoio/delve/pkg/logflags" @@ -807,10 +806,14 @@ func (conn *gdbConn) parseStopPacket(resp []byte, threadID string, tu *threadUpd } } - if syscall.Signal(sig) == syscall.SIGCHLD { - // FIXME get exit code - return false, stopPacket{}, proc.ErrProcessExited{Pid: conn.pid, Status: 0} + if conn.isUndoServer { + // Transform packet, if necessary, for instance at the end of time. + sp, err = undoHandleStopPacket(conn, sp) + if err != nil { + return false, stopPacket{}, err + } } + return false, sp, nil case 'W', 'X': diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index ccef6df02..997a948a9 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -7,6 +7,9 @@ import ( "os" "os/exec" "runtime" + "strconv" + "strings" + "syscall" "github.com/undoio/delve/pkg/proc" ) @@ -158,3 +161,92 @@ func UndoIsRecording(recordingFile string) (result bool, err error) { return bytes.Equal(marker, data), nil } + +// Fetch the output of a udbserver get_info command, split on ; and , characters. +// +// This is not (currently) implementing a proper parse of the data returned, just making it more +// convenient to search. +func undoGetInfo(conn *gdbConn) ([]string, error) { + info, err := conn.undoCmd("get_info") + if err != nil { + return nil, err + } + splitter := func(c rune) bool { + return c == ';' || c == ',' + } + return strings.FieldsFunc(info, splitter), nil +} + +// Fetch whether the replay session is currently at the end of recorded history. +func undoAtEndOfHistory(conn *gdbConn) (bool, error) { + info_fields, err := undoGetInfo(conn) + if err != nil { + return false, err + } + for _, value := range info_fields { + if value == "has_exited" || value == "at_event_log_end" { + return true, nil + } + } + return false, nil +} + +// Transform a stopPacket if necessary to represent the state of the replay session. +// +// Usually the packet will be passed through unaltered. Currently the only transformation +// implemented is modify a packet at the end of replay history to look like a SIGKILL, to be +// consistent with how RR would report this condition. +func undoHandleStopPacket(conn *gdbConn, sp stopPacket) (stopPacket, error) { + // TODO: find a different way of indicating end of history as opposed to actual process + // exit. + // + // TODO: find a different way of indicating the start of history (currently registers as a + // "hardcoded breakpoint") - should we use the atstart flag that rr uses somehow?. + + at_end, err := undoAtEndOfHistory(conn) + if err != nil { + return stopPacket{}, err + } + + if at_end { + // Mirror the behaviour of rr, in which the server will send a fake SIGKILL + // at the end of history. + sp.sig = _SIGKILL + } + + return sp, nil +} + +// Fetch the exit code of the replay process (or zero, if not applicable) from the recording. +func undoGetExitCode(conn *gdbConn) (int, error) { + exit_code := 0 + info_fields, err := undoGetInfo(conn) + if err != nil { + return 0, err + } + + for idx, value := range info_fields { + if value != "has_exited" { + continue + } + + // Exit status, encoded as hex, follows the has_exited string. + exit_status, err := strconv.ParseInt(info_fields[idx+1], 16, 16) + if err != nil { + return 0, err + } + + // Convert exit status into the form Delve usually reports - positive integer for a + // normal exit, negative signal number if terminated by a signal. + wait_status := syscall.WaitStatus(exit_status) + if wait_status.Signaled() { + exit_signal := wait_status.Signal() + exit_code = -int(exit_signal) + } else { + exit_code = wait_status.ExitStatus() + } + break + } + + return exit_code, nil +} From 03956c14330e8d3eda48300924372748abe2e424 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Mon, 5 Jun 2023 12:23:47 +0100 Subject: [PATCH 08/29] Factor fetching the current time out into separate Undo code. --- pkg/proc/gdbserial/gdbserver.go | 4 ++-- pkg/proc/gdbserial/undo.go | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index ea86ab06b..763a6f6cf 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1127,11 +1127,11 @@ func (p *gdbProcess) When() (string, error) { } result := "" if p.conn.isUndoServer { - extent, err := p.conn.undoCmd("get_time") + when, err := undoWhen(&p.conn) if err != nil { return "", err } - result = extent + result = when } else { event, err := p.conn.qRRCmd("when") if err != nil { diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 997a948a9..040a579fd 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -250,3 +250,12 @@ func undoGetExitCode(conn *gdbConn) (int, error) { return exit_code, nil } + +// Fetch a representation of the current time as a string. +func undoWhen(conn *gdbConn) (string, error) { + extent, err := conn.undoCmd("get_time") + if err != nil { + return "", err + } + return extent, nil +} From 9b776eb3226167e7bf7cf529ec2445319ed592cb Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Mon, 5 Jun 2023 12:26:09 +0100 Subject: [PATCH 09/29] Provide clearer display of current Undo time. --- pkg/proc/gdbserial/undo.go | 50 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 040a579fd..360bf1bb6 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -177,6 +177,24 @@ func undoGetInfo(conn *gdbConn) ([]string, error) { return strings.FieldsFunc(info, splitter), nil } +// Fetch the mininum and maximum bbcounts of recorded history. +func undoGetLogExtent(conn *gdbConn) (uint64, uint64, error) { + extent, err := conn.undoCmd("get_log_extent") + if err != nil { + return 0, 0, err + } + bbcounts := strings.Split(extent, ",") + bbcount_min, err := strconv.ParseUint(bbcounts[0], 16, 64) + if err != nil { + return 0, 0, err + } + bbcount_max, err := strconv.ParseUint(bbcounts[1], 16, 64) + if err != nil { + return 0, 0, err + } + return bbcount_min, bbcount_max, nil +} + // Fetch whether the replay session is currently at the end of recorded history. func undoAtEndOfHistory(conn *gdbConn) (bool, error) { info_fields, err := undoGetInfo(conn) @@ -253,9 +271,37 @@ func undoGetExitCode(conn *gdbConn) (int, error) { // Fetch a representation of the current time as a string. func undoWhen(conn *gdbConn) (string, error) { - extent, err := conn.undoCmd("get_time") + resp, err := conn.undoCmd("get_time") + if err != nil { + return "", err + } + + // We have received a comma-separated list of hex numbers. + time_parts := strings.Split(resp, ",") + + // First component is bbcount. + bbcount, err := strconv.ParseUint(time_parts[0], 16, 64) + if err != nil { + return "", err + } + + // Second component is PC. + pc, err := strconv.ParseUint(time_parts[1], 16, 64) + if err != nil { + return "", err + } + + // Calculate our percentage through available history. + bbcount_min, bbcount_max, err := undoGetLogExtent(conn) if err != nil { return "", err } - return extent, nil + + progress := uint64(100) + if bbcount_min != bbcount_max { + progress = ((bbcount - bbcount_min) * 100) / (bbcount_max - bbcount_min) + } + + result := fmt.Sprintf("[replaying %d%% %d:0x%x]", progress, bbcount, pc) + return result, nil } From 374f180c44a2a8b3fe7d84f686646aedaf658f7b Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Tue, 6 Jun 2023 22:29:20 +0100 Subject: [PATCH 10/29] Clear stepping breakpoints on process exit. This fixes a bug in which it was not possible to reverse debug after a stepping operation e.g. next encountered the end of recorded history. --- pkg/proc/target_exec.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/proc/target_exec.go b/pkg/proc/target_exec.go index 580d9efd4..fa8677011 100644 --- a/pkg/proc/target_exec.go +++ b/pkg/proc/target_exec.go @@ -107,6 +107,9 @@ func (grp *TargetGroup) Continue() error { // might very well not work. _ = grp.setCurrentThreads(traptgt, trapthread) if pe, ok := contOnceErr.(ErrProcessExited); ok { + // With a replay backend we may still debug after an apparent + // process exit so we still need to clean up our stepping state. + traptgt.ClearSteppingBreakpoints() traptgt.exitStatus = pe.Status } return contOnceErr From 9e6f2e33b3cd2279a568f35b84c5cfced6b4e565 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Wed, 14 Jun 2023 17:07:02 +0100 Subject: [PATCH 11/29] Resolve udbserver path relative to udb path. This ensures that the Undo backend can always find the server when `udb` is on the `PATH`. System-wide installs of UDB don't put the server on `PATH` by default, so this simplifies Delve setup in those cases. --- pkg/proc/gdbserial/undo.go | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 360bf1bb6..47bd82328 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "os/exec" + "path/filepath" "runtime" "strconv" "strings" @@ -14,6 +15,7 @@ import ( "github.com/undoio/delve/pkg/proc" ) +// Get the UDB server filename for the current architecture. func serverFile() (string, error) { switch runtime.GOARCH { case "amd64": @@ -27,8 +29,31 @@ func serverFile() (string, error) { } } +// Get the full path to the UDB server for the current architecture. +func serverPath() (string, error) { + udb_path, err := exec.LookPath("udb") + if err != nil { + return "", err + } + + udb_path_abs, err := filepath.EvalSymlinks(udb_path) + if err != nil { + return "", err + } + + server_file, err := serverFile() + if err != nil { + return "", err + } + + udb_dir_abs := filepath.Dir(udb_path_abs) + cmd_path := filepath.Join(udb_dir_abs, server_file) + + return cmd_path, nil +} + func UndoIsAvailable() error { - server, err := serverFile() + server, err := serverPath() if err != nil { return err } @@ -101,7 +126,7 @@ func UndoReplay(recording string, path string, quiet bool, debugInfoDirs []strin args := make([]string, 0) args = append(args, "--load-file", recording, "--connect-port", port[1:]) - server, err := serverFile() + server, err := serverPath() if err != nil { return nil, err } From 5108c388f8f7160c58c2885d91a5674c65cf1b21 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Mon, 26 Jun 2023 17:46:15 +0100 Subject: [PATCH 12/29] Implement basic progress indicator support in Delve. The error handling here was a bit painful but only needs doing in these two places (for now). --- pkg/proc/gdbserial/gdbserver.go | 53 +++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 763a6f6cf..7d48d1caf 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -807,7 +807,33 @@ const ( debugServerTargetExcBreakpoint = 0x96 ) +// The real work is accomplished in continueOnceWorker, this wrapper just handles udbserver's progress +// indicators. func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) { + if p.conn.isUndoServer { + // Clear interrupt (and enable progress indication) + _, err := p.conn.undoCmd("clear_interrupt") + if err != nil { + return nil, proc.StopUnknown, err + } + } + + trapthread, stopReason, err := p.continueOnceWorker(cctx) + + if p.conn.isUndoServer { + _, reset_err := p.conn.undoCmd("reset_progress_indicator") + if reset_err != nil { + p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) + } + if err == nil { + err = reset_err + } + } + + return trapthread, stopReason, err +} + +func (p *gdbProcess) continueOnceWorker(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) { if p.exited { return nil, proc.StopExited, proc.ErrProcessExited{Pid: p.conn.pid} } @@ -1067,7 +1093,34 @@ func (p *gdbProcess) Detach(kill bool) error { } // Restart will restart the process from the given position. +// The real work is accomplished in restartWorker, this wrapper just handles udbserver's progress +// indicators. func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.Thread, error) { + if p.conn.isUndoServer { + // Clear interrupt (and enable progress indication) + _, err := p.conn.undoCmd("clear_interrupt") + if err != nil { + return nil, err + } + } + + currentThread, err := p.restartWorker(cctx, pos) + + if p.conn.isUndoServer { + _, reset_err := p.conn.undoCmd("reset_progress_indicator") + if reset_err != nil { + p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) + } + if err == nil { + err = reset_err + } + } + + return currentThread, err +} + +// restartWorker will restart the process from the given position. +func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) (proc.Thread, error) { if p.tracedir == "" { return nil, proc.ErrNotRecorded } From 01bae8b62130761c1995aa63c795e7ff785522b6 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Fri, 7 Jul 2023 13:01:35 +0100 Subject: [PATCH 13/29] Separate the parsing and formatting of Undo Engine times. This makes it possible to apply a standard formatting to Undo times from anywhere in the code that requires it - this will later be used to display checkpoint times. --- pkg/proc/gdbserial/undo.go | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 47bd82328..0a53cdb43 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -294,24 +294,39 @@ func undoGetExitCode(conn *gdbConn) (int, error) { return exit_code, nil } -// Fetch a representation of the current time as a string. -func undoWhen(conn *gdbConn) (string, error) { - resp, err := conn.undoCmd("get_time") - if err != nil { - return "", err - } +// Print a bbcount and PC pair in standard Undo time notiation. +func undoTimeString(bbcount uint64, pc uint64) string { + return fmt.Sprintf("%d:0x%x", bbcount, pc) +} +// Parse the udbserver serial-level representation of a time into bbcount and PC. +func undoParseServerTime(resp string) (uint64, uint64, error) { // We have received a comma-separated list of hex numbers. time_parts := strings.Split(resp, ",") // First component is bbcount. bbcount, err := strconv.ParseUint(time_parts[0], 16, 64) if err != nil { - return "", err + return 0, 0, err } // Second component is PC. pc, err := strconv.ParseUint(time_parts[1], 16, 64) + if err != nil { + return 0, 0, err + } + + return bbcount, pc, nil +} + +// Fetch a representation of the current time as a string. +func undoWhen(conn *gdbConn) (string, error) { + resp, err := conn.undoCmd("get_time") + if err != nil { + return "", err + } + + bbcount, pc, err := undoParseServerTime(resp) if err != nil { return "", err } @@ -322,11 +337,12 @@ func undoWhen(conn *gdbConn) (string, error) { return "", err } - progress := uint64(100) + history_perc := uint64(100) if bbcount_min != bbcount_max { - progress = ((bbcount - bbcount_min) * 100) / (bbcount_max - bbcount_min) + history_perc = ((bbcount - bbcount_min) * 100) / (bbcount_max - bbcount_min) } - result := fmt.Sprintf("[replaying %d%% %d:0x%x]", progress, bbcount, pc) + history_perc_fmt := fmt.Sprintf("%d%%", history_perc) + result := fmt.Sprintf("[replaying %s %s]", history_perc_fmt, undoTimeString(bbcount, pc)) return result, nil } From 109a06c83a4e44a3a291d790fbdc10cb6024e380 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Fri, 7 Jul 2023 13:08:36 +0100 Subject: [PATCH 14/29] Fix checkpoints list output to contain human-readable times. --- pkg/proc/gdbserial/gdbserver.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 7d48d1caf..26b4a8b87 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1250,6 +1250,13 @@ func (p *gdbProcess) Checkpoints() ([]proc.Checkpoint, error) { if p.conn.isUndoServer { r := make([]proc.Checkpoint, 0, len(p.localCheckpoints)) for _, cp := range p.localCheckpoints { + // Convert the internal representation of time (which is based on the serial + // protocol level representation) to a human-readable version for display. + bbcount, pc, err := undoParseServerTime(cp.When) + if err != nil { + return nil, err + } + cp.When = undoTimeString(bbcount, pc) r = append(r, cp) } return r, nil From eddce42e8d9cc0e1c44ea4a4b4a63666c4c1dc22 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Mon, 10 Jul 2023 23:43:56 +0100 Subject: [PATCH 15/29] Format bbcount as comma-separated thousands groups. This is for readability and for consistency with the existing UDB convention. --- pkg/proc/gdbserial/undo.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 0a53cdb43..b1cff2ef0 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -296,7 +296,20 @@ func undoGetExitCode(conn *gdbConn) (int, error) { // Print a bbcount and PC pair in standard Undo time notiation. func undoTimeString(bbcount uint64, pc uint64) string { - return fmt.Sprintf("%d:0x%x", bbcount, pc) + var bbcount_groups []string + + // Chop 3 digits at a time from the low-order end of the bbcount string. + var bbcount_rem uint64 + for bbcount_rem = bbcount; bbcount_rem > 1000; bbcount_rem = bbcount_rem / 1000 { + // Format the group with leading zeros. + group := fmt.Sprintf("%03d", bbcount_rem%1000) + bbcount_groups = append([]string{group}, bbcount_groups...) + } + // Finally, add the highest-order group, which has no leading zeros. + bbcount_groups = append([]string{fmt.Sprintf("%d", bbcount_rem)}, bbcount_groups...) + + // Return the comma-separated whole. + return fmt.Sprintf("%s:0x%x", strings.Join(bbcount_groups, ","), pc) } // Parse the udbserver serial-level representation of a time into bbcount and PC. From 76926ebe2be8a47d245d003742055581991c92f9 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Thu, 6 Jul 2023 15:56:59 +0100 Subject: [PATCH 16/29] Add magic "start" and "end" checkpoints for Undo backend. Allow fast navigation to extremes of history. --- pkg/proc/gdbserial/gdbserver.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 26b4a8b87..03e7d0e99 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1144,7 +1144,19 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( p.ctrlC = false - err := p.conn.restart(pos) + var err error + if p.conn.isUndoServer { + switch pos { + case "start": + err = p.conn.restart("") + case "end": + _, err = p.conn.undoCmd("goto_record_mode") + default: + err = p.conn.restart(pos) + } + } else { + err = p.conn.restart(pos) + } if err != nil { return nil, err } From 2b798f985271d269fce44904f30220e115502d9e Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Wed, 12 Jul 2023 11:18:18 +0100 Subject: [PATCH 17/29] Update restart arg parsing to validate start/end and handle times. This changeset adds validation for the `start` / `end` magic arguments to the `restart` command, plus adds parsing for directly-specified bbcounts or bbcount:pc times. Doing the validation early allows us to bail out before the function makes any changes to global state. Parsing time specifications directly allows the user to jump to a time without it having a pre-existing checkpoint. --- pkg/proc/gdbserial/gdbserver.go | 46 ++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 03e7d0e99..ffc458733 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1126,13 +1126,47 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( } // Is this a checkpoint on a server using local checkpoints? - if len(pos) > 1 && pos[:1] == "c" && p.conn.isUndoServer { - cpid, _ := strconv.Atoi(pos[1:]) - checkpoint, exists := p.localCheckpoints[cpid] - if !exists { - return nil, errors.New("Checkpoint not found") + if p.conn.isUndoServer { + // Validate and transform input. + // + // We will accept: + // start | end - magic values for getting to the extremes of history. + // cN - a checkpoint name (a "c" character followed by an integer ID) + // BBCOUNT - an Undo bbcount as a decimal integer (with or without comma- + // separated grouping of digits). + // BBCOUNT:PC - an Undo bbcount, as above, followed by a colon and then a + // program counter value in hex (with leading 0x). + if pos == "start" || pos == "end" { + // Special case values - valid with no extra checking. + } else if len(pos) > 1 && pos[:1] == "c" { + // Validate a checkpoint ID. + cpid, _ := strconv.Atoi(pos[1:]) + checkpoint, exists := p.localCheckpoints[cpid] + if !exists { + return nil, errors.New("Checkpoint not found") + } + pos = checkpoint.When + } else { + // Validate a potential bbcount or precise time. + pos = strings.ReplaceAll(pos, ",", "") + var bbcount, pc uint64 + var err error + if strings.Contains(pos, ":") { + _, err = fmt.Sscanf(pos, "%d:0x%x\n", &bbcount, &pc) + } else if _, err = fmt.Sscanf(pos, "%d\n", &bbcount); err == nil { + // It's a valid bbcount. + pc = 0 + } + + if err != nil { + return nil, errors.New("Could not parse time or checkpoint argument to restart.") + } + + // A representation of the current time, as used by the udbserver serial + // protocol. This matches the format returned by vUDB;get_time and can be + // used as an argument to vUDB;goto_time. + pos = fmt.Sprintf("%x;%x", bbcount, pc) } - pos = checkpoint.When } p.exited = false From 5996cba3116167a85ddd71741e16d54415fd146b Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Thu, 13 Jul 2023 18:26:56 +0100 Subject: [PATCH 18/29] Move "local checkpoint" management code into an Undo session object. --- pkg/proc/gdbserial/gdbserver.go | 83 +++----------------- pkg/proc/gdbserial/undo.go | 135 ++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 73 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index ffc458733..d0e65bccd 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -167,8 +167,8 @@ type gdbProcess struct { onDetach func() // called after a successful detach - localCheckpointLastId int - localCheckpoints map[int]proc.Checkpoint + // State relating to the Undo session - present when conn.isUndoServer is set. + undoSession *undoSession } var _ proc.RecordingManipulationInternal = &gdbProcess{} @@ -242,9 +242,6 @@ func newProcess(process *os.Process) *gdbProcess { gcmdok: true, threadStopInfo: true, process: process, - - localCheckpointLastId: 1, - localCheckpoints: make(map[int]proc.Checkpoint), } switch p.bi.Arch.Name { @@ -1127,45 +1124,10 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( // Is this a checkpoint on a server using local checkpoints? if p.conn.isUndoServer { - // Validate and transform input. - // - // We will accept: - // start | end - magic values for getting to the extremes of history. - // cN - a checkpoint name (a "c" character followed by an integer ID) - // BBCOUNT - an Undo bbcount as a decimal integer (with or without comma- - // separated grouping of digits). - // BBCOUNT:PC - an Undo bbcount, as above, followed by a colon and then a - // program counter value in hex (with leading 0x). - if pos == "start" || pos == "end" { - // Special case values - valid with no extra checking. - } else if len(pos) > 1 && pos[:1] == "c" { - // Validate a checkpoint ID. - cpid, _ := strconv.Atoi(pos[1:]) - checkpoint, exists := p.localCheckpoints[cpid] - if !exists { - return nil, errors.New("Checkpoint not found") - } - pos = checkpoint.When - } else { - // Validate a potential bbcount or precise time. - pos = strings.ReplaceAll(pos, ",", "") - var bbcount, pc uint64 - var err error - if strings.Contains(pos, ":") { - _, err = fmt.Sscanf(pos, "%d:0x%x\n", &bbcount, &pc) - } else if _, err = fmt.Sscanf(pos, "%d\n", &bbcount); err == nil { - // It's a valid bbcount. - pc = 0 - } - - if err != nil { - return nil, errors.New("Could not parse time or checkpoint argument to restart.") - } - - // A representation of the current time, as used by the udbserver serial - // protocol. This matches the format returned by vUDB;get_time and can be - // used as an argument to vUDB;goto_time. - pos = fmt.Sprintf("%x;%x", bbcount, pc) + var err error + pos, err = p.undoSession.resolveUserTime(p, pos) + if err != nil { + return nil, err } } @@ -1180,14 +1142,7 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( var err error if p.conn.isUndoServer { - switch pos { - case "start": - err = p.conn.restart("") - case "end": - _, err = p.conn.undoCmd("goto_record_mode") - default: - err = p.conn.restart(pos) - } + err = p.undoSession.travelToTime(p, pos) } else { err = p.conn.restart(pos) } @@ -1253,14 +1208,7 @@ func (p *gdbProcess) Checkpoint(where string) (int, error) { // Handle locally managed checkpoints first if p.conn.isUndoServer { - cpid := p.localCheckpointLastId - p.localCheckpointLastId++ - when, err := p.conn.undoCmd("get_time") - if err != nil { - return -1, err - } - p.localCheckpoints[cpid] = proc.Checkpoint{ID: cpid, When: when, Where: where} - return cpid, nil + return p.undoSession.createCheckpoint(p, where) } resp, err := p.conn.qRRCmd("checkpoint", where) @@ -1294,18 +1242,7 @@ func (p *gdbProcess) Checkpoints() ([]proc.Checkpoint, error) { // Handle locally managed checkpoints first if p.conn.isUndoServer { - r := make([]proc.Checkpoint, 0, len(p.localCheckpoints)) - for _, cp := range p.localCheckpoints { - // Convert the internal representation of time (which is based on the serial - // protocol level representation) to a human-readable version for display. - bbcount, pc, err := undoParseServerTime(cp.When) - if err != nil { - return nil, err - } - cp.When = undoTimeString(bbcount, pc) - r = append(r, cp) - } - return r, nil + return p.undoSession.getCheckpoints() } resp, err := p.conn.qRRCmd("info checkpoints") @@ -1341,7 +1278,7 @@ func (p *gdbProcess) ClearCheckpoint(id int) error { // Handle locally managed checkpoints first if p.conn.isUndoServer { - delete(p.localCheckpoints, id) + p.undoSession.deleteCheckpoint(id) // We don't care if it didn't exist return nil } diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index b1cff2ef0..7683322bd 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -2,6 +2,7 @@ package gdbserial import ( "bytes" + "errors" "fmt" "io/ioutil" "os" @@ -15,6 +16,136 @@ import ( "github.com/undoio/delve/pkg/proc" ) +// State relating to an Undo "session" - used to correctly interpret and handle time-travel +// operations on a gdbProcess when running with the Undo backend. +// +// See also: isUndoServer on the gdbConn structure - when that is set, the undoSession member on the +// gdbProcess structure should point to an instance of this structure. +type undoSession struct { + checkpointLastId int // For allocating checkpoint IDs + checkpoints map[int]proc.Checkpoint // Map checkpoint IDs to Delve's proc.Checkpoint +} + +// Create a new undoSession structure. +func newUndoSession() *undoSession { + return &undoSession{ + checkpointLastId: 1, + checkpoints: make(map[int]proc.Checkpoint), + } +} + +// Create a Delve checkpoint structure at the current time, with the supplied note. +func (uc *undoSession) createCheckpoint(p *gdbProcess, where string) (int, error) { + cpid := uc.checkpointLastId + uc.checkpointLastId++ + when, err := p.conn.undoCmd("get_time") + if err != nil { + return -1, err + } + uc.checkpoints[cpid] = proc.Checkpoint{ID: cpid, When: when, Where: where} + return cpid, nil +} + +// Look up a Delve checkpoint structure by name. +func (uc *undoSession) lookupCheckpoint(pos string) (proc.Checkpoint, error) { + if len(pos) == 0 { + panic("empty checkpoint name") + } + if pos[0] != 'c' { + panic("invalid checkpoint name") + } + cpid, _ := strconv.Atoi(pos[1:]) + checkpoint, exists := uc.checkpoints[cpid] + if !exists { + return proc.Checkpoint{}, errors.New("checkpoint not found") + } + return checkpoint, nil +} + +// Delete a Delve checkpoint structure from our tracking. +func (uc *undoSession) deleteCheckpoint(id int) { + delete(uc.checkpoints, id) +} + +// Fetch all Delve checkpoint structures and return an array for user display (with the When field +// rewritten in human readable form). +func (uc *undoSession) getCheckpoints() ([]proc.Checkpoint, error) { + r := make([]proc.Checkpoint, 0, len(uc.checkpoints)) + for _, cp := range uc.checkpoints { + // Convert the internal representation of time (which is based on the serial + // protocol level representation) to a human-readable version for display. + bbcount, pc, err := undoParseServerTime(cp.When) + if err != nil { + return nil, err + } + cp.When = undoTimeString(bbcount, pc) + r = append(r, cp) + } + return r, nil +} + +// Transform a user-specified time into a canonical form. The returned string has been validated +// (unknown checkpoint IDs, misspelt magic values and incorrectly formatted times will be rejected) +// and is suitable for passing to travelToTime. +func (uc *undoSession) resolveUserTime(p *gdbProcess, pos string) (string, error) { + // Validate and transform input. + // + // We will accept: + // start | end - magic values for getting to the extremes of history. + // cN - a checkpoint name (a "c" character followed by an integer ID) + // BBCOUNT - an Undo bbcount as a decimal integer (with or without comma-separated + // grouping of digits). + // BBCOUNT:PC - an Undo bbcount, as above, followed by a colon and then a program + // counter value in hex (with leading 0x). + if pos == "start" || pos == "end" { + // Special case values - valid with no extra checking. + } else if len(pos) > 1 && pos[:1] == "c" { + // Validate a checkpoint ID. + checkpoint, err := uc.lookupCheckpoint(pos) + if err != nil { + return "", err + } + pos = checkpoint.When + } else { + // Validate a potential bbcount or precise time. + pos = strings.ReplaceAll(pos, ",", "") + var bbcount, pc uint64 + var err error + if strings.Contains(pos, ":") { + _, err = fmt.Sscanf(pos, "%d:0x%x\n", &bbcount, &pc) + } else if _, err = fmt.Sscanf(pos, "%d\n", &bbcount); err == nil { + // It's a valid bbcount. + pc = 0 + } + + if err != nil { + return "", errors.New("could not parse time or checkpoint argument to restart.") + } + + // A representation of the current time, as used by the udbserver serial protocol. + // This matches the format returned by vUDB;get_time and can be used as an argument + // to vUDB;goto_time. + pos = fmt.Sprintf("%x;%x", bbcount, pc) + } + + return pos, nil +} + +// Move the replay process to the a point in time. The "pos" argument should be obtained by calling +// resolveUserTime to ensure that it is valid. +func (uc *undoSession) travelToTime(p *gdbProcess, pos string) error { + var err error + switch pos { + case "start": + err = p.conn.restart("") + case "end": + _, err = p.conn.undoCmd("goto_record_mode") + default: + err = p.conn.restart(pos) + } + return err +} + // Get the UDB server filename for the current architecture. func serverFile() (string, error) { switch runtime.GOARCH { @@ -156,6 +287,10 @@ func UndoReplay(recording string, path string, quiet bool, debugInfoDirs []strin // to the GDB mapping, not the Linux mapping (the binutils-gdb repo // defines the GDB mapping in include/gdb/signals.def) p.conn.isUndoServer = true + + // Create storage for Undo checkpoints, which (unlike rr) aren't stored in the server. + p.undoSession = newUndoSession() + return tgt, nil } From 918ee54583d154e686b575fe79bfefcf36edec0c Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Fri, 14 Jul 2023 13:27:46 +0100 Subject: [PATCH 19/29] Implement save and load of checkpoints with an Undo session file. This is made compatible with UDB's bookmarks by using the UDB bookmark name as the "Note" field in Delve. To save Delve checkpoints, the "Note" must be made unique, so as to be a valid bookmark name in UDB. --- pkg/proc/gdbserial/gdbserver.go | 2 +- pkg/proc/gdbserial/undo.go | 191 +++++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 2 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index d0e65bccd..76acde397 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1278,7 +1278,7 @@ func (p *gdbProcess) ClearCheckpoint(id int) error { // Handle locally managed checkpoints first if p.conn.isUndoServer { - p.undoSession.deleteCheckpoint(id) + p.undoSession.deleteCheckpoint(p, id) // We don't care if it didn't exist return nil } diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 7683322bd..4eb029423 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -2,13 +2,16 @@ package gdbserial import ( "bytes" + "encoding/json" "errors" "fmt" "io/ioutil" "os" "os/exec" + "os/user" "path/filepath" "runtime" + "sort" "strconv" "strings" "syscall" @@ -19,6 +22,9 @@ import ( // State relating to an Undo "session" - used to correctly interpret and handle time-travel // operations on a gdbProcess when running with the Undo backend. // +// The current checkpoints are persisted to disk in an "Undo session file" via the save() method. +// They are restored via the load() method. +// // See also: isUndoServer on the gdbConn structure - when that is set, the undoSession member on the // gdbProcess structure should point to an instance of this structure. type undoSession struct { @@ -34,8 +40,44 @@ func newUndoSession() *undoSession { } } +// Validate a checkpoint note to ensure easy interopability with UDB bookmarks. +// Returns nil (no error) if a checkpoint is validated successfully. +func validateCheckpointNote(where string) error { + if where == "" { + panic("checkpoint note expectedly empty.") + } + + // Perform matching checking to UDB's bookmark creation code, to ensure Delve notes + // translate properly into UDB bookmarks when we save the session. + // + // (compare Bookmarks._verify_name() in the UDB Python code) + firstChar := where[0:1] + if firstChar == " " { + return errors.New("checkpoint note must not start with a space.") + } else if _, err := strconv.Atoi(firstChar); err == nil { + return errors.New("checkpoint note must not start with a digit.") + } else if firstChar == "," || firstChar == "-" || firstChar == "$" { + return fmt.Errorf("checkpoint note must not start with character: %c", where[0]) + } else { + firstWord := strings.Split(where, " ")[0] + reserved := []string{"annotation", "bookmark", "end", "event", "inferior", "pc", + "redo", "start", "time", "undo", "wallclock"} + for _, reservedWord := range reserved { + if firstWord == reservedWord { + return fmt.Errorf("checkpoint note must not start with reserved word: %s", reservedWord) + } + } + } + + return nil +} + // Create a Delve checkpoint structure at the current time, with the supplied note. func (uc *undoSession) createCheckpoint(p *gdbProcess, where string) (int, error) { + err := validateCheckpointNote(where) + if err != nil { + return -1, err + } cpid := uc.checkpointLastId uc.checkpointLastId++ when, err := p.conn.undoCmd("get_time") @@ -43,6 +85,7 @@ func (uc *undoSession) createCheckpoint(p *gdbProcess, where string) (int, error return -1, err } uc.checkpoints[cpid] = proc.Checkpoint{ID: cpid, When: when, Where: where} + uc.save(p) return cpid, nil } @@ -63,8 +106,9 @@ func (uc *undoSession) lookupCheckpoint(pos string) (proc.Checkpoint, error) { } // Delete a Delve checkpoint structure from our tracking. -func (uc *undoSession) deleteCheckpoint(id int) { +func (uc *undoSession) deleteCheckpoint(p *gdbProcess, id int) { delete(uc.checkpoints, id) + uc.save(p) } // Fetch all Delve checkpoint structures and return an array for user display (with the When field @@ -84,6 +128,148 @@ func (uc *undoSession) getCheckpoints() ([]proc.Checkpoint, error) { return r, nil } +// Represents a single serialised bookmark in our session file format. +type bookmarkTime struct { + Bbcount uint64 `json:"bbcount"` + Pc uint64 `json:"pc"` +} + +// Represents the overall structure of our session file format. +type session struct { + Bookmarks map[string]bookmarkTime `json:"bookmarks"` +} + +// Get the path to the UDB session file for the current recording. +func getSessionPath(p *gdbProcess) (string, error) { + user, err := user.Current() + if err != nil { + return "", err + } + recording_ids, err := p.conn.undoCmd("get_recording_ids") + if err != nil { + return "", err + } + uuids := strings.Split(recording_ids, ";") + if len(uuids) != 3 || uuids[1] == "" { + panic("unexpected response from get_recording_ids") + } + + // This directory stores sessions. + xdg_data_dir, present := os.LookupEnv("XDG_DATA_HOME") + if !present { + xdg_data_dir = filepath.Join(user.HomeDir, ".local", "share") + } + undo_sessions_dir := filepath.Join(xdg_data_dir, "undo", "sessions") + + err = os.MkdirAll(undo_sessions_dir, 0755) + if err != nil { + return "", err + } + + file := filepath.Join(undo_sessions_dir, string(uuids[1])+".json") + + return file, nil +} + +// Load the UDB session file (if it exists) for the current recording. +func (uc *undoSession) load(p *gdbProcess) error { + path, err := getSessionPath(p) + if err != nil { + return err + } + + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + decoder := json.NewDecoder(file) + decoder.DisallowUnknownFields() + + var s session + err = decoder.Decode(&s) + if err != nil { + return err + } + + // Clear out the session data. + *uc = *newUndoSession() + + // Translate the loaded Undo bookmarks into Delve checkpoints. + for name, position := range s.Bookmarks { + cpid := uc.checkpointLastId + uc.checkpointLastId++ + uc.checkpoints[cpid] = proc.Checkpoint{ + ID: cpid, + When: fmt.Sprintf("%x,%x", position.Bbcount, position.Pc), + Where: name, + } + } + + return err +} + +// Save the session file for the current recording. +func (uc *undoSession) save(p *gdbProcess) error { + // Translate Delve checkpoints into Undo bookmarks. + var s session + s.Bookmarks = make(map[string]bookmarkTime) + + // Local copy of the checkopints. + var checkpoints []proc.Checkpoint + for _, cp := range uc.checkpoints { + checkpoints = append(checkpoints, cp) + } + // Sort the checkpoints by descending note length - this is to avoid adding a suffix to a + // entries that we've already added a suffix to. e.g. if we've previously saved this session + // with a duplicated checkpoint note called "test" then we'll have extended one to + // "test-0". If the user adds "test" again, we want to rename that to "test-1" rather than + // creating a "test-0-0". + sort.Slice(checkpoints, func(i, j int) bool { + // This is a "Less" function that sorts in descending order of string length. + return len(checkpoints[i].Where) > len(checkpoints[j].Where) + }) + + // Iterate through sorted checkpoints to eliminate duplicates. + for _, cp := range checkpoints { + // Ensure that notes are made unique before saving - UDB expects bookmark names to + // be unique. + base_name := cp.Where + name := base_name + for i := 0; s.Bookmarks[name] != (bookmarkTime{}); i++ { + name = fmt.Sprintf("%s-%d", base_name, i) + } + + var time bookmarkTime + _, err := fmt.Sscanf(cp.When, "%x,%x", &time.Bbcount, &time.Pc) + if err != nil { + return err + } + s.Bookmarks[name] = time + } + + path, err := getSessionPath(p) + if err != nil { + return err + } + + file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + return err + } + defer file.Close() + + encoder := json.NewEncoder(file) + encoder.SetIndent("", " ") + err = encoder.Encode(&s) + if err != nil { + return err + } + + return err +} + // Transform a user-specified time into a canonical form. The returned string has been validated // (unknown checkpoint IDs, misspelt magic values and incorrectly formatted times will be rejected) // and is suitable for passing to travelToTime. @@ -291,6 +477,9 @@ func UndoReplay(recording string, path string, quiet bool, debugInfoDirs []strin // Create storage for Undo checkpoints, which (unlike rr) aren't stored in the server. p.undoSession = newUndoSession() + // Load the session details if possible (discarding errors, which are non-fatal). + _ = p.undoSession.load(p) + return tgt, nil } From 9420aa0f2c469b4fd6112852836dcfbe41802301 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Thu, 27 Jul 2023 21:02:11 +0100 Subject: [PATCH 20/29] Fix naming of checkpointLastId -> checkpointNextId. This is in line with the actual use of this variable. --- pkg/proc/gdbserial/undo.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 4eb029423..3a2fd858e 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -28,14 +28,14 @@ import ( // See also: isUndoServer on the gdbConn structure - when that is set, the undoSession member on the // gdbProcess structure should point to an instance of this structure. type undoSession struct { - checkpointLastId int // For allocating checkpoint IDs + checkpointNextId int // For allocating checkpoint IDs checkpoints map[int]proc.Checkpoint // Map checkpoint IDs to Delve's proc.Checkpoint } // Create a new undoSession structure. func newUndoSession() *undoSession { return &undoSession{ - checkpointLastId: 1, + checkpointNextId: 1, checkpoints: make(map[int]proc.Checkpoint), } } @@ -78,8 +78,8 @@ func (uc *undoSession) createCheckpoint(p *gdbProcess, where string) (int, error if err != nil { return -1, err } - cpid := uc.checkpointLastId - uc.checkpointLastId++ + cpid := uc.checkpointNextId + uc.checkpointNextId++ when, err := p.conn.undoCmd("get_time") if err != nil { return -1, err @@ -198,8 +198,8 @@ func (uc *undoSession) load(p *gdbProcess) error { // Translate the loaded Undo bookmarks into Delve checkpoints. for name, position := range s.Bookmarks { - cpid := uc.checkpointLastId - uc.checkpointLastId++ + cpid := uc.checkpointNextId + uc.checkpointNextId++ uc.checkpoints[cpid] = proc.Checkpoint{ ID: cpid, When: fmt.Sprintf("%x,%x", position.Bbcount, position.Pc), From fb640650a4b681d59d79d7909f813de1955cbac5 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Thu, 27 Jul 2023 22:31:52 +0100 Subject: [PATCH 21/29] Fix bug in handling zero-argument "restart" command. Previously we were trying to interpret an empty command as a time, which was not correct. --- pkg/proc/gdbserial/undo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 3a2fd858e..f4e8f8f9e 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -292,7 +292,7 @@ func (uc *undoSession) resolveUserTime(p *gdbProcess, pos string) (string, error return "", err } pos = checkpoint.When - } else { + } else if pos != "" { // Validate a potential bbcount or precise time. pos = strings.ReplaceAll(pos, ",", "") var bbcount, pc uint64 From d24d0e0a94b6b77735e30fee9e4fe474fc49ca9f Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Tue, 25 Jul 2023 15:09:33 +0100 Subject: [PATCH 22/29] Fix a bug with inferior calls by tracking volatile mode state. During inferior calls we are in volatile mode and should not attempt to use progress indicators. By tracking volatile mode we are able to correctly skip progress indicator commands. --- pkg/proc/gdbserial/gdbserver.go | 21 ++++++++++++--------- pkg/proc/gdbserial/undo.go | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 76acde397..2c7c38c41 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -807,7 +807,7 @@ const ( // The real work is accomplished in continueOnceWorker, this wrapper just handles udbserver's progress // indicators. func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) { - if p.conn.isUndoServer { + if p.conn.isUndoServer && !p.undoSession.volatile { // Clear interrupt (and enable progress indication) _, err := p.conn.undoCmd("clear_interrupt") if err != nil { @@ -817,7 +817,7 @@ func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, trapthread, stopReason, err := p.continueOnceWorker(cctx) - if p.conn.isUndoServer { + if p.conn.isUndoServer && !p.undoSession.volatile { _, reset_err := p.conn.undoCmd("reset_progress_indicator") if reset_err != nil { p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) @@ -1094,6 +1094,11 @@ func (p *gdbProcess) Detach(kill bool) error { // indicators. func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.Thread, error) { if p.conn.isUndoServer { + if p.undoSession.volatile { + // We should only be in volatile mode during an inferior call, so this case + // should not be possible. + panic("attempted to restart in volatile mode.") + } // Clear interrupt (and enable progress indication) _, err := p.conn.undoCmd("clear_interrupt") if err != nil { @@ -1104,6 +1109,10 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T currentThread, err := p.restartWorker(cctx, pos) if p.conn.isUndoServer { + if p.undoSession.volatile { + // Restart should not change our volatile mode state. + panic("in volatile mode after restart.") + } _, reset_err := p.conn.undoCmd("reset_progress_indicator") if reset_err != nil { p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) @@ -1327,13 +1336,7 @@ func (p *gdbProcess) StartCallInjection() (func(), error) { } if p.conn.isUndoServer { - _, err := p.conn.undoCmd("set_debuggee_volatile", "1") - if err != nil { - return nil, err - } - return func() { - _, _ = p.conn.undoCmd("set_debuggee_volatile", "0") - }, nil + return p.undoSession.activateVolatile(p) } // Normally it's impossible to inject function calls in a recorded target diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index f4e8f8f9e..692bb19c7 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -30,6 +30,7 @@ import ( type undoSession struct { checkpointNextId int // For allocating checkpoint IDs checkpoints map[int]proc.Checkpoint // Map checkpoint IDs to Delve's proc.Checkpoint + volatile bool // Is the Undo connection currently in volatile mode? } // Create a new undoSession structure. @@ -37,6 +38,7 @@ func newUndoSession() *undoSession { return &undoSession{ checkpointNextId: 1, checkpoints: make(map[int]proc.Checkpoint), + volatile: false, } } @@ -332,6 +334,25 @@ func (uc *undoSession) travelToTime(p *gdbProcess, pos string) error { return err } +// Activate volatile mode. +// On success, returns a callback that can be used to deactivate volatile mode (and a nil error). +// The deactivate callback should be used before volatile is next activated, since volatile mode +// does not support nesting. +func (uc *undoSession) activateVolatile(p *gdbProcess) (func(), error) { + if uc.volatile { + panic("tried to activate volatile mode when already active.") + } + _, err := p.conn.undoCmd("set_debuggee_volatile", "1") + if err != nil { + return nil, err + } + uc.volatile = true + return func() { + uc.volatile = false + _, _ = p.conn.undoCmd("set_debuggee_volatile", "0") + }, nil +} + // Get the UDB server filename for the current architecture. func serverFile() (string, error) { switch runtime.GOARCH { From c25e70b8ea8f7f3ee2766f3766e0729fbefbfaa9 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Tue, 1 Aug 2023 23:24:10 +0100 Subject: [PATCH 23/29] Consistently act on a gdbConn in the undoSession layer. This layer doesn't need to concern itself with gdbProcess structures for now. --- pkg/proc/gdbserial/gdbserver.go | 10 ++++---- pkg/proc/gdbserial/undo.go | 42 ++++++++++++++++----------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 2c7c38c41..bc6f10c77 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -1134,7 +1134,7 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( // Is this a checkpoint on a server using local checkpoints? if p.conn.isUndoServer { var err error - pos, err = p.undoSession.resolveUserTime(p, pos) + pos, err = p.undoSession.resolveUserTime(pos) if err != nil { return nil, err } @@ -1151,7 +1151,7 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( var err error if p.conn.isUndoServer { - err = p.undoSession.travelToTime(p, pos) + err = p.undoSession.travelToTime(&p.conn, pos) } else { err = p.conn.restart(pos) } @@ -1217,7 +1217,7 @@ func (p *gdbProcess) Checkpoint(where string) (int, error) { // Handle locally managed checkpoints first if p.conn.isUndoServer { - return p.undoSession.createCheckpoint(p, where) + return p.undoSession.createCheckpoint(&p.conn, where) } resp, err := p.conn.qRRCmd("checkpoint", where) @@ -1287,7 +1287,7 @@ func (p *gdbProcess) ClearCheckpoint(id int) error { // Handle locally managed checkpoints first if p.conn.isUndoServer { - p.undoSession.deleteCheckpoint(p, id) + p.undoSession.deleteCheckpoint(&p.conn, id) // We don't care if it didn't exist return nil } @@ -1336,7 +1336,7 @@ func (p *gdbProcess) StartCallInjection() (func(), error) { } if p.conn.isUndoServer { - return p.undoSession.activateVolatile(p) + return p.undoSession.activateVolatile(&p.conn) } // Normally it's impossible to inject function calls in a recorded target diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 692bb19c7..6ec9cca8c 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -20,7 +20,7 @@ import ( ) // State relating to an Undo "session" - used to correctly interpret and handle time-travel -// operations on a gdbProcess when running with the Undo backend. +// operations on a gdbConn when running with the Undo backend. // // The current checkpoints are persisted to disk in an "Undo session file" via the save() method. // They are restored via the load() method. @@ -75,19 +75,19 @@ func validateCheckpointNote(where string) error { } // Create a Delve checkpoint structure at the current time, with the supplied note. -func (uc *undoSession) createCheckpoint(p *gdbProcess, where string) (int, error) { +func (uc *undoSession) createCheckpoint(conn *gdbConn, where string) (int, error) { err := validateCheckpointNote(where) if err != nil { return -1, err } cpid := uc.checkpointNextId uc.checkpointNextId++ - when, err := p.conn.undoCmd("get_time") + when, err := conn.undoCmd("get_time") if err != nil { return -1, err } uc.checkpoints[cpid] = proc.Checkpoint{ID: cpid, When: when, Where: where} - uc.save(p) + uc.save(conn) return cpid, nil } @@ -108,9 +108,9 @@ func (uc *undoSession) lookupCheckpoint(pos string) (proc.Checkpoint, error) { } // Delete a Delve checkpoint structure from our tracking. -func (uc *undoSession) deleteCheckpoint(p *gdbProcess, id int) { +func (uc *undoSession) deleteCheckpoint(conn *gdbConn, id int) { delete(uc.checkpoints, id) - uc.save(p) + uc.save(conn) } // Fetch all Delve checkpoint structures and return an array for user display (with the When field @@ -142,12 +142,12 @@ type session struct { } // Get the path to the UDB session file for the current recording. -func getSessionPath(p *gdbProcess) (string, error) { +func getSessionPath(conn *gdbConn) (string, error) { user, err := user.Current() if err != nil { return "", err } - recording_ids, err := p.conn.undoCmd("get_recording_ids") + recording_ids, err := conn.undoCmd("get_recording_ids") if err != nil { return "", err } @@ -174,8 +174,8 @@ func getSessionPath(p *gdbProcess) (string, error) { } // Load the UDB session file (if it exists) for the current recording. -func (uc *undoSession) load(p *gdbProcess) error { - path, err := getSessionPath(p) +func (uc *undoSession) load(conn *gdbConn) error { + path, err := getSessionPath(conn) if err != nil { return err } @@ -213,7 +213,7 @@ func (uc *undoSession) load(p *gdbProcess) error { } // Save the session file for the current recording. -func (uc *undoSession) save(p *gdbProcess) error { +func (uc *undoSession) save(conn *gdbConn) error { // Translate Delve checkpoints into Undo bookmarks. var s session s.Bookmarks = make(map[string]bookmarkTime) @@ -251,7 +251,7 @@ func (uc *undoSession) save(p *gdbProcess) error { s.Bookmarks[name] = time } - path, err := getSessionPath(p) + path, err := getSessionPath(conn) if err != nil { return err } @@ -275,7 +275,7 @@ func (uc *undoSession) save(p *gdbProcess) error { // Transform a user-specified time into a canonical form. The returned string has been validated // (unknown checkpoint IDs, misspelt magic values and incorrectly formatted times will be rejected) // and is suitable for passing to travelToTime. -func (uc *undoSession) resolveUserTime(p *gdbProcess, pos string) (string, error) { +func (uc *undoSession) resolveUserTime(pos string) (string, error) { // Validate and transform input. // // We will accept: @@ -321,15 +321,15 @@ func (uc *undoSession) resolveUserTime(p *gdbProcess, pos string) (string, error // Move the replay process to the a point in time. The "pos" argument should be obtained by calling // resolveUserTime to ensure that it is valid. -func (uc *undoSession) travelToTime(p *gdbProcess, pos string) error { +func (uc *undoSession) travelToTime(conn *gdbConn, pos string) error { var err error switch pos { case "start": - err = p.conn.restart("") + err = conn.restart("") case "end": - _, err = p.conn.undoCmd("goto_record_mode") + _, err = conn.undoCmd("goto_record_mode") default: - err = p.conn.restart(pos) + err = conn.restart(pos) } return err } @@ -338,18 +338,18 @@ func (uc *undoSession) travelToTime(p *gdbProcess, pos string) error { // On success, returns a callback that can be used to deactivate volatile mode (and a nil error). // The deactivate callback should be used before volatile is next activated, since volatile mode // does not support nesting. -func (uc *undoSession) activateVolatile(p *gdbProcess) (func(), error) { +func (uc *undoSession) activateVolatile(conn *gdbConn) (func(), error) { if uc.volatile { panic("tried to activate volatile mode when already active.") } - _, err := p.conn.undoCmd("set_debuggee_volatile", "1") + _, err := conn.undoCmd("set_debuggee_volatile", "1") if err != nil { return nil, err } uc.volatile = true return func() { uc.volatile = false - _, _ = p.conn.undoCmd("set_debuggee_volatile", "0") + _, _ = conn.undoCmd("set_debuggee_volatile", "0") }, nil } @@ -499,7 +499,7 @@ func UndoReplay(recording string, path string, quiet bool, debugInfoDirs []strin p.undoSession = newUndoSession() // Load the session details if possible (discarding errors, which are non-fatal). - _ = p.undoSession.load(p) + _ = p.undoSession.load(&p.conn) return tgt, nil } From 7a397d97c7e7164d772785f101c4e0543eff6dba Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Tue, 1 Aug 2023 23:32:25 +0100 Subject: [PATCH 24/29] Eliminate separate isUndoServer boolean. Move undoSession struct down to the gdbConn level. --- pkg/proc/gdbserial/gdbserver.go | 45 +++++++++++++--------------- pkg/proc/gdbserial/gdbserver_conn.go | 7 +++-- pkg/proc/gdbserial/undo.go | 18 +++++------ 3 files changed, 32 insertions(+), 38 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index bc6f10c77..4f1656c7f 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -166,9 +166,6 @@ type gdbProcess struct { waitChan chan *os.ProcessState onDetach func() // called after a successful detach - - // State relating to the Undo session - present when conn.isUndoServer is set. - undoSession *undoSession } var _ proc.RecordingManipulationInternal = &gdbProcess{} @@ -807,7 +804,7 @@ const ( // The real work is accomplished in continueOnceWorker, this wrapper just handles udbserver's progress // indicators. func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) { - if p.conn.isUndoServer && !p.undoSession.volatile { + if p.conn.undoSession != nil && !p.conn.undoSession.volatile { // Clear interrupt (and enable progress indication) _, err := p.conn.undoCmd("clear_interrupt") if err != nil { @@ -817,7 +814,7 @@ func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, trapthread, stopReason, err := p.continueOnceWorker(cctx) - if p.conn.isUndoServer && !p.undoSession.volatile { + if p.conn.undoSession != nil && !p.conn.undoSession.volatile { _, reset_err := p.conn.undoCmd("reset_progress_indicator") if reset_err != nil { p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) @@ -897,7 +894,7 @@ continueLoop: p.almostExited = true exit_code := 0 - if p.conn.isUndoServer { + if p.conn.undoSession != nil { // Retrieve the exit code of the recorded process (if applicable) // from udbserver. exit_code, err = undoGetExitCode(&p.conn) @@ -1093,8 +1090,8 @@ func (p *gdbProcess) Detach(kill bool) error { // The real work is accomplished in restartWorker, this wrapper just handles udbserver's progress // indicators. func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.Thread, error) { - if p.conn.isUndoServer { - if p.undoSession.volatile { + if p.conn.undoSession != nil { + if p.conn.undoSession.volatile { // We should only be in volatile mode during an inferior call, so this case // should not be possible. panic("attempted to restart in volatile mode.") @@ -1108,8 +1105,8 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T currentThread, err := p.restartWorker(cctx, pos) - if p.conn.isUndoServer { - if p.undoSession.volatile { + if p.conn.undoSession != nil { + if p.conn.undoSession.volatile { // Restart should not change our volatile mode state. panic("in volatile mode after restart.") } @@ -1132,9 +1129,9 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( } // Is this a checkpoint on a server using local checkpoints? - if p.conn.isUndoServer { + if p.conn.undoSession != nil { var err error - pos, err = p.undoSession.resolveUserTime(pos) + pos, err = p.conn.undoSession.resolveUserTime(pos) if err != nil { return nil, err } @@ -1150,8 +1147,8 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( p.ctrlC = false var err error - if p.conn.isUndoServer { - err = p.undoSession.travelToTime(&p.conn, pos) + if p.conn.undoSession != nil { + err = p.conn.undoSession.travelToTime(&p.conn, pos) } else { err = p.conn.restart(pos) } @@ -1161,7 +1158,7 @@ func (p *gdbProcess) restartWorker(cctx *proc.ContinueOnceContext, pos string) ( // for some reason we have to send a vCont;c after a vRun to make rr behave // properly, because that's what gdb does. - if !p.conn.isUndoServer { + if p.conn.undoSession == nil { _, err = p.conn.resume(cctx, nil, nil) if err != nil { return nil, err @@ -1189,7 +1186,7 @@ func (p *gdbProcess) When() (string, error) { return "", proc.ErrNotRecorded } result := "" - if p.conn.isUndoServer { + if p.conn.undoSession != nil { when, err := undoWhen(&p.conn) if err != nil { return "", err @@ -1216,8 +1213,8 @@ func (p *gdbProcess) Checkpoint(where string) (int, error) { } // Handle locally managed checkpoints first - if p.conn.isUndoServer { - return p.undoSession.createCheckpoint(&p.conn, where) + if p.conn.undoSession != nil { + return p.conn.undoSession.createCheckpoint(&p.conn, where) } resp, err := p.conn.qRRCmd("checkpoint", where) @@ -1250,8 +1247,8 @@ func (p *gdbProcess) Checkpoints() ([]proc.Checkpoint, error) { } // Handle locally managed checkpoints first - if p.conn.isUndoServer { - return p.undoSession.getCheckpoints() + if p.conn.undoSession != nil { + return p.conn.undoSession.getCheckpoints() } resp, err := p.conn.qRRCmd("info checkpoints") @@ -1286,8 +1283,8 @@ func (p *gdbProcess) ClearCheckpoint(id int) error { } // Handle locally managed checkpoints first - if p.conn.isUndoServer { - p.undoSession.deleteCheckpoint(&p.conn, id) + if p.conn.undoSession != nil { + p.conn.undoSession.deleteCheckpoint(&p.conn, id) // We don't care if it didn't exist return nil } @@ -1335,8 +1332,8 @@ func (p *gdbProcess) StartCallInjection() (func(), error) { return nil, ErrStartCallInjectionBackwards } - if p.conn.isUndoServer { - return p.undoSession.activateVolatile(&p.conn) + if p.conn.undoSession != nil { + return p.conn.undoSession.activateVolatile(&p.conn) } // Normally it's impossible to inject function calls in a recorded target diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go index 9dab7a8d4..5002c875b 100644 --- a/pkg/proc/gdbserial/gdbserver_conn.go +++ b/pkg/proc/gdbserial/gdbserver_conn.go @@ -48,7 +48,8 @@ type gdbConn struct { useXcmd bool // forces writeMemory to use the 'X' command - isUndoServer bool // true if using an Undo backend + // State relating to the Undo session - non-nil when using an Undo backend. + undoSession *undoSession log logflags.Logger } @@ -806,7 +807,7 @@ func (conn *gdbConn) parseStopPacket(resp []byte, threadID string, tu *threadUpd } } - if conn.isUndoServer { + if conn.undoSession != nil { // Transform packet, if necessary, for instance at the end of time. sp, err = undoHandleStopPacket(conn, sp) if err != nil { @@ -1143,7 +1144,7 @@ func (conn *gdbConn) threadStopInfo(threadID string) (sp stopPacket, err error) func (conn *gdbConn) restart(pos string) error { conn.outbuf.Reset() - if conn.isUndoServer { + if conn.undoSession != nil { if pos != "" { fmt.Fprintf(&conn.outbuf, "$vUDB;goto_time;%s", pos) } else { diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 6ec9cca8c..2527aab5d 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -24,9 +24,6 @@ import ( // // The current checkpoints are persisted to disk in an "Undo session file" via the save() method. // They are restored via the load() method. -// -// See also: isUndoServer on the gdbConn structure - when that is set, the undoSession member on the -// gdbProcess structure should point to an instance of this structure. type undoSession struct { checkpointNextId int // For allocating checkpoint IDs checkpoints map[int]proc.Checkpoint // Map checkpoint IDs to Delve's proc.Checkpoint @@ -490,16 +487,15 @@ func UndoReplay(recording string, path string, quiet bool, debugInfoDirs []strin return nil, err } - // set to cause gdbserver.go to treat incoming signal numbers according - // to the GDB mapping, not the Linux mapping (the binutils-gdb repo - // defines the GDB mapping in include/gdb/signals.def) - p.conn.isUndoServer = true - - // Create storage for Undo checkpoints, which (unlike rr) aren't stored in the server. - p.undoSession = newUndoSession() + // Create storage for Undo-related state. + // + // This being non-nil indicates the use of an Undo backend, which selects alternative + // implementations for various functions and handles certain events (such as + // gdbserial stop packets) differently. + p.conn.undoSession = newUndoSession() // Load the session details if possible (discarding errors, which are non-fatal). - _ = p.undoSession.load(&p.conn) + _ = p.conn.undoSession.load(&p.conn) return tgt, nil } From 97de217c3ab566a9d46a917e42caa30549a3f76c Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Tue, 1 Aug 2023 23:43:14 +0100 Subject: [PATCH 25/29] Move Undo's time travelling out of restart and into our module. The current implementation of `restart()` is trying to fit us into the model used by `rr` but it's not a very natural fit. It's also convenient to concentrate our code in `undo.go` where possible, since we're still maintaining a fork. --- pkg/proc/gdbserial/gdbserver_conn.go | 20 +------------------- pkg/proc/gdbserial/undo.go | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go index 5002c875b..05776d398 100644 --- a/pkg/proc/gdbserial/gdbserver_conn.go +++ b/pkg/proc/gdbserial/gdbserver_conn.go @@ -1145,25 +1145,7 @@ func (conn *gdbConn) restart(pos string) error { conn.outbuf.Reset() if conn.undoSession != nil { - if pos != "" { - fmt.Fprintf(&conn.outbuf, "$vUDB;goto_time;%s", pos) - } else { - // Find the actual min BB count. - // TODO: is defaulting to zero if we can't get it correct? - minBbCount := "0" - - extent, err := conn.undoCmd("get_log_extent") - if err != nil { - return err - } - index := strings.Index(extent, ",") - if index > 0 { - minBbCount = extent[:index] - } - - conn.outbuf.Reset() - fmt.Fprintf(&conn.outbuf, "$vUDB;goto_time;%s;0", minBbCount) - } + panic("restart serial operation called with an Undo backend") } else { fmt.Fprint(&conn.outbuf, "$vRun;") if pos != "" { diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 2527aab5d..3854fa3cd 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -321,12 +321,25 @@ func (uc *undoSession) resolveUserTime(pos string) (string, error) { func (uc *undoSession) travelToTime(conn *gdbConn, pos string) error { var err error switch pos { - case "start": - err = conn.restart("") + case "start", "": + // Find the actual min BB count. + // TODO: is defaulting to zero if we can't get it correct? + minBbCount := "0" + + extent, err := conn.undoCmd("get_log_extent") + if err != nil { + return err + } + index := strings.Index(extent, ",") + if index > 0 { + minBbCount = extent[:index] + } + + _, err = conn.undoCmd("goto_time", minBbCount, "0") case "end": _, err = conn.undoCmd("goto_record_mode") default: - err = conn.restart(pos) + _, err = conn.undoCmd("goto_time", pos) } return err } From 7d87e237b6aea025176981b091f578968f91c6e4 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Tue, 1 Aug 2023 23:46:46 +0100 Subject: [PATCH 26/29] Move undoCmd out of gdbConn code and into undo.go. If we were a fully integrated backend then the undoCmd probably should live with the gdbConn code - but, for now, we're maintaining a fork and this should be easier to handle. --- pkg/proc/gdbserial/gdbserver.go | 8 +++--- pkg/proc/gdbserial/gdbserver_conn.go | 17 ------------ pkg/proc/gdbserial/undo.go | 39 ++++++++++++++++++++-------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 4f1656c7f..19cfcabc2 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -806,7 +806,7 @@ const ( func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) { if p.conn.undoSession != nil && !p.conn.undoSession.volatile { // Clear interrupt (and enable progress indication) - _, err := p.conn.undoCmd("clear_interrupt") + _, err := undoCmd(&p.conn, "clear_interrupt") if err != nil { return nil, proc.StopUnknown, err } @@ -815,7 +815,7 @@ func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, trapthread, stopReason, err := p.continueOnceWorker(cctx) if p.conn.undoSession != nil && !p.conn.undoSession.volatile { - _, reset_err := p.conn.undoCmd("reset_progress_indicator") + _, reset_err := undoCmd(&p.conn, "reset_progress_indicator") if reset_err != nil { p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) } @@ -1097,7 +1097,7 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T panic("attempted to restart in volatile mode.") } // Clear interrupt (and enable progress indication) - _, err := p.conn.undoCmd("clear_interrupt") + _, err := undoCmd(&p.conn, "clear_interrupt") if err != nil { return nil, err } @@ -1110,7 +1110,7 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T // Restart should not change our volatile mode state. panic("in volatile mode after restart.") } - _, reset_err := p.conn.undoCmd("reset_progress_indicator") + _, reset_err := undoCmd(&p.conn, "reset_progress_indicator") if reset_err != nil { p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) } diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go index 05776d398..7a39b767d 100644 --- a/pkg/proc/gdbserial/gdbserver_conn.go +++ b/pkg/proc/gdbserial/gdbserver_conn.go @@ -1180,23 +1180,6 @@ func (conn *gdbConn) qRRCmd(args ...string) (string, error) { return string(data), nil } -// undoCmd executes a vUDB command -func (conn *gdbConn) undoCmd(args ...string) (string, error) { - if len(args) == 0 { - panic("must specify at least one argument for undoCmd") - } - conn.outbuf.Reset() - fmt.Fprint(&conn.outbuf, "$vUDB") - for _, arg := range args { - fmt.Fprint(&conn.outbuf, ";", arg) - } - resp, err := conn.exec(conn.outbuf.Bytes(), "undoCmd") - if err != nil { - return "", err - } - return string(resp), nil -} - type imageList struct { Images []imageDescription `json:"images"` } diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 3854fa3cd..bc0b084b5 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -39,6 +39,23 @@ func newUndoSession() *undoSession { } } +// undoCmd executes a vUDB command +func undoCmd(conn *gdbConn, args ...string) (string, error) { + if len(args) == 0 { + panic("must specify at least one argument for undoCmd") + } + conn.outbuf.Reset() + fmt.Fprint(&conn.outbuf, "$vUDB") + for _, arg := range args { + fmt.Fprint(&conn.outbuf, ";", arg) + } + resp, err := conn.exec(conn.outbuf.Bytes(), "undoCmd") + if err != nil { + return "", err + } + return string(resp), nil +} + // Validate a checkpoint note to ensure easy interopability with UDB bookmarks. // Returns nil (no error) if a checkpoint is validated successfully. func validateCheckpointNote(where string) error { @@ -79,7 +96,7 @@ func (uc *undoSession) createCheckpoint(conn *gdbConn, where string) (int, error } cpid := uc.checkpointNextId uc.checkpointNextId++ - when, err := conn.undoCmd("get_time") + when, err := undoCmd(conn, "get_time") if err != nil { return -1, err } @@ -144,7 +161,7 @@ func getSessionPath(conn *gdbConn) (string, error) { if err != nil { return "", err } - recording_ids, err := conn.undoCmd("get_recording_ids") + recording_ids, err := undoCmd(conn, "get_recording_ids") if err != nil { return "", err } @@ -326,7 +343,7 @@ func (uc *undoSession) travelToTime(conn *gdbConn, pos string) error { // TODO: is defaulting to zero if we can't get it correct? minBbCount := "0" - extent, err := conn.undoCmd("get_log_extent") + extent, err := undoCmd(conn, "get_log_extent") if err != nil { return err } @@ -335,11 +352,11 @@ func (uc *undoSession) travelToTime(conn *gdbConn, pos string) error { minBbCount = extent[:index] } - _, err = conn.undoCmd("goto_time", minBbCount, "0") + _, err = undoCmd(conn, "goto_time", minBbCount, "0") case "end": - _, err = conn.undoCmd("goto_record_mode") + _, err = undoCmd(conn, "goto_record_mode") default: - _, err = conn.undoCmd("goto_time", pos) + _, err = undoCmd(conn, "goto_time", pos) } return err } @@ -352,14 +369,14 @@ func (uc *undoSession) activateVolatile(conn *gdbConn) (func(), error) { if uc.volatile { panic("tried to activate volatile mode when already active.") } - _, err := conn.undoCmd("set_debuggee_volatile", "1") + _, err := undoCmd(conn, "set_debuggee_volatile", "1") if err != nil { return nil, err } uc.volatile = true return func() { uc.volatile = false - _, _ = conn.undoCmd("set_debuggee_volatile", "0") + _, _ = undoCmd(conn, "set_debuggee_volatile", "0") }, nil } @@ -546,7 +563,7 @@ func UndoIsRecording(recordingFile string) (result bool, err error) { // This is not (currently) implementing a proper parse of the data returned, just making it more // convenient to search. func undoGetInfo(conn *gdbConn) ([]string, error) { - info, err := conn.undoCmd("get_info") + info, err := undoCmd(conn, "get_info") if err != nil { return nil, err } @@ -558,7 +575,7 @@ func undoGetInfo(conn *gdbConn) ([]string, error) { // Fetch the mininum and maximum bbcounts of recorded history. func undoGetLogExtent(conn *gdbConn) (uint64, uint64, error) { - extent, err := conn.undoCmd("get_log_extent") + extent, err := undoCmd(conn, "get_log_extent") if err != nil { return 0, 0, err } @@ -688,7 +705,7 @@ func undoParseServerTime(resp string) (uint64, uint64, error) { // Fetch a representation of the current time as a string. func undoWhen(conn *gdbConn) (string, error) { - resp, err := conn.undoCmd("get_time") + resp, err := undoCmd(conn, "get_time") if err != nil { return "", err } From 5e657fa33346fcc8afe3099d124a6cd840ec25bc Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Wed, 2 Aug 2023 17:59:17 +0100 Subject: [PATCH 27/29] Use lower case for error message, in line with Go convention. --- pkg/proc/gdbserial/undo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index bc0b084b5..5391bec59 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -467,7 +467,7 @@ func UndoRecord(cmd []string, wd string, quiet bool, redirects [3]string) (recor // Recording apparently failed to put anything in the file os.Remove(recording) if err == nil { - err = fmt.Errorf("Recording failed") + err = fmt.Errorf("recording failed") } return "", err } From 8ab9245bddd1b71adbc82cc70cb6b02b1cfbeccf Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Wed, 2 Aug 2023 18:32:49 +0100 Subject: [PATCH 28/29] Simplify travelToTime implementation further. --- pkg/proc/gdbserial/undo.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 5391bec59..0c937bdc2 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -336,28 +336,21 @@ func (uc *undoSession) resolveUserTime(pos string) (string, error) { // Move the replay process to the a point in time. The "pos" argument should be obtained by calling // resolveUserTime to ensure that it is valid. func (uc *undoSession) travelToTime(conn *gdbConn, pos string) error { - var err error + var args []string switch pos { case "start", "": // Find the actual min BB count. - // TODO: is defaulting to zero if we can't get it correct? - minBbCount := "0" - - extent, err := undoCmd(conn, "get_log_extent") + minBbCount, _, err := undoGetLogExtent(conn) if err != nil { return err } - index := strings.Index(extent, ",") - if index > 0 { - minBbCount = extent[:index] - } - - _, err = undoCmd(conn, "goto_time", minBbCount, "0") + args = []string{"goto_time", fmt.Sprint(minBbCount), "0"} case "end": - _, err = undoCmd(conn, "goto_record_mode") + args = []string{"goto_record_mode"} default: - _, err = undoCmd(conn, "goto_time", pos) + args = []string{"goto_time", pos} } + _, err := undoCmd(conn, args...) return err } From 367877478cfda1c613759754f91304257892bab7 Mon Sep 17 00:00:00 2001 From: Mark Williamson Date: Wed, 2 Aug 2023 18:43:59 +0100 Subject: [PATCH 29/29] Move details of maintaining progress indicators into undo.go. The exact details of when we'll activate them and how we do so are not relevant to the `gdbserver.go` code. --- pkg/proc/gdbserial/gdbserver.go | 33 +++++--------------- pkg/proc/gdbserial/undo.go | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index 19cfcabc2..22f6f34c4 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -804,9 +804,8 @@ const ( // The real work is accomplished in continueOnceWorker, this wrapper just handles udbserver's progress // indicators. func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) { - if p.conn.undoSession != nil && !p.conn.undoSession.volatile { - // Clear interrupt (and enable progress indication) - _, err := undoCmd(&p.conn, "clear_interrupt") + if p.conn.undoSession != nil { + err := p.conn.undoSession.continuePre(&p.conn) if err != nil { return nil, proc.StopUnknown, err } @@ -814,13 +813,10 @@ func (p *gdbProcess) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, trapthread, stopReason, err := p.continueOnceWorker(cctx) - if p.conn.undoSession != nil && !p.conn.undoSession.volatile { - _, reset_err := undoCmd(&p.conn, "reset_progress_indicator") - if reset_err != nil { - p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) - } + if p.conn.undoSession != nil { + post_err := p.conn.undoSession.continuePost(&p.conn) if err == nil { - err = reset_err + err = post_err } } @@ -1091,13 +1087,7 @@ func (p *gdbProcess) Detach(kill bool) error { // indicators. func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.Thread, error) { if p.conn.undoSession != nil { - if p.conn.undoSession.volatile { - // We should only be in volatile mode during an inferior call, so this case - // should not be possible. - panic("attempted to restart in volatile mode.") - } - // Clear interrupt (and enable progress indication) - _, err := undoCmd(&p.conn, "clear_interrupt") + err := p.conn.undoSession.restartPre(&p.conn) if err != nil { return nil, err } @@ -1106,16 +1096,9 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T currentThread, err := p.restartWorker(cctx, pos) if p.conn.undoSession != nil { - if p.conn.undoSession.volatile { - // Restart should not change our volatile mode state. - panic("in volatile mode after restart.") - } - _, reset_err := undoCmd(&p.conn, "reset_progress_indicator") - if reset_err != nil { - p.conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) - } + post_err := p.conn.undoSession.restartPost(&p.conn) if err == nil { - err = reset_err + err = post_err } } diff --git a/pkg/proc/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go index 0c937bdc2..1eead1146 100644 --- a/pkg/proc/gdbserial/undo.go +++ b/pkg/proc/gdbserial/undo.go @@ -373,6 +373,59 @@ func (uc *undoSession) activateVolatile(conn *gdbConn) (func(), error) { }, nil } +// Callback before Delve begins a continue-type operation. +// Used to ensure our progress indicators are active and ready to start. Returns an error of nil on +// success. +func (uc *undoSession) continuePre(conn *gdbConn) error { + if uc.volatile { + return nil + } + // Clear interrupt (and enable progress indication) + _, err := undoCmd(conn, "clear_interrupt") + return err +} + +// Callback after Delve finishes a continue-type operation. +// Used to ensure our progress indicators are reset. Returns an error of nil on success. +func (uc *undoSession) continuePost(conn *gdbConn) error { + if uc.volatile { + return nil + } + _, reset_err := undoCmd(conn, "reset_progress_indicator") + if reset_err != nil { + conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) + } + return reset_err +} + +// Callback before Delve starts a restart-type operation. +// Used to ensure our progress indicators are active and ready to start. Returns an error of nil on +// success. +func (uc *undoSession) restartPre(conn *gdbConn) error { + if uc.volatile { + // We should only be in volatile mode during an inferior call, so this case + // should not be possible. + panic("attempted to restart in volatile mode.") + } + // Clear interrupt (and enable progress indication) + _, err := undoCmd(conn, "clear_interrupt") + return err +} + +// Callback after Delve finishes a restart-type operation. +// Used to ensure our progress indicators are reset. Returns an error of nil on success. +func (uc *undoSession) restartPost(conn *gdbConn) error { + if uc.volatile { + // Restart should not change our volatile mode state. + panic("in volatile mode after restart.") + } + _, reset_err := undoCmd(conn, "reset_progress_indicator") + if reset_err != nil { + conn.log.Errorf("Error %s from reset_progress_indicator", reset_err) + } + return reset_err +} + // Get the UDB server filename for the current architecture. func serverFile() (string, error) { switch runtime.GOARCH {