2017-04-21 06:55:53 +00:00
|
|
|
package core
|
2017-02-08 20:22:04 +00:00
|
|
|
|
|
|
|
import (
|
2017-04-03 09:17:54 +00:00
|
|
|
"errors"
|
2017-02-08 20:22:04 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2017-04-21 06:55:53 +00:00
|
|
|
|
2021-03-04 18:28:28 +00:00
|
|
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
2021-07-31 15:16:26 +00:00
|
|
|
"github.com/go-delve/delve/pkg/elfwriter"
|
2019-01-04 18:39:25 +00:00
|
|
|
"github.com/go-delve/delve/pkg/proc"
|
2021-07-31 15:16:26 +00:00
|
|
|
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
2017-02-08 20:22:04 +00:00
|
|
|
)
|
|
|
|
|
2021-01-29 21:39:33 +00:00
|
|
|
// ErrNoThreads core file did not contain any threads.
|
|
|
|
var ErrNoThreads = errors.New("no threads found in core file")
|
|
|
|
|
2020-03-26 12:05:09 +00:00
|
|
|
// A splicedMemory represents a memory space formed from multiple regions,
|
2017-02-08 20:22:04 +00:00
|
|
|
// each of which may override previously regions. For example, in the following
|
|
|
|
// core, the program text was loaded at 0x400000:
|
|
|
|
// Start End Page Offset
|
|
|
|
// 0x0000000000400000 0x000000000044f000 0x0000000000000000
|
|
|
|
// but then it's partially overwritten with an RW mapping whose data is stored
|
|
|
|
// in the core file:
|
|
|
|
// Type Offset VirtAddr PhysAddr
|
|
|
|
// FileSiz MemSiz Flags Align
|
|
|
|
// LOAD 0x0000000000004000 0x000000000049a000 0x0000000000000000
|
|
|
|
// 0x0000000000002000 0x0000000000002000 RW 1000
|
|
|
|
// This can be represented in a SplicedMemory by adding the original region,
|
|
|
|
// then putting the RW mapping on top of it.
|
2020-03-26 12:05:09 +00:00
|
|
|
type splicedMemory struct {
|
2017-02-08 20:22:04 +00:00
|
|
|
readers []readerEntry
|
|
|
|
}
|
|
|
|
|
|
|
|
type readerEntry struct {
|
2020-09-09 17:36:15 +00:00
|
|
|
offset uint64
|
|
|
|
length uint64
|
2017-04-21 06:55:53 +00:00
|
|
|
reader proc.MemoryReader
|
2017-02-08 20:22:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add adds a new region to the SplicedMemory, which may override existing regions.
|
2020-09-09 17:36:15 +00:00
|
|
|
func (r *splicedMemory) Add(reader proc.MemoryReader, off, length uint64) {
|
2017-02-08 20:22:04 +00:00
|
|
|
if length == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
end := off + length - 1
|
|
|
|
newReaders := make([]readerEntry, 0, len(r.readers))
|
|
|
|
add := func(e readerEntry) {
|
|
|
|
if e.length == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
newReaders = append(newReaders, e)
|
|
|
|
}
|
|
|
|
inserted := false
|
|
|
|
// Walk through the list of regions, fixing up any that overlap and inserting the new one.
|
|
|
|
for _, entry := range r.readers {
|
|
|
|
entryEnd := entry.offset + entry.length - 1
|
|
|
|
switch {
|
|
|
|
case entryEnd < off:
|
|
|
|
// Entry is completely before the new region.
|
|
|
|
add(entry)
|
|
|
|
case end < entry.offset:
|
|
|
|
// Entry is completely after the new region.
|
|
|
|
if !inserted {
|
|
|
|
add(readerEntry{off, length, reader})
|
|
|
|
inserted = true
|
|
|
|
}
|
|
|
|
add(entry)
|
|
|
|
case off <= entry.offset && entryEnd <= end:
|
|
|
|
// Entry is completely overwritten by the new region. Drop.
|
|
|
|
case entry.offset < off && entryEnd <= end:
|
|
|
|
// New region overwrites the end of the entry.
|
|
|
|
entry.length = off - entry.offset
|
|
|
|
add(entry)
|
|
|
|
case off <= entry.offset && end < entryEnd:
|
|
|
|
// New reader overwrites the beginning of the entry.
|
|
|
|
if !inserted {
|
|
|
|
add(readerEntry{off, length, reader})
|
|
|
|
inserted = true
|
|
|
|
}
|
|
|
|
overlap := entry.offset - off
|
|
|
|
entry.offset += overlap
|
|
|
|
entry.length -= overlap
|
|
|
|
add(entry)
|
|
|
|
case entry.offset < off && end < entryEnd:
|
|
|
|
// New region punches a hole in the entry. Split it in two and put the new region in the middle.
|
|
|
|
add(readerEntry{entry.offset, off - entry.offset, entry.reader})
|
|
|
|
add(readerEntry{off, length, reader})
|
|
|
|
add(readerEntry{end + 1, entryEnd - end, entry.reader})
|
|
|
|
inserted = true
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("Unhandled case: existing entry is %v len %v, new is %v len %v", entry.offset, entry.length, off, length))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !inserted {
|
|
|
|
newReaders = append(newReaders, readerEntry{off, length, reader})
|
|
|
|
}
|
|
|
|
r.readers = newReaders
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadMemory implements MemoryReader.ReadMemory.
|
2020-09-09 17:36:15 +00:00
|
|
|
func (r *splicedMemory) ReadMemory(buf []byte, addr uint64) (n int, err error) {
|
2017-02-08 20:22:04 +00:00
|
|
|
started := false
|
|
|
|
for _, entry := range r.readers {
|
2021-01-29 21:39:04 +00:00
|
|
|
if entry.offset+entry.length <= addr {
|
2017-02-08 20:22:04 +00:00
|
|
|
if !started {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return n, fmt.Errorf("hit unmapped area at %v after %v bytes", addr, n)
|
|
|
|
}
|
|
|
|
|
2019-08-13 18:13:56 +00:00
|
|
|
// The reading of the memory has been started after the first iteration
|
|
|
|
started = true
|
|
|
|
|
2017-02-08 20:22:04 +00:00
|
|
|
// Don't go past the region.
|
|
|
|
pb := buf
|
2020-09-09 17:36:15 +00:00
|
|
|
if addr+uint64(len(buf)) > entry.offset+entry.length {
|
2017-02-08 20:22:04 +00:00
|
|
|
pb = pb[:entry.offset+entry.length-addr]
|
|
|
|
}
|
|
|
|
pn, err := entry.reader.ReadMemory(pb, addr)
|
|
|
|
n += pn
|
2019-10-07 16:33:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return n, fmt.Errorf("error while reading spliced memory at %#x: %v", addr, err)
|
|
|
|
}
|
|
|
|
if pn != len(pb) {
|
|
|
|
return n, nil
|
2017-02-08 20:22:04 +00:00
|
|
|
}
|
|
|
|
buf = buf[pn:]
|
2020-09-09 17:36:15 +00:00
|
|
|
addr += uint64(pn)
|
2017-02-08 20:22:04 +00:00
|
|
|
if len(buf) == 0 {
|
|
|
|
// Done, don't bother scanning the rest.
|
|
|
|
return n, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if n == 0 {
|
|
|
|
return 0, fmt.Errorf("offset %v did not match any regions", addr)
|
|
|
|
}
|
|
|
|
return n, nil
|
|
|
|
}
|
|
|
|
|
2020-03-26 12:05:09 +00:00
|
|
|
// offsetReaderAt wraps a ReaderAt into a MemoryReader, subtracting a fixed
|
2017-02-08 20:22:04 +00:00
|
|
|
// offset from the address. This is useful to represent a mapping in an address
|
|
|
|
// space. For example, if program text is mapped in at 0x400000, an
|
|
|
|
// OffsetReaderAt with offset 0x400000 can be wrapped around file.Open(program)
|
|
|
|
// to return the results of a read in that part of the address space.
|
2020-03-26 12:05:09 +00:00
|
|
|
type offsetReaderAt struct {
|
2017-02-08 20:22:04 +00:00
|
|
|
reader io.ReaderAt
|
2020-09-09 17:36:15 +00:00
|
|
|
offset uint64
|
2017-02-08 20:22:04 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ReadMemory will read the memory at addr-offset.
|
2020-09-09 17:36:15 +00:00
|
|
|
func (r *offsetReaderAt) ReadMemory(buf []byte, addr uint64) (n int, err error) {
|
2017-02-08 20:22:04 +00:00
|
|
|
return r.reader.ReadAt(buf, int64(addr-r.offset))
|
|
|
|
}
|
2017-04-03 09:17:54 +00:00
|
|
|
|
2020-03-26 12:05:09 +00:00
|
|
|
// process represents a core file.
|
|
|
|
type process struct {
|
2018-10-18 07:13:11 +00:00
|
|
|
mem proc.MemoryReader
|
2020-03-26 12:05:09 +00:00
|
|
|
Threads map[int]*thread
|
2018-10-18 07:13:11 +00:00
|
|
|
pid int
|
|
|
|
|
|
|
|
entryPoint uint64
|
|
|
|
|
2020-11-09 19:28:40 +00:00
|
|
|
bi *proc.BinaryInfo
|
|
|
|
breakpoints proc.BreakpointMap
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2020-03-26 12:05:09 +00:00
|
|
|
// thread represents a thread in the core file being debugged.
|
|
|
|
type thread struct {
|
2018-10-18 07:13:11 +00:00
|
|
|
th osThread
|
2020-03-26 12:05:09 +00:00
|
|
|
p *process
|
2018-05-11 12:51:15 +00:00
|
|
|
common proc.CommonThread
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-10-18 07:13:11 +00:00
|
|
|
type osThread interface {
|
2020-05-13 18:56:50 +00:00
|
|
|
registers() (proc.Registers, error)
|
2018-10-18 07:13:11 +00:00
|
|
|
pid() int
|
|
|
|
}
|
|
|
|
|
2018-09-20 07:07:33 +00:00
|
|
|
var (
|
|
|
|
// ErrWriteCore is returned when attempting to write to the core
|
|
|
|
// process memory.
|
|
|
|
ErrWriteCore = errors.New("can not write to core process")
|
2018-08-31 18:08:18 +00:00
|
|
|
|
2018-09-20 07:07:33 +00:00
|
|
|
// ErrShortRead is returned on a short read.
|
|
|
|
ErrShortRead = errors.New("short read")
|
2018-08-31 18:08:18 +00:00
|
|
|
|
2018-09-20 07:07:33 +00:00
|
|
|
// ErrContinueCore is returned when trying to continue execution of a core process.
|
|
|
|
ErrContinueCore = errors.New("can not continue execution of core process")
|
|
|
|
|
|
|
|
// ErrChangeRegisterCore is returned when trying to change register values for core files.
|
|
|
|
ErrChangeRegisterCore = errors.New("can not change register values of core process")
|
|
|
|
)
|
2017-04-03 09:17:54 +00:00
|
|
|
|
2020-11-09 19:28:40 +00:00
|
|
|
type openFn func(string, string) (*process, proc.Thread, error)
|
2018-10-16 10:48:59 +00:00
|
|
|
|
2021-01-29 21:39:33 +00:00
|
|
|
var openFns = []openFn{readLinuxOrPlatformIndependentCore, readAMD64Minidump}
|
2018-10-16 10:48:59 +00:00
|
|
|
|
|
|
|
// ErrUnrecognizedFormat is returned when the core file is not recognized as
|
|
|
|
// any of the supported formats.
|
|
|
|
var ErrUnrecognizedFormat = errors.New("unrecognized core format")
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// OpenCore will open the core file and return a Process struct.
|
2018-11-07 22:21:35 +00:00
|
|
|
// If the DWARF information cannot be found in the binary, Delve will look
|
|
|
|
// for external debug files in the directories passed in.
|
2020-01-21 20:41:24 +00:00
|
|
|
func OpenCore(corePath, exePath string, debugInfoDirs []string) (*proc.Target, error) {
|
2020-03-26 12:05:09 +00:00
|
|
|
var p *process
|
2020-11-09 19:28:40 +00:00
|
|
|
var currentThread proc.Thread
|
2018-10-16 10:48:59 +00:00
|
|
|
var err error
|
|
|
|
for _, openFn := range openFns {
|
2020-11-09 19:28:40 +00:00
|
|
|
p, currentThread, err = openFn(corePath, exePath)
|
2018-10-16 10:48:59 +00:00
|
|
|
if err != ErrUnrecognizedFormat {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2017-04-03 09:17:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-01-29 21:39:33 +00:00
|
|
|
if currentThread == nil {
|
|
|
|
return nil, ErrNoThreads
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:06:23 +00:00
|
|
|
return proc.NewTarget(p, p.pid, currentThread, proc.NewTargetConfig{
|
2020-03-10 19:27:38 +00:00
|
|
|
Path: exePath,
|
|
|
|
DebugInfoDirs: debugInfoDirs,
|
|
|
|
DisableAsyncPreempt: false,
|
2021-01-29 21:39:33 +00:00
|
|
|
StopReason: proc.StopAttached,
|
|
|
|
CanDump: false})
|
2018-11-12 22:52:13 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// BinInfo will return the binary info.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) BinInfo() *proc.BinaryInfo {
|
2018-08-31 18:08:18 +00:00
|
|
|
return p.bi
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-11-12 22:52:13 +00:00
|
|
|
// EntryPoint will return the entry point address for this core file.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) EntryPoint() (uint64, error) {
|
2018-11-12 22:52:13 +00:00
|
|
|
return p.entryPoint, nil
|
|
|
|
}
|
|
|
|
|
2020-06-03 18:14:14 +00:00
|
|
|
// WriteBreakpoint is a noop function since you
|
2018-11-12 22:52:13 +00:00
|
|
|
// cannot write breakpoints into core files.
|
2021-01-27 15:27:54 +00:00
|
|
|
func (p *process) WriteBreakpoint(*proc.Breakpoint) error {
|
|
|
|
return errors.New("cannot write a breakpoint to a core file")
|
2018-11-12 22:52:13 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Recorded returns whether this is a live or recorded process. Always returns true for core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) Recorded() (bool, string) { return true, "" }
|
2018-08-31 18:08:18 +00:00
|
|
|
|
|
|
|
// Restart will only return an error for core files, as they are not executing.
|
2022-05-04 17:56:41 +00:00
|
|
|
func (p *process) Restart(*proc.ContinueOnceContext, string) (proc.Thread, error) {
|
|
|
|
return nil, ErrContinueCore
|
|
|
|
}
|
2018-08-31 18:08:18 +00:00
|
|
|
|
proc,terminal: Implement reverse step, next and stepout (#1785)
* 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
2020-03-11 22:40:41 +00:00
|
|
|
// ChangeDirection will only return an error as you cannot continue a core process.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) ChangeDirection(proc.Direction) error { return ErrContinueCore }
|
proc,terminal: Implement reverse step, next and stepout (#1785)
* 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
2020-03-11 22:40:41 +00:00
|
|
|
|
|
|
|
// GetDirection will always return forward.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) GetDirection() proc.Direction { return proc.Forward }
|
2018-08-31 18:08:18 +00:00
|
|
|
|
|
|
|
// When does not apply to core files, it is to support the Mozilla 'rr' backend.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) When() (string, error) { return "", nil }
|
2018-08-31 18:08:18 +00:00
|
|
|
|
|
|
|
// Checkpoint for core files returns an error, there is no execution of a core file.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) Checkpoint(string) (int, error) { return -1, ErrContinueCore }
|
2018-08-31 18:08:18 +00:00
|
|
|
|
|
|
|
// Checkpoints returns nil on core files, you cannot set checkpoints when debugging core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) Checkpoints() ([]proc.Checkpoint, error) { return nil, nil }
|
2017-05-05 22:17:52 +00:00
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ClearCheckpoint clears a checkpoint, but will only return an error for core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) ClearCheckpoint(int) error { return errors.New("checkpoint not found") }
|
2018-08-31 18:08:18 +00:00
|
|
|
|
2021-07-31 15:16:26 +00:00
|
|
|
func (p *process) SupportsBPF() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-08-24 12:53:27 +00:00
|
|
|
func (dbp *process) SetUProbe(fnName string, goidOffset int64, args []ebpf.UProbeArgMap) error {
|
2021-07-31 15:16:26 +00:00
|
|
|
panic("not implemented")
|
|
|
|
}
|
|
|
|
|
2021-10-14 18:06:14 +00:00
|
|
|
// StartCallInjection notifies the backend that we are about to inject a function call.
|
|
|
|
func (p *process) StartCallInjection() (func(), error) { return func() {}, nil }
|
|
|
|
|
2021-10-25 19:37:36 +00:00
|
|
|
func (dbp *process) EnableURetProbes() error {
|
|
|
|
panic("not implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (dbp *process) DisableURetProbes() error {
|
|
|
|
panic("not implemented")
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ReadMemory will return memory from the core file at the specified location and put the
|
|
|
|
// read memory into `data`, returning the length read, and returning an error if
|
|
|
|
// the length read is shorter than the length of the `data` buffer.
|
2020-11-09 19:28:40 +00:00
|
|
|
func (p *process) ReadMemory(data []byte, addr uint64) (n int, err error) {
|
|
|
|
n, err = p.mem.ReadMemory(data, addr)
|
2017-04-03 09:17:54 +00:00
|
|
|
if err == nil && n != len(data) {
|
|
|
|
err = ErrShortRead
|
|
|
|
}
|
2017-04-18 14:24:45 +00:00
|
|
|
return n, err
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// WriteMemory will only return an error for core files, you cannot write
|
|
|
|
// to the memory of a core process.
|
2020-11-09 19:28:40 +00:00
|
|
|
func (p *process) WriteMemory(addr uint64, data []byte) (int, error) {
|
2017-04-03 09:17:54 +00:00
|
|
|
return 0, ErrWriteCore
|
|
|
|
}
|
|
|
|
|
2020-11-09 19:28:40 +00:00
|
|
|
// ProcessMemory returns the memory of this thread's process.
|
|
|
|
func (t *thread) ProcessMemory() proc.MemoryReadWriter {
|
|
|
|
return t.p
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Location returns the location of this thread based on
|
|
|
|
// the value of the instruction pointer register.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) Location() (*proc.Location, error) {
|
2020-05-13 18:56:50 +00:00
|
|
|
regs, err := t.th.registers()
|
2018-10-18 07:13:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pc := regs.PC()
|
|
|
|
f, l, fn := t.p.bi.PCToLine(pc)
|
|
|
|
return &proc.Location{PC: pc, File: f, Line: l, Fn: fn}, nil
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Breakpoint returns the current breakpoint this thread is stopped at.
|
|
|
|
// For core files this always returns an empty BreakpointState struct, as
|
|
|
|
// there are no breakpoints when debugging core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) Breakpoint() *proc.BreakpointState {
|
2020-01-21 20:41:24 +00:00
|
|
|
return &proc.BreakpointState{}
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ThreadID returns the ID for this thread.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) ThreadID() int {
|
2018-10-18 07:13:11 +00:00
|
|
|
return int(t.th.pid())
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Registers returns the current value of the registers for this thread.
|
2020-05-13 18:56:50 +00:00
|
|
|
func (t *thread) Registers() (proc.Registers, error) {
|
|
|
|
return t.th.registers()
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// RestoreRegisters will only return an error for core files,
|
|
|
|
// you cannot change register values for core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) RestoreRegisters(proc.Registers) error {
|
2018-09-20 07:07:33 +00:00
|
|
|
return ErrChangeRegisterCore
|
2018-05-04 17:31:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// BinInfo returns information about the binary.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) BinInfo() *proc.BinaryInfo {
|
2018-08-31 18:08:18 +00:00
|
|
|
return t.p.bi
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// StepInstruction will only return an error for core files,
|
|
|
|
// you cannot execute a core file.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) StepInstruction() error {
|
2017-04-03 09:17:54 +00:00
|
|
|
return ErrContinueCore
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// SetCurrentBreakpoint will always just return nil
|
|
|
|
// for core files, as there are no breakpoints in core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) SetCurrentBreakpoint(adjustPC bool) error {
|
2017-05-16 18:23:33 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-02-22 17:57:37 +00:00
|
|
|
// SoftExc returns true if this thread received a software exception during the last resume.
|
|
|
|
func (t *thread) SoftExc() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Common returns a struct containing common information
|
|
|
|
// across thread implementations.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) Common() *proc.CommonThread {
|
2018-05-11 12:51:15 +00:00
|
|
|
return &t.common
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// SetPC will always return an error, you cannot
|
|
|
|
// change register values when debugging core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) SetPC(uint64) error {
|
2018-09-20 07:07:33 +00:00
|
|
|
return ErrChangeRegisterCore
|
2018-05-04 17:31:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// SetSP will always return an error, you cannot
|
|
|
|
// change register values when debugging core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) SetSP(uint64) error {
|
2018-09-20 07:07:33 +00:00
|
|
|
return ErrChangeRegisterCore
|
2018-05-04 17:31:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// SetDX will always return an error, you cannot
|
|
|
|
// change register values when debugging core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (t *thread) SetDX(uint64) error {
|
2018-09-20 07:07:33 +00:00
|
|
|
return ErrChangeRegisterCore
|
2018-07-31 16:32:30 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 18:28:28 +00:00
|
|
|
// ChangeRegs will always return an error, you cannot
|
|
|
|
// change register values when debugging core files.
|
|
|
|
func (t *thread) SetReg(regNum uint64, reg *op.DwarfRegister) error {
|
|
|
|
return ErrChangeRegisterCore
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Breakpoints will return all breakpoints for the process.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) Breakpoints() *proc.BreakpointMap {
|
2017-09-24 13:00:55 +00:00
|
|
|
return &p.breakpoints
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2020-06-03 18:14:14 +00:00
|
|
|
// EraseBreakpoint will always return an error as you cannot set or clear
|
2018-08-31 18:08:18 +00:00
|
|
|
// breakpoints on core files.
|
2020-06-03 18:14:14 +00:00
|
|
|
func (p *process) EraseBreakpoint(bp *proc.Breakpoint) error {
|
|
|
|
return proc.NoBreakpointError{Addr: bp.Addr}
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ClearInternalBreakpoints will always return nil and have no
|
|
|
|
// effect since you cannot set breakpoints on core files.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) ClearInternalBreakpoints() error {
|
2017-04-03 09:17:54 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ContinueOnce will always return an error because you
|
|
|
|
// cannot control execution of a core file.
|
2022-03-21 19:42:37 +00:00
|
|
|
func (p *process) ContinueOnce(cctx *proc.ContinueOnceContext) (proc.Thread, proc.StopReason, error) {
|
2020-03-10 19:27:38 +00:00
|
|
|
return nil, proc.StopUnknown, ErrContinueCore
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// StepInstruction will always return an error
|
|
|
|
// as you cannot control execution of a core file.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) StepInstruction() error {
|
2017-04-03 09:17:54 +00:00
|
|
|
return ErrContinueCore
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// RequestManualStop will return nil and have no effect
|
|
|
|
// as you cannot control execution of a core file.
|
2022-03-21 19:42:37 +00:00
|
|
|
func (p *process) RequestManualStop(cctx *proc.ContinueOnceContext) error {
|
2017-04-03 09:17:54 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// CheckAndClearManualStopRequest will always return false and
|
|
|
|
// have no effect since there are no manual stop requests as
|
|
|
|
// there is no controlling execution of a core file.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) CheckAndClearManualStopRequest() bool {
|
2017-07-07 23:29:37 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-11-09 19:28:40 +00:00
|
|
|
// Memory returns the process memory.
|
|
|
|
func (p *process) Memory() proc.MemoryReadWriter {
|
|
|
|
return p
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Detach will always return nil and have no
|
|
|
|
// effect as you cannot detach from a core file
|
|
|
|
// and have it continue execution or exit.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) Detach(bool) error {
|
2017-04-03 09:17:54 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Valid returns whether the process is active. Always returns true
|
|
|
|
// for core files as it cannot exit or be otherwise detached from.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) Valid() (bool, error) {
|
2018-06-21 11:07:37 +00:00
|
|
|
return true, nil
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ResumeNotify is a no-op on core files as we cannot
|
|
|
|
// control execution.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) ResumeNotify(chan<- struct{}) {
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ThreadList will return a list of all threads currently in the process.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) ThreadList() []proc.Thread {
|
2018-10-18 07:13:11 +00:00
|
|
|
r := make([]proc.Thread, 0, len(p.Threads))
|
|
|
|
for _, v := range p.Threads {
|
2017-07-20 19:04:00 +00:00
|
|
|
r = append(r, v)
|
2017-04-03 09:17:54 +00:00
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// FindThread will return the thread with the corresponding thread ID.
|
2020-03-26 12:05:09 +00:00
|
|
|
func (p *process) FindThread(threadID int) (proc.Thread, bool) {
|
2018-10-18 07:13:11 +00:00
|
|
|
t, ok := p.Threads[threadID]
|
2017-07-20 19:04:00 +00:00
|
|
|
return t, ok
|
|
|
|
}
|
2021-01-29 21:39:33 +00:00
|
|
|
|
|
|
|
func (p *process) MemoryMap() ([]proc.MemoryMapEntry, error) {
|
|
|
|
return nil, proc.ErrMemoryMapNotSupported
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *process) DumpProcessNotes(notes []elfwriter.Note, threadDone func()) (threadsDone bool, out []elfwriter.Note, err error) {
|
|
|
|
return false, notes, nil
|
|
|
|
}
|
2021-07-31 15:16:26 +00:00
|
|
|
|
|
|
|
func (dbp *process) GetBufferedTracepoints() []ebpf.RawUProbeParams {
|
|
|
|
return nil
|
|
|
|
}
|