If we cannot find debug information locally on the system, try and
invoke debuginfod-find in order to ask the linux distribution we're on
to find the debug information for us.
StaticBase is the difference between the entry point declared in the
image file and the entry point as loaded in memory, since this
difference could be a negative number we have to use a signed
comparison when searching for a mapping.
Causes intermittent test failures on windows when resolving interface
types for position independent executables.
Fixes#2620
Conversion form a moduledata object into an image object was
implemented by looking for a function covering the start address of the
text section of the moduledata object, and then converting that into
its corresponding image.
Unfortunately this seems to not always work. In particular it does not
work on linux/386 with go1.17 (but it might also fail on other
combinations): the start address of the text section is, for whatever
reason, not part of any function.
As a fallback simply scan all images we know of and return the closest
one that has start address less than or equal to the start address of
the text section we are looking for.
Fixes TestPluginVariables on go1.17/linux/386.
Fixes#2611
Co-authored-by: a <a@kra>
* proc: support new Go 1.17 panic/defer mechanism
Go 1.17 will create wrappers for deferred calls that take arguments.
Change defer reading code so that wrappers are automatically unwrapped.
Also the deferred function is called directly by runtime.gopanic, without going through runtime.callN which means that sometimes when a panic happens the stack is either:
0. deferred function call
1. deferred call wrapper
2. runtime.gopanic
or:
0. deferred function call
1. runtime.gopanic
instead of always being:
0. deferred function call
1. runtime.callN
2. runtime.gopanic
the isPanicCall check is changed accordingly.
* test: miscellaneous minor test fixes for Go 1.17
* proc: resolve inlined calls when stepping out of runtime.breakpoint
Calls to runtime.Breakpoint are inlined in Go 1.17 when inlining is
enabled, resolve inlined calls in stepInstructionOut.
* proc: add support for debugCallV2 with regabi
This change adds support for the new debug call protocol which had to
change for the new register ABI introduced in Go 1.17.
Summary of changes:
- Abstracts over the debug call version depending on the Go version
found in the binary.
- Uses R12 instead of RAX as the debug protocol register when the binary
is from Go 1.17 or later.
- Creates a variable directly from the DWARF entry for function
arguments to support passing arguments however the ABI expects.
- Computes a very conservative stack frame size for the call when
injecting a call into a Go process whose version is >=1.17.
Co-authored-by: Michael Anthony Knyszek <mknyszek@google.com>
Co-authored-by: Alessandro Arzilli <alessandro.arzilli@gmail.com>
* TeamCity: enable tests on go-tip
* goversion: version compatibility bump
* TeamCity: fix go-tip builds on macOS/arm64
Co-authored-by: Michael Anthony Knyszek <mknyszek@google.com>
While Go still mostly uses DWARF v4, newer versions of GCC will emit
DWARF v5 by default. This patch improves support for DWARF v5 by parsing
the .debug_line_str section and using that during file:line lookups.
This patch only includes support for files, not directories.
Co-authored-by: Derek Parker <deparker@redhat.com>
The code populating runtimeTypeToDIE was incorrectly adding StaticBase
to the offset. We never noticed because on statically compiled
executables StaticBase is always zero and on PIE and plugins the
fallback code took care of the problem anyway.
A change in Go 1.17 broke the fallback code, making the issue apparent.
This commit fixes the setup of runtimeTypeToDIE and disables the
fallback code for Go 1.17 and later.
This change also fixes a rare failure in TestPluginVariables when PIE
is enabled.
This adds a workaround for the bug described at:
https://github.com/golang/go/issues/25841
Because dsymutil running on PIE does not adjust the address of
debug_frame entries (but adjusts debug_info entries) we try to do the
adjustment ourselves.
Updates #2346
When cgo is used the address of the g struct is saved on the special
register TPIDR_EL0. Because executing C code could overwrite the
contents of R28 that normally contains the address of g we should read
it from TPIDR_EL0 instead when runtime.iscgo is set.
* Reformat pkg/locspec documentation so that it is formatted correctly
by godoc/pkgsite
* Unexport some types and variables in proc that don't need to be
exported.
Add a helper method for collecting line table file references that
does the correct thing for DWARF 5 vs DWARF 4 (in the latter case you
have an implicit 0 entry which is the comp dir, whereas in the former
case you do not). This is to avoid out-of-bounds errors when examining
the file table section of a DWARF 5 compilation unit's line table.
Included is a new linux/amd-only test that includes a precompiled C
object file with a DWARF-5 section that triggers the bug in question.
Fixes#2319
The DWARF standard does not say that a DW_ATTR_abstract_origin can only
reference entries that appear before it, this change fixes BinaryInfo
to comply. See #2284 for an example of this happening.
* Revert "proc: Find executable should follow symbol links."
This reverts commit 3e04ad0fada0c3ab57caf58bc024e4c0f9a3e01a.
* proc: resolve symlinks when searching for split debug_info if path is /proc/pid/exe
Fixes#2168
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.
Under some circumstances (methods with non-pointer receivers or from
embedded fields called through an interface) the compiler will
autogenerate wrapper functions.
This commit changes next, step and stepout to skip all autogenerated
wrappers.
Fixes#1908
Instead of rescanning debug_info every time we want to read a function
(either to find inlined calls or its variables) cache the tree of
dwarf.Entry that we would generate and use that.
Benchmark before:
BenchmarkConditionalBreakpoints-4 1 5164689165 ns/op
Benchmark after:
BenchmarkConditionalBreakpoints-4 1 4817425836 ns/op
Updates #1549
Implement debugging function for 386 on linux with reference to AMD64.
There are a few remaining problems that need to be solved in another time.
1. The stacktrace of cgo are not exactly as expected.
2. Not implement `core` for now.
3. Not implement `call` for now. Can't not find `runtime·debugCallV1` or
similar function in $GOROOT/src/runtime/asm_386.s.
Update #20
* tests: misc test fixes for go1.14
- math.go is now ambiguous due to changes to the go runtime so specify
that we mean our own math.go in _fixtures
- go list -m requires vendor-mode to be disabled so pass '-mod=' to it
in case user has GOFLAGS=-mod=vendor
- update version of go/packages, required to work with go 1.14 (and
executed go mod vendor)
- Increased goroutine migration in one development version of Go 1.14
revealed a problem with TestCheckpoints in command_test.go and
rr_test.go. The tests were always wrong because Restart(checkpoint)
doesn't change the current thread but we can't assume that when the
checkpoint was taken the current goroutine was running on the same
thread.
* goversion: update maximum supported version
* Makefile: disable testing lldb-server backend on linux with Go 1.14
There seems to be some incompatibility with lldb-server version 6.0.0
on linux and Go 1.14.
* proc/gdbserial: better handling of signals
- if multiple signals are received simultaneously propagate all of them to the
target threads instead of only one.
- debugserver will drop an interrupt request if a target thread simultaneously
receives a signal, handle this situation.
* dwarf/line: normalize backslashes for windows executables
Starting with Go 1.14 the compiler sometimes emits backslashes as well
as forward slashes in debug_line, normalize everything to / for
conformity with the behavior of previous versions.
* proc/native: partial support for Windows async preempt mechanism
See https://github.com/golang/go/issues/36494 for a description of why
full support for 1.14 under windows is problematic.
* proc/native: disable Go 1.14 async preemption on Windows
See https://github.com/golang/go/issues/36494
Due to a bug in the Go compiler midstack inlined calls do not report
their ranges correctly. We can't check if an address is in the range of
a DIE by simply looking at that DIE's range, we should also recursively
check the DIE's children's ranges.
Also fixes the way stacktraces of midstack inlined calls are reported
(they used to be inverted, with the deepest inlined stack frame
reported last).
Fixes#1795
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.
* delve now can be built to arm64-arch and running on linux-arm64 OS.
* arm64 general-purpose registers have completed.
* arm64 disasm has completed.
Co-authored-by: tykcd996 <tang.yuke@zte.com.cn>
Co-authored-by: hengwu0 <wu.heng@zte.com.cn>
Use the name specified by compile unit attribute DW_AT_go_package_name,
introduced in Go 1.13, to map package names to package paths, instead of
trying to deduce it from names of types.
Also use this mapping for resolving global variables and function
expressions.
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.
program
When evaluating type casts always resolve array types.
Instead of resolving them by looking up the string in debug_info
construct a fake array type so that a type cast to an array type always
works as long as the element type exists.
We already did this for byte arrays, this commit extends this to any
array type. The reason is that we return a fake array type (that
doesn't exist in the target program) for the array of a channel type.
Fixes#1736
Make the 'list' command succeed for file:line expressions that don't
map to any instruction.
Adds an argument to the FindLocations API call that makes FindLocations
return if the expression can be parsed, even if it doesn't end up
matching any instruction in debug_line.
Splits the code that loads function information from debug_info into
multiple functions.
This makes the changes needed to implement logical breakpoints easier
to make.
The fix for #1428 was buggy, partly because I communicated poorly. Sorry
about that.
The size of the TLS segment should be padded such that TLS addresses
are congruent in the file to where they will end up memory, i.e.
(tlsoffset%align) == (vaddr%align). In most cases, vaddr will be aligned
and it won't matter, but if not then simply aligning the end of the
segment is incorrect. This should be right.
(For the record, the current rounding logic is working in bits, but
PtrSize is in bytes, so it wasn't working as originally intended
either.)
Intent here is to bring optargorder up to date with delve
and keep it in sync (and to use optargorder to help monitor
compiler output for debugging quality regressions).
Support for bulk queries makes the DWARF quality checker
(github.com/dr2chase/dwarf-goodness/cmd/dwarf-goodness)
run much more efficiently (replace quadratic cost with
linear).
Also fixes findCompileUnitForOffset which was broken in some edge cases
(when looking up an offset inside the last child of the compilation
unit) which don't happen in normal executables (we only look up types, and those
are always direct childs of compile units).
Instead of reading partial units as we see them skip them entirely and
then re-read them when they are imported, directly into the destination
compile unit.
This avoids a lot of duplicate code in the loadDebugInfoMaps function
and will simplify implementing logical breakpoints and support for the
new DW_AT_go_package_name attribute added in Go 1.13.
The current wording is confusing - the file exists and the line exists, so what is the problem? I suspect this ambiguity is behind #1496 and likely others.
Also I updated the style to return values like the rest of the code in the file, which is also more readable (IMO and per https://github.com/golang/go/wiki/CodeReviewComments#named-result-parameters)
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.
The size of the TLS memory arena needs to be aligned to pointer sized
boundaries on 86x64 architectures, otherwise some programs using cgo
will not have the correct offset for the g struct.
No tests because reproducing this problem depends on behavior of the
GNU ld linker caused by unclear influences.
Fixes#1428.
This patch is a slight refactor to share more code used for genericprocess initialization. There will always be OS/backend specificinitialization, but as much as can be shared should be to preventduplicating of any logic (setting internal breakpoints, loading bininfo,etc).
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.
Normally variables that have a named struct as a type will get a
typedef entry as their type, sometimes however the Go linker will
decide to use the DW_TAG_structure_type entry instead.
For consistency always wrap a struct type into a typedef when we are
creating a new variables (see comment in newVariable for exceptions).
This fixes a bug where it would be impossible to call methods on a
global variable.
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
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
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.
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
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.
'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.
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.
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.
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.
Adds a configuration option (show-location-expr) that when activated
will cause the whatis command to also print the DWARF location
expression for a variable.
1. Use a slice instead of a map to access standard and extended opcodes
(reduces BenchmarkStateMachine from ~12ms/op to ~7ms/op)
2. Cache StateMachine values for the entry point of functions.
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
Splits out type parsing and go-specific Type hierarchy from
x/debug/dwarf, replace x/debug/dwarf with debug/dwarf everywhere,
remove x/debug/dwarf from vendoring.
Variable lookup is slow because it requires a full scan of debug_info
to check for package variables, this doesn't matter much in interactive
use but can slow down evaluation of breakpoint conditions
significantly.
Providing benchmark proof for this is hard since this effect doesn't
show for small programs with small debug_info sections.
When a Go program is externally linked, the external linker is
responsible for picking the TLS offset. It records its decision in the
runtime.tlsg symbol. Read the offset from that rather than guessing -16.
This implementation causes a regression: 1.4 and earlier will no longer
work.
* proc: refactor BinaryInfo part of proc.Process to own type
The data structures and associated code used by proc.Process
to implement target.BinaryInfo will also be useful to support a
backend for examining core dumps, split this part of proc.Process
to a different type.
* proc: compile support for all executable formats unconditionally
So far we only compiled in support for loading the executable format
supported by the host operating system.
Once support for core files is introduced it is however useful to
support loading in all executable formats, there is no reason why it
shouldn't be possible to examine a linux coredump on windows, or
viceversa.
* proc: bugfix: do not resume threads on detach if killing
* Replace BinaryInfo interface with BinInfo() method returning proc.BinaryInfo