The `scope.Locals` function did not have any guard checks against missing DWARF information.
This patch adds a check, which likely will need to be added to other functions as well.
* 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
* enable func call injection on delve for ppc64le
* Function call injection on Delve/ppc64le, modified DWARF encoding and decoding for floating point registers to make floatsum test work
* Function call injection on Delve/ppc64le cleanup
* skip PIE tests for function call injection on other packages
* Address review comments
* accounted for additional skipped PIE tests for function call injection
* Code cleanup and undoing revert of previous commit
* Enable function call injection only on 1.22 and above and some cleanup
* additional cleanup, go fmt run
* Debug function call tests fail on ppc64le/PIE mode adjusted the backup_test_health.md file accordingly
Implementing the `DW_CFA_remember_state` and `DW_CFA_restore_state`
according to the DWARF specification requires us to create a stack that
can store an arbitrary number of elements, that is, there could be
multiple "pushes" before "popping" them.
From the 5th revision of the spec [0]:
> 6.4.2.4 Row State Instructions
> DW_CFA_remember_state
> The DW_CFA_remember_state instruction takes no operands. The required
> action is to push the set of rules for every register onto an implicit stack.
> DW_CFA_restore_state
> DW_CFA_restore_state
> The DW_CFA_restore_state instruction takes no operands. The required action
> is to pop the set of rules off the implicit stack and place them in the
> current row.
- [0]: https://dwarfstd.org/doc/DWARF5.pdf
Signed-off-by: Francisco Javier Honduvilla Coto <javierhonduco@gmail.com>
dwarf/op gained the ability to execute DW_OP_deref opcodes a while ago
but because we didn't save the readMemory function in the context
structure it never worked.
Change generated comment header for opcodes.go to match Go regexp:
```
^// Code generated .* DO NOT EDIT\.$
```
Fix panic in gen-opcodes.go if no args provided.
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.
Previously it was only possible to extract a value of type `any` using
an attribute name. This poses challenges when fields are allowed to have
different classes, and it is ambiguous how to handle them.
As they are unused and wrong. pkg/dwarf/op/opcodes.go has the right
opcodes and that's what's used
Signed-off-by: Francisco Javier Honduvilla Coto <javierhonduco@gmail.com>
Signed-off-by: Francisco Javier Honduvilla Coto <javierhonduco@gmail.com>
As we parse this informatin in the loop we must take care to assemble
things correctly. In this situation when we encounter a file name,
the dir index is -1, then subsequently we get the correct dir index
for that file and can put them together. Previously we were adding the
file and then the directory location to the file list instead of
correctly concatenating them, resulting in an incorrect file list making
indexing into the list return incorrect results later on.
We don't do anything with the personality function so there is no point
in complaining that we don't fully support the pointer encoding flags
used to describe it.
This matches the current level of support of pointer encodings in gdb
(they are discarded when reading the personality function and not
supported for FDEs because gcc doesn't generate them).
Fixes#3015
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'.
With generics a single function can have multiple concrete
instantiations, the old version of FindFileLocation supported at most
one concrete instantiation per function and any number of inlined
calls, this supports any number of inlined calls and concrete
functions.
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.
Right now, if (*compositeMemory).WriteMemory needs to write a value to
a register that's smaller than the full size of the register (say, a
uint32 being passed as an argument), then (*AMD64Registers).SetReg can
later fail a sanity check that ensures the passed DwarfRegister is a
full size register.
Fix this by reading the old value of the register and overwriting just
the relevant parts with the new register. For the purposes of an
argument, it would probably be fine to just pad with zeroes, but merging
with the existing value is what gdb does.
Fixes#2698
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>
Adds DWARF register number and support for AVX-512 registers.
Changes proc/gdbserial so that the 'g' and 'G' commands are never used
with debugserver since they seem to corrupt the thread state when used
on AVX-512 capable hardware.
Also changes TestClientServer_FpRegisters to be simpler and more
resilient to changes to the Go runtime.
Fixes#2479
The godwarf package provides two ways to turn a dwarf.Entry into a
godwarf.Tree: LoadTree and EntryToTree. The former doesn't handle
children - it doesn't advance a Reader past them (in fact, it doesn't
even know about a Reader). EntryToTree is only used for variables and
formal param DIEs, which don't have children, and it would very likely
be incorrect to use it for DIEs with children. This patch makes the
function panic if the entry can have children.
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