Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
pubx
delve
提交
26ad5f1d
D
delve
项目概览
pubx
/
delve
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
delve
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
26ad5f1d
编写于
2月 07, 2017
作者:
D
Derek Parker
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Introduce target interface
上级
3658d1e1
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
432 addition
and
320 deletion
+432
-320
pkg/target/target.go
pkg/target/target.go
+84
-0
proc/disasm.go
proc/disasm.go
+1
-1
proc/disasm_amd64.go
proc/disasm_amd64.go
+2
-1
proc/moduledata.go
proc/moduledata.go
+10
-10
proc/proc.go
proc/proc.go
+108
-84
proc/proc_darwin.go
proc/proc_darwin.go
+22
-22
proc/proc_linux.go
proc/proc_linux.go
+27
-27
proc/proc_test.go
proc/proc_test.go
+59
-59
proc/proc_unix_test.go
proc/proc_unix_test.go
+1
-1
proc/proc_windows.go
proc/proc_windows.go
+15
-15
proc/stack.go
proc/stack.go
+2
-1
proc/threads.go
proc/threads.go
+12
-12
proc/threads_linux.go
proc/threads_linux.go
+3
-3
proc/threads_windows.go
proc/threads_windows.go
+4
-4
proc/variables.go
proc/variables.go
+1
-1
service/debugger/debugger.go
service/debugger/debugger.go
+65
-63
service/debugger/locations.go
service/debugger/locations.go
+13
-13
service/test/variables_test.go
service/test/variables_test.go
+3
-3
未找到文件。
pkg/target/target.go
0 → 100644
浏览文件 @
26ad5f1d
package
target
import
(
"debug/gosym"
"go/ast"
"time"
"github.com/derekparker/delve/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
)
}
proc/disasm.go
浏览文件 @
26ad5f1d
...
@@ -41,7 +41,7 @@ func (thread *Thread) Disassemble(startPC, endPC uint64, currentGoroutine bool)
...
@@ -41,7 +41,7 @@ func (thread *Thread) Disassemble(startPC, endPC uint64, currentGoroutine bool)
}
}
for
len
(
mem
)
>
0
{
for
len
(
mem
)
>
0
{
bp
,
atbp
:=
thread
.
dbp
.
B
reakpoints
[
pc
]
bp
,
atbp
:=
thread
.
dbp
.
b
reakpoints
[
pc
]
if
atbp
{
if
atbp
{
for
i
:=
range
bp
.
OriginalData
{
for
i
:=
range
bp
.
OriginalData
{
mem
[
i
]
=
bp
.
OriginalData
[
i
]
mem
[
i
]
=
bp
.
OriginalData
[
i
]
...
...
proc/disasm_amd64.go
浏览文件 @
26ad5f1d
...
@@ -3,6 +3,7 @@ package proc
...
@@ -3,6 +3,7 @@ package proc
import
(
import
(
"debug/gosym"
"debug/gosym"
"encoding/binary"
"encoding/binary"
"rsc.io/x86/x86asm"
"rsc.io/x86/x86asm"
)
)
...
@@ -145,7 +146,7 @@ func init() {
...
@@ -145,7 +146,7 @@ func init() {
// FirstPCAfterPrologue returns the address of the first instruction after the prologue for function fn
// 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
// 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
)
{
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
{
if
err
!=
nil
{
return
fn
.
Entry
,
err
return
fn
.
Entry
,
err
}
}
...
...
proc/moduledata.go
浏览文件 @
26ad5f1d
...
@@ -13,7 +13,7 @@ type moduleData struct {
...
@@ -13,7 +13,7 @@ type moduleData struct {
func
(
dbp
*
Process
)
loadModuleData
()
(
err
error
)
{
func
(
dbp
*
Process
)
loadModuleData
()
(
err
error
)
{
dbp
.
loadModuleDataOnce
.
Do
(
func
()
{
dbp
.
loadModuleDataOnce
.
Do
(
func
()
{
scope
:=
&
EvalScope
{
Thread
:
dbp
.
C
urrentThread
,
PC
:
0
,
CFA
:
0
}
scope
:=
&
EvalScope
{
Thread
:
dbp
.
c
urrentThread
,
PC
:
0
,
CFA
:
0
}
var
md
*
Variable
var
md
*
Variable
md
,
err
=
scope
.
packageVarAddr
(
"runtime.firstmoduledata"
)
md
,
err
=
scope
.
packageVarAddr
(
"runtime.firstmoduledata"
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -84,13 +84,13 @@ func (dbp *Process) resolveTypeOff(typeAddr uintptr, off uintptr) (*Variable, er
...
@@ -84,13 +84,13 @@ func (dbp *Process) resolveTypeOff(typeAddr uintptr, off uintptr) (*Variable, er
return
v
.
newVariable
(
v
.
Name
,
uintptr
(
addr
),
rtyp
),
nil
return
v
.
newVariable
(
v
.
Name
,
uintptr
(
addr
),
rtyp
),
nil
}
}
if
t
,
_
:=
md
.
typemapVar
.
mapAccess
(
newConstant
(
constant
.
MakeUint64
(
uint64
(
off
)),
dbp
.
C
urrentThread
));
t
!=
nil
{
if
t
,
_
:=
md
.
typemapVar
.
mapAccess
(
newConstant
(
constant
.
MakeUint64
(
uint64
(
off
)),
dbp
.
c
urrentThread
));
t
!=
nil
{
return
t
,
nil
return
t
,
nil
}
}
res
:=
md
.
types
+
uintptr
(
off
)
res
:=
md
.
types
+
uintptr
(
off
)
return
dbp
.
C
urrentThread
.
newVariable
(
""
,
res
,
rtyp
),
nil
return
dbp
.
c
urrentThread
.
newVariable
(
""
,
res
,
rtyp
),
nil
}
}
func
(
dbp
*
Process
)
resolveNameOff
(
typeAddr
uintptr
,
off
uintptr
)
(
name
,
tag
string
,
pkgpathoff
int32
,
err
error
)
{
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
...
@@ -119,7 +119,7 @@ func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (name, tag str
}
}
func
(
dbp
*
Process
)
reflectOffsMapAccess
(
off
uintptr
)
(
*
Variable
,
error
)
{
func
(
dbp
*
Process
)
reflectOffsMapAccess
(
off
uintptr
)
(
*
Variable
,
error
)
{
scope
:=
&
EvalScope
{
Thread
:
dbp
.
C
urrentThread
,
PC
:
0
,
CFA
:
0
}
scope
:=
&
EvalScope
{
Thread
:
dbp
.
c
urrentThread
,
PC
:
0
,
CFA
:
0
}
reflectOffs
,
err
:=
scope
.
packageVarAddr
(
"runtime.reflectOffs"
)
reflectOffs
,
err
:=
scope
.
packageVarAddr
(
"runtime.reflectOffs"
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -130,7 +130,7 @@ func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) {
...
@@ -130,7 +130,7 @@ func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) {
return
nil
,
err
return
nil
,
err
}
}
return
reflectOffsm
.
mapAccess
(
newConstant
(
constant
.
MakeUint64
(
uint64
(
off
)),
dbp
.
C
urrentThread
))
return
reflectOffsm
.
mapAccess
(
newConstant
(
constant
.
MakeUint64
(
uint64
(
off
)),
dbp
.
c
urrentThread
))
}
}
const
(
const
(
...
@@ -142,7 +142,7 @@ const (
...
@@ -142,7 +142,7 @@ const (
func
(
dbp
*
Process
)
loadName
(
addr
uintptr
)
(
name
,
tag
string
,
pkgpathoff
int32
,
err
error
)
{
func
(
dbp
*
Process
)
loadName
(
addr
uintptr
)
(
name
,
tag
string
,
pkgpathoff
int32
,
err
error
)
{
off
:=
addr
off
:=
addr
namedata
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
off
,
3
)
namedata
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
off
,
3
)
off
+=
3
off
+=
3
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
""
,
0
,
err
return
""
,
""
,
0
,
err
...
@@ -150,7 +150,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
...
@@ -150,7 +150,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
namelen
:=
uint16
(
namedata
[
1
]
<<
8
)
|
uint16
(
namedata
[
2
])
namelen
:=
uint16
(
namedata
[
1
]
<<
8
)
|
uint16
(
namedata
[
2
])
rawstr
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
off
,
int
(
namelen
))
rawstr
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
off
,
int
(
namelen
))
off
+=
uintptr
(
namelen
)
off
+=
uintptr
(
namelen
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
""
,
0
,
err
return
""
,
""
,
0
,
err
...
@@ -159,14 +159,14 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
...
@@ -159,14 +159,14 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
name
=
string
(
rawstr
)
name
=
string
(
rawstr
)
if
namedata
[
0
]
&
nameflagHasTag
!=
0
{
if
namedata
[
0
]
&
nameflagHasTag
!=
0
{
taglendata
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
off
,
2
)
taglendata
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
off
,
2
)
off
+=
2
off
+=
2
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
""
,
0
,
err
return
""
,
""
,
0
,
err
}
}
taglen
:=
uint16
(
taglendata
[
0
]
<<
8
)
|
uint16
(
taglendata
[
1
])
taglen
:=
uint16
(
taglendata
[
0
]
<<
8
)
|
uint16
(
taglendata
[
1
])
rawstr
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
off
,
int
(
taglen
))
rawstr
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
off
,
int
(
taglen
))
off
+=
uintptr
(
taglen
)
off
+=
uintptr
(
taglen
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
""
,
0
,
err
return
""
,
""
,
0
,
err
...
@@ -176,7 +176,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
...
@@ -176,7 +176,7 @@ func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32,
}
}
if
namedata
[
0
]
&
nameflagHasPkg
!=
0
{
if
namedata
[
0
]
&
nameflagHasPkg
!=
0
{
pkgdata
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
off
,
4
)
pkgdata
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
off
,
4
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
""
,
0
,
err
return
""
,
""
,
0
,
err
}
}
...
...
proc/proc.go
浏览文件 @
26ad5f1d
...
@@ -25,23 +25,23 @@ import (
...
@@ -25,23 +25,23 @@ import (
// Process represents all of the information the debugger
// Process represents all of the information the debugger
// is holding onto regarding the process we are debugging.
// is holding onto regarding the process we are debugging.
type
Process
struct
{
type
Process
struct
{
P
id
int
// Process Pid
p
id
int
// Process Pid
Process
*
os
.
Process
// Pointer to process struct for the actual process we are debugging
Process
*
os
.
Process
// Pointer to process struct for the actual process we are debugging
L
astModified
time
.
Time
// Time the executable of this process was last modified
l
astModified
time
.
Time
// Time the executable of this process was last modified
// Breakpoint table, holds information on breakpoints.
// Breakpoint table, holds information on breakpoints.
// Maps instruction address to Breakpoint struct.
// Maps instruction address to Breakpoint struct.
B
reakpoints
map
[
uint64
]
*
Breakpoint
b
reakpoints
map
[
uint64
]
*
Breakpoint
// List of threads mapped as such: pid -> *Thread
// List of threads mapped as such: pid -> *Thread
T
hreads
map
[
int
]
*
Thread
t
hreads
map
[
int
]
*
Thread
// Active thread
// Active thread
C
urrentThread
*
Thread
c
urrentThread
*
Thread
// Goroutine that will be used by default to set breakpoint, eval variables, etc...
// Goroutine that will be used by default to set breakpoint, eval variables, etc...
// Normally
SelectedGoroutine is C
urrentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
// Normally
selectedGoroutine is c
urrentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
S
electedGoroutine
*
G
s
electedGoroutine
*
G
// Maps package names to package paths, needed to lookup types inside DWARF info
// Maps package names to package paths, needed to lookup types inside DWARF info
packageMap
map
[
string
]
string
packageMap
map
[
string
]
string
...
@@ -81,9 +81,9 @@ var NotExecutableErr = errors.New("not an executable file")
...
@@ -81,9 +81,9 @@ var NotExecutableErr = errors.New("not an executable file")
// `handlePtraceFuncs`.
// `handlePtraceFuncs`.
func
New
(
pid
int
)
*
Process
{
func
New
(
pid
int
)
*
Process
{
dbp
:=
&
Process
{
dbp
:=
&
Process
{
P
id
:
pid
,
p
id
:
pid
,
T
hreads
:
make
(
map
[
int
]
*
Thread
),
t
hreads
:
make
(
map
[
int
]
*
Thread
),
B
reakpoints
:
make
(
map
[
uint64
]
*
Breakpoint
),
b
reakpoints
:
make
(
map
[
uint64
]
*
Breakpoint
),
firstStart
:
true
,
firstStart
:
true
,
os
:
new
(
OSProcessDetails
),
os
:
new
(
OSProcessDetails
),
ptraceChan
:
make
(
chan
func
()),
ptraceChan
:
make
(
chan
func
()),
...
@@ -119,7 +119,7 @@ func (dbp *Process) Detach(kill bool) (err error) {
...
@@ -119,7 +119,7 @@ func (dbp *Process) Detach(kill bool) (err error) {
}
}
if
!
kill
{
if
!
kill
{
// Clean up any breakpoints we've set.
// Clean up any breakpoints we've set.
for
_
,
bp
:=
range
dbp
.
B
reakpoints
{
for
_
,
bp
:=
range
dbp
.
b
reakpoints
{
if
bp
!=
nil
{
if
bp
!=
nil
{
_
,
err
:=
dbp
.
ClearBreakpoint
(
bp
.
Addr
)
_
,
err
:=
dbp
.
ClearBreakpoint
(
bp
.
Addr
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -129,12 +129,12 @@ func (dbp *Process) Detach(kill bool) (err error) {
...
@@ -129,12 +129,12 @@ func (dbp *Process) Detach(kill bool) (err error) {
}
}
}
}
dbp
.
execPtraceFunc
(
func
()
{
dbp
.
execPtraceFunc
(
func
()
{
err
=
PtraceDetach
(
dbp
.
P
id
,
0
)
err
=
PtraceDetach
(
dbp
.
p
id
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
if
kill
{
if
kill
{
err
=
killProcess
(
dbp
.
P
id
)
err
=
killProcess
(
dbp
.
p
id
)
}
}
})
})
return
return
...
@@ -149,7 +149,7 @@ func (dbp *Process) Exited() bool {
...
@@ -149,7 +149,7 @@ func (dbp *Process) Exited() bool {
// Running returns whether the debugged
// Running returns whether the debugged
// process is currently executing.
// process is currently executing.
func
(
dbp
*
Process
)
Running
()
bool
{
func
(
dbp
*
Process
)
Running
()
bool
{
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
if
th
.
running
{
if
th
.
running
{
return
true
return
true
}
}
...
@@ -157,6 +157,30 @@ func (dbp *Process) Running() bool {
...
@@ -157,6 +157,30 @@ func (dbp *Process) Running() bool {
return
false
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
// LoadInformation finds the executable and then uses it
// to parse the following information:
// to parse the following information:
// * Dwarf .debug_frame section
// * Dwarf .debug_frame section
...
@@ -171,7 +195,7 @@ func (dbp *Process) LoadInformation(path string) error {
...
@@ -171,7 +195,7 @@ func (dbp *Process) LoadInformation(path string) error {
}
}
fi
,
err
:=
os
.
Stat
(
path
)
fi
,
err
:=
os
.
Stat
(
path
)
if
err
==
nil
{
if
err
==
nil
{
dbp
.
L
astModified
=
fi
.
ModTime
()
dbp
.
l
astModified
=
fi
.
ModTime
()
}
}
wg
.
Add
(
5
)
wg
.
Add
(
5
)
...
@@ -223,7 +247,7 @@ func (dbp *Process) FindFunctionLocation(funcName string, firstLine bool, lineOf
...
@@ -223,7 +247,7 @@ func (dbp *Process) FindFunctionLocation(funcName string, firstLine bool, lineOf
// CurrentLocation returns the location of the current thread.
// CurrentLocation returns the location of the current thread.
func
(
dbp
*
Process
)
CurrentLocation
()
(
*
Location
,
error
)
{
func
(
dbp
*
Process
)
CurrentLocation
()
(
*
Location
,
error
)
{
return
dbp
.
C
urrentThread
.
Location
()
return
dbp
.
c
urrentThread
.
Location
()
}
}
// RequestManualStop sets the `halt` flag and
// RequestManualStop sets the `halt` flag and
...
@@ -240,7 +264,7 @@ func (dbp *Process) RequestManualStop() error {
...
@@ -240,7 +264,7 @@ func (dbp *Process) RequestManualStop() error {
// break point table. Setting a break point must be thread specific due to
// 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.
// 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
)
{
func
(
dbp
*
Process
)
SetBreakpoint
(
addr
uint64
,
kind
BreakpointKind
,
cond
ast
.
Expr
)
(
*
Breakpoint
,
error
)
{
tid
:=
dbp
.
C
urrentThread
.
ID
tid
:=
dbp
.
c
urrentThread
.
ID
if
bp
,
ok
:=
dbp
.
FindBreakpoint
(
addr
);
ok
{
if
bp
,
ok
:=
dbp
.
FindBreakpoint
(
addr
);
ok
{
return
nil
,
BreakpointExistsError
{
bp
.
File
,
bp
.
Line
,
bp
.
Addr
}
return
nil
,
BreakpointExistsError
{
bp
.
File
,
bp
.
Line
,
bp
.
Addr
}
...
@@ -269,7 +293,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp
...
@@ -269,7 +293,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp
newBreakpoint
.
ID
=
dbp
.
breakpointIDCounter
newBreakpoint
.
ID
=
dbp
.
breakpointIDCounter
}
}
thread
:=
dbp
.
T
hreads
[
tid
]
thread
:=
dbp
.
t
hreads
[
tid
]
originalData
,
err
:=
thread
.
readMemory
(
uintptr
(
addr
),
dbp
.
arch
.
BreakpointSize
())
originalData
,
err
:=
thread
.
readMemory
(
uintptr
(
addr
),
dbp
.
arch
.
BreakpointSize
())
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -278,7 +302,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp
...
@@ -278,7 +302,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp
return
nil
,
err
return
nil
,
err
}
}
newBreakpoint
.
OriginalData
=
originalData
newBreakpoint
.
OriginalData
=
originalData
dbp
.
B
reakpoints
[
addr
]
=
newBreakpoint
dbp
.
b
reakpoints
[
addr
]
=
newBreakpoint
return
newBreakpoint
,
nil
return
newBreakpoint
,
nil
}
}
...
@@ -293,18 +317,18 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*Breakpoint, error) {
...
@@ -293,18 +317,18 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*Breakpoint, error) {
return
nil
,
NoBreakpointError
{
addr
:
addr
}
return
nil
,
NoBreakpointError
{
addr
:
addr
}
}
}
if
_
,
err
:=
bp
.
Clear
(
dbp
.
C
urrentThread
);
err
!=
nil
{
if
_
,
err
:=
bp
.
Clear
(
dbp
.
c
urrentThread
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
delete
(
dbp
.
B
reakpoints
,
addr
)
delete
(
dbp
.
b
reakpoints
,
addr
)
return
bp
,
nil
return
bp
,
nil
}
}
// Status returns the status of the current main thread context.
// Status returns the status of the current main thread context.
func
(
dbp
*
Process
)
Status
()
*
WaitStatus
{
func
(
dbp
*
Process
)
Status
()
*
WaitStatus
{
return
dbp
.
C
urrentThread
.
Status
return
dbp
.
c
urrentThread
.
Status
}
}
// Next continues execution until the next source line.
// Next continues execution until the next source line.
...
@@ -312,8 +336,8 @@ func (dbp *Process) Next() (err error) {
...
@@ -312,8 +336,8 @@ func (dbp *Process) Next() (err error) {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
return
&
ProcessExitedError
{}
}
}
for
i
:=
range
dbp
.
B
reakpoints
{
for
i
:=
range
dbp
.
b
reakpoints
{
if
dbp
.
B
reakpoints
[
i
]
.
Internal
()
{
if
dbp
.
b
reakpoints
[
i
]
.
Internal
()
{
return
fmt
.
Errorf
(
"next while nexting"
)
return
fmt
.
Errorf
(
"next while nexting"
)
}
}
}
}
...
@@ -343,7 +367,7 @@ func (dbp *Process) Continue() error {
...
@@ -343,7 +367,7 @@ func (dbp *Process) Continue() error {
}
}
dbp
.
allGCache
=
nil
dbp
.
allGCache
=
nil
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
th
.
clearBreakpointState
()
th
.
clearBreakpointState
()
}
}
...
@@ -362,42 +386,42 @@ func (dbp *Process) Continue() error {
...
@@ -362,42 +386,42 @@ func (dbp *Process) Continue() error {
}
}
switch
{
switch
{
case
dbp
.
C
urrentThread
.
CurrentBreakpoint
==
nil
:
case
dbp
.
c
urrentThread
.
CurrentBreakpoint
==
nil
:
// runtime.Breakpoint or manual stop
// runtime.Breakpoint or manual stop
if
dbp
.
C
urrentThread
.
onRuntimeBreakpoint
()
{
if
dbp
.
c
urrentThread
.
onRuntimeBreakpoint
()
{
// Single-step current thread until we exit runtime.breakpoint and
// Single-step current thread until we exit runtime.breakpoint and
// runtime.Breakpoint.
// runtime.Breakpoint.
// On go < 1.8 it was sufficient to single-step twice on go1.8 a change
// On go < 1.8 it was sufficient to single-step twice on go1.8 a change
// to the compiler requires 4 steps.
// to the compiler requires 4 steps.
for
{
for
{
if
err
=
dbp
.
C
urrentThread
.
StepInstruction
();
err
!=
nil
{
if
err
=
dbp
.
c
urrentThread
.
StepInstruction
();
err
!=
nil
{
return
err
return
err
}
}
loc
,
err
:=
dbp
.
C
urrentThread
.
Location
()
loc
,
err
:=
dbp
.
c
urrentThread
.
Location
()
if
err
!=
nil
||
loc
.
Fn
==
nil
||
(
loc
.
Fn
.
Name
!=
"runtime.breakpoint"
&&
loc
.
Fn
.
Name
!=
"runtime.Breakpoint"
)
{
if
err
!=
nil
||
loc
.
Fn
==
nil
||
(
loc
.
Fn
.
Name
!=
"runtime.breakpoint"
&&
loc
.
Fn
.
Name
!=
"runtime.Breakpoint"
)
{
break
break
}
}
}
}
}
}
return
dbp
.
conditionErrors
()
return
dbp
.
conditionErrors
()
case
dbp
.
C
urrentThread
.
onTriggeredInternalBreakpoint
()
:
case
dbp
.
c
urrentThread
.
onTriggeredInternalBreakpoint
()
:
if
dbp
.
C
urrentThread
.
CurrentBreakpoint
.
Kind
==
StepBreakpoint
{
if
dbp
.
c
urrentThread
.
CurrentBreakpoint
.
Kind
==
StepBreakpoint
{
// See description of proc.(*Process).next for the meaning of StepBreakpoints
// See description of proc.(*Process).next for the meaning of StepBreakpoints
if
err
:=
dbp
.
conditionErrors
();
err
!=
nil
{
if
err
:=
dbp
.
conditionErrors
();
err
!=
nil
{
return
err
return
err
}
}
pc
,
err
:=
dbp
.
C
urrentThread
.
PC
()
pc
,
err
:=
dbp
.
c
urrentThread
.
PC
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
text
,
err
:=
dbp
.
C
urrentThread
.
Disassemble
(
pc
,
pc
+
maxInstructionLength
,
true
)
text
,
err
:=
dbp
.
c
urrentThread
.
Disassemble
(
pc
,
pc
+
maxInstructionLength
,
true
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
// here we either set a breakpoint into the destination of the CALL
// here we either set a breakpoint into the destination of the CALL
// instruction or we determined that the called function is hidden,
// instruction or we determined that the called function is hidden,
// either way we need to resume execution
// either way we need to resume execution
if
err
=
dbp
.
setStepIntoBreakpoint
(
text
,
sameGoroutineCondition
(
dbp
.
S
electedGoroutine
));
err
!=
nil
{
if
err
=
dbp
.
setStepIntoBreakpoint
(
text
,
sameGoroutineCondition
(
dbp
.
s
electedGoroutine
));
err
!=
nil
{
return
err
return
err
}
}
}
else
{
}
else
{
...
@@ -406,8 +430,8 @@ func (dbp *Process) Continue() error {
...
@@ -406,8 +430,8 @@ func (dbp *Process) Continue() error {
}
}
return
dbp
.
conditionErrors
()
return
dbp
.
conditionErrors
()
}
}
case
dbp
.
C
urrentThread
.
onTriggeredBreakpoint
()
:
case
dbp
.
c
urrentThread
.
onTriggeredBreakpoint
()
:
onNextGoroutine
,
err
:=
dbp
.
C
urrentThread
.
onNextGoroutine
()
onNextGoroutine
,
err
:=
dbp
.
c
urrentThread
.
onNextGoroutine
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -426,7 +450,7 @@ func (dbp *Process) Continue() error {
...
@@ -426,7 +450,7 @@ func (dbp *Process) Continue() error {
func
(
dbp
*
Process
)
conditionErrors
()
error
{
func
(
dbp
*
Process
)
conditionErrors
()
error
{
var
condErr
error
var
condErr
error
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
if
th
.
CurrentBreakpoint
!=
nil
&&
th
.
BreakpointConditionError
!=
nil
{
if
th
.
CurrentBreakpoint
!=
nil
&&
th
.
BreakpointConditionError
!=
nil
{
if
condErr
==
nil
{
if
condErr
==
nil
{
condErr
=
th
.
BreakpointConditionError
condErr
=
th
.
BreakpointConditionError
...
@@ -438,12 +462,12 @@ func (dbp *Process) conditionErrors() error {
...
@@ -438,12 +462,12 @@ func (dbp *Process) conditionErrors() error {
return
condErr
return
condErr
}
}
// pick a new dbp.
C
urrentThread, with the following priority:
// pick a new dbp.
c
urrentThread, with the following priority:
// - a thread with onTriggeredInternalBreakpoint() == true
// - a thread with onTriggeredInternalBreakpoint() == true
// - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread)
// - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread)
// - trapthread
// - trapthread
func
(
dbp
*
Process
)
pickCurrentThread
(
trapthread
*
Thread
)
error
{
func
(
dbp
*
Process
)
pickCurrentThread
(
trapthread
*
Thread
)
error
{
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
if
th
.
onTriggeredInternalBreakpoint
()
{
if
th
.
onTriggeredInternalBreakpoint
()
{
return
dbp
.
SwitchThread
(
th
.
ID
)
return
dbp
.
SwitchThread
(
th
.
ID
)
}
}
...
@@ -451,7 +475,7 @@ func (dbp *Process) pickCurrentThread(trapthread *Thread) error {
...
@@ -451,7 +475,7 @@ func (dbp *Process) pickCurrentThread(trapthread *Thread) error {
if
trapthread
.
onTriggeredBreakpoint
()
{
if
trapthread
.
onTriggeredBreakpoint
()
{
return
dbp
.
SwitchThread
(
trapthread
.
ID
)
return
dbp
.
SwitchThread
(
trapthread
.
ID
)
}
}
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
if
th
.
onTriggeredBreakpoint
()
{
if
th
.
onTriggeredBreakpoint
()
{
return
dbp
.
SwitchThread
(
th
.
ID
)
return
dbp
.
SwitchThread
(
th
.
ID
)
}
}
...
@@ -465,8 +489,8 @@ func (dbp *Process) Step() (err error) {
...
@@ -465,8 +489,8 @@ func (dbp *Process) Step() (err error) {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
return
&
ProcessExitedError
{}
}
}
for
i
:=
range
dbp
.
B
reakpoints
{
for
i
:=
range
dbp
.
b
reakpoints
{
if
dbp
.
B
reakpoints
[
i
]
.
Internal
()
{
if
dbp
.
b
reakpoints
[
i
]
.
Internal
()
{
return
fmt
.
Errorf
(
"next while nexting"
)
return
fmt
.
Errorf
(
"next while nexting"
)
}
}
}
}
...
@@ -506,12 +530,12 @@ func sameGoroutineCondition(g *G) ast.Expr {
...
@@ -506,12 +530,12 @@ func sameGoroutineCondition(g *G) ast.Expr {
// asssociated with the selected goroutine. All other
// asssociated with the selected goroutine. All other
// threads will remain stopped.
// threads will remain stopped.
func
(
dbp
*
Process
)
StepInstruction
()
(
err
error
)
{
func
(
dbp
*
Process
)
StepInstruction
()
(
err
error
)
{
if
dbp
.
S
electedGoroutine
==
nil
{
if
dbp
.
s
electedGoroutine
==
nil
{
return
errors
.
New
(
"cannot single step: no selected goroutine"
)
return
errors
.
New
(
"cannot single step: no selected goroutine"
)
}
}
if
dbp
.
S
electedGoroutine
.
thread
==
nil
{
if
dbp
.
s
electedGoroutine
.
thread
==
nil
{
// Step called on parked goroutine
// Step called on parked goroutine
if
_
,
err
:=
dbp
.
SetBreakpoint
(
dbp
.
SelectedGoroutine
.
PC
,
NextBreakpoint
,
sameGoroutineCondition
(
dbp
.
S
electedGoroutine
));
err
!=
nil
{
if
_
,
err
:=
dbp
.
SetBreakpoint
(
dbp
.
selectedGoroutine
.
PC
,
NextBreakpoint
,
sameGoroutineCondition
(
dbp
.
s
electedGoroutine
));
err
!=
nil
{
return
err
return
err
}
}
return
dbp
.
Continue
()
return
dbp
.
Continue
()
...
@@ -520,20 +544,20 @@ func (dbp *Process) StepInstruction() (err error) {
...
@@ -520,20 +544,20 @@ func (dbp *Process) StepInstruction() (err error) {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
return
&
ProcessExitedError
{}
}
}
dbp
.
S
electedGoroutine
.
thread
.
clearBreakpointState
()
dbp
.
s
electedGoroutine
.
thread
.
clearBreakpointState
()
err
=
dbp
.
S
electedGoroutine
.
thread
.
StepInstruction
()
err
=
dbp
.
s
electedGoroutine
.
thread
.
StepInstruction
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
return
dbp
.
S
electedGoroutine
.
thread
.
SetCurrentBreakpoint
()
return
dbp
.
s
electedGoroutine
.
thread
.
SetCurrentBreakpoint
()
}
}
// StepOut will continue until the current goroutine exits the
// StepOut will continue until the current goroutine exits the
// function currently being executed or a deferred function is executed
// function currently being executed or a deferred function is executed
func
(
dbp
*
Process
)
StepOut
()
error
{
func
(
dbp
*
Process
)
StepOut
()
error
{
cond
:=
sameGoroutineCondition
(
dbp
.
S
electedGoroutine
)
cond
:=
sameGoroutineCondition
(
dbp
.
s
electedGoroutine
)
topframe
,
err
:=
topframe
(
dbp
.
SelectedGoroutine
,
dbp
.
C
urrentThread
)
topframe
,
err
:=
topframe
(
dbp
.
selectedGoroutine
,
dbp
.
c
urrentThread
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -542,8 +566,8 @@ func (dbp *Process) StepOut() error {
...
@@ -542,8 +566,8 @@ func (dbp *Process) StepOut() error {
var
deferpc
uint64
=
0
var
deferpc
uint64
=
0
if
filepath
.
Ext
(
topframe
.
Current
.
File
)
==
".go"
{
if
filepath
.
Ext
(
topframe
.
Current
.
File
)
==
".go"
{
if
dbp
.
S
electedGoroutine
!=
nil
{
if
dbp
.
s
electedGoroutine
!=
nil
{
deferPCEntry
:=
dbp
.
S
electedGoroutine
.
DeferPC
()
deferPCEntry
:=
dbp
.
s
electedGoroutine
.
DeferPC
()
if
deferPCEntry
!=
0
{
if
deferPCEntry
!=
0
{
_
,
_
,
deferfn
:=
dbp
.
goSymTable
.
PCToLine
(
deferPCEntry
)
_
,
_
,
deferfn
:=
dbp
.
goSymTable
.
PCToLine
(
deferPCEntry
)
deferpc
,
err
=
dbp
.
FirstPCAfterPrologue
(
deferfn
,
false
)
deferpc
,
err
=
dbp
.
FirstPCAfterPrologue
(
deferfn
,
false
)
...
@@ -589,9 +613,9 @@ func (dbp *Process) SwitchThread(tid int) error {
...
@@ -589,9 +613,9 @@ func (dbp *Process) SwitchThread(tid int) error {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
return
&
ProcessExitedError
{}
}
}
if
th
,
ok
:=
dbp
.
T
hreads
[
tid
];
ok
{
if
th
,
ok
:=
dbp
.
t
hreads
[
tid
];
ok
{
dbp
.
C
urrentThread
=
th
dbp
.
c
urrentThread
=
th
dbp
.
SelectedGoroutine
,
_
=
dbp
.
C
urrentThread
.
GetG
()
dbp
.
selectedGoroutine
,
_
=
dbp
.
c
urrentThread
.
GetG
()
return
nil
return
nil
}
}
return
fmt
.
Errorf
(
"thread %d does not exist"
,
tid
)
return
fmt
.
Errorf
(
"thread %d does not exist"
,
tid
)
...
@@ -608,13 +632,13 @@ func (dbp *Process) SwitchGoroutine(gid int) error {
...
@@ -608,13 +632,13 @@ func (dbp *Process) SwitchGoroutine(gid int) error {
return
err
return
err
}
}
if
g
==
nil
{
if
g
==
nil
{
// user specified -1 and
S
electedGoroutine is nil
// user specified -1 and
s
electedGoroutine is nil
return
nil
return
nil
}
}
if
g
.
thread
!=
nil
{
if
g
.
thread
!=
nil
{
return
dbp
.
SwitchThread
(
g
.
thread
.
ID
)
return
dbp
.
SwitchThread
(
g
.
thread
.
ID
)
}
}
dbp
.
S
electedGoroutine
=
g
dbp
.
s
electedGoroutine
=
g
return
nil
return
nil
}
}
...
@@ -634,13 +658,13 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
...
@@ -634,13 +658,13 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
rdr
=
dbp
.
DwarfReader
()
rdr
=
dbp
.
DwarfReader
()
)
)
for
i
:=
range
dbp
.
T
hreads
{
for
i
:=
range
dbp
.
t
hreads
{
if
dbp
.
T
hreads
[
i
]
.
blocked
()
{
if
dbp
.
t
hreads
[
i
]
.
blocked
()
{
continue
continue
}
}
g
,
_
:=
dbp
.
T
hreads
[
i
]
.
GetG
()
g
,
_
:=
dbp
.
t
hreads
[
i
]
.
GetG
()
if
g
!=
nil
{
if
g
!=
nil
{
threadg
[
g
.
ID
]
=
dbp
.
T
hreads
[
i
]
threadg
[
g
.
ID
]
=
dbp
.
t
hreads
[
i
]
}
}
}
}
...
@@ -648,7 +672,7 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
...
@@ -648,7 +672,7 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
allglenBytes
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
uintptr
(
addr
),
8
)
allglenBytes
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
uintptr
(
addr
),
8
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -663,11 +687,11 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
...
@@ -663,11 +687,11 @@ func (dbp *Process) GoroutinesInfo() ([]*G, error) {
return
nil
,
err
return
nil
,
err
}
}
}
}
faddr
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
uintptr
(
allgentryaddr
),
dbp
.
arch
.
PtrSize
())
faddr
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
uintptr
(
allgentryaddr
),
dbp
.
arch
.
PtrSize
())
allgptr
:=
binary
.
LittleEndian
.
Uint64
(
faddr
)
allgptr
:=
binary
.
LittleEndian
.
Uint64
(
faddr
)
for
i
:=
uint64
(
0
);
i
<
allglen
;
i
++
{
for
i
:=
uint64
(
0
);
i
<
allglen
;
i
++
{
gvar
,
err
:=
dbp
.
C
urrentThread
.
newGVariable
(
uintptr
(
allgptr
+
(
i
*
uint64
(
dbp
.
arch
.
PtrSize
()))),
true
)
gvar
,
err
:=
dbp
.
c
urrentThread
.
newGVariable
(
uintptr
(
allgptr
+
(
i
*
uint64
(
dbp
.
arch
.
PtrSize
()))),
true
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -701,7 +725,7 @@ func (dbp *Process) Halt() (err error) {
...
@@ -701,7 +725,7 @@ func (dbp *Process) Halt() (err error) {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
&
ProcessExitedError
{}
return
&
ProcessExitedError
{}
}
}
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
if
err
:=
th
.
Halt
();
err
!=
nil
{
if
err
:=
th
.
Halt
();
err
!=
nil
{
return
err
return
err
}
}
...
@@ -712,18 +736,18 @@ func (dbp *Process) Halt() (err error) {
...
@@ -712,18 +736,18 @@ func (dbp *Process) Halt() (err error) {
// Registers obtains register values from the
// Registers obtains register values from the
// "current" thread of the traced process.
// "current" thread of the traced process.
func
(
dbp
*
Process
)
Registers
()
(
Registers
,
error
)
{
func
(
dbp
*
Process
)
Registers
()
(
Registers
,
error
)
{
return
dbp
.
C
urrentThread
.
Registers
(
false
)
return
dbp
.
c
urrentThread
.
Registers
(
false
)
}
}
// PC returns the PC of the current thread.
// PC returns the PC of the current thread.
func
(
dbp
*
Process
)
PC
()
(
uint64
,
error
)
{
func
(
dbp
*
Process
)
PC
()
(
uint64
,
error
)
{
return
dbp
.
C
urrentThread
.
PC
()
return
dbp
.
c
urrentThread
.
PC
()
}
}
// CurrentBreakpoint returns the breakpoint the current thread
// CurrentBreakpoint returns the breakpoint the current thread
// is stopped at.
// is stopped at.
func
(
dbp
*
Process
)
CurrentBreakpoint
()
*
Breakpoint
{
func
(
dbp
*
Process
)
CurrentBreakpoint
()
*
Breakpoint
{
return
dbp
.
C
urrentThread
.
CurrentBreakpoint
return
dbp
.
c
urrentThread
.
CurrentBreakpoint
}
}
// DwarfReader returns a reader for the dwarf data
// DwarfReader returns a reader for the dwarf data
...
@@ -757,7 +781,7 @@ func (dbp *Process) PCToLine(pc uint64) (string, int, *gosym.Func) {
...
@@ -757,7 +781,7 @@ func (dbp *Process) PCToLine(pc uint64) (string, int, *gosym.Func) {
// FindBreakpointByID finds the breakpoint for the given ID.
// FindBreakpointByID finds the breakpoint for the given ID.
func
(
dbp
*
Process
)
FindBreakpointByID
(
id
int
)
(
*
Breakpoint
,
bool
)
{
func
(
dbp
*
Process
)
FindBreakpointByID
(
id
int
)
(
*
Breakpoint
,
bool
)
{
for
_
,
bp
:=
range
dbp
.
B
reakpoints
{
for
_
,
bp
:=
range
dbp
.
b
reakpoints
{
if
bp
.
ID
==
id
{
if
bp
.
ID
==
id
{
return
bp
,
true
return
bp
,
true
}
}
...
@@ -768,11 +792,11 @@ func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) {
...
@@ -768,11 +792,11 @@ func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) {
// FindBreakpoint finds the breakpoint for the given pc.
// FindBreakpoint finds the breakpoint for the given pc.
func
(
dbp
*
Process
)
FindBreakpoint
(
pc
uint64
)
(
*
Breakpoint
,
bool
)
{
func
(
dbp
*
Process
)
FindBreakpoint
(
pc
uint64
)
(
*
Breakpoint
,
bool
)
{
// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
if
bp
,
ok
:=
dbp
.
B
reakpoints
[
pc
-
uint64
(
dbp
.
arch
.
BreakpointSize
())];
ok
{
if
bp
,
ok
:=
dbp
.
b
reakpoints
[
pc
-
uint64
(
dbp
.
arch
.
BreakpointSize
())];
ok
{
return
bp
,
true
return
bp
,
true
}
}
// Directly use addr to lookup breakpoint.
// Directly use addr to lookup breakpoint.
if
bp
,
ok
:=
dbp
.
B
reakpoints
[
pc
];
ok
{
if
bp
,
ok
:=
dbp
.
b
reakpoints
[
pc
];
ok
{
return
bp
,
true
return
bp
,
true
}
}
return
nil
,
false
return
nil
,
false
...
@@ -782,17 +806,17 @@ func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
...
@@ -782,17 +806,17 @@ func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
func
initializeDebugProcess
(
dbp
*
Process
,
path
string
,
attach
bool
)
(
*
Process
,
error
)
{
func
initializeDebugProcess
(
dbp
*
Process
,
path
string
,
attach
bool
)
(
*
Process
,
error
)
{
if
attach
{
if
attach
{
var
err
error
var
err
error
dbp
.
execPtraceFunc
(
func
()
{
err
=
PtraceAttach
(
dbp
.
P
id
)
})
dbp
.
execPtraceFunc
(
func
()
{
err
=
PtraceAttach
(
dbp
.
p
id
)
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
_
,
_
,
err
=
dbp
.
wait
(
dbp
.
P
id
,
0
)
_
,
_
,
err
=
dbp
.
wait
(
dbp
.
p
id
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
}
}
proc
,
err
:=
os
.
FindProcess
(
dbp
.
P
id
)
proc
,
err
:=
os
.
FindProcess
(
dbp
.
p
id
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -813,11 +837,11 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
...
@@ -813,11 +837,11 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
}
}
dbp
.
arch
.
SetGStructOffset
(
ver
,
isextld
)
dbp
.
arch
.
SetGStructOffset
(
ver
,
isextld
)
//
S
electedGoroutine can not be set correctly by the call to updateThreadList
//
s
electedGoroutine can not be set correctly by the call to updateThreadList
// because without calling SetGStructOffset we can not read the G struct of
C
urrentThread
// because without calling SetGStructOffset we can not read the G struct of
c
urrentThread
// but without calling updateThreadList we can not examine memory to determine
// but without calling updateThreadList we can not examine memory to determine
// the offset of g struct inside TLS
// the offset of g struct inside TLS
dbp
.
SelectedGoroutine
,
_
=
dbp
.
C
urrentThread
.
GetG
()
dbp
.
selectedGoroutine
,
_
=
dbp
.
c
urrentThread
.
GetG
()
panicpc
,
err
:=
dbp
.
FindFunctionLocation
(
"runtime.startpanic"
,
true
,
0
)
panicpc
,
err
:=
dbp
.
FindFunctionLocation
(
"runtime.startpanic"
,
true
,
0
)
if
err
==
nil
{
if
err
==
nil
{
...
@@ -833,7 +857,7 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
...
@@ -833,7 +857,7 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
}
}
func
(
dbp
*
Process
)
ClearInternalBreakpoints
()
error
{
func
(
dbp
*
Process
)
ClearInternalBreakpoints
()
error
{
for
_
,
bp
:=
range
dbp
.
B
reakpoints
{
for
_
,
bp
:=
range
dbp
.
b
reakpoints
{
if
!
bp
.
Internal
()
{
if
!
bp
.
Internal
()
{
continue
continue
}
}
...
@@ -841,9 +865,9 @@ func (dbp *Process) ClearInternalBreakpoints() error {
...
@@ -841,9 +865,9 @@ func (dbp *Process) ClearInternalBreakpoints() error {
return
err
return
err
}
}
}
}
for
i
:=
range
dbp
.
T
hreads
{
for
i
:=
range
dbp
.
t
hreads
{
if
dbp
.
Threads
[
i
]
.
CurrentBreakpoint
!=
nil
&&
dbp
.
T
hreads
[
i
]
.
CurrentBreakpoint
.
Internal
()
{
if
dbp
.
threads
[
i
]
.
CurrentBreakpoint
!=
nil
&&
dbp
.
t
hreads
[
i
]
.
CurrentBreakpoint
.
Internal
()
{
dbp
.
T
hreads
[
i
]
.
CurrentBreakpoint
=
nil
dbp
.
t
hreads
[
i
]
.
CurrentBreakpoint
=
nil
}
}
}
}
return
nil
return
nil
...
@@ -901,7 +925,7 @@ func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error)
...
@@ -901,7 +925,7 @@ func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error)
// specified by `gid`.
// specified by `gid`.
func
(
dbp
*
Process
)
FindGoroutine
(
gid
int
)
(
*
G
,
error
)
{
func
(
dbp
*
Process
)
FindGoroutine
(
gid
int
)
(
*
G
,
error
)
{
if
gid
==
-
1
{
if
gid
==
-
1
{
return
dbp
.
S
electedGoroutine
,
nil
return
dbp
.
s
electedGoroutine
,
nil
}
}
gs
,
err
:=
dbp
.
GoroutinesInfo
()
gs
,
err
:=
dbp
.
GoroutinesInfo
()
...
@@ -927,13 +951,13 @@ func (dbp *Process) ConvertEvalScope(gid, frame int) (*EvalScope, error) {
...
@@ -927,13 +951,13 @@ func (dbp *Process) ConvertEvalScope(gid, frame int) (*EvalScope, error) {
return
nil
,
err
return
nil
,
err
}
}
if
g
==
nil
{
if
g
==
nil
{
return
dbp
.
C
urrentThread
.
Scope
()
return
dbp
.
c
urrentThread
.
Scope
()
}
}
var
out
EvalScope
var
out
EvalScope
if
g
.
thread
==
nil
{
if
g
.
thread
==
nil
{
out
.
Thread
=
dbp
.
C
urrentThread
out
.
Thread
=
dbp
.
c
urrentThread
}
else
{
}
else
{
out
.
Thread
=
g
.
thread
out
.
Thread
=
g
.
thread
}
}
...
...
proc/proc_darwin.go
浏览文件 @
26ad5f1d
...
@@ -77,7 +77,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
...
@@ -77,7 +77,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
if
pid
<=
0
{
if
pid
<=
0
{
return
nil
,
fmt
.
Errorf
(
"could not fork/exec"
)
return
nil
,
fmt
.
Errorf
(
"could not fork/exec"
)
}
}
dbp
.
P
id
=
pid
dbp
.
p
id
=
pid
for
i
:=
range
argvSlice
{
for
i
:=
range
argvSlice
{
C
.
free
(
unsafe
.
Pointer
(
argvSlice
[
i
]))
C
.
free
(
unsafe
.
Pointer
(
argvSlice
[
i
]))
}
}
...
@@ -86,7 +86,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
...
@@ -86,7 +86,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
// trapWait to wait until the child process calls execve.
// trapWait to wait until the child process calls execve.
for
{
for
{
err
=
dbp
.
updateThreadListForTask
(
C
.
get_task_for_pid
(
C
.
int
(
dbp
.
P
id
)))
err
=
dbp
.
updateThreadListForTask
(
C
.
get_task_for_pid
(
C
.
int
(
dbp
.
p
id
)))
if
err
==
nil
{
if
err
==
nil
{
break
break
}
}
...
@@ -100,7 +100,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
...
@@ -100,7 +100,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
}
}
dbp
.
allGCache
=
nil
dbp
.
allGCache
=
nil
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
th
.
clearBreakpointState
()
th
.
clearBreakpointState
()
}
}
...
@@ -152,11 +152,11 @@ func (dbp *Process) Kill() (err error) {
...
@@ -152,11 +152,11 @@ func (dbp *Process) Kill() (err error) {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
nil
return
nil
}
}
err
=
sys
.
Kill
(
-
dbp
.
P
id
,
sys
.
SIGKILL
)
err
=
sys
.
Kill
(
-
dbp
.
p
id
,
sys
.
SIGKILL
)
if
err
!=
nil
{
if
err
!=
nil
{
return
errors
.
New
(
"could not deliver signal: "
+
err
.
Error
())
return
errors
.
New
(
"could not deliver signal: "
+
err
.
Error
())
}
}
for
port
:=
range
dbp
.
T
hreads
{
for
port
:=
range
dbp
.
t
hreads
{
if
C
.
thread_resume
(
C
.
thread_act_t
(
port
))
!=
C
.
KERN_SUCCESS
{
if
C
.
thread_resume
(
C
.
thread_act_t
(
port
))
!=
C
.
KERN_SUCCESS
{
return
errors
.
New
(
"could not resume task"
)
return
errors
.
New
(
"could not resume task"
)
}
}
...
@@ -218,12 +218,12 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
...
@@ -218,12 +218,12 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
return
couldNotGetThreadList
return
couldNotGetThreadList
}
}
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
thread
.
os
.
exists
=
false
thread
.
os
.
exists
=
false
}
}
for
_
,
port
:=
range
list
{
for
_
,
port
:=
range
list
{
thread
,
ok
:=
dbp
.
T
hreads
[
int
(
port
)]
thread
,
ok
:=
dbp
.
t
hreads
[
int
(
port
)]
if
!
ok
{
if
!
ok
{
thread
,
err
=
dbp
.
addThread
(
int
(
port
),
false
)
thread
,
err
=
dbp
.
addThread
(
int
(
port
),
false
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -233,9 +233,9 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
...
@@ -233,9 +233,9 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
thread
.
os
.
exists
=
true
thread
.
os
.
exists
=
true
}
}
for
threadID
,
thread
:=
range
dbp
.
T
hreads
{
for
threadID
,
thread
:=
range
dbp
.
t
hreads
{
if
!
thread
.
os
.
exists
{
if
!
thread
.
os
.
exists
{
delete
(
dbp
.
T
hreads
,
threadID
)
delete
(
dbp
.
t
hreads
,
threadID
)
}
}
}
}
...
@@ -243,7 +243,7 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
...
@@ -243,7 +243,7 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
}
}
func
(
dbp
*
Process
)
addThread
(
port
int
,
attach
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
Process
)
addThread
(
port
int
,
attach
bool
)
(
*
Thread
,
error
)
{
if
thread
,
ok
:=
dbp
.
T
hreads
[
port
];
ok
{
if
thread
,
ok
:=
dbp
.
t
hreads
[
port
];
ok
{
return
thread
,
nil
return
thread
,
nil
}
}
thread
:=
&
Thread
{
thread
:=
&
Thread
{
...
@@ -251,7 +251,7 @@ func (dbp *Process) addThread(port int, attach bool) (*Thread, error) {
...
@@ -251,7 +251,7 @@ func (dbp *Process) addThread(port int, attach bool) (*Thread, error) {
dbp
:
dbp
,
dbp
:
dbp
,
os
:
new
(
OSSpecificDetails
),
os
:
new
(
OSSpecificDetails
),
}
}
dbp
.
T
hreads
[
port
]
=
thread
dbp
.
t
hreads
[
port
]
=
thread
thread
.
os
.
threadAct
=
C
.
thread_act_t
(
port
)
thread
.
os
.
threadAct
=
C
.
thread_act_t
(
port
)
if
dbp
.
CurrentThread
==
nil
{
if
dbp
.
CurrentThread
==
nil
{
dbp
.
SwitchThread
(
thread
.
ID
)
dbp
.
SwitchThread
(
thread
.
ID
)
...
@@ -338,7 +338,7 @@ var UnsupportedArchErr = errors.New("unsupported architecture - only darwin/amd6
...
@@ -338,7 +338,7 @@ var UnsupportedArchErr = errors.New("unsupported architecture - only darwin/amd6
func
(
dbp
*
Process
)
findExecutable
(
path
string
)
(
*
macho
.
File
,
string
,
error
)
{
func
(
dbp
*
Process
)
findExecutable
(
path
string
)
(
*
macho
.
File
,
string
,
error
)
{
if
path
==
""
{
if
path
==
""
{
path
=
C
.
GoString
(
C
.
find_executable
(
C
.
int
(
dbp
.
P
id
)))
path
=
C
.
GoString
(
C
.
find_executable
(
C
.
int
(
dbp
.
p
id
)))
}
}
exe
,
err
:=
macho
.
Open
(
path
)
exe
,
err
:=
macho
.
Open
(
path
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -369,16 +369,16 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -369,16 +369,16 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
continue
continue
}
}
if
!
dbp
.
os
.
initialized
{
if
!
dbp
.
os
.
initialized
{
if
pidtask
:=
C
.
get_task_for_pid
(
C
.
int
(
dbp
.
P
id
));
pidtask
!=
0
&&
dbp
.
os
.
task
!=
pidtask
{
if
pidtask
:=
C
.
get_task_for_pid
(
C
.
int
(
dbp
.
p
id
));
pidtask
!=
0
&&
dbp
.
os
.
task
!=
pidtask
{
continue
continue
}
}
}
}
_
,
status
,
err
:=
dbp
.
wait
(
dbp
.
P
id
,
0
)
_
,
status
,
err
:=
dbp
.
wait
(
dbp
.
p
id
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
dbp
.
postExit
()
dbp
.
postExit
()
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
P
id
,
Status
:
status
.
ExitStatus
()}
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
p
id
,
Status
:
status
.
ExitStatus
()}
case
C
.
MACH_RCV_INTERRUPTED
:
case
C
.
MACH_RCV_INTERRUPTED
:
if
!
dbp
.
halt
{
if
!
dbp
.
halt
{
...
@@ -407,7 +407,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -407,7 +407,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
// Since we cannot be notified of new threads on OS X
// Since we cannot be notified of new threads on OS X
// this is as good a time as any to check for them.
// this is as good a time as any to check for them.
dbp
.
updateThreadList
()
dbp
.
updateThreadList
()
th
,
ok
:=
dbp
.
T
hreads
[
int
(
port
)]
th
,
ok
:=
dbp
.
t
hreads
[
int
(
port
)]
if
!
ok
{
if
!
ok
{
if
dbp
.
halt
{
if
dbp
.
halt
{
dbp
.
halt
=
false
dbp
.
halt
=
false
...
@@ -427,7 +427,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -427,7 +427,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
}
}
func
(
dbp
*
Process
)
waitForStop
()
([]
int
,
error
)
{
func
(
dbp
*
Process
)
waitForStop
()
([]
int
,
error
)
{
ports
:=
make
([]
int
,
0
,
len
(
dbp
.
T
hreads
))
ports
:=
make
([]
int
,
0
,
len
(
dbp
.
t
hreads
))
count
:=
0
count
:=
0
for
{
for
{
var
task
C
.
task_t
var
task
C
.
task_t
...
@@ -455,7 +455,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
...
@@ -455,7 +455,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
}
}
trapthread
.
SetCurrentBreakpoint
()
trapthread
.
SetCurrentBreakpoint
()
for
_
,
port
:=
range
ports
{
for
_
,
port
:=
range
ports
{
if
th
,
ok
:=
dbp
.
T
hreads
[
port
];
ok
{
if
th
,
ok
:=
dbp
.
t
hreads
[
port
];
ok
{
err
:=
th
.
SetCurrentBreakpoint
()
err
:=
th
.
SetCurrentBreakpoint
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -483,17 +483,17 @@ func (dbp *Process) exitGuard(err error) error {
...
@@ -483,17 +483,17 @@ func (dbp *Process) exitGuard(err error) error {
if
err
!=
ErrContinueThread
{
if
err
!=
ErrContinueThread
{
return
err
return
err
}
}
_
,
status
,
werr
:=
dbp
.
wait
(
dbp
.
P
id
,
sys
.
WNOHANG
)
_
,
status
,
werr
:=
dbp
.
wait
(
dbp
.
p
id
,
sys
.
WNOHANG
)
if
werr
==
nil
&&
status
.
Exited
()
{
if
werr
==
nil
&&
status
.
Exited
()
{
dbp
.
postExit
()
dbp
.
postExit
()
return
ProcessExitedError
{
Pid
:
dbp
.
P
id
,
Status
:
status
.
ExitStatus
()}
return
ProcessExitedError
{
Pid
:
dbp
.
p
id
,
Status
:
status
.
ExitStatus
()}
}
}
return
err
return
err
}
}
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
Process
)
resume
()
error
{
// all threads stopped over a breakpoint are made to step over it
// all threads stopped over a breakpoint are made to step over it
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
if
thread
.
CurrentBreakpoint
!=
nil
{
if
thread
.
CurrentBreakpoint
!=
nil
{
if
err
:=
thread
.
StepInstruction
();
err
!=
nil
{
if
err
:=
thread
.
StepInstruction
();
err
!=
nil
{
return
err
return
err
...
@@ -502,7 +502,7 @@ func (dbp *Process) resume() error {
...
@@ -502,7 +502,7 @@ func (dbp *Process) resume() error {
}
}
}
}
// everything is resumed
// everything is resumed
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
if
err
:=
thread
.
resume
();
err
!=
nil
{
if
err
:=
thread
.
resume
();
err
!=
nil
{
return
dbp
.
exitGuard
(
err
)
return
dbp
.
exitGuard
(
err
)
}
}
...
...
proc/proc_linux.go
浏览文件 @
26ad5f1d
...
@@ -70,7 +70,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
...
@@ -70,7 +70,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
dbp
.
P
id
=
proc
.
Process
.
Pid
dbp
.
p
id
=
proc
.
Process
.
Pid
_
,
_
,
err
=
dbp
.
wait
(
proc
.
Process
.
Pid
,
0
)
_
,
_
,
err
=
dbp
.
wait
(
proc
.
Process
.
Pid
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"waiting for target execve failed: %s"
,
err
)
return
nil
,
fmt
.
Errorf
(
"waiting for target execve failed: %s"
,
err
)
...
@@ -88,13 +88,13 @@ func (dbp *Process) Kill() (err error) {
...
@@ -88,13 +88,13 @@ func (dbp *Process) Kill() (err error) {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
nil
return
nil
}
}
if
!
dbp
.
Threads
[
dbp
.
P
id
]
.
Stopped
()
{
if
!
dbp
.
threads
[
dbp
.
p
id
]
.
Stopped
()
{
return
errors
.
New
(
"process must be stopped in order to kill it"
)
return
errors
.
New
(
"process must be stopped in order to kill it"
)
}
}
if
err
=
sys
.
Kill
(
-
dbp
.
P
id
,
sys
.
SIGKILL
);
err
!=
nil
{
if
err
=
sys
.
Kill
(
-
dbp
.
p
id
,
sys
.
SIGKILL
);
err
!=
nil
{
return
errors
.
New
(
"could not deliver signal "
+
err
.
Error
())
return
errors
.
New
(
"could not deliver signal "
+
err
.
Error
())
}
}
if
_
,
_
,
err
=
dbp
.
wait
(
dbp
.
P
id
,
0
);
err
!=
nil
{
if
_
,
_
,
err
=
dbp
.
wait
(
dbp
.
p
id
,
0
);
err
!=
nil
{
return
return
}
}
dbp
.
postExit
()
dbp
.
postExit
()
...
@@ -102,13 +102,13 @@ func (dbp *Process) Kill() (err error) {
...
@@ -102,13 +102,13 @@ func (dbp *Process) Kill() (err error) {
}
}
func
(
dbp
*
Process
)
requestManualStop
()
(
err
error
)
{
func
(
dbp
*
Process
)
requestManualStop
()
(
err
error
)
{
return
sys
.
Kill
(
dbp
.
P
id
,
sys
.
SIGTRAP
)
return
sys
.
Kill
(
dbp
.
p
id
,
sys
.
SIGTRAP
)
}
}
// Attach to a newly created thread, and store that thread in our list of
// Attach to a newly created thread, and store that thread in our list of
// known threads.
// known threads.
func
(
dbp
*
Process
)
addThread
(
tid
int
,
attach
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
Process
)
addThread
(
tid
int
,
attach
bool
)
(
*
Thread
,
error
)
{
if
thread
,
ok
:=
dbp
.
T
hreads
[
tid
];
ok
{
if
thread
,
ok
:=
dbp
.
t
hreads
[
tid
];
ok
{
return
thread
,
nil
return
thread
,
nil
}
}
...
@@ -145,26 +145,26 @@ func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) {
...
@@ -145,26 +145,26 @@ func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) {
}
}
}
}
dbp
.
T
hreads
[
tid
]
=
&
Thread
{
dbp
.
t
hreads
[
tid
]
=
&
Thread
{
ID
:
tid
,
ID
:
tid
,
dbp
:
dbp
,
dbp
:
dbp
,
os
:
new
(
OSSpecificDetails
),
os
:
new
(
OSSpecificDetails
),
}
}
if
dbp
.
C
urrentThread
==
nil
{
if
dbp
.
c
urrentThread
==
nil
{
dbp
.
SwitchThread
(
tid
)
dbp
.
SwitchThread
(
tid
)
}
}
return
dbp
.
T
hreads
[
tid
],
nil
return
dbp
.
t
hreads
[
tid
],
nil
}
}
func
(
dbp
*
Process
)
updateThreadList
()
error
{
func
(
dbp
*
Process
)
updateThreadList
()
error
{
tids
,
_
:=
filepath
.
Glob
(
fmt
.
Sprintf
(
"/proc/%d/task/*"
,
dbp
.
P
id
))
tids
,
_
:=
filepath
.
Glob
(
fmt
.
Sprintf
(
"/proc/%d/task/*"
,
dbp
.
p
id
))
for
_
,
tidpath
:=
range
tids
{
for
_
,
tidpath
:=
range
tids
{
tidstr
:=
filepath
.
Base
(
tidpath
)
tidstr
:=
filepath
.
Base
(
tidpath
)
tid
,
err
:=
strconv
.
Atoi
(
tidstr
)
tid
,
err
:=
strconv
.
Atoi
(
tidstr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
_
,
err
:=
dbp
.
addThread
(
tid
,
tid
!=
dbp
.
P
id
);
err
!=
nil
{
if
_
,
err
:=
dbp
.
addThread
(
tid
,
tid
!=
dbp
.
p
id
);
err
!=
nil
{
return
err
return
err
}
}
}
}
...
@@ -175,7 +175,7 @@ var UnsupportedArchErr = errors.New("unsupported architecture - only linux/amd64
...
@@ -175,7 +175,7 @@ var UnsupportedArchErr = errors.New("unsupported architecture - only linux/amd64
func
(
dbp
*
Process
)
findExecutable
(
path
string
)
(
*
elf
.
File
,
string
,
error
)
{
func
(
dbp
*
Process
)
findExecutable
(
path
string
)
(
*
elf
.
File
,
string
,
error
)
{
if
path
==
""
{
if
path
==
""
{
path
=
fmt
.
Sprintf
(
"/proc/%d/exe"
,
dbp
.
P
id
)
path
=
fmt
.
Sprintf
(
"/proc/%d/exe"
,
dbp
.
p
id
)
}
}
f
,
err
:=
os
.
OpenFile
(
path
,
0
,
os
.
ModePerm
)
f
,
err
:=
os
.
OpenFile
(
path
,
0
,
os
.
ModePerm
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -279,16 +279,16 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -279,16 +279,16 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
if
wpid
==
0
{
if
wpid
==
0
{
continue
continue
}
}
th
,
ok
:=
dbp
.
T
hreads
[
wpid
]
th
,
ok
:=
dbp
.
t
hreads
[
wpid
]
if
ok
{
if
ok
{
th
.
Status
=
(
*
WaitStatus
)(
status
)
th
.
Status
=
(
*
WaitStatus
)(
status
)
}
}
if
status
.
Exited
()
{
if
status
.
Exited
()
{
if
wpid
==
dbp
.
P
id
{
if
wpid
==
dbp
.
p
id
{
dbp
.
postExit
()
dbp
.
postExit
()
return
nil
,
ProcessExitedError
{
Pid
:
wpid
,
Status
:
status
.
ExitStatus
()}
return
nil
,
ProcessExitedError
{
Pid
:
wpid
,
Status
:
status
.
ExitStatus
()}
}
}
delete
(
dbp
.
T
hreads
,
wpid
)
delete
(
dbp
.
t
hreads
,
wpid
)
continue
continue
}
}
if
status
.
StopSignal
()
==
sys
.
SIGTRAP
&&
status
.
TrapCause
()
==
sys
.
PTRACE_EVENT_CLONE
{
if
status
.
StopSignal
()
==
sys
.
SIGTRAP
&&
status
.
TrapCause
()
==
sys
.
PTRACE_EVENT_CLONE
{
...
@@ -314,12 +314,12 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -314,12 +314,12 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
if
err
=
th
.
Continue
();
err
!=
nil
{
if
err
=
th
.
Continue
();
err
!=
nil
{
if
err
==
sys
.
ESRCH
{
if
err
==
sys
.
ESRCH
{
// thread died while we were adding it
// thread died while we were adding it
delete
(
dbp
.
T
hreads
,
th
.
ID
)
delete
(
dbp
.
t
hreads
,
th
.
ID
)
continue
continue
}
}
return
nil
,
fmt
.
Errorf
(
"could not continue new thread %d %s"
,
cloned
,
err
)
return
nil
,
fmt
.
Errorf
(
"could not continue new thread %d %s"
,
cloned
,
err
)
}
}
if
err
=
dbp
.
T
hreads
[
int
(
wpid
)]
.
Continue
();
err
!=
nil
{
if
err
=
dbp
.
t
hreads
[
int
(
wpid
)]
.
Continue
();
err
!=
nil
{
if
err
!=
sys
.
ESRCH
{
if
err
!=
sys
.
ESRCH
{
return
nil
,
fmt
.
Errorf
(
"could not continue existing thread %d %s"
,
wpid
,
err
)
return
nil
,
fmt
.
Errorf
(
"could not continue existing thread %d %s"
,
wpid
,
err
)
}
}
...
@@ -343,7 +343,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -343,7 +343,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
// TODO(dp) alert user about unexpected signals here.
// TODO(dp) alert user about unexpected signals here.
if
err
:=
th
.
resumeWithSig
(
int
(
status
.
StopSignal
()));
err
!=
nil
{
if
err
:=
th
.
resumeWithSig
(
int
(
status
.
StopSignal
()));
err
!=
nil
{
if
err
==
sys
.
ESRCH
{
if
err
==
sys
.
ESRCH
{
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
P
id
}
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
p
id
}
}
}
return
nil
,
err
return
nil
,
err
}
}
...
@@ -354,19 +354,19 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -354,19 +354,19 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
func
(
dbp
*
Process
)
loadProcessInformation
(
wg
*
sync
.
WaitGroup
)
{
func
(
dbp
*
Process
)
loadProcessInformation
(
wg
*
sync
.
WaitGroup
)
{
defer
wg
.
Done
()
defer
wg
.
Done
()
comm
,
err
:=
ioutil
.
ReadFile
(
fmt
.
Sprintf
(
"/proc/%d/comm"
,
dbp
.
P
id
))
comm
,
err
:=
ioutil
.
ReadFile
(
fmt
.
Sprintf
(
"/proc/%d/comm"
,
dbp
.
p
id
))
if
err
==
nil
{
if
err
==
nil
{
// removes newline character
// removes newline character
comm
=
bytes
.
TrimSuffix
(
comm
,
[]
byte
(
"
\n
"
))
comm
=
bytes
.
TrimSuffix
(
comm
,
[]
byte
(
"
\n
"
))
}
}
if
comm
==
nil
||
len
(
comm
)
<=
0
{
if
comm
==
nil
||
len
(
comm
)
<=
0
{
stat
,
err
:=
ioutil
.
ReadFile
(
fmt
.
Sprintf
(
"/proc/%d/stat"
,
dbp
.
P
id
))
stat
,
err
:=
ioutil
.
ReadFile
(
fmt
.
Sprintf
(
"/proc/%d/stat"
,
dbp
.
p
id
))
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Printf
(
"Could not read proc stat: %v
\n
"
,
err
)
fmt
.
Printf
(
"Could not read proc stat: %v
\n
"
,
err
)
os
.
Exit
(
1
)
os
.
Exit
(
1
)
}
}
expr
:=
fmt
.
Sprintf
(
"%d
\\
s*
\\
((.*)
\\
)"
,
dbp
.
P
id
)
expr
:=
fmt
.
Sprintf
(
"%d
\\
s*
\\
((.*)
\\
)"
,
dbp
.
p
id
)
rexp
,
err
:=
regexp
.
Compile
(
expr
)
rexp
,
err
:=
regexp
.
Compile
(
expr
)
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Printf
(
"Regexp compile error: %v
\n
"
,
err
)
fmt
.
Printf
(
"Regexp compile error: %v
\n
"
,
err
)
...
@@ -374,7 +374,7 @@ func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) {
...
@@ -374,7 +374,7 @@ func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) {
}
}
match
:=
rexp
.
FindSubmatch
(
stat
)
match
:=
rexp
.
FindSubmatch
(
stat
)
if
match
==
nil
{
if
match
==
nil
{
fmt
.
Printf
(
"No match found using regexp '%s' in /proc/%d/stat
\n
"
,
expr
,
dbp
.
P
id
)
fmt
.
Printf
(
"No match found using regexp '%s' in /proc/%d/stat
\n
"
,
expr
,
dbp
.
p
id
)
os
.
Exit
(
1
)
os
.
Exit
(
1
)
}
}
comm
=
match
[
1
]
comm
=
match
[
1
]
...
@@ -411,7 +411,7 @@ func (dbp *Process) waitFast(pid int) (int, *sys.WaitStatus, error) {
...
@@ -411,7 +411,7 @@ func (dbp *Process) waitFast(pid int) (int, *sys.WaitStatus, error) {
func
(
dbp
*
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
func
(
dbp
*
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
var
s
sys
.
WaitStatus
var
s
sys
.
WaitStatus
if
(
pid
!=
dbp
.
P
id
)
||
(
options
!=
0
)
{
if
(
pid
!=
dbp
.
p
id
)
||
(
options
!=
0
)
{
wpid
,
err
:=
sys
.
Wait4
(
pid
,
&
s
,
sys
.
WALL
|
options
,
nil
)
wpid
,
err
:=
sys
.
Wait4
(
pid
,
&
s
,
sys
.
WALL
|
options
,
nil
)
return
wpid
,
&
s
,
err
return
wpid
,
&
s
,
err
}
}
...
@@ -442,7 +442,7 @@ func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) {
...
@@ -442,7 +442,7 @@ func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) {
}
}
func
(
dbp
*
Process
)
setCurrentBreakpoints
(
trapthread
*
Thread
)
error
{
func
(
dbp
*
Process
)
setCurrentBreakpoints
(
trapthread
*
Thread
)
error
{
for
_
,
th
:=
range
dbp
.
T
hreads
{
for
_
,
th
:=
range
dbp
.
t
hreads
{
if
th
.
CurrentBreakpoint
==
nil
{
if
th
.
CurrentBreakpoint
==
nil
{
err
:=
th
.
SetCurrentBreakpoint
()
err
:=
th
.
SetCurrentBreakpoint
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -457,7 +457,7 @@ func (dbp *Process) exitGuard(err error) error {
...
@@ -457,7 +457,7 @@ func (dbp *Process) exitGuard(err error) error {
if
err
!=
sys
.
ESRCH
{
if
err
!=
sys
.
ESRCH
{
return
err
return
err
}
}
if
status
(
dbp
.
P
id
,
dbp
.
os
.
comm
)
==
StatusZombie
{
if
status
(
dbp
.
p
id
,
dbp
.
os
.
comm
)
==
StatusZombie
{
_
,
err
:=
dbp
.
trapWait
(
-
1
)
_
,
err
:=
dbp
.
trapWait
(
-
1
)
return
err
return
err
}
}
...
@@ -467,7 +467,7 @@ func (dbp *Process) exitGuard(err error) error {
...
@@ -467,7 +467,7 @@ func (dbp *Process) exitGuard(err error) error {
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
Process
)
resume
()
error
{
// all threads stopped over a breakpoint are made to step over it
// all threads stopped over a breakpoint are made to step over it
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
if
thread
.
CurrentBreakpoint
!=
nil
{
if
thread
.
CurrentBreakpoint
!=
nil
{
if
err
:=
thread
.
StepInstruction
();
err
!=
nil
{
if
err
:=
thread
.
StepInstruction
();
err
!=
nil
{
return
err
return
err
...
@@ -476,7 +476,7 @@ func (dbp *Process) resume() error {
...
@@ -476,7 +476,7 @@ func (dbp *Process) resume() error {
}
}
}
}
// everything is resumed
// everything is resumed
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
if
err
:=
thread
.
resume
();
err
!=
nil
&&
err
!=
sys
.
ESRCH
{
if
err
:=
thread
.
resume
();
err
!=
nil
&&
err
!=
sys
.
ESRCH
{
return
err
return
err
}
}
...
...
proc/proc_test.go
浏览文件 @
26ad5f1d
...
@@ -108,7 +108,7 @@ func TestExit(t *testing.T) {
...
@@ -108,7 +108,7 @@ func TestExit(t *testing.T) {
if
pe
.
Status
!=
0
{
if
pe
.
Status
!=
0
{
t
.
Errorf
(
"Unexpected error status: %d"
,
pe
.
Status
)
t
.
Errorf
(
"Unexpected error status: %d"
,
pe
.
Status
)
}
}
if
pe
.
Pid
!=
p
.
P
id
{
if
pe
.
Pid
!=
p
.
p
id
{
t
.
Errorf
(
"Unexpected process id: %d"
,
pe
.
Pid
)
t
.
Errorf
(
"Unexpected process id: %d"
,
pe
.
Pid
)
}
}
})
})
...
@@ -127,7 +127,7 @@ func TestExitAfterContinue(t *testing.T) {
...
@@ -127,7 +127,7 @@ func TestExitAfterContinue(t *testing.T) {
if
pe
.
Status
!=
0
{
if
pe
.
Status
!=
0
{
t
.
Errorf
(
"Unexpected error status: %d"
,
pe
.
Status
)
t
.
Errorf
(
"Unexpected error status: %d"
,
pe
.
Status
)
}
}
if
pe
.
Pid
!=
p
.
P
id
{
if
pe
.
Pid
!=
p
.
p
id
{
t
.
Errorf
(
"Unexpected process id: %d"
,
pe
.
Pid
)
t
.
Errorf
(
"Unexpected process id: %d"
,
pe
.
Pid
)
}
}
})
})
...
@@ -159,7 +159,7 @@ func TestHalt(t *testing.T) {
...
@@ -159,7 +159,7 @@ func TestHalt(t *testing.T) {
_
,
err
:=
setFunctionBreakpoint
(
p
,
"main.loop"
)
_
,
err
:=
setFunctionBreakpoint
(
p
,
"main.loop"
)
assertNoError
(
err
,
t
,
"SetBreakpoint"
)
assertNoError
(
err
,
t
,
"SetBreakpoint"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue"
)
for
_
,
th
:=
range
p
.
T
hreads
{
for
_
,
th
:=
range
p
.
t
hreads
{
if
th
.
running
!=
false
{
if
th
.
running
!=
false
{
t
.
Fatal
(
"expected running = false for thread"
,
th
.
ID
)
t
.
Fatal
(
"expected running = false for thread"
,
th
.
ID
)
}
}
...
@@ -182,7 +182,7 @@ func TestHalt(t *testing.T) {
...
@@ -182,7 +182,7 @@ func TestHalt(t *testing.T) {
// Loop through threads and make sure they are all
// Loop through threads and make sure they are all
// actually stopped, err will not be nil if the process
// actually stopped, err will not be nil if the process
// is still running.
// is still running.
for
_
,
th
:=
range
p
.
T
hreads
{
for
_
,
th
:=
range
p
.
t
hreads
{
if
!
th
.
Stopped
()
{
if
!
th
.
Stopped
()
{
t
.
Fatal
(
"expected thread to be stopped, but was not"
)
t
.
Fatal
(
"expected thread to be stopped, but was not"
)
}
}
...
@@ -207,7 +207,7 @@ func TestStep(t *testing.T) {
...
@@ -207,7 +207,7 @@ func TestStep(t *testing.T) {
regs
:=
getRegisters
(
p
,
t
)
regs
:=
getRegisters
(
p
,
t
)
rip
:=
regs
.
PC
()
rip
:=
regs
.
PC
()
err
=
p
.
C
urrentThread
.
StepInstruction
()
err
=
p
.
c
urrentThread
.
StepInstruction
()
assertNoError
(
err
,
t
,
"Step()"
)
assertNoError
(
err
,
t
,
"Step()"
)
regs
=
getRegisters
(
p
,
t
)
regs
=
getRegisters
(
p
,
t
)
...
@@ -289,7 +289,7 @@ func TestClearBreakpointBreakpoint(t *testing.T) {
...
@@ -289,7 +289,7 @@ func TestClearBreakpointBreakpoint(t *testing.T) {
bp
,
err
=
p
.
ClearBreakpoint
(
fn
.
Entry
)
bp
,
err
=
p
.
ClearBreakpoint
(
fn
.
Entry
)
assertNoError
(
err
,
t
,
"ClearBreakpoint()"
)
assertNoError
(
err
,
t
,
"ClearBreakpoint()"
)
data
,
err
:=
dataAtAddr
(
p
.
C
urrentThread
,
bp
.
Addr
)
data
,
err
:=
dataAtAddr
(
p
.
c
urrentThread
,
bp
.
Addr
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -311,7 +311,7 @@ type nextTest struct {
...
@@ -311,7 +311,7 @@ type nextTest struct {
func
countBreakpoints
(
p
*
Process
)
int
{
func
countBreakpoints
(
p
*
Process
)
int
{
bpcount
:=
0
bpcount
:=
0
for
_
,
bp
:=
range
p
.
B
reakpoints
{
for
_
,
bp
:=
range
p
.
b
reakpoints
{
if
bp
.
ID
>=
0
{
if
bp
.
ID
>=
0
{
bpcount
++
bpcount
++
}
}
...
@@ -341,11 +341,11 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc
...
@@ -341,11 +341,11 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc
assertNoError
(
err
,
t
,
"SetBreakpoint()"
)
assertNoError
(
err
,
t
,
"SetBreakpoint()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
p
.
ClearBreakpoint
(
bp
.
Addr
)
p
.
ClearBreakpoint
(
bp
.
Addr
)
p
.
C
urrentThread
.
SetPC
(
bp
.
Addr
)
p
.
c
urrentThread
.
SetPC
(
bp
.
Addr
)
f
,
ln
:=
currentLineNumber
(
p
,
t
)
f
,
ln
:=
currentLineNumber
(
p
,
t
)
for
_
,
tc
:=
range
testcases
{
for
_
,
tc
:=
range
testcases
{
pc
,
_
:=
p
.
C
urrentThread
.
PC
()
pc
,
_
:=
p
.
c
urrentThread
.
PC
()
if
ln
!=
tc
.
begin
{
if
ln
!=
tc
.
begin
{
t
.
Fatalf
(
"Program not stopped at correct spot expected %d was %s:%d"
,
tc
.
begin
,
filepath
.
Base
(
f
),
ln
)
t
.
Fatalf
(
"Program not stopped at correct spot expected %d was %s:%d"
,
tc
.
begin
,
filepath
.
Base
(
f
),
ln
)
}
}
...
@@ -358,14 +358,14 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc
...
@@ -358,14 +358,14 @@ func testseq(program string, contFunc contFunc, testcases []nextTest, initialLoc
}
}
f
,
ln
=
currentLineNumber
(
p
,
t
)
f
,
ln
=
currentLineNumber
(
p
,
t
)
pc
,
_
=
p
.
C
urrentThread
.
PC
()
pc
,
_
=
p
.
c
urrentThread
.
PC
()
if
ln
!=
tc
.
end
{
if
ln
!=
tc
.
end
{
t
.
Fatalf
(
"Program did not continue to correct next location expected %d was %s:%d (%#x)"
,
tc
.
end
,
filepath
.
Base
(
f
),
ln
,
pc
)
t
.
Fatalf
(
"Program did not continue to correct next location expected %d was %s:%d (%#x)"
,
tc
.
end
,
filepath
.
Base
(
f
),
ln
,
pc
)
}
}
}
}
if
countBreakpoints
(
p
)
!=
0
{
if
countBreakpoints
(
p
)
!=
0
{
t
.
Fatal
(
"Not all breakpoints were cleaned up"
,
len
(
p
.
B
reakpoints
))
t
.
Fatal
(
"Not all breakpoints were cleaned up"
,
len
(
p
.
b
reakpoints
))
}
}
})
})
}
}
...
@@ -434,10 +434,10 @@ func TestNextConcurrent(t *testing.T) {
...
@@ -434,10 +434,10 @@ func TestNextConcurrent(t *testing.T) {
_
,
err
=
p
.
ClearBreakpoint
(
bp
.
Addr
)
_
,
err
=
p
.
ClearBreakpoint
(
bp
.
Addr
)
assertNoError
(
err
,
t
,
"ClearBreakpoint()"
)
assertNoError
(
err
,
t
,
"ClearBreakpoint()"
)
for
_
,
tc
:=
range
testcases
{
for
_
,
tc
:=
range
testcases
{
g
,
err
:=
p
.
C
urrentThread
.
GetG
()
g
,
err
:=
p
.
c
urrentThread
.
GetG
()
assertNoError
(
err
,
t
,
"GetG()"
)
assertNoError
(
err
,
t
,
"GetG()"
)
if
p
.
S
electedGoroutine
.
ID
!=
g
.
ID
{
if
p
.
s
electedGoroutine
.
ID
!=
g
.
ID
{
t
.
Fatalf
(
"SelectedGoroutine not CurrentThread's goroutine: %d %d"
,
g
.
ID
,
p
.
S
electedGoroutine
.
ID
)
t
.
Fatalf
(
"SelectedGoroutine not CurrentThread's goroutine: %d %d"
,
g
.
ID
,
p
.
s
electedGoroutine
.
ID
)
}
}
if
ln
!=
tc
.
begin
{
if
ln
!=
tc
.
begin
{
t
.
Fatalf
(
"Program not stopped at correct spot expected %d was %s:%d"
,
tc
.
begin
,
filepath
.
Base
(
f
),
ln
)
t
.
Fatalf
(
"Program not stopped at correct spot expected %d was %s:%d"
,
tc
.
begin
,
filepath
.
Base
(
f
),
ln
)
...
@@ -473,10 +473,10 @@ func TestNextConcurrentVariant2(t *testing.T) {
...
@@ -473,10 +473,10 @@ func TestNextConcurrentVariant2(t *testing.T) {
initVval
,
_
:=
constant
.
Int64Val
(
initV
.
Value
)
initVval
,
_
:=
constant
.
Int64Val
(
initV
.
Value
)
assertNoError
(
err
,
t
,
"EvalVariable"
)
assertNoError
(
err
,
t
,
"EvalVariable"
)
for
_
,
tc
:=
range
testcases
{
for
_
,
tc
:=
range
testcases
{
g
,
err
:=
p
.
C
urrentThread
.
GetG
()
g
,
err
:=
p
.
c
urrentThread
.
GetG
()
assertNoError
(
err
,
t
,
"GetG()"
)
assertNoError
(
err
,
t
,
"GetG()"
)
if
p
.
S
electedGoroutine
.
ID
!=
g
.
ID
{
if
p
.
s
electedGoroutine
.
ID
!=
g
.
ID
{
t
.
Fatalf
(
"SelectedGoroutine not CurrentThread's goroutine: %d %d"
,
g
.
ID
,
p
.
S
electedGoroutine
.
ID
)
t
.
Fatalf
(
"SelectedGoroutine not CurrentThread's goroutine: %d %d"
,
g
.
ID
,
p
.
s
electedGoroutine
.
ID
)
}
}
if
ln
!=
tc
.
begin
{
if
ln
!=
tc
.
begin
{
t
.
Fatalf
(
"Program not stopped at correct spot expected %d was %s:%d"
,
tc
.
begin
,
filepath
.
Base
(
f
),
ln
)
t
.
Fatalf
(
"Program not stopped at correct spot expected %d was %s:%d"
,
tc
.
begin
,
filepath
.
Base
(
f
),
ln
)
...
@@ -487,7 +487,7 @@ func TestNextConcurrentVariant2(t *testing.T) {
...
@@ -487,7 +487,7 @@ func TestNextConcurrentVariant2(t *testing.T) {
v
,
err
:=
evalVariable
(
p
,
"n"
)
v
,
err
:=
evalVariable
(
p
,
"n"
)
assertNoError
(
err
,
t
,
"EvalVariable"
)
assertNoError
(
err
,
t
,
"EvalVariable"
)
vval
,
_
=
constant
.
Int64Val
(
v
.
Value
)
vval
,
_
=
constant
.
Int64Val
(
v
.
Value
)
if
p
.
C
urrentThread
.
CurrentBreakpoint
==
nil
{
if
p
.
c
urrentThread
.
CurrentBreakpoint
==
nil
{
if
vval
!=
initVval
{
if
vval
!=
initVval
{
t
.
Fatal
(
"Did not end up on same goroutine"
)
t
.
Fatal
(
"Did not end up on same goroutine"
)
}
}
...
@@ -599,7 +599,7 @@ func TestFindReturnAddress(t *testing.T) {
...
@@ -599,7 +599,7 @@ func TestFindReturnAddress(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
addr
,
err
:=
p
.
C
urrentThread
.
ReturnAddress
()
addr
,
err
:=
p
.
c
urrentThread
.
ReturnAddress
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -623,7 +623,7 @@ func TestFindReturnAddressTopOfStackFn(t *testing.T) {
...
@@ -623,7 +623,7 @@ func TestFindReturnAddressTopOfStackFn(t *testing.T) {
if
err
:=
p
.
Continue
();
err
!=
nil
{
if
err
:=
p
.
Continue
();
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
_
,
err
:=
p
.
C
urrentThread
.
ReturnAddress
();
err
==
nil
{
if
_
,
err
:=
p
.
c
urrentThread
.
ReturnAddress
();
err
==
nil
{
t
.
Fatal
(
"expected error to be returned"
)
t
.
Fatal
(
"expected error to be returned"
)
}
}
})
})
...
@@ -649,8 +649,8 @@ func TestSwitchThread(t *testing.T) {
...
@@ -649,8 +649,8 @@ func TestSwitchThread(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
var
nt
int
var
nt
int
ct
:=
p
.
C
urrentThread
.
ID
ct
:=
p
.
c
urrentThread
.
ID
for
tid
:=
range
p
.
T
hreads
{
for
tid
:=
range
p
.
t
hreads
{
if
tid
!=
ct
{
if
tid
!=
ct
{
nt
=
tid
nt
=
tid
break
break
...
@@ -664,7 +664,7 @@ func TestSwitchThread(t *testing.T) {
...
@@ -664,7 +664,7 @@ func TestSwitchThread(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
p
.
C
urrentThread
.
ID
!=
nt
{
if
p
.
c
urrentThread
.
ID
!=
nt
{
t
.
Fatal
(
"Did not switch threads"
)
t
.
Fatal
(
"Did not switch threads"
)
}
}
})
})
...
@@ -725,7 +725,7 @@ func TestStacktrace(t *testing.T) {
...
@@ -725,7 +725,7 @@ func TestStacktrace(t *testing.T) {
for
i
:=
range
stacks
{
for
i
:=
range
stacks
{
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
locations
,
err
:=
p
.
C
urrentThread
.
Stacktrace
(
40
)
locations
,
err
:=
p
.
c
urrentThread
.
Stacktrace
(
40
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
if
len
(
locations
)
!=
len
(
stacks
[
i
])
+
2
{
if
len
(
locations
)
!=
len
(
stacks
[
i
])
+
2
{
...
@@ -753,7 +753,7 @@ func TestStacktrace2(t *testing.T) {
...
@@ -753,7 +753,7 @@ func TestStacktrace2(t *testing.T) {
withTestProcess
(
"retstack"
,
t
,
func
(
p
*
Process
,
fixture
protest
.
Fixture
)
{
withTestProcess
(
"retstack"
,
t
,
func
(
p
*
Process
,
fixture
protest
.
Fixture
)
{
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
locations
,
err
:=
p
.
C
urrentThread
.
Stacktrace
(
40
)
locations
,
err
:=
p
.
c
urrentThread
.
Stacktrace
(
40
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
if
!
stackMatch
([]
loc
{{
-
1
,
"main.f"
},
{
16
,
"main.main"
}},
locations
,
false
)
{
if
!
stackMatch
([]
loc
{{
-
1
,
"main.f"
},
{
16
,
"main.main"
}},
locations
,
false
)
{
for
i
:=
range
locations
{
for
i
:=
range
locations
{
...
@@ -763,7 +763,7 @@ func TestStacktrace2(t *testing.T) {
...
@@ -763,7 +763,7 @@ func TestStacktrace2(t *testing.T) {
}
}
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
locations
,
err
=
p
.
C
urrentThread
.
Stacktrace
(
40
)
locations
,
err
=
p
.
c
urrentThread
.
Stacktrace
(
40
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
if
!
stackMatch
([]
loc
{{
-
1
,
"main.g"
},
{
17
,
"main.main"
}},
locations
,
false
)
{
if
!
stackMatch
([]
loc
{{
-
1
,
"main.g"
},
{
17
,
"main.main"
}},
locations
,
false
)
{
for
i
:=
range
locations
{
for
i
:=
range
locations
{
...
@@ -863,9 +863,9 @@ func TestKill(t *testing.T) {
...
@@ -863,9 +863,9 @@ func TestKill(t *testing.T) {
t
.
Fatal
(
"expected process to have exited"
)
t
.
Fatal
(
"expected process to have exited"
)
}
}
if
runtime
.
GOOS
==
"linux"
{
if
runtime
.
GOOS
==
"linux"
{
_
,
err
:=
os
.
Open
(
fmt
.
Sprintf
(
"/proc/%d/"
,
p
.
P
id
))
_
,
err
:=
os
.
Open
(
fmt
.
Sprintf
(
"/proc/%d/"
,
p
.
p
id
))
if
err
==
nil
{
if
err
==
nil
{
t
.
Fatal
(
"process has not exited"
,
p
.
P
id
)
t
.
Fatal
(
"process has not exited"
,
p
.
p
id
)
}
}
}
}
})
})
...
@@ -877,7 +877,7 @@ func testGSupportFunc(name string, t *testing.T, p *Process, fixture protest.Fix
...
@@ -877,7 +877,7 @@ func testGSupportFunc(name string, t *testing.T, p *Process, fixture protest.Fix
assertNoError
(
p
.
Continue
(),
t
,
name
+
": Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
name
+
": Continue()"
)
g
,
err
:=
p
.
C
urrentThread
.
GetG
()
g
,
err
:=
p
.
c
urrentThread
.
GetG
()
assertNoError
(
err
,
t
,
name
+
": GetG()"
)
assertNoError
(
err
,
t
,
name
+
": GetG()"
)
if
g
==
nil
{
if
g
==
nil
{
...
@@ -1005,7 +1005,7 @@ func TestIssue239(t *testing.T) {
...
@@ -1005,7 +1005,7 @@ func TestIssue239(t *testing.T) {
}
}
func
evalVariable
(
p
*
Process
,
symbol
string
)
(
*
Variable
,
error
)
{
func
evalVariable
(
p
*
Process
,
symbol
string
)
(
*
Variable
,
error
)
{
scope
,
err
:=
p
.
C
urrentThread
.
Scope
()
scope
,
err
:=
p
.
c
urrentThread
.
Scope
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -1013,7 +1013,7 @@ func evalVariable(p *Process, symbol string) (*Variable, error) {
...
@@ -1013,7 +1013,7 @@ func evalVariable(p *Process, symbol string) (*Variable, error) {
}
}
func
setVariable
(
p
*
Process
,
symbol
,
value
string
)
error
{
func
setVariable
(
p
*
Process
,
symbol
,
value
string
)
error
{
scope
,
err
:=
p
.
C
urrentThread
.
Scope
()
scope
,
err
:=
p
.
c
urrentThread
.
Scope
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -1152,7 +1152,7 @@ func TestFrameEvaluation(t *testing.T) {
...
@@ -1152,7 +1152,7 @@ func TestFrameEvaluation(t *testing.T) {
// Testing evaluation on frames
// Testing evaluation on frames
assertNoError
(
p
.
Continue
(),
t
,
"Continue() 2"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue() 2"
)
g
,
err
:=
p
.
C
urrentThread
.
GetG
()
g
,
err
:=
p
.
c
urrentThread
.
GetG
()
assertNoError
(
err
,
t
,
"GetG()"
)
assertNoError
(
err
,
t
,
"GetG()"
)
for
i
:=
0
;
i
<=
3
;
i
++
{
for
i
:=
0
;
i
<=
3
;
i
++
{
...
@@ -1185,7 +1185,7 @@ func TestPointerSetting(t *testing.T) {
...
@@ -1185,7 +1185,7 @@ func TestPointerSetting(t *testing.T) {
pval
(
1
)
pval
(
1
)
// change p1 to point to i2
// change p1 to point to i2
scope
,
err
:=
p
.
C
urrentThread
.
Scope
()
scope
,
err
:=
p
.
c
urrentThread
.
Scope
()
assertNoError
(
err
,
t
,
"Scope()"
)
assertNoError
(
err
,
t
,
"Scope()"
)
i2addr
,
err
:=
scope
.
EvalExpression
(
"i2"
,
normalLoadConfig
)
i2addr
,
err
:=
scope
.
EvalExpression
(
"i2"
,
normalLoadConfig
)
assertNoError
(
err
,
t
,
"EvalExpression()"
)
assertNoError
(
err
,
t
,
"EvalExpression()"
)
...
@@ -1320,7 +1320,7 @@ func TestBreakpointCountsWithDetection(t *testing.T) {
...
@@ -1320,7 +1320,7 @@ func TestBreakpointCountsWithDetection(t *testing.T) {
}
}
assertNoError
(
err
,
t
,
"Continue()"
)
assertNoError
(
err
,
t
,
"Continue()"
)
}
}
for
_
,
th
:=
range
p
.
T
hreads
{
for
_
,
th
:=
range
p
.
t
hreads
{
if
th
.
CurrentBreakpoint
==
nil
{
if
th
.
CurrentBreakpoint
==
nil
{
continue
continue
}
}
...
@@ -1454,7 +1454,7 @@ func TestIssue341(t *testing.T) {
...
@@ -1454,7 +1454,7 @@ func TestIssue341(t *testing.T) {
func
BenchmarkLocalVariables
(
b
*
testing
.
B
)
{
func
BenchmarkLocalVariables
(
b
*
testing
.
B
)
{
withTestProcess
(
"testvariables"
,
b
,
func
(
p
*
Process
,
fixture
protest
.
Fixture
)
{
withTestProcess
(
"testvariables"
,
b
,
func
(
p
*
Process
,
fixture
protest
.
Fixture
)
{
assertNoError
(
p
.
Continue
(),
b
,
"Continue() returned an error"
)
assertNoError
(
p
.
Continue
(),
b
,
"Continue() returned an error"
)
scope
,
err
:=
p
.
C
urrentThread
.
Scope
()
scope
,
err
:=
p
.
c
urrentThread
.
Scope
()
assertNoError
(
err
,
b
,
"Scope()"
)
assertNoError
(
err
,
b
,
"Scope()"
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
_
,
err
:=
scope
.
LocalVariables
(
normalLoadConfig
)
_
,
err
:=
scope
.
LocalVariables
(
normalLoadConfig
)
...
@@ -1588,7 +1588,7 @@ func TestIssue332_Part1(t *testing.T) {
...
@@ -1588,7 +1588,7 @@ func TestIssue332_Part1(t *testing.T) {
assertNoError
(
err
,
t
,
"SetBreakpoint()"
)
assertNoError
(
err
,
t
,
"SetBreakpoint()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Next
(),
t
,
"first Next()"
)
assertNoError
(
p
.
Next
(),
t
,
"first Next()"
)
locations
,
err
:=
p
.
C
urrentThread
.
Stacktrace
(
2
)
locations
,
err
:=
p
.
c
urrentThread
.
Stacktrace
(
2
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
if
locations
[
0
]
.
Call
.
Fn
==
nil
{
if
locations
[
0
]
.
Call
.
Fn
==
nil
{
t
.
Fatalf
(
"Not on a function"
)
t
.
Fatalf
(
"Not on a function"
)
...
@@ -1617,7 +1617,7 @@ func TestIssue332_Part2(t *testing.T) {
...
@@ -1617,7 +1617,7 @@ func TestIssue332_Part2(t *testing.T) {
// step until we enter changeMe
// step until we enter changeMe
for
{
for
{
assertNoError
(
p
.
Step
(),
t
,
"Step()"
)
assertNoError
(
p
.
Step
(),
t
,
"Step()"
)
locations
,
err
:=
p
.
C
urrentThread
.
Stacktrace
(
2
)
locations
,
err
:=
p
.
c
urrentThread
.
Stacktrace
(
2
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
if
locations
[
0
]
.
Call
.
Fn
==
nil
{
if
locations
[
0
]
.
Call
.
Fn
==
nil
{
t
.
Fatalf
(
"Not on a function"
)
t
.
Fatalf
(
"Not on a function"
)
...
@@ -1627,7 +1627,7 @@ func TestIssue332_Part2(t *testing.T) {
...
@@ -1627,7 +1627,7 @@ func TestIssue332_Part2(t *testing.T) {
}
}
}
}
pc
,
err
:=
p
.
C
urrentThread
.
PC
()
pc
,
err
:=
p
.
c
urrentThread
.
PC
()
assertNoError
(
err
,
t
,
"PC()"
)
assertNoError
(
err
,
t
,
"PC()"
)
pcAfterPrologue
,
err
:=
p
.
FindFunctionLocation
(
"main.changeMe"
,
true
,
-
1
)
pcAfterPrologue
,
err
:=
p
.
FindFunctionLocation
(
"main.changeMe"
,
true
,
-
1
)
assertNoError
(
err
,
t
,
"FindFunctionLocation()"
)
assertNoError
(
err
,
t
,
"FindFunctionLocation()"
)
...
@@ -1680,7 +1680,7 @@ func TestPackageVariables(t *testing.T) {
...
@@ -1680,7 +1680,7 @@ func TestPackageVariables(t *testing.T) {
withTestProcess
(
"testvariables"
,
t
,
func
(
p
*
Process
,
fixture
protest
.
Fixture
)
{
withTestProcess
(
"testvariables"
,
t
,
func
(
p
*
Process
,
fixture
protest
.
Fixture
)
{
err
:=
p
.
Continue
()
err
:=
p
.
Continue
()
assertNoError
(
err
,
t
,
"Continue()"
)
assertNoError
(
err
,
t
,
"Continue()"
)
scope
,
err
:=
p
.
C
urrentThread
.
Scope
()
scope
,
err
:=
p
.
c
urrentThread
.
Scope
()
assertNoError
(
err
,
t
,
"Scope()"
)
assertNoError
(
err
,
t
,
"Scope()"
)
vars
,
err
:=
scope
.
PackageVariables
(
normalLoadConfig
)
vars
,
err
:=
scope
.
PackageVariables
(
normalLoadConfig
)
assertNoError
(
err
,
t
,
"PackageVariables()"
)
assertNoError
(
err
,
t
,
"PackageVariables()"
)
...
@@ -1714,7 +1714,7 @@ func TestPanicBreakpoint(t *testing.T) {
...
@@ -1714,7 +1714,7 @@ func TestPanicBreakpoint(t *testing.T) {
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
bp
:=
p
.
CurrentBreakpoint
()
bp
:=
p
.
CurrentBreakpoint
()
if
bp
==
nil
||
bp
.
Name
!=
"unrecovered-panic"
{
if
bp
==
nil
||
bp
.
Name
!=
"unrecovered-panic"
{
t
.
Fatalf
(
"not on unrecovered-panic breakpoint: %v"
,
p
.
CurrentBreakpoint
)
t
.
Fatalf
(
"not on unrecovered-panic breakpoint: %v"
,
p
.
CurrentBreakpoint
()
)
}
}
})
})
}
}
...
@@ -1724,7 +1724,7 @@ func TestCmdLineArgs(t *testing.T) {
...
@@ -1724,7 +1724,7 @@ func TestCmdLineArgs(t *testing.T) {
err
:=
p
.
Continue
()
err
:=
p
.
Continue
()
bp
:=
p
.
CurrentBreakpoint
()
bp
:=
p
.
CurrentBreakpoint
()
if
bp
!=
nil
&&
bp
.
Name
==
"unrecovered-panic"
{
if
bp
!=
nil
&&
bp
.
Name
==
"unrecovered-panic"
{
t
.
Fatalf
(
"testing args failed on unrecovered-panic breakpoint: %v"
,
p
.
CurrentBreakpoint
)
t
.
Fatalf
(
"testing args failed on unrecovered-panic breakpoint: %v"
,
p
.
CurrentBreakpoint
()
)
}
}
exit
,
exited
:=
err
.
(
ProcessExitedError
)
exit
,
exited
:=
err
.
(
ProcessExitedError
)
if
!
exited
{
if
!
exited
{
...
@@ -1740,7 +1740,7 @@ func TestCmdLineArgs(t *testing.T) {
...
@@ -1740,7 +1740,7 @@ func TestCmdLineArgs(t *testing.T) {
p
.
Continue
()
p
.
Continue
()
bp
:=
p
.
CurrentBreakpoint
()
bp
:=
p
.
CurrentBreakpoint
()
if
bp
==
nil
||
bp
.
Name
!=
"unrecovered-panic"
{
if
bp
==
nil
||
bp
.
Name
!=
"unrecovered-panic"
{
t
.
Fatalf
(
"not on unrecovered-panic breakpoint: %v"
,
p
.
CurrentBreakpoint
)
t
.
Fatalf
(
"not on unrecovered-panic breakpoint: %v"
,
p
.
CurrentBreakpoint
()
)
}
}
}
}
...
@@ -1783,7 +1783,7 @@ func TestIssue462(t *testing.T) {
...
@@ -1783,7 +1783,7 @@ func TestIssue462(t *testing.T) {
}()
}()
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
_
,
err
:=
p
.
C
urrentThread
.
Stacktrace
(
40
)
_
,
err
:=
p
.
c
urrentThread
.
Stacktrace
(
40
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
assertNoError
(
err
,
t
,
"Stacktrace()"
)
})
})
}
}
...
@@ -1828,8 +1828,8 @@ func TestNextParked(t *testing.T) {
...
@@ -1828,8 +1828,8 @@ func TestNextParked(t *testing.T) {
p
.
ClearBreakpoint
(
bp
.
Addr
)
p
.
ClearBreakpoint
(
bp
.
Addr
)
assertNoError
(
p
.
Next
(),
t
,
"Next()"
)
assertNoError
(
p
.
Next
(),
t
,
"Next()"
)
if
p
.
S
electedGoroutine
.
ID
!=
parkedg
.
ID
{
if
p
.
s
electedGoroutine
.
ID
!=
parkedg
.
ID
{
t
.
Fatalf
(
"Next did not continue on the selected goroutine, expected %d got %d"
,
parkedg
.
ID
,
p
.
S
electedGoroutine
.
ID
)
t
.
Fatalf
(
"Next did not continue on the selected goroutine, expected %d got %d"
,
parkedg
.
ID
,
p
.
s
electedGoroutine
.
ID
)
}
}
})
})
}
}
...
@@ -1865,8 +1865,8 @@ func TestStepParked(t *testing.T) {
...
@@ -1865,8 +1865,8 @@ func TestStepParked(t *testing.T) {
p
.
ClearBreakpoint
(
bp
.
Addr
)
p
.
ClearBreakpoint
(
bp
.
Addr
)
assertNoError
(
p
.
Step
(),
t
,
"Step()"
)
assertNoError
(
p
.
Step
(),
t
,
"Step()"
)
if
p
.
S
electedGoroutine
.
ID
!=
parkedg
.
ID
{
if
p
.
s
electedGoroutine
.
ID
!=
parkedg
.
ID
{
t
.
Fatalf
(
"Step did not continue on the selected goroutine, expected %d got %d"
,
parkedg
.
ID
,
p
.
S
electedGoroutine
.
ID
)
t
.
Fatalf
(
"Step did not continue on the selected goroutine, expected %d got %d"
,
parkedg
.
ID
,
p
.
s
electedGoroutine
.
ID
)
}
}
})
})
}
}
...
@@ -2093,7 +2093,7 @@ func TestStepConcurrentDirect(t *testing.T) {
...
@@ -2093,7 +2093,7 @@ func TestStepConcurrentDirect(t *testing.T) {
_
,
err
=
p
.
ClearBreakpoint
(
bp
.
Addr
)
_
,
err
=
p
.
ClearBreakpoint
(
bp
.
Addr
)
assertNoError
(
err
,
t
,
"ClearBreakpoint()"
)
assertNoError
(
err
,
t
,
"ClearBreakpoint()"
)
gid
:=
p
.
S
electedGoroutine
.
ID
gid
:=
p
.
s
electedGoroutine
.
ID
seq
:=
[]
int
{
37
,
38
,
13
,
15
,
16
,
38
}
seq
:=
[]
int
{
37
,
38
,
13
,
15
,
16
,
38
}
...
@@ -2108,8 +2108,8 @@ func TestStepConcurrentDirect(t *testing.T) {
...
@@ -2108,8 +2108,8 @@ func TestStepConcurrentDirect(t *testing.T) {
}
}
t
.
Fatalf
(
"Program did not continue at expected location (%d) %s:%d"
,
seq
[
i
],
f
,
ln
)
t
.
Fatalf
(
"Program did not continue at expected location (%d) %s:%d"
,
seq
[
i
],
f
,
ln
)
}
}
if
p
.
S
electedGoroutine
.
ID
!=
gid
{
if
p
.
s
electedGoroutine
.
ID
!=
gid
{
t
.
Fatalf
(
"Step switched to different goroutine %d %d
\n
"
,
gid
,
p
.
S
electedGoroutine
.
ID
)
t
.
Fatalf
(
"Step switched to different goroutine %d %d
\n
"
,
gid
,
p
.
s
electedGoroutine
.
ID
)
}
}
i
=
(
i
+
1
)
%
len
(
seq
)
i
=
(
i
+
1
)
%
len
(
seq
)
if
i
==
0
{
if
i
==
0
{
...
@@ -2125,7 +2125,7 @@ func TestStepConcurrentDirect(t *testing.T) {
...
@@ -2125,7 +2125,7 @@ func TestStepConcurrentDirect(t *testing.T) {
}
}
func
nextInProgress
(
p
*
Process
)
bool
{
func
nextInProgress
(
p
*
Process
)
bool
{
for
_
,
bp
:=
range
p
.
B
reakpoints
{
for
_
,
bp
:=
range
p
.
b
reakpoints
{
if
bp
.
Internal
()
{
if
bp
.
Internal
()
{
return
true
return
true
}
}
...
@@ -2155,7 +2155,7 @@ func TestStepConcurrentPtr(t *testing.T) {
...
@@ -2155,7 +2155,7 @@ func TestStepConcurrentPtr(t *testing.T) {
t
.
Fatalf
(
"Program did not continue at expected location (24): %s:%d"
,
f
,
ln
)
t
.
Fatalf
(
"Program did not continue at expected location (24): %s:%d"
,
f
,
ln
)
}
}
gid
:=
p
.
S
electedGoroutine
.
ID
gid
:=
p
.
s
electedGoroutine
.
ID
kvar
,
err
:=
evalVariable
(
p
,
"k"
)
kvar
,
err
:=
evalVariable
(
p
,
"k"
)
assertNoError
(
err
,
t
,
"EvalVariable()"
)
assertNoError
(
err
,
t
,
"EvalVariable()"
)
...
@@ -2170,14 +2170,14 @@ func TestStepConcurrentPtr(t *testing.T) {
...
@@ -2170,14 +2170,14 @@ func TestStepConcurrentPtr(t *testing.T) {
assertNoError
(
p
.
Step
(),
t
,
"Step()"
)
assertNoError
(
p
.
Step
(),
t
,
"Step()"
)
for
nextInProgress
(
p
)
{
for
nextInProgress
(
p
)
{
if
p
.
S
electedGoroutine
.
ID
==
gid
{
if
p
.
s
electedGoroutine
.
ID
==
gid
{
t
.
Fatalf
(
"step did not step into function call (but internal breakpoints still active?) (%d %d)"
,
gid
,
p
.
S
electedGoroutine
.
ID
)
t
.
Fatalf
(
"step did not step into function call (but internal breakpoints still active?) (%d %d)"
,
gid
,
p
.
s
electedGoroutine
.
ID
)
}
}
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue()"
)
}
}
if
p
.
S
electedGoroutine
.
ID
!=
gid
{
if
p
.
s
electedGoroutine
.
ID
!=
gid
{
t
.
Fatalf
(
"Step switched goroutines (wanted: %d got: %d)"
,
gid
,
p
.
S
electedGoroutine
.
ID
)
t
.
Fatalf
(
"Step switched goroutines (wanted: %d got: %d)"
,
gid
,
p
.
s
electedGoroutine
.
ID
)
}
}
f
,
ln
=
currentLineNumber
(
p
,
t
)
f
,
ln
=
currentLineNumber
(
p
,
t
)
...
@@ -2256,9 +2256,9 @@ func TestStepOnCallPtrInstr(t *testing.T) {
...
@@ -2256,9 +2256,9 @@ func TestStepOnCallPtrInstr(t *testing.T) {
if
ln
!=
10
{
if
ln
!=
10
{
break
break
}
}
pc
,
err
:=
p
.
C
urrentThread
.
PC
()
pc
,
err
:=
p
.
c
urrentThread
.
PC
()
assertNoError
(
err
,
t
,
"PC()"
)
assertNoError
(
err
,
t
,
"PC()"
)
text
,
err
:=
p
.
C
urrentThread
.
Disassemble
(
pc
,
pc
+
maxInstructionLength
,
true
)
text
,
err
:=
p
.
c
urrentThread
.
Disassemble
(
pc
,
pc
+
maxInstructionLength
,
true
)
assertNoError
(
err
,
t
,
"Disassemble()"
)
assertNoError
(
err
,
t
,
"Disassemble()"
)
if
text
[
0
]
.
IsCall
()
{
if
text
[
0
]
.
IsCall
()
{
found
=
true
found
=
true
...
@@ -2394,7 +2394,7 @@ func BenchmarkTrace(b *testing.B) {
...
@@ -2394,7 +2394,7 @@ func BenchmarkTrace(b *testing.B) {
b
.
ResetTimer
()
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
assertNoError
(
p
.
Continue
(),
b
,
"Continue()"
)
assertNoError
(
p
.
Continue
(),
b
,
"Continue()"
)
s
,
err
:=
p
.
C
urrentThread
.
Scope
()
s
,
err
:=
p
.
c
urrentThread
.
Scope
()
assertNoError
(
err
,
b
,
"Scope()"
)
assertNoError
(
err
,
b
,
"Scope()"
)
_
,
err
=
s
.
FunctionArguments
(
LoadConfig
{
false
,
0
,
64
,
0
,
3
})
_
,
err
=
s
.
FunctionArguments
(
LoadConfig
{
false
,
0
,
64
,
0
,
3
})
assertNoError
(
err
,
b
,
"FunctionArguments()"
)
assertNoError
(
err
,
b
,
"FunctionArguments()"
)
...
...
proc/proc_unix_test.go
浏览文件 @
26ad5f1d
...
@@ -17,7 +17,7 @@ func TestIssue419(t *testing.T) {
...
@@ -17,7 +17,7 @@ func TestIssue419(t *testing.T) {
for
{
for
{
if
p
.
Running
()
{
if
p
.
Running
()
{
time
.
Sleep
(
2
*
time
.
Second
)
time
.
Sleep
(
2
*
time
.
Second
)
err
:=
syscall
.
Kill
(
p
.
P
id
,
syscall
.
SIGINT
)
err
:=
syscall
.
Kill
(
p
.
p
id
,
syscall
.
SIGINT
)
assertNoError
(
err
,
t
,
"syscall.Kill"
)
assertNoError
(
err
,
t
,
"syscall.Kill"
)
return
return
}
}
...
...
proc/proc_windows.go
浏览文件 @
26ad5f1d
...
@@ -113,7 +113,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
...
@@ -113,7 +113,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Process
))
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Process
))
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Thread
))
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Thread
))
dbp
.
P
id
=
int
(
pi
.
ProcessId
)
dbp
.
p
id
=
int
(
pi
.
ProcessId
)
return
newDebugProcess
(
dbp
,
argv0Go
)
return
newDebugProcess
(
dbp
,
argv0Go
)
}
}
...
@@ -135,11 +135,11 @@ func newDebugProcess(dbp *Process, exepath string) (*Process, error) {
...
@@ -135,11 +135,11 @@ func newDebugProcess(dbp *Process, exepath string) (*Process, error) {
}
}
if
tid
==
0
{
if
tid
==
0
{
dbp
.
postExit
()
dbp
.
postExit
()
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
P
id
,
Status
:
exitCode
}
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
p
id
,
Status
:
exitCode
}
}
}
// Suspend all threads so that the call to _ContinueDebugEvent will
// Suspend all threads so that the call to _ContinueDebugEvent will
// not resume the target.
// not resume the target.
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
_
,
err
:=
_SuspendThread
(
thread
.
os
.
hThread
)
_
,
err
:=
_SuspendThread
(
thread
.
os
.
hThread
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -147,7 +147,7 @@ func newDebugProcess(dbp *Process, exepath string) (*Process, error) {
...
@@ -147,7 +147,7 @@ func newDebugProcess(dbp *Process, exepath string) (*Process, error) {
}
}
dbp
.
execPtraceFunc
(
func
()
{
dbp
.
execPtraceFunc
(
func
()
{
err
=
_ContinueDebugEvent
(
uint32
(
dbp
.
P
id
),
uint32
(
dbp
.
os
.
breakThread
),
_DBG_CONTINUE
)
err
=
_ContinueDebugEvent
(
uint32
(
dbp
.
p
id
),
uint32
(
dbp
.
os
.
breakThread
),
_DBG_CONTINUE
)
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -209,7 +209,7 @@ func (dbp *Process) Kill() error {
...
@@ -209,7 +209,7 @@ func (dbp *Process) Kill() error {
if
dbp
.
exited
{
if
dbp
.
exited
{
return
nil
return
nil
}
}
if
!
dbp
.
Threads
[
dbp
.
P
id
]
.
Stopped
()
{
if
!
dbp
.
threads
[
dbp
.
p
id
]
.
Stopped
()
{
return
errors
.
New
(
"process must be stopped in order to kill it"
)
return
errors
.
New
(
"process must be stopped in order to kill it"
)
}
}
// TODO: Should not have to ignore failures here,
// TODO: Should not have to ignore failures here,
...
@@ -231,7 +231,7 @@ func (dbp *Process) updateThreadList() error {
...
@@ -231,7 +231,7 @@ func (dbp *Process) updateThreadList() error {
}
}
func
(
dbp
*
Process
)
addThread
(
hThread
syscall
.
Handle
,
threadID
int
,
attach
,
suspendNewThreads
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
Process
)
addThread
(
hThread
syscall
.
Handle
,
threadID
int
,
attach
,
suspendNewThreads
bool
)
(
*
Thread
,
error
)
{
if
thread
,
ok
:=
dbp
.
T
hreads
[
threadID
];
ok
{
if
thread
,
ok
:=
dbp
.
t
hreads
[
threadID
];
ok
{
return
thread
,
nil
return
thread
,
nil
}
}
thread
:=
&
Thread
{
thread
:=
&
Thread
{
...
@@ -240,7 +240,7 @@ func (dbp *Process) addThread(hThread syscall.Handle, threadID int, attach, susp
...
@@ -240,7 +240,7 @@ func (dbp *Process) addThread(hThread syscall.Handle, threadID int, attach, susp
os
:
new
(
OSSpecificDetails
),
os
:
new
(
OSSpecificDetails
),
}
}
thread
.
os
.
hThread
=
hThread
thread
.
os
.
hThread
=
hThread
dbp
.
T
hreads
[
threadID
]
=
thread
dbp
.
t
hreads
[
threadID
]
=
thread
if
dbp
.
CurrentThread
==
nil
{
if
dbp
.
CurrentThread
==
nil
{
dbp
.
SwitchThread
(
thread
.
ID
)
dbp
.
SwitchThread
(
thread
.
ID
)
}
}
...
@@ -488,7 +488,7 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e
...
@@ -488,7 +488,7 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e
}
}
break
break
case
_EXIT_THREAD_DEBUG_EVENT
:
case
_EXIT_THREAD_DEBUG_EVENT
:
delete
(
dbp
.
T
hreads
,
int
(
debugEvent
.
ThreadId
))
delete
(
dbp
.
t
hreads
,
int
(
debugEvent
.
ThreadId
))
break
break
case
_OUTPUT_DEBUG_STRING_EVENT
:
case
_OUTPUT_DEBUG_STRING_EVENT
:
//TODO: Handle debug output strings
//TODO: Handle debug output strings
...
@@ -547,9 +547,9 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
...
@@ -547,9 +547,9 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
}
}
if
tid
==
0
{
if
tid
==
0
{
dbp
.
postExit
()
dbp
.
postExit
()
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
P
id
,
Status
:
exitCode
}
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
p
id
,
Status
:
exitCode
}
}
}
th
:=
dbp
.
T
hreads
[
tid
]
th
:=
dbp
.
t
hreads
[
tid
]
return
th
,
nil
return
th
,
nil
}
}
...
@@ -577,7 +577,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
...
@@ -577,7 +577,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
return
err
return
err
}
}
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
thread
.
running
=
false
thread
.
running
=
false
_
,
err
:=
_SuspendThread
(
thread
.
os
.
hThread
)
_
,
err
:=
_SuspendThread
(
thread
.
os
.
hThread
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -589,7 +589,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
...
@@ -589,7 +589,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
var
err
error
var
err
error
var
tid
int
var
tid
int
dbp
.
execPtraceFunc
(
func
()
{
dbp
.
execPtraceFunc
(
func
()
{
err
=
_ContinueDebugEvent
(
uint32
(
dbp
.
P
id
),
uint32
(
dbp
.
os
.
breakThread
),
_DBG_CONTINUE
)
err
=
_ContinueDebugEvent
(
uint32
(
dbp
.
p
id
),
uint32
(
dbp
.
os
.
breakThread
),
_DBG_CONTINUE
)
if
err
==
nil
{
if
err
==
nil
{
tid
,
_
,
_
=
dbp
.
waitForDebugEvent
(
waitSuspendNewThreads
)
tid
,
_
,
_
=
dbp
.
waitForDebugEvent
(
waitSuspendNewThreads
)
}
}
...
@@ -600,7 +600,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
...
@@ -600,7 +600,7 @@ func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
if
tid
==
0
{
if
tid
==
0
{
break
break
}
}
err
=
dbp
.
T
hreads
[
tid
]
.
SetCurrentBreakpoint
()
err
=
dbp
.
t
hreads
[
tid
]
.
SetCurrentBreakpoint
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -614,7 +614,7 @@ func (dbp *Process) exitGuard(err error) error {
...
@@ -614,7 +614,7 @@ func (dbp *Process) exitGuard(err error) error {
}
}
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
Process
)
resume
()
error
{
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
if
thread
.
CurrentBreakpoint
!=
nil
{
if
thread
.
CurrentBreakpoint
!=
nil
{
if
err
:=
thread
.
StepInstruction
();
err
!=
nil
{
if
err
:=
thread
.
StepInstruction
();
err
!=
nil
{
return
err
return
err
...
@@ -623,7 +623,7 @@ func (dbp *Process) resume() error {
...
@@ -623,7 +623,7 @@ func (dbp *Process) resume() error {
}
}
}
}
for
_
,
thread
:=
range
dbp
.
T
hreads
{
for
_
,
thread
:=
range
dbp
.
t
hreads
{
thread
.
running
=
true
thread
.
running
=
true
_
,
err
:=
_ResumeThread
(
thread
.
os
.
hThread
)
_
,
err
:=
_ResumeThread
(
thread
.
os
.
hThread
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
proc/stack.go
浏览文件 @
26ad5f1d
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"encoding/binary"
"encoding/binary"
"errors"
"errors"
"fmt"
"fmt"
"github.com/derekparker/delve/dwarf/frame"
"github.com/derekparker/delve/dwarf/frame"
)
)
...
@@ -222,7 +223,7 @@ func (dbp *Process) frameInfo(pc, sp uint64, top bool) (Stackframe, error) {
...
@@ -222,7 +223,7 @@ func (dbp *Process) frameInfo(pc, sp uint64, top bool) (Stackframe, error) {
if
retaddr
==
0
{
if
retaddr
==
0
{
return
Stackframe
{},
NullAddrError
{}
return
Stackframe
{},
NullAddrError
{}
}
}
data
,
err
:=
dbp
.
C
urrentThread
.
readMemory
(
retaddr
,
dbp
.
arch
.
PtrSize
())
data
,
err
:=
dbp
.
c
urrentThread
.
readMemory
(
retaddr
,
dbp
.
arch
.
PtrSize
())
if
err
!=
nil
{
if
err
!=
nil
{
return
Stackframe
{},
err
return
Stackframe
{},
err
}
}
...
...
proc/threads.go
浏览文件 @
26ad5f1d
...
@@ -154,7 +154,7 @@ func topframe(g *G, thread *Thread) (Stackframe, error) {
...
@@ -154,7 +154,7 @@ func topframe(g *G, thread *Thread) (Stackframe, error) {
// Continue will take care of setting a breakpoint to the destination
// Continue will take care of setting a breakpoint to the destination
// once the CALL is reached.
// once the CALL is reached.
func
(
dbp
*
Process
)
next
(
stepInto
bool
)
error
{
func
(
dbp
*
Process
)
next
(
stepInto
bool
)
error
{
topframe
,
err
:=
topframe
(
dbp
.
SelectedGoroutine
,
dbp
.
C
urrentThread
)
topframe
,
err
:=
topframe
(
dbp
.
selectedGoroutine
,
dbp
.
c
urrentThread
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -167,10 +167,10 @@ func (dbp *Process) next(stepInto bool) error {
...
@@ -167,10 +167,10 @@ func (dbp *Process) next(stepInto bool) error {
}()
}()
csource
:=
filepath
.
Ext
(
topframe
.
Current
.
File
)
!=
".go"
csource
:=
filepath
.
Ext
(
topframe
.
Current
.
File
)
!=
".go"
thread
:=
dbp
.
C
urrentThread
thread
:=
dbp
.
c
urrentThread
currentGoroutine
:=
false
currentGoroutine
:=
false
if
dbp
.
SelectedGoroutine
!=
nil
&&
dbp
.
S
electedGoroutine
.
thread
!=
nil
{
if
dbp
.
selectedGoroutine
!=
nil
&&
dbp
.
s
electedGoroutine
.
thread
!=
nil
{
thread
=
dbp
.
S
electedGoroutine
.
thread
thread
=
dbp
.
s
electedGoroutine
.
thread
currentGoroutine
=
true
currentGoroutine
=
true
}
}
...
@@ -179,7 +179,7 @@ func (dbp *Process) next(stepInto bool) error {
...
@@ -179,7 +179,7 @@ func (dbp *Process) next(stepInto bool) error {
return
err
return
err
}
}
cond
:=
sameGoroutineCondition
(
dbp
.
S
electedGoroutine
)
cond
:=
sameGoroutineCondition
(
dbp
.
s
electedGoroutine
)
if
stepInto
{
if
stepInto
{
for
_
,
instr
:=
range
text
{
for
_
,
instr
:=
range
text
{
...
@@ -215,8 +215,8 @@ func (dbp *Process) next(stepInto bool) error {
...
@@ -215,8 +215,8 @@ func (dbp *Process) next(stepInto bool) error {
// Set breakpoint on the most recently deferred function (if any)
// Set breakpoint on the most recently deferred function (if any)
var
deferpc
uint64
=
0
var
deferpc
uint64
=
0
if
dbp
.
S
electedGoroutine
!=
nil
{
if
dbp
.
s
electedGoroutine
!=
nil
{
deferPCEntry
:=
dbp
.
S
electedGoroutine
.
DeferPC
()
deferPCEntry
:=
dbp
.
s
electedGoroutine
.
DeferPC
()
if
deferPCEntry
!=
0
{
if
deferPCEntry
!=
0
{
_
,
_
,
deferfn
:=
dbp
.
goSymTable
.
PCToLine
(
deferPCEntry
)
_
,
_
,
deferfn
:=
dbp
.
goSymTable
.
PCToLine
(
deferPCEntry
)
var
err
error
var
err
error
...
@@ -256,7 +256,7 @@ func (dbp *Process) next(stepInto bool) error {
...
@@ -256,7 +256,7 @@ func (dbp *Process) next(stepInto bool) error {
if
!
covered
{
if
!
covered
{
fn
:=
dbp
.
goSymTable
.
PCToFunc
(
topframe
.
Ret
)
fn
:=
dbp
.
goSymTable
.
PCToFunc
(
topframe
.
Ret
)
if
dbp
.
S
electedGoroutine
!=
nil
&&
fn
!=
nil
&&
fn
.
Name
==
"runtime.goexit"
{
if
dbp
.
s
electedGoroutine
!=
nil
&&
fn
!=
nil
&&
fn
.
Name
==
"runtime.goexit"
{
return
nil
return
nil
}
}
}
}
...
@@ -342,7 +342,7 @@ func (thread *Thread) getGVariable() (*Variable, error) {
...
@@ -342,7 +342,7 @@ func (thread *Thread) getGVariable() (*Variable, error) {
if
thread
.
dbp
.
arch
.
GStructOffset
()
==
0
{
if
thread
.
dbp
.
arch
.
GStructOffset
()
==
0
{
// GetG was called through SwitchThread / updateThreadList during initialization
// GetG was called through SwitchThread / updateThreadList during initialization
// thread.dbp.arch isn't setup yet (it needs a
CurrentT
hread to read global variables from)
// thread.dbp.arch isn't setup yet (it needs a
current t
hread to read global variables from)
return
nil
,
fmt
.
Errorf
(
"g struct offset not initialized"
)
return
nil
,
fmt
.
Errorf
(
"g struct offset not initialized"
)
}
}
...
@@ -490,9 +490,9 @@ func (thread *Thread) onRuntimeBreakpoint() bool {
...
@@ -490,9 +490,9 @@ func (thread *Thread) onRuntimeBreakpoint() bool {
// onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command
// onNextGorutine returns true if this thread is on the goroutine requested by the current 'next' command
func
(
thread
*
Thread
)
onNextGoroutine
()
(
bool
,
error
)
{
func
(
thread
*
Thread
)
onNextGoroutine
()
(
bool
,
error
)
{
var
bp
*
Breakpoint
var
bp
*
Breakpoint
for
i
:=
range
thread
.
dbp
.
B
reakpoints
{
for
i
:=
range
thread
.
dbp
.
b
reakpoints
{
if
thread
.
dbp
.
B
reakpoints
[
i
]
.
Internal
()
{
if
thread
.
dbp
.
b
reakpoints
[
i
]
.
Internal
()
{
bp
=
thread
.
dbp
.
B
reakpoints
[
i
]
bp
=
thread
.
dbp
.
b
reakpoints
[
i
]
break
break
}
}
}
}
...
...
proc/threads_linux.go
浏览文件 @
26ad5f1d
...
@@ -15,7 +15,7 @@ type OSSpecificDetails struct {
...
@@ -15,7 +15,7 @@ type OSSpecificDetails struct {
}
}
func
(
t
*
Thread
)
halt
()
(
err
error
)
{
func
(
t
*
Thread
)
halt
()
(
err
error
)
{
err
=
sys
.
Tgkill
(
t
.
dbp
.
P
id
,
t
.
ID
,
sys
.
SIGSTOP
)
err
=
sys
.
Tgkill
(
t
.
dbp
.
p
id
,
t
.
ID
,
sys
.
SIGSTOP
)
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"halt err %s on thread %d"
,
err
,
t
.
ID
)
err
=
fmt
.
Errorf
(
"halt err %s on thread %d"
,
err
,
t
.
ID
)
return
return
...
@@ -53,13 +53,13 @@ func (t *Thread) singleStep() (err error) {
...
@@ -53,13 +53,13 @@ func (t *Thread) singleStep() (err error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
(
status
==
nil
||
status
.
Exited
())
&&
wpid
==
t
.
dbp
.
P
id
{
if
(
status
==
nil
||
status
.
Exited
())
&&
wpid
==
t
.
dbp
.
p
id
{
t
.
dbp
.
postExit
()
t
.
dbp
.
postExit
()
rs
:=
0
rs
:=
0
if
status
!=
nil
{
if
status
!=
nil
{
rs
=
status
.
ExitStatus
()
rs
=
status
.
ExitStatus
()
}
}
return
ProcessExitedError
{
Pid
:
t
.
dbp
.
P
id
,
Status
:
rs
}
return
ProcessExitedError
{
Pid
:
t
.
dbp
.
p
id
,
Status
:
rs
}
}
}
if
wpid
==
t
.
ID
&&
status
.
StopSignal
()
==
sys
.
SIGTRAP
{
if
wpid
==
t
.
ID
&&
status
.
StopSignal
()
==
sys
.
SIGTRAP
{
return
nil
return
nil
...
...
proc/threads_windows.go
浏览文件 @
26ad5f1d
...
@@ -57,7 +57,7 @@ func (t *Thread) singleStep() error {
...
@@ -57,7 +57,7 @@ func (t *Thread) singleStep() error {
}
}
if
tid
==
0
{
if
tid
==
0
{
t
.
dbp
.
postExit
()
t
.
dbp
.
postExit
()
return
ProcessExitedError
{
Pid
:
t
.
dbp
.
P
id
,
Status
:
exitCode
}
return
ProcessExitedError
{
Pid
:
t
.
dbp
.
p
id
,
Status
:
exitCode
}
}
}
if
t
.
dbp
.
os
.
breakThread
==
t
.
ID
{
if
t
.
dbp
.
os
.
breakThread
==
t
.
ID
{
...
@@ -65,7 +65,7 @@ func (t *Thread) singleStep() error {
...
@@ -65,7 +65,7 @@ func (t *Thread) singleStep() error {
}
}
t
.
dbp
.
execPtraceFunc
(
func
()
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
_ContinueDebugEvent
(
uint32
(
t
.
dbp
.
P
id
),
uint32
(
t
.
dbp
.
os
.
breakThread
),
_DBG_CONTINUE
)
err
=
_ContinueDebugEvent
(
uint32
(
t
.
dbp
.
p
id
),
uint32
(
t
.
dbp
.
os
.
breakThread
),
_DBG_CONTINUE
)
})
})
}
}
...
@@ -75,7 +75,7 @@ func (t *Thread) singleStep() error {
...
@@ -75,7 +75,7 @@ func (t *Thread) singleStep() error {
}
}
t
.
dbp
.
execPtraceFunc
(
func
()
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
_ContinueDebugEvent
(
uint32
(
t
.
dbp
.
P
id
),
uint32
(
t
.
ID
),
_DBG_CONTINUE
)
err
=
_ContinueDebugEvent
(
uint32
(
t
.
dbp
.
p
id
),
uint32
(
t
.
ID
),
_DBG_CONTINUE
)
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -98,7 +98,7 @@ func (t *Thread) resume() error {
...
@@ -98,7 +98,7 @@ func (t *Thread) resume() error {
t
.
dbp
.
execPtraceFunc
(
func
()
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
//TODO: Note that we are ignoring the thread we were asked to continue and are continuing the
//TODO: Note that we are ignoring the thread we were asked to continue and are continuing the
//thread that we last broke on.
//thread that we last broke on.
err
=
_ContinueDebugEvent
(
uint32
(
t
.
dbp
.
P
id
),
uint32
(
t
.
ID
),
_DBG_CONTINUE
)
err
=
_ContinueDebugEvent
(
uint32
(
t
.
dbp
.
p
id
),
uint32
(
t
.
ID
),
_DBG_CONTINUE
)
})
})
return
err
return
err
}
}
...
...
proc/variables.go
浏览文件 @
26ad5f1d
...
@@ -649,7 +649,7 @@ func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) {
...
@@ -649,7 +649,7 @@ func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) {
// EvalPackageVariable will evaluate the package level variable
// EvalPackageVariable will evaluate the package level variable
// specified by 'name'.
// specified by 'name'.
func
(
dbp
*
Process
)
EvalPackageVariable
(
name
string
,
cfg
LoadConfig
)
(
*
Variable
,
error
)
{
func
(
dbp
*
Process
)
EvalPackageVariable
(
name
string
,
cfg
LoadConfig
)
(
*
Variable
,
error
)
{
scope
:=
&
EvalScope
{
Thread
:
dbp
.
C
urrentThread
,
PC
:
0
,
CFA
:
0
}
scope
:=
&
EvalScope
{
Thread
:
dbp
.
c
urrentThread
,
PC
:
0
,
CFA
:
0
}
v
,
err
:=
scope
.
packageVarAddr
(
name
)
v
,
err
:=
scope
.
packageVarAddr
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
service/debugger/debugger.go
浏览文件 @
26ad5f1d
...
@@ -13,6 +13,7 @@ import (
...
@@ -13,6 +13,7 @@ import (
"sync"
"sync"
"time"
"time"
"github.com/derekparker/delve/pkg/target"
"github.com/derekparker/delve/proc"
"github.com/derekparker/delve/proc"
"github.com/derekparker/delve/service/api"
"github.com/derekparker/delve/service/api"
)
)
...
@@ -26,9 +27,10 @@ import (
...
@@ -26,9 +27,10 @@ import (
// functionality needed by clients, but not needed in
// functionality needed by clients, but not needed in
// lower lever packages such as proc.
// lower lever packages such as proc.
type
Debugger
struct
{
type
Debugger
struct
{
config
*
Config
config
*
Config
// TODO(DO NOT MERGE WITHOUT) rename to targetMutex
processMutex
sync
.
Mutex
processMutex
sync
.
Mutex
process
*
proc
.
Process
target
target
.
Interface
}
}
// Config provides the configuration to start a Debugger.
// Config provides the configuration to start a Debugger.
...
@@ -61,7 +63,7 @@ func New(config *Config) (*Debugger, error) {
...
@@ -61,7 +63,7 @@ func New(config *Config) (*Debugger, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
attachErrorMessage
(
d
.
config
.
AttachPid
,
err
)
return
nil
,
attachErrorMessage
(
d
.
config
.
AttachPid
,
err
)
}
}
d
.
process
=
p
d
.
target
=
p
}
else
{
}
else
{
log
.
Printf
(
"launching process with args: %v"
,
d
.
config
.
ProcessArgs
)
log
.
Printf
(
"launching process with args: %v"
,
d
.
config
.
ProcessArgs
)
p
,
err
:=
proc
.
Launch
(
d
.
config
.
ProcessArgs
,
d
.
config
.
WorkingDir
)
p
,
err
:=
proc
.
Launch
(
d
.
config
.
ProcessArgs
,
d
.
config
.
WorkingDir
)
...
@@ -71,7 +73,7 @@ func New(config *Config) (*Debugger, error) {
...
@@ -71,7 +73,7 @@ func New(config *Config) (*Debugger, error) {
}
}
return
nil
,
err
return
nil
,
err
}
}
d
.
process
=
p
d
.
target
=
p
}
}
return
d
,
nil
return
d
,
nil
}
}
...
@@ -79,13 +81,13 @@ func New(config *Config) (*Debugger, error) {
...
@@ -79,13 +81,13 @@ func New(config *Config) (*Debugger, error) {
// ProcessPid returns the PID of the process
// ProcessPid returns the PID of the process
// the debugger is debugging.
// the debugger is debugging.
func
(
d
*
Debugger
)
ProcessPid
()
int
{
func
(
d
*
Debugger
)
ProcessPid
()
int
{
return
d
.
process
.
Pid
return
d
.
target
.
Pid
()
}
}
// LastModified returns the time that the process' executable was last
// LastModified returns the time that the process' executable was last
// modified.
// modified.
func
(
d
*
Debugger
)
LastModified
()
time
.
Time
{
func
(
d
*
Debugger
)
LastModified
()
time
.
Time
{
return
d
.
process
.
LastModified
return
d
.
target
.
LastModified
()
}
}
// Detach detaches from the target process.
// Detach detaches from the target process.
...
@@ -100,9 +102,9 @@ func (d *Debugger) Detach(kill bool) error {
...
@@ -100,9 +102,9 @@ func (d *Debugger) Detach(kill bool) error {
func
(
d
*
Debugger
)
detach
(
kill
bool
)
error
{
func
(
d
*
Debugger
)
detach
(
kill
bool
)
error
{
if
d
.
config
.
AttachPid
!=
0
{
if
d
.
config
.
AttachPid
!=
0
{
return
d
.
process
.
Detach
(
kill
)
return
d
.
target
.
Detach
(
kill
)
}
}
return
d
.
process
.
Kill
()
return
d
.
target
.
Kill
()
}
}
// Restart will restart the target process, first killing
// Restart will restart the target process, first killing
...
@@ -111,9 +113,9 @@ func (d *Debugger) Restart() ([]api.DiscardedBreakpoint, error) {
...
@@ -111,9 +113,9 @@ func (d *Debugger) Restart() ([]api.DiscardedBreakpoint, error) {
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
if
!
d
.
process
.
Exited
()
{
if
!
d
.
target
.
Exited
()
{
if
d
.
process
.
Running
()
{
if
d
.
target
.
Running
()
{
d
.
process
.
Halt
()
d
.
target
.
Halt
()
}
}
// Ensure the process is in a PTRACE_STOP.
// Ensure the process is in a PTRACE_STOP.
if
err
:=
stopProcess
(
d
.
ProcessPid
());
err
!=
nil
{
if
err
:=
stopProcess
(
d
.
ProcessPid
());
err
!=
nil
{
...
@@ -147,7 +149,7 @@ func (d *Debugger) Restart() ([]api.DiscardedBreakpoint, error) {
...
@@ -147,7 +149,7 @@ func (d *Debugger) Restart() ([]api.DiscardedBreakpoint, error) {
return
nil
,
err
return
nil
,
err
}
}
}
}
d
.
process
=
p
d
.
target
=
p
return
discarded
,
nil
return
discarded
,
nil
}
}
...
@@ -159,7 +161,7 @@ func (d *Debugger) State() (*api.DebuggerState, error) {
...
@@ -159,7 +161,7 @@ func (d *Debugger) State() (*api.DebuggerState, error) {
}
}
func
(
d
*
Debugger
)
state
()
(
*
api
.
DebuggerState
,
error
)
{
func
(
d
*
Debugger
)
state
()
(
*
api
.
DebuggerState
,
error
)
{
if
d
.
process
.
Exited
()
{
if
d
.
target
.
Exited
()
{
return
nil
,
proc
.
ProcessExitedError
{
Pid
:
d
.
ProcessPid
()}
return
nil
,
proc
.
ProcessExitedError
{
Pid
:
d
.
ProcessPid
()}
}
}
...
@@ -168,24 +170,24 @@ func (d *Debugger) state() (*api.DebuggerState, error) {
...
@@ -168,24 +170,24 @@ func (d *Debugger) state() (*api.DebuggerState, error) {
goroutine
*
api
.
Goroutine
goroutine
*
api
.
Goroutine
)
)
if
d
.
process
.
SelectedGoroutine
!=
nil
{
if
d
.
target
.
SelectedGoroutine
()
!=
nil
{
goroutine
=
api
.
ConvertGoroutine
(
d
.
process
.
SelectedGoroutine
)
goroutine
=
api
.
ConvertGoroutine
(
d
.
target
.
SelectedGoroutine
()
)
}
}
state
=
&
api
.
DebuggerState
{
state
=
&
api
.
DebuggerState
{
SelectedGoroutine
:
goroutine
,
SelectedGoroutine
:
goroutine
,
Exited
:
d
.
process
.
Exited
(),
Exited
:
d
.
target
.
Exited
(),
}
}
for
i
:=
range
d
.
process
.
Threads
{
for
i
:=
range
d
.
target
.
Threads
()
{
th
:=
api
.
ConvertThread
(
d
.
process
.
Threads
[
i
])
th
:=
api
.
ConvertThread
(
d
.
target
.
Threads
()
[
i
])
state
.
Threads
=
append
(
state
.
Threads
,
th
)
state
.
Threads
=
append
(
state
.
Threads
,
th
)
if
i
==
d
.
process
.
CurrentThread
.
ID
{
if
i
==
d
.
target
.
CurrentThread
()
.
ID
{
state
.
CurrentThread
=
th
state
.
CurrentThread
=
th
}
}
}
}
for
_
,
bp
:=
range
d
.
process
.
Breakpoints
{
for
_
,
bp
:=
range
d
.
target
.
Breakpoints
()
{
if
bp
.
Internal
()
{
if
bp
.
Internal
()
{
state
.
NextInProgress
=
true
state
.
NextInProgress
=
true
break
break
...
@@ -221,19 +223,19 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin
...
@@ -221,19 +223,19 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin
if
runtime
.
GOOS
==
"windows"
{
if
runtime
.
GOOS
==
"windows"
{
// Accept fileName which is case-insensitive and slash-insensitive match
// Accept fileName which is case-insensitive and slash-insensitive match
fileNameNormalized
:=
strings
.
ToLower
(
filepath
.
ToSlash
(
fileName
))
fileNameNormalized
:=
strings
.
ToLower
(
filepath
.
ToSlash
(
fileName
))
for
symFile
:=
range
d
.
process
.
Sources
()
{
for
symFile
:=
range
d
.
target
.
Sources
()
{
if
fileNameNormalized
==
strings
.
ToLower
(
filepath
.
ToSlash
(
symFile
))
{
if
fileNameNormalized
==
strings
.
ToLower
(
filepath
.
ToSlash
(
symFile
))
{
fileName
=
symFile
fileName
=
symFile
break
break
}
}
}
}
}
}
addr
,
err
=
d
.
process
.
FindFileLocation
(
fileName
,
requestedBp
.
Line
)
addr
,
err
=
d
.
target
.
FindFileLocation
(
fileName
,
requestedBp
.
Line
)
case
len
(
requestedBp
.
FunctionName
)
>
0
:
case
len
(
requestedBp
.
FunctionName
)
>
0
:
if
requestedBp
.
Line
>=
0
{
if
requestedBp
.
Line
>=
0
{
addr
,
err
=
d
.
process
.
FindFunctionLocation
(
requestedBp
.
FunctionName
,
false
,
requestedBp
.
Line
)
addr
,
err
=
d
.
target
.
FindFunctionLocation
(
requestedBp
.
FunctionName
,
false
,
requestedBp
.
Line
)
}
else
{
}
else
{
addr
,
err
=
d
.
process
.
FindFunctionLocation
(
requestedBp
.
FunctionName
,
true
,
0
)
addr
,
err
=
d
.
target
.
FindFunctionLocation
(
requestedBp
.
FunctionName
,
true
,
0
)
}
}
default
:
default
:
addr
=
requestedBp
.
Addr
addr
=
requestedBp
.
Addr
...
@@ -243,12 +245,12 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin
...
@@ -243,12 +245,12 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin
return
nil
,
err
return
nil
,
err
}
}
bp
,
err
:=
d
.
process
.
SetBreakpoint
(
addr
,
proc
.
UserBreakpoint
,
nil
)
bp
,
err
:=
d
.
target
.
SetBreakpoint
(
addr
,
proc
.
UserBreakpoint
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
err
:=
copyBreakpointInfo
(
bp
,
requestedBp
);
err
!=
nil
{
if
err
:=
copyBreakpointInfo
(
bp
,
requestedBp
);
err
!=
nil
{
if
_
,
err1
:=
d
.
process
.
ClearBreakpoint
(
bp
.
Addr
);
err1
!=
nil
{
if
_
,
err1
:=
d
.
target
.
ClearBreakpoint
(
bp
.
Addr
);
err1
!=
nil
{
err
=
fmt
.
Errorf
(
"error while creating breakpoint: %v, additionally the breakpoint could not be properly rolled back: %v"
,
err
,
err1
)
err
=
fmt
.
Errorf
(
"error while creating breakpoint: %v, additionally the breakpoint could not be properly rolled back: %v"
,
err
,
err1
)
}
}
return
nil
,
err
return
nil
,
err
...
@@ -273,7 +275,7 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
...
@@ -273,7 +275,7 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
}
}
func
(
d
*
Debugger
)
CancelNext
()
error
{
func
(
d
*
Debugger
)
CancelNext
()
error
{
return
d
.
process
.
ClearInternalBreakpoints
()
return
d
.
target
.
ClearInternalBreakpoints
()
}
}
func
copyBreakpointInfo
(
bp
*
proc
.
Breakpoint
,
requested
*
api
.
Breakpoint
)
(
err
error
)
{
func
copyBreakpointInfo
(
bp
*
proc
.
Breakpoint
,
requested
*
api
.
Breakpoint
)
(
err
error
)
{
...
@@ -297,7 +299,7 @@ func (d *Debugger) ClearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint
...
@@ -297,7 +299,7 @@ func (d *Debugger) ClearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
var
clearedBp
*
api
.
Breakpoint
var
clearedBp
*
api
.
Breakpoint
bp
,
err
:=
d
.
process
.
ClearBreakpoint
(
requestedBp
.
Addr
)
bp
,
err
:=
d
.
target
.
ClearBreakpoint
(
requestedBp
.
Addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Can't clear breakpoint @%x: %s"
,
requestedBp
.
Addr
,
err
)
return
nil
,
fmt
.
Errorf
(
"Can't clear breakpoint @%x: %s"
,
requestedBp
.
Addr
,
err
)
}
}
...
@@ -315,7 +317,7 @@ func (d *Debugger) Breakpoints() []*api.Breakpoint {
...
@@ -315,7 +317,7 @@ func (d *Debugger) Breakpoints() []*api.Breakpoint {
func
(
d
*
Debugger
)
breakpoints
()
[]
*
api
.
Breakpoint
{
func
(
d
*
Debugger
)
breakpoints
()
[]
*
api
.
Breakpoint
{
bps
:=
[]
*
api
.
Breakpoint
{}
bps
:=
[]
*
api
.
Breakpoint
{}
for
_
,
bp
:=
range
d
.
process
.
Breakpoints
{
for
_
,
bp
:=
range
d
.
target
.
Breakpoints
()
{
if
bp
.
Internal
()
{
if
bp
.
Internal
()
{
continue
continue
}
}
...
@@ -337,7 +339,7 @@ func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint {
...
@@ -337,7 +339,7 @@ func (d *Debugger) FindBreakpoint(id int) *api.Breakpoint {
}
}
func
(
d
*
Debugger
)
findBreakpoint
(
id
int
)
*
proc
.
Breakpoint
{
func
(
d
*
Debugger
)
findBreakpoint
(
id
int
)
*
proc
.
Breakpoint
{
for
_
,
bp
:=
range
d
.
process
.
Breakpoints
{
for
_
,
bp
:=
range
d
.
target
.
Breakpoints
()
{
if
bp
.
ID
==
id
{
if
bp
.
ID
==
id
{
return
bp
return
bp
}
}
...
@@ -366,11 +368,11 @@ func (d *Debugger) Threads() ([]*api.Thread, error) {
...
@@ -366,11 +368,11 @@ func (d *Debugger) Threads() ([]*api.Thread, error) {
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
if
d
.
process
.
Exited
()
{
if
d
.
target
.
Exited
()
{
return
nil
,
&
proc
.
ProcessExitedError
{}
return
nil
,
&
proc
.
ProcessExitedError
{}
}
}
threads
:=
[]
*
api
.
Thread
{}
threads
:=
[]
*
api
.
Thread
{}
for
_
,
th
:=
range
d
.
process
.
Threads
{
for
_
,
th
:=
range
d
.
target
.
Threads
()
{
threads
=
append
(
threads
,
api
.
ConvertThread
(
th
))
threads
=
append
(
threads
,
api
.
ConvertThread
(
th
))
}
}
return
threads
,
nil
return
threads
,
nil
...
@@ -381,11 +383,11 @@ func (d *Debugger) FindThread(id int) (*api.Thread, error) {
...
@@ -381,11 +383,11 @@ func (d *Debugger) FindThread(id int) (*api.Thread, error) {
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
if
d
.
process
.
Exited
()
{
if
d
.
target
.
Exited
()
{
return
nil
,
&
proc
.
ProcessExitedError
{}
return
nil
,
&
proc
.
ProcessExitedError
{}
}
}
for
_
,
th
:=
range
d
.
process
.
Threads
{
for
_
,
th
:=
range
d
.
target
.
Threads
()
{
if
th
.
ID
==
id
{
if
th
.
ID
==
id
{
return
api
.
ConvertThread
(
th
),
nil
return
api
.
ConvertThread
(
th
),
nil
}
}
...
@@ -401,7 +403,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
...
@@ -401,7 +403,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
// RequestManualStop does not invoke any ptrace syscalls, so it's safe to
// RequestManualStop does not invoke any ptrace syscalls, so it's safe to
// access the process directly.
// access the process directly.
log
.
Print
(
"halting"
)
log
.
Print
(
"halting"
)
err
=
d
.
process
.
RequestManualStop
()
err
=
d
.
target
.
RequestManualStop
()
}
}
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
...
@@ -410,7 +412,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
...
@@ -410,7 +412,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
switch
command
.
Name
{
switch
command
.
Name
{
case
api
.
Continue
:
case
api
.
Continue
:
log
.
Print
(
"continuing"
)
log
.
Print
(
"continuing"
)
err
=
d
.
process
.
Continue
()
err
=
d
.
target
.
Continue
()
if
err
!=
nil
{
if
err
!=
nil
{
if
exitedErr
,
exited
:=
err
.
(
proc
.
ProcessExitedError
);
exited
{
if
exitedErr
,
exited
:=
err
.
(
proc
.
ProcessExitedError
);
exited
{
state
:=
&
api
.
DebuggerState
{}
state
:=
&
api
.
DebuggerState
{}
...
@@ -430,22 +432,22 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
...
@@ -430,22 +432,22 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
case
api
.
Next
:
case
api
.
Next
:
log
.
Print
(
"nexting"
)
log
.
Print
(
"nexting"
)
err
=
d
.
process
.
Next
()
err
=
d
.
target
.
Next
()
case
api
.
Step
:
case
api
.
Step
:
log
.
Print
(
"stepping"
)
log
.
Print
(
"stepping"
)
err
=
d
.
process
.
Step
()
err
=
d
.
target
.
Step
()
case
api
.
StepInstruction
:
case
api
.
StepInstruction
:
log
.
Print
(
"single stepping"
)
log
.
Print
(
"single stepping"
)
err
=
d
.
process
.
StepInstruction
()
err
=
d
.
target
.
StepInstruction
()
case
api
.
StepOut
:
case
api
.
StepOut
:
log
.
Print
(
"step out"
)
log
.
Print
(
"step out"
)
err
=
d
.
process
.
StepOut
()
err
=
d
.
target
.
StepOut
()
case
api
.
SwitchThread
:
case
api
.
SwitchThread
:
log
.
Printf
(
"switching to thread %d"
,
command
.
ThreadID
)
log
.
Printf
(
"switching to thread %d"
,
command
.
ThreadID
)
err
=
d
.
process
.
SwitchThread
(
command
.
ThreadID
)
err
=
d
.
target
.
SwitchThread
(
command
.
ThreadID
)
case
api
.
SwitchGoroutine
:
case
api
.
SwitchGoroutine
:
log
.
Printf
(
"switching to goroutine %d"
,
command
.
GoroutineID
)
log
.
Printf
(
"switching to goroutine %d"
,
command
.
GoroutineID
)
err
=
d
.
process
.
SwitchGoroutine
(
command
.
GoroutineID
)
err
=
d
.
target
.
SwitchGoroutine
(
command
.
GoroutineID
)
case
api
.
Halt
:
case
api
.
Halt
:
// RequestManualStop already called
// RequestManualStop already called
}
}
...
@@ -470,7 +472,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
...
@@ -470,7 +472,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
state
.
Threads
[
i
]
.
BreakpointInfo
=
bpi
state
.
Threads
[
i
]
.
BreakpointInfo
=
bpi
if
bp
.
Goroutine
{
if
bp
.
Goroutine
{
g
,
err
:=
d
.
process
.
CurrentThread
.
GetG
()
g
,
err
:=
d
.
target
.
CurrentThread
()
.
GetG
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -478,7 +480,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
...
@@ -478,7 +480,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
}
}
if
bp
.
Stacktrace
>
0
{
if
bp
.
Stacktrace
>
0
{
rawlocs
,
err
:=
d
.
process
.
CurrentThread
.
Stacktrace
(
bp
.
Stacktrace
)
rawlocs
,
err
:=
d
.
target
.
CurrentThread
()
.
Stacktrace
(
bp
.
Stacktrace
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -488,7 +490,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
...
@@ -488,7 +490,7 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
}
}
}
}
s
,
err
:=
d
.
process
.
Threads
[
state
.
Threads
[
i
]
.
ID
]
.
Scope
()
s
,
err
:=
d
.
target
.
Threads
()
[
state
.
Threads
[
i
]
.
ID
]
.
Scope
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -529,7 +531,7 @@ func (d *Debugger) Sources(filter string) ([]string, error) {
...
@@ -529,7 +531,7 @@ func (d *Debugger) Sources(filter string) ([]string, error) {
}
}
files
:=
[]
string
{}
files
:=
[]
string
{}
for
f
:=
range
d
.
process
.
Sources
()
{
for
f
:=
range
d
.
target
.
Sources
()
{
if
regex
.
Match
([]
byte
(
f
))
{
if
regex
.
Match
([]
byte
(
f
))
{
files
=
append
(
files
,
f
)
files
=
append
(
files
,
f
)
}
}
...
@@ -542,7 +544,7 @@ func (d *Debugger) Functions(filter string) ([]string, error) {
...
@@ -542,7 +544,7 @@ func (d *Debugger) Functions(filter string) ([]string, error) {
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
return
regexFilterFuncs
(
filter
,
d
.
process
.
Funcs
())
return
regexFilterFuncs
(
filter
,
d
.
target
.
Funcs
())
}
}
func
(
d
*
Debugger
)
Types
(
filter
string
)
([]
string
,
error
)
{
func
(
d
*
Debugger
)
Types
(
filter
string
)
([]
string
,
error
)
{
...
@@ -554,7 +556,7 @@ func (d *Debugger) Types(filter string) ([]string, error) {
...
@@ -554,7 +556,7 @@ func (d *Debugger) Types(filter string) ([]string, error) {
return
nil
,
fmt
.
Errorf
(
"invalid filter argument: %s"
,
err
.
Error
())
return
nil
,
fmt
.
Errorf
(
"invalid filter argument: %s"
,
err
.
Error
())
}
}
types
,
err
:=
d
.
process
.
Types
()
types
,
err
:=
d
.
target
.
Types
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -596,7 +598,7 @@ func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadCo
...
@@ -596,7 +598,7 @@ func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadCo
}
}
vars
:=
[]
api
.
Variable
{}
vars
:=
[]
api
.
Variable
{}
thread
,
found
:=
d
.
process
.
Threads
[
threadID
]
thread
,
found
:=
d
.
target
.
Threads
()
[
threadID
]
if
!
found
{
if
!
found
{
return
nil
,
fmt
.
Errorf
(
"couldn't find thread %d"
,
threadID
)
return
nil
,
fmt
.
Errorf
(
"couldn't find thread %d"
,
threadID
)
}
}
...
@@ -621,7 +623,7 @@ func (d *Debugger) Registers(threadID int, floatingPoint bool) (api.Registers, e
...
@@ -621,7 +623,7 @@ func (d *Debugger) Registers(threadID int, floatingPoint bool) (api.Registers, e
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
thread
,
found
:=
d
.
process
.
Threads
[
threadID
]
thread
,
found
:=
d
.
target
.
Threads
()
[
threadID
]
if
!
found
{
if
!
found
{
return
nil
,
fmt
.
Errorf
(
"couldn't find thread %d"
,
threadID
)
return
nil
,
fmt
.
Errorf
(
"couldn't find thread %d"
,
threadID
)
}
}
...
@@ -645,7 +647,7 @@ func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]a
...
@@ -645,7 +647,7 @@ func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]a
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
s
,
err
:=
d
.
process
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
s
,
err
:=
d
.
target
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -661,7 +663,7 @@ func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) (
...
@@ -661,7 +663,7 @@ func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) (
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
s
,
err
:=
d
.
process
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
s
,
err
:=
d
.
target
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -678,7 +680,7 @@ func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg p
...
@@ -678,7 +680,7 @@ func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg p
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
s
,
err
:=
d
.
process
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
s
,
err
:=
d
.
target
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -695,7 +697,7 @@ func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string)
...
@@ -695,7 +697,7 @@ func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string)
d
.
processMutex
.
Lock
()
d
.
processMutex
.
Lock
()
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
s
,
err
:=
d
.
process
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
s
,
err
:=
d
.
target
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -708,7 +710,7 @@ func (d *Debugger) Goroutines() ([]*api.Goroutine, error) {
...
@@ -708,7 +710,7 @@ func (d *Debugger) Goroutines() ([]*api.Goroutine, error) {
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
goroutines
:=
[]
*
api
.
Goroutine
{}
goroutines
:=
[]
*
api
.
Goroutine
{}
gs
,
err
:=
d
.
process
.
GoroutinesInfo
()
gs
,
err
:=
d
.
target
.
GoroutinesInfo
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -727,13 +729,13 @@ func (d *Debugger) Stacktrace(goroutineID, depth int, cfg *proc.LoadConfig) ([]a
...
@@ -727,13 +729,13 @@ func (d *Debugger) Stacktrace(goroutineID, depth int, cfg *proc.LoadConfig) ([]a
var
rawlocs
[]
proc
.
Stackframe
var
rawlocs
[]
proc
.
Stackframe
g
,
err
:=
d
.
process
.
FindGoroutine
(
goroutineID
)
g
,
err
:=
d
.
target
.
FindGoroutine
(
goroutineID
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
g
==
nil
{
if
g
==
nil
{
rawlocs
,
err
=
d
.
process
.
CurrentThread
.
Stacktrace
(
depth
)
rawlocs
,
err
=
d
.
target
.
CurrentThread
()
.
Stacktrace
(
depth
)
}
else
{
}
else
{
rawlocs
,
err
=
g
.
Stacktrace
(
depth
)
rawlocs
,
err
=
g
.
Stacktrace
(
depth
)
}
}
...
@@ -750,7 +752,7 @@ func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadCo
...
@@ -750,7 +752,7 @@ func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadCo
frame
:=
api
.
Stackframe
{
Location
:
api
.
ConvertLocation
(
rawlocs
[
i
]
.
Call
)}
frame
:=
api
.
Stackframe
{
Location
:
api
.
ConvertLocation
(
rawlocs
[
i
]
.
Call
)}
if
cfg
!=
nil
{
if
cfg
!=
nil
{
var
err
error
var
err
error
scope
:=
rawlocs
[
i
]
.
Scope
(
d
.
process
.
CurrentThread
)
scope
:=
rawlocs
[
i
]
.
Scope
(
d
.
target
.
CurrentThread
()
)
locals
,
err
:=
scope
.
LocalVariables
(
*
cfg
)
locals
,
err
:=
scope
.
LocalVariables
(
*
cfg
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -779,11 +781,11 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat
...
@@ -779,11 +781,11 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat
return
nil
,
err
return
nil
,
err
}
}
s
,
_
:=
d
.
process
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
s
,
_
:=
d
.
target
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
)
locs
,
err
:=
loc
.
Find
(
d
,
s
,
locStr
)
locs
,
err
:=
loc
.
Find
(
d
,
s
,
locStr
)
for
i
:=
range
locs
{
for
i
:=
range
locs
{
file
,
line
,
fn
:=
d
.
process
.
PCToLine
(
locs
[
i
]
.
PC
)
file
,
line
,
fn
:=
d
.
target
.
PCToLine
(
locs
[
i
]
.
PC
)
locs
[
i
]
.
File
=
file
locs
[
i
]
.
File
=
file
locs
[
i
]
.
Line
=
line
locs
[
i
]
.
Line
=
line
locs
[
i
]
.
Function
=
api
.
ConvertFunction
(
fn
)
locs
[
i
]
.
Function
=
api
.
ConvertFunction
(
fn
)
...
@@ -798,7 +800,7 @@ func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavo
...
@@ -798,7 +800,7 @@ func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavo
defer
d
.
processMutex
.
Unlock
()
defer
d
.
processMutex
.
Unlock
()
if
endPC
==
0
{
if
endPC
==
0
{
_
,
_
,
fn
:=
d
.
process
.
PCToLine
(
startPC
)
_
,
_
,
fn
:=
d
.
target
.
PCToLine
(
startPC
)
if
fn
==
nil
{
if
fn
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Address 0x%x does not belong to any function"
,
startPC
)
return
nil
,
fmt
.
Errorf
(
"Address 0x%x does not belong to any function"
,
startPC
)
}
}
...
@@ -807,9 +809,9 @@ func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavo
...
@@ -807,9 +809,9 @@ func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavo
}
}
currentGoroutine
:=
true
currentGoroutine
:=
true
thread
:=
d
.
process
.
CurrentThread
thread
:=
d
.
target
.
CurrentThread
()
if
s
,
err
:=
d
.
process
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
);
err
==
nil
{
if
s
,
err
:=
d
.
target
.
ConvertEvalScope
(
scope
.
GoroutineID
,
scope
.
Frame
);
err
==
nil
{
thread
=
s
.
Thread
thread
=
s
.
Thread
if
scope
.
GoroutineID
!=
-
1
{
if
scope
.
GoroutineID
!=
-
1
{
g
,
_
:=
s
.
Thread
.
GetG
()
g
,
_
:=
s
.
Thread
.
GetG
()
...
...
service/debugger/locations.go
浏览文件 @
26ad5f1d
...
@@ -243,14 +243,14 @@ func (spec *FuncLocationSpec) Match(sym *gosym.Sym) bool {
...
@@ -243,14 +243,14 @@ func (spec *FuncLocationSpec) Match(sym *gosym.Sym) bool {
}
}
func
(
loc
*
RegexLocationSpec
)
Find
(
d
*
Debugger
,
scope
*
proc
.
EvalScope
,
locStr
string
)
([]
api
.
Location
,
error
)
{
func
(
loc
*
RegexLocationSpec
)
Find
(
d
*
Debugger
,
scope
*
proc
.
EvalScope
,
locStr
string
)
([]
api
.
Location
,
error
)
{
funcs
:=
d
.
process
.
Funcs
()
funcs
:=
d
.
target
.
Funcs
()
matches
,
err
:=
regexFilterFuncs
(
loc
.
FuncRegex
,
funcs
)
matches
,
err
:=
regexFilterFuncs
(
loc
.
FuncRegex
,
funcs
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
r
:=
make
([]
api
.
Location
,
0
,
len
(
matches
))
r
:=
make
([]
api
.
Location
,
0
,
len
(
matches
))
for
i
:=
range
matches
{
for
i
:=
range
matches
{
addr
,
err
:=
d
.
process
.
FindFunctionLocation
(
matches
[
i
],
true
,
0
)
addr
,
err
:=
d
.
target
.
FindFunctionLocation
(
matches
[
i
],
true
,
0
)
if
err
==
nil
{
if
err
==
nil
{
r
=
append
(
r
,
api
.
Location
{
PC
:
addr
})
r
=
append
(
r
,
api
.
Location
{
PC
:
addr
})
}
}
...
@@ -278,8 +278,8 @@ func (loc *AddrLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str
...
@@ -278,8 +278,8 @@ func (loc *AddrLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str
addr
,
_
:=
constant
.
Uint64Val
(
v
.
Value
)
addr
,
_
:=
constant
.
Uint64Val
(
v
.
Value
)
return
[]
api
.
Location
{{
PC
:
addr
}},
nil
return
[]
api
.
Location
{{
PC
:
addr
}},
nil
case
reflect
.
Func
:
case
reflect
.
Func
:
_
,
_
,
fn
:=
d
.
process
.
PCToLine
(
uint64
(
v
.
Base
))
_
,
_
,
fn
:=
d
.
target
.
PCToLine
(
uint64
(
v
.
Base
))
pc
,
err
:=
d
.
process
.
FirstPCAfterPrologue
(
fn
,
false
)
pc
,
err
:=
d
.
target
.
FirstPCAfterPrologue
(
fn
,
false
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -327,8 +327,8 @@ func (ale AmbiguousLocationError) Error() string {
...
@@ -327,8 +327,8 @@ func (ale AmbiguousLocationError) Error() string {
}
}
func
(
loc
*
NormalLocationSpec
)
Find
(
d
*
Debugger
,
scope
*
proc
.
EvalScope
,
locStr
string
)
([]
api
.
Location
,
error
)
{
func
(
loc
*
NormalLocationSpec
)
Find
(
d
*
Debugger
,
scope
*
proc
.
EvalScope
,
locStr
string
)
([]
api
.
Location
,
error
)
{
funcs
:=
d
.
process
.
Funcs
()
funcs
:=
d
.
target
.
Funcs
()
files
:=
d
.
process
.
Sources
()
files
:=
d
.
target
.
Sources
()
candidates
:=
[]
string
{}
candidates
:=
[]
string
{}
for
file
:=
range
files
{
for
file
:=
range
files
{
...
@@ -366,12 +366,12 @@ func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s
...
@@ -366,12 +366,12 @@ func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s
if
loc
.
LineOffset
<
0
{
if
loc
.
LineOffset
<
0
{
return
nil
,
fmt
.
Errorf
(
"Malformed breakpoint location, no line offset specified"
)
return
nil
,
fmt
.
Errorf
(
"Malformed breakpoint location, no line offset specified"
)
}
}
addr
,
err
=
d
.
process
.
FindFileLocation
(
candidates
[
0
],
loc
.
LineOffset
)
addr
,
err
=
d
.
target
.
FindFileLocation
(
candidates
[
0
],
loc
.
LineOffset
)
}
else
{
}
else
{
if
loc
.
LineOffset
<
0
{
if
loc
.
LineOffset
<
0
{
addr
,
err
=
d
.
process
.
FindFunctionLocation
(
candidates
[
0
],
true
,
0
)
addr
,
err
=
d
.
target
.
FindFunctionLocation
(
candidates
[
0
],
true
,
0
)
}
else
{
}
else
{
addr
,
err
=
d
.
process
.
FindFunctionLocation
(
candidates
[
0
],
false
,
loc
.
LineOffset
)
addr
,
err
=
d
.
target
.
FindFunctionLocation
(
candidates
[
0
],
false
,
loc
.
LineOffset
)
}
}
}
}
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -390,11 +390,11 @@ func (loc *OffsetLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s
...
@@ -390,11 +390,11 @@ func (loc *OffsetLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s
if
scope
==
nil
{
if
scope
==
nil
{
return
nil
,
fmt
.
Errorf
(
"could not determine current location (scope is nil)"
)
return
nil
,
fmt
.
Errorf
(
"could not determine current location (scope is nil)"
)
}
}
file
,
line
,
fn
:=
d
.
process
.
PCToLine
(
scope
.
PC
)
file
,
line
,
fn
:=
d
.
target
.
PCToLine
(
scope
.
PC
)
if
fn
==
nil
{
if
fn
==
nil
{
return
nil
,
fmt
.
Errorf
(
"could not determine current location"
)
return
nil
,
fmt
.
Errorf
(
"could not determine current location"
)
}
}
addr
,
err
:=
d
.
process
.
FindFileLocation
(
file
,
line
+
loc
.
Offset
)
addr
,
err
:=
d
.
target
.
FindFileLocation
(
file
,
line
+
loc
.
Offset
)
return
[]
api
.
Location
{{
PC
:
addr
}},
err
return
[]
api
.
Location
{{
PC
:
addr
}},
err
}
}
...
@@ -402,10 +402,10 @@ func (loc *LineLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str
...
@@ -402,10 +402,10 @@ func (loc *LineLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str
if
scope
==
nil
{
if
scope
==
nil
{
return
nil
,
fmt
.
Errorf
(
"could not determine current location (scope is nil)"
)
return
nil
,
fmt
.
Errorf
(
"could not determine current location (scope is nil)"
)
}
}
file
,
_
,
fn
:=
d
.
process
.
PCToLine
(
scope
.
PC
)
file
,
_
,
fn
:=
d
.
target
.
PCToLine
(
scope
.
PC
)
if
fn
==
nil
{
if
fn
==
nil
{
return
nil
,
fmt
.
Errorf
(
"could not determine current location"
)
return
nil
,
fmt
.
Errorf
(
"could not determine current location"
)
}
}
addr
,
err
:=
d
.
process
.
FindFileLocation
(
file
,
loc
.
Line
)
addr
,
err
:=
d
.
target
.
FindFileLocation
(
file
,
loc
.
Line
)
return
[]
api
.
Location
{{
PC
:
addr
}},
err
return
[]
api
.
Location
{{
PC
:
addr
}},
err
}
}
service/test/variables_test.go
浏览文件 @
26ad5f1d
...
@@ -54,7 +54,7 @@ func assertVariable(t *testing.T, variable *proc.Variable, expected varTest) {
...
@@ -54,7 +54,7 @@ func assertVariable(t *testing.T, variable *proc.Variable, expected varTest) {
}
}
func
evalVariable
(
p
*
proc
.
Process
,
symbol
string
,
cfg
proc
.
LoadConfig
)
(
*
proc
.
Variable
,
error
)
{
func
evalVariable
(
p
*
proc
.
Process
,
symbol
string
,
cfg
proc
.
LoadConfig
)
(
*
proc
.
Variable
,
error
)
{
scope
,
err
:=
p
.
CurrentThread
.
Scope
()
scope
,
err
:=
p
.
CurrentThread
()
.
Scope
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -68,7 +68,7 @@ func (tc *varTest) alternateVarTest() varTest {
...
@@ -68,7 +68,7 @@ func (tc *varTest) alternateVarTest() varTest {
}
}
func
setVariable
(
p
*
proc
.
Process
,
symbol
,
value
string
)
error
{
func
setVariable
(
p
*
proc
.
Process
,
symbol
,
value
string
)
error
{
scope
,
err
:=
p
.
CurrentThread
.
Scope
()
scope
,
err
:=
p
.
CurrentThread
()
.
Scope
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -348,7 +348,7 @@ func TestLocalVariables(t *testing.T) {
...
@@ -348,7 +348,7 @@ func TestLocalVariables(t *testing.T) {
assertNoError
(
err
,
t
,
"Continue() returned an error"
)
assertNoError
(
err
,
t
,
"Continue() returned an error"
)
for
_
,
tc
:=
range
testcases
{
for
_
,
tc
:=
range
testcases
{
scope
,
err
:=
p
.
CurrentThread
.
Scope
()
scope
,
err
:=
p
.
CurrentThread
()
.
Scope
()
assertNoError
(
err
,
t
,
"AsScope()"
)
assertNoError
(
err
,
t
,
"AsScope()"
)
vars
,
err
:=
tc
.
fn
(
scope
,
pnormalLoadConfig
)
vars
,
err
:=
tc
.
fn
(
scope
,
pnormalLoadConfig
)
assertNoError
(
err
,
t
,
"LocalVariables() returned an error"
)
assertNoError
(
err
,
t
,
"LocalVariables() returned an error"
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录