Changes FindLocation to support multiple targets and adds an AddrPid
member to api.Breakpoint so that clients can set breakpoints by address
when multiple targets are connected (but at them moment this field is
ignored).
Updates #1653
Updates #2551
Go 1.20 switched to uint64 to represent goroutine IDs, we can't
actually follow suit because we have allowed clients to use -1 to refer
to the currently selected goroutine, however we should at least switch
to int64 and also update the rtype check to accept the 1.20 type.
This patch removes the old error-prone way of tracking
whether the tracepoint is for a function entry or
return. Instead of trying to guess, let the data structure
simply tell us directly.
Log points are special kinds of breakpoints that do not 'break' but instead log a message and then continue. This change implements basic log points that simply log the provided message, without any interpolation.
In order to resume execution after hitting a breakpoint, I added a new lock resumeMu and tracked the running state within the DAP server. resumeMu must be held in order to issue a debugger request that would start execution. This means it can be used to make sure that another goroutine does not resume execution while you are holding the lock.
Most of the synchronization logic is taken from PR #2530
Updates golang/vscode-go#123
This patch enables the eBPF tracer backend to parse the ID of the
Goroutine which hit the uprobe. This implementation is specific to AMD64
and will have to be generalized further in order to be used on other
architectures.
* terminal,service: add way to see internal breakpoints
Now that Delve has internal breakpoints that survive for long periods
of time it will be useful to have an option to display them.
* proc,terminal,service: support stack watchpoints
Adds support for watchpoints on stack allocated variables.
When a stack variable is watched, in addition to the normal watchpoint
some support breakpoints are created:
- one breakpoint inside runtime.copystack, used to adjust the address
of the watchpoint when the stack is resized
- one or more breakpoints used to detect when the stack variable goes
out of scope, those are similar to the breakpoints set by StepOut.
Implements #279
Adds filtering and grouping to the goroutines command.
The current implementation of the goroutines command is modeled after
the threads command of gdb. It works well for programs that have up to
a couple dozen goroutines but becomes unusable quickly after that.
This commit adds the ability to filter and group goroutines by several
different properties, allowing a better debugging experience on
programs that have hundreds or thousands of goroutines.
Ensure that any command executed after the process we are trying to
debug prints a correct and consistent exit status.
Previously the exit code was being lost after the first time we printed
that a process has exited. Additionally, certain commands would print
the PID of the process and other would not. This change makes everything
more correct and consistent.
* pkg/proc: implement support for hit count breakpoints
* update comment
* udpate hitcount comment
* update HitCond description
* add test for hit condition error
* respond to review
* service/dap: add support for hit count breakpoints
* use amendbps to preserve hit counts
* update test health doc
* fix failing test
* simplify hit conditions
* REmove RequestString, use name instead
* update backend_test_health.md
* document hit count cond
* fix tests
A RequestManualStop received while the target program is stopped can
induce a crash when the target is restarted.
This is caused by the phantom breakpoint detection that was introduced
in PR #2179 / commit e69d536.
Instead of always interpreting an unexplained SIGTRAP as a phantom
breakpoint memorize all possible unreported breakpoint hits and only
act on it when the thread hasn't moved from one.
Also clarifies the behavior of the halt command when it is received
while the target is stopped or in the process of stopping.
Changes the expression evaluation code so that register names, when not
shadowed by local or global variables, will evaluate to the current
value of the corresponding CPU register.
This allows a greater flexibility with displaying CPU registers than is
possible with using the ListRegisters API call. Also it allows
debuggers users to view register values even if the frontend they are
using does not implement a register view.
* Adds toggle command
Also adds two rpc2 tests for testing the new functionality
* Removes Debuggers' ToggleBreakpoint method
rpc2's ToggleBreakpoint now calls AmendBreakpoint
Refactors the ClearBreakpoint to avoid a lock.
* proc/core: off-by-one error reading ELF core files
core.(*splicedMemory).ReadMemory checked the entry interval
erroneously when dealing with contiguous entries.
* terminal,service,proc/*: adds dump command (gcore equivalent)
Adds the `dump` command that creates a core file from the target process.
Backends will need to implement a new, optional, method `MemoryMap` that
returns a list of mapped memory regions.
Additionally the method `DumpProcessNotes` can be implemented to write out
to the core file notes describing the target process and its threads. If
DumpProcessNotes is not implemented `proc.Dump` will write a description of
the process and its threads in a OS/arch-independent format (that only Delve
understands).
Currently only linux/amd64 implements `DumpProcessNotes`.
Core files are only written in ELF, there is no minidump or macho-o writers.
# Conflicts:
# pkg/proc/proc_test.go
Adds a flag that distinguishes the return values of an injected
function call from the return values of a function call executed by the
target program.
Since proc is supposed to work independently from the target
architecture it shouldn't use architecture-dependent types, like
uintptr. For example when reading a 64bit core file on a 32bit
architecture, uintptr will be 32bit but the addresses proc needs to
represent will be 64bit.
* cmd/dlv,debugger: Improve dlv trace and trace command output
This patch improves the `dlv trace` subcommand output by reducing the
noise that is generated and providing clearer more concise information.
Also adds new tests closing a gap in our testing (we previously never
really tested this subcommand).
This patch also fixes the `dlv trace` REPL command to behave like the
subcommand in certain situations. If the tracepoint is for a function,
we now show function arguements and return values properly.
Also makes the overall output of the trace subcommand clearer.
Fixes#2027
Allows Delve clients to stop a recording midway by sending a
Command('halt')
request.
This is implemented by changing debugger.New to start recording the
process on a separate goroutine while holding the processMutex locked.
By locking the processMutex we ensure that almost all RPC requests will
block until the recording is done, since we can not respond correctly
to any of them.
API calls that do not require manipulating or examining the target
process, such as "IsMulticlient", "SetApiVersion" and
"GetState(nowait=true)" will work while we are recording the process.
Two other internal changes are made to the API: both GetState and
Restart become asynchronous requests, like Command. Restart because
this way it can be interrupted by a StopRecording request if the
rerecord option is passed.
GetState because clients need a call that will block until the
recording is compelted and can also be interrupted with a
StopRecording.
Clients that are uninterested in allowing the user to stop a recording
can ignore this change, since eventually they will make a request to
Delve that will block until the recording is completed.
Clients that wish to support this feature must:
1. call GetState(nowait=false) after connecting to Delve, before any
call that would need to manipulate the target process
2. allow the user to send a StopRecording request during the initial
GetState call
3. allow the user to send a StopRecording request during any subsequent
Restart(rerecord=true) request (if supported).
Implements #1747
* proc: move defer breakpoint code into a function
Moves the code that sets a breakpoint on the first deferred function,
used by both next and StepOut, to its function.
* proc: implement reverse step/next/stepout
When the direction of execution is reversed (on a recording) Step, Next and
StepOut will behave similarly to their forward version. However there are
some subtle interactions between their behavior, prologue skipping, deferred
calls and normal calls. Specifically:
- when stepping backwards we need to set a breakpoint on the first
instruction after each CALL instruction, once this breakpoint is reached we
need to execute a single StepInstruction operation to reverse step into the
CALL.
- to insure that the prologue is skipped reverse next needs to check if it
is on the first instruction after the prologue, and if it is behave like
reverse stepout.
- there is no reason to set breakpoints on deferred calls when reverse
nexting or reverse stepping out, they will never be hit.
- reverse step out should generally place its breakpoint on the CALL
instruction that created the current stack frame (which will be the CALL
instruction immediately preceding the instruction at the return address).
- reverse step out needs to treat panic calls and deferreturn calls
specially.
* service,terminal: implement reverse step, next, stepout
Adds an optional scope prefix to the `regs` command which allows
printing registers for any stack frame (as long as they were somehow
saved). Issue #1838 is not yet to be closed since we are still not
recovering the registers of a segfaulting frame.
Updates #1838
Adds an API call that returns a list of packages contained in the
program and the files that were used to build them, and also a best
guess at which filesystem directory contained the package when it was
built.
This can be used by IDEs to map file paths if the debugging environment
doesn't match the build environment exactly.
Changes CreateBreakpoint to create a logical breakpoint when multiple
addresses are specified, FindLocation and the api.Location type to
return logical locations and the cli to support logical breakpoints.
Modifies FindFileLocation, FindFunctionLocation and LineToPC as well as
service/debugger to support inlining and introduces the concept of
logical breakpoints.
For inlined functions FindFileLocation, FindFunctionLocation and
LineToPC will now return one PC address for each inlining and one PC
for the concrete implementation of the function (if present).
A proc.Breakpoint will continue to represent a physical breakpoint, at
a single memory location.
Breakpoints returned by service/debugger, however, will represent
logical breakpoints and may be associated with multiple memory
locations and, therefore, multiple proc.Breakpoints.
The necessary logic is introduced in service/debugger so that a change
to a logical breakpoint will be mirrored to all its physical
breakpoints and physical breakpoints are aggregated into a single
logical breakpoint when returned.
Add options to start a stacktrace from the values saved in the
runtime.g struct as well as a way to disable the stackSwitch logic and
just get a normal stacktrace.
Add variables flag to mark variables that are allocated on a register
(and have no address) and variables that we read as result of a
function call (and are allocated on a stack that no longer exists when
we show them to the user).
* proc: allow simultaneous call injection to multiple goroutines
Changes the call injection code so that we can have multiple call
injections going on at the same time as long as they happen on distinct
goroutines.
* proc: fix EvalExpressionWithCalls for constant expressions
The lack of address of constant expressions would confuse EvalExpressionWithCalls
Fixes#1577
The initial implementation of the 'call' command required the
function call to be the root expression, i.e. something like:
double(3) + 1
was not allowed, because the root expression was the binary operator
'+', not the function call.
With this change expressions like the one above and others are
allowed.
This is the first step necessary to implement nested function calls
(where the result of a function call is used as argument to another
function call).
This is implemented by replacing proc.CallFunction with
proc.EvalExpressionWithCalls. EvalExpressionWithCalls will run
proc.(*EvalScope).EvalExpression in a different goroutine. This
goroutine, the 'eval' goroutine, will communicate with the main
goroutine of the debugger by means of two channels: continueRequest
and continueCompleted.
The eval goroutine evaluates the expression recursively, when
a function call is encountered it takes care of setting up the
function call on the target program and writes a request to the
continueRequest channel, this causes the 'main' goroutine to restart
the target program by calling proc.Continue.
Whenever Continue encounters a breakpoint that belongs to the
function call injection protocol (runtime.debugCallV1 and associated
functions) it writes to continueCompleted which resumes the 'eval'
goroutine.
The 'eval' goroutine takes care of implementing the function call
injection protocol.
When the expression is fully evaluated the 'eval' goroutine will
write a special message to 'continueRequest' signaling that the
expression evaluation is terminated which will cause Continue to
return to the user.
Updates #119
This change splits the BinaryInfo object into a slice of Image objects
containing information about the base executable and each loaded shared
library (note: go plugins are shared libraries).
Delve backens are supposed to call BinaryInfo.AddImage whenever they
detect that a new shared library has been loaded.
Member fields of BinaryInfo that are used to speed up access to dwarf
(Functions, packageVars, consts, etc...) remain part of BinaryInfo and
are updated to reference the correct image object. This simplifies this
change.
This approach has a few shortcomings:
1. Multiple shared libraries can define functions or globals with the
same name and we have no way to disambiguate between them.
2. We don't have a way to handle library unloading.
Both of those affect C shared libraries much more than they affect go
plugins. Go plugins can't be unloaded at all and a lot of name
collisions are prevented by import paths.
There's only one problem that is concerning: if two plugins both import
the same package they will end up with multiple definition for the same
function.
For example if two plugins use fmt.Printf the final in-memory image
(and therefore our BinaryInfo object) will end up with two copies of
fmt.Printf at different memory addresses. If a user types
break fmt.Printf
a breakpoint should be created at *both* locations.
Allowing this is a relatively complex change that should be done in a
different PR than this.
For this reason I consider this approach an acceptable and sustainable
stopgap.
Updates #865
Adds initial support for plugins, this is only the code needed to keep
track of loaded plugins on linux (both native and gdbserial backend).
It does not actually implement support for debugging plugins on linux.
Updates #865
The repository is being switched from the personal account
github.com/derekparker/delve to the organization account
github.com/go-delve/delve. This patch updates imports and docs, while
preserving things which should not be changed such as my name in the
CHANGELOG and in TODO comments.
This patch allows the `trace` CLI subcommand to display return values of
a function. Additionally, it will also display information on where the
function exited, which could also be helpful in determining the path
taken during function execution.
Fixes#388