* proc: use stack machine to evaluate expressions
This commit splits expression evaluation into two parts. The first part (in
pkg/proc/evalop/evalcompile.go) "compiles" as ast.Expr into a list of
instructions (defined in pkg/proc/evalop/ops.go) for a stack machine
(defined by `proc.(*evalStack)`).
The second part is a stack machine (implemented by `proc.(*EvalScope).eval`
and `proc.(*EvalScope).evalOne`) that has two modes of operation: in the
main mode it executes inteructions from the list (by calling `evalOne`), in
the second mode it executes the call injection protocol by calling
`funcCallStep` repeatedly until it either the protocol finishes, needs more
input from the stack machine (to set call arguments) or fails.
This approach has several benefits:
- it is now possible to remove the goroutine we use to evaluate expression
and the channel used to communicate with the Continue loop.
- every time we resume the target to execute the call injection protocol we
need to update several local variables to match the changed state of the
target, this is now done at the top level of the evaluation loop instead of
being hidden inside a recurisive evaluator
- using runtime.Pin to pin addresses returned by an injected call would
allow us to use a more natural evaluation order for function calls, which
would solve some bugs #3310, allow users to inspect values returned by a
call injection #1599 and allow implementing some other features #1465. Doing
this with the recursive evaluator, while keeping backwards compatibility
with versions of Go that do not have runtime.Pin is very hard. However after
this change we can simply conditionally change how compileFunctionCall works
and add some opcodes.
* review round 1
* review round 2
Use the trampoline attribute to detect auto-generated code. This fixes
a bug where stepping into a method of a generic type called through an
interface will take the debugger into an auto-generated wrapper that
does not have a dictionary and using next will step out of the wrapper.
Fixes a bug reported on the #delve channel of the gophers slack server.
There is no benefit to having a small part of the freebsd backend
implemented in C, rather than using cgo. While here, add a missing
call to procstat_close and check the return value of
procstat_getpathname.
Thank you to everyone who contributed to this release:
@alexsaezm, @pgavlin, @archanaravindar, @aarzilli, @hyangah, @thechampagne, @javierhonduco, @andreimatei, @gocurr, @alexandear, @stefanhaller.
* enable func call injection on delve for ppc64le
* Function call injection on Delve/ppc64le, modified DWARF encoding and decoding for floating point registers to make floatsum test work
* Function call injection on Delve/ppc64le cleanup
* skip PIE tests for function call injection on other packages
* Address review comments
* accounted for additional skipped PIE tests for function call injection
* Code cleanup and undoing revert of previous commit
* Enable function call injection only on 1.22 and above and some cleanup
* additional cleanup, go fmt run
* Debug function call tests fail on ppc64le/PIE mode adjusted the backup_test_health.md file accordingly
The current implementation assumes a specific command line interface
for opening an editor at a specific location within the source file.
This patch updates for different formats, namely the one used by the
editor 'hx'.
* proc: correctly update local variables after continue
At various point during the execution of the call injection protocol
the process is resumed and the call injection goroutine could migrate
to a different thread, we must make sure to update our local variables
correctly after every point where the target program is resumed.
'fncall122debug_clean' on 'f469a0a5'.
* go.mod: update golang.org/x/tools
Go 1.22 broke golang.org/x/tools/packages
* cmd/dlv: disable TestStaticcheck with go1.22
Go 1.22 is not yet supported by staticcheck.
This command lists the packages included in the debugee.
The implementation utilizes "ListPackagesBuildInfo" RPC.
In order to support server-side filtering like `sources` and other
commands, expanded the ListPackagesBuildInfo RPC to take an optional
filter field.
From the Go specification:
"1. For a nil slice, the number of iterations is 0." [1]
Therefore, an additional nil check for before the loop is unnecessary.
[1]: https://go.dev/ref/spec#For_range
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
Miscellaneous non-functional changes to prepare for adding support for
follow-exec mode on Windows:
- removed (*nativeProcess).wait function from Windows backend (unused).
- move close of ptraceDoneChan from release to handlePtraceFuncs, this
makes postExit callable by a function executed by execPtraceFunc.
- change addTarget to detach before creating the target object if we
don't actually want to attach to the child process, also moved the
detach call to (*processGroup).add instead of having one in addTarget
and one in the code that calls (*processGroup).add.
- changed Detach to be a method of TargetGroup/ProcessGroup, the
Windows backend will need access to the process group to call
WaitForDebugEvent.
- moved resume method to processGroup. First all threads stopped at a
breakpoint need to be stepped, then all other threads can be resumed.
This is true also for linux even though it didn't cause the current
tests to fail.
Adds -chan option to the goroutines command to list only the goroutines
running on a specified channel.
Also when printing a variable if it is a channel also print the list of
goroutines that are waiting on it.
Implementing the `DW_CFA_remember_state` and `DW_CFA_restore_state`
according to the DWARF specification requires us to create a stack that
can store an arbitrary number of elements, that is, there could be
multiple "pushes" before "popping" them.
From the 5th revision of the spec [0]:
> 6.4.2.4 Row State Instructions
> DW_CFA_remember_state
> The DW_CFA_remember_state instruction takes no operands. The required
> action is to push the set of rules for every register onto an implicit stack.
> DW_CFA_restore_state
> DW_CFA_restore_state
> The DW_CFA_restore_state instruction takes no operands. The required action
> is to pop the set of rules off the implicit stack and place them in the
> current row.
- [0]: https://dwarfstd.org/doc/DWARF5.pdf
Signed-off-by: Francisco Javier Honduvilla Coto <javierhonduco@gmail.com>
- add architecture rule for ppc64le so that incompatible agents don't
pick up the build
- disable PIE tests on linux/ppc64le (the tests claim it doesn't work)
- enable PIE tests on darwin/amd64 now that the entry point calculation
has been fixed
- remove dependency on wget and curl in the test script for linux to
reduce test time
- only install git in the linux test script when we need it
- remove staticcheck from linux/ppc64le builds (it takes almost 5
minutes between installation and execution and makes the test timeout
sometimes)
- drop windows/arm64/tip build, the windows/arm64 build is broken
anyway and since there is only one agent it makes CI runs slow
- drop linux/ppc64le/tip build, there is only one agent, it's slow and
it will always timeout. CI runs in excess of 1h are too long.
If there is no current goroutine when 'next', 'step' or 'stepout' are
used set a condition that the thread ID should stay the same instead.
This makes stepping work for multithreaded C programs or Go programs
that have threads started by cgo code.
Fixes#3262
Add parsing for the new version format with toolchain (X.Y.Z-something)
and simplify internal representation of versions so that revision, beta
version and rc version are all represented on a single field with rc
and beta versions being negative numbers (this limits rc versions to a
maximum of 1000 which will not be a problem in practice).
The -C argument must come first on the command line of 'go build' if
the flags specified by the user via build-flags start with -C pass it
first.
Replaces #3380
TestStacktraceGoroutine failed intermittently on freebsd/amd64/go1.20.
This happens because of two windows, in the scheduler (right after
parking a goroutine and just before resuming a parked goroutine) where
a thread is associated with a goroutine but running in the system stack
and there is no systemstack_switch frame to connect the two stacks.
Go1.22 switched to emitting PIE by default and also changed some
details of the PIE implementation. This breaks delve entirely on macOS.
Fix how relocations are handled on macOS.
Update test matrix to remove 1.18 and add 1.21, fix build scripts to
deal with the new format returned by:
https://golang.org/VERSION?m=text
which now has an extra second line with the time.
Adds a waitfor option to 'dlv attach' that waits for a process with a
name starting with a given prefix to appear before attaching to it.
Debugserver on macOS does not support follow-fork mode, but has this
feature instead which is not the same thing but still helps with
multiprocess debugging somewhat.
I searched the source code of Go, and found no usages of
"== (reflect.Value{})" and "!= (reflect.Value{})". I think
it's more idiomatic to use "IsValid" to check a zero Value.
Change FindLocation so it can return a substitute location expression
and propagate it to pkg/terminal/command.
When breakpoints are set using the syntax :<lineno> or +<lineno>
produce a substitute location expression that doesn't depend on having
a valid scope and can be used to restore the breakpoint.
Fixes#3423
Show the location expression that will be used to set a suspended
breakpoint in the breakpoints list.
Also change 'target' called without arguments to print a better error
message and 'target follow-exec' without the last argument to print the
state of follow-exec.
* logflags,proc: flag to log stacktrace execution
Add a log flag to write logs about what the stacktracer does.
* proc: read context from sigtrampgo, fixes TestCgoStacktrace2 on 1.21
Changes stacktrace code to read the signal context from the arguments
of sigtrampgo.
Also changes the automatic fatalthrow breakpoint for go 1.21.
In combination these two changes fix TestCgoStacktrace2 on Go 1.21 on
various platforms.
Only print the warning that gopclntab can not be read for the first
image (i.e. the executable file), also change the returned when neither
DWARF nor gopclntab are found to preserve the DWARF error.
Uprobes get automatically cleaned and removed when the reference to
the Link object is lost. Hold a reference to any active Uprobe Link
for duration of Delve execution and ensure they are cleaned up
at exit.
Fixes ebpf probes don't work after time.Sleep() #3227
We used to parse the .gopclntab section but removed support in favor of
simply using DWARF debug information, due to lack of C symbols among
other reasons. This makes it impossible to debug stripped binaries,
which some distrubutions ship by default.
Add back in basic support for .gopclntab which survives if the binary
is stripped, allowing for rudimentary debugging such as basic
program navigation, tracing, etc...
Adds a new starlark builtin 'help' that prints the list of available
builtins when called without arguments and help for the specified
builtin when passed an argument.
The help is autogenerated from godoc comments so it isn't always
exactly accurate for starlark (in particular we sometimes refer to the
In structs), but it's better than nothing.
dwarf/op gained the ability to execute DW_OP_deref opcodes a while ago
but because we didn't save the readMemory function in the context
structure it never worked.
This patch makes the time library available to Starlark scripts. This
library is one of the very few few that are built into starlark-go (the
others are json, math, proto).
I've played around with Starlark scripting today, and immediately I
wanted to measure how long certain computations take.
Using a fixed path as the default output binary means that executing
Delve twice in the same directory will cause the second invocation to
overwrite the output binary of the first instance of Delve, making the
restart command not work correctly.
Fixes#3345
* pkg/proc: pad variable mem in extractVarInfoFromEntry
On 64 bit system, the byte size of the following struct is 16:
type myStruct struct {
a int
b uint32
}
But extractVarInfoFromEntry only allocates a mem of 12 bytes for it.
When calling method of this struct with the "call" command, it will
result in this error:
write out of bounds
This patch extends the mem by adding padding bytes to the end of the
mem.
Fixes#3364.
* move the padding logic into newCompositeMemory
Go 1.21 renamed runtime._type to internal/abi.Type and changed the name
of its fields. Update Delve so that it uses the new names for loading
interfaces and generic type parameters.
Read the command line of the main target process as well as any other
process Delve attaches to in follow exec mode.
The command line can be viewed using the 'target list' command.
In follow exec mode this command line is used to match the follow exec
regex to decide whether or not to attach to a child process.
On macOS or when using rr the list of arguments is not available for
attached processes since there is no way to use the gdb serial protocol
to read it.
Fixes#2242
We can simplify the following code
dir, err := os.Open(dirname)
if err != nil {
return err
}
defer dir.Close()
dirs, err := dir.Readdir(-1)
with just `os.ReadDir(dirname)`.
Reference: https://pkg.go.dev/os#ReadDir
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
A series of interconnected changes to both the terminal command
'config', DAP command 'dlv config', quality of life improvements to how
substitute-path works, and better documentation.
- Let 'config substitute-path' show the current substitute path rules
- Add a -clear command to 'config substitute-path'
- Support 'config-debug-info-directories'
- rewrite SubstitutePath to be platform independent (see below)
- document path substitution more
Regarding the rewrite of SubstitutePath: the previous version used
runtime.GOOS and filepath.IsAbs to determine which filepath separator to use
and if matching should be case insensitive. This is wrong in all situations
where the client and server run on different OSes, when examining core files
and when cross-compilation is involved.
The new version of SubstitutePath checks the rules and the input path to
determine if Windows is involved in the process, if it looks like it is it
switches to case-insensitive matching. It uses a lax version of
filepath.IsAbs to determine if a path is absolute and tries to avoid having
to select a path separator as much as possible
Fixes#2891, #2890, #2889, #3179, #3332, #3343
* Remove standard C headers since we have vmlinux.h already
* Simplify get_goroutine_id() implementation, this reduces a map
and thus reduces runtime memory comsumption.
While at it, unify all indention using 4 spaces.
Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
When using Step on a function that has a dynamic CALL instruction we
set a Step breakpoint on the call.
When it is hit we determine the destination of the CALL by looking at
registers, set a breakpoint there and continue.
If the Step breakpoint is hit simultaneously with a normal breakpoint
our Step logic will take precedence and the normal breakpoint hit will
be hidden from the user.
Move the Step logic to a breaklet callback so that it does not
interfere with the decision to stop.