mirror of
https://github.com/go-delve/delve.git
synced 2025-11-03 05:47:34 +08:00
Rename: s/ThreadContext/Thread/
This commit is contained in:
@ -28,7 +28,7 @@ func (bp *Breakpoint) String() string {
|
||||
|
||||
// Clear this breakpoint appropriately depending on whether it is a
|
||||
// hardware or software breakpoint.
|
||||
func (bp *Breakpoint) Clear(thread *ThreadContext) (*Breakpoint, error) {
|
||||
func (bp *Breakpoint) Clear(thread *Thread) (*Breakpoint, error) {
|
||||
if bp.hardware {
|
||||
if err := clearHardwareBreakpoint(bp.reg, thread.Id); err != nil {
|
||||
return nil, err
|
||||
|
||||
10
proc/proc.go
10
proc/proc.go
@ -29,11 +29,11 @@ type DebuggedProcess struct {
|
||||
// Software breakpoint table. Hardware breakpoints are stored in proc/arch.go, as they are architecture dependant.
|
||||
Breakpoints map[uint64]*Breakpoint
|
||||
|
||||
// List of threads mapped as such: pid -> *ThreadContext
|
||||
Threads map[int]*ThreadContext
|
||||
// List of threads mapped as such: pid -> *Thread
|
||||
Threads map[int]*Thread
|
||||
|
||||
// Active thread. This is the default thread used for setting breakpoints, evaluating variables, etc..
|
||||
CurrentThread *ThreadContext
|
||||
CurrentThread *Thread
|
||||
|
||||
dwarf *dwarf.Data
|
||||
goSymTable *gosym.Table
|
||||
@ -74,7 +74,7 @@ func (pe ProcessExitedError) Error() string {
|
||||
func Attach(pid int) (*DebuggedProcess, error) {
|
||||
dbp := &DebuggedProcess{
|
||||
Pid: pid,
|
||||
Threads: make(map[int]*ThreadContext),
|
||||
Threads: make(map[int]*Thread),
|
||||
Breakpoints: make(map[uint64]*Breakpoint),
|
||||
os: new(OSProcessDetails),
|
||||
ast: source.New(),
|
||||
@ -565,7 +565,7 @@ func (dbp *DebuggedProcess) clearTempBreakpoints() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*ThreadContext, error) {
|
||||
func (dbp *DebuggedProcess) handleBreakpointOnThread(id int) (*Thread, error) {
|
||||
thread, ok := dbp.Threads[id]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("could not find thread for %d", id)
|
||||
|
||||
@ -45,7 +45,7 @@ func Launch(cmd []string) (*DebuggedProcess, error) {
|
||||
argv = &argvSlice[0]
|
||||
|
||||
dbp := &DebuggedProcess{
|
||||
Threads: make(map[int]*ThreadContext),
|
||||
Threads: make(map[int]*Thread),
|
||||
Breakpoints: make(map[uint64]*Breakpoint),
|
||||
firstStart: true,
|
||||
os: new(OSProcessDetails),
|
||||
@ -116,11 +116,11 @@ func (dbp *DebuggedProcess) updateThreadList() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) addThread(port int, attach bool) (*ThreadContext, error) {
|
||||
func (dbp *DebuggedProcess) addThread(port int, attach bool) (*Thread, error) {
|
||||
if thread, ok := dbp.Threads[port]; ok {
|
||||
return thread, nil
|
||||
}
|
||||
thread := &ThreadContext{
|
||||
thread := &Thread{
|
||||
Id: port,
|
||||
dbp: dbp,
|
||||
os: new(OSSpecificDetails),
|
||||
@ -216,9 +216,9 @@ func (dbp *DebuggedProcess) findExecutable(path string) (*macho.File, error) {
|
||||
return exe, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) trapWait(pid int) (*ThreadContext, error) {
|
||||
func (dbp *DebuggedProcess) trapWait(pid int) (*Thread, error) {
|
||||
var (
|
||||
th *ThreadContext
|
||||
th *Thread
|
||||
err error
|
||||
)
|
||||
for {
|
||||
|
||||
@ -46,7 +46,7 @@ func Launch(cmd []string) (*DebuggedProcess, error) {
|
||||
}
|
||||
dbp := &DebuggedProcess{
|
||||
Pid: proc.Process.Pid,
|
||||
Threads: make(map[int]*ThreadContext),
|
||||
Threads: make(map[int]*Thread),
|
||||
Breakpoints: make(map[uint64]*Breakpoint),
|
||||
os: new(OSProcessDetails),
|
||||
ast: source.New(),
|
||||
@ -61,7 +61,7 @@ func (dbp *DebuggedProcess) requestManualStop() (err error) {
|
||||
|
||||
// Attach to a newly created thread, and store that thread in our list of
|
||||
// known threads.
|
||||
func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*ThreadContext, error) {
|
||||
func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*Thread, error) {
|
||||
if thread, ok := dbp.Threads[tid]; ok {
|
||||
return thread, nil
|
||||
}
|
||||
@ -99,7 +99,7 @@ func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*ThreadContext, err
|
||||
}
|
||||
}
|
||||
|
||||
dbp.Threads[tid] = &ThreadContext{
|
||||
dbp.Threads[tid] = &Thread{
|
||||
Id: tid,
|
||||
dbp: dbp,
|
||||
os: new(OSSpecificDetails),
|
||||
@ -221,7 +221,7 @@ func (dbp *DebuggedProcess) parseDebugLineInfo(exe *elf.File, wg *sync.WaitGroup
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) trapWait(pid int) (*ThreadContext, error) {
|
||||
func (dbp *DebuggedProcess) trapWait(pid int) (*Thread, error) {
|
||||
for {
|
||||
wpid, status, err := wait(pid, 0)
|
||||
if err != nil {
|
||||
|
||||
@ -37,7 +37,7 @@ func getRegisters(p *DebuggedProcess, t *testing.T) Registers {
|
||||
return regs
|
||||
}
|
||||
|
||||
func dataAtAddr(thread *ThreadContext, addr uint64) ([]byte, error) {
|
||||
func dataAtAddr(thread *Thread, addr uint64) ([]byte, error) {
|
||||
data := make([]byte, 1)
|
||||
_, err := readMemory(thread, uintptr(addr), data)
|
||||
if err != nil {
|
||||
|
||||
@ -10,11 +10,11 @@ type Registers interface {
|
||||
PC() uint64
|
||||
SP() uint64
|
||||
CX() uint64
|
||||
SetPC(*ThreadContext, uint64) error
|
||||
SetPC(*Thread, uint64) error
|
||||
}
|
||||
|
||||
// Obtains register values from the debugged process.
|
||||
func (thread *ThreadContext) Registers() (Registers, error) {
|
||||
func (thread *Thread) Registers() (Registers, error) {
|
||||
regs, err := registers(thread)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get registers: %s", err)
|
||||
@ -23,7 +23,7 @@ func (thread *ThreadContext) Registers() (Registers, error) {
|
||||
}
|
||||
|
||||
// Returns the current PC for this thread.
|
||||
func (thread *ThreadContext) PC() (uint64, error) {
|
||||
func (thread *Thread) PC() (uint64, error) {
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
||||
@ -20,7 +20,7 @@ func (r *Regs) CX() uint64 {
|
||||
return r.cx
|
||||
}
|
||||
|
||||
func (r *Regs) SetPC(thread *ThreadContext, pc uint64) error {
|
||||
func (r *Regs) SetPC(thread *Thread, pc uint64) error {
|
||||
kret := C.set_pc(thread.os.thread_act, C.uint64_t(pc))
|
||||
if kret != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("could not set pc")
|
||||
@ -28,7 +28,7 @@ func (r *Regs) SetPC(thread *ThreadContext, pc uint64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func registers(thread *ThreadContext) (Registers, error) {
|
||||
func registers(thread *Thread) (Registers, error) {
|
||||
var state C.x86_thread_state64_t
|
||||
kret := C.get_registers(C.mach_port_name_t(thread.os.thread_act), &state)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
|
||||
@ -18,12 +18,12 @@ func (r *Regs) CX() uint64 {
|
||||
return r.regs.Rcx
|
||||
}
|
||||
|
||||
func (r *Regs) SetPC(thread *ThreadContext, pc uint64) error {
|
||||
func (r *Regs) SetPC(thread *Thread, pc uint64) error {
|
||||
r.regs.SetPC(pc)
|
||||
return sys.PtraceSetRegs(thread.Id, r.regs)
|
||||
}
|
||||
|
||||
func registers(thread *ThreadContext) (Registers, error) {
|
||||
func registers(thread *Thread) (Registers, error) {
|
||||
var regs sys.PtraceRegs
|
||||
err := sys.PtraceGetRegs(thread.Id, ®s)
|
||||
if err != nil {
|
||||
|
||||
@ -14,7 +14,7 @@ type stackLocation struct {
|
||||
|
||||
// Takes an offset from RSP and returns the address of the
|
||||
// instruction the currect function is going to return to.
|
||||
func (thread *ThreadContext) ReturnAddress() (uint64, error) {
|
||||
func (thread *Thread) ReturnAddress() (uint64, error) {
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
||||
@ -10,12 +10,12 @@ import (
|
||||
sys "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// ThreadContext represents a single thread in the traced process
|
||||
// Id represents the thread id, Process holds a reference to the
|
||||
// Thread represents a single thread in the traced process
|
||||
// Id represents the thread id or port, Process holds a reference to the
|
||||
// DebuggedProcess struct that contains info on the process as
|
||||
// a whole, and Status represents the last result of a `wait` call
|
||||
// on this thread.
|
||||
type ThreadContext struct {
|
||||
type Thread struct {
|
||||
Id int
|
||||
Status *sys.WaitStatus
|
||||
CurrentBreakpoint *Breakpoint
|
||||
@ -36,7 +36,7 @@ type Location struct {
|
||||
// software breakpoints into consideration and ensures that
|
||||
// we step over any breakpoints. It will restore the instruction,
|
||||
// step, and then restore the breakpoint and continue.
|
||||
func (thread *ThreadContext) Continue() error {
|
||||
func (thread *Thread) Continue() error {
|
||||
pc, err := thread.PC()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -54,7 +54,7 @@ func (thread *ThreadContext) Continue() error {
|
||||
|
||||
// Single steps this thread a single instruction, ensuring that
|
||||
// we correctly handle the likely case that we are at a breakpoint.
|
||||
func (thread *ThreadContext) Step() (err error) {
|
||||
func (thread *Thread) Step() (err error) {
|
||||
thread.singleStepping = true
|
||||
defer func() { thread.singleStepping = false }()
|
||||
pc, err := thread.PC()
|
||||
@ -86,21 +86,21 @@ func (thread *ThreadContext) Step() (err error) {
|
||||
}
|
||||
|
||||
// Set breakpoint using this thread.
|
||||
func (thread *ThreadContext) Break(addr uint64) (*Breakpoint, error) {
|
||||
func (thread *Thread) Break(addr uint64) (*Breakpoint, error) {
|
||||
return thread.dbp.setBreakpoint(thread.Id, addr, false)
|
||||
}
|
||||
|
||||
// Set breakpoint using this thread.
|
||||
func (thread *ThreadContext) TempBreak(addr uint64) (*Breakpoint, error) {
|
||||
func (thread *Thread) TempBreak(addr uint64) (*Breakpoint, error) {
|
||||
return thread.dbp.setBreakpoint(thread.Id, addr, true)
|
||||
}
|
||||
|
||||
// Clear breakpoint using this thread.
|
||||
func (thread *ThreadContext) Clear(addr uint64) (*Breakpoint, error) {
|
||||
func (thread *Thread) Clear(addr uint64) (*Breakpoint, error) {
|
||||
return thread.dbp.clearBreakpoint(thread.Id, addr)
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) Location() (*Location, error) {
|
||||
func (thread *Thread) Location() (*Location, error) {
|
||||
pc, err := thread.PC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -117,7 +117,7 @@ func (thread *ThreadContext) Location() (*Location, error) {
|
||||
// This functionality is implemented by finding all possible next lines
|
||||
// and setting a breakpoint at them. Once we've set a breakpoint at each
|
||||
// potential line, we continue the thread.
|
||||
func (thread *ThreadContext) SetNextBreakpoints() (err error) {
|
||||
func (thread *Thread) SetNextBreakpoints() (err error) {
|
||||
curpc, err := thread.PC()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -158,7 +158,7 @@ func (ge GoroutineExitingError) Error() string {
|
||||
|
||||
// This version of next uses the AST from the current source file to figure out all of the potential source lines
|
||||
// we could end up at.
|
||||
func (thread *ThreadContext) next(curpc uint64, fde *frame.FrameDescriptionEntry, file string, line int) error {
|
||||
func (thread *Thread) next(curpc uint64, fde *frame.FrameDescriptionEntry, file string, line int) error {
|
||||
lines, err := thread.dbp.ast.NextLines(file, line)
|
||||
if err != nil {
|
||||
if _, ok := err.(source.NoNodeError); !ok {
|
||||
@ -201,7 +201,7 @@ func (thread *ThreadContext) next(curpc uint64, fde *frame.FrameDescriptionEntry
|
||||
// Set a breakpoint at every reachable location, as well as the return address. Without
|
||||
// the benefit of an AST we can't be sure we're not at a branching statement and thus
|
||||
// cannot accurately predict where we may end up.
|
||||
func (thread *ThreadContext) cnext(curpc uint64, fde *frame.FrameDescriptionEntry) error {
|
||||
func (thread *Thread) cnext(curpc uint64, fde *frame.FrameDescriptionEntry) error {
|
||||
pcs := thread.dbp.lineInfo.AllPCsBetween(fde.Begin(), fde.End())
|
||||
ret, err := thread.ReturnAddress()
|
||||
if err != nil {
|
||||
@ -211,7 +211,7 @@ func (thread *ThreadContext) cnext(curpc uint64, fde *frame.FrameDescriptionEntr
|
||||
return thread.setNextTempBreakpoints(curpc, pcs)
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) setNextTempBreakpoints(curpc uint64, pcs []uint64) error {
|
||||
func (thread *Thread) setNextTempBreakpoints(curpc uint64, pcs []uint64) error {
|
||||
for i := range pcs {
|
||||
if pcs[i] == curpc || pcs[i] == curpc-1 {
|
||||
continue
|
||||
@ -226,7 +226,7 @@ func (thread *ThreadContext) setNextTempBreakpoints(curpc uint64, pcs []uint64)
|
||||
}
|
||||
|
||||
// Sets the PC for this thread.
|
||||
func (thread *ThreadContext) SetPC(pc uint64) error {
|
||||
func (thread *Thread) SetPC(pc uint64) error {
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -252,7 +252,7 @@ func (thread *ThreadContext) SetPC(pc uint64) error {
|
||||
// current instruction stream. The instructions are obviously arch/os dependant, as they
|
||||
// vary on how thread local storage is implemented, which MMU register is used and
|
||||
// what the offset into thread local storage is.
|
||||
func (thread *ThreadContext) getG() (g *G, err error) {
|
||||
func (thread *Thread) getG() (g *G, err error) {
|
||||
var pcInt uint64
|
||||
pcInt, err = thread.PC()
|
||||
if err != nil {
|
||||
|
||||
@ -12,7 +12,7 @@ type OSSpecificDetails struct {
|
||||
registers C.x86_thread_state64_t
|
||||
}
|
||||
|
||||
func (t *ThreadContext) Halt() error {
|
||||
func (t *Thread) Halt() error {
|
||||
var kret C.kern_return_t
|
||||
kret = C.thread_suspend(t.os.thread_act)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
@ -21,7 +21,7 @@ func (t *ThreadContext) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) singleStep() error {
|
||||
func (t *Thread) singleStep() error {
|
||||
kret := C.single_step(t.os.thread_act)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("could not single step")
|
||||
@ -34,7 +34,7 @@ func (t *ThreadContext) singleStep() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) resume() error {
|
||||
func (t *Thread) resume() error {
|
||||
// TODO(dp) set flag for ptrace stops
|
||||
if PtraceCont(t.dbp.Pid, 0) == nil {
|
||||
return nil
|
||||
@ -46,7 +46,7 @@ func (t *ThreadContext) resume() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) blocked() bool {
|
||||
func (t *Thread) blocked() bool {
|
||||
// TODO(dp) cache the func pc to remove this lookup
|
||||
pc, _ := t.PC()
|
||||
fn := t.dbp.goSymTable.PCToFunc(pc)
|
||||
@ -56,7 +56,7 @@ func (t *ThreadContext) blocked() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func writeMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
|
||||
func writeMemory(thread *Thread, addr uintptr, data []byte) (int, error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@ -71,7 +71,7 @@ func writeMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error)
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func readMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
|
||||
func readMemory(thread *Thread, addr uintptr, data []byte) (int, error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@ -88,7 +88,7 @@ func readMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) saveRegisters() (Registers, error) {
|
||||
func (thread *Thread) saveRegisters() (Registers, error) {
|
||||
kret := C.get_registers(C.mach_port_name_t(thread.os.thread_act), &thread.os.registers)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
return nil, fmt.Errorf("could not save register contents")
|
||||
@ -96,7 +96,7 @@ func (thread *ThreadContext) saveRegisters() (Registers, error) {
|
||||
return &Regs{pc: uint64(thread.os.registers.__rip), sp: uint64(thread.os.registers.__rsp)}, nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) restoreRegisters() error {
|
||||
func (thread *Thread) restoreRegisters() error {
|
||||
kret := C.set_registers(C.mach_port_name_t(thread.os.thread_act), &thread.os.registers)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("could not save register contents")
|
||||
|
||||
@ -12,7 +12,7 @@ type OSSpecificDetails struct {
|
||||
registers sys.PtraceRegs
|
||||
}
|
||||
|
||||
func (t *ThreadContext) Halt() error {
|
||||
func (t *Thread) Halt() error {
|
||||
if stopped(t.Id) {
|
||||
return nil
|
||||
}
|
||||
@ -27,11 +27,11 @@ func (t *ThreadContext) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) resume() error {
|
||||
func (t *Thread) resume() error {
|
||||
return PtraceCont(t.Id, 0)
|
||||
}
|
||||
|
||||
func (t *ThreadContext) singleStep() error {
|
||||
func (t *Thread) singleStep() error {
|
||||
err := sys.PtraceSingleStep(t.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -40,7 +40,7 @@ func (t *ThreadContext) singleStep() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *ThreadContext) blocked() bool {
|
||||
func (t *Thread) blocked() bool {
|
||||
// TODO(dp) cache the func pc to remove this lookup
|
||||
pc, _ := t.PC()
|
||||
fn := t.dbp.goSymTable.PCToFunc(pc)
|
||||
@ -50,25 +50,25 @@ func (t *ThreadContext) blocked() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) saveRegisters() (Registers, error) {
|
||||
func (thread *Thread) saveRegisters() (Registers, error) {
|
||||
if err := sys.PtraceGetRegs(thread.Id, &thread.os.registers); err != nil {
|
||||
return nil, fmt.Errorf("could not save register contents")
|
||||
}
|
||||
return &Regs{&thread.os.registers}, nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) restoreRegisters() error {
|
||||
func (thread *Thread) restoreRegisters() error {
|
||||
return sys.PtraceSetRegs(thread.Id, &thread.os.registers)
|
||||
}
|
||||
|
||||
func writeMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
|
||||
func writeMemory(thread *Thread, addr uintptr, data []byte) (int, error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
return sys.PtracePokeData(thread.Id, addr, data)
|
||||
}
|
||||
|
||||
func readMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
|
||||
func readMemory(thread *Thread, addr uintptr, data []byte) (int, error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ func (ng NoGError) Error() string {
|
||||
return fmt.Sprintf("no G executing on thread %d", ng.tid)
|
||||
}
|
||||
|
||||
func parseG(thread *ThreadContext, gaddr uint64, deref bool) (*G, error) {
|
||||
func parseG(thread *Thread, gaddr uint64, deref bool) (*G, error) {
|
||||
initialInstructions := make([]byte, thread.dbp.arch.PtrSize()+1)
|
||||
initialInstructions[0] = op.DW_OP_addr
|
||||
binary.LittleEndian.PutUint64(initialInstructions[1:], gaddr)
|
||||
@ -198,7 +198,7 @@ func parseG(thread *ThreadContext, gaddr uint64, deref bool) (*G, error) {
|
||||
}
|
||||
|
||||
// Returns the value of the named variable.
|
||||
func (thread *ThreadContext) EvalVariable(name string) (*Variable, error) {
|
||||
func (thread *Thread) EvalVariable(name string) (*Variable, error) {
|
||||
pc, err := thread.PC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -241,17 +241,17 @@ func (thread *ThreadContext) EvalVariable(name string) (*Variable, error) {
|
||||
}
|
||||
|
||||
// LocalVariables returns all local variables from the current function scope.
|
||||
func (thread *ThreadContext) LocalVariables() ([]*Variable, error) {
|
||||
func (thread *Thread) LocalVariables() ([]*Variable, error) {
|
||||
return thread.variablesByTag(dwarf.TagVariable)
|
||||
}
|
||||
|
||||
// FunctionArguments returns the name, value, and type of all current function arguments.
|
||||
func (thread *ThreadContext) FunctionArguments() ([]*Variable, error) {
|
||||
func (thread *Thread) FunctionArguments() ([]*Variable, error) {
|
||||
return thread.variablesByTag(dwarf.TagFormalParameter)
|
||||
}
|
||||
|
||||
// PackageVariables returns the name, value, and type of all package variables in the application.
|
||||
func (thread *ThreadContext) PackageVariables() ([]*Variable, error) {
|
||||
func (thread *Thread) PackageVariables() ([]*Variable, error) {
|
||||
reader := thread.dbp.DwarfReader()
|
||||
|
||||
vars := make([]*Variable, 0)
|
||||
@ -272,7 +272,7 @@ func (thread *ThreadContext) PackageVariables() ([]*Variable, error) {
|
||||
return vars, nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) evaluateStructMember(parentEntry *dwarf.Entry, rdr *reader.Reader, memberName string) (*Variable, error) {
|
||||
func (thread *Thread) evaluateStructMember(parentEntry *dwarf.Entry, rdr *reader.Reader, memberName string) (*Variable, error) {
|
||||
parentAddr, err := thread.extractVariableDataAddress(parentEntry, rdr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -339,7 +339,7 @@ func (thread *ThreadContext) evaluateStructMember(parentEntry *dwarf.Entry, rdr
|
||||
}
|
||||
|
||||
// Extracts the name, type, and value of a variable from a dwarf entry
|
||||
func (thread *ThreadContext) extractVariableFromEntry(entry *dwarf.Entry) (*Variable, error) {
|
||||
func (thread *Thread) extractVariableFromEntry(entry *dwarf.Entry) (*Variable, error) {
|
||||
if entry == nil {
|
||||
return nil, fmt.Errorf("invalid entry")
|
||||
}
|
||||
@ -378,7 +378,7 @@ func (thread *ThreadContext) extractVariableFromEntry(entry *dwarf.Entry) (*Vari
|
||||
}
|
||||
|
||||
// Execute the stack program taking into account the current stack frame
|
||||
func (thread *ThreadContext) executeStackProgram(instructions []byte) (int64, error) {
|
||||
func (thread *Thread) executeStackProgram(instructions []byte) (int64, error) {
|
||||
regs, err := thread.Registers()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -399,7 +399,7 @@ func (thread *ThreadContext) executeStackProgram(instructions []byte) (int64, er
|
||||
}
|
||||
|
||||
// Extracts the address of a variable, dereferencing any pointers
|
||||
func (thread *ThreadContext) extractVariableDataAddress(entry *dwarf.Entry, rdr *reader.Reader) (int64, error) {
|
||||
func (thread *Thread) extractVariableDataAddress(entry *dwarf.Entry, rdr *reader.Reader) (int64, error) {
|
||||
instructions, err := rdr.InstructionsForEntry(entry)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -435,11 +435,11 @@ func (thread *ThreadContext) extractVariableDataAddress(entry *dwarf.Entry, rdr
|
||||
// Extracts the value from the instructions given in the DW_AT_location entry.
|
||||
// We execute the stack program described in the DW_OP_* instruction stream, and
|
||||
// then grab the value from the other processes memory.
|
||||
func (thread *ThreadContext) extractValue(instructions []byte, addr int64, typ interface{}, printStructName bool) (string, error) {
|
||||
func (thread *Thread) extractValue(instructions []byte, addr int64, typ interface{}, printStructName bool) (string, error) {
|
||||
return thread.extractValueInternal(instructions, addr, typ, printStructName, 0)
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) extractValueInternal(instructions []byte, addr int64, typ interface{}, printStructName bool, recurseLevel int) (string, error) {
|
||||
func (thread *Thread) extractValueInternal(instructions []byte, addr int64, typ interface{}, printStructName bool, recurseLevel int) (string, error) {
|
||||
var err error
|
||||
|
||||
if addr == 0 {
|
||||
@ -532,7 +532,7 @@ func (thread *ThreadContext) extractValueInternal(instructions []byte, addr int6
|
||||
return "", fmt.Errorf("could not find value for type %s", typ)
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readString(addr uintptr) (string, error) {
|
||||
func (thread *Thread) readString(addr uintptr) (string, error) {
|
||||
// string data structure is always two ptrs in size. Addr, followed by len
|
||||
// http://research.swtch.com/godata
|
||||
|
||||
@ -561,7 +561,7 @@ func (thread *ThreadContext) readString(addr uintptr) (string, error) {
|
||||
return *(*string)(unsafe.Pointer(&val)), nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readSlice(addr uintptr, t *dwarf.StructType) (string, error) {
|
||||
func (thread *Thread) readSlice(addr uintptr, t *dwarf.StructType) (string, error) {
|
||||
var sliceLen, sliceCap int64
|
||||
var arrayAddr uintptr
|
||||
var arrayType dwarf.Type
|
||||
@ -612,7 +612,7 @@ func (thread *ThreadContext) readSlice(addr uintptr, t *dwarf.StructType) (strin
|
||||
return fmt.Sprintf("[]%s len: %d, cap: %d, [%s]", arrayType, sliceLen, sliceCap, strings.Join(vals, ",")), nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readArray(addr uintptr, t *dwarf.ArrayType) (string, error) {
|
||||
func (thread *Thread) readArray(addr uintptr, t *dwarf.ArrayType) (string, error) {
|
||||
if t.Count > 0 {
|
||||
vals, err := thread.readArrayValues(addr, t.Count, t.ByteSize/t.Count, t.Type)
|
||||
if err != nil {
|
||||
@ -624,7 +624,7 @@ func (thread *ThreadContext) readArray(addr uintptr, t *dwarf.ArrayType) (string
|
||||
return fmt.Sprintf("%s []", t), nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readArrayValues(addr uintptr, count int64, stride int64, t dwarf.Type) ([]string, error) {
|
||||
func (thread *Thread) readArrayValues(addr uintptr, count int64, stride int64, t dwarf.Type) ([]string, error) {
|
||||
vals := make([]string, 0)
|
||||
|
||||
for i := int64(0); i < count; i++ {
|
||||
@ -643,7 +643,7 @@ func (thread *ThreadContext) readArrayValues(addr uintptr, count int64, stride i
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readInt(addr uintptr, size int64) (string, error) {
|
||||
func (thread *Thread) readInt(addr uintptr, size int64) (string, error) {
|
||||
n, err := thread.readIntRaw(addr, size)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -651,7 +651,7 @@ func (thread *ThreadContext) readInt(addr uintptr, size int64) (string, error) {
|
||||
return strconv.FormatInt(n, 10), nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readIntRaw(addr uintptr, size int64) (int64, error) {
|
||||
func (thread *Thread) readIntRaw(addr uintptr, size int64) (int64, error) {
|
||||
var n int64
|
||||
|
||||
val, err := thread.readMemory(addr, int(size))
|
||||
@ -673,7 +673,7 @@ func (thread *ThreadContext) readIntRaw(addr uintptr, size int64) (int64, error)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readUint(addr uintptr, size int64) (string, error) {
|
||||
func (thread *Thread) readUint(addr uintptr, size int64) (string, error) {
|
||||
n, err := thread.readUintRaw(addr, size)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -681,7 +681,7 @@ func (thread *ThreadContext) readUint(addr uintptr, size int64) (string, error)
|
||||
return strconv.FormatUint(n, 10), nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readUintRaw(addr uintptr, size int64) (uint64, error) {
|
||||
func (thread *Thread) readUintRaw(addr uintptr, size int64) (uint64, error) {
|
||||
var n uint64
|
||||
|
||||
val, err := thread.readMemory(addr, int(size))
|
||||
@ -703,7 +703,7 @@ func (thread *ThreadContext) readUintRaw(addr uintptr, size int64) (uint64, erro
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readFloat(addr uintptr, size int64) (string, error) {
|
||||
func (thread *Thread) readFloat(addr uintptr, size int64) (string, error) {
|
||||
val, err := thread.readMemory(addr, int(size))
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -724,7 +724,7 @@ func (thread *ThreadContext) readFloat(addr uintptr, size int64) (string, error)
|
||||
return "", fmt.Errorf("could not read float")
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readBool(addr uintptr) (string, error) {
|
||||
func (thread *Thread) readBool(addr uintptr) (string, error) {
|
||||
val, err := thread.readMemory(addr, 1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -737,7 +737,7 @@ func (thread *ThreadContext) readBool(addr uintptr) (string, error) {
|
||||
return "true", nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) {
|
||||
func (thread *Thread) readFunctionPtr(addr uintptr) (string, error) {
|
||||
val, err := thread.readMemory(addr, thread.dbp.arch.PtrSize())
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -763,7 +763,7 @@ func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) {
|
||||
return fn.Name, nil
|
||||
}
|
||||
|
||||
func (thread *ThreadContext) readMemory(addr uintptr, size int) ([]byte, error) {
|
||||
func (thread *Thread) readMemory(addr uintptr, size int) ([]byte, error) {
|
||||
if size == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
@ -777,7 +777,7 @@ func (thread *ThreadContext) readMemory(addr uintptr, size int) ([]byte, error)
|
||||
}
|
||||
|
||||
// Fetches all variables of a specific type in the current function scope
|
||||
func (thread *ThreadContext) variablesByTag(tag dwarf.Tag) ([]*Variable, error) {
|
||||
func (thread *Thread) variablesByTag(tag dwarf.Tag) ([]*Variable, error) {
|
||||
pc, err := thread.PC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -145,10 +145,10 @@ func (s varArray) Less(i, j int) bool {
|
||||
|
||||
func TestLocalVariables(t *testing.T) {
|
||||
testcases := []struct {
|
||||
fn func(*ThreadContext) ([]*Variable, error)
|
||||
fn func(*Thread) ([]*Variable, error)
|
||||
output []varTest
|
||||
}{
|
||||
{(*ThreadContext).LocalVariables,
|
||||
{(*Thread).LocalVariables,
|
||||
[]varTest{
|
||||
{"a1", "foofoofoofoofoofoo", "struct string", nil},
|
||||
{"a10", "ofo", "struct string", nil},
|
||||
@ -177,7 +177,7 @@ func TestLocalVariables(t *testing.T) {
|
||||
{"u64", "18446744073709551615", "uint64", nil},
|
||||
{"u8", "255", "uint8", nil},
|
||||
{"up", "5", "uintptr", nil}}},
|
||||
{(*ThreadContext).FunctionArguments,
|
||||
{(*Thread).FunctionArguments,
|
||||
[]varTest{
|
||||
{"bar", "main.FooBar {Baz: 10, Bur: lorem}", "main.FooBar", nil},
|
||||
{"baz", "bazburzum", "struct string", nil}}},
|
||||
|
||||
@ -471,7 +471,7 @@ func convertBreakpoint(bp *proc.Breakpoint) *api.Breakpoint {
|
||||
}
|
||||
|
||||
// convertThread converts an internal thread to an API Thread.
|
||||
func convertThread(th *proc.ThreadContext) *api.Thread {
|
||||
func convertThread(th *proc.Thread) *api.Thread {
|
||||
var (
|
||||
function *api.Function
|
||||
file string
|
||||
|
||||
Reference in New Issue
Block a user