Commit Graph

96 Commits

Author SHA1 Message Date
Alessandro Arzilli
520d792422 proc: workarounds for runtime.clone (#1470)
runtime.clone (on some operating systems?) work similarly to fork:
when a thread calls runtime.clone a new thread is created. For a
short period of time both the parent thread and the child thread
appear to be running the same goroutine, until the child thread
adjusts its TLS to point to the correct goroutine.

This means that proc.GetG for a thread that's currently running
'runtime.clone' could be wrong and, consequently, the field
proc.(G).thread of a G struct returned by GoroutinesInfo could be
also wrong. And, finally, that FindGoroutine could sometimes return
a *G with a bad associated thread if the goroutine of interest
recently called 'runtime.clone'.

To work around this problem this commit makes two changes:

1. proc.GetG will return nil for all threads executing runtime.clone.
2. FindGoroutine will return the selected goroutine as long as the
   ID matches the one requested.

Change (1) takes care of the 'runtime.clone' problem. If we stop
the target process shortly after a thread executed the SYSCALL
instruction in 'runtime.clone' there are three possibilities:

a. Both the parent thread and the child thread are stopped inside
'runtime.clone'. In this case the state we report is slightly
incorrect, because both threads will be reported as not running any
goroutine when we do know which goorutine one of them (the parent)
is running. This doesn't actually matter since runtime.clone is
always called on the system stack and therefore the goroutine in
runtime.allgs will have the correct location.

b. The child thread managed to exit 'runtime.clone' but the parent
thread didn't. This is similar to (a) but in this case GetG on the
child thread will return the correct goroutine. GetG on the parent
thread will still return (incorrectly) nil but this doesn't matter
for the samer reason as described in (a).

c. The parent thread managed to exit 'runtime.clone' but the child
thread didn't. In this case GetG will return the correct goroutine
both for the parent thread (because it's not executing runtime.clone)
and the child thread.

Change (2) means that even if a thread has a completely nonsensical
TLS (for example because it's set through cgo) evaluating a variable
with a valid GoroutineID will still work as long as it's the current
goroutine (which is the most common case). This change also doubles
as an optimization for FindGoroutine.

Fixes #1469
2019-02-26 09:22:33 -08:00
aarzilli
515ccc4b66 proc: fix GoroutinesInfo cache
The allg cache was corrupted when the count parameter was actually
reached.

Fix the bug and add a test for this.
2019-01-07 11:48:35 -08:00
Derek Parker
4c9a72e486 *: Update import name to github.com/go-delve/delve
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.
2019-01-04 19:43:13 +01:00
aarzilli
34e802a42b proc: make structMember work on pointer Variables created through cast
When casting an integer into a struct pointer we make a fake pointer
variable that doesn't have an address, maybeDereference and
structMember should still work on this kind of Variable.

Fixes #1432
2018-12-03 10:00:22 -08:00
aarzilli
85e4ba439c proc/core: add support for windows minidumps
Minidumps are the windows equivalent of unix core files.
This commit updates pkg/proc/core so that it can open and read windows
minidumps.

Updates #794
2018-11-21 12:17:16 -08:00
aarzilli
f8c0c37f30 proc: remove inversion of return variables from returnBreakpointInfo
It was never true that return variables were in the inverse order.
Instead in Go1.11 return variables are saved in debug_info in an
arbitrary order and inverting them just happened to work for this
specific example.

This bug was fixed in Go 1.12, regardless we should attempt to
rearrange return variables anyway.
2018-11-20 12:57:25 -08:00
Sergio Lopez
11accd4d71 proc/proc: Extend GoroutinesInfo to allow specifying a range
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
2018-11-19 10:06:38 -08:00
aarzilli
89c8da65b6 proc: Improve performance of loadMap on very large sparse maps
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`.
2018-11-09 08:12:45 -08:00
Derek Parker
51c342c6b7 pkg/prog: Improve support for external debug info
Adds a config file option to allow specifying a list of directories to
search in when looking for seperate external debug info files.

Fixes #1353
2018-11-08 10:16:42 -08:00
aarzilli
f72c48c034 proc: Continue should always work after CallFunction
Continue did not resume execution after a call to CallFunction if the
point where the process was stopped, before the call CallFunction, was
a breakpoint.

Fixes #1374
2018-10-17 09:07:36 -07:00
aarzilli
b59032516e proc,service,terminal: eval expressions in the scope of a deferred call
Add ability to evaluate variables on the scope of a deferred call's
argument frame.
2018-10-16 08:40:07 -07:00
aarzilli
74c98bc961 proc: support position independent executables (PIE)
Support for position independent executables (PIE) on the native linux
backend, the gdbserver backend on linux and the core backend.
Also implemented in the windows native backend, but it can't be tested
because go doesn't support PIE on windows yet.
2018-10-11 11:21:27 -07:00
aarzilli
910f90c3c8 proc/native,Makefile: allow compiling on macOS without native backend
On macOS 10.14 Apple changed the command line tools so that system
headers now need to be manually installed.

Instead of adding one extra install step to the install procedure add a
build tag to allow compilation of delve without the native backend on
macOS. By default (i.e. when using `go get`) this is how delve will be
compiled on macOS, the make script is changed to enable compiling the
native backend if the required dependencies have been installed.

Insure that both configuration still build correctly on Travis CI and
change the documentation to describe how to compile the native backend
and that it isn't normally needed.

Fixes #1359
2018-10-02 10:46:09 -07:00
Derek Parker
c3f50742b9 *: Misc refactors, and doc additions
Refactors some code, adds a bunch of docstrings and just generally fixes
a bunch of linter complaints.
2018-09-19 20:59:35 +02:00
aarzilli
cab09a4bbb proc: fix next when disassembly fails
Next should work even if one or more instructions in the current
function can not be disassembled.
2018-08-29 16:11:18 -07:00
Derek Parker
49bfbe6d24 proc: Increase inline function support
This patch makes it so inlined functions are returned in the
function
list, and also allows users to set breakpoints on the call site of
inlined functions.

Fixes #1261
2018-08-08 11:08:34 +02:00
aarzilli
568251e43f proc_test: fix test failure on macOS
Something changed on Travis side that broke TestIssue877. Disable that
test when $TRAVIS is set to true.
2018-08-07 17:57:22 -07:00
aarzilli
8f1fc63da8 proc,service,terminal: read defer list
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.
2018-07-24 14:58:56 -07:00
aarzilli
0c15ca5f19 proc: allow breakpoint conditions to contain a single boolean variable
Fixes a bug where breakpoint condition evaluation would never load the
value if the breakpoint condition consisted of just a single variable.

Fix #1264
2018-07-09 17:25:47 -07:00
aarzilli
9a216211d3 proc,terminal,service: let headless instances run without connected clients
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
2018-06-26 10:32:40 -07:00
aarzilli
e19cbcefa9 proc,command: fix optimized function warning in 1.9
A user complained on the mailing list about having continuous
"optimized function warnings" on non-optimized functions when using 1.9.
This commit fixes the problem by disabling optimized function detection
on 1.9 and earlier (where it's impossible) and adds a test so we don't
break it again in the future.
2018-06-20 07:56:32 -07:00
aarzilli
60c58acb8e proc,service: display return values when stepping out of a function
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.
2018-06-12 11:35:56 +02:00
aarzilli
f38a2816d1 proc: move AllGCache to a common struct
Add a new method "Common" to proc.Process that returns a pointer to a
struct that pkg/proc can use to store its things, independently of the
backend.

This is used here to replace the AllGCache typecasts, it will also be
used to store the return values of the stepout breakpoint and the state
for injected function calls.
2018-06-12 11:35:56 +02:00
aarzilli
5155ef047f proc,dwarf/line: support is_stmt and prologue_end flags
Go1.11 uses the is_stmt flag of .debug_line to communicate which
assembly instructions are good places for breakpoints, we should
respect this flag.

These changes were introduced by:
* https://go-review.googlesource.com/c/go/+/102435/

Additionally when setting next breakpoints ignore all PC addresses that
belong to the same line as the one currently under at the cursor. This
matches the behavior of gdb and avoids stopping multiple times at the
heading line of a for statement with go1.11.

Change: https://go-review.googlesource.com/c/go/+/110416 adds the
prologue_end flag to the .debug_line section to communicate the end of
the stack-split prologue. We should use it instead of pattern matching
the disassembly when available.

Fixes #550

type of interfaces
'c7cde8b'.
2018-06-11 11:09:02 -07:00
aarzilli
77056de757 proc_test: miscellaneous line number changes in go1.11 2018-06-11 11:09:02 -07:00
aarzilli
5d26d333bf proc: handle new way of panic'ing in 1.11 2018-06-11 11:09:02 -07:00
aarzilli
3381404604 pkg/proc: respect specified load configuration after reslicing a map
Maps were always loaded with using the default configuration during a
reslice. This is probably a remnant from when we didn't let clients
configure the load parameters.
2018-06-08 13:20:54 -07:00
Sergio Lopez
bafa512067 proc_test: implement test for DWZ compressed DWARF
If dwz binary is available in the system, test delve's ability to find
deduplicated symbols in the DWARF information.

dwzcompression.go contains a small C function (void fortytwo()) which
calls glibc's fprintf with stdin as first argument. Normally, stdin
will be present as a DW_TAG_variable as part of a DW_TAG_compile_unit
named dwzcompression.cgo2.c.

After running dwz on the binary, stdin is moved to a
DW_TAG_partial_unit, which is imported from dwzcompression.cgo2.c with
a DW_TAG_imported_unit.

This test verifies that delve is able to find stdin symbol's type, as a
way to confirm it understands dwz's compressed/deduplicated DWARF
information.
2018-05-23 13:59:45 -07:00
aarzilli
cc86bde549 proc/native,proc/gdbserial: let target access terminal
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
2018-05-18 09:53:29 -07:00
aarzilli
7fd47749ef proc: Flag shadowed arguments as shadowed
Fixes #951
2018-04-23 10:13:21 -07:00
aarzilli
21be59469a proc: cache entire frame in FrameToScope instead of variablesByTag
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
2018-04-23 10:13:21 -07:00
aarzilli
e1f2626b56 proc_test: instrument TestFrameEvaluation
I've seen TestFrameEvaluation fail in CI in the past. It's been a while
since the last time and I couldn't reproduce it locally at all. I'd
like to have some instrumentation in case it happens again.
2018-04-13 15:32:33 -07:00
aarzilli
290e8e7528 proc: support inlining
Go 1.10 added inlined calls to debug_info, this commit adds support
for DW_TAG_inlined_call to delve, both for stack traces (where
inlined calls will appear as normal stack frames) and to correct
the behavior of next, step and stepout.

The calls to Next and Frame of stackIterator continue to work
unchanged and only return real stack frames, after reading each line
appendInlinedCalls is called to unpacked all the inlined calls that
involve the current PC.

The fake stack frames produced by appendInlinedCalls are
distinguished from real stack frames by having the Inlined attribute
set to true. Also their Current and Call locations are treated
differently. The Call location will be changed to represent the
position inside the inlined call, while the Current location will
always reference the real stack frame. This is done because:

* next, step and stepout need to access the debug_info entry of
the real function they are stepping through
* we are already manipulating Call in different ways while Current
is just what we read from the call stack

The strategy remains mostly the same, we disassemble the function
and we set a breakpoint on each instruction corresponding to a
different file:line. The function in question will be the one
corresponding to the first real (i.e. non-inlined) stack frame.

* If the current function contains inlined calls, 'next' will not
set any breakpoints on instructions that belong to inlined calls. We
do not do this for 'step'.

* If we are inside an inlined call that makes other inlined
functions, 'next' will not set any breakpoints that belong to
inlined calls that are children of the current inlined call.

* If the current function is inlined the breakpoint on the return
address won't be set, because inlined frames don't have a return
address.

* The code we use for stepout doesn't work at all if we are inside
an inlined call, instead we call 'next' but instruct it to remove
all PCs belonging to the current inlined call.
2018-03-26 14:30:38 -04:00
Yasushi Saito
82aff3f18a Extend the "frame" command to set the current frame. (#1110)
* Extend the "frame" command to set the current frame.

Command

  frame 3

sets up so that subsequent "print", "set", "whatis" command
will operate on frame 3.

  frame 3 print foo

continues to work.

Added "up", "down". They move the current frame up or down.

Implementation note:

This changes removes "scopePrefix" mode from the terminal/command.go and instead
have the command examine the goroutine/frame value to see if it is invoked in a
scoped context.

* Rename Command.Frame -> Command.frame.
2018-03-22 10:02:15 -07:00
aarzilli
ec8dc3a10d proc,vendor: show global variables in disassembly
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.
2018-03-22 10:01:00 -07:00
Josh Soref
1d3b41f64e all: Spelling 2018-03-20 11:05:35 +01:00
aarzilli
449b3cedef proc: manual stop requests should clear internal breakpoints
Fixes #1145
2018-03-08 12:02:29 -08:00
aarzilli
e47599d09a proc: remove proc.Process.Halt
The proper way to stop a running process is to call RequestManualStop,
which most code already did with the exception of some old test code.
2018-03-06 09:06:19 -08:00
aarzilli
ac1aa98378 proc: remove proc.Process.Kill
the proper way to kill the target process is to pass true to Detach.
Everything except old test code did that already.
2018-03-06 09:06:19 -08:00
aarzilli
f32ce1b21d proc/native: fix race condition between Halt and process death (linux)
If a breakpoint is hit close to process death on a thread that isn't
the group leader the process could die while we are trying to stop it.

This can be easily reproduced by having the goroutine that's executing
main.main (which will almost always run on the thread group leader)
wait for a second goroutine before exiting, then setting a breakpoint
on the second goroutine and stepping through it (see TestIssue1101 in
proc_test.go).

When stepping over the return instruction of main.f the deferred
wg.Done() call will be executed which will cause the main goroutine to
resume and proceed to exit. Both the temporary breakpoint on wg.Done
and the temporary breakpoint on the return address of main.f will be in
close proximity to main.main calling os.Exit() and causing the death of
the thread group leader.

Under these circumstances the call to native.(*Thread).waitFast in
native.(*Thread).halt can hang forever due to a bug similar to
https://sourceware.org/bugzilla/show_bug.cgi?id=12702 (see comment in
native.(*Thread).wait for an explanation).

Replacing waitFast with a normal wait work in most circumstances,
however, besides the performance hit, it looks like in this
circumstances trapWait sometimes receives a spurious SIGTRAP on the
dying group leader which would cause the subsequent call to wait in
halt to accidentally reap the process without noting that it did exit.

Instead this patch removes the call to wait from halt and instead calls
trapWait in a loop in setCurrentBreakpoints until all threads are set
to running=false. This is also a better fix than the workaround to
ESRCH error while setting current breakpoints implemented in 94b50d.

Fixes #1101
2018-03-06 09:06:19 -08:00
aarzilli
dc7a4ccb16 proc: support interface type resolution for packages containing a dot
If the last entry of the package path contains a '.' the corresponding
DIEs for its types will replace the '.' character with '%2e'. We must
do the same when resolving the package path of the concrete type of an
interface variable.

Fixes #1137
2018-03-05 10:07:11 -08:00
Alessandro Arzilli
0c40a8f52a dwarf/reader,proc: support DW_AT_abstract_origin (#1111)
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.
2018-02-13 09:20:45 -08:00
aarzilli
74d330a013 proc: Remove unused code 2018-01-26 12:58:21 -08:00
aarzilli
91fdc5202d proc_test: clean some repeated patterns in proc_test 2018-01-26 12:58:21 -08:00
Alessandro Arzilli
bc77ff4534
proc_test: deflake TestSystemstackOnRuntimeNewstack (#1078)
Depending on how the runtime schedules our goroutines we can get
unlucky and have the first call to runtime.newstack we intercept be for
a different goroutine (usually the garbage collector).
Only check stacktraces that happen on the same goroutine that executed
main.main.
2018-01-19 15:42:23 +01:00
aarzilli
7bec20e5fc proc: avoid scanning system stack if it's not executing cgo
The runtime calls into g0 in many places, not necessarily using
runtime.systemstack or runtime.asmcgocall.
One example of this is the call to runtime.newstack inside
runtime.morestack.

If we stop the process while one goroutine is executing
runtime.newstack we would be unable to fully scan its stack because we
don't know that we have to switch back to the goroutine stack after
runtime.newstack.

Instead of tracking down every possible way that the runtime switches
to g0 we switch to the goroutine stack immediately after the top of the
stack, unless cgo is being executed on the systemstack.

Fixes #1066
2018-01-05 10:29:31 -08:00
aarzilli
07c716818e proc/test: miscellaneous test changes for go1.10 2017-12-13 12:18:18 -08:00
aarzilli
85669434f6 pkg/proc: use DW_AT_decl_line to determine var visibility
Fixes #186, #83
2017-12-13 12:18:18 -08:00
aarzilli
b3246296d7 dwarf/line: handle DW_LNE_end_of_sequence correctly
We need to reset the current file and line number.

Fixes #1008
2017-12-08 02:16:26 -08:00
aarzilli
77c955365f proc: handle DW_TAG_subprogram with a nochildren abbrev
On macOS, externally linked programs will have an abbrev for
DW_TAG_subprogram without the haschildren flag set. We should handle
this case instead of expecting all DW_TAG_subprogram entries to have
list of children.

Fixes #1034
2017-12-07 15:00:18 -08:00