When cgo is used the address of the g struct is saved on the special
register TPIDR_EL0. Because executing C code could overwrite the
contents of R28 that normally contains the address of g we should read
it from TPIDR_EL0 instead when runtime.iscgo is set.
* proc/core: off-by-one error reading ELF core files
core.(*splicedMemory).ReadMemory checked the entry interval
erroneously when dealing with contiguous entries.
* terminal,service,proc/*: adds dump command (gcore equivalent)
Adds the `dump` command that creates a core file from the target process.
Backends will need to implement a new, optional, method `MemoryMap` that
returns a list of mapped memory regions.
Additionally the method `DumpProcessNotes` can be implemented to write out
to the core file notes describing the target process and its threads. If
DumpProcessNotes is not implemented `proc.Dump` will write a description of
the process and its threads in a OS/arch-independent format (that only Delve
understands).
Currently only linux/amd64 implements `DumpProcessNotes`.
Core files are only written in ELF, there is no minidump or macho-o writers.
# Conflicts:
# pkg/proc/proc_test.go
If a thread exits while we are looking at it just treat it as if the
status had reported it as exited instead of doing something special.
Fixes flakiness in TestIssue387.
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
TestStepConcurrentDirect will occasionally fail (7% of the time on my
setup) by either causing the target processs to execute an invalid
instruction or (more infrequently) by switching to the wrong thread.
Both of those are caused by receiving SIGTRAPs for threads hitting a
breakpoint after it has been removed (the thread hits the breakpoint,
we stop everything and remove the breakpoint and only after we receive
the signal).
Change native.(*nativeProcess).stop to handle SIGTRAPs that can't be
attributed to a breakpoint, a hardcoded breakpoint in the program's
text, or manual stops (and therefore are likely caused by phantom
breakpoint hits).
Co-authored-by: a <a@kra>
If the process receives a signal (or sends a singal to itself) and then
dies before we can route the signal back to it we still need to
retrieve its exit status.
Fixes a rare failure of TestIssue1101 in proc_test.go
Co-authored-by: a <a@kra>
* Revert "proc: Find executable should follow symbol links."
This reverts commit 3e04ad0fada0c3ab57caf58bc024e4c0f9a3e01a.
* proc: resolve symlinks when searching for split debug_info if path is /proc/pid/exe
Fixes#2168
Since proc is supposed to work independently from the target
architecture it shouldn't use architecture-dependent types, like
uintptr. For example when reading a 64bit core file on a 32bit
architecture, uintptr will be 32bit but the addresses proc needs to
represent will be 64bit.
Adds features to support default file descriptor redirects for the
target process:
1. A new command line flag '--redirect' and '-r' are added to specify
file redirects for the target process
2. New syntax is added to the 'restart' command to specify file
redirects.
3. Interactive instances will check if stdin/stdout and stderr are
terminals and print a helpful error message if they aren't.
Changes implementations of proc.Registers interface and the
op.DwarfRegisters struct so that floating point registers can be loaded
only when they are needed.
Removes the floatingPoint parameter from proc.Thread.Registers.
This accomplishes three things:
1. it simplifies the proc.Thread.Registers interface
2. it makes it impossible to accidentally create a broken set of saved
registers or of op.DwarfRegisters by accidentally calling
Registers(false)
3. it improves general performance of Delve by avoiding to load
floating point registers as much as possible
Floating point registers are loaded under two circumstances:
1. When the Slice method is called with floatingPoint == true
2. When the Copy method is called
Benchmark before:
BenchmarkConditionalBreakpoints-4 1 4327350142 ns/op
Benchmark after:
BenchmarkConditionalBreakpoints-4 1 3852642917 ns/op
Updates #1549
On linux platform, we simply treated `/proc/$pid/exe` as the
executable of targeting process when doing `dlv attach`. The
`/proc/$pid/exe` is a symbol link of the real executable file.
Delve couldn't find the corrsponding external debug file based on the
symbol link:
```
could not attach to pid $pid: could not open debug info
```
The fix is to evaluate the symbol links to the actual executable path.
The process could quit while we are inside stop, we should report the
error otherwise the following code will try to send on the closed
ptrace channel.
Fixes a sporadic error in TestIssue1101.
This flag allows users on UNIX systems to set the tty for the program
being debugged by Delve. This is useful for debugging command line
applications which need access to their own TTY, and also for
controlling the output of the debugged programs so that IDEs may open a
dedicated terminal to show the output for the process.
* *: Fix go vet struct complaints
* *: Fix struct vet issue on linux
* *: Ignore proc/native in go vet check
We have to do some unsafe pointer manipulation that will never make go
vet happy within the proc/native package. Ignore it for runs of go vet.
* proc: move defer breakpoint code into a function
Moves the code that sets a breakpoint on the first deferred function,
used by both next and StepOut, to its function.
* proc: implement reverse step/next/stepout
When the direction of execution is reversed (on a recording) Step, Next and
StepOut will behave similarly to their forward version. However there are
some subtle interactions between their behavior, prologue skipping, deferred
calls and normal calls. Specifically:
- when stepping backwards we need to set a breakpoint on the first
instruction after each CALL instruction, once this breakpoint is reached we
need to execute a single StepInstruction operation to reverse step into the
CALL.
- to insure that the prologue is skipped reverse next needs to check if it
is on the first instruction after the prologue, and if it is behave like
reverse stepout.
- there is no reason to set breakpoints on deferred calls when reverse
nexting or reverse stepping out, they will never be hit.
- reverse step out should generally place its breakpoint on the CALL
instruction that created the current stack frame (which will be the CALL
instruction immediately preceding the instruction at the return address).
- reverse step out needs to treat panic calls and deferreturn calls
specially.
* service,terminal: implement reverse step, next, stepout
* proc,proc/*: move SelectedGoroutine to proc.Target, remove PostInitializationSetup
moves SelectedGoroutine, SwitchThread and SwitchGoroutine to
proc.Target, merges PostInitializationSetup with NewTarget.
* proc,proc/*: add StopReason field to Target
Adds a StopReason field to the Target object describing why the target
process is currently stopped. This will be useful for the DAP server
(which needs to report this reason in one of its requests) as well as
making pull request #1785 (reverse step) conformant to the new
architecture.
* proc: collect NewTarget arguments into a struct
Implement debugging function for 386 on linux with reference to AMD64.
There are a few remaining problems that need to be solved in another time.
1. The stacktrace of cgo are not exactly as expected.
2. Not implement `core` for now.
3. Not implement `call` for now. Can't not find `runtime·debugCallV1` or
similar function in $GOROOT/src/runtime/asm_386.s.
Update #20
* proc/native/linux: only set breakpoints on threads that receive SIGTRAP
* proc/native/linux: do not call (*Thread).Stopped inside (*Process).stop
(*Thread).Stopped is slow because it needs to open, read and parse a
file in /proc, we don't actually need to do that, we can just rely on
the value of Thread.os.running.
Benchmark before:
BenchmarkConditionalBreakpoints-4 1 12476166303 ns/op
Benchmark after:
BenchmarkConditionalBreakpoints-4 1 10403533675 ns/op
Conditional breakpoint evaluation: 1.24ms -> 1ms
Updates #1549
This change adds `ProcessVmRead` and `ProcessVmWrite` wrappers around
the syscalls `process_vm_readv` and `process_vm_writev`, available since
Linux 3.2. These follow the same permission model as `ptrace`, but they
don't actually require being attached, which means they can be called
directly from any thread in the debugger. They also use `iovec` to write
entire blocks at once, rather than having to peek/poke each `uintptr`.
These wrappers are used in `Thread.ReadMemory` and `WriteMemory`, still
falling back to `ptrace` if that fails for any reason. Notably,
`process_vm_writev` respects memory protection, so it can't modify
read-only memory like `ptrace`. This frequently occurs when writing
breakpoints in read-only `.text`, so to avoid a lot of wasted `EFAULT`
calls, we only try `process_vm_writev` for larger writes.
As we rearrange the code and the Go compiler changes the error message
returned by the compiler on unsupported architectures will change too,
making it un-googlable. Since the error message tends to be rather
obscure too this regularly confuses newbies.
This is an effort to make the error message for unsupported GOOS/GOARCH
combinations the same across all unsupported combinations and to make
it more user friendly.
Directories containing Go source code are supposed to contain a single
package. This property happens to be checked by cmd/go itself so it
will happen even before the syntax is fully checked and therefore has a
high probability of being the first (and only) error message being
print.
Here we take advantage of this by adding to the pkg/proc/native
directory a file with a bad package line that only gets compiled in on
unsupported GOOS/GOARCH combinations.
At present the error message for compiling Delve on unsupported systems
will be:
service/debugger/debugger.go:21:2: found packages native (proc.go) and your_operating_system_and_architecture_combination_is_not_supported_by_delve (support_sentinel.go) in $PATH_TO_DELVE/pkg/proc/native
A significant amount of time is spent generating the string
representation for the proc.Registers object of each thread, since this
field is rarely used (only when the Registers API is called) it should
be generated on demand.
Also by changing the internal representation of proc.Register to be
closer to that of op.DwarfRegister it will help us implement #1838
(when Delve will need to be able to display the registers of an
internal frame, which we currently represent using op.DwarfRegister
objects).
Benchmark before:
BenchmarkConditionalBreakpoints-4 1 22292554301 ns/op
Benchmark after:
BenchmarkConditionalBreakpoints-4 1 17326345671 ns/op
Reduces conditional breakpoint latency from 2.2ms to 1.7ms.
Updates #1549, #1838
* tests: misc test fixes for go1.14
- math.go is now ambiguous due to changes to the go runtime so specify
that we mean our own math.go in _fixtures
- go list -m requires vendor-mode to be disabled so pass '-mod=' to it
in case user has GOFLAGS=-mod=vendor
- update version of go/packages, required to work with go 1.14 (and
executed go mod vendor)
- Increased goroutine migration in one development version of Go 1.14
revealed a problem with TestCheckpoints in command_test.go and
rr_test.go. The tests were always wrong because Restart(checkpoint)
doesn't change the current thread but we can't assume that when the
checkpoint was taken the current goroutine was running on the same
thread.
* goversion: update maximum supported version
* Makefile: disable testing lldb-server backend on linux with Go 1.14
There seems to be some incompatibility with lldb-server version 6.0.0
on linux and Go 1.14.
* proc/gdbserial: better handling of signals
- if multiple signals are received simultaneously propagate all of them to the
target threads instead of only one.
- debugserver will drop an interrupt request if a target thread simultaneously
receives a signal, handle this situation.
* dwarf/line: normalize backslashes for windows executables
Starting with Go 1.14 the compiler sometimes emits backslashes as well
as forward slashes in debug_line, normalize everything to / for
conformity with the behavior of previous versions.
* proc/native: partial support for Windows async preempt mechanism
See https://github.com/golang/go/issues/36494 for a description of why
full support for 1.14 under windows is problematic.
* proc/native: disable Go 1.14 async preemption on Windows
See https://github.com/golang/go/issues/36494
* pkg/proc: Introduce Target
* pkg/proc: Remove Common.fncallEnabled
Realistically we only block it on recorded backends.
* pkg/proc: Move fncallForG to Target
* pkg/proc: Remove CommonProcess
Remove final bit of functionality stored in CommonProcess and move it to
*Target.
* pkg/proc: Add SupportsFunctionCall to Target
Specifically, make sure that both DebugActiveProcess and
WaitForDebugEvent Windows APIs are executed on the same thread.
Otherwise WaitForDebugEvent fails with ERROR_INVALID_HANDLE as per its
documentation
https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-waitfordebugevent
'... Only the thread that created the process being debugged can call
WaitForDebugEvent. ...'
Fixes#1825
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).
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.