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.
When attaching to a process in linux ElfUpdateSharedObjects will be
called for the first time during the call to updateThreadList,
unfortunately it won't do anything because the dynamic section of the
base elf executable needs to have been read first and that's done when
we initialize the BinaryInfo object (which happens later during the
call to initialize).
Remove build tags from disassembler code, move architecture specific
functionality inside proc.Arch.
This is necessary because Delve should be able to debug corefiles
cross-platform.
* fix TestKill test:
It will fail in Open /proc/pid/ sporadicly since there is no any sync between signal sended(tracee handled) and open /proc/%d/, especially in some weak arm64 cpu. Skip /proc check on arm64.
* remove skip-code of Detach tests.
arm64 use hardware breakpoint, and it will not set PC to the next instruction like amd64. Let adjustPC always fasle in arm64, in case of infinite loop.
PtraceSingleStep cannot step over BRK instruction(linux-arm64 feature or kernel bug maybe).
GDB has the same question too, it will hang on forever with c command or execute that instruction indefinitely with s,si command.
SetPC+BreakpointSize to jump over BRK to prevent repeating the instruction indefinitely.
Co-authored-by: tykcd996 <tang.yuke@zte.com.cn>
Co-authored-by: hengwu0 <wu.heng@zte.com.cn>
* 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>
As proc/native is arch related, it should move some functions to arch-relate file. And this patch can help us to separate the architecture code, make code tidy. So that the merge of arm64 code later will not cause chaos.(#118)
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.
* Makefile: discard stderr of "go list"
In module mode "go" will print messages about downloading modules to
stderr, we shouldn't confuse them for the real command output.
* proc/core: enable PIE tests
PIE tests for core files were never enabled due to a missing flag.Parse
call.
* proc/linux: do not route signals to threads while stopping
While we are trying to stop the process we should not route signals
sent to threads because that will result in threads being resumed.
Also keep better track of which threads are stopped.
This fixes an incompatibility with Go 1.14, which sends a lot of
signals to its threads to implement non-cooperative preemption,
resulting in Delve hanging waiting for an already-stopped thread to
stop.
In principle however this bug has nothing to do with Go 1.14 and could
manifest in any instance of high signal pressure.
* Makefile: discard stderr of "go list"
In module mode "go" will print messages about downloading modules to
stderr, we shouldn't confuse them for the real command output.
Instead of just sending unhandled signals back to the process send them
to the specific thread that received them.
This is important because:
1. debugserver does not appear to support the vCont;CXX packet without
specifying a target thread
2. the non-cooperative preemption change in an upcoming version of Go
(1.15?) will require sending signals to a specific thread.
Fixes#1744
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
Fixes a case of breakpoint confusion on resume caused by having two
breakpoints one byte apart. This bug can cause the target program to
resume execution a single byte inside an instruction and crash either
with SIGILL or a SIGSEGV, or misbehave (depending on how the truncated
instruction is decoded).
native.(*Thread).StepInstruction should call FindBreakpoint using
adjustPC==false because at that point the PC of the thread should
already have been adjusted (and it has been).
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.
Adds a '-r' option to the 'restart' command (and to the Restart API)
that re-records the target when using rr.
Also moves the code to delete the trace directory inside the gdbserial
package.
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.
Trust argument order to determine argument frame layout when calling
functions, this allows calling optimized functions and removes the
special cases for runtime.mallocgc.
Fixes#1589
Add options to start a stacktrace from the values saved in the
runtime.g struct as well as a way to disable the stackSwitch logic and
just get a normal stacktrace.
If a closure captures a variable but also defines a variable of the
same name in its root scope the shadowed flag would, sometimes, not be
appropriately applied to the captured variable.
This change:
1. sorts the variable list by depth *and* declaration line, so that
closure captured variables always appear before other root-scope
variables, regardless of the order used by the compiler
2. marks variable with the same name as shadowed even if there is only
one scope at play.
This fixes the problem but as a side effect:
1. programs compiled with Go prior to version 1.9 will have the
shadowed flag applied arbitrarily (previously the shadowed flag was not
applied at all)
2. programs compiled with Go prior to versoin 1.11 will still exhibit
the bug, as they do not have DeclLine information.
Fixes#1672
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).
proc.Next and proc.Step will call, after setting their temp
breakpoints, curthread.SetCurrentBreakpoint. This is intended to find
if one of the newly created breakpoints happens to be at the same
instruction that curthread is stopped at.
However SetCurrentBreakpoint is intended to be called after a Continue
and StepInstruction operation so it will also detect if curthread is
stopped one byte after a breakpoint.
If the instruction immediately preceeding the current instruction of
curthread happens to:
1. have one of the newly created temp breakpoints
2. be one byte long
SetCurrentBreakpoint will believe that we just hit that breakpoint and
therefore the instruction should be repeated, and thus rewind the PC of
curthread by 1.
We should distinguish between the two uses of SetCurrentBreakpoint and
disable the check for "just hit" breakpoints when inappropriate.
Fixes#1656
Moves EvalScope methods to the proper file and organizes everything
together. Also makes some EvalScope methods no longer methods and just
pure functions.
* proc: fix stacktraces when a SIGSEGV happens during a cgo call
When a SIGSEGV happens in a cgo call (for example as a result of
dereferencing a NULL pointer) the stack layout will look like this:
(system stack) runtime.fatalthrow
(system stack) runtime.throw
(system stack) runtime.sigpanic
(system stack) offending C function
... other C functions...
(system stack) runtime.asmcgocall
(goroutine stack) call inside cgo
The code in switchStack would switch directly from the
runtime.fatalthrow frame to the first frame in the goroutine stack,
hiding important information.
Disable this switch for runtime.fatalthrow and reintroduce the check
for runtime.mstart that existed before this version of the code was
implemented in commit 7bec20.
This problem was reported in comment:
https://github.com/go-delve/delve/issues/935#issuecomment-512182533
* cmd/dlv: actually disable C compiler optimizations when building
* *: Add .cirrus.yml for FreeBSD testing
* *: run go mod tidy
* service/test: prefer 127.0.0.1 over localhost
* dwarf/line: fix TestDebugLinePrologueParser
* vendor: rerun go mod vendor
Propagate signals when stepping because debugserver will report them,
from the issue:
2019-07-11T16:31:25+02:00 debug layer=gdbconn <- $z0,105525d,1#c9
2019-07-11T16:31:25+02:00 debug layer=gdbconn -> $OK#00
2019-07-11T16:31:25+02:00 debug layer=gdbconn <- $vCont;s:c41c3#50
2019-07-11T16:31:25+02:00 debug layer=gdbconn -> $T1cthread:c41c3;threads:c41c3,c41d7,c41d8,c41d9,c41da;thread-pcs:105525d,7fffc464bf46,7fffc464bbf2,7fffc464bbf2,7fffc46...
2019-07-11T16:31:25+02:00 debug layer=gdbconn <- $Z0,105525d,1#a9
2019-07-11T16:31:25+02:00 debug layer=gdbconn -> $OK#00
in this case we request a single step on thread c41c3 but debugserver
reports instead a signal (in this case SIGWINCH).
Fixes#1610
Add variables flag to mark variables that are allocated on a register
(and have no address) and variables that we read as result of a
function call (and are allocated on a stack that no longer exists when
we show them to the user).
Increases the maximum string length from 64 to 1MB when loading strings
for a binary operator, also delays the loading until it's necessary.
This ensures that comparison between strings will always succeed in
reasonable situations.
Fixes#1615
Backports debug/dwarf commit: 535741a69a1300d1fe2800778b99c8a1b75d7fdd
CL: https://go-review.googlesource.com/18459
The x/debug/dwarf that we used for dwarf/godwarf/type.go was forked
from debug/dwarf long before this commit.
Original description:
Currently readType simultaneously constructs a type graph and resolves
the sizes of the types. However, these two operations are
fundamentally at odds: the order we parse a cyclic structure in may be
different than the order we need to resolve type sizes in. As a
result, it's possible that when readType attempts to resolve the size
of a typedef, it may dereference a nil Type field of another typedef
retrieved from the type cache that's only partially constructed.
To fix this, we delay resolving typedef sizes until the end of the
readType recursion, when the full type graph is constructed.
Fixes#1601
* proc: allow simultaneous call injection to multiple goroutines
Changes the call injection code so that we can have multiple call
injections going on at the same time as long as they happen on distinct
goroutines.
* proc: fix EvalExpressionWithCalls for constant expressions
The lack of address of constant expressions would confuse EvalExpressionWithCalls
Fixes#1577
* tests: fix tests for Go 1.13
- Go 1.13 doesn't autogenerate init functions anymore, tests that
expected that now fail and should be skipped.
- Plugin tests now need -gcflags'all=-N -l' now, we were probably
getting lucky with -gcflags='-N -l' before.
* proc: allow signed integers as shift counts
Go1.13 allows signed integers to be used as the right hand side of a
shift operator, change eval to match.
* goversion: update maximum supported version
* travis: force Go to use vendor directory
Travis scripts get confused by "go: downloading" lines, the exact
reason is not clear. Testing that the vendor directory is up to date is
a good idea anyway.
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).
The location specified '<fnname>:0' could be used to set a breakpoint
on the entry point of the function (as opposed to locspec '<fnname>'
which sets it after the prologue).
Setting a breakpoint on an entry point is almost never useful, the way
this feature was implemented could cause it to be used accidentally and
there are other ways to accomplish the same task (by setting a
breakpoint on the PC address directly).
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).
Allow changing the value of a string variable to a new literal string,
which requires calling runtime.mallocgc to allocate the string into the
target process.
This means that a command like:
call f("some string")
is now supported.
Additionally the command:
call s = "some string"
is also supported.
Fixes#826
The bitmasks for transforming a 64-bit register into it's lower-bit
counterparts (e.g. RAX -> EAX -> AX -> AH/AL) were incorrect. This patch
fixes the bitmasks and adds an additional test.
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.
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)
* proc: support nested function calls
Changes the code in fncall.go to support nested function calls.
This changes delays argument evaluation until after we have used
the call injection protocol to allocate an argument frame. When
evaluating the parse tree of an expression we'll initiate each
function call we find on the way down and then complete the function
call on the way up.
For example. in:
f(g(x))
we will:
1. initiate the call injection protocol for f(...)
2. progress it until the point where we have space for the arguments
of 'f' (i.e. when we receive the debugCallAXCompleteCall message
from the target runtime)
3. inititate the call injection protocol for g(...)
4. progress it until the point where we have space for the arguments
of 'g'
5. copy the value of x into the argument frame of 'g'
6. finish the call to g(...)
7. copy the return value of g(x) into the argument frame of 'f'
8. finish the call to f(...)
Updates #119
* proc: bugfix: closure addr was wrong for non-closure functions
The initial implementation of the 'call' command required the
function call to be the root expression, i.e. something like:
double(3) + 1
was not allowed, because the root expression was the binary operator
'+', not the function call.
With this change expressions like the one above and others are
allowed.
This is the first step necessary to implement nested function calls
(where the result of a function call is used as argument to another
function call).
This is implemented by replacing proc.CallFunction with
proc.EvalExpressionWithCalls. EvalExpressionWithCalls will run
proc.(*EvalScope).EvalExpression in a different goroutine. This
goroutine, the 'eval' goroutine, will communicate with the main
goroutine of the debugger by means of two channels: continueRequest
and continueCompleted.
The eval goroutine evaluates the expression recursively, when
a function call is encountered it takes care of setting up the
function call on the target program and writes a request to the
continueRequest channel, this causes the 'main' goroutine to restart
the target program by calling proc.Continue.
Whenever Continue encounters a breakpoint that belongs to the
function call injection protocol (runtime.debugCallV1 and associated
functions) it writes to continueCompleted which resumes the 'eval'
goroutine.
The 'eval' goroutine takes care of implementing the function call
injection protocol.
When the expression is fully evaluated the 'eval' goroutine will
write a special message to 'continueRequest' signaling that the
expression evaluation is terminated which will cause Continue to
return to the user.
Updates #119
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
Remove the breakpoint set in TestCallConcurrent so that it doesn't
interfere with the call injection protocol.
The fact that it can is a bug but that bug is better addressed after
PRs #1503 and #1504 are merged, this keeps tests happy in the meantime.
Fixes#1542
Go 1.12 introduced a change to the internal map representation where
empty map cells can be marked with a tophash value of 1 instead of just
0.
Fixes#1531
RestoreRegisters on linux would also restore FS_BASE and GS_BASE, if
the target goroutine migrated to a different thread during the call
injection this would result in two threads of the target process
pointing to the same TLS area which would greatly confuse the target
runtime, leading to fatal panics with nonsensical stack traces.
Other backends are unaffected:
- native/windows doesn't store the TLS in the same CONTEXT struct as
the other register values.
- native/darwin doesn't support function calls (and wouldn't store the
TLS value in the same struct)
- gdbserial/rr doesn't support function calls (because it's a
recording)
- gsdbserial/lldb extracts the value of TLS by executing code in the
target process.
* *: use loglevel to control what gets logged instead of output redirection
This stops logrus from doing all the formatting just to discard it
immediately afterwards.
* logflags: replace default formatter of logrus
The default formatter of logrus emits logs in two different formats
depending on whether or not the output is going to a terminal. The
output format for non-terminals is indented to be machine readable, but
we mostly read logs ourselves and the excessive quoting makes that
format unreadable.
When outputting to terminals it uses ANSI escape codes unconditionally,
without checking whether the terminal it is connected to actually
supports colors.
This commit replaces the default formatter with a much simpler
formatter that always uses a more readable format, doesn't use colors
and places the key-value pairs at the beginning of the line (which is a
better match for how we use them).
* cmd/dlv: add command line options to redirect logs
Adds two options, --log-to-file and --log-to-fd, to redirect logs to a
file or to a file descriptor.
When one of those two options is specified the "API server listening
at:" message will also be redirected to the specified file/file
descriptor.
This allows clients that want to use the "API server listening at:"
message to do so even if they want to redirect the target's stdout to
another file or device.
Implements #1179, #1523
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
Like we do with unrecovered panics, create a default breakpoint to
catch runtime errors that will cause the program to terminate.
Primarily intended to give users the opportunity to examine the state
of a deadlocked process.
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
When compression is applied by default running the DWZ tool on the
resulting binary will crash.
The actual default compression code will look and see if compression
makes any difference and if so replace the normal `.debug_*` section
with `.zdebug_*`. This is why it may not have been hit before. On one of
my workstations I build with 1.12rc1 and no compression happens, but on
a Fedora VM I build and the binary results in compressed DWARF sections.
Adding this flag will make this test more consistent overall.
FindGoroutine can be slow when there are many goroutines running. This
can not be fixed in the general case, however:
1. Instead of getting the entire list of goroutines at once just get a
few at a time and return as soon as we find the one we want.
2. Since FindGoroutine is mostly called by ConvertEvalScope and users
are more likely to request informations about a goroutine running on a
thread, look within the threads first.
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.
Some build environments (such as when building RPMs) enjoy symlinking
things. This unfortunately causes our tests to fail as we record the
path of fixtures and use that when looking up file:line information.
However, the debug info in the binary records the original file
location, not the location of the symlink.
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
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.
Goroutine id == 0 is special (there can be many goroutines with id 0).
If the caller of FindGoroutine asks for gid==0 and current thread is
running a goroutine 0 (i.e. either no goroutine or a special
goroutine) return whatever goroutine is running on the current thread.
Updates #1428
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
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.
If proc.Step encounters a CALL instruction that points to an address
that isn't associated with any function it should still follow the
CALL.
The circumstances creating this problem do not normally occur, it was
encountered in the process of fixing a bug created by Go1.12.
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.
When a location expression requests a register check that we have as
many bytes in the register as requested and if we don't report the
error.
Updates #1416
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
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).
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`.
The linux version of proc/native and proc/core contained largely
overlapping implementations of the register handling code, deduplicate
it by moving it into proc/linutil.
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
Some libraries (for example steam_api64.dll) will send this exception
code to set the thread name on Microsoft VisualC.
In theory it should be fine to send the exception back to the target,
which is responsible for setting a handler for it, in practice in some
cases (steam_api64.dll) this will crash the program. So we'll mask it
instead.
Fixes#1383
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
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.
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
With this syntax users do not need to type the concrete type of an
interface variable to access its contents. This also sidesteps the
problem where the serialization of a type by go/printer is different
from the one used for debug_info type names.
Updates #1328
Go allows converting a single integer value to string, resulting in a
string containing a single unicode rune with the same code as the value
of the integer.
Allow the same conversion to happen.
Fixes#1322
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.
Fncall.go was written with the assumption that the object returned by
proc.Thread.Registers does not change after we call
proc.Thread.SetPC/etc.
This is true for the native backend but not for gdbserial. I had
anticipated this problem and introduced the Save/SavedRegisters
mechanism during the first implementation of fncall.go but that's
insufficient.
Instead:
1. clarify that the object returned by proc.Thread.Registers could
change when the CPU registers are modified.
2. add a Copy method to Registers that returns a copy of the registers
that are guaranteed not to change when the CPU registers change.
3. remove the Save/SavedRegisters mechanism.
This solution leaves us the option, in the future, to cache the output
of proc.(Thread).Registers, avoiding a system call every time it's
called.
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.
Evaluates var.method expressions into a variable holding the
corresponding method with the receiver variable as a child, in
preparation for extending CallFunction so that it can call methods.
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
If we send a process to foreground while the headless instance may get
a SIGTTOU/SIGTTIN, if not ignored this signal will stop the headless.
It's not clear why this only happens the second time we do this but
that's how it is.
Also removes the direct syscall to TIOCSPGRP and lets the go runtime do
it instead.
Fixes#1279
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.
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
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
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.
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.
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
Change memCache so that the preloaded memory is not read immediately
but only after the actual read to the preloaded range.
This allows us to request caching the entire stack frame every time we
create an eval scope and no unnecessary reads will be made even if the
user is just trying to evaluate a global variable.
Vet found the following errors:
pkg/proc/moduledata.go:152: namedata[1] (8 bits) too small for shift of 8
pkg/proc/moduledata.go:170: taglendata[0] (8 bits) too small for shift of 8
The fix is to convert before shifting.
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.
printcontext should use SelectedGoroutine instead of trusting that the
goroutine running on current thread matches the SelectedGoroutine.
When the user switches to a parked goroutine CurrentThread and
SelectedGoroutine will diverge.
Almost all calls to printcontext are safe, they happen after a continue
command returns when SelectedGoroutine and CurrentThread always agree,
but the calls in frameCommand and listCommand are wrong.
Additionally we should stop reporting an error when the debugger is
stopped on an unknown PC address.
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.
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.
* 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.
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.