Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
pubx
delve
提交
708cf2f2
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,发现更多精彩内容 >>
提交
708cf2f2
编写于
10月 29, 2015
作者:
A
aarzilli
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
service,terminal: propagating simultaneous breakpoints
上级
a9e2696f
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
166 addition
and
113 deletion
+166
-113
cmd/dlv/main.go
cmd/dlv/main.go
+15
-10
service/api/conversions.go
service/api/conversions.go
+18
-5
service/api/types.go
service/api/types.go
+10
-6
service/debugger/debugger.go
service/debugger/debugger.go
+48
-46
service/rpc/client.go
service/rpc/client.go
+15
-1
service/test/integration_test.go
service/test/integration_test.go
+5
-5
terminal/command.go
terminal/command.go
+55
-40
未找到文件。
cmd/dlv/main.go
浏览文件 @
708cf2f2
...
...
@@ -193,18 +193,23 @@ starts and attaches to it, and enables you to immediately begin debugging your p
fmt
.
Fprintln
(
os
.
Stderr
,
state
.
Err
)
return
0
}
var
args
[]
string
var
fname
string
if
state
.
CurrentThread
!=
nil
&&
state
.
CurrentThread
.
Function
!=
nil
{
fname
=
state
.
CurrentThread
.
Function
.
Name
}
if
state
.
BreakpointInfo
!=
nil
{
for
_
,
arg
:=
range
state
.
BreakpointInfo
.
Arguments
{
args
=
append
(
args
,
arg
.
SinglelineString
())
for
i
:=
range
state
.
Threads
{
th
:=
state
.
Threads
[
i
]
if
th
.
Breakpoint
==
nil
{
continue
}
var
args
[]
string
var
fname
string
if
th
.
Function
!=
nil
{
fname
=
th
.
Function
.
Name
}
if
th
.
BreakpointInfo
!=
nil
{
for
_
,
arg
:=
range
th
.
BreakpointInfo
.
Arguments
{
args
=
append
(
args
,
arg
.
SinglelineString
())
}
}
fmt
.
Printf
(
"%s(%s) %s:%d
\n
"
,
fname
,
strings
.
Join
(
args
,
", "
),
terminal
.
ShortenFilePath
(
th
.
File
),
th
.
Line
)
}
fp
:=
terminal
.
ShortenFilePath
(
state
.
CurrentThread
.
File
)
fmt
.
Printf
(
"%s(%s) %s:%d
\n
"
,
fname
,
strings
.
Join
(
args
,
", "
),
fp
,
state
.
CurrentThread
.
Line
)
case
<-
sigChan
:
server
.
Stop
(
traceAttachPid
==
0
)
return
1
...
...
service/api/conversions.go
浏览文件 @
708cf2f2
...
...
@@ -37,6 +37,7 @@ func ConvertThread(th *proc.Thread) *Thread {
file
string
line
int
pc
uint64
gid
int
)
loc
,
err
:=
th
.
Location
()
...
...
@@ -47,12 +48,24 @@ func ConvertThread(th *proc.Thread) *Thread {
function
=
ConvertFunction
(
loc
.
Fn
)
}
var
bp
*
Breakpoint
if
th
.
CurrentBreakpoint
!=
nil
{
bp
=
ConvertBreakpoint
(
th
.
CurrentBreakpoint
)
}
if
g
,
_
:=
th
.
GetG
();
g
!=
nil
{
gid
=
g
.
Id
}
return
&
Thread
{
ID
:
th
.
Id
,
PC
:
pc
,
File
:
file
,
Line
:
line
,
Function
:
function
,
ID
:
th
.
Id
,
PC
:
pc
,
File
:
file
,
Line
:
line
,
Function
:
function
,
GoroutineID
:
gid
,
Breakpoint
:
bp
,
}
}
...
...
service/api/types.go
浏览文件 @
708cf2f2
...
...
@@ -4,19 +4,15 @@ import "reflect"
// DebuggerState represents the current context of the debugger.
type
DebuggerState
struct
{
// Breakpoint is the current breakpoint at which the debugged process is
// suspended, and may be empty if the process is not suspended.
Breakpoint
*
Breakpoint
`json:"breakPoint,omitempty"`
// CurrentThread is the currently selected debugger thread.
CurrentThread
*
Thread
`json:"currentThread,omitempty"`
// SelectedGoroutine is the currently selected goroutine
SelectedGoroutine
*
Goroutine
`json:"currentGoroutine,omitempty"`
//
Information requested by the current breakpoint
BreakpointInfo
*
BreakpointInfo
`json:"breakPointInfo,omitrempty"`
//
List of all the process threads
Threads
[]
*
Thread
// Exited indicates whether the debugged process has exited.
Exited
bool
`json:"exited"`
ExitStatus
int
`json:"exitStatus"`
// Filled by RPCClient.Continue, indicates an error
Err
error
`json:"-"`
}
...
...
@@ -62,6 +58,14 @@ type Thread struct {
Line
int
`json:"line"`
// Function is function information at the program counter. May be nil.
Function
*
Function
`json:"function,omitempty"`
// ID of the goroutine running on this thread
GoroutineID
int
`json:"goroutineID"`
// Breakpoint this thread is stopped at
Breakpoint
*
Breakpoint
`json:"breakPoint,omitempty"`
// Informations requested by the current breakpoint
BreakpointInfo
*
BreakpointInfo
`json:"breakPointInfo,omitrempty"`
}
type
Location
struct
{
...
...
service/debugger/debugger.go
浏览文件 @
708cf2f2
...
...
@@ -111,31 +111,26 @@ func (d *Debugger) State() (*api.DebuggerState, error) {
var
(
state
*
api
.
DebuggerState
thread
*
api
.
Thread
goroutine
*
api
.
Goroutine
)
if
d
.
process
.
CurrentThread
!=
nil
{
thread
=
api
.
ConvertThread
(
d
.
process
.
CurrentThread
)
}
if
d
.
process
.
SelectedGoroutine
!=
nil
{
goroutine
=
api
.
ConvertGoroutine
(
d
.
process
.
SelectedGoroutine
)
}
var
breakpoint
*
api
.
Breakpoint
bp
:=
d
.
process
.
CurrentBreakpoint
()
if
bp
!=
nil
{
breakpoint
=
api
.
ConvertBreakpoint
(
bp
)
}
state
=
&
api
.
DebuggerState
{
Breakpoint
:
breakpoint
,
CurrentThread
:
thread
,
SelectedGoroutine
:
goroutine
,
Exited
:
d
.
process
.
Exited
(),
}
for
i
:=
range
d
.
process
.
Threads
{
th
:=
api
.
ConvertThread
(
d
.
process
.
Threads
[
i
])
state
.
Threads
=
append
(
state
.
Threads
,
th
)
if
i
==
d
.
process
.
CurrentThread
.
Id
{
state
.
CurrentThread
=
th
}
}
return
state
,
nil
}
...
...
@@ -272,52 +267,59 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
}
func
(
d
*
Debugger
)
collectBreakpointInformation
(
state
*
api
.
DebuggerState
)
error
{
if
state
==
nil
||
state
.
Breakpoint
==
nil
{
if
state
==
nil
{
return
nil
}
bp
:=
state
.
Breakpoint
bpi
:=
&
api
.
BreakpointInfo
{}
state
.
BreakpointInfo
=
bpi
for
i
:=
range
state
.
Threads
{
if
state
.
Threads
[
i
]
.
Breakpoint
==
nil
{
continue
}
bp
:=
state
.
Threads
[
i
]
.
Breakpoint
bpi
:=
&
api
.
BreakpointInfo
{}
state
.
Threads
[
i
]
.
BreakpointInfo
=
bpi
if
bp
.
Goroutine
{
g
,
err
:=
d
.
process
.
CurrentThread
.
GetG
()
if
err
!=
nil
{
return
err
if
bp
.
Goroutine
{
g
,
err
:=
d
.
process
.
CurrentThread
.
GetG
()
if
err
!=
nil
{
return
err
}
bpi
.
Goroutine
=
api
.
ConvertGoroutine
(
g
)
}
bpi
.
Goroutine
=
api
.
ConvertGoroutine
(
g
)
}
if
bp
.
Stacktrace
>
0
{
rawlocs
,
err
:=
d
.
process
.
CurrentThread
.
Stacktrace
(
bp
.
Stacktrace
)
if
err
!=
nil
{
return
err
if
bp
.
Stacktrace
>
0
{
rawlocs
,
err
:=
d
.
process
.
CurrentThread
.
Stacktrace
(
bp
.
Stacktrace
)
if
err
!=
nil
{
return
err
}
bpi
.
Stacktrace
,
err
=
d
.
convertStacktrace
(
rawlocs
,
false
)
if
err
!=
nil
{
return
err
}
}
bpi
.
Stacktrace
,
err
=
d
.
convertStacktrace
(
rawlocs
,
false
)
s
,
err
:=
d
.
process
.
CurrentThread
.
Scope
()
if
err
!=
nil
{
return
err
}
}
s
,
err
:=
d
.
process
.
CurrentThread
.
Scope
()
if
err
!=
nil
{
return
err
}
if
len
(
bp
.
Variables
)
>
0
{
bpi
.
Variables
=
make
([]
api
.
Variable
,
len
(
bp
.
Variables
))
}
for
i
:=
range
bp
.
Variables
{
v
,
err
:=
s
.
EvalVariable
(
bp
.
Variables
[
i
])
if
err
!=
nil
{
return
err
if
len
(
bp
.
Variables
)
>
0
{
bpi
.
Variables
=
make
([]
api
.
Variable
,
len
(
bp
.
Variables
))
}
for
i
:=
range
bp
.
Variables
{
v
,
err
:=
s
.
EvalVariable
(
bp
.
Variables
[
i
])
if
err
!=
nil
{
return
err
}
bpi
.
Variables
[
i
]
=
*
api
.
ConvertVar
(
v
)
}
vars
,
err
:=
s
.
FunctionArguments
()
if
err
==
nil
{
bpi
.
Arguments
=
convertVars
(
vars
)
}
bpi
.
Variables
[
i
]
=
*
api
.
ConvertVar
(
v
)
}
args
,
err
:=
s
.
FunctionArguments
()
if
err
==
nil
{
bpi
.
Arguments
=
convertVars
(
args
)
}
return
nil
}
...
...
service/rpc/client.go
浏览文件 @
708cf2f2
...
...
@@ -66,7 +66,21 @@ func (c *RPCClient) Continue() <-chan *api.DebuggerState {
state
.
Err
=
fmt
.
Errorf
(
"Process %d has exited with status %d"
,
c
.
ProcessPid
(),
state
.
ExitStatus
)
}
ch
<-
state
if
err
!=
nil
||
state
.
Exited
||
state
.
Breakpoint
==
nil
||
!
state
.
Breakpoint
.
Tracepoint
{
if
err
!=
nil
||
state
.
Exited
{
close
(
ch
)
return
}
isbreakpoint
:=
false
istracepoint
:=
true
for
i
:=
range
state
.
Threads
{
if
state
.
Threads
[
i
]
.
Breakpoint
!=
nil
{
isbreakpoint
=
true
istracepoint
=
istracepoint
&&
state
.
Threads
[
i
]
.
Breakpoint
.
Tracepoint
}
}
if
!
isbreakpoint
||
!
istracepoint
{
close
(
ch
)
return
}
...
...
service/test/integration_test.go
浏览文件 @
708cf2f2
...
...
@@ -96,7 +96,7 @@ func TestRestart_duringStop(t *testing.T) {
t
.
Fatal
(
err
)
}
state
:=
<-
c
.
Continue
()
if
state
.
Breakpoint
==
nil
{
if
state
.
CurrentThread
.
Breakpoint
==
nil
{
t
.
Fatal
(
"did not hit breakpoint"
)
}
if
err
:=
c
.
Restart
();
err
!=
nil
{
...
...
@@ -433,12 +433,12 @@ func TestClientServer_traceContinue(t *testing.T) {
count
:=
0
contChan
:=
c
.
Continue
()
for
state
:=
range
contChan
{
if
state
.
Breakpoint
!=
nil
{
if
state
.
CurrentThread
!=
nil
&&
state
.
CurrentThread
.
Breakpoint
!=
nil
{
count
++
t
.
Logf
(
"%v"
,
state
)
bpi
:=
state
.
BreakpointInfo
bpi
:=
state
.
CurrentThread
.
BreakpointInfo
if
bpi
.
Goroutine
==
nil
{
t
.
Fatalf
(
"No goroutine information"
)
...
...
@@ -494,8 +494,8 @@ func TestClientServer_traceContinue2(t *testing.T) {
countSayhi
:=
0
contChan
:=
c
.
Continue
()
for
state
:=
range
contChan
{
if
state
.
Breakpoint
!=
nil
{
switch
state
.
Breakpoint
.
ID
{
if
state
.
CurrentThread
!=
nil
&&
state
.
CurrentThread
.
Breakpoint
!=
nil
{
switch
state
.
CurrentThread
.
Breakpoint
.
ID
{
case
bp1
.
ID
:
countMain
++
case
bp2
.
ID
:
...
...
terminal/command.go
浏览文件 @
708cf2f2
...
...
@@ -837,6 +837,15 @@ func printStack(stack []api.Stackframe, ind string) {
}
func
printcontext
(
t
*
Term
,
state
*
api
.
DebuggerState
)
error
{
for
i
:=
range
state
.
Threads
{
if
(
state
.
CurrentThread
!=
nil
)
&&
(
state
.
Threads
[
i
]
.
ID
==
state
.
CurrentThread
.
ID
)
{
continue
}
if
state
.
Threads
[
i
]
.
Breakpoint
!=
nil
{
printcontextThread
(
t
,
state
.
Threads
[
i
])
}
}
if
state
.
CurrentThread
==
nil
{
fmt
.
Println
(
"No current thread available"
)
return
nil
...
...
@@ -846,64 +855,70 @@ func printcontext(t *Term, state *api.DebuggerState) error {
t
.
Println
(
"=>"
,
"no source available"
)
return
nil
}
var
fn
*
api
.
Function
if
state
.
CurrentThread
.
Function
!=
nil
{
fn
=
state
.
CurrentThread
.
Function
printcontextThread
(
t
,
state
.
CurrentThread
)
if
state
.
CurrentThread
.
Breakpoint
==
nil
||
!
state
.
CurrentThread
.
Breakpoint
.
Tracepoint
{
return
printfile
(
t
,
state
.
CurrentThread
.
File
,
state
.
CurrentThread
.
Line
,
true
)
}
return
nil
}
if
state
.
Breakpoint
!=
nil
{
args
:=
""
if
state
.
Breakpoint
.
Tracepoint
{
var
arg
[]
string
for
_
,
ar
:=
range
state
.
CurrentThread
.
Function
.
Args
{
arg
=
append
(
arg
,
ar
.
SinglelineString
())
}
args
=
strings
.
Join
(
arg
,
", "
)
}
if
hitCount
,
ok
:=
state
.
Breakpoint
.
HitCount
[
strconv
.
Itoa
(
state
.
SelectedGoroutine
.
ID
)];
ok
{
fmt
.
Printf
(
"> %s(%s) %s:%d (hits goroutine(%d):%d total:%d)
\n
"
,
fn
.
Name
,
args
,
ShortenFilePath
(
state
.
CurrentThread
.
File
),
state
.
CurrentThread
.
Line
,
state
.
SelectedGoroutine
.
ID
,
hitCount
,
state
.
Breakpoint
.
TotalHitCount
)
}
else
{
fmt
.
Printf
(
"> %s(%s) %s:%d (hits total:%d)
\n
"
,
fn
.
Name
,
args
,
ShortenFilePath
(
state
.
CurrentThread
.
File
),
state
.
CurrentThread
.
Line
,
state
.
Breakpoint
.
TotalHitCount
)
func
printcontextThread
(
t
*
Term
,
th
*
api
.
Thread
)
{
fn
:=
th
.
Function
if
th
.
Breakpoint
==
nil
{
fmt
.
Printf
(
"> %s() %s:%d
\n
"
,
fn
.
Name
,
ShortenFilePath
(
th
.
File
),
th
.
Line
)
return
}
args
:=
""
if
th
.
Breakpoint
.
Tracepoint
&&
fn
!=
nil
{
var
arg
[]
string
for
_
,
ar
:=
range
fn
.
Args
{
arg
=
append
(
arg
,
ar
.
SinglelineString
())
}
args
=
strings
.
Join
(
arg
,
", "
)
}
if
hitCount
,
ok
:=
th
.
Breakpoint
.
HitCount
[
strconv
.
Itoa
(
th
.
GoroutineID
)];
ok
{
fmt
.
Printf
(
"> %s(%s) %s:%d (hits goroutine(%d):%d total:%d)
\n
"
,
fn
.
Name
,
args
,
ShortenFilePath
(
th
.
File
),
th
.
Line
,
th
.
GoroutineID
,
hitCount
,
th
.
Breakpoint
.
TotalHitCount
)
}
else
{
fmt
.
Printf
(
"> %s() %s:%d
\n
"
,
fn
.
Name
,
ShortenFilePath
(
state
.
CurrentThread
.
File
),
state
.
CurrentThread
.
Line
)
fmt
.
Printf
(
"> %s(%s) %s:%d (hits total:%d)
\n
"
,
fn
.
Name
,
args
,
ShortenFilePath
(
th
.
File
),
th
.
Line
,
th
.
Breakpoint
.
TotalHitCount
)
}
if
state
.
BreakpointInfo
!=
nil
{
bpi
:=
state
.
BreakpointInfo
if
th
.
BreakpointInfo
!=
nil
{
bpi
:=
th
.
BreakpointInfo
if
bpi
.
Goroutine
!=
nil
{
writeGoroutineLong
(
os
.
Stdout
,
bpi
.
Goroutine
,
"
\t
"
)
}
ss
:=
make
([]
string
,
len
(
bpi
.
Variables
))
for
i
,
v
:=
range
bpi
.
Variables
{
ss
[
i
]
=
fmt
.
Sprintf
(
"%s: %v"
,
v
.
Name
,
v
.
MultilineString
(
""
))
if
len
(
bpi
.
Variables
)
>
0
{
ss
:=
make
([]
string
,
len
(
bpi
.
Variables
))
for
i
,
v
:=
range
bpi
.
Variables
{
ss
[
i
]
=
fmt
.
Sprintf
(
"%s: %s"
,
v
.
Name
,
v
.
MultilineString
(
""
))
}
fmt
.
Printf
(
"
\t
%s
\n
"
,
strings
.
Join
(
ss
,
", "
))
}
fmt
.
Printf
(
"
\t
%s
\n
"
,
strings
.
Join
(
ss
,
", "
))
if
bpi
.
Stacktrace
!=
nil
{
fmt
.
Printf
(
"
\t
Stack:
\n
"
)
printStack
(
bpi
.
Stacktrace
,
"
\t\t
"
)
}
}
if
state
.
Breakpoint
!=
nil
&&
state
.
Breakpoint
.
Tracepoint
{
return
nil
}
return
printfile
(
t
,
state
.
CurrentThread
.
File
,
state
.
CurrentThread
.
Line
,
true
)
}
func
printfile
(
t
*
Term
,
filename
string
,
line
int
,
showArrow
bool
)
error
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录