提交 3dacc25d 编写于 作者: A aarzilli 提交者: Derek Parker

proc: refactor Continue to work on any Process implementation

上级 510b7db2
......@@ -107,7 +107,7 @@ func (dbp *Process) writeSoftwareBreakpoint(thread *Thread, addr uint64) error {
return err
}
func (bp *Breakpoint) checkCondition(thread *Thread) (bool, error) {
func (bp *Breakpoint) checkCondition(thread IThread) (bool, error) {
if bp.Cond == nil {
return true, nil
}
......
package proc
import (
"debug/gosym"
"encoding/binary"
"errors"
"fmt"
......@@ -319,17 +320,17 @@ func (dbp *Process) Status() *WaitStatus {
}
// Next continues execution until the next source line.
func (dbp *Process) Next() (err error) {
if dbp.exited {
func Next(dbp Continuable) (err error) {
if dbp.Exited() {
return &ProcessExitedError{}
}
for i := range dbp.breakpoints {
if dbp.breakpoints[i].Internal() {
for _, bp := range dbp.Breakpoints() {
if bp.Internal() {
return fmt.Errorf("next while nexting")
}
}
if err = dbp.next(false); err != nil {
if err = next(dbp, false); err != nil {
switch err.(type) {
case ThreadBlockedError, NoReturnAddr: // Noop
default:
......@@ -338,91 +339,119 @@ func (dbp *Process) Next() (err error) {
}
}
return dbp.Continue()
return Continue(dbp)
}
func (dbp *Process) ContinueOnce() (IThread, error) {
if dbp.exited {
return nil, &ProcessExitedError{}
}
if err := dbp.resume(); err != nil {
return nil, err
}
dbp.allGCache = nil
for _, th := range dbp.threads {
th.clearBreakpointState()
}
trapthread, err := dbp.trapWait(-1)
if err != nil {
return nil, err
}
if err := dbp.Halt(); err != nil {
return nil, dbp.exitGuard(err)
}
if err := dbp.setCurrentBreakpoints(trapthread); err != nil {
return nil, err
}
return trapthread, err
}
// Continuable is the subinterface of target.Interface used to implement
// Continue/Next/etc.
type Continuable interface {
ContinueOnce() (trapthread IThread, err error)
CurrentThread() IThread
SelectedGoroutine() *G
Breakpoints() map[uint64]*Breakpoint
ThreadList() []IThread
SwitchThread(int) error
BinInfo() *BinaryInfo
ClearInternalBreakpoints() error
FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error)
SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error)
Exited() bool
}
// Continue continues execution of the debugged
// process. It will continue until it hits a breakpoint
// or is otherwise stopped.
func (dbp *Process) Continue() error {
if dbp.exited {
return &ProcessExitedError{}
}
func Continue(dbp Continuable) error {
for {
if err := dbp.resume(); err != nil {
trapthread, err := dbp.ContinueOnce()
if err != nil {
return err
}
dbp.allGCache = nil
for _, th := range dbp.threads {
th.clearBreakpointState()
}
threads := dbp.ThreadList()
trapthread, err := dbp.trapWait(-1)
if err != nil {
return err
}
if err := dbp.Halt(); err != nil {
return dbp.exitGuard(err)
}
if err := dbp.setCurrentBreakpoints(trapthread); err != nil {
return err
}
if err := dbp.pickCurrentThread(trapthread); err != nil {
if err := pickCurrentThread(dbp, trapthread, threads); err != nil {
return err
}
curthread := dbp.CurrentThread()
curbp, curbpActive, _ := curthread.Breakpoint()
switch {
case dbp.currentThread.CurrentBreakpoint == nil:
case curbp == nil:
// runtime.Breakpoint or manual stop
if dbp.currentThread.onRuntimeBreakpoint() {
if onRuntimeBreakpoint(curthread) {
// Single-step current thread until we exit runtime.breakpoint and
// runtime.Breakpoint.
// On go < 1.8 it was sufficient to single-step twice on go1.8 a change
// to the compiler requires 4 steps.
for {
if err = dbp.currentThread.StepInstruction(); err != nil {
if err = curthread.StepInstruction(); err != nil {
return err
}
loc, err := dbp.currentThread.Location()
loc, err := curthread.Location()
if err != nil || loc.Fn == nil || (loc.Fn.Name != "runtime.breakpoint" && loc.Fn.Name != "runtime.Breakpoint") {
break
}
}
}
return dbp.conditionErrors()
case dbp.currentThread.onTriggeredInternalBreakpoint():
if dbp.currentThread.CurrentBreakpoint.Kind == StepBreakpoint {
return conditionErrors(threads)
case curbpActive && curbp.Internal():
if curbp.Kind == StepBreakpoint {
// See description of proc.(*Process).next for the meaning of StepBreakpoints
if err := dbp.conditionErrors(); err != nil {
return err
}
pc, err := dbp.currentThread.PC()
if err != nil {
if err := conditionErrors(threads); err != nil {
return err
}
regs, err := dbp.currentThread.Registers(false)
regs, err := curthread.Registers(false)
if err != nil {
return err
}
text, err := disassemble(dbp.currentThread, regs, dbp.breakpoints, dbp.BinInfo(), pc, pc+maxInstructionLength)
pc := regs.PC()
text, err := disassemble(curthread, regs, dbp.Breakpoints(), dbp.BinInfo(), pc, pc+maxInstructionLength)
if err != nil {
return err
}
// here we either set a breakpoint into the destination of the CALL
// instruction or we determined that the called function is hidden,
// either way we need to resume execution
if err = dbp.setStepIntoBreakpoint(text, sameGoroutineCondition(dbp.selectedGoroutine)); err != nil {
if err = setStepIntoBreakpoint(dbp, text, sameGoroutineCondition(dbp.SelectedGoroutine())); err != nil {
return err
}
} else {
if err := dbp.ClearInternalBreakpoints(); err != nil {
return err
}
return dbp.conditionErrors()
return conditionErrors(threads)
}
case dbp.currentThread.onTriggeredBreakpoint():
onNextGoroutine, err := dbp.currentThread.onNextGoroutine()
case curbpActive:
onNextGoroutine, err := onNextGoroutine(curthread, dbp.Breakpoints())
if err != nil {
return err
}
......@@ -432,19 +461,19 @@ func (dbp *Process) Continue() error {
return err
}
}
return dbp.conditionErrors()
return conditionErrors(threads)
default:
// not a manual stop, not on runtime.Breakpoint, not on a breakpoint, just repeat
}
}
}
func (dbp *Process) conditionErrors() error {
func conditionErrors(threads []IThread) error {
var condErr error
for _, th := range dbp.threads {
if th.CurrentBreakpoint != nil && th.BreakpointConditionError != nil {
for _, th := range threads {
if bp, _, bperr := th.Breakpoint(); bp != nil && bperr != nil {
if condErr == nil {
condErr = th.BreakpointConditionError
condErr = bperr
} else {
return fmt.Errorf("multiple errors evaluating conditions")
}
......@@ -457,36 +486,36 @@ func (dbp *Process) conditionErrors() error {
// - a thread with onTriggeredInternalBreakpoint() == true
// - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread)
// - trapthread
func (dbp *Process) pickCurrentThread(trapthread *Thread) error {
for _, th := range dbp.threads {
if th.onTriggeredInternalBreakpoint() {
return dbp.SwitchThread(th.ID)
func pickCurrentThread(dbp Continuable, trapthread IThread, threads []IThread) error {
for _, th := range threads {
if bp, active, _ := th.Breakpoint(); active && bp.Internal() {
return dbp.SwitchThread(th.ThreadID())
}
}
if trapthread.onTriggeredBreakpoint() {
return dbp.SwitchThread(trapthread.ID)
if _, active, _ := trapthread.Breakpoint(); active {
return dbp.SwitchThread(trapthread.ThreadID())
}
for _, th := range dbp.threads {
if th.onTriggeredBreakpoint() {
return dbp.SwitchThread(th.ID)
for _, th := range threads {
if _, active, _ := th.Breakpoint(); active {
return dbp.SwitchThread(th.ThreadID())
}
}
return dbp.SwitchThread(trapthread.ID)
return dbp.SwitchThread(trapthread.ThreadID())
}
// Step will continue until another source line is reached.
// Will step into functions.
func (dbp *Process) Step() (err error) {
if dbp.exited {
func Step(dbp Continuable) (err error) {
if dbp.Exited() {
return &ProcessExitedError{}
}
for i := range dbp.breakpoints {
if dbp.breakpoints[i].Internal() {
for _, bp := range dbp.Breakpoints() {
if bp.Internal() {
return fmt.Errorf("next while nexting")
}
}
if err = dbp.next(true); err != nil {
if err = next(dbp, true); err != nil {
switch err.(type) {
case ThreadBlockedError, NoReturnAddr: // Noop
default:
......@@ -495,7 +524,7 @@ func (dbp *Process) Step() (err error) {
}
}
return dbp.Continue()
return Continue(dbp)
}
// Returns an expression that evaluates to true when the current goroutine is g
......@@ -529,7 +558,7 @@ func (dbp *Process) StepInstruction() (err error) {
if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.selectedGoroutine)); err != nil {
return err
}
return dbp.Continue()
return Continue(dbp)
}
dbp.allGCache = nil
if dbp.exited {
......@@ -545,10 +574,12 @@ func (dbp *Process) StepInstruction() (err error) {
// StepOut will continue until the current goroutine exits the
// function currently being executed or a deferred function is executed
func (dbp *Process) StepOut() error {
cond := sameGoroutineCondition(dbp.selectedGoroutine)
func StepOut(dbp Continuable) error {
selg := dbp.SelectedGoroutine()
curthread := dbp.CurrentThread()
cond := sameGoroutineCondition(selg)
topframe, err := topframe(dbp.selectedGoroutine, dbp.currentThread)
topframe, err := topframe(selg, curthread)
if err != nil {
return err
}
......@@ -557,10 +588,10 @@ func (dbp *Process) StepOut() error {
var deferpc uint64 = 0
if filepath.Ext(topframe.Current.File) == ".go" {
if dbp.selectedGoroutine != nil {
deferPCEntry := dbp.selectedGoroutine.DeferPC()
if selg != nil {
deferPCEntry := selg.DeferPC()
if deferPCEntry != 0 {
_, _, deferfn := dbp.bi.goSymTable.PCToLine(deferPCEntry)
_, _, deferfn := dbp.BinInfo().PCToLine(deferPCEntry)
deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false)
if err != nil {
return err
......@@ -591,12 +622,12 @@ func (dbp *Process) StepOut() error {
}
if topframe.Ret != 0 {
if err := dbp.setInternalBreakpoints(topframe.Current.PC, []uint64{topframe.Ret}, NextBreakpoint, cond); err != nil {
if err := setInternalBreakpoints(dbp, topframe.Current.PC, []uint64{topframe.Ret}, NextBreakpoint, cond); err != nil {
return err
}
}
return dbp.Continue()
return Continue(dbp)
}
// SwitchThread changes from current thread to the thread specified by `tid`.
......@@ -633,29 +664,42 @@ func (dbp *Process) SwitchGoroutine(gid int) error {
return nil
}
// If the argument of GoroutinesInfo implements AllGCache GoroutinesInfo
// will use the pointer returned by AllGCache as a cache.
type AllGCache interface {
AllGCache() *[]*G
}
func (dbp *Process) AllGCache() *[]*G {
return &dbp.allGCache
}
// GoroutinesInfo returns an array of G structures representing the information
// Delve cares about from the internal runtime G structure.
func (dbp *Process) GoroutinesInfo() ([]*G, error) {
if dbp.exited {
func GoroutinesInfo(dbp EvalScopeConvertible) ([]*G, error) {
if dbp.Exited() {
return nil, &ProcessExitedError{}
}
if dbp.allGCache != nil {
return dbp.allGCache, nil
if dbp, ok := dbp.(AllGCache); ok {
if allGCache := dbp.AllGCache(); *allGCache != nil {
return *allGCache, nil
}
}
var (
threadg = map[int]*Thread{}
threadg = map[int]IThread{}
allg []*G
rdr = dbp.bi.DwarfReader()
rdr = dbp.BinInfo().DwarfReader()
)
for i := range dbp.threads {
if dbp.threads[i].blocked() {
threads := dbp.ThreadList()
for _, th := range threads {
if threadBlocked(th) {
continue
}
g, _ := GetG(dbp.threads[i])
g, _ := GetG(th)
if g != nil {
threadg[g.ID] = dbp.threads[i]
threadg[g.ID] = th
}
}
......@@ -663,7 +707,7 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
if err != nil {
return nil, err
}
allglenBytes, err := dbp.currentThread.readMemory(uintptr(addr), 8)
allglenBytes, err := dbp.CurrentThread().readMemory(uintptr(addr), 8)
if err != nil {
return nil, err
}
......@@ -678,11 +722,11 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
return nil, err
}
}
faddr, err := dbp.currentThread.readMemory(uintptr(allgentryaddr), dbp.bi.arch.PtrSize())
faddr, err := dbp.CurrentThread().readMemory(uintptr(allgentryaddr), dbp.BinInfo().arch.PtrSize())
allgptr := binary.LittleEndian.Uint64(faddr)
for i := uint64(0); i < allglen; i++ {
gvar, err := newGVariable(dbp.currentThread, uintptr(allgptr+(i*uint64(dbp.bi.arch.PtrSize()))), true)
gvar, err := newGVariable(dbp.CurrentThread(), uintptr(allgptr+(i*uint64(dbp.BinInfo().arch.PtrSize()))), true)
if err != nil {
return nil, err
}
......@@ -703,7 +747,11 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
allg = append(allg, g)
}
}
dbp.allGCache = allg
if dbp, ok := dbp.(AllGCache); ok {
allGCache := dbp.AllGCache()
*allGCache = allg
}
return allg, nil
}
......@@ -884,19 +932,14 @@ func (scope *EvalScope) getGoInformation() (ver GoVersion, isextld bool, err err
return
}
type GoroutinesInfo interface {
SelectedGoroutine() *G
GoroutinesInfo() ([]*G, error)
}
// FindGoroutine returns a G struct representing the goroutine
// specified by `gid`.
func FindGoroutine(dbp GoroutinesInfo, gid int) (*G, error) {
func FindGoroutine(dbp EvalScopeConvertible, gid int) (*G, error) {
if gid == -1 {
return dbp.SelectedGoroutine(), nil
}
gs, err := dbp.GoroutinesInfo()
gs, err := GoroutinesInfo(dbp)
if err != nil {
return nil, err
}
......@@ -911,9 +954,11 @@ func FindGoroutine(dbp GoroutinesInfo, gid int) (*G, error) {
// EvalScopeConvertible is a subset of target.Interface with the methods
// used by ConvertEvalScope/GoroutinesInfo/etc.
type EvalScopeConvertible interface {
GoroutinesInfo
Exited() bool
SelectedGoroutine() *G
CurrentThread() IThread
BinInfo() *BinaryInfo
ThreadList() []IThread
}
// ConvertEvalScope returns a new EvalScope in the context of the
......
此差异已折叠。
......@@ -23,7 +23,7 @@ func TestIssue419(t *testing.T) {
}
}
}()
err := p.Continue()
err := Continue(p)
if _, exited := err.(ProcessExitedError); !exited {
t.Fatalf("Unexpected error after Continue(): %v\n", err)
}
......
......@@ -46,6 +46,7 @@ type IThread interface {
Registers(floatingPoint bool) (Registers, error)
Arch() Arch
BinInfo() *BinaryInfo
StepInstruction() error
}
// Location represents the location of a thread.
......@@ -149,12 +150,12 @@ func (tbe ThreadBlockedError) Error() string {
}
// returns topmost frame of g or thread if g is nil
func topframe(g *G, thread *Thread) (Stackframe, error) {
func topframe(g *G, thread IThread) (Stackframe, error) {
var frames []Stackframe
var err error
if g == nil {
if thread.blocked() {
if threadBlocked(thread) {
return Stackframe{}, ThreadBlockedError{}
}
frames, err = ThreadStacktrace(thread, 0)
......@@ -177,8 +178,10 @@ func topframe(g *G, thread *Thread) (Stackframe, error) {
// a breakpoint of kind StepBreakpoint is set on the CALL instruction,
// Continue will take care of setting a breakpoint to the destination
// once the CALL is reached.
func (dbp *Process) next(stepInto bool) error {
topframe, err := topframe(dbp.selectedGoroutine, dbp.currentThread)
func next(dbp Continuable, stepInto bool) error {
selg := dbp.SelectedGoroutine()
curthread := dbp.CurrentThread()
topframe, err := topframe(selg, curthread)
if err != nil {
return err
}
......@@ -191,22 +194,22 @@ func (dbp *Process) next(stepInto bool) error {
}()
csource := filepath.Ext(topframe.Current.File) != ".go"
var thread memoryReadWriter = dbp.currentThread
var thread memoryReadWriter = curthread
var regs Registers
if dbp.selectedGoroutine != nil && dbp.selectedGoroutine.thread != nil {
thread = dbp.selectedGoroutine.thread
regs, err = dbp.selectedGoroutine.thread.Registers(false)
if selg != nil && selg.Thread() != nil {
thread = selg.Thread()
regs, err = selg.Thread().Registers(false)
if err != nil {
return err
}
}
text, err := disassemble(thread, regs, dbp.breakpoints, dbp.BinInfo(), topframe.FDE.Begin(), topframe.FDE.End())
text, err := disassemble(thread, regs, dbp.Breakpoints(), dbp.BinInfo(), topframe.FDE.Begin(), topframe.FDE.End())
if err != nil && stepInto {
return err
}
cond := sameGoroutineCondition(dbp.selectedGoroutine)
cond := sameGoroutineCondition(selg)
if stepInto {
for _, instr := range text {
......@@ -215,7 +218,7 @@ func (dbp *Process) next(stepInto bool) error {
}
if instr.DestLoc != nil && instr.DestLoc.Fn != nil {
if err := dbp.setStepIntoBreakpoint([]AsmInstruction{instr}, cond); err != nil {
if err := setStepIntoBreakpoint(dbp, []AsmInstruction{instr}, cond); err != nil {
return err
}
} else {
......@@ -242,10 +245,10 @@ func (dbp *Process) next(stepInto bool) error {
// Set breakpoint on the most recently deferred function (if any)
var deferpc uint64 = 0
if dbp.selectedGoroutine != nil {
deferPCEntry := dbp.selectedGoroutine.DeferPC()
if selg != nil {
deferPCEntry := selg.DeferPC()
if deferPCEntry != 0 {
_, _, deferfn := dbp.bi.goSymTable.PCToLine(deferPCEntry)
_, _, deferfn := dbp.BinInfo().PCToLine(deferPCEntry)
var err error
deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false)
if err != nil {
......@@ -267,7 +270,7 @@ func (dbp *Process) next(stepInto bool) error {
}
// Add breakpoints on all the lines in the current function
pcs, err := dbp.bi.lineInfo.AllPCsBetween(topframe.FDE.Begin(), topframe.FDE.End()-1, topframe.Current.File)
pcs, err := dbp.BinInfo().lineInfo.AllPCsBetween(topframe.FDE.Begin(), topframe.FDE.End()-1, topframe.Current.File)
if err != nil {
return err
}
......@@ -282,8 +285,8 @@ func (dbp *Process) next(stepInto bool) error {
}
if !covered {
fn := dbp.bi.goSymTable.PCToFunc(topframe.Ret)
if dbp.selectedGoroutine != nil && fn != nil && fn.Name == "runtime.goexit" {
fn := dbp.BinInfo().goSymTable.PCToFunc(topframe.Ret)
if selg != nil && fn != nil && fn.Name == "runtime.goexit" {
return nil
}
}
......@@ -292,10 +295,10 @@ func (dbp *Process) next(stepInto bool) error {
// Add a breakpoint on the return address for the current frame
pcs = append(pcs, topframe.Ret)
success = true
return dbp.setInternalBreakpoints(topframe.Current.PC, pcs, NextBreakpoint, cond)
return setInternalBreakpoints(dbp, topframe.Current.PC, pcs, NextBreakpoint, cond)
}
func (dbp *Process) setStepIntoBreakpoint(text []AsmInstruction, cond ast.Expr) error {
func setStepIntoBreakpoint(dbp Continuable, text []AsmInstruction, cond ast.Expr) error {
if len(text) <= 0 {
return nil
}
......@@ -337,7 +340,7 @@ func (dbp *Process) setStepIntoBreakpoint(text []AsmInstruction, cond ast.Expr)
// setInternalBreakpoints sets a breakpoint to all addresses specified in pcs
// skipping over curpc and curpc-1
func (dbp *Process) setInternalBreakpoints(curpc uint64, pcs []uint64, kind BreakpointKind, cond ast.Expr) error {
func setInternalBreakpoints(dbp Continuable, curpc uint64, pcs []uint64, kind BreakpointKind, cond ast.Expr) error {
for i := range pcs {
if pcs[i] == curpc || pcs[i] == curpc-1 {
continue
......@@ -495,7 +498,7 @@ func (thread *Thread) SetCurrentBreakpoint() error {
return err
}
thread.BreakpointConditionMet, thread.BreakpointConditionError = bp.checkCondition(thread)
if thread.onTriggeredBreakpoint() {
if thread.CurrentBreakpoint != nil && thread.BreakpointConditionMet {
if g, err := GetG(thread); err == nil {
thread.CurrentBreakpoint.HitCount[g.ID]++
}
......@@ -511,15 +514,7 @@ func (thread *Thread) clearBreakpointState() {
thread.BreakpointConditionError = nil
}
func (thread *Thread) onTriggeredBreakpoint() bool {
return (thread.CurrentBreakpoint != nil) && thread.BreakpointConditionMet
}
func (thread *Thread) onTriggeredInternalBreakpoint() bool {
return thread.onTriggeredBreakpoint() && thread.CurrentBreakpoint.Internal()
}
func (thread *Thread) onRuntimeBreakpoint() bool {
func onRuntimeBreakpoint(thread IThread) bool {
loc, err := thread.Location()
if err != nil {
return false
......@@ -528,11 +523,11 @@ func (thread *Thread) onRuntimeBreakpoint() bool {
}
// onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command
func (thread *Thread) onNextGoroutine() (bool, error) {
func onNextGoroutine(thread IThread, breakpoints map[uint64]*Breakpoint) (bool, error) {
var bp *Breakpoint
for i := range thread.dbp.breakpoints {
if thread.dbp.breakpoints[i].Internal() {
bp = thread.dbp.breakpoints[i]
for i := range breakpoints {
if breakpoints[i].Internal() {
bp = breakpoints[i]
break
}
}
......
......@@ -81,13 +81,14 @@ func (t *Thread) resume() error {
return nil
}
func (t *Thread) blocked() bool {
func threadBlocked(t IThread) bool {
// TODO(dp) cache the func pc to remove this lookup
pc, err := t.PC()
regs, err := t.Registers(false)
if err != nil {
return false
}
fn := t.dbp.bi.goSymTable.PCToFunc(pc)
pc := regs.PC()
fn := t.BinInfo().goSymTable.PCToFunc(pc)
if fn == nil {
return false
}
......
......@@ -67,9 +67,13 @@ func (t *Thread) singleStep() (err error) {
}
}
func (t *Thread) blocked() bool {
pc, _ := t.PC()
fn := t.dbp.bi.goSymTable.PCToFunc(pc)
func threadBlocked(t IThread) bool {
regs, err := t.Registers(false)
if err != nil {
return false
}
pc := regs.PC()
fn := t.BinInfo().goSymTable.PCToFunc(pc)
if fn != nil && ((fn.Name == "runtime.futex") || (fn.Name == "runtime.usleep") || (fn.Name == "runtime.clone")) {
return true
}
......
......@@ -103,14 +103,15 @@ func (t *Thread) resume() error {
return err
}
func (t *Thread) blocked() bool {
func threadBlocked(t IThread) bool {
// TODO: Probably incorrect - what are the runtime functions that
// indicate blocking on Windows?
pc, err := t.PC()
regs, err := t.Registers(false)
if err != nil {
return false
}
fn := t.dbp.bi.goSymTable.PCToFunc(pc)
pc := regs.PC()
fn := t.BinInfo().goSymTable.PCToFunc(pc)
if fn == nil {
return false
}
......
......@@ -60,16 +60,12 @@ type ThreadInfo interface {
// GoroutineInfo is an interface for getting information on running goroutines.
type GoroutineInfo interface {
GoroutinesInfo() ([]*proc.G, error)
SelectedGoroutine() *proc.G
}
// ProcessManipulation is an interface for changing the execution state of a process.
type ProcessManipulation interface {
Continue() error
Next() error
Step() error
StepOut() error
ContinueOnce() (trapthread proc.IThread, err error)
StepInstruction() error
SwitchThread(int) error
SwitchGoroutine(int) error
......
......@@ -412,7 +412,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
switch command.Name {
case api.Continue:
log.Print("continuing")
err = d.target.Continue()
err = proc.Continue(d.target)
if err != nil {
if exitedErr, exited := err.(proc.ProcessExitedError); exited {
state := &api.DebuggerState{}
......@@ -432,16 +432,16 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
case api.Next:
log.Print("nexting")
err = d.target.Next()
err = proc.Next(d.target)
case api.Step:
log.Print("stepping")
err = d.target.Step()
err = proc.Step(d.target)
case api.StepInstruction:
log.Print("single stepping")
err = d.target.StepInstruction()
case api.StepOut:
log.Print("step out")
err = d.target.StepOut()
err = proc.StepOut(d.target)
case api.SwitchThread:
log.Printf("switching to thread %d", command.ThreadID)
err = d.target.SwitchThread(command.ThreadID)
......@@ -714,7 +714,7 @@ func (d *Debugger) Goroutines() ([]*api.Goroutine, error) {
defer d.processMutex.Unlock()
goroutines := []*api.Goroutine{}
gs, err := d.target.GoroutinesInfo()
gs, err := proc.GoroutinesInfo(d.target)
if err != nil {
return nil, err
}
......
......@@ -138,7 +138,7 @@ func TestVariableEvaluation(t *testing.T) {
}
withTestProcess("testvariables", t, func(p *proc.Process, fixture protest.Fixture) {
err := p.Continue()
err := proc.Continue(p)
assertNoError(err, t, "Continue() returned an error")
for _, tc := range testcases {
......@@ -216,7 +216,7 @@ func TestVariableEvaluationShort(t *testing.T) {
}
withTestProcess("testvariables", t, func(p *proc.Process, fixture protest.Fixture) {
err := p.Continue()
err := proc.Continue(p)
assertNoError(err, t, "Continue() returned an error")
for _, tc := range testcases {
......@@ -271,7 +271,7 @@ func TestMultilineVariableEvaluation(t *testing.T) {
}
withTestProcess("testvariables", t, func(p *proc.Process, fixture protest.Fixture) {
err := p.Continue()
err := proc.Continue(p)
assertNoError(err, t, "Continue() returned an error")
for _, tc := range testcases {
......@@ -344,7 +344,7 @@ func TestLocalVariables(t *testing.T) {
}
withTestProcess("testvariables", t, func(p *proc.Process, fixture protest.Fixture) {
err := p.Continue()
err := proc.Continue(p)
assertNoError(err, t, "Continue() returned an error")
for _, tc := range testcases {
......@@ -377,7 +377,7 @@ func TestEmbeddedStruct(t *testing.T) {
{"b.s", true, "\"hello\"", "\"hello\"", "string", nil},
{"b2", true, "main.B {main.A: main.A {val: 42}, *main.C: *main.C nil, a: main.A {val: 47}, ptr: *main.A nil}", "main.B {main.A: (*main.A)(0x…", "main.B", nil},
}
assertNoError(p.Continue(), t, "Continue()")
assertNoError(proc.Continue(p), t, "Continue()")
for _, tc := range testcases {
variable, err := evalVariable(p, tc.name, pnormalLoadConfig)
......@@ -398,7 +398,7 @@ func TestEmbeddedStruct(t *testing.T) {
func TestComplexSetting(t *testing.T) {
withTestProcess("testvariables", t, func(p *proc.Process, fixture protest.Fixture) {
err := p.Continue()
err := proc.Continue(p)
assertNoError(err, t, "Continue() returned an error")
h := func(setExpr, value string) {
......@@ -644,7 +644,7 @@ func TestEvalExpression(t *testing.T) {
}
withTestProcess("testvariables2", t, func(p *proc.Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue() returned an error")
assertNoError(proc.Continue(p), t, "Continue() returned an error")
for _, tc := range testcases {
variable, err := evalVariable(p, tc.name, pnormalLoadConfig)
if tc.err == nil {
......@@ -668,7 +668,7 @@ func TestEvalExpression(t *testing.T) {
func TestEvalAddrAndCast(t *testing.T) {
withTestProcess("testvariables2", t, func(p *proc.Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue() returned an error")
assertNoError(proc.Continue(p), t, "Continue() returned an error")
c1addr, err := evalVariable(p, "&c1", pnormalLoadConfig)
assertNoError(err, t, "EvalExpression(&c1)")
c1addrstr := api.ConvertVar(c1addr).SinglelineString()
......@@ -694,7 +694,7 @@ func TestEvalAddrAndCast(t *testing.T) {
func TestMapEvaluation(t *testing.T) {
withTestProcess("testvariables2", t, func(p *proc.Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue() returned an error")
assertNoError(proc.Continue(p), t, "Continue() returned an error")
m1v, err := evalVariable(p, "m1", pnormalLoadConfig)
assertNoError(err, t, "EvalVariable()")
m1 := api.ConvertVar(m1v)
......@@ -728,7 +728,7 @@ func TestMapEvaluation(t *testing.T) {
func TestUnsafePointer(t *testing.T) {
withTestProcess("testvariables2", t, func(p *proc.Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue() returned an error")
assertNoError(proc.Continue(p), t, "Continue() returned an error")
up1v, err := evalVariable(p, "up1", pnormalLoadConfig)
assertNoError(err, t, "EvalVariable(up1)")
up1 := api.ConvertVar(up1v)
......@@ -765,7 +765,7 @@ func TestIssue426(t *testing.T) {
// Serialization of type expressions (go/ast.Expr) containing anonymous structs or interfaces
// differs from the serialization used by the linker to produce DWARF type information
withTestProcess("testvariables2", t, func(p *proc.Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue() returned an error")
assertNoError(proc.Continue(p), t, "Continue() returned an error")
for _, testcase := range testcases {
v, err := evalVariable(p, testcase.name, pnormalLoadConfig)
assertNoError(err, t, fmt.Sprintf("EvalVariable(%s)", testcase.name))
......@@ -816,7 +816,7 @@ func TestPackageRenames(t *testing.T) {
}
withTestProcess("pkgrenames", t, func(p *proc.Process, fixture protest.Fixture) {
assertNoError(p.Continue(), t, "Continue() returned an error")
assertNoError(proc.Continue(p), t, "Continue() returned an error")
for _, tc := range testcases {
variable, err := evalVariable(p, tc.name, pnormalLoadConfig)
if tc.err == nil {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册