Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
HugeYuan
delve
提交
c625f09a
D
delve
项目概览
HugeYuan
/
delve
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
delve
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c625f09a
编写于
10月 25, 2014
作者:
D
Derek Parker
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Promote breakpoints back up to process
上级
4c95bf73
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
99 addition
and
113 deletion
+99
-113
proctl/proctl_linux_amd64.go
proctl/proctl_linux_amd64.go
+86
-22
proctl/proctl_test.go
proctl/proctl_test.go
+2
-2
proctl/threads_linux_amd64.go
proctl/threads_linux_amd64.go
+11
-89
未找到文件。
proctl/proctl_linux_amd64.go
浏览文件 @
c625f09a
...
...
@@ -3,6 +3,7 @@
package
proctl
import
(
"bytes"
"debug/gosym"
"encoding/binary"
"fmt"
...
...
@@ -24,10 +25,32 @@ type DebuggedProcess struct {
Symbols
[]
elf
.
Symbol
GoSymTable
*
gosym
.
Table
FrameEntries
*
frame
.
FrameDescriptionEntries
BreakPoints
map
[
uint64
]
*
BreakPoint
Threads
map
[
int
]
*
ThreadContext
CurrentThread
*
ThreadContext
}
// Represents a single breakpoint. Stores information on the break
// point including the byte of data that originally was stored at that
// address.
type
BreakPoint
struct
{
FunctionName
string
File
string
Line
int
Addr
uint64
OriginalData
[]
byte
}
type
BreakPointExistsError
struct
{
file
string
line
int
addr
uintptr
}
func
(
bpe
BreakPointExistsError
)
Error
()
string
{
return
fmt
.
Sprintf
(
"Breakpoint exists at %s:%d at %x"
,
bpe
.
file
,
bpe
.
line
,
bpe
.
addr
)
}
func
AttachBinary
(
name
string
)
(
*
DebuggedProcess
,
error
)
{
proc
:=
exec
.
Command
(
name
)
proc
.
Stdout
=
os
.
Stdout
...
...
@@ -48,8 +71,9 @@ func AttachBinary(name string) (*DebuggedProcess, error) {
// Returns a new DebuggedProcess struct with sensible defaults.
func
NewDebugProcess
(
pid
int
)
(
*
DebuggedProcess
,
error
)
{
debuggedProc
:=
DebuggedProcess
{
Pid
:
pid
,
Threads
:
make
(
map
[
int
]
*
ThreadContext
),
Pid
:
pid
,
Threads
:
make
(
map
[
int
]
*
ThreadContext
),
BreakPoints
:
make
(
map
[
uint64
]
*
BreakPoint
),
}
_
,
err
:=
debuggedProc
.
AttachThread
(
pid
)
...
...
@@ -149,10 +173,9 @@ func (dbp *DebuggedProcess) addThread(tid int) (*ThreadContext, error) {
}
tctxt
:=
&
ThreadContext
{
Id
:
tid
,
Process
:
dbp
,
Regs
:
new
(
syscall
.
PtraceRegs
),
BreakPoints
:
make
(
map
[
uint64
]
*
BreakPoint
),
Id
:
tid
,
Process
:
dbp
,
Regs
:
new
(
syscall
.
PtraceRegs
),
}
if
tid
==
dbp
.
Pid
{
...
...
@@ -164,16 +187,67 @@ func (dbp *DebuggedProcess) addThread(tid int) (*ThreadContext, error) {
return
tctxt
,
nil
}
// Sets a breakpoint in the running process.
func
(
dbp
*
DebuggedProcess
)
Break
(
addr
uintptr
)
(
*
BreakPoint
,
error
)
{
var
(
int3
=
[]
byte
{
0xCC
}
f
,
l
,
fn
=
dbp
.
GoSymTable
.
PCToLine
(
uint64
(
addr
))
originalData
=
make
([]
byte
,
1
)
)
if
fn
==
nil
{
return
nil
,
InvalidAddressError
{
address
:
addr
}
}
_
,
err
:=
syscall
.
PtracePeekData
(
dbp
.
CurrentThread
.
Id
,
addr
,
originalData
)
if
err
!=
nil
{
return
nil
,
err
}
if
bytes
.
Equal
(
originalData
,
int3
)
{
return
nil
,
BreakPointExistsError
{
f
,
l
,
addr
}
}
_
,
err
=
syscall
.
PtracePokeData
(
dbp
.
CurrentThread
.
Id
,
addr
,
int3
)
if
err
!=
nil
{
return
nil
,
err
}
breakpoint
:=
&
BreakPoint
{
FunctionName
:
fn
.
Name
,
File
:
f
,
Line
:
l
,
Addr
:
uint64
(
addr
),
OriginalData
:
originalData
,
}
dbp
.
BreakPoints
[
uint64
(
addr
)]
=
breakpoint
return
breakpoint
,
nil
}
// Clears a breakpoint.
func
(
dbp
*
DebuggedProcess
)
Clear
(
pc
uint64
)
(
*
BreakPoint
,
error
)
{
bp
,
ok
:=
dbp
.
BreakPoints
[
pc
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"No breakpoint currently set for %#v"
,
pc
)
}
_
,
err
:=
syscall
.
PtracePokeData
(
dbp
.
CurrentThread
.
Id
,
uintptr
(
bp
.
Addr
),
bp
.
OriginalData
)
if
err
!=
nil
{
return
nil
,
err
}
delete
(
dbp
.
BreakPoints
,
pc
)
return
bp
,
nil
}
// Returns the status of the current main thread context.
func
(
dbp
*
DebuggedProcess
)
Status
()
*
syscall
.
WaitStatus
{
return
dbp
.
CurrentThread
.
Status
}
// Returns the breakpoints of the current main thread context.
func
(
dbp
*
DebuggedProcess
)
BreakPoints
()
map
[
uint64
]
*
BreakPoint
{
return
dbp
.
CurrentThread
.
BreakPoints
}
// Finds the executable from /proc/<pid>/exe and then
// uses that to parse the following information:
// * Dwarf .debug_frame section
...
...
@@ -257,16 +331,6 @@ func (iae InvalidAddressError) Error() string {
return
fmt
.
Sprintf
(
"Invalid address %#v
\n
"
,
iae
.
address
)
}
// Sets a breakpoint in the running process.
func
(
dbp
*
DebuggedProcess
)
Break
(
addr
uintptr
)
(
*
BreakPoint
,
error
)
{
return
dbp
.
CurrentThread
.
Break
(
addr
)
}
// Clears a breakpoint.
func
(
dbp
*
DebuggedProcess
)
Clear
(
pc
uint64
)
(
*
BreakPoint
,
error
)
{
return
dbp
.
CurrentThread
.
Clear
(
pc
)
}
func
(
dbp
*
DebuggedProcess
)
CurrentPC
()
(
uint64
,
error
)
{
return
dbp
.
CurrentThread
.
CurrentPC
()
}
...
...
@@ -429,7 +493,7 @@ func wait(dbp *DebuggedProcess, pid int, options int) (int, *syscall.WaitStatus,
for
_
,
th
:=
range
dbp
.
Threads
{
if
th
.
Id
==
pid
{
pc
,
_
:=
th
.
CurrentPC
()
_
,
ok
:=
th
.
BreakPoints
[
pc
-
1
]
_
,
ok
:=
dbp
.
BreakPoints
[
pc
-
1
]
if
ok
{
return
pid
,
&
status
,
nil
}
else
{
...
...
proctl/proctl_test.go
浏览文件 @
c625f09a
...
...
@@ -169,7 +169,7 @@ func TestClearBreakPoint(t *testing.T) {
t
.
Fatalf
(
"Breakpoint was not cleared data: %#v, int3: %#v"
,
data
,
int3
)
}
if
len
(
p
.
BreakPoints
()
)
!=
0
{
if
len
(
p
.
BreakPoints
)
!=
0
{
t
.
Fatal
(
"Breakpoint not removed internally"
)
}
})
...
...
@@ -229,7 +229,7 @@ func TestNext(t *testing.T) {
}
}
if
len
(
p
.
BreakPoints
()
)
!=
1
{
if
len
(
p
.
BreakPoints
)
!=
1
{
t
.
Fatal
(
"Not all breakpoints were cleaned up"
)
}
})
...
...
proctl/threads_linux_amd64.go
浏览文件 @
c625f09a
...
...
@@ -18,22 +18,10 @@ import (
// ThreadContext represents a single thread of execution in the
// traced program.
type
ThreadContext
struct
{
Id
int
Process
*
DebuggedProcess
Status
*
syscall
.
WaitStatus
Regs
*
syscall
.
PtraceRegs
BreakPoints
map
[
uint64
]
*
BreakPoint
}
// Represents a single breakpoint. Stores information on the break
// point including the byte of data that originally was stored at that
// address.
type
BreakPoint
struct
{
FunctionName
string
File
string
Line
int
Addr
uint64
OriginalData
[]
byte
Id
int
Process
*
DebuggedProcess
Status
*
syscall
.
WaitStatus
Regs
*
syscall
.
PtraceRegs
}
type
Variable
struct
{
...
...
@@ -42,16 +30,6 @@ type Variable struct {
Type
string
}
type
BreakPointExistsError
struct
{
file
string
line
int
addr
uintptr
}
func
(
bpe
BreakPointExistsError
)
Error
()
string
{
return
fmt
.
Sprintf
(
"Breakpoint exists at %s:%d at %x"
,
bpe
.
file
,
bpe
.
line
,
bpe
.
addr
)
}
// Obtains register values from the debugged process.
func
(
thread
*
ThreadContext
)
Registers
()
(
*
syscall
.
PtraceRegs
,
error
)
{
err
:=
syscall
.
PtraceGetRegs
(
thread
.
Id
,
thread
.
Regs
)
...
...
@@ -80,62 +58,6 @@ func (thread *ThreadContext) CurrentPC() (uint64, error) {
return
regs
.
PC
(),
nil
}
// Sets a breakpoint in the running process.
func
(
thread
*
ThreadContext
)
Break
(
addr
uintptr
)
(
*
BreakPoint
,
error
)
{
var
(
int3
=
[]
byte
{
0xCC
}
f
,
l
,
fn
=
thread
.
Process
.
GoSymTable
.
PCToLine
(
uint64
(
addr
))
originalData
=
make
([]
byte
,
1
)
)
if
fn
==
nil
{
return
nil
,
InvalidAddressError
{
address
:
addr
}
}
_
,
err
:=
syscall
.
PtracePeekData
(
thread
.
Id
,
addr
,
originalData
)
if
err
!=
nil
{
return
nil
,
err
}
if
bytes
.
Equal
(
originalData
,
int3
)
{
return
nil
,
BreakPointExistsError
{
f
,
l
,
addr
}
}
_
,
err
=
syscall
.
PtracePokeData
(
thread
.
Id
,
addr
,
int3
)
if
err
!=
nil
{
return
nil
,
err
}
breakpoint
:=
&
BreakPoint
{
FunctionName
:
fn
.
Name
,
File
:
f
,
Line
:
l
,
Addr
:
uint64
(
addr
),
OriginalData
:
originalData
,
}
thread
.
BreakPoints
[
uint64
(
addr
)]
=
breakpoint
return
breakpoint
,
nil
}
// Clears a breakpoint.
func
(
thread
*
ThreadContext
)
Clear
(
pc
uint64
)
(
*
BreakPoint
,
error
)
{
bp
,
ok
:=
thread
.
BreakPoints
[
pc
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"No breakpoint currently set for %#v"
,
pc
)
}
_
,
err
:=
syscall
.
PtracePokeData
(
thread
.
Id
,
uintptr
(
bp
.
Addr
),
bp
.
OriginalData
)
if
err
!=
nil
{
return
nil
,
err
}
delete
(
thread
.
BreakPoints
,
pc
)
return
bp
,
nil
}
func
(
thread
*
ThreadContext
)
Continue
()
error
{
// Stepping first will ensure we are able to continue
// past a breakpoint if that's currently where we are stopped.
...
...
@@ -154,10 +76,10 @@ func (thread *ThreadContext) Step() (err error) {
return
err
}
bp
,
ok
:=
thread
.
BreakPoints
[
regs
.
PC
()
-
1
]
bp
,
ok
:=
thread
.
Process
.
BreakPoints
[
regs
.
PC
()
-
1
]
if
ok
{
// Clear the breakpoint so that we can continue execution.
_
,
err
=
thread
.
Clear
(
bp
.
Addr
)
_
,
err
=
thread
.
Process
.
Clear
(
bp
.
Addr
)
if
err
!=
nil
{
return
err
}
...
...
@@ -171,7 +93,7 @@ func (thread *ThreadContext) Step() (err error) {
// Restore breakpoint now that we have passed it.
defer
func
()
{
_
,
err
=
thread
.
Break
(
uintptr
(
bp
.
Addr
))
_
,
err
=
thread
.
Process
.
Break
(
uintptr
(
bp
.
Addr
))
}()
}
...
...
@@ -195,7 +117,7 @@ func (thread *ThreadContext) Next() (err error) {
return
err
}
if
_
,
ok
:=
thread
.
BreakPoints
[
pc
-
1
];
ok
{
if
_
,
ok
:=
thread
.
Process
.
BreakPoints
[
pc
-
1
];
ok
{
// Decrement the PC to be before
// the breakpoint instruction.
pc
--
...
...
@@ -251,7 +173,7 @@ func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.Frame
// has not had a chance to modify its' stack
// and change our offset.
addr
:=
thread
.
Process
.
ReturnAddressFromOffset
(
0
)
bp
,
err
:=
thread
.
Break
(
uintptr
(
addr
))
bp
,
err
:=
thread
.
Process
.
Break
(
uintptr
(
addr
))
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
BreakPointExistsError
);
!
ok
{
return
err
...
...
@@ -280,14 +202,14 @@ func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.Frame
}
func
(
thread
*
ThreadContext
)
clearTempBreakpoint
(
pc
uint64
)
error
{
if
bp
,
ok
:=
thread
.
BreakPoints
[
pc
];
ok
{
if
bp
,
ok
:=
thread
.
Process
.
BreakPoints
[
pc
];
ok
{
regs
,
err
:=
thread
.
Registers
()
if
err
!=
nil
{
return
err
}
// Reset program counter to our restored instruction.
bp
,
err
=
thread
.
Clear
(
bp
.
Addr
)
bp
,
err
=
thread
.
Process
.
Clear
(
bp
.
Addr
)
if
err
!=
nil
{
return
err
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录