Commit Graph

97 Commits

Author SHA1 Message Date
Derek Parker
1e2338d233
proc: allow evaluator to reference previous frames (#3534)
Fixes #3515
2023-10-24 18:57:39 +02:00
Alessandro Arzilli
d4104a6bcc
proc: remove expr evaluation goroutine from EvalExpressionWithCalls (#3532)
We have used a goroutine to keep track of some of the expression
evaluation status across target resumes during call injections.
Now that the expression interpreter has been rewritten to use a stack
machine we can move what little state is left into the stack machine
and get rid of the goroutine-and-channel mechanism.
2023-10-23 12:29:04 -07:00
Alessandro Arzilli
909add7894
proc: add min and max builtins (#3530)
Go 1.21 added two new builtins: min and max. Add them to the expression
evaluator.
2023-10-19 11:05:36 -07:00
Alessandro Arzilli
2c700230de
proc: use stack machine to evaluate expressions (#3508)
* proc: use stack machine to evaluate expressions

This commit splits expression evaluation into two parts. The first part (in
pkg/proc/evalop/evalcompile.go) "compiles" as ast.Expr into a list of
instructions (defined in pkg/proc/evalop/ops.go) for a stack machine
(defined by `proc.(*evalStack)`).
The second part is a stack machine (implemented by `proc.(*EvalScope).eval`
and `proc.(*EvalScope).evalOne`) that has two modes of operation: in the
main mode it executes inteructions from the list (by calling `evalOne`), in
the second mode it executes the call injection protocol by calling
`funcCallStep` repeatedly until it either the protocol finishes, needs more
input from the stack machine (to set call arguments) or fails.

This approach has several benefits:

- it is now possible to remove the goroutine we use to evaluate expression
  and the channel used to communicate with the Continue loop.
- every time we resume the target to execute the call injection protocol we
  need to update several local variables to match the changed state of the
  target, this is now done at the top level of the evaluation loop instead of
  being hidden inside a recurisive evaluator
- using runtime.Pin to pin addresses returned by an injected call would
  allow us to use a more natural evaluation order for function calls, which
  would solve some bugs #3310, allow users to inspect values returned by a
  call injection #1599 and allow implementing some other features #1465. Doing
  this with the recursive evaluator, while keeping backwards compatibility
  with versions of Go that do not have runtime.Pin is very hard. However after
  this change we can simply conditionally change how compileFunctionCall works
  and add some opcodes.

* review round 1

* review round 2
2023-10-17 11:21:59 -07:00
Alessandro Arzilli
e0b4bfbed3
Various fixes for go 1.22 (#3455)
* proc: correctly update local variables after continue

At various point during the execution of the call injection protocol
the process is resumed and the call injection goroutine could migrate
to a different thread, we must make sure to update our local variables
correctly after every point where the target program is resumed.

'fncall122debug_clean' on 'f469a0a5'.

* go.mod: update golang.org/x/tools

Go 1.22 broke golang.org/x/tools/packages

* cmd/dlv: disable TestStaticcheck with go1.22

Go 1.22 is not yet supported by staticcheck.
2023-09-19 09:34:34 -07:00
Alessandro Arzilli
0b35fe6d42
proc,service,terminal: add ways to list goroutines waiting on a channel (#3481)
Adds -chan option to the goroutines command to list only the goroutines
running on a specified channel.
Also when printing a variable if it is a channel also print the list of
goroutines that are waiting on it.
2023-08-23 13:02:34 -07:00
Alessandro Arzilli
789f8b4054
proc: remove unused functions (#3479) 2023-08-23 09:49:54 -07:00
Alessandro Arzilli
6a0423a1e9
proc: when stepping set condition on thread ID if there is no curg (#3475)
If there is no current goroutine when 'next', 'step' or 'stepout' are
used set a condition that the thread ID should stay the same instead.
This makes stepping work for multithreaded C programs or Go programs
that have threads started by cgo code.

Fixes #3262
2023-08-21 12:30:56 -07:00
gocurr
8023fa956e
all: use "len == 0" rather than "len <= 0" when checking empty slice/string (#3439) 2023-07-13 11:30:32 -07:00
Oleksandr Redko
2d3fd35e04
pkg,service: refactor to use %q instead of "%s" (#3430) 2023-07-05 08:49:08 -07:00
Alessandro Arzilli
d963eb1057
proc: read context from sigtrampgo, fixes TestCgoStacktrace2 on 1.21 (#3401)
* logflags,proc: flag to log stacktrace execution

Add a log flag to write logs about what the stacktracer does.

* proc: read context from sigtrampgo, fixes TestCgoStacktrace2 on 1.21

Changes stacktrace code to read the signal context from the arguments
of sigtrampgo.
Also changes the automatic fatalthrow breakpoint for go 1.21.
In combination these two changes fix TestCgoStacktrace2 on Go 1.21 on
various platforms.
2023-06-27 09:33:07 -07:00
Alessandro Arzilli
3507ff977a
proc: support multiple functions with the same name (#3297)
The compiler produces ABI compatibility wrappers for some functions.
We have changed the support for breakpoints to allow a single logical
breakpoint to correspond to multiple physical breakpoints, take
advantage of that to set breakpoints on both the ABI wrapper and the
real function.

Fixes #3296
2023-03-22 11:38:09 -07:00
Derek Parker
cac86b8791
dwarf/line: handle end_seq properly (#3277)
This patch changes how we handle end_seq in the debug_line state machine
program. Instead of always considering the state machine invalid at the
end_seq instead simply consider the *current* address invalid. This
solves a number of issues such as incorrect disassemble output for the
last few instructions in certain functions, and creating an eval scope
at an address within the last few instructions of certain functions. It
also handles the case where the end_seq address is the same as the start
address of the next adjacent function, which would previously confuse
Delve which is why we initially marked end_seq as invalid for the entire
state machine. This approach is more nuanced and still solves that
initial problem while fixing some problems introduced by that patch.
2023-02-20 10:36:09 +01:00
Derek Parker
a01fe73845
pkg/proc: do not check decl line for FunctionArguments (#3254)
Fixes a bug where we cannot get locals (including arguments and return
values) from a given scope because the line number state machine ends up
in an invalid state because of this parameter being set to false.
2023-01-24 15:56:05 +01:00
Andrei Matei
aee401b69a
pkg/proc: populate pointer values (#3229)
* proc: add a test for dangling unsafe pointers

This new tests checks the behavior when dereferencing dangling pointers.
The behavior does not fully make sense; the test checks the current
behavior for now, which will be improved in subsequent commits.

* proc: populate pointer values

This patch changes how Value and Unreadable are populated for pointer
Variables. Before this patch, variables of kind reflect.Ptr did not have
their Value field populated. This patch populates it in
Variable.loadValue(), which seems natural and consistent with other
types of variables. The Value is the address that the pointer points to.
The Unreadable field was populated inconsistently for pointer variables:
it was never populated for an outer pointer, but it could be populated
for an inner pointer in pointer-to-pointer types. Before this patch,
in pointer whose value could not be read was not easily distinguishable
from a pointer with a value that could be read, but that cannot be
dereferenced (i.e. a dangling pointer): neither of these would be marked
as Unreadable, and both would have a child marked as Unreadable. This
patch makes it so that a pointer variable whose pointer value cannot be
read is marked as Unreadable.

Using this new distinction, this patch fixes a bug around dereferencing
dangling pointers: before, attempting such a dereference produced a
"nil pointer dereference" error. This was bogus, since the pointer was
not nil. Now, we are more discerning and generate a different error.
2023-01-04 09:07:23 -08:00
Alessandro Arzilli
824e0a81e8
Two fixes to type cast evaluation (#3186)
* proc: allow casts form unsafe.Pointer to any pointer and vice versa

We've allowed doing this with uintptr but we should allow
unsafe.Pointer to be used like Go uses it.

* proc: fix type casts to ptr-to-ptr types

Fix type casts to **type.
2022-11-10 09:53:28 -08:00
Alessandro Arzilli
cba16f92e8
proc: fix index access to already-loaded string values (#3184)
Fixes #3176
2022-11-07 15:22:12 -08:00
Alessandro Arzilli
6bda7085c7
proc: allow type casts between compatible types (#3149)
Go allows some type casts when the underlying types are the same.
Conform to that behavior.

Fixes #3130
2022-09-29 10:08:19 -07:00
Alessandro Arzilli
5b9f65dac2
*: switch to int64 for goroutine IDs (#3110)
Go 1.20 switched to uint64 to represent goroutine IDs, we can't
actually follow suit because we have allowed clients to use -1 to refer
to the currently selected goroutine, however we should at least switch
to int64 and also update the rtype check to accept the 1.20 type.
2022-08-16 09:31:11 -07:00
Alessandro Arzilli
f82d225bdb
proc: fuse evalToplevelTypeCast and evalTypeCast (#3057)
We allowed integer and pointer type casts everywhere but type casts to
string, []byte and []rune only at toplevel.
Fuse evalToplevelTypeCast and evalTypeCast and allow both kinds
everywhere. There are multiple other ways to create variables than
don't reference user memory anyway (which wasn't the case back when
evalToplevelTypeCast was implemented).

Fixes #1423
2022-08-11 13:13:55 +02:00
Alessandro Arzilli
db3e5ef2cd
proc: map access with string literal key should always succeed (#3036)
When doing a map lookup with a string literal we should load as much of
the keys to at least match the length of the string literal, so that
the lookup doesn't fail with the "string too long" error.

Fixes #3034
2022-06-24 06:48:16 -07:00
Alessandro Arzilli
c412dcdc4f
*: run go1.19 'go fmt' on everything and fix problems (#3031)
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
2022-06-17 10:08:11 -07:00
Alessandro Arzilli
97405bbdd9
proc: allow low index == len in reslice (#2951)
Fixes #2950
2022-03-29 09:57:11 -07:00
Alessandro Arzilli
6ea826c363
proc: better error messages for ambiguous function calls/type casts (#2903)
Try to produce better error messages when we can't distinguish between
a function call and a type cast.

Fixes #2902
2022-02-22 09:55:59 -08:00
Alessandro Arzilli
01b01423ae
proc/*: minor miscellaneous code cleanups (#2790)
* made Pid a method of Target instead of a method of Process
* changed argument of NewTarget to ProcessInternal, since that's the
  interface that backends have to implement
* removed warnings about ProcessInternal since there is no way for
  users of pkg/proc to access those methods anyway
* made RecordingManipulation an optional interface for backends, Target
  supplies its own dummy implementation when the backend doesn't
* inlined small interfaces that only existed to be inlined in
  proc.Process anyway
* removed unused function findExecutable in the Windows and no-native
  darwin backends
* removed (*EvalScope).EvalVariable, an old synonym for EvalExpression
2021-11-26 08:06:23 -08:00
Alessandro Arzilli
c207db792a
proc,locspec: support setting breakpoints by func name on generic funcs (#2745)
* proc,locspec: support setting breakpoints by func name on generic funcs

Changes proc.Function to parse function names correctly when they
contain instantiation lists and locspec to match generic functions.

* vendor: update golang.org/x/tools

The old version of golang.org/x/tools is incompatible with the new
iexport format.
2021-10-30 11:52:26 -07:00
Alessandro Arzilli
bdcbcc6836
proc: return error when assigning between function variables (#2692)
Fixes #2691
2021-10-13 08:44:59 -07:00
aarzilli
18f2a4c46b proc,dwarf/godwarf: support parametric types with dictionaries
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'.
2021-10-02 15:44:30 +02:00
aarzilli
4a004e4bc1 proc: do not check return args when loading return vals of call injection
When the function we are calling is an autogenerated stub (because, for
example, we are calling it through a function pointer) the declaration
line of variables is meaningless and could cause us to discard valid
return arguments.
2021-10-02 15:44:30 +02:00
Alessandro Arzilli
29eae8f617
*: clean up staticcheck problems (#2723)
Fix problems that can be fixed, ignore the ones that don't make sense
2021-09-28 12:07:42 -07:00
Alessandro Arzilli
f3e76238e3
proc: move breakpoint condition evaluation out of backends (#2628)
* proc: move breakpoint condition evaluation out of backends

Moves breakpoint condition evaluation from the point where breakpoints
are set, inside ContinueOnce, to (*Target).Continue.

This accomplishes three things:

1. the breakpoint evaluation method needs not be exported anymore
2. breakpoint condition evaluation can be done with a full scope,
   containing a Target object, something that wasn't possible before
   because ContinueOnce doesn't have access to the Target object.
3. moves breakpoint condition evaluation out of the critical section
   where some of the threads of the target process might be still
   running.

* proc/native: handle process death during stop() on Windows

It is possible that the thread dies while we are inside the stop()
function. This results in an Access is denied error being returned by
SuspendThread being called on threads that no longer exist.

Delay the reporting the error from SuspendThread until the end of
stop() and only report it if the thread still exists at that point.

Fixes flakyness with TestIssue1101 that was exacerbated by moving
breakpoint condition evaluation outside of the backends.
2021-08-09 10:16:24 -07:00
Suzy Mueller
de117a2f4f
pkg/proc: fix bug where frame parameter is ignored if no goroutine (#2563)
ConvertEvalScope() attempts to find the scope for the specified
goroutine id and frame index. If the goroutine that is found is nil,
then it falls back to the threads stack trace to find the scope.
This fix makes sure that the frame id is taken into account for
thread strack traces as well.
2021-07-03 15:48:35 +02:00
Alessandro Arzilli
1b0c4310c4
proc: give unique addresses to registerized variables (#2527)
We told clients that further loading of variables can be done by
specifying a type cast using the address of a variable that we
returned.
This does not work for registerized variables (or, in general,
variables that have a complex location expression) because we don't
give them unique addresses and we throw away the compositeMemory object
we made to read them.

This commit changes proc so that:

1. variables with location expression divided in pieces do get a unique
   memory address
2. the compositeMemory object is saved somewhere
3. when an integer is cast back into a pointer type we look through our
   saved compositeMemory objects to see if there is one that covers the
   specified address and use it.

The unique memory addresses we generate have the MSB set to 1, as
specified by the Intel 86x64 manual addresses in this form are reserved
for kernel memory (which we can not read anyway) so we are guaranteed
to never generate a fake memory address that overlaps a real memory
address of the application.

The unfortunate side effect of this is that it will break clients that
do not deserialize the address to a 64bit integer. This practice is
contrary to how we defined our types and contrary to the specification
of the JSON format, as of json.org, however it is also fairly common,
due to javascript itself having only 53bit integers.

We could come up with a new mechanism but then even more old clients
would have to be changed.
2021-07-02 18:37:55 +02:00
Suzy Mueller
30b3cc2c6f
service/dap: implement array, slice, and map paging (#2512)
If the client supports paging, we allow them to fetch array and slice items in chunks that we assume will be of a reasonable size. For example, VS Code requests indexed variables in chunks of 100.

Fixes golang/vscode-go#1518
2021-06-10 09:34:20 -07:00
Alessandro Arzilli
32946b2d7c
proc: correctly truncate the result of binary ops on integers (#2463)
Truncates the result of binary operations on integers to the size of
the resulting type.
Also rewrites convertInt to not require allocations.

Fixes #2454
2021-05-17 10:31:05 -07:00
Alessandro Arzilli
c5d58f494a
proc: add way to use CPU registers in expressions (#2446)
Changes the expression evaluation code so that register names, when not
shadowed by local or global variables, will evaluate to the current
value of the corresponding CPU register.

This allows a greater flexibility with displaying CPU registers than is
possible with using the ListRegisters API call. Also it allows
debuggers users to view register values even if the frontend they are
using does not implement a register view.
2021-05-04 12:56:17 -07:00
Alessandro Arzilli
f19d5e5c13
proc: fix embedded field search (#2320)
Both structMember and findMethod implemented a depth-first search in
embedded fields but the Go specification requires a breadth-first
search. They also allowed promotion of fields in the concrete type of
embedded interfaces even though this is not allowed by Go.
Furthermore they both lacked protection from infinite recursion
when a type embeds itself and the user requests a non-existent field.

Fixes #2316
2021-01-29 09:25:31 -08:00
Alessandro Arzilli
3c86d68a99
proc: remove dead code (#2321) 2021-01-27 06:54:50 -08:00
Andrei Matei
60b5e9d4ba
dwarf/reader: minor comments around variable resolving (#2253)
Fix some stale comments and add some comments that I would have found
useful.
2020-12-08 11:46:40 -08:00
Alessandro Arzilli
0843376018
proc/*: remove proc.Thread.Blocked, refactor memory access (#2206)
On linux we can not read memory if the thread we use to do it is
occupied doing certain system calls. The exact conditions when this
happens have never been clear.

This problem was worked around by using the Blocked method which
recognized the most common circumstances where this would happen.

However this is a hack: Blocked returning true doesn't mean that the
problem will manifest and Blocked returning false doesn't necessarily
mean the problem will not manifest. A side effect of this is issue
#2151 where sometimes we can't read the memory of a thread and find its
associated goroutine.

This commit fixes this problem by always reading memory using a thread
we know to be good for this, specifically the one returned by
ContinueOnce. In particular the changes are as follows:

1. Remove (ProcessInternal).CurrentThread and
(ProcessInternal).SetCurrentThread, the "current thread" becomes a
field of Target, CurrentThread becomes a (*Target) method and
(*Target).SwitchThread basically just sets a field Target.

2. The backends keep track of their own internal idea of what the
current thread is, to use it to read memory, this is the thread they
return from ContinueOnce as trapthread

3. The current thread in the backend and the current thread in Target
only ever get synchronized in two places: when the backend creates a
Target object the currentThread field of Target is initialized with the
backend's current thread and when (*Target).Restart gets called (when a
recording is rewound the currentThread used by Target might not exist
anymore).

4. We remove the MemoryReadWriter interface embedded in Thread and
instead add a Memory method to Process that returns a MemoryReadWriter.
The  backends will return something here that will read memory using
the current thread saved by the backend.

5. The Thread.Blocked method is removed

One possible problem with this change is processes that have threads
with different memory maps. As far as I can determine this could happen
on old versions of linux but this option was removed in linux 2.5.

Fixes #2151
2020-11-09 11:28:40 -08:00
Alessandro Arzilli
7e00666b9f
proc: use argument position for addr only when injecting function calls (#2181)
* proc: use argument position for addr only when injecting function calls

We can not, in general, use the argument position to determine the
address of a formal parameter, it will not work in presence of
optimizations or inlining. In those cases formal arguments could be
stored in registers.

Fixes #2176

* Travis-CI: add ignorechecksum option to chocolatey command

Looks like a configuration problem on chocolatey's end.

Co-authored-by: a <a@kra>
2020-09-24 08:05:24 -07:00
Alessandro Arzilli
12009e9833
proc/*,service: replace uses of uintptr with uint64 (#2163)
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.
2020-09-09 10:36:15 -07:00
aarzilli
f90134eb4d proc: prevent internal breakpoint conditions from failing
An internal breakpoint condition shouldn't ever error:
* use a ThreadContext to evaluate conditions if a goroutine isn't
  available
* evaluate runtime.curg to a fake g variable containing only
  `goid == 0` when there is no current goroutine

Fixes #2113
2020-09-01 15:01:39 +02:00
Alessandro Arzilli
0fa2ac5a9c
proc: set OnlyAddr on variables created by typecast to pointer (#2142)
If OnlyAddr is not set pretty printing an interface will fail with an
index out of bounds error.
2020-08-24 13:37:06 -07:00
Alessandro Arzilli
f9c8f7f55b
Go 1.15 support (#2011)
* proc: start variable visibility one line after their decl line

In most cases variables shouldn't be visible on their declaration line
because they won't be initialized there.
Function arguments are treated as an exception.

This fix is only applied to programs compiled with Go 1.15 or later as
previous versions of Go did not report the correct declaration line for
variables captured by closures.

Fixes #1134

* proc: silence go vet error

* Makefile: enable PIE tests on windows/Go 1.15

* core: support core files for PIEs on windows

* goversion: add Go 1.15 to supported versions

* proc: fix function call injection for Go 1.15

Go 1.15 changed the call injection protocol so that the runtime will
execute the injected call on a different (new) goroutine.

This commit changes the function call support in delve to:

1. correctly track down the call injection state after the runtime
   switches to a different goroutine.
2. correctly perform the escapeCheck when stack values can come from
   multiple goroutine stacks.

* proc: miscellaneous fixed for call injection under macOS with go 1.15

- create copy of SP in debugCallAXCompleteCall case because the code
  used to assume that regs doesn't change
- fix automatic address calculation for function arguments when an
  argument has a spurious DW_OP_piece at entry
2020-07-28 09:19:51 -07:00
Mostafa Sedaghat Joo
3d896ece07
Update eval.go (#2110)
Check val != nil to ignore possible crash.
Related to #2101
2020-07-26 19:24:29 -07:00
chainhelen
cb39564502 pkg/proc: Fix crash when LocationExpr is nil
Add nil check for v.LocationExpr and keep unreadable error of var.

Fix #2049
2020-07-16 15:37:31 +02:00
Alessandro Arzilli
a72723433b
proc: better support for C pointers (#1997)
- treat C pointers as arrays
- print 'char *' variables as strings
2020-06-05 11:22:40 -07:00
aarzilli
c078223d56 proc: use cached packageVars in proc.(*EvalScope).PackageVariables 2020-05-01 11:01:35 -07:00
aarzilli
a61b6c0d7c proc: avoid constructing unnecessary strings when evaluating variables
Avoids constructing:

1. name of runtime.curg fields while executing parseG
2. the location expression while evaluating any variable.

Benchmark before:

BenchmarkConditionalBreakpoints-4   	       1	4953889884 ns/op

Benchmark after:

BenchmarkConditionalBreakpoints-4   	       1	4419775128 ns/op

Updates #1549
2020-03-31 10:29:26 -07:00