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.
next/step/stepout should work even if the current frame isn't the
topmost stack frame, but their behavior should be different in that
case (they should continue inside the function of the selected frame).
Most of the logic of next/step/stepout would work correctly if we
simply replaced the call to proc.topframe with something that took a
frame index. However the breakpoint they set on the first deferred
function is wrong, and fixing it requires scanning the defer stack and
matching it to the call stack, something we can't do yet.
Given that enhancing next/step/stepout will take time and the current
behavior confuses users (see issue #1240) return an error if
next/step/stepout are called while the currently selected frame isn't
frame 0.
Updates #1240
There is no guarantee that files will end up stored contiguously in the
debug_line section which makes this optimization wrong in the general
case.
In particular with recent versions of go1.11 and a go.mod file present
the go compiler seems to sometimes produce executables that actually
violate this assumption.
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
The JSON-RPC layer doesn't like non-nil error that return an empty string
when the Error method is called and when this happens it shuts down the
connection to the server.
Since we can return a ThreadBlockedError to the client it can't have an
empty string as return value.
Fixes#1251
Core files created by gdb can have sections missing that would be
present in OS created core files.
We work around this by first reading PT_LOAD entries from the exe and
then reading them from the core.
Fixes#1121
* Adds some links to the more relevant documentation pages on the main
README.md
* Adds a document informally describing how to write a client of delve
* Adds link to slides describing the architecture of delve
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
This message is used by clients to determine the port that a headless
instance is using, therefore the format can not change or move to a
different file handle.
Fixes#1245
Go1.11 switched to the zlib-gnu compression format for debug sections.
Change proc and and a test in dwarf/line to support this change.
Also deletes some dead code from pkg/proc/bininfo.go that hadn't been
used in a long time.
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.
To save disk space, some distributions strip the debugging information
from the binaries, putting it in separate files, usually distributed in
separate packages.
To locate the file containing the debug information for a certain
binary, an ELF note named ".note.gnu.build-id" is added to the latter,
which contains a header and a build identification. This identification
can be used to compose a path with this form:
/usr/lib/debug/.build-id/BUILDID[:2]/BUILDID[2:].debug
With this patch, if Delve can't find the debug information in the main
binary, it'll try to locate and parse ".note.gnu.build-id", to compose
and attempt to open a path with the format described above.
Fixes#1206
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.
If the application being debugged imports two packages with the same
name (but different paths) there was no way to disambiguate the two,
since the character '/' can not appear inside a go identifier.
By allowing users to use a string literal as the package name a package
path can be specified.
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.
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.
go1.11 adds a new extended attribute to all type DIEs containing the
address of the corresponding runtime._type struct, use this attribute
to find the DIE of the concrete type of interface variables when
available.
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'.
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.
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.
The EnableDWZCompression flag allows tests to request BuildFixture to
run "dwz" on the Fixture's resulting binary to compress/deduplicate its
DWARF sections.
'dwz' is a tool that reduces the size of DWARF sections by
deduplicating symbols. The deduplicated symbols are moved from their
original 'compile unit' to a 'partial unit', which is then referenced
from its original location with an 'imported unit' tag.
In the case of Go binaries, all symbols are located in a single
'compile unit', and the name of each symbol contains a reference to its
package, so 'dwz' is not able to deduplicate them. But still, some C
symbols included in the binary are deduplicated, which also alters the
structure of the DWARF sections, making delve unable to parse them
(crashing in the attempt).
While it would've been possible to simply ignore the C symbols, or
blindly loading all then into BinaryInfo members (packageVars,
Functions...), for correctness sake this change tries to do the right
thing, staging symbols into temporary partialUnit objects, moving them
to BinaryInfo when they are actually requested by a 'imported unit'
tag.
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
Go seems to be generating multiple compilation units that have
the same file. I think this happens for functions that get inlined.
Without this patch, those inlined functions break the ability to set
a breakpoint at other lines in the file. I was able to load the same
binary in gdb and set a breakpoints throughout the file without issue.
```
➜ objdump --dwarf=decodedline automate-gateway | grep handler/users.go
.../handler/users.go:[++]
s/.../handler/users.go 20 0xb6dd88
.../handler/users.go:[++]
s/.../handler/users.go 20 0xb6e50f
.../handler/users.go:[++]
s/automate-gateway/handler/users.go 32 0xb66640
```
Inlined functions are still a little weird. setting a breakpoint on
a function that gets inlined picks the first occurence. That being
said, I think delve should still do something reasonable for the rest
of the lines in the file.
Previously to 4e177bb99acc511897f9cdbfc6cbc50d92ae4725 it was possible
to use --log without arguments to enable logging, this commit reenables
that use case.
The new functionality of the --log flag moved to a new flag name
--logx.
Fixes#1188
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