Instead of unconditionally returning all present goroutines,
GoroutinesInfo now allows specifying a range (start and count). In
addition to the array of goroutines and the error, it now also returns
the next goroutine to be processed, to be used as 'start' argument on
the next call, or 0 if all present goroutines have already been
processed.
This way clients can avoid eating large amounts of RAM while debugging
core dumps and processes with a exceptionally high amount of goroutines.
Fixes#1403
Users can create sparse maps in two ways, either by:
a) adding lots of entries to a map and then deleting most of them, or
b) using the make(mapType, N) expression with a very large N
When this happens reading the resulting map will be very slow
because loadMap needs to scan many buckets for each entry it finds.
Technically this is not a bug, the user just created a map that's
very sparse and therefore very slow to read. However it's very
annoying to have the debugger hang for several seconds when trying
to read the local variables just because one of them (which you
might not even be interested into) happens to be a very sparse map.
There is an easy mitigation to this problem: not reading any
additional buckets once we know that we have already read all
entries of the map, or as many entries as we need to fulfill the
MaxArrayValues parameter.
Unfortunately this is mostly useless, a VLSM (Very Large Sparse Map)
with a single entry will still be slow to access, because the single
entry in the map could easily end up in the last bucket.
The obvious solution to this problem is to set a limit to the
number of buckets we read when loading a map. However there is no
good way to set this limit.
If we hardcode it there will be no way to print maps that are beyond
whatever limit we pick.
We could let users (or clients) specify it but the meaning of such
knob would be arcane and they would have no way of picking a good
value (because there is no objectively good value for it).
The solution used in this commit is to set an arbirtray limit on
the number of buckets we read but only when loadMap is invoked
through API calls ListLocalVars and ListFunctionArgs. In this way
`ListLocalVars` and `ListFunctionArgs` (which are often invoked
automatically by GUI clients) remain fast even in presence of a
VLSM, but the contents of the VLSM can still be inspected using
`EvalVariable`.
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
Add a flag to Stackframe that indicates where the stack frame is the
bottom-most frame of the stack. This allows clients to know whether the
stack trace terminated normally or if it was truncated because the
maximum depth was reached.
Add a truncation message to the 'stack' command.
Adds -defer flag to the stack command that decorates the stack traces
by associating each stack frame with its deferred calls.
Reworks proc.next to use this feature instead of using proc.DeferPC,
laying the groundwork to implement #1240.
Implements the function call injection protocol introduced in go 1.11
by https://go-review.googlesource.com/c/go/+/109699.
This is only the basic support, see TODO comments in pkg/proc/fncall.go
for a list of missing features.
Updates #119
Setting the Level field of a logrus logger doesn't actually do anything
since the Level field simply reports the log level of the last log
message emitted on the logger.
The right way to do that is to set logger.Logger.Level.
Also cleans up newline characters from log messages emitted through
logrus and fixes the direction of the arrows in the messages emitted by
rpccommon, which was inconsistent with the arrows of gdbserial.
This pull request makes several changes to delve to allow headless
instancess that are started with the --accept-multiclient flag to
keep running even if there is no connected client. Specifically:
1. Makes a headless instance started with --accept-multiclient quit
after one of the clients sends a Detach request (previously they
would never ever quit, which was a bug).
2. Changes proc/gdbserial and proc/native so that they mark the
Process as exited after they detach, even if they did not kill the
process during detach. This prevents bugs such as #1231 where we
attempt to manipulate a target process after we detached from it.
3. On non --accept-multiclient instances do not kill the target
process unless we started it or the client specifically requests
it (previously if the client did not Detach before closing the
connection we would kill the target process unconditionally)
4. Add a -c option to the quit command that detaches from the
headless server after restarting the target.
5. Change terminal so that, when attached to --accept-multiclient,
pressing ^C will prompt the user to either disconnect from the
server or pause the target process. Also extend the exit prompt to
ask if the user wants to keep the headless server running.
Implements #245, #952, #1159, #1231
Implements structured logging via Logrus. This gives us a logger per
boundry that we care about, allowing for easier parsing of logs if users
have more than one log option enabled. Also, cleans up a lot of
conditionals in the code by simply silencing the logger at creation as
opposed to conditionally logging everywhere.
We occasionally receive bug reports from users of VSCode-go and GoLand.
GoLand has its own way of capturing the packet exchange between itself
and delve but VSCode-go (supposedly) doesn't.
So far this hasn't been a problem since all bug reports were obvious
bugs on the plugin or easy to reproduce without VSCode-go, but it might
be helpful in the future to have a way to log the packet exchange
between dlv and a frontend.
This commit adds a --log-output option to enable logging of all rpc
messages and changes service/rpccommon accordingly.
Displays the return values of the current function when we step out of
it after executing a step, next or stepout command.
Implementation of this feature is tricky: when the function has
returned the return variables are not in scope anymore. Implementing
this feature requires evaluating variables that are out of scope, using
a stack frame that doesn't exist anymore.
We can't calculate the address of these variables when the
next/step/stepout command is initiated either, because between that
point and the time where the stepout breakpoint is actually hit the
goroutine stack could grow and be moved to a different memory address.
Change the linux verison of proc/native and proc/gdbserial (with
debugserver) so that they let the target process use the terminal when
delve is launched in headless mode.
Windows already worked, proc/gdbserial (with rr) already worked.
I couldn't find a way to make proc/gdbserial (with lldb-server) work.
No tests are added because I can't think of a way to test for
foregroundness of a process.
Fixes#65
Caching the frame in variablesByTag is problematic:
1. accounting for variables that are (partially) stored in registers is
complicated (see issue #1106)
2. for some types (strings, interfaces...) simply creating the Variable
object reads memory, which therefore happens before we can do any
caching.
Instead cache the entire frame when the EvalScope object is created.
The cached range is between the SP value of the current frame and the
CFA of the preceeding frame, if available, or the CFA of the current
frame otherwise.
Fixes#1106
When gdbserial can not find debugserver or lldb-server the error
message is always the same and it complains about lldb-server not being
found.
This is fine on linux (where the backend is unnecessary) but incomplete
on macOS (where the backend is actually used).
Make the error message clearer so that users who do not bother reading
install instructions are not confused.
updates vendored version of x86asm, adds a symbol lookup function to
pass to the disassembler.
This will show global symbol names in the disassembly like go tool
objdump does.
debug_info entries can use DW_AT_abstract_origin to inherit the
attributes of another entry, supporting this attribute is necessary to
support DW_TAG_inlined_subroutine.
Go, starting with 1.10, emits DW_TAG_inlined_subroutine entries when
inlining is enabled.
* command/terminal: allow restart to change process args
Add -args flag to "restart" command. For example, "restart -args a b c" will
pass args a b c to the new process.
Add "-c" flag to pass the checkpoint name. This is needed to disambiguate the
checkpoint name and arglist.
Reverted unnecessary changes.
* Applied reviewer comments.
Vendored argv.
Change the syntax of restart. When the target is is in recording mode, it always
interprets the args as a checkpoint. Otherwise, it interprets the args as
commandline args. The flag "-args" is still there, to handle the case in which
the user wants to pass an empty args on restart.
* Add restartargs.go.
Change "restart -args" to "restart -noargs" to clarify that this flag is used to
start a process with an empty arg.
So far we have evaluated the locspec "+0" the same way we evaluate all
"+n" locspecs, this means that we turn the current PC into a file:line
pair, then we turn back the file:line into a PC address.
Normally this is harmless, however all autogenerated code returns the
source position "<autogenerated>:1" which resolves back to the very
first autogenerated instruction in the code.
This messes up the behaviour of the "disassemble" command which uses
the locspec "+0" to figure out what code to disassemble if no arguments
are passed.
We should make +0 always resolve to the current PC (of the given scope)
so that clients can use +0 as a default locspec.
When creating a stack trace we should switch between the goroutine
stack and the system stack (where cgo code is executed) as appropriate
to reconstruct the logical stacktrace.
Goroutines that are currently executing on the system stack will have
the SystemStack flag set, frames of the goroutine stack will have a
negative FrameOffset (like always) and frames of the system stack will
have a positive FrameOffset (which is actually just the CFA value for
the frame).
Updates #935
Conditional breakpoints with unmet conditions would cause next and step
to skip the line.
This breakpoint changes the Kind field of proc.Breakpoint from a single
value to a bit field, each breakpoint object can represent
simultaneously a user breakpoint and one internal breakpoint (of which
we have several different kinds).
The breakpoint condition for internal breakpoints is stored in the new
internalCond field of proc.Breakpoint so that it will not conflict with
user specified conditions.
The breakpoint setting code is changed to allow overlapping one
internal breakpoint on a user breakpoint, or a user breakpoint on an
existing internal breakpoint. All other combinations are rejected. The
breakpoint clearing code is changed to clear the UserBreakpoint bit and
only remove the phisical breakpoint if no other bits are set in the
Kind field. ClearInternalBreakpoints does the same thing but clearing
all bits that aren't the UserBreakpoint bit.
Fixes#844
Move some duplicate code, related to breakpoints, that was in both
backends into a single place.
This is in preparation to solve issue #844 (conditional breakpoints
make step and next fail) which will make this common breakpoint code
more complicated.
Instead of only tracking a few cherrypicked registers in stack.go track
all DWARF registers.
This is needed for cgo code and for the locationlists emitted by go in
1.10:
* The debug_frame sections emitted by C compilers can not be used
without tracking all registers
* the loclists emitted by go1.10 need all registers of a frame to be
interpreted.
gosymtab and gopclntab only contain informations about go code, linked
C code isn't there, we should use debug_line instead to also cover C.
Updates #935
debugserver doesn't support qXfer:exec-file:read, and it doesn't return
the executable path in the response to qProcessInfoPID, however we can
find out the executable path by using jGetLoadedDynamicLibrariesInfos.
Instead of panicing for sending on a closed channel, detect that the
process has exited and return a proper error message.
This patch also cleans up some spots where the Pid is omitted from the
error.
Fixes#920
If the user tries to list the contents of a function pointer but
forgets the '*' operator the location lookup will fail and result in a
unhelpful "location not found" error.
Instead if the location lookup fails we should try interpreting the
locspec as if it was preceded by '*'.
When the process exits during we used to return an error, but after
commit 8bbcc89711f4263e7bb2b6d9c00fa96d0294e56f we move the error into
state.Err. Revert this behavior change.
If one of the expressions that are automatically evaluated when a
breakpoint is hit can't be evaluated breakpoint information collection
should continue and the error should be returned for that specific
expression instead of the whole command.
When there's a error reading the stack trace the call stack itself
could be corrupted and we should return the partial stacktrace that we
have.
Fixes#868
When location spec is given and the base can be interpreted either in
source file name or function name, NomalLocationSpec searches both
the source file list and the function symbol list, and selects matching
candidates. Previously, all the matching candidates were added to one
single list regardless whether the candidate was from the source file
list or not. Then, later, Find tries to guess whether the candiate
was a function or a file based on a heuristic, i.e, whether the
candidate is an absolute file path. The heuristic is fragile - since
there is no guarantee that the included source file name is an absolute
path.
Instead, this CL preserves where the candidate was found; file list or
function symbol list. Then, use that info to determine whether the
candidate is a source file name or not.
* Fix various issues detected by megacheck
I've ran honnef.co/go/tools/cmd/megacheck and fixed a few of the
things that came up there.
* Cleanup using Gogland
Other debuggers can be instructed to decorate the stacktrace with the
value of SP. Our SP equivalent is the frame offset, since we can add it
to the Stackframe structure without incurring into added costs we
should, so that frontends can use it if they want.
A next/step/stepout command could hit a normal breakpoint, decorated
with a list of variables to evaluate, if that happens the variable
should be evaluated just as if the breakpoint was hit by a continue.
Implementing proc.Process.Running in a thread safe way is complicated
and nothing actually uses it besides tests, so we are better off
rewriting the tests without Running and removing it.
In particular:
* The call to d.target.Running() in service/debugger/debugger.go
(Restart) can never return true because that line executes while
holding processMutex and all continue operations are also executed
while holding processMutex.
* The call to dbp.Running() pkg/proc/native/proc.go (Detach) can never
return true, because it's only called from
debugger.(*Debugger).detach() which is also always called while
holding processMutex.
Since some tests are hard to write correctly without Process.Running a
simpler interface, Process.NotifyResumed, is introduced.
Fixes#830
- moved target.Interface into proc as proc.Process
- rename proc.IThread to proc.Thread
- replaced interfaces DisassembleInfo, Continuable and
EvalScopeConvertible with Process.
- removed superfluous Gdbserver prefix from types in the gdbserial
backend.
- removed superfluous Core prefix from types in the core backend.