* Adjust rtype.go script to handle constants moved to internal/abi from
runtime
* Remove tests in service/dap/server_test that relied on knowledge of
the internal layout of channels.
Go 1.21 renamed runtime._type to internal/abi.Type and changed the name
of its fields. Update Delve so that it uses the new names for loading
interfaces and generic type parameters.
Before 1.11 we used to read a bunch of runtime structures to determine
the runtime type of an interface variable. This had significant
dependencies on private structs of the Go runtime and the code is
broken for versions of Go after 1.17.
Remove all this code, since it is no longer used and doesn't work with
newer versions of Go anyway.
Go 1.19 also formats doc comments according to the new godoc syntax.
Some of our comments, especially unexported symbols did not conform to
the godoc syntax and therefore are mangled by 'go fmt'.
This PR runs 'go fmt' from go1.19 on everything and manually fixes the
problems.
See also:
https://github.com/golang/proposal/blob/master/design/51082-godocfmt.md
Change debug_info type reader and proc to convert parametric types into
their real types by reading the corresponding dictionary entry and
using the same method used for interfaces to retrieve the DIE from a
runtime._type address.
'2586e9b1'.
Adds a script that check automatically that the the assumptions that
pkg/proc makes about runtime are met by the actual runtime, using a
combination of parsing and magic comments.
Also emits a file describing all the struct fields, constants and
variables of the runtime that we use in pkg/proc.
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>
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.
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.
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.
Go 1.8 has been out of date for a while and the code to support it is
potentially dangerous if a future version of Go removes the runtime
types from debug_info and also changes their representation.
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.
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).
Childless compile units would confuse loadDebugInfoMaps.
No test because I don't know what causes go to invoke GNU As in such a
way that it produces a childless compile unit.
Fixes#1572
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.
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
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.
If a function can be inlined it will appear as two entries in
debug_info. A DW_TAG_subprogram entry with DW_AT_inlined = true (that
will be used as the abstract origin) and a second DW_TAG_subprogram
entry with an abstract origin.
To retrieve the name of this second entry we must load its abstract
origin.
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`.
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.
Changes (*Variable).setValue so that it can be used in CallFunction to
set up the argument frame for the function call, adding the ability to:
- nil nillable types
- set strings to the empty string
- copy from one structure to another (including strings and slices)
- convert any interface type to interface{}
- convert pointer shaped types (map, chan, pointers, and structs
consisting of a single pointer field) to interface{}
This covers all cases where an assignment statement can be evaluated
without allocating memory or calling functions in the target process.
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
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.
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.
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.
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'.
'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.
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.
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
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