1
0
mirror of https://github.com/beego/bee.git synced 2025-02-19 14:27:12 +00:00

Use Delve v0.12.1 instead of master

This commit is contained in:
Faissal Elamraoui 2017-03-26 16:55:28 +02:00
parent abf3c41032
commit 4dd6983d3c
67 changed files with 448 additions and 925 deletions

View File

@ -7,7 +7,7 @@ import (
"bytes"
"encoding/binary"
"github.com/derekparker/delve/pkg/dwarf/util"
"github.com/derekparker/delve/dwarf/util"
)
type parsefunc func(*parseContext) parsefunc

View File

@ -5,7 +5,7 @@ import (
"encoding/binary"
"fmt"
"github.com/derekparker/delve/pkg/dwarf/util"
"github.com/derekparker/delve/dwarf/util"
)
type CurrentFrameAddress struct {

View File

@ -4,7 +4,7 @@ import (
"bytes"
"encoding/binary"
"github.com/derekparker/delve/pkg/dwarf/util"
"github.com/derekparker/delve/dwarf/util"
)
type DebugLinePrologue struct {

View File

@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"github.com/derekparker/delve/pkg/dwarf/util"
"github.com/derekparker/delve/dwarf/util"
)
type Location struct {
@ -27,11 +27,6 @@ type StateMachine struct {
endSeq bool
lastWasStandard bool
lastDelta int
// valid is true if the current value of the state machine is the address of
// an instruction (using the terminology used by DWARF spec the current
// value of the state machine should be appended to the matrix representing
// the compilation unit)
valid bool
}
type opcodefn func(*StateMachine, *bytes.Buffer)
@ -96,9 +91,7 @@ func (dbl *DebugLines) AllPCsForFileLine(f string, l int) (pcs []uint64) {
}
if sm.line == l && sm.file == f && sm.address != lastAddr {
foundFile = true
if sm.valid {
pcs = append(pcs, sm.address)
}
pcs = append(pcs, sm.address)
line := sm.line
// Keep going until we're on a different line. We only care about
// when a line comes back around (i.e. for loop) so get to next line,
@ -130,9 +123,6 @@ func (dbl *DebugLines) AllPCsBetween(begin, end uint64, filename string) ([]uint
for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() {
findAndExecOpcode(sm, buf, b)
if !sm.valid {
continue
}
if sm.address > end {
break
}
@ -167,10 +157,9 @@ func execSpecialOpcode(sm *StateMachine, instr byte) {
sm.lastDelta = int(sm.dbl.Prologue.LineBase + int8(decoded%sm.dbl.Prologue.LineRange))
sm.line += sm.lastDelta
sm.address += uint64(decoded/sm.dbl.Prologue.LineRange) * uint64(sm.dbl.Prologue.MinInstrLength)
sm.address += uint64(decoded / sm.dbl.Prologue.LineRange)
sm.basicBlock = false
sm.lastWasStandard = false
sm.valid = true
}
func execExtendedOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) {
@ -181,7 +170,6 @@ func execExtendedOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) {
panic(fmt.Sprintf("Encountered unknown extended opcode %#v\n", b))
}
sm.lastWasStandard = false
sm.valid = false
fn(sm, buf)
}
@ -192,14 +180,12 @@ func execStandardOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) {
panic(fmt.Sprintf("Encountered unknown standard opcode %#v\n", instr))
}
sm.lastWasStandard = true
sm.valid = false
fn(sm, buf)
}
func copyfn(sm *StateMachine, buf *bytes.Buffer) {
sm.basicBlock = false
sm.valid = true
}
func advancepc(sm *StateMachine, buf *bytes.Buffer) {
@ -232,7 +218,7 @@ func setbasicblock(sm *StateMachine, buf *bytes.Buffer) {
}
func constaddpc(sm *StateMachine, buf *bytes.Buffer) {
sm.address += uint64((255-sm.dbl.Prologue.OpcodeBase)/sm.dbl.Prologue.LineRange) * uint64(sm.dbl.Prologue.MinInstrLength)
sm.address += (255 / uint64(sm.dbl.Prologue.LineRange))
}
func fixedadvancepc(sm *StateMachine, buf *bytes.Buffer) {
@ -244,7 +230,6 @@ func fixedadvancepc(sm *StateMachine, buf *bytes.Buffer) {
func endsequence(sm *StateMachine, buf *bytes.Buffer) {
sm.endSeq = true
sm.valid = true
}
func setaddress(sm *StateMachine, buf *bytes.Buffer) {

View File

@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"github.com/derekparker/delve/pkg/dwarf/util"
"github.com/derekparker/delve/dwarf/util"
)
const (

View File

@ -4,8 +4,8 @@ import (
"errors"
"fmt"
"github.com/derekparker/delve/pkg/dwarf/op"
"golang.org/x/debug/dwarf"
"github.com/derekparker/delve/dwarf/op"
)
type Reader struct {

View File

@ -1,84 +0,0 @@
package target
import (
"debug/gosym"
"go/ast"
"time"
"github.com/derekparker/delve/pkg/proc"
)
// Target represents the target of the debugger. This
// target could be a system process, core file, etc.
type Interface interface {
Info
ProcessManipulation
BreakpointManipulation
VariableEval
}
// Info is an interface that provides general information on the target.
type Info interface {
Pid() int
Exited() bool
Running() bool
BinaryInfo
ThreadInfo
GoroutineInfo
}
// BinaryInfo is an interface for accessing information on the binary file
// and the contents of binary sections.
type BinaryInfo interface {
LastModified() time.Time
Sources() map[string]*gosym.Obj
FindFileLocation(fileName string, lineNumber int) (uint64, error)
FindFunctionLocation(funcName string, firstLine bool, lineOffset int) (uint64, error)
Funcs() []gosym.Func
Types() ([]string, error)
PCToLine(uint64) (string, int, *gosym.Func)
FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error)
}
// ThreadInfo is an interface for getting information on active threads
// in the process.
type ThreadInfo interface {
Threads() map[int]*proc.Thread
CurrentThread() *proc.Thread
}
// GoroutineInfo is an interface for getting information on running goroutines.
type GoroutineInfo interface {
GoroutinesInfo() ([]*proc.G, error)
SelectedGoroutine() *proc.G
FindGoroutine(int) (*proc.G, error)
}
// ProcessManipulation is an interface for changing the execution state of a process.
type ProcessManipulation interface {
Continue() error
Next() error
Step() error
StepOut() error
StepInstruction() error
SwitchThread(int) error
SwitchGoroutine(int) error
RequestManualStop() error
Halt() error
Kill() error
Detach(bool) error
}
// BreakpointManipulation is an interface for managing breakpoints.
type BreakpointManipulation interface {
Breakpoints() map[uint64]*proc.Breakpoint
SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error)
ClearBreakpoint(addr uint64) (*proc.Breakpoint, error)
ClearInternalBreakpoints() error
}
// VariableEval is an interface for dealing with eval scopes.
type VariableEval interface {
ConvertEvalScope(gid, frame int) (*proc.EvalScope, error)
}

View File

@ -41,7 +41,7 @@ func (thread *Thread) Disassemble(startPC, endPC uint64, currentGoroutine bool)
}
for len(mem) > 0 {
bp, atbp := thread.dbp.breakpoints[pc]
bp, atbp := thread.dbp.Breakpoints[pc]
if atbp {
for i := range bp.OriginalData {
mem[i] = bp.OriginalData[i]

View File

@ -3,7 +3,6 @@ package proc
import (
"debug/gosym"
"encoding/binary"
"rsc.io/x86/x86asm"
)
@ -146,7 +145,7 @@ func init() {
// FirstPCAfterPrologue returns the address of the first instruction after the prologue for function fn
// If sameline is set FirstPCAfterPrologue will always return an address associated with the same line as fn.Entry
func (dbp *Process) FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error) {
text, err := dbp.CurrentThread().Disassemble(fn.Entry, fn.End, false)
text, err := dbp.CurrentThread.Disassemble(fn.Entry, fn.End, false)
if err != nil {
return fn.Entry, err
}

View File

@ -3,7 +3,6 @@ package proc
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"go/ast"
"go/constant"
@ -12,12 +11,10 @@ import (
"go/token"
"reflect"
"github.com/derekparker/delve/pkg/dwarf/reader"
"github.com/derekparker/delve/dwarf/reader"
"golang.org/x/debug/dwarf"
)
var OperationOnSpecialFloatError = errors.New("operations on non-finite floats not implemented")
// EvalExpression returns the value of the given expression.
func (scope *EvalScope) EvalExpression(expr string, cfg LoadConfig) (*Variable, error) {
t, err := parser.ParseExpr(expr)
@ -691,9 +688,6 @@ func (scope *EvalScope) evalUnary(node *ast.UnaryExpr) (*Variable, error) {
if xv.Unreadable != nil {
return nil, xv.Unreadable
}
if xv.FloatSpecial != 0 {
return nil, OperationOnSpecialFloatError
}
if xv.Value == nil {
return nil, fmt.Errorf("operator %s can not be applied to \"%s\"", node.Op.String(), exprToString(node.X))
}
@ -800,10 +794,6 @@ func (scope *EvalScope) evalBinary(node *ast.BinaryExpr) (*Variable, error) {
return nil, yv.Unreadable
}
if xv.FloatSpecial != 0 || yv.FloatSpecial != 0 {
return nil, OperationOnSpecialFloatError
}
typ, err := negotiateType(node.Op, xv, yv)
if err != nil {
return nil, err

View File

@ -16,10 +16,6 @@ type GoVersion struct {
RC int
}
var (
GoVer18Beta = GoVersion{1, 8, -1, 0, 0}
)
func ParseVersionString(ver string) (GoVersion, bool) {
var r GoVersion
var err1, err2, err3 error

View File

@ -13,7 +13,7 @@ type moduleData struct {
func (dbp *Process) loadModuleData() (err error) {
dbp.loadModuleDataOnce.Do(func() {
scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0}
scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0}
var md *Variable
md, err = scope.packageVarAddr("runtime.firstmoduledata")
if err != nil {
@ -84,13 +84,13 @@ func (dbp *Process) resolveTypeOff(typeAddr uintptr, off uintptr) (*Variable, er
return v.newVariable(v.Name, uintptr(addr), rtyp), nil
}
if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.currentThread)); t != nil {
if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread)); t != nil {
return t, nil
}
res := md.types + uintptr(off)
return dbp.currentThread.newVariable("", res, rtyp), nil
return dbp.CurrentThread.newVariable("", res, rtyp), nil
}
func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (name, tag string, pkgpathoff int32, err error) {
@ -119,7 +119,7 @@ func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (name, tag str
}
func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) {
scope := &EvalScope{Thread: dbp.currentThread, PC: 0, CFA: 0}
scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0}
reflectOffs, err := scope.packageVarAddr("runtime.reflectOffs")
if err != nil {
return nil, err
@ -130,7 +130,7 @@ func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) {
return nil, err
}
return reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.currentThread))
return reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread))
}
const (
@ -142,7 +142,7 @@ const (
func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32, err error) {
off := addr
namedata, err := dbp.currentThread.readMemory(off, 3)
namedata, err := dbp.CurrentThread.readMemory(off, 3)
off += 3
if err != nil {
return "", "", 0, err
@ -150,7 +150,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
namelen := uint16(namedata[1]<<8) | uint16(namedata[2])
rawstr, err := dbp.currentThread.readMemory(off, int(namelen))
rawstr, err := dbp.CurrentThread.readMemory(off, int(namelen))
off += uintptr(namelen)
if err != nil {
return "", "", 0, err
@ -159,14 +159,14 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
name = string(rawstr)
if namedata[0]&nameflagHasTag != 0 {
taglendata, err := dbp.currentThread.readMemory(off, 2)
taglendata, err := dbp.CurrentThread.readMemory(off, 2)
off += 2
if err != nil {
return "", "", 0, err
}
taglen := uint16(taglendata[0]<<8) | uint16(taglendata[1])
rawstr, err := dbp.currentThread.readMemory(off, int(taglen))
rawstr, err := dbp.CurrentThread.readMemory(off, int(taglen))
off += uintptr(taglen)
if err != nil {
return "", "", 0, err
@ -176,7 +176,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
}
if namedata[0]&nameflagHasPkg != 0 {
pkgdata, err := dbp.currentThread.readMemory(off, 4)
pkgdata, err := dbp.CurrentThread.readMemory(off, 4)
if err != nil {
return "", "", 0, err
}

View File

@ -16,32 +16,32 @@ import (
"sync"
"time"
"github.com/derekparker/delve/pkg/dwarf/frame"
"github.com/derekparker/delve/pkg/dwarf/line"
"github.com/derekparker/delve/pkg/dwarf/reader"
"github.com/derekparker/delve/dwarf/frame"
"github.com/derekparker/delve/dwarf/line"
"github.com/derekparker/delve/dwarf/reader"
"golang.org/x/debug/dwarf"
)
// Process represents all of the information the debugger
// is holding onto regarding the process we are debugging.
type Process struct {
pid int // Process Pid
Pid int // Process Pid
Process *os.Process // Pointer to process struct for the actual process we are debugging
lastModified time.Time // Time the executable of this process was last modified
LastModified time.Time // Time the executable of this process was last modified
// Breakpoint table, holds information on breakpoints.
// Maps instruction address to Breakpoint struct.
breakpoints map[uint64]*Breakpoint
Breakpoints map[uint64]*Breakpoint
// List of threads mapped as such: pid -> *Thread
threads map[int]*Thread
Threads map[int]*Thread
// Active thread
currentThread *Thread
CurrentThread *Thread
// Goroutine that will be used by default to set breakpoint, eval variables, etc...
// Normally selectedGoroutine is currentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
selectedGoroutine *G
// Normally SelectedGoroutine is CurrentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
SelectedGoroutine *G
// Maps package names to package paths, needed to lookup types inside DWARF info
packageMap map[string]string
@ -61,18 +61,12 @@ type Process struct {
ptraceChan chan func()
ptraceDoneChan chan interface{}
types map[string]dwarf.Offset
functions []functionDebugInfo
loadModuleDataOnce sync.Once
moduleData []moduleData
nameOfRuntimeType map[uintptr]nameOfRuntimeTypeEntry
}
type functionDebugInfo struct {
lowpc, highpc uint64
offset dwarf.Offset
}
var NotExecutableErr = errors.New("not an executable file")
// New returns an initialized Process struct. Before returning,
@ -81,9 +75,9 @@ var NotExecutableErr = errors.New("not an executable file")
// `handlePtraceFuncs`.
func New(pid int) *Process {
dbp := &Process{
pid: pid,
threads: make(map[int]*Thread),
breakpoints: make(map[uint64]*Breakpoint),
Pid: pid,
Threads: make(map[int]*Thread),
Breakpoints: make(map[uint64]*Breakpoint),
firstStart: true,
os: new(OSProcessDetails),
ptraceChan: make(chan func()),
@ -112,9 +106,6 @@ func (pe ProcessExitedError) Error() string {
// Detach from the process being debugged, optionally killing it.
func (dbp *Process) Detach(kill bool) (err error) {
if dbp.exited {
return nil
}
if dbp.Running() {
if err = dbp.Halt(); err != nil {
return
@ -122,7 +113,7 @@ func (dbp *Process) Detach(kill bool) (err error) {
}
if !kill {
// Clean up any breakpoints we've set.
for _, bp := range dbp.breakpoints {
for _, bp := range dbp.Breakpoints {
if bp != nil {
_, err := dbp.ClearBreakpoint(bp.Addr)
if err != nil {
@ -132,12 +123,12 @@ func (dbp *Process) Detach(kill bool) (err error) {
}
}
dbp.execPtraceFunc(func() {
err = PtraceDetach(dbp.pid, 0)
err = PtraceDetach(dbp.Pid, 0)
if err != nil {
return
}
if kill {
err = killProcess(dbp.pid)
err = killProcess(dbp.Pid)
}
})
return
@ -152,7 +143,7 @@ func (dbp *Process) Exited() bool {
// Running returns whether the debugged
// process is currently executing.
func (dbp *Process) Running() bool {
for _, th := range dbp.threads {
for _, th := range dbp.Threads {
if th.running {
return true
}
@ -160,30 +151,6 @@ func (dbp *Process) Running() bool {
return false
}
func (dbp *Process) LastModified() time.Time {
return dbp.lastModified
}
func (dbp *Process) Pid() int {
return dbp.pid
}
func (dbp *Process) SelectedGoroutine() *G {
return dbp.selectedGoroutine
}
func (dbp *Process) Threads() map[int]*Thread {
return dbp.threads
}
func (dbp *Process) CurrentThread() *Thread {
return dbp.currentThread
}
func (dbp *Process) Breakpoints() map[uint64]*Breakpoint {
return dbp.breakpoints
}
// LoadInformation finds the executable and then uses it
// to parse the following information:
// * Dwarf .debug_frame section
@ -198,7 +165,7 @@ func (dbp *Process) LoadInformation(path string) error {
}
fi, err := os.Stat(path)
if err == nil {
dbp.lastModified = fi.ModTime()
dbp.LastModified = fi.ModTime()
}
wg.Add(5)
@ -206,7 +173,7 @@ func (dbp *Process) LoadInformation(path string) error {
go dbp.parseDebugFrame(exe, &wg)
go dbp.obtainGoSymbols(exe, &wg)
go dbp.parseDebugLineInfo(exe, &wg)
go dbp.loadDebugInfoMaps(&wg)
go dbp.loadTypeMap(&wg)
wg.Wait()
return nil
@ -250,7 +217,7 @@ func (dbp *Process) FindFunctionLocation(funcName string, firstLine bool, lineOf
// CurrentLocation returns the location of the current thread.
func (dbp *Process) CurrentLocation() (*Location, error) {
return dbp.currentThread.Location()
return dbp.CurrentThread.Location()
}
// RequestManualStop sets the `halt` flag and
@ -267,7 +234,7 @@ func (dbp *Process) RequestManualStop() error {
// break point table. Setting a break point must be thread specific due to
// ptrace actions needing the thread to be in a signal-delivery-stop.
func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) {
tid := dbp.currentThread.ID
tid := dbp.CurrentThread.ID
if bp, ok := dbp.FindBreakpoint(addr); ok {
return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
@ -296,7 +263,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp
newBreakpoint.ID = dbp.breakpointIDCounter
}
thread := dbp.threads[tid]
thread := dbp.Threads[tid]
originalData, err := thread.readMemory(uintptr(addr), dbp.arch.BreakpointSize())
if err != nil {
return nil, err
@ -305,7 +272,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp
return nil, err
}
newBreakpoint.OriginalData = originalData
dbp.breakpoints[addr] = newBreakpoint
dbp.Breakpoints[addr] = newBreakpoint
return newBreakpoint, nil
}
@ -320,18 +287,18 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*Breakpoint, error) {
return nil, NoBreakpointError{addr: addr}
}
if _, err := bp.Clear(dbp.currentThread); err != nil {
if _, err := bp.Clear(dbp.CurrentThread); err != nil {
return nil, err
}
delete(dbp.breakpoints, addr)
delete(dbp.Breakpoints, addr)
return bp, nil
}
// Status returns the status of the current main thread context.
func (dbp *Process) Status() *WaitStatus {
return dbp.currentThread.Status
return dbp.CurrentThread.Status
}
// Next continues execution until the next source line.
@ -339,8 +306,8 @@ func (dbp *Process) Next() (err error) {
if dbp.exited {
return &ProcessExitedError{}
}
for i := range dbp.breakpoints {
if dbp.breakpoints[i].Internal() {
for i := range dbp.Breakpoints {
if dbp.Breakpoints[i].Internal() {
return fmt.Errorf("next while nexting")
}
}
@ -370,7 +337,7 @@ func (dbp *Process) Continue() error {
}
dbp.allGCache = nil
for _, th := range dbp.threads {
for _, th := range dbp.Threads {
th.clearBreakpointState()
}
@ -389,42 +356,34 @@ func (dbp *Process) Continue() error {
}
switch {
case dbp.currentThread.CurrentBreakpoint == nil:
case dbp.CurrentThread.CurrentBreakpoint == nil:
// runtime.Breakpoint or manual stop
if dbp.currentThread.onRuntimeBreakpoint() {
// 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 dbp.CurrentThread.onRuntimeBreakpoint() {
for i := 0; i < 2; i++ {
if err = dbp.CurrentThread.StepInstruction(); err != nil {
return err
}
loc, err := dbp.currentThread.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 {
case dbp.CurrentThread.onTriggeredInternalBreakpoint():
if dbp.CurrentThread.CurrentBreakpoint.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()
pc, err := dbp.CurrentThread.PC()
if err != nil {
return err
}
text, err := dbp.currentThread.Disassemble(pc, pc+maxInstructionLength, true)
text, err := dbp.CurrentThread.Disassemble(pc, pc+maxInstructionLength, true)
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 = dbp.setStepIntoBreakpoint(text, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil {
return err
}
} else {
@ -433,8 +392,8 @@ func (dbp *Process) Continue() error {
}
return dbp.conditionErrors()
}
case dbp.currentThread.onTriggeredBreakpoint():
onNextGoroutine, err := dbp.currentThread.onNextGoroutine()
case dbp.CurrentThread.onTriggeredBreakpoint():
onNextGoroutine, err := dbp.CurrentThread.onNextGoroutine()
if err != nil {
return err
}
@ -453,7 +412,7 @@ func (dbp *Process) Continue() error {
func (dbp *Process) conditionErrors() error {
var condErr error
for _, th := range dbp.threads {
for _, th := range dbp.Threads {
if th.CurrentBreakpoint != nil && th.BreakpointConditionError != nil {
if condErr == nil {
condErr = th.BreakpointConditionError
@ -465,12 +424,12 @@ func (dbp *Process) conditionErrors() error {
return condErr
}
// pick a new dbp.currentThread, with the following priority:
// pick a new dbp.CurrentThread, with the following priority:
// - 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 {
for _, th := range dbp.Threads {
if th.onTriggeredInternalBreakpoint() {
return dbp.SwitchThread(th.ID)
}
@ -478,7 +437,7 @@ func (dbp *Process) pickCurrentThread(trapthread *Thread) error {
if trapthread.onTriggeredBreakpoint() {
return dbp.SwitchThread(trapthread.ID)
}
for _, th := range dbp.threads {
for _, th := range dbp.Threads {
if th.onTriggeredBreakpoint() {
return dbp.SwitchThread(th.ID)
}
@ -492,8 +451,8 @@ func (dbp *Process) Step() (err error) {
if dbp.exited {
return &ProcessExitedError{}
}
for i := range dbp.breakpoints {
if dbp.breakpoints[i].Internal() {
for i := range dbp.Breakpoints {
if dbp.Breakpoints[i].Internal() {
return fmt.Errorf("next while nexting")
}
}
@ -533,12 +492,12 @@ func sameGoroutineCondition(g *G) ast.Expr {
// asssociated with the selected goroutine. All other
// threads will remain stopped.
func (dbp *Process) StepInstruction() (err error) {
if dbp.selectedGoroutine == nil {
if dbp.SelectedGoroutine == nil {
return errors.New("cannot single step: no selected goroutine")
}
if dbp.selectedGoroutine.thread == nil {
if dbp.SelectedGoroutine.thread == nil {
// Step called on parked goroutine
if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.selectedGoroutine)); err != nil {
if _, err := dbp.SetBreakpoint(dbp.SelectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil {
return err
}
return dbp.Continue()
@ -547,20 +506,20 @@ func (dbp *Process) StepInstruction() (err error) {
if dbp.exited {
return &ProcessExitedError{}
}
dbp.selectedGoroutine.thread.clearBreakpointState()
err = dbp.selectedGoroutine.thread.StepInstruction()
dbp.SelectedGoroutine.thread.clearBreakpointState()
err = dbp.SelectedGoroutine.thread.StepInstruction()
if err != nil {
return err
}
return dbp.selectedGoroutine.thread.SetCurrentBreakpoint()
return dbp.SelectedGoroutine.thread.SetCurrentBreakpoint()
}
// 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)
cond := sameGoroutineCondition(dbp.SelectedGoroutine)
topframe, err := topframe(dbp.selectedGoroutine, dbp.currentThread)
topframe, err := topframe(dbp.SelectedGoroutine, dbp.CurrentThread)
if err != nil {
return err
}
@ -569,16 +528,13 @@ 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 deferPCEntry != 0 {
_, _, deferfn := dbp.goSymTable.PCToLine(deferPCEntry)
deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false)
if err != nil {
return err
}
pcs = append(pcs, deferpc)
if dbp.SelectedGoroutine != nil && dbp.SelectedGoroutine.DeferPC != 0 {
_, _, deferfn := dbp.goSymTable.PCToLine(dbp.SelectedGoroutine.DeferPC)
deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false)
if err != nil {
return err
}
pcs = append(pcs, deferpc)
}
}
@ -616,9 +572,9 @@ func (dbp *Process) SwitchThread(tid int) error {
if dbp.exited {
return &ProcessExitedError{}
}
if th, ok := dbp.threads[tid]; ok {
dbp.currentThread = th
dbp.selectedGoroutine, _ = dbp.currentThread.GetG()
if th, ok := dbp.Threads[tid]; ok {
dbp.CurrentThread = th
dbp.SelectedGoroutine, _ = dbp.CurrentThread.GetG()
return nil
}
return fmt.Errorf("thread %d does not exist", tid)
@ -635,13 +591,13 @@ func (dbp *Process) SwitchGoroutine(gid int) error {
return err
}
if g == nil {
// user specified -1 and selectedGoroutine is nil
// user specified -1 and SelectedGoroutine is nil
return nil
}
if g.thread != nil {
return dbp.SwitchThread(g.thread.ID)
}
dbp.selectedGoroutine = g
dbp.SelectedGoroutine = g
return nil
}
@ -661,13 +617,13 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
rdr = dbp.DwarfReader()
)
for i := range dbp.threads {
if dbp.threads[i].blocked() {
for i := range dbp.Threads {
if dbp.Threads[i].blocked() {
continue
}
g, _ := dbp.threads[i].GetG()
g, _ := dbp.Threads[i].GetG()
if g != nil {
threadg[g.ID] = dbp.threads[i]
threadg[g.ID] = dbp.Threads[i]
}
}
@ -675,7 +631,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
}
@ -690,11 +646,11 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
return nil, err
}
}
faddr, err := dbp.currentThread.readMemory(uintptr(allgentryaddr), dbp.arch.PtrSize())
faddr, err := dbp.CurrentThread.readMemory(uintptr(allgentryaddr), dbp.arch.PtrSize())
allgptr := binary.LittleEndian.Uint64(faddr)
for i := uint64(0); i < allglen; i++ {
gvar, err := dbp.currentThread.newGVariable(uintptr(allgptr+(i*uint64(dbp.arch.PtrSize()))), true)
gvar, err := dbp.CurrentThread.newGVariable(uintptr(allgptr+(i*uint64(dbp.arch.PtrSize()))), true)
if err != nil {
return nil, err
}
@ -728,7 +684,7 @@ func (dbp *Process) Halt() (err error) {
if dbp.exited {
return &ProcessExitedError{}
}
for _, th := range dbp.threads {
for _, th := range dbp.Threads {
if err := th.Halt(); err != nil {
return err
}
@ -739,18 +695,18 @@ func (dbp *Process) Halt() (err error) {
// Registers obtains register values from the
// "current" thread of the traced process.
func (dbp *Process) Registers() (Registers, error) {
return dbp.currentThread.Registers(false)
return dbp.CurrentThread.Registers(false)
}
// PC returns the PC of the current thread.
func (dbp *Process) PC() (uint64, error) {
return dbp.currentThread.PC()
return dbp.CurrentThread.PC()
}
// CurrentBreakpoint returns the breakpoint the current thread
// is stopped at.
func (dbp *Process) CurrentBreakpoint() *Breakpoint {
return dbp.currentThread.CurrentBreakpoint
return dbp.CurrentThread.CurrentBreakpoint
}
// DwarfReader returns a reader for the dwarf data
@ -784,7 +740,7 @@ func (dbp *Process) PCToLine(pc uint64) (string, int, *gosym.Func) {
// FindBreakpointByID finds the breakpoint for the given ID.
func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) {
for _, bp := range dbp.breakpoints {
for _, bp := range dbp.Breakpoints {
if bp.ID == id {
return bp, true
}
@ -795,11 +751,11 @@ func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) {
// FindBreakpoint finds the breakpoint for the given pc.
func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
if bp, ok := dbp.breakpoints[pc-uint64(dbp.arch.BreakpointSize())]; ok {
if bp, ok := dbp.Breakpoints[pc-uint64(dbp.arch.BreakpointSize())]; ok {
return bp, true
}
// Directly use addr to lookup breakpoint.
if bp, ok := dbp.breakpoints[pc]; ok {
if bp, ok := dbp.Breakpoints[pc]; ok {
return bp, true
}
return nil, false
@ -809,17 +765,17 @@ func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, error) {
if attach {
var err error
dbp.execPtraceFunc(func() { err = PtraceAttach(dbp.pid) })
dbp.execPtraceFunc(func() { err = PtraceAttach(dbp.Pid) })
if err != nil {
return nil, err
}
_, _, err = dbp.wait(dbp.pid, 0)
_, _, err = dbp.wait(dbp.Pid, 0)
if err != nil {
return nil, err
}
}
proc, err := os.FindProcess(dbp.pid)
proc, err := os.FindProcess(dbp.Pid)
if err != nil {
return nil, err
}
@ -840,11 +796,11 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
}
dbp.arch.SetGStructOffset(ver, isextld)
// selectedGoroutine can not be set correctly by the call to updateThreadList
// because without calling SetGStructOffset we can not read the G struct of currentThread
// SelectedGoroutine can not be set correctly by the call to updateThreadList
// because without calling SetGStructOffset we can not read the G struct of CurrentThread
// but without calling updateThreadList we can not examine memory to determine
// the offset of g struct inside TLS
dbp.selectedGoroutine, _ = dbp.currentThread.GetG()
dbp.SelectedGoroutine, _ = dbp.CurrentThread.GetG()
panicpc, err := dbp.FindFunctionLocation("runtime.startpanic", true, 0)
if err == nil {
@ -860,7 +816,7 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
}
func (dbp *Process) ClearInternalBreakpoints() error {
for _, bp := range dbp.breakpoints {
for _, bp := range dbp.Breakpoints {
if !bp.Internal() {
continue
}
@ -868,9 +824,9 @@ func (dbp *Process) ClearInternalBreakpoints() error {
return err
}
}
for i := range dbp.threads {
if dbp.threads[i].CurrentBreakpoint != nil && dbp.threads[i].CurrentBreakpoint.Internal() {
dbp.threads[i].CurrentBreakpoint = nil
for i := range dbp.Threads {
if dbp.Threads[i].CurrentBreakpoint != nil && dbp.Threads[i].CurrentBreakpoint.Internal() {
dbp.Threads[i].CurrentBreakpoint = nil
}
}
return nil
@ -928,7 +884,7 @@ func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error)
// specified by `gid`.
func (dbp *Process) FindGoroutine(gid int) (*G, error) {
if gid == -1 {
return dbp.selectedGoroutine, nil
return dbp.SelectedGoroutine, nil
}
gs, err := dbp.GoroutinesInfo()
@ -954,13 +910,13 @@ func (dbp *Process) ConvertEvalScope(gid, frame int) (*EvalScope, error) {
return nil, err
}
if g == nil {
return dbp.currentThread.Scope()
return dbp.CurrentThread.Scope()
}
var out EvalScope
if g.thread == nil {
out.Thread = dbp.currentThread
out.Thread = dbp.CurrentThread
} else {
out.Thread = g.thread
}

View File

@ -17,8 +17,8 @@ import (
"golang.org/x/debug/macho"
"github.com/derekparker/delve/pkg/dwarf/frame"
"github.com/derekparker/delve/pkg/dwarf/line"
"github.com/derekparker/delve/dwarf/frame"
"github.com/derekparker/delve/dwarf/line"
sys "golang.org/x/sys/unix"
)
@ -77,7 +77,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
if pid <= 0 {
return nil, fmt.Errorf("could not fork/exec")
}
dbp.pid = pid
dbp.Pid = pid
for i := range argvSlice {
C.free(unsafe.Pointer(argvSlice[i]))
}
@ -86,7 +86,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
// trapWait to wait until the child process calls execve.
for {
err = dbp.updateThreadListForTask(C.get_task_for_pid(C.int(dbp.pid)))
err = dbp.updateThreadListForTask(C.get_task_for_pid(C.int(dbp.Pid)))
if err == nil {
break
}
@ -100,7 +100,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
}
dbp.allGCache = nil
for _, th := range dbp.threads {
for _, th := range dbp.Threads {
th.clearBreakpointState()
}
@ -152,11 +152,11 @@ func (dbp *Process) Kill() (err error) {
if dbp.exited {
return nil
}
err = sys.Kill(-dbp.pid, sys.SIGKILL)
err = sys.Kill(-dbp.Pid, sys.SIGKILL)
if err != nil {
return errors.New("could not deliver signal: " + err.Error())
}
for port := range dbp.threads {
for port := range dbp.Threads {
if C.thread_resume(C.thread_act_t(port)) != C.KERN_SUCCESS {
return errors.New("could not resume task")
}
@ -175,7 +175,7 @@ func (dbp *Process) Kill() (err error) {
func (dbp *Process) requestManualStop() (err error) {
var (
task = C.mach_port_t(dbp.os.task)
thread = C.mach_port_t(dbp.currentThread.os.threadAct)
thread = C.mach_port_t(dbp.CurrentThread.os.threadAct)
exceptionPort = C.mach_port_t(dbp.os.exceptionPort)
)
kret := C.raise_exception(task, thread, exceptionPort, C.EXC_BREAKPOINT)
@ -218,12 +218,12 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
return couldNotGetThreadList
}
for _, thread := range dbp.threads {
for _, thread := range dbp.Threads {
thread.os.exists = false
}
for _, port := range list {
thread, ok := dbp.threads[int(port)]
thread, ok := dbp.Threads[int(port)]
if !ok {
thread, err = dbp.addThread(int(port), false)
if err != nil {
@ -233,9 +233,9 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
thread.os.exists = true
}
for threadID, thread := range dbp.threads {
for threadID, thread := range dbp.Threads {
if !thread.os.exists {
delete(dbp.threads, threadID)
delete(dbp.Threads, threadID)
}
}
@ -243,7 +243,7 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
}
func (dbp *Process) addThread(port int, attach bool) (*Thread, error) {
if thread, ok := dbp.threads[port]; ok {
if thread, ok := dbp.Threads[port]; ok {
return thread, nil
}
thread := &Thread{
@ -251,9 +251,9 @@ func (dbp *Process) addThread(port int, attach bool) (*Thread, error) {
dbp: dbp,
os: new(OSSpecificDetails),
}
dbp.threads[port] = thread
dbp.Threads[port] = thread
thread.os.threadAct = C.thread_act_t(port)
if dbp.currentThread == nil {
if dbp.CurrentThread == nil {
dbp.SwitchThread(thread.ID)
}
return thread, nil