diff --git a/.github/ISSUE_TEMPLATE/issue_template.yml b/.github/ISSUE_TEMPLATE/issue_template.yml index 5a101bb19..cde653ec6 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.yml +++ b/.github/ISSUE_TEMPLATE/issue_template.yml @@ -24,7 +24,7 @@ body: attributes: label: Description value: | - If this is about source listing not showing up (or breakpoints not being accepted) while running in a container please read our [FAQ](https://github.com/go-delve/delve/blob/master/Documentation/faq.md#substpath) first. + If this is about source listing not showing up (or breakpoints not being accepted) while running in a container please read our [FAQ](https://github.com/undoio/delve/blob/master/Documentation/faq.md#substpath) first. 1. What did you do? 2. What did you expect to see? 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 2e25dedf2..33fad7438 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. @@ -43,7 +43,7 @@ The methods of a `service/rpc2.RPCServer` are exposed through this connection, t ### Example -Let's say you are trying to create a breakpoint. By looking at [Go Reference](https://pkg.go.dev/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 [Go Reference](https://pkg.go.dev/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 c75f2d99b..95e53c2e0 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
@@ -45,13 +45,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: @@ -66,7 +65,7 @@ Not all of the configurations are supported by each of the two available DAP ser
attach"remote"NOT supportedsupportedTells the `dlv --headless` server that it is expected to already be debugging a target specified as part of its command-line invocation. -The client would expect `host:port` specification of an external (a.k.a. remote) server that the user already started with target command and args. +The client would expect `host:port` specification of an external (a.k.a. remote) server that the user already started with target command and args.
@@ -144,4 +143,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 c0c7863e8..4ae5126e1 100644 --- a/Documentation/api/json-rpc/README.md +++ b/Documentation/api/json-rpc/README.md @@ -10,7 +10,7 @@ Delve currently only supports v2 of its API. Support for v1 was dropped in versi # 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://pkg.go.dev/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://pkg.go.dev/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 8c2606700..81486d161 100644 --- a/Documentation/cli/README.md +++ b/Documentation/cli/README.md @@ -212,7 +212,7 @@ Set breakpoint condition. Specifies that the breakpoint, tracepoint or watchpoint should break only if the boolean expression is true. -See [Documentation/cli/expr.md](//github.com/go-delve/delve/tree/master/Documentation/cli/expr.md) for a description of supported expressions and [Documentation/cli/cond.md](//github.com/go-delve/delve/tree/master/Documentation/cli/cond.md) for a description of how breakpoint conditions are evaluated. +See [Documentation/cli/expr.md](//github.com/undoio/delve/tree/master/Documentation/cli/expr.md) for a description of supported expressions and [Documentation/cli/cond.md](//github.com/undoio/delve/tree/master/Documentation/cli/cond.md) for a description of how breakpoint conditions are evaluated. With the -hitcount option a condition on the breakpoint hit count can be set, the following operators are supported @@ -264,7 +264,7 @@ substitute-path rules are removed. Without arguments shows the current list of substitute-path rules. The -guess option causes Delve to try to guess your substitute-path configuration automatically. -See also [Documentation/cli/substitutepath.md](//github.com/go-delve/delve/tree/master/Documentation/cli/substitutepath.md) for how the rules are applied. +See also [Documentation/cli/substitutepath.md](//github.com/undoio/delve/tree/master/Documentation/cli/substitutepath.md) for how the rules are applied. config alias config alias @@ -593,7 +593,7 @@ Evaluate an expression. [goroutine ] [frame ] print [%format] -See [Documentation/cli/expr.md](//github.com/go-delve/delve/tree/master/Documentation/cli/expr.md) for a description of supported expressions. +See [Documentation/cli/expr.md](//github.com/undoio/delve/tree/master/Documentation/cli/expr.md) for a description of supported expressions. The optional format argument is a format specifier, like the ones used by the fmt package. For example "print %x v" will print v as an hexadecimal number. @@ -608,7 +608,7 @@ Print contents of CPU registers. regs [-a] -Argument -a shows more registers. Individual registers can also be displayed by 'print' and 'display'. See [Documentation/cli/expr.md](//github.com/go-delve/delve/tree/master/Documentation/cli/expr.md). +Argument -a shows more registers. Individual registers can also be displayed by 'print' and 'display'. See [Documentation/cli/expr.md](//github.com/undoio/delve/tree/master/Documentation/cli/expr.md). ## restart @@ -651,15 +651,15 @@ Changes the value of a variable. [goroutine ] [frame ] set = -See [Documentation/cli/expr.md](//github.com/go-delve/delve/tree/master/Documentation/cli/expr.md) for a description of supported expressions. Only numerical variables and pointers can be changed. +See [Documentation/cli/expr.md](//github.com/undoio/delve/tree/master/Documentation/cli/expr.md) for a description of supported expressions. Only numerical variables and pointers can be changed. ## source 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. @@ -743,7 +743,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 f70ed3f9e..9fcc3f417 100644 --- a/Documentation/cli/expr.md +++ b/Documentation/cli/expr.md @@ -56,7 +56,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 75119cfb5..ef2e9f869 100644 --- a/Documentation/cli/starlark.md +++ b/Documentation/cli/starlark.md @@ -17,57 +17,57 @@ 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://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.AmendBreakpoint) -ancestors(GoroutineID, NumAncestors, Depth) | Equivalent to API call [Ancestors](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Ancestors) -attached_to_existing_process() | Equivalent to API call [AttachedToExistingProcess](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.AttachedToExistingProcess) -build_id() | Equivalent to API call [BuildID](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.BuildID) -cancel_next() | Equivalent to API call [CancelNext](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.CancelNext) -checkpoint(Where) | Equivalent to API call [Checkpoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Checkpoint) -clear_breakpoint(Id, Name) | Equivalent to API call [ClearBreakpoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ClearBreakpoint) -clear_checkpoint(ID) | Equivalent to API call [ClearCheckpoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ClearCheckpoint) -raw_command(Name, ThreadID, GoroutineID, ReturnInfoLoadConfig, Expr, WithEvents, UnsafeCall) | Equivalent to API call [Command](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Command) -create_breakpoint(Breakpoint, LocExpr, SubstitutePathRules, Suspended) | Equivalent to API call [CreateBreakpoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.CreateBreakpoint) -create_ebpf_tracepoint(FunctionName) | Equivalent to API call [CreateEBPFTracepoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.CreateEBPFTracepoint) -create_watchpoint(Scope, Expr, Type) | Equivalent to API call [CreateWatchpoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.CreateWatchpoint) -debug_info_directories(Set, List) | Equivalent to API call [DebugInfoDirectories](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.DebugInfoDirectories) -detach(Kill) | Equivalent to API call [Detach](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Detach) -disassemble(Scope, StartPC, EndPC, Flavour) | Equivalent to API call [Disassemble](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Disassemble) -dump_cancel() | Equivalent to API call [DumpCancel](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.DumpCancel) -dump_start(Destination) | Equivalent to API call [DumpStart](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.DumpStart) -dump_wait(Wait) | Equivalent to API call [DumpWait](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.DumpWait) -eval(Scope, Expr, Cfg) | Equivalent to API call [Eval](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Eval) -examine_memory(Address, Length) | Equivalent to API call [ExamineMemory](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ExamineMemory) -find_location(Scope, Loc, IncludeNonExecutableLines, SubstitutePathRules) | Equivalent to API call [FindLocation](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.FindLocation) -follow_exec(Enable, Regex) | Equivalent to API call [FollowExec](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.FollowExec) -follow_exec_enabled() | Equivalent to API call [FollowExecEnabled](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.FollowExecEnabled) -function_return_locations(FnName) | Equivalent to API call [FunctionReturnLocations](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.FunctionReturnLocations) -get_breakpoint(Id, Name) | Equivalent to API call [GetBreakpoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.GetBreakpoint) -get_buffered_tracepoints() | Equivalent to API call [GetBufferedTracepoints](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.GetBufferedTracepoints) -get_thread(Id) | Equivalent to API call [GetThread](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.GetThread) -guess_substitute_path(Args) | Equivalent to API call [GuessSubstitutePath](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.GuessSubstitutePath) -is_multiclient() | Equivalent to API call [IsMulticlient](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.IsMulticlient) -last_modified() | Equivalent to API call [LastModified](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.LastModified) -breakpoints(All) | Equivalent to API call [ListBreakpoints](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListBreakpoints) -checkpoints() | Equivalent to API call [ListCheckpoints](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListCheckpoints) -dynamic_libraries() | Equivalent to API call [ListDynamicLibraries](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListDynamicLibraries) -function_args(Scope, Cfg) | Equivalent to API call [ListFunctionArgs](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListFunctionArgs) -functions(Filter, FollowCalls) | Equivalent to API call [ListFunctions](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListFunctions) -goroutines(Start, Count, Filters, GoroutineGroupingOptions, EvalScope) | Equivalent to API call [ListGoroutines](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListGoroutines) -local_vars(Scope, Cfg) | Equivalent to API call [ListLocalVars](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListLocalVars) -package_vars(Filter, Cfg) | Equivalent to API call [ListPackageVars](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListPackageVars) -packages_build_info(IncludeFiles, Filter) | Equivalent to API call [ListPackagesBuildInfo](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListPackagesBuildInfo) -registers(ThreadID, IncludeFp, Scope) | Equivalent to API call [ListRegisters](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListRegisters) -sources(Filter) | Equivalent to API call [ListSources](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListSources) -targets() | Equivalent to API call [ListTargets](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListTargets) -threads() | Equivalent to API call [ListThreads](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListThreads) -types(Filter) | Equivalent to API call [ListTypes](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ListTypes) -process_pid() | Equivalent to API call [ProcessPid](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ProcessPid) -recorded() | Equivalent to API call [Recorded](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Recorded) -restart(Position, ResetArgs, NewArgs, Rerecord, Rebuild, NewRedirects) | Equivalent to API call [Restart](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Restart) -set_expr(Scope, Symbol, Value) | Equivalent to API call [Set](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Set) -stacktrace(Id, Depth, Full, Defers, Opts, Cfg) | Equivalent to API call [Stacktrace](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Stacktrace) -state(NonBlocking) | Equivalent to API call [State](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.State) -toggle_breakpoint(Id, Name) | Equivalent to API call [ToggleBreakpoint](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.ToggleBreakpoint) +amend_breakpoint(Breakpoint) | Equivalent to API call [AmendBreakpoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.AmendBreakpoint) +ancestors(GoroutineID, NumAncestors, Depth) | Equivalent to API call [Ancestors](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Ancestors) +attached_to_existing_process() | Equivalent to API call [AttachedToExistingProcess](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.AttachedToExistingProcess) +build_id() | Equivalent to API call [BuildID](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.BuildID) +cancel_next() | Equivalent to API call [CancelNext](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.CancelNext) +checkpoint(Where) | Equivalent to API call [Checkpoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Checkpoint) +clear_breakpoint(Id, Name) | Equivalent to API call [ClearBreakpoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ClearBreakpoint) +clear_checkpoint(ID) | Equivalent to API call [ClearCheckpoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ClearCheckpoint) +raw_command(Name, ThreadID, GoroutineID, ReturnInfoLoadConfig, Expr, WithEvents, UnsafeCall) | Equivalent to API call [Command](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Command) +create_breakpoint(Breakpoint, LocExpr, SubstitutePathRules, Suspended) | Equivalent to API call [CreateBreakpoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.CreateBreakpoint) +create_ebpf_tracepoint(FunctionName) | Equivalent to API call [CreateEBPFTracepoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.CreateEBPFTracepoint) +create_watchpoint(Scope, Expr, Type) | Equivalent to API call [CreateWatchpoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.CreateWatchpoint) +debug_info_directories(Set, List) | Equivalent to API call [DebugInfoDirectories](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.DebugInfoDirectories) +detach(Kill) | Equivalent to API call [Detach](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Detach) +disassemble(Scope, StartPC, EndPC, Flavour) | Equivalent to API call [Disassemble](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Disassemble) +dump_cancel() | Equivalent to API call [DumpCancel](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.DumpCancel) +dump_start(Destination) | Equivalent to API call [DumpStart](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.DumpStart) +dump_wait(Wait) | Equivalent to API call [DumpWait](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.DumpWait) +eval(Scope, Expr, Cfg) | Equivalent to API call [Eval](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Eval) +examine_memory(Address, Length) | Equivalent to API call [ExamineMemory](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ExamineMemory) +find_location(Scope, Loc, IncludeNonExecutableLines, SubstitutePathRules) | Equivalent to API call [FindLocation](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.FindLocation) +follow_exec(Enable, Regex) | Equivalent to API call [FollowExec](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.FollowExec) +follow_exec_enabled() | Equivalent to API call [FollowExecEnabled](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.FollowExecEnabled) +function_return_locations(FnName) | Equivalent to API call [FunctionReturnLocations](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.FunctionReturnLocations) +get_breakpoint(Id, Name) | Equivalent to API call [GetBreakpoint](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.GetBreakpoint) +get_buffered_tracepoints() | Equivalent to API call [GetBufferedTracepoints](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.GetBufferedTracepoints) +get_thread(Id) | Equivalent to API call [GetThread](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.GetThread) +guess_substitute_path(Args) | Equivalent to API call [GuessSubstitutePath](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.GuessSubstitutePath) +is_multiclient() | Equivalent to API call [IsMulticlient](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.IsMulticlient) +last_modified() | Equivalent to API call [LastModified](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.LastModified) +breakpoints(All) | Equivalent to API call [ListBreakpoints](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListBreakpoints) +checkpoints() | Equivalent to API call [ListCheckpoints](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListCheckpoints) +dynamic_libraries() | Equivalent to API call [ListDynamicLibraries](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListDynamicLibraries) +function_args(Scope, Cfg) | Equivalent to API call [ListFunctionArgs](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListFunctionArgs) +functions(Filter, FollowCalls) | Equivalent to API call [ListFunctions](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListFunctions) +goroutines(Start, Count, Filters, GoroutineGroupingOptions, EvalScope) | Equivalent to API call [ListGoroutines](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListGoroutines) +local_vars(Scope, Cfg) | Equivalent to API call [ListLocalVars](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListLocalVars) +package_vars(Filter, Cfg) | Equivalent to API call [ListPackageVars](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListPackageVars) +packages_build_info(IncludeFiles, Filter) | Equivalent to API call [ListPackagesBuildInfo](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListPackagesBuildInfo) +registers(ThreadID, IncludeFp, Scope) | Equivalent to API call [ListRegisters](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListRegisters) +sources(Filter) | Equivalent to API call [ListSources](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListSources) +targets() | Equivalent to API call [ListTargets](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListTargets) +threads() | Equivalent to API call [ListThreads](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListThreads) +types(Filter) | Equivalent to API call [ListTypes](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ListTypes) +process_pid() | Equivalent to API call [ProcessPid](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.ProcessPid) +recorded() | Equivalent to API call [Recorded](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Recorded) +restart(Position, ResetArgs, NewArgs, Rerecord, Rebuild, NewRedirects) | Equivalent to API call [Restart](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Restart) +set_expr(Scope, Symbol, Value) | Equivalent to API call [Set](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Set) +stacktrace(Id, Depth, Full, Defers, Opts, Cfg) | Equivalent to API call [Stacktrace](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Stacktrace) +state(NonBlocking) | Equivalent to API call [State](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.State) +toggle_breakpoint(Id, Name) | Equivalent to API call [ToggleBreakpoint](https://pkg.go.dev/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 @@ -84,7 +84,7 @@ There are two ways to resume the execution of the target program: raw_command("continue") dlv_command("continue") -The first one maps to the API call [Command](https://pkg.go.dev/github.com/go-delve/delve/service/rpc2#RPCServer.Command). As such all the caveats explained in the [Client HowTo](../api/ClientHowto.md). +The first one maps to the API call [Command](https://pkg.go.dev/github.com/undoio/delve/service/rpc2#RPCServer.Command). As such all the caveats explained in the [Client HowTo](../api/ClientHowto.md). The latter is equivalent to typing `continue` to the `(dlv)` command line and should do what you expect. @@ -117,7 +117,7 @@ You can use this command like this: # 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://pkg.go.dev/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://pkg.go.dev/github.com/undoio/delve/service/api#Variable) struct, with one special field: `Value`. As a convenience a special global object exists, called `tgt`: evaluating `tgt.varname` is equivalent to evaluating `eval(None, "varname").Variable.Value`. @@ -347,8 +347,8 @@ def command_flaky(args): ## Passing a struct as an argument Struct literals can be passed to built-ins as Starlark dictionaries. For example, the following snippet passes -in an [api.EvalScope](https://pkg.go.dev/github.com/go-delve/delve/service/api#EvalScope) -and [api.LoadConfig](https://pkg.go.dev/github.com/go-delve/delve/service/api#LoadConfig) +in an [api.EvalScope](https://pkg.go.dev/github.com/undoio/delve/service/api#EvalScope) +and [api.LoadConfig](https://pkg.go.dev/github.com/undoio/delve/service/api#LoadConfig) to the `eval` built-in. `None` can be passed for optional arguments, and trailing optional arguments can be elided completely. diff --git a/Documentation/faq.md b/Documentation/faq.md index ff8d628c3..a4ee59332 100644 --- a/Documentation/faq.md +++ b/Documentation/faq.md @@ -119,7 +119,7 @@ The `sources` command could also be useful in troubleshooting this problem, it s For more information on path substitution see [path substitution](cli/substitutepath.md). -If you still think this is a bug in Delve and not a configuration problem, open an [issue](https://github.com/go-delve/delve/issues), filling the issue template and including the logs produced by delve with the options `--log --log-output=rpc,dap`. +If you still think this is a bug in Delve and not a configuration problem, open an [issue](https://github.com/undoio/delve/delve/issues), filling the issue template and including the logs produced by delve with the options `--log --log-output=rpc,dap`. ### Using Delve to debug the Go runtime diff --git a/Documentation/installation/README.md b/Documentation/installation/README.md index ab2cbe365..bc741c650 100644 --- a/Documentation/installation/README.md +++ b/Documentation/installation/README.md @@ -5,14 +5,14 @@ With 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@undo # Install from tree head: -$ go install github.com/go-delve/delve/cmd/dlv@master +$ go install github.com/undoio/delve/cmd/dlv@master # Install 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@undo-v1.24.1 +$ go install github.com/undoio/delve/cmd/dlv@undo-v1.23.1-1 ``` 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. @@ -20,9 +20,9 @@ See [Versions](https://go.dev/ref/mod#versions) and [Pseudo-versions](https://go Alternatively, 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 ``` See `go help install` for details on where the `dlv` executable is saved. @@ -30,7 +30,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`. @@ -57,11 +57,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/Documentation/usage/dlv.md b/Documentation/usage/dlv.md index d0c1dfb4a..357087462 100644 --- a/Documentation/usage/dlv.md +++ b/Documentation/usage/dlv.md @@ -29,7 +29,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 test](dlv_test.md) - Compile test binary and begin debugging program. * [dlv trace](dlv_trace.md) - Compile and begin tracing program. * [dlv version](dlv_version.md) - Prints version. diff --git a/Documentation/usage/dlv_replay.md b/Documentation/usage/dlv_replay.md index 46b7ed2f6..15d1ba623 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/README.md b/README.md index 469d34f70..c8a566f80 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ ![Delve](https://raw.githubusercontent.com/go-delve/delve/master/assets/delve_horizontal.png) -[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/go-delve/delve/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-delve/delve.svg)](https://pkg.go.dev/github.com/go-delve/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) +[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/undoio/delve/master/LICENSE) +[![Go Reference](https://pkg.go.dev/badge/github.com/go-delve/delve.svg)](https://pkg.go.dev/github.com/undoio/delve) 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 ddba40211..f54b9cfeb 100644 --- a/_scripts/gen-cli-docs.go +++ b/_scripts/gen-cli-docs.go @@ -7,7 +7,7 @@ import ( "log" "os" - "github.com/go-delve/delve/pkg/terminal" + "github.com/undoio/delve/pkg/terminal" ) func main() { diff --git a/_scripts/gen-travis.go b/_scripts/gen-travis.go index 04d4c1714..81f99f7c5 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 17e5e3b90..ac5adc3cc 100644 --- a/_scripts/gen-usage-docs.go +++ b/_scripts/gen-usage-docs.go @@ -8,8 +8,8 @@ import ( "os" "path/filepath" - "github.com/go-delve/delve/cmd/dlv/cmds" - "github.com/go-delve/delve/cmd/dlv/cmds/helphelpers" + "github.com/undoio/delve/cmd/dlv/cmds" + "github.com/undoio/delve/cmd/dlv/cmds/helphelpers" "github.com/spf13/cobra/doc" ) diff --git a/_scripts/make.go b/_scripts/make.go index 5f18e5ce3..c8d3cd6cf 100644 --- a/_scripts/make.go +++ b/_scripts/make.go @@ -12,11 +12,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 @@ -99,7 +99,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`) @@ -398,6 +398,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 { @@ -435,6 +439,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) { @@ -487,10 +495,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 6f1aae7c3..3b3d9f47c 100644 --- a/_scripts/rtype.go +++ b/_scripts/rtype.go @@ -183,7 +183,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) } @@ -339,7 +339,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 3f7406593..89b618e5f 100644 --- a/cmd/dlv/cmds/commands.go +++ b/cmd/dlv/cmds/commands.go @@ -17,22 +17,23 @@ import ( "syscall" "time" - "github.com/go-delve/delve/cmd/dlv/cmds/helphelpers" - "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/proc" - "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/cmd/dlv/cmds/helphelpers" + "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/proc" + "github.com/undoio/delve/pkg/proc/gdbserial" + "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 ( @@ -101,6 +102,10 @@ var ( rrOnProcessPid int rrDelOnDetach bool + // External unstripped executable to use for symbols while replaying an Undo recording. + // TODO: Support this for rr backend. + replaySymbolFile string + attachWaitFor string attachWaitForInterval float64 attachWaitForDuration float64 @@ -418,25 +423,47 @@ 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 ", + 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" - rrDelOnDetach = false - os.Exit(execute(0, []string{}, conf, args[0], debugger.ExecutingOther, args, buildFlags)) + recording := args[0] + + if isUndo, _ := gdbserial.UndoIsRecording(recording); isUndo { + backend = "undo" + } else { + backend = "rr" + rrDelOnDetach = false + if replaySymbolFile != "" { + fmt.Fprintf(os.Stderr, "Separate symbol file is not supported with rr backend.\n") + os.Exit(1) + } + } + os.Exit(execute(0, []string{replaySymbolFile}, conf, recording, debugger.ExecutingOther, args, buildFlags)) }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) > 2 { @@ -445,6 +472,7 @@ https://github.com/mozilla/rr return nil, cobra.ShellCompDirectiveDefault }, } + replayCommand.Flags().StringVarP(&replaySymbolFile, "symbol-file", "", "", "External unstripped executable for debug symbol lookups while replaying a recording.") replayCommand.Flags().IntVarP(&rrOnProcessPid, "onprocess", "p", 0, "Pass onprocess pid to rr.") diff --git a/cmd/dlv/dlv_test.go b/cmd/dlv/dlv_test.go index 9949071d6..b9f57acf1 100644 --- a/cmd/dlv/dlv_test.go +++ b/cmd/dlv/dlv_test.go @@ -19,12 +19,6 @@ 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/rpc2" godap "github.com/google/go-dap" ) @@ -404,7 +398,7 @@ func TestTypecheckRPC(t *testing.T) { if !isLatestMinor(t) { t.Skip("N/A") } - cmd := exec.Command("go", "run", "github.com/go-delve/build-tools/cmd/typecheck-rpc@latest") + cmd := exec.Command("go", "run", "github.com/undoio/build-tools/cmd/typecheck-rpc@latest") buf, err := cmd.CombinedOutput() t.Logf("output: %s", string(buf)) if err != nil { @@ -1244,7 +1238,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 %s and %s in the output", got, want1, want2) @@ -1258,7 +1252,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 588712720..b83430c88 100644 --- a/cmd/dlv/main.go +++ b/cmd/dlv/main.go @@ -1,11 +1,13 @@ package main import ( + "fmt" "os" + "strings" - "github.com/go-delve/delve/cmd/dlv/cmds" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/version" + "github.com/undoio/delve/cmd/dlv/cmds" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/version" "golang.org/x/telemetry" ) @@ -28,5 +30,49 @@ func main() { logflags.WriteCgoFlagsWarning() } + // 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/go.mod b/go.mod index cc0e6bf31..6b23ed4d8 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/go-delve/delve +module github.com/undoio/delve go 1.24 @@ -15,6 +15,7 @@ require ( github.com/spf13/pflag v1.0.6 go.starlark.net v0.0.0-20231101134539-556fd59b42f6 golang.org/x/arch v0.11.0 + golang.org/x/mod v0.20.0 golang.org/x/sys v0.26.0 golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5 gopkg.in/yaml.v3 v3.0.1 diff --git a/patch-goland-delve.sh b/patch-goland-delve.sh new file mode 100755 index 000000000..962ad2c8d --- /dev/null +++ b/patch-goland-delve.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# +# This script is used to patch the GoLand dlv binary with a dlv version +# that has support for Undo. + +usage() { +cat < + -u Uninstall patched dlv +EOF +exit +} + +checkdeps() { + deps="git go" + for d in $deps + do + command -v "$d" >/dev/null || { + echo "$0: missing dependency: $d" 1>&2 + exit 1 + } + done +} + +installdlv() { + dst="$1" + + # Keep a copy of the original dlv binary so we can restore it if needed. + if test -e "$dst/dlv" -a ! -e "$dst/dlv.orig" + then + cp "$dst/dlv" "$dst/dlv.orig" + fi + + tmprepo=$(mktemp -d) + trap 'GOPATH="$tmprepo" go clean -modcache 2>/dev/null || rm -rf $tmprepo' EXIT INT QUIT TERM HUP + + GOPATH="$tmprepo" go install github.com/undoio/delve/cmd/dlv@undo + + ( + install -m 755 "$tmprepo/bin/dlv" "$dst" + ) || exit 1 + + echo "dlv has been installed to $dst" +} + +uninstalldlv() { + dst="$1" + + if test -e "$dst/dlv.orig" + then + mv "$dst/dlv.orig" "$dst/dlv" + echo "dlv has been uninstalled from $dst" + else + echo "no patched dlv installation found" + fi +} + +uflag=0 +for arg +do +case "$arg" in +--help|-h) usage ;; +--uninstall|-u) uflag=1 ;; +-*) echo "$0: unknown option $arg" ;; +*) dst="$arg" ;; +esac +done + +if test -z "$dst" +then + usage +fi + +dst=$(readlink -e "$dst"plugins/go-plugin/lib/dlv/linux/) +if test ! $? -eq 0 +then + exit 1 +fi + +checkdeps + +if test "$uflag" -eq 1 +then + uninstalldlv "$dst" +else + installdlv "$dst" +fi diff --git a/pkg/config/config.go b/pkg/config/config.go index a77a16c13..f2cdb8133 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -8,7 +8,7 @@ import ( "path" "runtime" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service/api" "gopkg.in/yaml.v3" ) diff --git a/pkg/dwarf/dwarfbuilder/info.go b/pkg/dwarf/dwarfbuilder/info.go index e65a50576..b539bbe1e 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 66aa451aa..a37500ffc 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 23cb8b445..0dd5f8693 100644 --- a/pkg/dwarf/frame/table.go +++ b/pkg/dwarf/frame/table.go @@ -6,7 +6,7 @@ import ( "fmt" "maps" - "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 6cc1d85b4..35586809d 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 80d9875c5..3aeb5044d 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 f6e5f6852..5eea8ac99 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 cc5f587fc..5851cda9b 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 18c0d20c7..ab5b7ba36 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 3337f76a0..9e949b88f 100644 --- a/pkg/dwarf/line/state_machine_test.go +++ b/pkg/dwarf/line/state_machine_test.go @@ -11,8 +11,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 89fef49f9..de4b570d3 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 acdaf604d..f8621cd92 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 efd82376f..deeab994f 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 c8694fcc9..6e5783675 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" - "github.com/go-delve/delve/pkg/dwarf/leb128" + "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 6929ac4f8..7753440c5 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 c4a6de09b..90b9ed4ea 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 ae48bc939..4489225c3 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/defaultexe.go b/pkg/gobuild/defaultexe.go index da7d1ec49..dd85dc792 100644 --- a/pkg/gobuild/defaultexe.go +++ b/pkg/gobuild/defaultexe.go @@ -4,7 +4,7 @@ import ( "os" "runtime" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/logflags" ) // DefaultDebugBinaryPath returns an unused file path in the current diff --git a/pkg/gobuild/gobuild.go b/pkg/gobuild/gobuild.go index c93e45ff5..6a5148fa1 100644 --- a/pkg/gobuild/gobuild.go +++ b/pkg/gobuild/gobuild.go @@ -10,8 +10,8 @@ import ( "strings" "time" - "github.com/go-delve/delve/pkg/config" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/config" + "github.com/undoio/delve/pkg/logflags" ) // Remove the file at path and issue a warning to stderr if this fails. diff --git a/pkg/gobuild/gobuild_test.go b/pkg/gobuild/gobuild_test.go index a5caa2c9e..47702f49a 100644 --- a/pkg/gobuild/gobuild_test.go +++ b/pkg/gobuild/gobuild_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/go-delve/delve/pkg/config" + "github.com/undoio/delve/pkg/config" ) func TestGoBuildArgsDashC(t *testing.T) { diff --git a/pkg/goversion/compat.go b/pkg/goversion/compat.go index eceeee8cb..8eac418a3 100644 --- a/pkg/goversion/compat.go +++ b/pkg/goversion/compat.go @@ -5,7 +5,7 @@ import ( "fmt" "runtime" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/logflags" ) //lint:file-ignore ST1005 errors here can be capitalized diff --git a/pkg/internal/lru/lru_test.go b/pkg/internal/lru/lru_test.go index b27ab82f0..69990dfff 100644 --- a/pkg/internal/lru/lru_test.go +++ b/pkg/internal/lru/lru_test.go @@ -4,7 +4,7 @@ import ( "sync" "testing" - "github.com/go-delve/delve/pkg/internal/lru" + "github.com/undoio/delve/pkg/internal/lru" ) func TestCache_ZeroCapacity(t *testing.T) { diff --git a/pkg/locspec/locations.go b/pkg/locspec/locations.go index c98103fd0..f26550e8b 100644 --- a/pkg/locspec/locations.go +++ b/pkg/locspec/locations.go @@ -12,8 +12,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 58aa6d2de..6000f01e3 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 9d34c35c1..4a72242e6 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 eeae28b22..6e9fd4965 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 c4a8d5940..07a33eb11 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 29834407e..019f5e56f 100644 --- a/pkg/proc/arm64_arch.go +++ b/pkg/proc/arm64_arch.go @@ -6,10 +6,10 @@ import ( "fmt" "runtime" - "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 9997dfd36..1917faa3a 100644 --- a/pkg/proc/arm64_disasm.go +++ b/pkg/proc/arm64_disasm.go @@ -1,8 +1,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 41b7e25a2..5d9e1946b 100644 --- a/pkg/proc/bininfo.go +++ b/pkg/proc/bininfo.go @@ -25,20 +25,20 @@ import ( "sync" "time" - "github.com/go-delve/delve/pkg/astutil" - 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/internal/gosym" - "github.com/go-delve/delve/pkg/internal/lru" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/pkg/proc/debuginfod" - "github.com/go-delve/delve/pkg/proc/evalop" + "github.com/undoio/delve/pkg/astutil" + 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/internal/gosym" + "github.com/undoio/delve/pkg/internal/lru" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc/debuginfod" + "github.com/undoio/delve/pkg/proc/evalop" ) const ( @@ -81,7 +81,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 94b1d5e58..505375255 100644 --- a/pkg/proc/breakpoints.go +++ b/pkg/proc/breakpoints.go @@ -13,13 +13,13 @@ import ( "reflect" "strconv" - "github.com/go-delve/delve/pkg/astutil" - "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/evalop" - "github.com/go-delve/delve/pkg/proc/internal/ebpf" + "github.com/undoio/delve/pkg/astutil" + "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/evalop" + "github.com/undoio/delve/pkg/proc/internal/ebpf" ) const ( diff --git a/pkg/proc/core/core.go b/pkg/proc/core/core.go index 3d0ef859d..245685fb0 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 30acea9b2..324793f88 100644 --- a/pkg/proc/core/core_test.go +++ b/pkg/proc/core/core_test.go @@ -14,9 +14,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 a6e14957e..20bc6aaef 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 55ef66396..964011e6d 100644 --- a/pkg/proc/core/linux_core.go +++ b/pkg/proc/core/linux_core.go @@ -10,10 +10,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 0e1831cd4..5adeabb8e 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 f69b193bf..cfac18b02 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 4b7b69aa3..6e2a2347c 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 e1841cfbf..57417795a 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 3431f93ba..e30349f27 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 e5f14b0cd..b44b994dd 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 35a04528b..094f4b2e7 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -13,13 +13,13 @@ import ( "sort" "strings" - "github.com/go-delve/delve/pkg/astutil" - "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/go-delve/delve/pkg/proc/evalop" + "github.com/undoio/delve/pkg/astutil" + "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" + "github.com/undoio/delve/pkg/proc/evalop" ) var errOperationOnSpecialFloat = errors.New("operations on non-finite floats not implemented") diff --git a/pkg/proc/evalop/evalcompile.go b/pkg/proc/evalop/evalcompile.go index 078a5249c..8257a0c86 100644 --- a/pkg/proc/evalop/evalcompile.go +++ b/pkg/proc/evalop/evalcompile.go @@ -11,9 +11,9 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/astutil" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/astutil" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/reader" ) var ( diff --git a/pkg/proc/evalop/ops.go b/pkg/proc/evalop/ops.go index 58d37c882..d740f4d6c 100644 --- a/pkg/proc/evalop/ops.go +++ b/pkg/proc/evalop/ops.go @@ -4,7 +4,7 @@ import ( "go/ast" "go/constant" - "github.com/go-delve/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/godwarf" ) // Op is a stack machine opcode 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 12e0fdac1..2f9103bb8 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -13,14 +13,14 @@ import ( "strconv" "strings" - "github.com/go-delve/delve/pkg/astutil" - "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/go-delve/delve/pkg/proc/evalop" + "github.com/undoio/delve/pkg/astutil" + "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" + "github.com/undoio/delve/pkg/proc/evalop" ) // 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 4c9466a9b..1953cbe46 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 @@ -79,13 +81,13 @@ import ( isatty "github.com/mattn/go-isatty" - "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" + "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 ( @@ -160,8 +162,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 @@ -187,9 +187,14 @@ type gdbThread struct { } // ErrBackendUnavailable is returned when the stub program can not be found. -type ErrBackendUnavailable struct{} +type ErrBackendUnavailable struct { + Detail string +} func (err *ErrBackendUnavailable) Error() string { + if len(err.Detail) > 0 { + return err.Detail + } return "backend unavailable" } @@ -359,24 +364,6 @@ func (p *gdbProcess) Connect(conn net.Conn, path, cmdline string, pid int, debug 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 } @@ -700,6 +687,16 @@ func (p *gdbProcess) EntryPoint() (uint64, error) { // stubs will report both the PID and executable path. func (p *gdbProcess) initialize(path, cmdline string, debugInfoDirs []string, stopReason proc.StopReason) (*proc.TargetGroup, error) { var err error + + if path == "" && p.conn.undoSession != nil { + // Always use the path from the recording file, so that we have consistent debug + // symbols. Allowing the user to specify other paths is out of scope for now. + path, err = undoGetExePath(&p.conn) + if err != nil { + return nil, err + } + } + if path == "" { // If we are attaching to a running process and the user didn't specify // the executable file manually we must ask the stub for it. @@ -845,7 +842,29 @@ 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.undoSession != nil { + err := p.conn.undoSession.continuePre(&p.conn) + if err != nil { + return nil, proc.StopUnknown, err + } + } + + trapthread, stopReason, err := p.continueOnceWorker(cctx) + + if p.conn.undoSession != nil { + post_err := p.conn.undoSession.continuePost(&p.conn) + if err == nil { + err = post_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} } @@ -918,7 +937,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.undoSession != nil { + // 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 { trapThreadRegs = sp.regs @@ -992,7 +1021,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 } @@ -1113,11 +1142,43 @@ func (p *gdbProcess) Close() 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.undoSession != nil { + err := p.conn.undoSession.restartPre(&p.conn) + if err != nil { + return nil, err + } + } + + currentThread, err := p.restartWorker(cctx, pos) + + if p.conn.undoSession != nil { + post_err := p.conn.undoSession.restartPost(&p.conn) + if err == nil { + err = post_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 } + // Is this a checkpoint on a server using local checkpoints? + if p.conn.undoSession != nil { + var err error + pos, err = p.conn.undoSession.resolveUserTime(pos) + if err != nil { + return nil, err + } + } + p.exited = false p.almostExited = false @@ -1127,16 +1188,23 @@ func (p *gdbProcess) Restart(cctx *proc.ContinueOnceContext, pos string) (proc.T p.ctrlC = false - err := p.conn.restart(pos) + var err error + if p.conn.undoSession != nil { + err = p.conn.undoSession.travelToTime(&p.conn, pos) + } else { + err = p.conn.restart(pos) + } if err != nil { return nil, err } // 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.undoSession == nil { + _, err = p.conn.resume(cctx, nil, nil) + if err != nil { + return nil, err + } } err = p.updateThreadList(&threadUpdater{p: p}, nil) @@ -1153,17 +1221,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.undoSession != nil { + when, err := undoWhen(&p.conn) + if err != nil { + return "", err + } + result = when + } 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 ( @@ -1175,6 +1253,12 @@ func (p *gdbProcess) Checkpoint(where string) (int, error) { if p.tracedir == "" { return -1, proc.ErrNotRecorded } + + // Handle locally managed checkpoints first + if p.conn.undoSession != nil { + return p.conn.undoSession.createCheckpoint(&p.conn, where) + } + resp, err := p.conn.qRRCmd("checkpoint", where) if err != nil { return -1, err @@ -1203,6 +1287,12 @@ func (p *gdbProcess) Checkpoints() ([]proc.Checkpoint, error) { if p.tracedir == "" { return nil, proc.ErrNotRecorded } + + // Handle locally managed checkpoints first + if p.conn.undoSession != nil { + return p.conn.undoSession.getCheckpoints() + } + resp, err := p.conn.qRRCmd("info checkpoints") if err != nil { return nil, err @@ -1233,6 +1323,14 @@ func (p *gdbProcess) ClearCheckpoint(id int) error { if p.tracedir == "" { return proc.ErrNotRecorded } + + // Handle locally managed checkpoints first + if p.conn.undoSession != nil { + p.conn.undoSession.deleteCheckpoint(&p.conn, 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 @@ -1276,6 +1374,10 @@ func (p *gdbProcess) StartCallInjection() (func(), error) { return nil, ErrStartCallInjectionBackwards } + if p.conn.undoSession != nil { + return p.conn.undoSession.activateVolatile(&p.conn) + } + // Normally it's impossible to inject function calls in a recorded target // because the sequence of instructions that the target will execute is // predetermined. @@ -1607,31 +1709,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) @@ -1744,15 +1821,6 @@ func (t *gdbThread) reloadRegisters(regs map[uint64]uint64) 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 @@ -1761,10 +1829,7 @@ func (t *gdbThread) reloadRegisters(regs map[uint64]uint64) 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 @@ -1816,143 +1881,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.watchAddr = 0 @@ -2258,3 +2186,47 @@ func checkRosettaExpensive() 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 +} diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go index 2ddde57db..711772760 100644 --- a/pkg/proc/gdbserial/gdbserver_conn.go +++ b/pkg/proc/gdbserial/gdbserver_conn.go @@ -16,8 +16,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 { @@ -50,6 +50,9 @@ type gdbConn struct { useXcmd bool // forces writeMemory to use the 'X' command newRRCmdStyle bool // forces qRRCmd to use the post-5.8.0 style always + // State relating to the Undo session - non-nil when using an Undo backend. + undoSession *undoSession + log logflags.Logger } @@ -864,6 +867,14 @@ func (conn *gdbConn) parseStopPacket(resp []byte, threadID string, tu *threadUpd parseMachException(&sp, metype, medata) + if conn.undoSession != nil { + // 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': @@ -1181,10 +1192,15 @@ 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.undoSession != nil { + panic("restart serial operation called with an Undo backend") + } 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 diff --git a/pkg/proc/gdbserial/rr.go b/pkg/proc/gdbserial/rr.go index 161e03328..7f0c40eff 100644 --- a/pkg/proc/gdbserial/rr.go +++ b/pkg/proc/gdbserial/rr.go @@ -11,10 +11,10 @@ import ( "strings" "syscall" - "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" + "github.com/undoio/delve/pkg/config" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/pkg/proc" ) const ( diff --git a/pkg/proc/gdbserial/rr_test.go b/pkg/proc/gdbserial/rr_test.go index 9f31de1a9..43c2a939a 100644 --- a/pkg/proc/gdbserial/rr_test.go +++ b/pkg/proc/gdbserial/rr_test.go @@ -10,10 +10,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/gdbserial/undo.go b/pkg/proc/gdbserial/undo.go new file mode 100644 index 000000000..ef8150ddd --- /dev/null +++ b/pkg/proc/gdbserial/undo.go @@ -0,0 +1,902 @@ +package gdbserial + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "os/exec" + "os/user" + "path/filepath" + "regexp" + "runtime" + "sort" + "strconv" + "strings" + "syscall" + + "github.com/undoio/delve/pkg/proc" + "golang.org/x/mod/semver" +) + +// State relating to an Undo "session" - used to correctly interpret and handle time-travel +// 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. +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? + sessionState *session // The most recently loaded / saved session state file contents. +} + +// Create a new undoSession structure. +func newUndoSession() *undoSession { + return &undoSession{ + checkpointNextId: 1, + checkpoints: make(map[int]proc.Checkpoint), + volatile: false, + sessionState: nil, + } +} + +// 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 { + 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(conn *gdbConn, where string) (int, error) { + err := validateCheckpointNote(where) + if err != nil { + return -1, err + } + cpid := uc.checkpointNextId + uc.checkpointNextId++ + when, err := undoCmd(conn, "get_time") + if err != nil { + return -1, err + } + uc.checkpoints[cpid] = proc.Checkpoint{ID: cpid, When: when, Where: where} + uc.save(conn) + 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(conn *gdbConn, id int) { + delete(uc.checkpoints, id) + uc.save(conn) +} + +// 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 +} + +// 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. +// +// Delve can only generate complete state for a v0 session file (which just contains the bookmarks +// data). When saving state for a recording that does not already have a session file it will use +// version 1. +// +// When saving state for a recording that already had a session file it will use that same format +// again at save time. That means it will pass through, unmodified, any of the UDB-only fields. +// +// To make this happen, all fields from the v1 telemetry format are tagged "omitempty". +type session struct { + Version int `json:"version,omitempty"` + Bookmarks map[string]bookmarkTime `json:"bookmarks"` + UndoStack interface{} `json:"undo_stack,omitempty"` + UndoStackIndex interface{} `json:"undo_stack_index,omitempty"` + Breakpoints interface{} `json:"breakpoints,omitempty"` + BreakpointsMax interface{} `json:"breakpoints_max,omitempty"` + TimeLimits interface{} `json:"time_limits,omitempty"` + WallClockTimeZone interface{} `json:"wallclock_timezone,omitempty"` + ReplayStandardStreams interface{} `json:"replay_standard_streams,omitempty"` + SelectedTid interface{} `json:"selected_tid,omitempty"` + SharedLibraryPaths interface{} `json:"shared_library_search_paths,omitempty"` + SignalStance interface{} `json:"signal_stance,omitempty"` + SourceDirectories interface{} `json:"source_directories,omitempty"` + SubstitutePaths interface{} `json:"substitute_paths,omitempty"` + Sysroot interface{} `json:"sysroot,omitempty"` + ConvenienceVariables interface{} `json:"convenience_variables,omitempty"` + TelemetryId interface{} `json:"telemetry_id,omitempty"` +} + +// Get the path to the UDB session file for the current recording. +func getSessionPath(conn *gdbConn) (string, error) { + user, err := user.Current() + if err != nil { + return "", err + } + recording_ids, err := undoCmd(conn, "get_recording_ids") + if err != nil { + return "", err + } + uuids := strings.Split(recording_ids, ";") + // We may get 3 or 4 UUIDs depending on the version of the server, since more recent + // versions also return a common UUID for the whole process tree. + if n := len(uuids); n < 3 || n > 4 || uuids[1] == "" { + panic(fmt.Sprintf("unexpected response from get_recording_ids: got %d UUIDs: %v", n, uuids)) + } + + // This directory is used to determine where the sessions are stored, unless XDG_DATA_HOME + // is set. + home_dir, present := os.LookupEnv("HOME") + if !present { + home_dir = user.HomeDir + } + + // This directory stores sessions. + xdg_data_dir, present := os.LookupEnv("XDG_DATA_HOME") + if !present { + xdg_data_dir = filepath.Join(home_dir, ".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(conn *gdbConn) error { + path, err := getSessionPath(conn) + if err != nil { + return err + } + + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + decoder := json.NewDecoder(file) + decoder.DisallowUnknownFields() + + // Clear out the session data. + *uc = *newUndoSession() + + uc.sessionState = &session{} + err = decoder.Decode(uc.sessionState) + if err != nil { + return err + } + + if uc.sessionState.Version != 0 && uc.sessionState.Version != 1 { + return fmt.Errorf("Unknown session version %d in file %s", uc.sessionState.Version, path) + } + + // Translate the loaded Undo bookmarks into Delve checkpoints. + for name, position := range uc.sessionState.Bookmarks { + cpid := uc.checkpointNextId + uc.checkpointNextId++ + 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(conn *gdbConn) error { + // Translate Delve checkpoints into Undo bookmarks. + if uc.sessionState == nil { + // If we don't already have a session state cached from a previous load then we'll + // use a version 0 representation as Delve doesn't generate appropriate state for + // the other fields in the version 1 format. + // + // All new-to-v1 fields are tagged "omitempty" and will not be written out. + uc.sessionState = &session{ + Version: 0, + } + } + uc.sessionState.Bookmarks = make(map[string]bookmarkTime) + + // Local copy of the checkpoints. + 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; uc.sessionState.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 + } + uc.sessionState.Bookmarks[name] = time + } + + path, err := getSessionPath(conn) + if err != nil { + return err + } + + file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + defer file.Close() + + encoder := json.NewEncoder(file) + encoder.SetIndent("", " ") + err = encoder.Encode(uc.sessionState) + 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. +func (uc *undoSession) resolveUserTime(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 if pos != "" { + // 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(conn *gdbConn, pos string) error { + var args []string + switch pos { + case "start", "": + // Find the actual min BB count. + minBbCount, _, err := undoGetLogExtent(conn) + if err != nil { + return err + } + args = []string{"goto_time", fmt.Sprint(minBbCount), "0"} + case "end": + args = []string{"goto_record_mode"} + default: + args = []string{"goto_time", pos} + } + _, err := undoCmd(conn, args...) + 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(conn *gdbConn) (func(), error) { + if uc.volatile { + panic("tried to activate volatile mode when already active.") + } + _, err := undoCmd(conn, "set_volatile_mode", "1") + if err != nil { + return nil, err + } + uc.volatile = true + return func() { + uc.volatile = false + _, _ = undoCmd(conn, "set_volatile_mode", "0") + }, 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 { + case "amd64": + return "udbserver_x64", nil + case "arm64": + return "udbserver_arm64", nil + case "386": + return "udbserver_x32", nil + default: + return "", &ErrBackendUnavailable{} + } +} + +// 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, "tools", server_file) + + return cmd_path, nil +} + +func UndoIsAvailable() error { + const MinimumVersion = "v8.2.0" + + server, err := serverPath() + if err != nil { + return err + } + + cmds := []string{server, "live-record"} + + for _, cmd := range cmds { + if _, err := exec.LookPath(cmd); err != nil { + return &ErrBackendUnavailable{ + Detail: "unable to find an Undo " + MinimumVersion + "+ installation on the current PATH"} + } + } + + /* Check we're using a sufficiently new version of Undo */ + versionCmd := exec.Command(server, "--version") + var out strings.Builder + versionCmd.Stdout = &out + err = versionCmd.Run() + if err != nil { + return &ErrBackendUnavailable{ + Detail: "unable to check Undo version", + } + } + + versionRe := regexp.MustCompile("^udbserver ([0-9]+\\.[0-9]+\\.[0-9]+)") + matches := versionRe.FindStringSubmatch(out.String()) + if len(matches) != 2 { + return &ErrBackendUnavailable{ + Detail: "unable to check Undo version from " + out.String(), + } + } + + /* The semver package requires a leading 'v', so add one */ + if semver.Compare("v"+matches[1], MinimumVersion) < 0 { + return &ErrBackendUnavailable{ + Detail: "Undo version " + matches[1] + " too old (required " + MinimumVersion + ")", + } + } + + return nil +} + +func UndoRecord(cmd []string, wd string, quiet bool, stdin string, stdout proc.OutputRedirect, stderr proc.OutputRedirect) (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(stdin, stdout, stderr, 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, exePath string, quiet bool, debugInfoDirs []string, cmdline 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 := serverPath() + 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) + + // 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() + + p.tracedir = recording + tgt, err = p.Dial(port, exePath, cmdline, 0, debugInfoDirs, proc.StopAttached) + if err != nil { + servercmd.Process.Kill() + return nil, err + } + + // Load the session details if possible (discarding errors, which are non-fatal). + _ = p.conn.undoSession.load(&p.conn) + + return tgt, nil +} + +// RecordAndReplay acts like calling Record and then Replay. +func UndoRecordAndReplay(cmd []string, wd string, quiet bool, debugInfoDirs []string, stdin string, stdout proc.OutputRedirect, stderr proc.OutputRedirect) (tgt *proc.TargetGroup, recording string, err error) { + recording, err = UndoRecord(cmd, wd, quiet, stdin, stdout, stderr) + if err != nil || recording == "" { + return nil, "", err + } + tgt, err = UndoReplay(recording, "", quiet, debugInfoDirs, strings.Join(cmd, " ")) + 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 +} + +// Fetch the local path to the main executable in a recording. +// +// This should always be present in a recording and can then be queried for symbol information, etc. +func undoGetExePath(conn *gdbConn) (string, error) { + path, err := undoCmd(conn, "get_load_exe_original") + if err != nil { + return "", err + } + path, ok := decodeHexString([]byte(path)) + if !ok { + return "", errors.New("failed to decode load exe") + } + + tmpdir, err := undoCmd(conn, "get_tmpdir") + if err != nil { + return "", err + } + tmpdir, ok = decodeHexString([]byte(tmpdir)) + if !ok { + return "", errors.New("failed to decode tmpdir") + } + + return filepath.Join(tmpdir, "symbol-files", path), 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 := undoCmd(conn, "get_info") + if err != nil { + return nil, err + } + splitter := func(c rune) bool { + return c == ';' || c == ',' + } + return strings.FieldsFunc(info, splitter), nil +} + +// Fetch the mininum and maximum bbcounts of recorded history. +func undoGetLogExtent(conn *gdbConn) (uint64, uint64, error) { + extent, err := undoCmd(conn, "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 start of recorded history. +func undoInfoAtStart(info_fields []string) bool { + for _, value := range info_fields { + if value == "at_event_log_start" { + return true + } + } + return false +} + +// Fetch whether the replay session is currently at the end of recorded history. +func undoInfoAtEnd(info_fields []string) bool { + for _, value := range info_fields { + if value == "has_exited" || value == "just_exited" || value == "at_event_log_end" { + return true + } + } + return false +} + +// 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?. + + info_fields, err := undoGetInfo(conn) + if err != nil { + return stopPacket{}, err + } + + at_end := undoInfoAtEnd(info_fields) + 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 + } + + at_start := undoInfoAtStart(info_fields) + if at_start { + // Mirror the behaviour of rr, in which the server will send a fake Signal 0 when it + // reaches the start of the process history. + sp.sig = 0 + return sp, nil + } + + 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 { + // Support older and newer serial protocol behaviour. + if value != "just_exited" && 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 +} + +// Print a bbcount and PC pair in standard Undo time notiation. +func undoTimeString(bbcount uint64, pc uint64) string { + 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. +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 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 := undoCmd(conn, "get_time") + if err != nil { + return "", err + } + + bbcount, pc, err := undoParseServerTime(resp) + if err != nil { + return "", err + } + + // Calculate our percentage through available history. + bbcount_min, bbcount_max, err := undoGetLogExtent(conn) + if err != nil { + return "", err + } + + history_perc := uint64(100) + if bbcount_min != bbcount_max { + history_perc = ((bbcount - bbcount_min) * 100) / (bbcount_max - bbcount_min) + } + + history_perc_fmt := fmt.Sprintf("%d%%", history_perc) + result := fmt.Sprintf("[replaying %s %s]", history_perc_fmt, undoTimeString(bbcount, pc)) + return result, nil +} diff --git a/pkg/proc/gdbserial/undo_test.go b/pkg/proc/gdbserial/undo_test.go new file mode 100644 index 000000000..6cb917184 --- /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(t, 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{}, "", proc.OutputRedirect{}, proc.OutputRedirect{}) + 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 := proc.ThreadLocation(p.CurrentThread()) + 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 := proc.ThreadLocation(p.CurrentThread()) + 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 := proc.ThreadLocation(p.CurrentThread()) + assertNoError(err, t, "CurrentThread().Location()") + + assertNoError(grp.Restart(""), t, "Restart") + + assertNoError(grp.Continue(), t, "Continue (after restart)") + loc2, err := proc.ThreadLocation(p.CurrentThread()) + 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, _ := proc.ThreadLocation(p.CurrentThread()) + 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, _ := proc.ThreadLocation(p.CurrentThread()) + 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/i386_arch.go b/pkg/proc/i386_arch.go index bf23bdb06..f2f25bc0d 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 cd66aa59b..12c70174f 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 4b17cd683..b154522bb 100644 --- a/pkg/proc/interface.go +++ b/pkg/proc/interface.go @@ -4,8 +4,8 @@ import ( "sync" "time" - "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 68070e3dd..65ca52a65 100644 --- a/pkg/proc/internal/ebpf/dummy.go +++ b/pkg/proc/internal/ebpf/dummy.go @@ -8,6 +8,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 c9c67b3df..8d41dbfb0 100644 --- a/pkg/proc/internal/ebpf/helpers.go +++ b/pkg/proc/internal/ebpf/helpers.go @@ -11,8 +11,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 e70e4639b..0f86357ec 100644 --- a/pkg/proc/internal/ebpf/helpers_test.go +++ b/pkg/proc/internal/ebpf/helpers_test.go @@ -6,7 +6,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 any) { diff --git a/pkg/proc/linutil/dynamic.go b/pkg/proc/linutil/dynamic.go index 9668c6d12..da2bbbb58 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/linutil/regs_loong64_arch.go b/pkg/proc/linutil/regs_loong64_arch.go index 9b6d1cb03..6e07a9f42 100644 --- a/pkg/proc/linutil/regs_loong64_arch.go +++ b/pkg/proc/linutil/regs_loong64_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" ) // LOONG64Registers is a wrapper for sys.PtraceRegs. diff --git a/pkg/proc/linutil/regs_ppc64le_arch.go b/pkg/proc/linutil/regs_ppc64le_arch.go index adcf3164a..705ae3e6a 100644 --- a/pkg/proc/linutil/regs_ppc64le_arch.go +++ b/pkg/proc/linutil/regs_ppc64le_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" ) // PPC64LERegisters implements the proc.Registers interface for the native/linux diff --git a/pkg/proc/linutil/regs_riscv64_arch.go b/pkg/proc/linutil/regs_riscv64_arch.go index 726bd67bf..82910bdae 100644 --- a/pkg/proc/linutil/regs_riscv64_arch.go +++ b/pkg/proc/linutil/regs_riscv64_arch.go @@ -4,9 +4,9 @@ import ( "encoding/binary" "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" "golang.org/x/arch/riscv64/riscv64asm" ) diff --git a/pkg/proc/loong64_arch.go b/pkg/proc/loong64_arch.go index b46c77023..c18de4a65 100644 --- a/pkg/proc/loong64_arch.go +++ b/pkg/proc/loong64_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" ) // Break Instruction : 0x002a0000 diff --git a/pkg/proc/loong64_disasm.go b/pkg/proc/loong64_disasm.go index 33c07b7cf..b0af6bec5 100644 --- a/pkg/proc/loong64_disasm.go +++ b/pkg/proc/loong64_disasm.go @@ -1,8 +1,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/loong64/loong64asm" ) diff --git a/pkg/proc/mapiter.go b/pkg/proc/mapiter.go index eca4c12e4..d699f7da0 100644 --- a/pkg/proc/mapiter.go +++ b/pkg/proc/mapiter.go @@ -5,8 +5,8 @@ import ( "fmt" "reflect" - "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" ) type mapIterator interface { diff --git a/pkg/proc/mem.go b/pkg/proc/mem.go index c309a3de2..125f1060f 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_freebsd.go b/pkg/proc/native/dump_freebsd.go index c4e1a9762..55d27190f 100644 --- a/pkg/proc/native/dump_freebsd.go +++ b/pkg/proc/native/dump_freebsd.go @@ -4,8 +4,8 @@ import ( "errors" "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" ) /* diff --git a/pkg/proc/native/dump_linux.go b/pkg/proc/native/dump_linux.go index 78c1d5ca8..9ba595a3d 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 f802046d0..1a75ada4c 100644 --- a/pkg/proc/native/dump_linux_amd64.go +++ b/pkg/proc/native/dump_linux_amd64.go @@ -8,8 +8,8 @@ import ( "os" "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 27533aec2..7f18ea67a 100644 --- a/pkg/proc/native/dump_linux_other.go +++ b/pkg/proc/native/dump_linux_other.go @@ -3,7 +3,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 dbe3b5622..4ae1aa053 100644 --- a/pkg/proc/native/dump_other.go +++ b/pkg/proc/native/dump_other.go @@ -3,8 +3,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 9c080eea7..83ca30e66 100644 --- a/pkg/proc/native/hwbreak_other.go +++ b/pkg/proc/native/hwbreak_other.go @@ -5,7 +5,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 bbeafeb94..495f851b7 100644 --- a/pkg/proc/native/nonative_darwin.go +++ b/pkg/proc/native/nonative_darwin.go @@ -5,10 +5,10 @@ package native import ( "errors" - "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 2dda5be94..11bced43a 100644 --- a/pkg/proc/native/proc.go +++ b/pkg/proc/native/proc.go @@ -7,7 +7,7 @@ import ( "sync/atomic" "time" - "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 aafa5d5f0..540aa707c 100644 --- a/pkg/proc/native/proc_darwin.go +++ b/pkg/proc/native/proc_darwin.go @@ -17,9 +17,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 ec93a40ae..7c03a7235 100644 --- a/pkg/proc/native/proc_freebsd.go +++ b/pkg/proc/native/proc_freebsd.go @@ -29,9 +29,9 @@ import ( sys "golang.org/x/sys/unix" - "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/undoio/delve/pkg/logflags" + "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 cb79c8da9..56799d90d 100644 --- a/pkg/proc/native/proc_linux.go +++ b/pkg/proc/native/proc_linux.go @@ -18,10 +18,10 @@ import ( sys "golang.org/x/sys/unix" - "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/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" isatty "github.com/mattn/go-isatty" ) diff --git a/pkg/proc/native/proc_windows.go b/pkg/proc/native/proc_windows.go index 124e29123..0a29ea8cb 100644 --- a/pkg/proc/native/proc_windows.go +++ b/pkg/proc/native/proc_windows.go @@ -10,9 +10,8 @@ import ( sys "golang.org/x/sys/windows" - "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/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 3ddbc42e9..833b68769 100644 --- a/pkg/proc/native/ptrace_freebsd_amd64.go +++ b/pkg/proc/native/ptrace_freebsd_amd64.go @@ -10,8 +10,8 @@ import ( "fmt" "unsafe" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/native/cpuid" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/native/cpuid" ) var ( diff --git a/pkg/proc/native/ptrace_linux_386.go b/pkg/proc/native/ptrace_linux_386.go index af3e8d5d7..295ff3438 100644 --- a/pkg/proc/native/ptrace_linux_386.go +++ b/pkg/proc/native/ptrace_linux_386.go @@ -7,8 +7,8 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/native/cpuid" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/native/cpuid" ) // 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 44d483262..18e9f1a20 100644 --- a/pkg/proc/native/ptrace_linux_amd64.go +++ b/pkg/proc/native/ptrace_linux_amd64.go @@ -6,8 +6,8 @@ import ( sys "golang.org/x/sys/unix" - "github.com/go-delve/delve/pkg/proc/amd64util" - "github.com/go-delve/delve/pkg/proc/native/cpuid" + "github.com/undoio/delve/pkg/proc/amd64util" + "github.com/undoio/delve/pkg/proc/native/cpuid" ) // 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 4d00c3d7e..1e021b352 100644 --- a/pkg/proc/native/registers_darwin_amd64.go +++ b/pkg/proc/native/registers_darwin_amd64.go @@ -10,9 +10,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_linux_loong64.go b/pkg/proc/native/registers_linux_loong64.go index c32cb63b1..02f70d77f 100644 --- a/pkg/proc/native/registers_linux_loong64.go +++ b/pkg/proc/native/registers_linux_loong64.go @@ -11,9 +11,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_linux_ppc64le.go b/pkg/proc/native/registers_linux_ppc64le.go index 5094057a5..a3a285abd 100644 --- a/pkg/proc/native/registers_linux_ppc64le.go +++ b/pkg/proc/native/registers_linux_ppc64le.go @@ -5,9 +5,9 @@ import ( "syscall" "unsafe" - "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" sys "golang.org/x/sys/unix" ) diff --git a/pkg/proc/native/registers_linux_riscv64.go b/pkg/proc/native/registers_linux_riscv64.go index d1796b3bc..9b135c6ae 100644 --- a/pkg/proc/native/registers_linux_riscv64.go +++ b/pkg/proc/native/registers_linux_riscv64.go @@ -8,9 +8,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" ) // Defined in asm/ptrace.h 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 56ae4529f..b211309fe 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 5be7c415b..8e15610ee 100644 --- a/pkg/proc/native/threads_darwin.go +++ b/pkg/proc/native/threads_darwin.go @@ -12,8 +12,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 94ee83340..ee7e341d4 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_hardware_singlestep_linux.go b/pkg/proc/native/threads_hardware_singlestep_linux.go index 774178662..ffd1b3d9b 100644 --- a/pkg/proc/native/threads_hardware_singlestep_linux.go +++ b/pkg/proc/native/threads_hardware_singlestep_linux.go @@ -3,7 +3,7 @@ package native import ( - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" sys "golang.org/x/sys/unix" ) 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_linux_loong64.go b/pkg/proc/native/threads_linux_loong64.go index c17b726b5..46fac5637 100644 --- a/pkg/proc/native/threads_linux_loong64.go +++ b/pkg/proc/native/threads_linux_loong64.go @@ -11,8 +11,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_linux_ppc64le.go b/pkg/proc/native/threads_linux_ppc64le.go index 94ce21ff4..7fe074e1a 100644 --- a/pkg/proc/native/threads_linux_ppc64le.go +++ b/pkg/proc/native/threads_linux_ppc64le.go @@ -8,8 +8,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 (t *nativeThread) fpRegisters() ([]proc.Register, []byte, error) { diff --git a/pkg/proc/native/threads_linux_riscv64.go b/pkg/proc/native/threads_linux_riscv64.go index 1a1b34fb7..28dad89ae 100644 --- a/pkg/proc/native/threads_linux_riscv64.go +++ b/pkg/proc/native/threads_linux_riscv64.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" "golang.org/x/arch/riscv64/riscv64asm" ) 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/pclntab.go b/pkg/proc/pclntab.go index fc3bf6452..e78fa875c 100644 --- a/pkg/proc/pclntab.go +++ b/pkg/proc/pclntab.go @@ -6,7 +6,7 @@ import ( "errors" "fmt" - "github.com/go-delve/delve/pkg/internal/gosym" + "github.com/undoio/delve/pkg/internal/gosym" ) func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, uint64, error) { diff --git a/pkg/proc/ppc64le_arch.go b/pkg/proc/ppc64le_arch.go index 00ed4df5a..0496f0e8d 100644 --- a/pkg/proc/ppc64le_arch.go +++ b/pkg/proc/ppc64le_arch.go @@ -5,10 +5,10 @@ import ( "fmt" "strings" - "github.com/go-delve/delve/pkg/dwarf/frame" + "github.com/undoio/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/op" + "github.com/undoio/delve/pkg/dwarf/regnum" ) // This is the unconditional trap, the same mnemonic that both clang and gcc use diff --git a/pkg/proc/ppc64le_disasm.go b/pkg/proc/ppc64le_disasm.go index fbf16c96c..1825d9291 100644 --- a/pkg/proc/ppc64le_disasm.go +++ b/pkg/proc/ppc64le_disasm.go @@ -3,8 +3,8 @@ package proc import ( "encoding/binary" - "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/ppc64/ppc64asm" ) diff --git a/pkg/proc/proc_amd64_test.go b/pkg/proc/proc_amd64_test.go index 0443f62a5..c135f0a27 100644 --- a/pkg/proc/proc_amd64_test.go +++ b/pkg/proc/proc_amd64_test.go @@ -6,10 +6,10 @@ import ( "runtime" "testing" - "github.com/go-delve/delve/pkg/dwarf/regnum" - "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/dwarf/regnum" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/proc" + protest "github.com/undoio/delve/pkg/proc/test" ) func TestStepInstructionOnBreakpoint(t *testing.T) { @@ -33,6 +33,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()") @@ -41,6 +42,7 @@ func TestNextUnknownInstr(t *testing.T) { } func TestIssue1656(t *testing.T) { + 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()") @@ -58,6 +60,7 @@ func TestBreakpointConfusionOnResume(t *testing.T) { // native.(*Thread).singleStep all agree on which breakpoint the thread is // stopped at. // This test checks for a regression introduced when fixing Issue #1656 + 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")) diff --git a/pkg/proc/proc_darwin_amd64_test.go b/pkg/proc/proc_darwin_amd64_test.go index ef8700592..42faf5f93 100644 --- a/pkg/proc/proc_darwin_amd64_test.go +++ b/pkg/proc/proc_darwin_amd64_test.go @@ -3,11 +3,11 @@ package proc_test import ( "testing" - "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" - protest "github.com/go-delve/delve/pkg/proc/test" + protest "github.com/undoio/delve/pkg/proc/test" ) func TestSetYMMRegister(t *testing.T) { diff --git a/pkg/proc/proc_darwin_test.go b/pkg/proc/proc_darwin_test.go index 52b7d8413..65d4dc0a9 100644 --- a/pkg/proc/proc_darwin_test.go +++ b/pkg/proc/proc_darwin_test.go @@ -3,8 +3,8 @@ package proc_test import ( "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 TestStacktraceExtlinkMac(t *testing.T) { diff --git a/pkg/proc/proc_general_test.go b/pkg/proc/proc_general_test.go index 86e5b2de8..ffb111c46 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 { @@ -161,20 +161,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 31ce72ce1..4b8e0434d 100644 --- a/pkg/proc/proc_linux_test.go +++ b/pkg/proc/proc_linux_test.go @@ -9,9 +9,9 @@ import ( "strings" "testing" - "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" ) func mustHaveObjcopy(t *testing.T) { diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 4278cd84f..c200ccdb4 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -28,16 +28,16 @@ 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/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/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} @@ -95,19 +95,23 @@ func withTestProcessArgs(name string, t testing.TB, wd string, args []string, bu } fixture := protest.BuildFixture(t, name, buildFlags) - grp := startTestProcessArgs(fixture, t, wd, args) + grp, recording := startTestProcessArgs(fixture, t, wd, args) defer func() { grp.Detach(true) + if recording != "" { + os.Remove(recording) + } }() fn(grp.Selected, grp, fixture) } -func startTestProcessArgs(fixture protest.Fixture, t testing.TB, wd string, args []string) *proc.TargetGroup { +func startTestProcessArgs(fixture protest.Fixture, t testing.TB, wd string, args []string) (*proc.TargetGroup, string) { var grp *proc.TargetGroup var err error var tracedir string + var recording string switch testBackend { case "native": @@ -119,13 +123,19 @@ func startTestProcessArgs(fixture protest.Fixture, t testing.TB, wd string, args t.Log("recording") grp, tracedir, err = gdbserial.RecordAndReplay(append([]string{fixture.Path}, args...), wd, true, true, []string{}, "", proc.OutputRedirect{}, proc.OutputRedirect{}) 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{}, "", proc.OutputRedirect{}, proc.OutputRedirect{}) + t.Logf("replaying") default: t.Fatal("unknown backend") } if err != nil { t.Fatal("Launch():", err) } - return grp + + return grp, recording } func getRegisters(p *proc.Target, t *testing.T) proc.Registers { @@ -409,6 +419,7 @@ func TestBreakpointWithNonExistentFunction(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") @@ -923,6 +934,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) }) @@ -1040,7 +1052,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 { @@ -1157,6 +1169,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()") @@ -1588,6 +1601,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) grp.ChangeBreakpointCondition(bp.Logical, "", "== 3", false) @@ -1817,6 +1831,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) }) @@ -1857,6 +1872,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) @@ -2085,6 +2101,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") @@ -2411,7 +2428,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 @@ -2553,7 +2570,7 @@ func TestAttachDetach(t *testing.T) { return } } - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { return } var buildFlags protest.BuildFlags @@ -2743,6 +2760,7 @@ func TestIssue877(t *testing.T) { } const envval = "/usr/local/lib" t.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") @@ -2793,7 +2811,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 { @@ -2947,6 +2965,7 @@ func TestDebugStripped2(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) @@ -3181,6 +3200,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"} { @@ -3201,6 +3221,7 @@ func TestCgoSources(t *testing.T) { func TestSystemstackStacktrace(t *testing.T) { skipOn(t, "broken", "ppc64le") // 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") @@ -3257,6 +3278,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()") @@ -3277,6 +3299,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()") @@ -3323,6 +3346,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) @@ -3363,6 +3387,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") @@ -3469,6 +3494,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() @@ -3510,6 +3536,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 { @@ -3574,6 +3601,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") @@ -3656,6 +3684,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 { @@ -3676,6 +3705,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 { @@ -3797,6 +3827,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") @@ -3845,6 +3876,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() { @@ -3865,6 +3897,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"} @@ -4030,6 +4063,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()") @@ -4059,6 +4093,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()") @@ -4096,6 +4131,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()") @@ -4156,6 +4192,7 @@ func TestListImages(t *testing.T) { func TestAncestors(t *testing.T) { t.Setenv("GODEBUG", "tracebackancestors=100") + 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()") @@ -4318,6 +4355,7 @@ func TestBreakpointMaterializedEvent(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") @@ -4327,6 +4365,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{ @@ -4352,6 +4391,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) { err := grp.Continue() if _, exited := err.(proc.ErrProcessExited); exited { @@ -4368,6 +4408,7 @@ func TestCgoStacktrace2(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)") @@ -4383,12 +4424,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)) @@ -4537,6 +4580,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()") @@ -4871,6 +4915,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") @@ -5038,6 +5083,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()") @@ -5199,6 +5245,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()") @@ -5659,7 +5706,7 @@ func TestWaitForAttach(t *testing.T) { return } } - if testBackend == "rr" { + if testBackend == "rr" || testBackend == "undo" { return } @@ -5988,7 +6035,10 @@ func TestChainedBreakpoint(t *testing.T) { t.Logf("=== Restart ===") - grp2 := startTestProcessArgs(fixture, t, ".", []string{}) + grp2, recording := startTestProcessArgs(fixture, t, ".", []string{}) + defer func () { + os.Remove(recording) + }() proc.Restart(grp2, grp, func(lbp *proc.LogicalBreakpoint, err error) { t.Fatalf("discarded logical breakpoint %v: %v", lbp, err) }) diff --git a/pkg/proc/proc_unix_test.go b/pkg/proc/proc_unix_test.go index 8b0bbbadf..f2b545421 100644 --- a/pkg/proc/proc_unix_test.go +++ b/pkg/proc/proc_unix_test.go @@ -13,9 +13,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 { @@ -28,7 +28,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/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/riscv64_arch.go b/pkg/proc/riscv64_arch.go index 5c25ca87c..fca2a0afe 100644 --- a/pkg/proc/riscv64_arch.go +++ b/pkg/proc/riscv64_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" ) // ebreak instruction: 0x00100073 diff --git a/pkg/proc/riscv64_disasm.go b/pkg/proc/riscv64_disasm.go index 0a2be1236..82860061f 100644 --- a/pkg/proc/riscv64_disasm.go +++ b/pkg/proc/riscv64_disasm.go @@ -1,8 +1,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/riscv64/riscv64asm" ) diff --git a/pkg/proc/scope_test.go b/pkg/proc/scope_test.go index 8829e4e27..f4562e1bf 100644 --- a/pkg/proc/scope_test.go +++ b/pkg/proc/scope_test.go @@ -14,9 +14,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) { @@ -24,6 +24,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") @@ -73,6 +74,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/stack.go b/pkg/proc/stack.go index 1792e48db..06c09852f 100644 --- a/pkg/proc/stack.go +++ b/pkg/proc/stack.go @@ -10,10 +10,10 @@ import ( "reflect" "strings" - "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/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/dwarf/frame" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/logflags" ) // This code is partly adapted from runtime.gentraceback in diff --git a/pkg/proc/stack_sigtramp.go b/pkg/proc/stack_sigtramp.go index e66d94dc8..b7f96c5bf 100644 --- a/pkg/proc/stack_sigtramp.go +++ b/pkg/proc/stack_sigtramp.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/logflags" + "github.com/undoio/delve/pkg/dwarf/op" + "github.com/undoio/delve/pkg/dwarf/regnum" + "github.com/undoio/delve/pkg/logflags" ) // readSigtrampgoContext reads runtime.sigtrampgo context at the specified address diff --git a/pkg/proc/stackwatch.go b/pkg/proc/stackwatch.go index ff9b94901..1bac6c288 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/stepping_test.go b/pkg/proc/stepping_test.go index cb78f2641..38e6ff84c 100644 --- a/pkg/proc/stepping_test.go +++ b/pkg/proc/stepping_test.go @@ -9,10 +9,10 @@ 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/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/goversion" + "github.com/undoio/delve/pkg/proc" + protest "github.com/undoio/delve/pkg/proc/test" + "github.com/undoio/delve/service/api" ) type nextTest struct { @@ -433,8 +433,8 @@ func TestInlineStepOut(t *testing.T) { } 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}, @@ -464,8 +464,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}, @@ -476,8 +476,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}, @@ -515,8 +515,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/target.go b/pkg/proc/target.go index be7257280..34d016809 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 e665fe10f..ed7a0dd45 100644 --- a/pkg/proc/target_exec.go +++ b/pkg/proc/target_exec.go @@ -15,10 +15,10 @@ import ( "golang.org/x/arch/ppc64/ppc64asm" - "github.com/go-delve/delve/pkg/astutil" - "github.com/go-delve/delve/pkg/dwarf/godwarf" - "github.com/go-delve/delve/pkg/dwarf/reader" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/astutil" + "github.com/undoio/delve/pkg/dwarf/godwarf" + "github.com/undoio/delve/pkg/dwarf/reader" + "github.com/undoio/delve/pkg/logflags" ) const maxSkipAutogeneratedWrappers = 5 // maximum recursion depth for skipAutogeneratedWrappers @@ -145,6 +145,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 diff --git a/pkg/proc/target_group.go b/pkg/proc/target_group.go index 54adc7277..26386d913 100644 --- a/pkg/proc/target_group.go +++ b/pkg/proc/target_group.go @@ -9,7 +9,7 @@ import ( "strconv" "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 18b50f78e..91aaaf61b 100644 --- a/pkg/proc/test/support.go +++ b/pkg/proc/test/support.go @@ -15,7 +15,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. @@ -493,7 +493,7 @@ func getDlvBinInternal(t *testing.T, goflags ...string) string { AddPathToRemove(dlvbin) 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 %s: %v\n%s", strings.Join(args, " "), err, string(out)) diff --git a/pkg/proc/threads.go b/pkg/proc/threads.go index 4fb78b3b9..e541e2502 100644 --- a/pkg/proc/threads.go +++ b/pkg/proc/threads.go @@ -3,7 +3,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 ea4343409..53964e15b 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 1618a6bbb..8cb24cf10 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 fffe79d2c..dab92e46a 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -18,10 +18,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 6431981d6..2477e1299 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 c1a2bc6aa..e9aa4373f 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -13,11 +13,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{ @@ -76,7 +76,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) @@ -258,7 +258,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()") @@ -503,7 +503,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 { @@ -1177,18 +1177,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}, @@ -1198,7 +1198,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{ @@ -1241,6 +1241,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 { @@ -1257,6 +1258,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()") @@ -1325,7 +1327,7 @@ func TestCallFunction(t *testing.T) { {`fn2glob(10, 20)`, []string{":int:30"}, nil, 0}, // indirect call of func value / set to top-level func {`fn2clos(11)`, []string{`:string:"1 + 6 + 11 = 18"`}, nil, 0}, // indirect call of func value / set to func literal - {`fn2clos(12)`, []string{`:string:"2 + 6 + 12 = 20"`}, nil, 0}, + // UNDO [#30]: {`fn2clos(12)`, []string{`:string:"2 + 6 + 12 = 20"`}, nil, 0}, {`fn2valmeth(13)`, []string{`:string:"13 + 6 = 19"`}, nil, 0}, // indirect call of func value / set to value method {`fn2ptrmeth(14)`, []string{`:string:"14 - 6 = 8"`}, nil, 0}, // indirect call of func value / set to pointer method @@ -1346,7 +1348,7 @@ func TestCallFunction(t *testing.T) { {`onetwothree(intcallpanic("not a number"))`, nil, altErrors("can not convert \"not a number\" constant to int", "literal string can not be allocated because function calls are not allowed without using 'call'"), 1}, // Variable setting tests - {`pa2 = getAStructPtr(8); pa2`, []string{`pa2:*main.astruct:*main.astruct {X: 8}`}, nil, 1}, + // UNDO [#30]: {`pa2 = getAStructPtr(8); pa2`, []string{`pa2:*main.astruct:*main.astruct {X: 8}`}, nil, 1}, // Escape tests @@ -1367,7 +1369,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, 1}, - {`str = "a new string"; str`, []string{`str:string:"a new string"`}, nil, 1}, + // UNDO [#30]: {`str = "a new string"; str`, []string{`str:string:"a new string"`}, nil, 1}, // support calling optimized functions {`strings.Join(nil, "")`, []string{`:string:""`}, nil, 0}, @@ -1641,6 +1643,7 @@ func TestIssue4051(t *testing.T) { 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()") @@ -1702,9 +1705,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) @@ -1720,7 +1723,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 @@ -1736,12 +1739,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}) @@ -1753,7 +1756,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 807857061..d2f0abcaf 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 eda1ca43a..624def98a 100644 --- a/pkg/terminal/colorize/colorize_test.go +++ b/pkg/terminal/colorize/colorize_test.go @@ -7,8 +7,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 d8f67a6f8..4b6fcd1e7 100644 --- a/pkg/terminal/command.go +++ b/pkg/terminal/command.go @@ -28,12 +28,12 @@ import ( "time" "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 144182b2c..f239c01e7 100644 --- a/pkg/terminal/command_test.go +++ b/pkg/terminal/command_test.go @@ -18,15 +18,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" "github.com/go-delve/liner" ) @@ -121,7 +121,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) } t.Setenv("TERM", "dumb") @@ -342,6 +342,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() @@ -673,7 +674,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) { @@ -687,7 +688,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) { @@ -913,6 +914,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") @@ -929,6 +931,7 @@ func TestPrintContextParkedGoroutine(t *testing.T) { if runtime.GOARCH == "ppc64le" && buildMode == "pie" { t.Skip("pie mode broken on ppc64le") } + test.AllowRecording(t) withTestTerminal("goroutinestackprog", t, func(term *FakeTerminal) { term.MustExec("break stacktraceme") term.MustExec("continue") @@ -968,6 +971,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") @@ -980,6 +984,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") @@ -1006,6 +1011,7 @@ func TestTruncateStacktrace(t *testing.T) { t.Skip("pie mode broken on ppc64le") } const stacktraceTruncatedMessage = "(truncated)" + test.AllowRecording(t) withTestTerminal("stacktraceprog", t, func(term *FakeTerminal) { term.MustExec("break main.stacktraceme") term.MustExec("continue") @@ -1162,6 +1168,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") @@ -1228,6 +1235,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) @@ -1239,6 +1247,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" { @@ -1261,6 +1270,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/pkg/terminal/config.go b/pkg/terminal/config.go index 1405bac64..789d92389 100644 --- a/pkg/terminal/config.go +++ b/pkg/terminal/config.go @@ -7,7 +7,7 @@ import ( "strings" "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 799e3f963..decdbaf93 100644 --- a/pkg/terminal/docgen.go +++ b/pkg/terminal/docgen.go @@ -33,7 +33,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 49563e526..694dbbc24 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 8c1e9202f..865429c89 100644 --- a/pkg/terminal/starbind/starlark.go +++ b/pkg/terminal/starbind/starlark.go @@ -15,9 +15,9 @@ import ( "go.starlark.net/starlark" "go.starlark.net/syntax" - "github.com/go-delve/delve/pkg/logflags" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/pkg/logflags" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" ) //go:generate go run github.com/go-delve/build-tools/cmd/gen-starlark-bindings@latest go ./starlark_mapping.go diff --git a/pkg/terminal/starbind/starlark_mapping.go b/pkg/terminal/starbind/starlark_mapping.go index cb6726924..064eb2c6b 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" ) @@ -367,7 +367,7 @@ func (env *Env) starlarkPredeclare() (starlark.StringDict, map[string]string) { } return env.interfaceToStarlarkValue(&rpcRet), nil }) - doc["create_breakpoint"] = "builtin create_breakpoint(Breakpoint, LocExpr, SubstitutePathRules, Suspended)\n\ncreate_breakpoint creates a new breakpoint. The client is expected to populate `CreateBreakpointIn`\nwith an `api.Breakpoint` struct describing where to set the breakpoint. For more information on\nhow to properly request a breakpoint via the `api.Breakpoint` struct see the documentation for\n`debugger.CreateBreakpoint` here: https://pkg.go.dev/github.com/go-delve/delve/service/debugger#Debugger.CreateBreakpoint." + doc["create_breakpoint"] = "builtin create_breakpoint(Breakpoint, LocExpr, SubstitutePathRules, Suspended)\n\ncreate_breakpoint creates a new breakpoint. The client is expected to populate `CreateBreakpointIn`\nwith an `api.Breakpoint` struct describing where to set the breakpoint. For more information on\nhow to properly request a breakpoint via the `api.Breakpoint` struct see the documentation for\n`debugger.CreateBreakpoint` here: https://pkg.go.dev/github.com/undoio/delve/service/debugger#Debugger.CreateBreakpoint." r["create_ebpf_tracepoint"] = starlark.NewBuiltin("create_ebpf_tracepoint", func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { if err := isCancelled(thread); err != nil { return starlark.None, decorateError(thread, err) @@ -701,7 +701,7 @@ func (env *Env) starlarkPredeclare() (starlark.StringDict, map[string]string) { } return env.interfaceToStarlarkValue(&rpcRet), nil }) - doc["eval"] = "builtin eval(Scope, Expr, Cfg)\n\neval returns a variable in the specified context.\n\nSee https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md\nfor a description of acceptable values of arg.Expr." + doc["eval"] = "builtin eval(Scope, Expr, Cfg)\n\neval returns a variable in the specified context.\n\nSee https://github.com/undoio/delve/blob/master/Documentation/cli/expr.md\nfor a description of acceptable values of arg.Expr." r["examine_memory"] = starlark.NewBuiltin("examine_memory", func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { if err := isCancelled(thread); err != nil { return starlark.None, decorateError(thread, err) diff --git a/pkg/terminal/starlark.go b/pkg/terminal/starlark.go index c28d01d85..340922285 100644 --- a/pkg/terminal/starlark.go +++ b/pkg/terminal/starlark.go @@ -3,9 +3,9 @@ package terminal import ( "slices" - "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 030db8b88..dacb34f6a 100644 --- a/pkg/terminal/terminal.go +++ b/pkg/terminal/terminal.go @@ -16,13 +16,13 @@ import ( "github.com/derekparker/trie/v3" "github.com/go-delve/liner" - "github.com/go-delve/delve/pkg/config" - "github.com/go-delve/delve/pkg/goversion" - "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/goversion" + "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/service/api/conversions.go b/service/api/conversions.go index ed18c8cbc..88160fc86 100644 --- a/service/api/conversions.go +++ b/service/api/conversions.go @@ -8,9 +8,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 b77074957..2cee89a9a 100644 --- a/service/api/types.go +++ b/service/api/types.go @@ -10,7 +10,7 @@ import ( "unicode" "unicode/utf8" - "github.com/go-delve/delve/pkg/proc" + "github.com/undoio/delve/pkg/proc" ) // ErrNotExecutable is an error returned when trying diff --git a/service/api/waitreason.go b/service/api/waitreason.go index db46a6e4c..8c6084c4c 100644 --- a/service/api/waitreason.go +++ b/service/api/waitreason.go @@ -3,7 +3,7 @@ package api import ( "fmt" - "github.com/go-delve/delve/pkg/goversion" + "github.com/undoio/delve/pkg/goversion" ) var waitReasonStrings1dot18 = []string{ diff --git a/service/client.go b/service/client.go index 1734aed94..fc7c1c08f 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 8db0ea6ca..29e97ca45 100644 --- a/service/dap/command.go +++ b/service/dap/command.go @@ -9,8 +9,8 @@ import ( "strconv" "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 b569609c7..bf2cc68f6 100644 --- a/service/dap/config.go +++ b/service/dap/config.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "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 da4eb8650..80bbe2013 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 7fb21ecaf..b1c66edf9 100644 --- a/service/dap/server.go +++ b/service/dap/server.go @@ -33,17 +33,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 @@ -2899,7 +2899,7 @@ func (s *Session) convertVariableWithOpts(v *proc.Variable, qualifiedNameOrExpr 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 cd8311094..89fb2eddd 100644 --- a/service/dap/server_test.go +++ b/service/dap/server_test.go @@ -27,15 +27,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 ( @@ -2840,19 +2840,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", "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", "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, diff --git a/service/dap/types.go b/service/dap/types.go index a94e926b7..3c4102fdb 100644 --- a/service/dap/types.go +++ b/service/dap/types.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service/api" ) // Launch debug sessions support the following modes: diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index c9b1f2cfc..214428d54 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -20,16 +20,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 ( @@ -202,6 +202,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, d.config.RrDelOnDetach, 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, d.processArgs[0], 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) @@ -326,6 +329,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.Stdin, d.config.Stdout, d.config.Stderr) + return tgt, err case "default": if runtime.GOOS == "darwin" { @@ -535,7 +541,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.Stdin, d.config.Stdout, d.config.Stderr) if err2 != nil { return nil, err2 @@ -544,6 +550,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.Stdin, d.config.Stdout, d.config.Stderr) } else { grp, err = d.Launch(d.processArgs, d.config.WorkingDir) } @@ -2247,8 +2255,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/debugger/debugger_test.go b/service/debugger/debugger_test.go index d0c322458..5c1fd8661 100644 --- a/service/debugger/debugger_test.go +++ b/service/debugger/debugger_test.go @@ -9,11 +9,11 @@ import ( "strings" "testing" - "github.com/go-delve/delve/pkg/gobuild" - "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/api" + "github.com/undoio/delve/pkg/gobuild" + "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/api" ) func TestMain(m *testing.M) { diff --git a/service/debugger/debugger_unix_test.go b/service/debugger/debugger_unix_test.go index f6250164e..7da99d89c 100644 --- a/service/debugger/debugger_unix_test.go +++ b/service/debugger/debugger_unix_test.go @@ -13,9 +13,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 f07a81b1e..5a84d51f8 100644 --- a/service/internal/sameuser/sameuser_linux.go +++ b/service/internal/sameuser/sameuser_linux.go @@ -9,7 +9,7 @@ import ( "os" "strings" - "github.com/go-delve/delve/pkg/logflags" + "github.com/undoio/delve/pkg/logflags" ) // for testing diff --git a/service/rpc2/client.go b/service/rpc2/client.go index 911544846..356e4bd0d 100644 --- a/service/rpc2/client.go +++ b/service/rpc2/client.go @@ -13,8 +13,8 @@ import ( "strings" "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. @@ -287,7 +287,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 405fa6358..51faa7f9c 100644 --- a/service/rpc2/server.go +++ b/service/rpc2/server.go @@ -7,11 +7,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 { @@ -266,7 +266,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 breakpoint. 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 @@ -539,7 +539,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 24c71ef55..b340d1d32 100644 --- a/service/rpccommon/server.go +++ b/service/rpccommon/server.go @@ -15,14 +15,14 @@ import ( "runtime" "sync" - "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/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/rpc2" ) //go:generate go run github.com/go-delve/build-tools/cmd/gen-suitablemethods@latest suitablemethods diff --git a/service/rpccommon/suitablemethods.go b/service/rpccommon/suitablemethods.go index fa39ef550..67988a385 100644 --- a/service/rpccommon/suitablemethods.go +++ b/service/rpccommon/suitablemethods.go @@ -3,7 +3,7 @@ package rpccommon import ( - "github.com/go-delve/delve/service/rpc2" + "github.com/undoio/delve/service/rpc2" "reflect" ) diff --git a/service/test/common_test.go b/service/test/common_test.go index 047d0bc74..85d2e8708 100644 --- a/service/test/common_test.go +++ b/service/test/common_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "github.com/go-delve/delve/service" - "github.com/go-delve/delve/service/api" + "github.com/undoio/delve/service" + "github.com/undoio/delve/service/api" ) func assertNoError(err error, t *testing.T, s string) { diff --git a/service/test/integration2_test.go b/service/test/integration2_test.go index c55ae6a32..d1fc93c47 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{ @@ -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() @@ -478,6 +478,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 { @@ -487,6 +488,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 { @@ -521,6 +523,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() @@ -594,6 +597,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) @@ -1016,6 +1020,7 @@ func TestClientServer_FindLocations(t *testing.T) { if runtime.GOARCH == "ppc64le" && buildMode == "pie" { t.Skip("pie mode broken on ppc64le") } + 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] @@ -1130,7 +1135,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) }) } @@ -1219,6 +1224,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" @@ -1619,6 +1625,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 := clientEvalVariable(t, c, "main.callme").Addr @@ -1742,12 +1749,16 @@ 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) }) } 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") } @@ -1925,8 +1936,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}) @@ -2054,6 +2065,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}) @@ -2094,7 +2106,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") @@ -2261,6 +2273,7 @@ func TestAncestors(t *testing.T) { t.Skip("not supported on Go <= 1.10") } t.Setenv("GODEBUG", "tracebackancestors=100") + protest.AllowRecording(t) withTestClient2("testnextprog", t, func(c service.Client) { _, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.testgoroutine", Line: -1}) assertNoError(err, t, "CreateBreakpoint") @@ -2315,6 +2328,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) @@ -2328,7 +2342,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) { @@ -2380,6 +2394,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") @@ -2388,6 +2403,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") @@ -2446,6 +2462,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()") @@ -2482,7 +2499,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() @@ -2524,7 +2541,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 } @@ -2613,6 +2630,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") @@ -2694,6 +2712,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") @@ -2783,7 +2802,7 @@ func TestGenericsBreakpoint(t *testing.T) { } func TestRestartRewindAfterEnd(t *testing.T) { - if testBackend != "rr" { + if testBackend != "rr" && testBackend != "undo" { t.Skip("not relevant") } // Check that Restart works after the program has terminated, even if a @@ -2975,7 +2994,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) @@ -3316,7 +3335,7 @@ func TestGuessSubstitutePath(t *testing.T) { found := false for _, e := range gsp { t.Logf("\t%s -> %s", e[0], e[1]) - if e[0] == "github.com/go-delve/delve" && e[1] == delvePath { + if e[0] == "github.com/undoio/delve" && e[1] == delvePath { found = true } } @@ -3334,7 +3353,7 @@ func TestGuessSubstitutePath(t *testing.T) { found := false for _, e := range gsp { t.Logf("\t%s -> %s", e[0], e[1]) - if e[0] == "github.com/go-delve/delve" && e[1] == delvePath { + if e[0] == "github.com/undoio/delve" && e[1] == delvePath { found = true } } diff --git a/vendor/golang.org/x/mod/LICENSE b/vendor/golang.org/x/mod/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/vendor/golang.org/x/mod/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/mod/PATENTS b/vendor/golang.org/x/mod/PATENTS new file mode 100644 index 000000000..733099041 --- /dev/null +++ b/vendor/golang.org/x/mod/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/mod/semver/semver.go b/vendor/golang.org/x/mod/semver/semver.go new file mode 100644 index 000000000..9a2dfd33a --- /dev/null +++ b/vendor/golang.org/x/mod/semver/semver.go @@ -0,0 +1,401 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package semver implements comparison of semantic version strings. +// In this package, semantic version strings must begin with a leading "v", +// as in "v1.0.0". +// +// The general form of a semantic version string accepted by this package is +// +// vMAJOR[.MINOR[.PATCH[-PRERELEASE][+BUILD]]] +// +// where square brackets indicate optional parts of the syntax; +// MAJOR, MINOR, and PATCH are decimal integers without extra leading zeros; +// PRERELEASE and BUILD are each a series of non-empty dot-separated identifiers +// using only alphanumeric characters and hyphens; and +// all-numeric PRERELEASE identifiers must not have leading zeros. +// +// This package follows Semantic Versioning 2.0.0 (see semver.org) +// with two exceptions. First, it requires the "v" prefix. Second, it recognizes +// vMAJOR and vMAJOR.MINOR (with no prerelease or build suffixes) +// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0. +package semver + +import "sort" + +// parsed returns the parsed form of a semantic version string. +type parsed struct { + major string + minor string + patch string + short string + prerelease string + build string +} + +// IsValid reports whether v is a valid semantic version string. +func IsValid(v string) bool { + _, ok := parse(v) + return ok +} + +// Canonical returns the canonical formatting of the semantic version v. +// It fills in any missing .MINOR or .PATCH and discards build metadata. +// Two semantic versions compare equal only if their canonical formattings +// are identical strings. +// The canonical invalid semantic version is the empty string. +func Canonical(v string) string { + p, ok := parse(v) + if !ok { + return "" + } + if p.build != "" { + return v[:len(v)-len(p.build)] + } + if p.short != "" { + return v + p.short + } + return v +} + +// Major returns the major version prefix of the semantic version v. +// For example, Major("v2.1.0") == "v2". +// If v is an invalid semantic version string, Major returns the empty string. +func Major(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + return v[:1+len(pv.major)] +} + +// MajorMinor returns the major.minor version prefix of the semantic version v. +// For example, MajorMinor("v2.1.0") == "v2.1". +// If v is an invalid semantic version string, MajorMinor returns the empty string. +func MajorMinor(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + i := 1 + len(pv.major) + if j := i + 1 + len(pv.minor); j <= len(v) && v[i] == '.' && v[i+1:j] == pv.minor { + return v[:j] + } + return v[:i] + "." + pv.minor +} + +// Prerelease returns the prerelease suffix of the semantic version v. +// For example, Prerelease("v2.1.0-pre+meta") == "-pre". +// If v is an invalid semantic version string, Prerelease returns the empty string. +func Prerelease(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + return pv.prerelease +} + +// Build returns the build suffix of the semantic version v. +// For example, Build("v2.1.0+meta") == "+meta". +// If v is an invalid semantic version string, Build returns the empty string. +func Build(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + return pv.build +} + +// Compare returns an integer comparing two versions according to +// semantic version precedence. +// The result will be 0 if v == w, -1 if v < w, or +1 if v > w. +// +// An invalid semantic version string is considered less than a valid one. +// All invalid semantic version strings compare equal to each other. +func Compare(v, w string) int { + pv, ok1 := parse(v) + pw, ok2 := parse(w) + if !ok1 && !ok2 { + return 0 + } + if !ok1 { + return -1 + } + if !ok2 { + return +1 + } + if c := compareInt(pv.major, pw.major); c != 0 { + return c + } + if c := compareInt(pv.minor, pw.minor); c != 0 { + return c + } + if c := compareInt(pv.patch, pw.patch); c != 0 { + return c + } + return comparePrerelease(pv.prerelease, pw.prerelease) +} + +// Max canonicalizes its arguments and then returns the version string +// that compares greater. +// +// Deprecated: use [Compare] instead. In most cases, returning a canonicalized +// version is not expected or desired. +func Max(v, w string) string { + v = Canonical(v) + w = Canonical(w) + if Compare(v, w) > 0 { + return v + } + return w +} + +// ByVersion implements [sort.Interface] for sorting semantic version strings. +type ByVersion []string + +func (vs ByVersion) Len() int { return len(vs) } +func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] } +func (vs ByVersion) Less(i, j int) bool { + cmp := Compare(vs[i], vs[j]) + if cmp != 0 { + return cmp < 0 + } + return vs[i] < vs[j] +} + +// Sort sorts a list of semantic version strings using [ByVersion]. +func Sort(list []string) { + sort.Sort(ByVersion(list)) +} + +func parse(v string) (p parsed, ok bool) { + if v == "" || v[0] != 'v' { + return + } + p.major, v, ok = parseInt(v[1:]) + if !ok { + return + } + if v == "" { + p.minor = "0" + p.patch = "0" + p.short = ".0.0" + return + } + if v[0] != '.' { + ok = false + return + } + p.minor, v, ok = parseInt(v[1:]) + if !ok { + return + } + if v == "" { + p.patch = "0" + p.short = ".0" + return + } + if v[0] != '.' { + ok = false + return + } + p.patch, v, ok = parseInt(v[1:]) + if !ok { + return + } + if len(v) > 0 && v[0] == '-' { + p.prerelease, v, ok = parsePrerelease(v) + if !ok { + return + } + } + if len(v) > 0 && v[0] == '+' { + p.build, v, ok = parseBuild(v) + if !ok { + return + } + } + if v != "" { + ok = false + return + } + ok = true + return +} + +func parseInt(v string) (t, rest string, ok bool) { + if v == "" { + return + } + if v[0] < '0' || '9' < v[0] { + return + } + i := 1 + for i < len(v) && '0' <= v[i] && v[i] <= '9' { + i++ + } + if v[0] == '0' && i != 1 { + return + } + return v[:i], v[i:], true +} + +func parsePrerelease(v string) (t, rest string, ok bool) { + // "A pre-release version MAY be denoted by appending a hyphen and + // a series of dot separated identifiers immediately following the patch version. + // Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-]. + // Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes." + if v == "" || v[0] != '-' { + return + } + i := 1 + start := 1 + for i < len(v) && v[i] != '+' { + if !isIdentChar(v[i]) && v[i] != '.' { + return + } + if v[i] == '.' { + if start == i || isBadNum(v[start:i]) { + return + } + start = i + 1 + } + i++ + } + if start == i || isBadNum(v[start:i]) { + return + } + return v[:i], v[i:], true +} + +func parseBuild(v string) (t, rest string, ok bool) { + if v == "" || v[0] != '+' { + return + } + i := 1 + start := 1 + for i < len(v) { + if !isIdentChar(v[i]) && v[i] != '.' { + return + } + if v[i] == '.' { + if start == i { + return + } + start = i + 1 + } + i++ + } + if start == i { + return + } + return v[:i], v[i:], true +} + +func isIdentChar(c byte) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '-' +} + +func isBadNum(v string) bool { + i := 0 + for i < len(v) && '0' <= v[i] && v[i] <= '9' { + i++ + } + return i == len(v) && i > 1 && v[0] == '0' +} + +func isNum(v string) bool { + i := 0 + for i < len(v) && '0' <= v[i] && v[i] <= '9' { + i++ + } + return i == len(v) +} + +func compareInt(x, y string) int { + if x == y { + return 0 + } + if len(x) < len(y) { + return -1 + } + if len(x) > len(y) { + return +1 + } + if x < y { + return -1 + } else { + return +1 + } +} + +func comparePrerelease(x, y string) int { + // "When major, minor, and patch are equal, a pre-release version has + // lower precedence than a normal version. + // Example: 1.0.0-alpha < 1.0.0. + // Precedence for two pre-release versions with the same major, minor, + // and patch version MUST be determined by comparing each dot separated + // identifier from left to right until a difference is found as follows: + // identifiers consisting of only digits are compared numerically and + // identifiers with letters or hyphens are compared lexically in ASCII + // sort order. Numeric identifiers always have lower precedence than + // non-numeric identifiers. A larger set of pre-release fields has a + // higher precedence than a smaller set, if all of the preceding + // identifiers are equal. + // Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < + // 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0." + if x == y { + return 0 + } + if x == "" { + return +1 + } + if y == "" { + return -1 + } + for x != "" && y != "" { + x = x[1:] // skip - or . + y = y[1:] // skip - or . + var dx, dy string + dx, x = nextIdent(x) + dy, y = nextIdent(y) + if dx != dy { + ix := isNum(dx) + iy := isNum(dy) + if ix != iy { + if ix { + return -1 + } else { + return +1 + } + } + if ix { + if len(dx) < len(dy) { + return -1 + } + if len(dx) > len(dy) { + return +1 + } + } + if dx < dy { + return -1 + } else { + return +1 + } + } + } + if x == "" { + return -1 + } else { + return +1 + } +} + +func nextIdent(x string) (dx, rest string) { + i := 0 + for i < len(x) && x[i] != '.' { + i++ + } + return x[:i], x[i:] +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 5017744cb..53c6f7805 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -76,6 +76,9 @@ golang.org/x/arch/x86/x86asm golang.org/x/exp/constraints golang.org/x/exp/maps golang.org/x/exp/slices +# golang.org/x/mod v0.20.0 +## explicit; go 1.18 +golang.org/x/mod/semver # golang.org/x/sync v0.8.0 ## explicit; go 1.18 golang.org/x/sync/errgroup