Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
pubx
delve
提交
3c8d4d52
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,发现更多精彩内容 >>
提交
3c8d4d52
编写于
3月 26, 2020
作者:
A
aarzilli
提交者:
Derek Parker
3月 31, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
*: un-export unnecessarily public symbols
上级
1ee8d5c2
变更
41
展开全部
隐藏空白更改
内联
并排
Showing
41 changed file
with
593 addition
and
639 deletion
+593
-639
pkg/dwarf/frame/entries.go
pkg/dwarf/frame/entries.go
+1
-1
pkg/dwarf/frame/entries_test.go
pkg/dwarf/frame/entries_test.go
+1
-1
pkg/dwarf/frame/parser.go
pkg/dwarf/frame/parser.go
+1
-1
pkg/dwarf/frame/table.go
pkg/dwarf/frame/table.go
+2
-2
pkg/proc/core/core.go
pkg/proc/core/core.go
+60
-60
pkg/proc/core/core_test.go
pkg/proc/core/core_test.go
+2
-2
pkg/proc/core/linux_core.go
pkg/proc/core/linux_core.go
+69
-69
pkg/proc/core/windows_amd64_minidump.go
pkg/proc/core/windows_amd64_minidump.go
+5
-5
pkg/proc/gdbserial/gdbserver.go
pkg/proc/gdbserial/gdbserver.go
+82
-82
pkg/proc/gdbserial/gdbserver_conn.go
pkg/proc/gdbserial/gdbserver_conn.go
+1
-1
pkg/proc/gdbserial/rr.go
pkg/proc/gdbserial/rr.go
+1
-1
pkg/proc/native/nonative_darwin.go
pkg/proc/native/nonative_darwin.go
+27
-27
pkg/proc/native/proc.go
pkg/proc/native/proc.go
+42
-42
pkg/proc/native/proc_darwin.go
pkg/proc/native/proc_darwin.go
+22
-22
pkg/proc/native/proc_freebsd.go
pkg/proc/native/proc_freebsd.go
+35
-35
pkg/proc/native/proc_linux.go
pkg/proc/native/proc_linux.go
+30
-30
pkg/proc/native/proc_windows.go
pkg/proc/native/proc_windows.go
+19
-19
pkg/proc/native/ptrace_darwin.go
pkg/proc/native/ptrace_darwin.go
+8
-8
pkg/proc/native/ptrace_freebsd.go
pkg/proc/native/ptrace_freebsd.go
+10
-10
pkg/proc/native/ptrace_linux.go
pkg/proc/native/ptrace_linux.go
+6
-31
pkg/proc/native/ptrace_linux_386.go
pkg/proc/native/ptrace_linux_386.go
+8
-8
pkg/proc/native/ptrace_linux_64bit.go
pkg/proc/native/ptrace_linux_64bit.go
+4
-4
pkg/proc/native/ptrace_linux_amd64.go
pkg/proc/native/ptrace_linux_amd64.go
+3
-3
pkg/proc/native/register_linux_386.go
pkg/proc/native/register_linux_386.go
+7
-7
pkg/proc/native/registers_darwin_amd64.go
pkg/proc/native/registers_darwin_amd64.go
+4
-4
pkg/proc/native/registers_freebsd_amd64.go
pkg/proc/native/registers_freebsd_amd64.go
+6
-6
pkg/proc/native/registers_linux_amd64.go
pkg/proc/native/registers_linux_amd64.go
+6
-6
pkg/proc/native/registers_linux_arm64.go
pkg/proc/native/registers_linux_arm64.go
+12
-12
pkg/proc/native/registers_windows_amd64.go
pkg/proc/native/registers_windows_amd64.go
+4
-4
pkg/proc/native/threads.go
pkg/proc/native/threads.go
+16
-16
pkg/proc/native/threads_darwin.go
pkg/proc/native/threads_darwin.go
+13
-13
pkg/proc/native/threads_freebsd.go
pkg/proc/native/threads_freebsd.go
+17
-17
pkg/proc/native/threads_linux.go
pkg/proc/native/threads_linux.go
+15
-15
pkg/proc/native/threads_linux_386.go
pkg/proc/native/threads_linux_386.go
+1
-1
pkg/proc/native/threads_linux_amd64.go
pkg/proc/native/threads_linux_amd64.go
+1
-1
pkg/proc/native/threads_linux_arm64.go
pkg/proc/native/threads_linux_arm64.go
+3
-3
pkg/proc/native/threads_windows.go
pkg/proc/native/threads_windows.go
+11
-11
pkg/proc/proc_test.go
pkg/proc/proc_test.go
+0
-21
pkg/proc/test/support.go
pkg/proc/test/support.go
+7
-7
pkg/terminal/command.go
pkg/terminal/command.go
+30
-30
pkg/terminal/disasmprint.go
pkg/terminal/disasmprint.go
+1
-1
未找到文件。
pkg/dwarf/frame/entries.go
浏览文件 @
3c8d4d52
...
...
@@ -53,7 +53,7 @@ func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
type
FrameDescriptionEntries
[]
*
FrameDescriptionEntry
func
N
ewFrameIndex
()
FrameDescriptionEntries
{
func
n
ewFrameIndex
()
FrameDescriptionEntries
{
return
make
(
FrameDescriptionEntries
,
0
,
1000
)
}
...
...
pkg/dwarf/frame/entries_test.go
浏览文件 @
3c8d4d52
...
...
@@ -13,7 +13,7 @@ func ptrSizeByRuntimeArch() int {
}
func
TestFDEForPC
(
t
*
testing
.
T
)
{
frames
:=
N
ewFrameIndex
()
frames
:=
n
ewFrameIndex
()
frames
=
append
(
frames
,
&
FrameDescriptionEntry
{
begin
:
10
,
size
:
40
},
&
FrameDescriptionEntry
{
begin
:
50
,
size
:
50
},
...
...
pkg/dwarf/frame/parser.go
浏览文件 @
3c8d4d52
...
...
@@ -29,7 +29,7 @@ type parseContext struct {
func
Parse
(
data
[]
byte
,
order
binary
.
ByteOrder
,
staticBase
uint64
,
ptrSize
int
)
FrameDescriptionEntries
{
var
(
buf
=
bytes
.
NewBuffer
(
data
)
pctx
=
&
parseContext
{
buf
:
buf
,
entries
:
N
ewFrameIndex
(),
staticBase
:
staticBase
,
ptrSize
:
ptrSize
}
pctx
=
&
parseContext
{
buf
:
buf
,
entries
:
n
ewFrameIndex
(),
staticBase
:
staticBase
,
ptrSize
:
ptrSize
}
)
for
fn
:=
parselength
;
buf
.
Len
()
!=
0
;
{
...
...
pkg/dwarf/frame/table.go
浏览文件 @
3c8d4d52
...
...
@@ -127,7 +127,7 @@ func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext {
buf
:
bytes
.
NewBuffer
(
initialInstructions
),
}
frame
.
E
xecuteDwarfProgram
()
frame
.
e
xecuteDwarfProgram
()
return
frame
}
...
...
@@ -142,7 +142,7 @@ func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameCon
return
frame
}
func
(
frame
*
FrameContext
)
E
xecuteDwarfProgram
()
{
func
(
frame
*
FrameContext
)
e
xecuteDwarfProgram
()
{
for
frame
.
buf
.
Len
()
>
0
{
executeDwarfInstruction
(
frame
)
}
...
...
pkg/proc/core/core.go
浏览文件 @
3c8d4d52
...
...
@@ -9,7 +9,7 @@ import (
"github.com/go-delve/delve/pkg/proc"
)
// A
S
plicedMemory represents a memory space formed from multiple regions,
// A
s
plicedMemory represents a memory space formed from multiple regions,
// each of which may override previously regions. For example, in the following
// core, the program text was loaded at 0x400000:
// Start End Page Offset
...
...
@@ -22,7 +22,7 @@ import (
// 0x0000000000002000 0x0000000000002000 RW 1000
// This can be represented in a SplicedMemory by adding the original region,
// then putting the RW mapping on top of it.
type
S
plicedMemory
struct
{
type
s
plicedMemory
struct
{
readers
[]
readerEntry
}
...
...
@@ -33,7 +33,7 @@ type readerEntry struct {
}
// Add adds a new region to the SplicedMemory, which may override existing regions.
func
(
r
*
S
plicedMemory
)
Add
(
reader
proc
.
MemoryReader
,
off
,
length
uintptr
)
{
func
(
r
*
s
plicedMemory
)
Add
(
reader
proc
.
MemoryReader
,
off
,
length
uintptr
)
{
if
length
==
0
{
return
}
...
...
@@ -93,7 +93,7 @@ func (r *SplicedMemory) Add(reader proc.MemoryReader, off, length uintptr) {
}
// ReadMemory implements MemoryReader.ReadMemory.
func
(
r
*
S
plicedMemory
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
func
(
r
*
s
plicedMemory
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
started
:=
false
for
_
,
entry
:=
range
r
.
readers
{
if
entry
.
offset
+
entry
.
length
<
addr
{
...
...
@@ -132,40 +132,40 @@ func (r *SplicedMemory) ReadMemory(buf []byte, addr uintptr) (n int, err error)
return
n
,
nil
}
//
O
ffsetReaderAt wraps a ReaderAt into a MemoryReader, subtracting a fixed
//
o
ffsetReaderAt wraps a ReaderAt into a MemoryReader, subtracting a fixed
// offset from the address. This is useful to represent a mapping in an address
// space. For example, if program text is mapped in at 0x400000, an
// OffsetReaderAt with offset 0x400000 can be wrapped around file.Open(program)
// to return the results of a read in that part of the address space.
type
O
ffsetReaderAt
struct
{
type
o
ffsetReaderAt
struct
{
reader
io
.
ReaderAt
offset
uintptr
}
// ReadMemory will read the memory at addr-offset.
func
(
r
*
O
ffsetReaderAt
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
func
(
r
*
o
ffsetReaderAt
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
return
r
.
reader
.
ReadAt
(
buf
,
int64
(
addr
-
r
.
offset
))
}
//
P
rocess represents a core file.
type
P
rocess
struct
{
//
p
rocess represents a core file.
type
p
rocess
struct
{
mem
proc
.
MemoryReader
Threads
map
[
int
]
*
T
hread
Threads
map
[
int
]
*
t
hread
pid
int
entryPoint
uint64
bi
*
proc
.
BinaryInfo
breakpoints
proc
.
BreakpointMap
currentThread
*
T
hread
currentThread
*
t
hread
}
var
_
proc
.
ProcessInternal
=
&
P
rocess
{}
var
_
proc
.
ProcessInternal
=
&
p
rocess
{}
//
T
hread represents a thread in the core file being debugged.
type
T
hread
struct
{
//
t
hread represents a thread in the core file being debugged.
type
t
hread
struct
{
th
osThread
p
*
P
rocess
p
*
p
rocess
common
proc
.
CommonThread
}
...
...
@@ -189,7 +189,7 @@ var (
ErrChangeRegisterCore
=
errors
.
New
(
"can not change register values of core process"
)
)
type
openFn
func
(
string
,
string
)
(
*
P
rocess
,
error
)
type
openFn
func
(
string
,
string
)
(
*
p
rocess
,
error
)
var
openFns
=
[]
openFn
{
readLinuxCore
,
readAMD64Minidump
}
...
...
@@ -201,7 +201,7 @@ var ErrUnrecognizedFormat = errors.New("unrecognized core format")
// If the DWARF information cannot be found in the binary, Delve will look
// for external debug files in the directories passed in.
func
OpenCore
(
corePath
,
exePath
string
,
debugInfoDirs
[]
string
)
(
*
proc
.
Target
,
error
)
{
var
p
*
P
rocess
var
p
*
p
rocess
var
err
error
for
_
,
openFn
:=
range
openFns
{
p
,
err
=
openFn
(
corePath
,
exePath
)
...
...
@@ -222,49 +222,49 @@ func OpenCore(corePath, exePath string, debugInfoDirs []string) (*proc.Target, e
}
// BinInfo will return the binary info.
func
(
p
*
P
rocess
)
BinInfo
()
*
proc
.
BinaryInfo
{
func
(
p
*
p
rocess
)
BinInfo
()
*
proc
.
BinaryInfo
{
return
p
.
bi
}
// EntryPoint will return the entry point address for this core file.
func
(
p
*
P
rocess
)
EntryPoint
()
(
uint64
,
error
)
{
func
(
p
*
p
rocess
)
EntryPoint
()
(
uint64
,
error
)
{
return
p
.
entryPoint
,
nil
}
// writeBreakpoint is a noop function since you
// cannot write breakpoints into core files.
func
(
p
*
P
rocess
)
writeBreakpoint
(
addr
uint64
)
(
file
string
,
line
int
,
fn
*
proc
.
Function
,
originalData
[]
byte
,
err
error
)
{
func
(
p
*
p
rocess
)
writeBreakpoint
(
addr
uint64
)
(
file
string
,
line
int
,
fn
*
proc
.
Function
,
originalData
[]
byte
,
err
error
)
{
return
""
,
0
,
nil
,
nil
,
errors
.
New
(
"cannot write a breakpoint to a core file"
)
}
// Recorded returns whether this is a live or recorded process. Always returns true for core files.
func
(
p
*
P
rocess
)
Recorded
()
(
bool
,
string
)
{
return
true
,
""
}
func
(
p
*
p
rocess
)
Recorded
()
(
bool
,
string
)
{
return
true
,
""
}
// Restart will only return an error for core files, as they are not executing.
func
(
p
*
P
rocess
)
Restart
(
string
)
error
{
return
ErrContinueCore
}
func
(
p
*
p
rocess
)
Restart
(
string
)
error
{
return
ErrContinueCore
}
// ChangeDirection will only return an error as you cannot continue a core process.
func
(
p
*
P
rocess
)
ChangeDirection
(
proc
.
Direction
)
error
{
return
ErrContinueCore
}
func
(
p
*
p
rocess
)
ChangeDirection
(
proc
.
Direction
)
error
{
return
ErrContinueCore
}
// GetDirection will always return forward.
func
(
p
*
P
rocess
)
GetDirection
()
proc
.
Direction
{
return
proc
.
Forward
}
func
(
p
*
p
rocess
)
GetDirection
()
proc
.
Direction
{
return
proc
.
Forward
}
// When does not apply to core files, it is to support the Mozilla 'rr' backend.
func
(
p
*
P
rocess
)
When
()
(
string
,
error
)
{
return
""
,
nil
}
func
(
p
*
p
rocess
)
When
()
(
string
,
error
)
{
return
""
,
nil
}
// Checkpoint for core files returns an error, there is no execution of a core file.
func
(
p
*
P
rocess
)
Checkpoint
(
string
)
(
int
,
error
)
{
return
-
1
,
ErrContinueCore
}
func
(
p
*
p
rocess
)
Checkpoint
(
string
)
(
int
,
error
)
{
return
-
1
,
ErrContinueCore
}
// Checkpoints returns nil on core files, you cannot set checkpoints when debugging core files.
func
(
p
*
P
rocess
)
Checkpoints
()
([]
proc
.
Checkpoint
,
error
)
{
return
nil
,
nil
}
func
(
p
*
p
rocess
)
Checkpoints
()
([]
proc
.
Checkpoint
,
error
)
{
return
nil
,
nil
}
// ClearCheckpoint clears a checkpoint, but will only return an error for core files.
func
(
p
*
P
rocess
)
ClearCheckpoint
(
int
)
error
{
return
errors
.
New
(
"checkpoint not found"
)
}
func
(
p
*
p
rocess
)
ClearCheckpoint
(
int
)
error
{
return
errors
.
New
(
"checkpoint not found"
)
}
// ReadMemory will return memory from the core file at the specified location and put the
// read memory into `data`, returning the length read, and returning an error if
// the length read is shorter than the length of the `data` buffer.
func
(
t
*
T
hread
)
ReadMemory
(
data
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
func
(
t
*
t
hread
)
ReadMemory
(
data
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
n
,
err
=
t
.
p
.
mem
.
ReadMemory
(
data
,
addr
)
if
err
==
nil
&&
n
!=
len
(
data
)
{
err
=
ErrShortRead
...
...
@@ -274,13 +274,13 @@ func (t *Thread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
// WriteMemory will only return an error for core files, you cannot write
// to the memory of a core process.
func
(
t
*
T
hread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
func
(
t
*
t
hread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
return
0
,
ErrWriteCore
}
// Location returns the location of this thread based on
// the value of the instruction pointer register.
func
(
t
*
T
hread
)
Location
()
(
*
proc
.
Location
,
error
)
{
func
(
t
*
t
hread
)
Location
()
(
*
proc
.
Location
,
error
)
{
regs
,
err
:=
t
.
th
.
registers
(
false
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -293,150 +293,150 @@ func (t *Thread) Location() (*proc.Location, error) {
// Breakpoint returns the current breakpoint this thread is stopped at.
// For core files this always returns an empty BreakpointState struct, as
// there are no breakpoints when debugging core files.
func
(
t
*
T
hread
)
Breakpoint
()
*
proc
.
BreakpointState
{
func
(
t
*
t
hread
)
Breakpoint
()
*
proc
.
BreakpointState
{
return
&
proc
.
BreakpointState
{}
}
// ThreadID returns the ID for this thread.
func
(
t
*
T
hread
)
ThreadID
()
int
{
func
(
t
*
t
hread
)
ThreadID
()
int
{
return
int
(
t
.
th
.
pid
())
}
// Registers returns the current value of the registers for this thread.
func
(
t
*
T
hread
)
Registers
(
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
(
t
*
t
hread
)
Registers
(
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
return
t
.
th
.
registers
(
floatingPoint
)
}
// RestoreRegisters will only return an error for core files,
// you cannot change register values for core files.
func
(
t
*
T
hread
)
RestoreRegisters
(
proc
.
Registers
)
error
{
func
(
t
*
t
hread
)
RestoreRegisters
(
proc
.
Registers
)
error
{
return
ErrChangeRegisterCore
}
// BinInfo returns information about the binary.
func
(
t
*
T
hread
)
BinInfo
()
*
proc
.
BinaryInfo
{
func
(
t
*
t
hread
)
BinInfo
()
*
proc
.
BinaryInfo
{
return
t
.
p
.
bi
}
// StepInstruction will only return an error for core files,
// you cannot execute a core file.
func
(
t
*
T
hread
)
StepInstruction
()
error
{
func
(
t
*
t
hread
)
StepInstruction
()
error
{
return
ErrContinueCore
}
// Blocked will return false always for core files as there is
// no execution.
func
(
t
*
T
hread
)
Blocked
()
bool
{
func
(
t
*
t
hread
)
Blocked
()
bool
{
return
false
}
// SetCurrentBreakpoint will always just return nil
// for core files, as there are no breakpoints in core files.
func
(
t
*
T
hread
)
SetCurrentBreakpoint
(
adjustPC
bool
)
error
{
func
(
t
*
t
hread
)
SetCurrentBreakpoint
(
adjustPC
bool
)
error
{
return
nil
}
// Common returns a struct containing common information
// across thread implementations.
func
(
t
*
T
hread
)
Common
()
*
proc
.
CommonThread
{
func
(
t
*
t
hread
)
Common
()
*
proc
.
CommonThread
{
return
&
t
.
common
}
// SetPC will always return an error, you cannot
// change register values when debugging core files.
func
(
t
*
T
hread
)
SetPC
(
uint64
)
error
{
func
(
t
*
t
hread
)
SetPC
(
uint64
)
error
{
return
ErrChangeRegisterCore
}
// SetSP will always return an error, you cannot
// change register values when debugging core files.
func
(
t
*
T
hread
)
SetSP
(
uint64
)
error
{
func
(
t
*
t
hread
)
SetSP
(
uint64
)
error
{
return
ErrChangeRegisterCore
}
// SetDX will always return an error, you cannot
// change register values when debugging core files.
func
(
t
*
T
hread
)
SetDX
(
uint64
)
error
{
func
(
t
*
t
hread
)
SetDX
(
uint64
)
error
{
return
ErrChangeRegisterCore
}
// Breakpoints will return all breakpoints for the process.
func
(
p
*
P
rocess
)
Breakpoints
()
*
proc
.
BreakpointMap
{
func
(
p
*
p
rocess
)
Breakpoints
()
*
proc
.
BreakpointMap
{
return
&
p
.
breakpoints
}
// ClearBreakpoint will always return an error as you cannot set or clear
// breakpoints on core files.
func
(
p
*
P
rocess
)
ClearBreakpoint
(
addr
uint64
)
(
*
proc
.
Breakpoint
,
error
)
{
func
(
p
*
p
rocess
)
ClearBreakpoint
(
addr
uint64
)
(
*
proc
.
Breakpoint
,
error
)
{
return
nil
,
proc
.
NoBreakpointError
{
Addr
:
addr
}
}
// ClearInternalBreakpoints will always return nil and have no
// effect since you cannot set breakpoints on core files.
func
(
p
*
P
rocess
)
ClearInternalBreakpoints
()
error
{
func
(
p
*
p
rocess
)
ClearInternalBreakpoints
()
error
{
return
nil
}
// ContinueOnce will always return an error because you
// cannot control execution of a core file.
func
(
p
*
P
rocess
)
ContinueOnce
()
(
proc
.
Thread
,
proc
.
StopReason
,
error
)
{
func
(
p
*
p
rocess
)
ContinueOnce
()
(
proc
.
Thread
,
proc
.
StopReason
,
error
)
{
return
nil
,
proc
.
StopUnknown
,
ErrContinueCore
}
// StepInstruction will always return an error
// as you cannot control execution of a core file.
func
(
p
*
P
rocess
)
StepInstruction
()
error
{
func
(
p
*
p
rocess
)
StepInstruction
()
error
{
return
ErrContinueCore
}
// RequestManualStop will return nil and have no effect
// as you cannot control execution of a core file.
func
(
p
*
P
rocess
)
RequestManualStop
()
error
{
func
(
p
*
p
rocess
)
RequestManualStop
()
error
{
return
nil
}
// CheckAndClearManualStopRequest will always return false and
// have no effect since there are no manual stop requests as
// there is no controlling execution of a core file.
func
(
p
*
P
rocess
)
CheckAndClearManualStopRequest
()
bool
{
func
(
p
*
p
rocess
)
CheckAndClearManualStopRequest
()
bool
{
return
false
}
// CurrentThread returns the current active thread.
func
(
p
*
P
rocess
)
CurrentThread
()
proc
.
Thread
{
func
(
p
*
p
rocess
)
CurrentThread
()
proc
.
Thread
{
return
p
.
currentThread
}
// Detach will always return nil and have no
// effect as you cannot detach from a core file
// and have it continue execution or exit.
func
(
p
*
P
rocess
)
Detach
(
bool
)
error
{
func
(
p
*
p
rocess
)
Detach
(
bool
)
error
{
return
nil
}
// Valid returns whether the process is active. Always returns true
// for core files as it cannot exit or be otherwise detached from.
func
(
p
*
P
rocess
)
Valid
()
(
bool
,
error
)
{
func
(
p
*
p
rocess
)
Valid
()
(
bool
,
error
)
{
return
true
,
nil
}
// Pid returns the process ID of this process.
func
(
p
*
P
rocess
)
Pid
()
int
{
func
(
p
*
p
rocess
)
Pid
()
int
{
return
p
.
pid
}
// ResumeNotify is a no-op on core files as we cannot
// control execution.
func
(
p
*
P
rocess
)
ResumeNotify
(
chan
<-
struct
{})
{
func
(
p
*
p
rocess
)
ResumeNotify
(
chan
<-
struct
{})
{
}
// SetBreakpoint will always return an error for core files as you cannot write memory or control execution.
func
(
p
*
P
rocess
)
SetBreakpoint
(
addr
uint64
,
kind
proc
.
BreakpointKind
,
cond
ast
.
Expr
)
(
*
proc
.
Breakpoint
,
error
)
{
func
(
p
*
p
rocess
)
SetBreakpoint
(
addr
uint64
,
kind
proc
.
BreakpointKind
,
cond
ast
.
Expr
)
(
*
proc
.
Breakpoint
,
error
)
{
return
nil
,
ErrWriteCore
}
// ThreadList will return a list of all threads currently in the process.
func
(
p
*
P
rocess
)
ThreadList
()
[]
proc
.
Thread
{
func
(
p
*
p
rocess
)
ThreadList
()
[]
proc
.
Thread
{
r
:=
make
([]
proc
.
Thread
,
0
,
len
(
p
.
Threads
))
for
_
,
v
:=
range
p
.
Threads
{
r
=
append
(
r
,
v
)
...
...
@@ -445,12 +445,12 @@ func (p *Process) ThreadList() []proc.Thread {
}
// FindThread will return the thread with the corresponding thread ID.
func
(
p
*
P
rocess
)
FindThread
(
threadID
int
)
(
proc
.
Thread
,
bool
)
{
func
(
p
*
p
rocess
)
FindThread
(
threadID
int
)
(
proc
.
Thread
,
bool
)
{
t
,
ok
:=
p
.
Threads
[
threadID
]
return
t
,
ok
}
// SetCurrentThread is used internally by proc.Target to change the current thread.
func
(
p
*
P
rocess
)
SetCurrentThread
(
th
proc
.
Thread
)
{
p
.
currentThread
=
th
.
(
*
T
hread
)
func
(
p
*
p
rocess
)
SetCurrentThread
(
th
proc
.
Thread
)
{
p
.
currentThread
=
th
.
(
*
t
hread
)
}
pkg/proc/core/core_test.go
浏览文件 @
3c8d4d52
...
...
@@ -134,10 +134,10 @@ func TestSplicedReader(t *testing.T) {
}
for
_
,
test
:=
range
tests
{
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
mem
:=
&
S
plicedMemory
{}
mem
:=
&
s
plicedMemory
{}
for
_
,
region
:=
range
test
.
regions
{
r
:=
bytes
.
NewReader
(
region
.
data
)
mem
.
Add
(
&
O
ffsetReaderAt
{
r
,
0
},
region
.
off
,
region
.
length
)
mem
.
Add
(
&
o
ffsetReaderAt
{
r
,
0
},
region
.
off
,
region
.
length
)
}
got
:=
make
([]
byte
,
test
.
readLen
)
n
,
err
:=
mem
.
ReadMemory
(
got
,
test
.
readAddr
)
...
...
pkg/proc/core/linux_core.go
浏览文件 @
3c8d4d52
...
...
@@ -15,68 +15,68 @@ import (
// Copied from golang.org/x/sys/unix.Timeval since it's not available on all
// systems.
type
L
inuxCoreTimeval
struct
{
type
l
inuxCoreTimeval
struct
{
Sec
int64
Usec
int64
}
// NT_FILE is file mapping information, e.g. program text mappings. Desc is a LinuxNTFile.
const
NT_FILE
elf
.
NType
=
0x46494c45
// "FILE".
const
_
NT_FILE
elf
.
NType
=
0x46494c45
// "FILE".
// NT_X86_XSTATE is other registers, including AVX and such.
const
NT_X86_XSTATE
elf
.
NType
=
0x202
// Note type for notes containing X86 XSAVE area.
const
_
NT_X86_XSTATE
elf
.
NType
=
0x202
// Note type for notes containing X86 XSAVE area.
// NT_AUXV is the note type for notes containing a copy of the Auxv array
const
NT_AUXV
elf
.
NType
=
0x6
const
_
NT_AUXV
elf
.
NType
=
0x6
// NT_FPREGSET is the note type for floating point registers.
const
NT_FPREGSET
elf
.
NType
=
0x2
const
_
NT_FPREGSET
elf
.
NType
=
0x2
// Fetch architecture using exeELF.Machine from core file
// Refer http://man7.org/linux/man-pages/man5/elf.5.html
const
(
EM_AARCH64
=
183
EM_X86_64
=
62
_EM_AARCH64
=
183
_EM_X86_64
=
62
_ARM_FP_HEADER_START
=
512
)
const
elfErrorBadMagicNumber
=
"bad magic number"
func
linuxThreadsFromNotes
(
p
*
Process
,
notes
[]
*
N
ote
,
machineType
elf
.
Machine
)
{
func
linuxThreadsFromNotes
(
p
*
process
,
notes
[]
*
n
ote
,
machineType
elf
.
Machine
)
{
var
lastThreadAMD
*
linuxAMD64Thread
var
lastThreadARM
*
linuxARM64Thread
for
_
,
note
:=
range
notes
{
switch
note
.
Type
{
case
elf
.
NT_PRSTATUS
:
if
machineType
==
EM_X86_64
{
t
:=
note
.
Desc
.
(
*
L
inuxPrStatusAMD64
)
if
machineType
==
_
EM_X86_64
{
t
:=
note
.
Desc
.
(
*
l
inuxPrStatusAMD64
)
lastThreadAMD
=
&
linuxAMD64Thread
{
linutil
.
AMD64Registers
{
Regs
:
&
t
.
Reg
},
t
}
p
.
Threads
[
int
(
t
.
Pid
)]
=
&
T
hread
{
lastThreadAMD
,
p
,
proc
.
CommonThread
{}}
p
.
Threads
[
int
(
t
.
Pid
)]
=
&
t
hread
{
lastThreadAMD
,
p
,
proc
.
CommonThread
{}}
if
p
.
currentThread
==
nil
{
p
.
currentThread
=
p
.
Threads
[
int
(
t
.
Pid
)]
}
}
else
if
machineType
==
EM_AARCH64
{
t
:=
note
.
Desc
.
(
*
L
inuxPrStatusARM64
)
}
else
if
machineType
==
_
EM_AARCH64
{
t
:=
note
.
Desc
.
(
*
l
inuxPrStatusARM64
)
lastThreadARM
=
&
linuxARM64Thread
{
linutil
.
ARM64Registers
{
Regs
:
&
t
.
Reg
},
t
}
p
.
Threads
[
int
(
t
.
Pid
)]
=
&
T
hread
{
lastThreadARM
,
p
,
proc
.
CommonThread
{}}
p
.
Threads
[
int
(
t
.
Pid
)]
=
&
t
hread
{
lastThreadARM
,
p
,
proc
.
CommonThread
{}}
if
p
.
currentThread
==
nil
{
p
.
currentThread
=
p
.
Threads
[
int
(
t
.
Pid
)]
}
}
case
NT_FPREGSET
:
if
machineType
==
EM_AARCH64
{
case
_
NT_FPREGSET
:
if
machineType
==
_
EM_AARCH64
{
if
lastThreadARM
!=
nil
{
lastThreadARM
.
regs
.
Fpregs
=
note
.
Desc
.
(
*
linutil
.
ARM64PtraceFpRegs
)
.
Decode
()
}
}
case
NT_X86_XSTATE
:
if
machineType
==
EM_X86_64
{
case
_
NT_X86_XSTATE
:
if
machineType
==
_
EM_X86_64
{
if
lastThreadAMD
!=
nil
{
lastThreadAMD
.
regs
.
Fpregs
=
note
.
Desc
.
(
*
linutil
.
AMD64Xstate
)
.
Decode
()
}
}
case
elf
.
NT_PRPSINFO
:
p
.
pid
=
int
(
note
.
Desc
.
(
*
L
inuxPrPsInfo
)
.
Pid
)
p
.
pid
=
int
(
note
.
Desc
.
(
*
l
inuxPrPsInfo
)
.
Pid
)
}
}
}
...
...
@@ -87,7 +87,7 @@ func linuxThreadsFromNotes(p *Process, notes []*Note, machineType elf.Machine) {
// http://uhlo.blogspot.fr/2012/05/brief-look-into-core-dumps.html,
// elf_core_dump in http://lxr.free-electrons.com/source/fs/binfmt_elf.c,
// and, if absolutely desperate, readelf.c from the binutils source.
func
readLinuxCore
(
corePath
,
exePath
string
)
(
*
P
rocess
,
error
)
{
func
readLinuxCore
(
corePath
,
exePath
string
)
(
*
p
rocess
,
error
)
{
coreFile
,
err
:=
elf
.
Open
(
corePath
)
if
err
!=
nil
{
if
_
,
isfmterr
:=
err
.
(
*
elf
.
FormatError
);
isfmterr
&&
(
strings
.
Contains
(
err
.
Error
(),
elfErrorBadMagicNumber
)
||
strings
.
Contains
(
err
.
Error
(),
" at offset 0x0: too short"
))
{
...
...
@@ -122,9 +122,9 @@ func readLinuxCore(corePath, exePath string) (*Process, error) {
// TODO support 386
var
bi
*
proc
.
BinaryInfo
switch
machineType
{
case
EM_X86_64
:
case
_
EM_X86_64
:
bi
=
proc
.
NewBinaryInfo
(
"linux"
,
"amd64"
)
case
EM_AARCH64
:
case
_
EM_AARCH64
:
bi
=
proc
.
NewBinaryInfo
(
"linux"
,
"arm64"
)
default
:
return
nil
,
fmt
.
Errorf
(
"unsupported machine type"
)
...
...
@@ -132,9 +132,9 @@ func readLinuxCore(corePath, exePath string) (*Process, error) {
entryPoint
:=
findEntryPoint
(
notes
,
bi
.
Arch
.
PtrSize
())
p
:=
&
P
rocess
{
p
:=
&
p
rocess
{
mem
:
memory
,
Threads
:
map
[
int
]
*
T
hread
{},
Threads
:
map
[
int
]
*
t
hread
{},
entryPoint
:
entryPoint
,
bi
:
bi
,
breakpoints
:
proc
.
NewBreakpointMap
(),
...
...
@@ -146,12 +146,12 @@ func readLinuxCore(corePath, exePath string) (*Process, error) {
type
linuxAMD64Thread
struct
{
regs
linutil
.
AMD64Registers
t
*
L
inuxPrStatusAMD64
t
*
l
inuxPrStatusAMD64
}
type
linuxARM64Thread
struct
{
regs
linutil
.
ARM64Registers
t
*
L
inuxPrStatusARM64
t
*
l
inuxPrStatusARM64
}
func
(
t
*
linuxAMD64Thread
)
registers
(
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
...
...
@@ -187,14 +187,14 @@ func (t *linuxARM64Thread) pid() int {
// - NT_PRSTATUS: Information about a thread, including base registers, state, etc. Desc is a LinuxPrStatus.
// - NT_FPREGSET (Not implemented): x87 floating point registers.
// - NT_X86_XSTATE: Other registers, including AVX and such.
type
N
ote
struct
{
type
n
ote
struct
{
Type
elf
.
NType
Name
string
Desc
interface
{}
// Decoded Desc from the
}
// readNotes reads all the notes from the notes prog in core.
func
readNotes
(
core
*
elf
.
File
,
machineType
elf
.
Machine
)
([]
*
N
ote
,
error
)
{
func
readNotes
(
core
*
elf
.
File
,
machineType
elf
.
Machine
)
([]
*
n
ote
,
error
)
{
var
notesProg
*
elf
.
Prog
for
_
,
prog
:=
range
core
.
Progs
{
if
prog
.
Type
==
elf
.
PT_NOTE
{
...
...
@@ -204,7 +204,7 @@ func readNotes(core *elf.File, machineType elf.Machine) ([]*Note, error) {
}
r
:=
notesProg
.
Open
()
notes
:=
[]
*
N
ote
{}
notes
:=
[]
*
n
ote
{}
for
{
note
,
err
:=
readNote
(
r
,
machineType
)
if
err
==
io
.
EOF
{
...
...
@@ -220,11 +220,11 @@ func readNotes(core *elf.File, machineType elf.Machine) ([]*Note, error) {
}
// readNote reads a single note from r, decoding the descriptor if possible.
func
readNote
(
r
io
.
ReadSeeker
,
machineType
elf
.
Machine
)
(
*
N
ote
,
error
)
{
func
readNote
(
r
io
.
ReadSeeker
,
machineType
elf
.
Machine
)
(
*
n
ote
,
error
)
{
// Notes are laid out as described in the SysV ABI:
// http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section
note
:=
&
N
ote
{}
hdr
:=
&
ELF
NotesHdr
{}
note
:=
&
n
ote
{}
hdr
:=
&
elf
NotesHdr
{}
err
:=
binary
.
Read
(
r
,
binary
.
LittleEndian
,
hdr
)
if
err
!=
nil
{
...
...
@@ -247,10 +247,10 @@ func readNote(r io.ReadSeeker, machineType elf.Machine) (*Note, error) {
descReader
:=
bytes
.
NewReader
(
desc
)
switch
note
.
Type
{
case
elf
.
NT_PRSTATUS
:
if
machineType
==
EM_X86_64
{
note
.
Desc
=
&
L
inuxPrStatusAMD64
{}
}
else
if
machineType
==
EM_AARCH64
{
note
.
Desc
=
&
L
inuxPrStatusARM64
{}
if
machineType
==
_
EM_X86_64
{
note
.
Desc
=
&
l
inuxPrStatusAMD64
{}
}
else
if
machineType
==
_
EM_AARCH64
{
note
.
Desc
=
&
l
inuxPrStatusARM64
{}
}
else
{
return
nil
,
fmt
.
Errorf
(
"unsupported machine type"
)
}
...
...
@@ -258,39 +258,39 @@ func readNote(r io.ReadSeeker, machineType elf.Machine) (*Note, error) {
return
nil
,
fmt
.
Errorf
(
"reading NT_PRSTATUS: %v"
,
err
)
}
case
elf
.
NT_PRPSINFO
:
note
.
Desc
=
&
L
inuxPrPsInfo
{}
note
.
Desc
=
&
l
inuxPrPsInfo
{}
if
err
:=
binary
.
Read
(
descReader
,
binary
.
LittleEndian
,
note
.
Desc
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"reading NT_PRPSINFO: %v"
,
err
)
}
case
NT_FILE
:
case
_
NT_FILE
:
// No good documentation reference, but the structure is
// simply a header, including entry count, followed by that
// many entries, and then the file name of each entry,
// null-delimited. Not reading the names here.
data
:=
&
L
inuxNTFile
{}
if
err
:=
binary
.
Read
(
descReader
,
binary
.
LittleEndian
,
&
data
.
L
inuxNTFileHdr
);
err
!=
nil
{
data
:=
&
l
inuxNTFile
{}
if
err
:=
binary
.
Read
(
descReader
,
binary
.
LittleEndian
,
&
data
.
l
inuxNTFileHdr
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"reading NT_FILE header: %v"
,
err
)
}
for
i
:=
0
;
i
<
int
(
data
.
Count
);
i
++
{
entry
:=
&
L
inuxNTFileEntry
{}
entry
:=
&
l
inuxNTFileEntry
{}
if
err
:=
binary
.
Read
(
descReader
,
binary
.
LittleEndian
,
entry
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"reading NT_FILE entry %v: %v"
,
i
,
err
)
}
data
.
entries
=
append
(
data
.
entries
,
entry
)
}
note
.
Desc
=
data
case
NT_X86_XSTATE
:
if
machineType
==
EM_X86_64
{
case
_
NT_X86_XSTATE
:
if
machineType
==
_
EM_X86_64
{
var
fpregs
linutil
.
AMD64Xstate
if
err
:=
linutil
.
AMD64XstateRead
(
desc
,
true
,
&
fpregs
);
err
!=
nil
{
return
nil
,
err
}
note
.
Desc
=
&
fpregs
}
case
NT_AUXV
:
case
_
NT_AUXV
:
note
.
Desc
=
desc
case
NT_FPREGSET
:
if
machineType
==
EM_AARCH64
{
case
_
NT_FPREGSET
:
if
machineType
==
_
EM_AARCH64
{
fpregs
:=
&
linutil
.
ARM64PtraceFpRegs
{}
rdr
:=
bytes
.
NewReader
(
desc
[
:
_ARM_FP_HEADER_START
])
if
err
:=
binary
.
Read
(
rdr
,
binary
.
LittleEndian
,
fpregs
.
Byte
());
err
!=
nil
{
...
...
@@ -320,15 +320,15 @@ func skipPadding(r io.ReadSeeker, pad int64) error {
return
nil
}
func
buildMemory
(
core
,
exeELF
*
elf
.
File
,
exe
io
.
ReaderAt
,
notes
[]
*
N
ote
)
proc
.
MemoryReader
{
memory
:=
&
S
plicedMemory
{}
func
buildMemory
(
core
,
exeELF
*
elf
.
File
,
exe
io
.
ReaderAt
,
notes
[]
*
n
ote
)
proc
.
MemoryReader
{
memory
:=
&
s
plicedMemory
{}
// For now, assume all file mappings are to the exe.
for
_
,
note
:=
range
notes
{
if
note
.
Type
==
NT_FILE
{
fileNote
:=
note
.
Desc
.
(
*
L
inuxNTFile
)
if
note
.
Type
==
_
NT_FILE
{
fileNote
:=
note
.
Desc
.
(
*
l
inuxNTFile
)
for
_
,
entry
:=
range
fileNote
.
entries
{
r
:=
&
O
ffsetReaderAt
{
r
:=
&
o
ffsetReaderAt
{
reader
:
exe
,
offset
:
uintptr
(
entry
.
Start
-
(
entry
.
FileOfs
*
fileNote
.
PageSize
)),
}
...
...
@@ -346,7 +346,7 @@ func buildMemory(core, exeELF *elf.File, exe io.ReaderAt, notes []*Note) proc.Me
if
prog
.
Filesz
==
0
{
continue
}
r
:=
&
O
ffsetReaderAt
{
r
:=
&
o
ffsetReaderAt
{
reader
:
prog
.
ReaderAt
,
offset
:
uintptr
(
prog
.
Vaddr
),
}
...
...
@@ -357,9 +357,9 @@ func buildMemory(core, exeELF *elf.File, exe io.ReaderAt, notes []*Note) proc.Me
return
memory
}
func
findEntryPoint
(
notes
[]
*
N
ote
,
ptrSize
int
)
uint64
{
func
findEntryPoint
(
notes
[]
*
n
ote
,
ptrSize
int
)
uint64
{
for
_
,
note
:=
range
notes
{
if
note
.
Type
==
NT_AUXV
{
if
note
.
Type
==
_
NT_AUXV
{
return
linutil
.
EntryPointFromAuxv
(
note
.
Desc
.
([]
byte
),
ptrSize
)
}
}
...
...
@@ -370,7 +370,7 @@ func findEntryPoint(notes []*Note, ptrSize int) uint64 {
// AMD64 specific primarily because of unix.PtraceRegs, but also
// because some of the fields are word sized.
// See http://lxr.free-electrons.com/source/include/uapi/linux/elfcore.h
type
L
inuxPrPsInfo
struct
{
type
l
inuxPrPsInfo
struct
{
State
uint8
Sname
int8
Zomb
uint8
...
...
@@ -384,61 +384,61 @@ type LinuxPrPsInfo struct {
}
// LinuxPrStatusAMD64 is a copy of the prstatus kernel struct.
type
L
inuxPrStatusAMD64
struct
{
Siginfo
L
inuxSiginfo
type
l
inuxPrStatusAMD64
struct
{
Siginfo
l
inuxSiginfo
Cursig
uint16
_
[
2
]
uint8
Sigpend
uint64
Sighold
uint64
Pid
,
Ppid
,
Pgrp
,
Sid
int32
Utime
,
Stime
,
CUtime
,
CStime
L
inuxCoreTimeval
Utime
,
Stime
,
CUtime
,
CStime
l
inuxCoreTimeval
Reg
linutil
.
AMD64PtraceRegs
Fpvalid
int32
}
// LinuxPrStatusARM64 is a copy of the prstatus kernel struct.
type
L
inuxPrStatusARM64
struct
{
Siginfo
L
inuxSiginfo
type
l
inuxPrStatusARM64
struct
{
Siginfo
l
inuxSiginfo
Cursig
uint16
_
[
2
]
uint8
Sigpend
uint64
Sighold
uint64
Pid
,
Ppid
,
Pgrp
,
Sid
int32
Utime
,
Stime
,
CUtime
,
CStime
L
inuxCoreTimeval
Utime
,
Stime
,
CUtime
,
CStime
l
inuxCoreTimeval
Reg
linutil
.
ARM64PtraceRegs
Fpvalid
int32
}
// LinuxSiginfo is a copy of the
// siginfo kernel struct.
type
L
inuxSiginfo
struct
{
type
l
inuxSiginfo
struct
{
Signo
int32
Code
int32
Errno
int32
}
// LinuxNTFile contains information on mapped files.
type
L
inuxNTFile
struct
{
L
inuxNTFileHdr
entries
[]
*
L
inuxNTFileEntry
type
l
inuxNTFile
struct
{
l
inuxNTFileHdr
entries
[]
*
l
inuxNTFileEntry
}
// LinuxNTFileHdr is a header struct for NTFile.
type
L
inuxNTFileHdr
struct
{
type
l
inuxNTFileHdr
struct
{
Count
uint64
PageSize
uint64
}
// LinuxNTFileEntry is an entry of an NT_FILE note.
type
L
inuxNTFileEntry
struct
{
type
l
inuxNTFileEntry
struct
{
Start
uint64
End
uint64
FileOfs
uint64
}
//
ELF
NotesHdr is the ELF Notes header.
//
elf
NotesHdr is the ELF Notes header.
// Same size on 64 and 32-bit machines.
type
ELF
NotesHdr
struct
{
type
elf
NotesHdr
struct
{
Namesz
uint32
Descsz
uint32
Type
uint32
...
...
pkg/proc/core/windows_amd64_minidump.go
浏览文件 @
3c8d4d52
...
...
@@ -7,7 +7,7 @@ import (
"github.com/go-delve/delve/pkg/proc/winutil"
)
func
readAMD64Minidump
(
minidumpPath
,
exePath
string
)
(
*
P
rocess
,
error
)
{
func
readAMD64Minidump
(
minidumpPath
,
exePath
string
)
(
*
p
rocess
,
error
)
{
var
logfn
func
(
string
,
...
interface
{})
if
logflags
.
Minidump
()
{
logfn
=
logflags
.
MinidumpLogger
()
.
Infof
...
...
@@ -21,16 +21,16 @@ func readAMD64Minidump(minidumpPath, exePath string) (*Process, error) {
return
nil
,
err
}
memory
:=
&
S
plicedMemory
{}
memory
:=
&
s
plicedMemory
{}
for
i
:=
range
mdmp
.
MemoryRanges
{
m
:=
&
mdmp
.
MemoryRanges
[
i
]
memory
.
Add
(
m
,
uintptr
(
m
.
Addr
),
uintptr
(
len
(
m
.
Data
)))
}
p
:=
&
P
rocess
{
p
:=
&
p
rocess
{
mem
:
memory
,
Threads
:
map
[
int
]
*
T
hread
{},
Threads
:
map
[
int
]
*
t
hread
{},
bi
:
proc
.
NewBinaryInfo
(
"windows"
,
"amd64"
),
breakpoints
:
proc
.
NewBreakpointMap
(),
pid
:
int
(
mdmp
.
Pid
),
...
...
@@ -38,7 +38,7 @@ func readAMD64Minidump(minidumpPath, exePath string) (*Process, error) {
for
i
:=
range
mdmp
.
Threads
{
th
:=
&
mdmp
.
Threads
[
i
]
p
.
Threads
[
int
(
th
.
ID
)]
=
&
T
hread
{
&
windowsAMD64Thread
{
th
},
p
,
proc
.
CommonThread
{}}
p
.
Threads
[
int
(
th
.
ID
)]
=
&
t
hread
{
&
windowsAMD64Thread
{
th
},
p
,
proc
.
CommonThread
{}}
if
p
.
currentThread
==
nil
{
p
.
currentThread
=
p
.
Threads
[
int
(
th
.
ID
)]
}
...
...
pkg/proc/gdbserial/gdbserver.go
浏览文件 @
3c8d4d52
此差异已折叠。
点击以展开。
pkg/proc/gdbserial/gdbserver_conn.go
浏览文件 @
3c8d4d52
...
...
@@ -545,7 +545,7 @@ func (conn *gdbConn) writeRegister(threadID string, regnum int, data []byte) err
// resume each thread. If a thread has sig == 0 the 'c' action will be used,
// otherwise the 'C' action will be used and the value of sig will be passed
// to it.
func
(
conn
*
gdbConn
)
resume
(
threads
map
[
int
]
*
Thread
,
tu
*
threadUpdater
)
(
string
,
uint8
,
error
)
{
func
(
conn
*
gdbConn
)
resume
(
threads
map
[
int
]
*
gdb
Thread
,
tu
*
threadUpdater
)
(
string
,
uint8
,
error
)
{
if
conn
.
direction
==
proc
.
Forward
{
conn
.
outbuf
.
Reset
()
fmt
.
Fprintf
(
&
conn
.
outbuf
,
"$vCont"
)
...
...
pkg/proc/gdbserial/rr.go
浏览文件 @
3c8d4d52
...
...
@@ -104,7 +104,7 @@ func Replay(tracedir string, quiet, deleteOnDetach bool, debugInfoDirs []string)
return
nil
,
init
.
err
}
p
:=
New
(
rrcmd
.
Process
)
p
:=
newProcess
(
rrcmd
.
Process
)
p
.
tracedir
=
tracedir
if
deleteOnDetach
{
p
.
onDetach
=
func
()
{
...
...
pkg/proc/native/nonative_darwin.go
浏览文件 @
3c8d4d52
...
...
@@ -21,15 +21,15 @@ func Attach(pid int, _ []string) (*proc.Target, error) {
return
nil
,
ErrNativeBackendDisabled
}
//
W
aitStatus is a synonym for the platform-specific WaitStatus
type
W
aitStatus
struct
{}
//
w
aitStatus is a synonym for the platform-specific WaitStatus
type
w
aitStatus
struct
{}
//
OS
SpecificDetails holds information specific to the OSX/Darwin
//
os
SpecificDetails holds information specific to the OSX/Darwin
// operating system / kernel.
type
OS
SpecificDetails
struct
{}
type
os
SpecificDetails
struct
{}
//
OS
ProcessDetails holds Darwin specific information.
type
OS
ProcessDetails
struct
{}
//
os
ProcessDetails holds Darwin specific information.
type
os
ProcessDetails
struct
{}
func
findExecutable
(
path
string
,
pid
int
)
string
{
panic
(
ErrNativeBackendDisabled
)
...
...
@@ -39,94 +39,94 @@ func killProcess(pid int) error {
panic
(
ErrNativeBackendDisabled
)
}
func
registers
(
thread
*
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
registers
(
thread
*
native
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
loadProcessInformation
(
wg
*
sync
.
WaitGroup
)
{
func
(
dbp
*
native
Process
)
loadProcessInformation
(
wg
*
sync
.
WaitGroup
)
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
requestManualStop
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
requestManualStop
()
(
err
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
native
Process
)
resume
()
error
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
trapWait
(
pid
int
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
trapWait
(
pid
int
)
(
*
native
Thread
,
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
stop
(
trapthread
*
Thread
)
(
err
error
)
{
func
(
dbp
*
nativeProcess
)
stop
(
trapthread
*
native
Thread
)
(
err
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
updateThreadList
()
error
{
func
(
dbp
*
native
Process
)
updateThreadList
()
error
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
kill
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
kill
()
(
err
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
dbp
*
Process
)
detach
(
kill
bool
)
error
{
func
(
dbp
*
native
Process
)
detach
(
kill
bool
)
error
{
panic
(
ErrNativeBackendDisabled
)
}
// EntryPoint returns the entry point for the process,
// useful for PIEs.
func
(
dbp
*
Process
)
EntryPoint
()
(
uint64
,
error
)
{
func
(
dbp
*
native
Process
)
EntryPoint
()
(
uint64
,
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
// Blocked returns true if the thread is blocked
func
(
t
*
Thread
)
Blocked
()
bool
{
func
(
t
*
native
Thread
)
Blocked
()
bool
{
panic
(
ErrNativeBackendDisabled
)
}
// SetPC sets the value of the PC register.
func
(
t
*
Thread
)
SetPC
(
pc
uint64
)
error
{
func
(
t
*
native
Thread
)
SetPC
(
pc
uint64
)
error
{
panic
(
ErrNativeBackendDisabled
)
}
// SetSP sets the value of the SP register.
func
(
t
*
Thread
)
SetSP
(
sp
uint64
)
error
{
func
(
t
*
native
Thread
)
SetSP
(
sp
uint64
)
error
{
panic
(
ErrNativeBackendDisabled
)
}
// SetDX sets the value of the DX register.
func
(
t
*
Thread
)
SetDX
(
dx
uint64
)
error
{
func
(
t
*
native
Thread
)
SetDX
(
dx
uint64
)
error
{
panic
(
ErrNativeBackendDisabled
)
}
// ReadMemory reads len(buf) bytes at addr into buf.
func
(
t
*
Thread
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
int
,
error
)
{
func
(
t
*
native
Thread
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
int
,
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
// WriteMemory writes the contents of data at addr.
func
(
t
*
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
func
(
t
*
native
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
t
*
Thread
)
resume
()
error
{
func
(
t
*
native
Thread
)
resume
()
error
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
t
*
Thread
)
singleStep
()
error
{
func
(
t
*
native
Thread
)
singleStep
()
error
{
panic
(
ErrNativeBackendDisabled
)
}
func
(
t
*
Thread
)
restoreRegisters
(
sr
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
restoreRegisters
(
sr
proc
.
Registers
)
error
{
panic
(
ErrNativeBackendDisabled
)
}
// Stopped returns whether the thread is stopped at
// the operating system level.
func
(
t
*
Thread
)
Stopped
()
bool
{
func
(
t
*
native
Thread
)
Stopped
()
bool
{
panic
(
ErrNativeBackendDisabled
)
}
func
initialize
(
dbp
*
Process
)
error
{
return
nil
}
func
initialize
(
dbp
*
native
Process
)
error
{
return
nil
}
pkg/proc/native/proc.go
浏览文件 @
3c8d4d52
...
...
@@ -10,7 +10,7 @@ import (
// Process represents all of the information the debugger
// is holding onto regarding the process we are debugging.
type
Process
struct
{
type
native
Process
struct
{
bi
*
proc
.
BinaryInfo
pid
int
// Process Pid
...
...
@@ -20,12 +20,12 @@ type Process struct {
breakpoints
proc
.
BreakpointMap
// List of threads mapped as such: pid -> *Thread
threads
map
[
int
]
*
Thread
threads
map
[
int
]
*
native
Thread
// Active thread
currentThread
*
Thread
currentThread
*
native
Thread
os
*
OS
ProcessDetails
os
*
os
ProcessDetails
firstStart
bool
stopMu
sync
.
Mutex
resumeChan
chan
<-
struct
{}
...
...
@@ -37,19 +37,19 @@ type Process struct {
exited
,
detached
bool
}
var
_
proc
.
ProcessInternal
=
&
Process
{}
var
_
proc
.
ProcessInternal
=
&
native
Process
{}
//
New
returns an initialized Process struct. Before returning,
//
newProcess
returns an initialized Process struct. Before returning,
// it will also launch a goroutine in order to handle ptrace(2)
// functions. For more information, see the documentation on
// `handlePtraceFuncs`.
func
New
(
pid
int
)
*
Process
{
dbp
:=
&
Process
{
func
newProcess
(
pid
int
)
*
native
Process
{
dbp
:=
&
native
Process
{
pid
:
pid
,
threads
:
make
(
map
[
int
]
*
Thread
),
threads
:
make
(
map
[
int
]
*
native
Thread
),
breakpoints
:
proc
.
NewBreakpointMap
(),
firstStart
:
true
,
os
:
new
(
OS
ProcessDetails
),
os
:
new
(
os
ProcessDetails
),
ptraceChan
:
make
(
chan
func
()),
ptraceDoneChan
:
make
(
chan
interface
{}),
bi
:
proc
.
NewBinaryInfo
(
runtime
.
GOOS
,
runtime
.
GOARCH
),
...
...
@@ -59,20 +59,20 @@ func New(pid int) *Process {
}
// BinInfo will return the binary info struct associated with this process.
func
(
dbp
*
Process
)
BinInfo
()
*
proc
.
BinaryInfo
{
func
(
dbp
*
native
Process
)
BinInfo
()
*
proc
.
BinaryInfo
{
return
dbp
.
bi
}
// Recorded always returns false for the native proc backend.
func
(
dbp
*
Process
)
Recorded
()
(
bool
,
string
)
{
return
false
,
""
}
func
(
dbp
*
native
Process
)
Recorded
()
(
bool
,
string
)
{
return
false
,
""
}
// Restart will always return an error in the native proc backend, only for
// recorded traces.
func
(
dbp
*
Process
)
Restart
(
string
)
error
{
return
proc
.
ErrNotRecorded
}
func
(
dbp
*
native
Process
)
Restart
(
string
)
error
{
return
proc
.
ErrNotRecorded
}
// ChangeDirection will always return an error in the native proc backend, only for
// recorded traces.
func
(
dbp
*
Process
)
ChangeDirection
(
dir
proc
.
Direction
)
error
{
func
(
dbp
*
native
Process
)
ChangeDirection
(
dir
proc
.
Direction
)
error
{
if
dir
!=
proc
.
Forward
{
return
proc
.
ErrNotRecorded
}
...
...
@@ -80,25 +80,25 @@ func (dbp *Process) ChangeDirection(dir proc.Direction) error {
}
// GetDirection will always return Forward.
func
(
p
*
Process
)
GetDirection
()
proc
.
Direction
{
return
proc
.
Forward
}
func
(
p
*
native
Process
)
GetDirection
()
proc
.
Direction
{
return
proc
.
Forward
}
// When will always return an empty string and nil, not supported on native proc backend.
func
(
dbp
*
Process
)
When
()
(
string
,
error
)
{
return
""
,
nil
}
func
(
dbp
*
native
Process
)
When
()
(
string
,
error
)
{
return
""
,
nil
}
// Checkpoint will always return an error on the native proc backend,
// only supported for recorded traces.
func
(
dbp
*
Process
)
Checkpoint
(
string
)
(
int
,
error
)
{
return
-
1
,
proc
.
ErrNotRecorded
}
func
(
dbp
*
native
Process
)
Checkpoint
(
string
)
(
int
,
error
)
{
return
-
1
,
proc
.
ErrNotRecorded
}
// Checkpoints will always return an error on the native proc backend,
// only supported for recorded traces.
func
(
dbp
*
Process
)
Checkpoints
()
([]
proc
.
Checkpoint
,
error
)
{
return
nil
,
proc
.
ErrNotRecorded
}
func
(
dbp
*
native
Process
)
Checkpoints
()
([]
proc
.
Checkpoint
,
error
)
{
return
nil
,
proc
.
ErrNotRecorded
}
// ClearCheckpoint will always return an error on the native proc backend,
// only supported in recorded traces.
func
(
dbp
*
Process
)
ClearCheckpoint
(
int
)
error
{
return
proc
.
ErrNotRecorded
}
func
(
dbp
*
native
Process
)
ClearCheckpoint
(
int
)
error
{
return
proc
.
ErrNotRecorded
}
// Detach from the process being debugged, optionally killing it.
func
(
dbp
*
Process
)
Detach
(
kill
bool
)
(
err
error
)
{
func
(
dbp
*
native
Process
)
Detach
(
kill
bool
)
(
err
error
)
{
if
dbp
.
exited
{
return
nil
}
...
...
@@ -135,7 +135,7 @@ func (dbp *Process) Detach(kill bool) (err error) {
// Valid returns whether the process is still attached to and
// has not exited.
func
(
dbp
*
Process
)
Valid
()
(
bool
,
error
)
{
func
(
dbp
*
native
Process
)
Valid
()
(
bool
,
error
)
{
if
dbp
.
detached
{
return
false
,
proc
.
ErrProcessDetached
}
...
...
@@ -147,17 +147,17 @@ func (dbp *Process) Valid() (bool, error) {
// ResumeNotify specifies a channel that will be closed the next time
// ContinueOnce finishes resuming the target.
func
(
dbp
*
Process
)
ResumeNotify
(
ch
chan
<-
struct
{})
{
func
(
dbp
*
native
Process
)
ResumeNotify
(
ch
chan
<-
struct
{})
{
dbp
.
resumeChan
=
ch
}
// Pid returns the process ID.
func
(
dbp
*
Process
)
Pid
()
int
{
func
(
dbp
*
native
Process
)
Pid
()
int
{
return
dbp
.
pid
}
// ThreadList returns a list of threads in the process.
func
(
dbp
*
Process
)
ThreadList
()
[]
proc
.
Thread
{
func
(
dbp
*
native
Process
)
ThreadList
()
[]
proc
.
Thread
{
r
:=
make
([]
proc
.
Thread
,
0
,
len
(
dbp
.
threads
))
for
_
,
v
:=
range
dbp
.
threads
{
r
=
append
(
r
,
v
)
...
...
@@ -166,29 +166,29 @@ func (dbp *Process) ThreadList() []proc.Thread {
}
// FindThread attempts to find the thread with the specified ID.
func
(
dbp
*
Process
)
FindThread
(
threadID
int
)
(
proc
.
Thread
,
bool
)
{
func
(
dbp
*
native
Process
)
FindThread
(
threadID
int
)
(
proc
.
Thread
,
bool
)
{
th
,
ok
:=
dbp
.
threads
[
threadID
]
return
th
,
ok
}
// CurrentThread returns the current selected, active thread.
func
(
dbp
*
Process
)
CurrentThread
()
proc
.
Thread
{
func
(
dbp
*
native
Process
)
CurrentThread
()
proc
.
Thread
{
return
dbp
.
currentThread
}
// SetCurrentThread is used internally by proc.Target to change the current thread.
func
(
p
*
Process
)
SetCurrentThread
(
th
proc
.
Thread
)
{
p
.
currentThread
=
th
.
(
*
Thread
)
func
(
p
*
native
Process
)
SetCurrentThread
(
th
proc
.
Thread
)
{
p
.
currentThread
=
th
.
(
*
native
Thread
)
}
// Breakpoints returns a list of breakpoints currently set.
func
(
dbp
*
Process
)
Breakpoints
()
*
proc
.
BreakpointMap
{
func
(
dbp
*
native
Process
)
Breakpoints
()
*
proc
.
BreakpointMap
{
return
&
dbp
.
breakpoints
}
// RequestManualStop sets the `halt` flag and
// sends SIGSTOP to all threads.
func
(
dbp
*
Process
)
RequestManualStop
()
error
{
func
(
dbp
*
native
Process
)
RequestManualStop
()
error
{
if
dbp
.
exited
{
return
&
proc
.
ErrProcessExited
{
Pid
:
dbp
.
Pid
()}
}
...
...
@@ -200,7 +200,7 @@ func (dbp *Process) RequestManualStop() error {
// CheckAndClearManualStopRequest checks if a manual stop has
// been requested, and then clears that state.
func
(
dbp
*
Process
)
CheckAndClearManualStopRequest
()
bool
{
func
(
dbp
*
native
Process
)
CheckAndClearManualStopRequest
()
bool
{
dbp
.
stopMu
.
Lock
()
defer
dbp
.
stopMu
.
Unlock
()
...
...
@@ -210,7 +210,7 @@ func (dbp *Process) CheckAndClearManualStopRequest() bool {
return
msr
}
func
(
dbp
*
Process
)
writeBreakpoint
(
addr
uint64
)
(
string
,
int
,
*
proc
.
Function
,
[]
byte
,
error
)
{
func
(
dbp
*
native
Process
)
writeBreakpoint
(
addr
uint64
)
(
string
,
int
,
*
proc
.
Function
,
[]
byte
,
error
)
{
f
,
l
,
fn
:=
dbp
.
bi
.
PCToLine
(
uint64
(
addr
))
originalData
:=
make
([]
byte
,
dbp
.
bi
.
Arch
.
BreakpointSize
())
...
...
@@ -227,12 +227,12 @@ func (dbp *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, [
// SetBreakpoint sets a breakpoint at addr, and stores it in the process wide
// break point table.
func
(
dbp
*
Process
)
SetBreakpoint
(
addr
uint64
,
kind
proc
.
BreakpointKind
,
cond
ast
.
Expr
)
(
*
proc
.
Breakpoint
,
error
)
{
func
(
dbp
*
native
Process
)
SetBreakpoint
(
addr
uint64
,
kind
proc
.
BreakpointKind
,
cond
ast
.
Expr
)
(
*
proc
.
Breakpoint
,
error
)
{
return
dbp
.
breakpoints
.
Set
(
addr
,
kind
,
cond
,
dbp
.
writeBreakpoint
)
}
// ClearBreakpoint clears the breakpoint at addr.
func
(
dbp
*
Process
)
ClearBreakpoint
(
addr
uint64
)
(
*
proc
.
Breakpoint
,
error
)
{
func
(
dbp
*
native
Process
)
ClearBreakpoint
(
addr
uint64
)
(
*
proc
.
Breakpoint
,
error
)
{
if
dbp
.
exited
{
return
nil
,
&
proc
.
ErrProcessExited
{
Pid
:
dbp
.
Pid
()}
}
...
...
@@ -241,7 +241,7 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
// ContinueOnce will continue the target until it stops.
// This could be the result of a breakpoint or signal.
func
(
dbp
*
Process
)
ContinueOnce
()
(
proc
.
Thread
,
proc
.
StopReason
,
error
)
{
func
(
dbp
*
native
Process
)
ContinueOnce
()
(
proc
.
Thread
,
proc
.
StopReason
,
error
)
{
if
dbp
.
exited
{
return
nil
,
proc
.
StopExited
,
&
proc
.
ErrProcessExited
{
Pid
:
dbp
.
Pid
()}
}
...
...
@@ -270,7 +270,7 @@ func (dbp *Process) ContinueOnce() (proc.Thread, proc.StopReason, error) {
}
// FindBreakpoint finds the breakpoint for the given pc.
func
(
dbp
*
Process
)
FindBreakpoint
(
pc
uint64
,
adjustPC
bool
)
(
*
proc
.
Breakpoint
,
bool
)
{
func
(
dbp
*
native
Process
)
FindBreakpoint
(
pc
uint64
,
adjustPC
bool
)
(
*
proc
.
Breakpoint
,
bool
)
{
if
adjustPC
{
// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
if
bp
,
ok
:=
dbp
.
breakpoints
.
M
[
pc
-
uint64
(
dbp
.
bi
.
Arch
.
BreakpointSize
())];
ok
{
...
...
@@ -286,7 +286,7 @@ func (dbp *Process) FindBreakpoint(pc uint64, adjustPC bool) (*proc.Breakpoint,
// initialize will ensure that all relevant information is loaded
// so the process is ready to be debugged.
func
(
dbp
*
Process
)
initialize
(
path
string
,
debugInfoDirs
[]
string
)
(
*
proc
.
Target
,
error
)
{
func
(
dbp
*
native
Process
)
initialize
(
path
string
,
debugInfoDirs
[]
string
)
(
*
proc
.
Target
,
error
)
{
if
err
:=
initialize
(
dbp
);
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -307,7 +307,7 @@ func (dbp *Process) initialize(path string, debugInfoDirs []string) (*proc.Targe
// ClearInternalBreakpoints will clear all non-user set breakpoints. These
// breakpoints are set for internal operations such as 'next'.
func
(
dbp
*
Process
)
ClearInternalBreakpoints
()
error
{
func
(
dbp
*
native
Process
)
ClearInternalBreakpoints
()
error
{
return
dbp
.
breakpoints
.
ClearInternalBreakpoints
(
func
(
bp
*
proc
.
Breakpoint
)
error
{
if
err
:=
dbp
.
currentThread
.
ClearBreakpoint
(
bp
);
err
!=
nil
{
return
err
...
...
@@ -321,7 +321,7 @@ func (dbp *Process) ClearInternalBreakpoints() error {
})
}
func
(
dbp
*
Process
)
handlePtraceFuncs
()
{
func
(
dbp
*
native
Process
)
handlePtraceFuncs
()
{
// We must ensure here that we are running on the same thread during
// while invoking the ptrace(2) syscall. This is due to the fact that ptrace(2) expects
// all commands after PTRACE_ATTACH to come from the same thread.
...
...
@@ -333,19 +333,19 @@ func (dbp *Process) handlePtraceFuncs() {
}
}
func
(
dbp
*
Process
)
execPtraceFunc
(
fn
func
())
{
func
(
dbp
*
native
Process
)
execPtraceFunc
(
fn
func
())
{
dbp
.
ptraceChan
<-
fn
<-
dbp
.
ptraceDoneChan
}
func
(
dbp
*
Process
)
postExit
()
{
func
(
dbp
*
native
Process
)
postExit
()
{
dbp
.
exited
=
true
close
(
dbp
.
ptraceChan
)
close
(
dbp
.
ptraceDoneChan
)
dbp
.
bi
.
Close
()
}
func
(
dbp
*
Process
)
writeSoftwareBreakpoint
(
thread
*
Thread
,
addr
uint64
)
error
{
func
(
dbp
*
nativeProcess
)
writeSoftwareBreakpoint
(
thread
*
native
Thread
,
addr
uint64
)
error
{
_
,
err
:=
thread
.
WriteMemory
(
uintptr
(
addr
),
dbp
.
bi
.
Arch
.
BreakpointInstruction
())
return
err
}
pkg/proc/native/proc_darwin.go
浏览文件 @
3c8d4d52
...
...
@@ -20,8 +20,8 @@ import (
"github.com/go-delve/delve/pkg/proc"
)
//
OS
ProcessDetails holds Darwin specific information.
type
OS
ProcessDetails
struct
{
//
os
ProcessDetails holds Darwin specific information.
type
os
ProcessDetails
struct
{
task
C
.
task_t
// mach task for the debugged process.
exceptionPort
C
.
mach_port_t
// mach port for receiving mach exceptions.
notificationPort
C
.
mach_port_t
// mach port for dead name notification (process exit).
...
...
@@ -64,7 +64,7 @@ func Launch(cmd []string, wd string, foreground bool, _ []string) (*proc.Target,
// argv array must be null terminated.
argvSlice
=
append
(
argvSlice
,
nil
)
dbp
:=
New
(
0
)
dbp
:=
newProcess
(
0
)
var
pid
int
dbp
.
execPtraceFunc
(
func
()
{
ret
:=
C
.
fork_exec
(
argv0
,
&
argvSlice
[
0
],
C
.
int
(
len
(
argvSlice
)),
...
...
@@ -129,7 +129,7 @@ func Launch(cmd []string, wd string, foreground bool, _ []string) (*proc.Target,
// Attach to an existing process with the given PID.
func
Attach
(
pid
int
,
_
[]
string
)
(
*
proc
.
Target
,
error
)
{
dbp
:=
New
(
pid
)
dbp
:=
newProcess
(
pid
)
kret
:=
C
.
acquire_mach_task
(
C
.
int
(
pid
),
&
dbp
.
os
.
task
,
&
dbp
.
os
.
portSet
,
&
dbp
.
os
.
exceptionPort
,
...
...
@@ -142,7 +142,7 @@ func Attach(pid int, _ []string) (*proc.Target, error) {
dbp
.
os
.
initialized
=
true
var
err
error
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceAttach
(
dbp
.
pid
)
})
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceAttach
(
dbp
.
pid
)
})
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -160,7 +160,7 @@ func Attach(pid int, _ []string) (*proc.Target, error) {
}
// Kill kills the process.
func
(
dbp
*
Process
)
kill
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
kill
()
(
err
error
)
{
if
dbp
.
exited
{
return
nil
}
...
...
@@ -184,7 +184,7 @@ func (dbp *Process) kill() (err error) {
return
}
func
(
dbp
*
Process
)
requestManualStop
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
requestManualStop
()
(
err
error
)
{
var
(
task
=
C
.
mach_port_t
(
dbp
.
os
.
task
)
thread
=
C
.
mach_port_t
(
dbp
.
currentThread
.
os
.
threadAct
)
...
...
@@ -201,11 +201,11 @@ func (dbp *Process) requestManualStop() (err error) {
var
couldNotGetThreadCount
=
errors
.
New
(
"could not get thread count"
)
var
couldNotGetThreadList
=
errors
.
New
(
"could not get thread list"
)
func
(
dbp
*
Process
)
updateThreadList
()
error
{
func
(
dbp
*
native
Process
)
updateThreadList
()
error
{
return
dbp
.
updateThreadListForTask
(
dbp
.
os
.
task
)
}
func
(
dbp
*
Process
)
updateThreadListForTask
(
task
C
.
task_t
)
error
{
func
(
dbp
*
native
Process
)
updateThreadListForTask
(
task
C
.
task_t
)
error
{
var
(
err
error
kret
C
.
kern_return_t
...
...
@@ -255,14 +255,14 @@ func (dbp *Process) updateThreadListForTask(task C.task_t) error {
return
nil
}
func
(
dbp
*
Process
)
addThread
(
port
int
,
attach
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
addThread
(
port
int
,
attach
bool
)
(
*
native
Thread
,
error
)
{
if
thread
,
ok
:=
dbp
.
threads
[
port
];
ok
{
return
thread
,
nil
}
thread
:=
&
Thread
{
thread
:=
&
native
Thread
{
ID
:
port
,
dbp
:
dbp
,
os
:
new
(
OS
SpecificDetails
),
os
:
new
(
os
SpecificDetails
),
}
dbp
.
threads
[
port
]
=
thread
thread
.
os
.
threadAct
=
C
.
thread_act_t
(
port
)
...
...
@@ -279,7 +279,7 @@ func findExecutable(path string, pid int) string {
return
path
}
func
(
dbp
*
Process
)
trapWait
(
pid
int
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
trapWait
(
pid
int
)
(
*
native
Thread
,
error
)
{
for
{
task
:=
dbp
.
os
.
task
port
:=
C
.
mach_port_wait
(
dbp
.
os
.
portSet
,
&
task
,
C
.
int
(
0
))
...
...
@@ -357,7 +357,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
}
}
func
(
dbp
*
Process
)
waitForStop
()
([]
int
,
error
)
{
func
(
dbp
*
native
Process
)
waitForStop
()
([]
int
,
error
)
{
ports
:=
make
([]
int
,
0
,
len
(
dbp
.
threads
))
count
:=
0
for
{
...
...
@@ -379,7 +379,7 @@ func (dbp *Process) waitForStop() ([]int, error) {
}
}
func
(
dbp
*
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
func
(
dbp
*
native
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
var
status
sys
.
WaitStatus
wpid
,
err
:=
sys
.
Wait4
(
pid
,
&
status
,
options
,
nil
)
return
wpid
,
&
status
,
err
...
...
@@ -389,7 +389,7 @@ func killProcess(pid int) error {
return
sys
.
Kill
(
pid
,
sys
.
SIGINT
)
}
func
(
dbp
*
Process
)
exitGuard
(
err
error
)
error
{
func
(
dbp
*
native
Process
)
exitGuard
(
err
error
)
error
{
if
err
!=
ErrContinueThread
{
return
err
}
...
...
@@ -401,7 +401,7 @@ func (dbp *Process) exitGuard(err error) error {
return
err
}
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
native
Process
)
resume
()
error
{
// all threads stopped over a breakpoint are made to step over it
for
_
,
thread
:=
range
dbp
.
threads
{
if
thread
.
CurrentBreakpoint
.
Breakpoint
!=
nil
{
...
...
@@ -421,7 +421,7 @@ func (dbp *Process) resume() error {
}
// stop stops all running threads and sets breakpoints
func
(
dbp
*
Process
)
stop
(
trapthread
*
Thread
)
(
err
error
)
{
func
(
dbp
*
nativeProcess
)
stop
(
trapthread
*
native
Thread
)
(
err
error
)
{
if
dbp
.
exited
{
return
&
proc
.
ErrProcessExited
{
Pid
:
dbp
.
Pid
()}
}
...
...
@@ -452,13 +452,13 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
return
nil
}
func
(
dbp
*
Process
)
detach
(
kill
bool
)
error
{
return
P
traceDetach
(
dbp
.
pid
,
0
)
func
(
dbp
*
native
Process
)
detach
(
kill
bool
)
error
{
return
p
traceDetach
(
dbp
.
pid
,
0
)
}
func
(
dbp
*
Process
)
EntryPoint
()
(
uint64
,
error
)
{
func
(
dbp
*
native
Process
)
EntryPoint
()
(
uint64
,
error
)
{
//TODO(aarzilli): implement this
return
0
,
nil
}
func
initialize
(
dbp
*
Process
)
error
{
return
nil
}
func
initialize
(
dbp
*
native
Process
)
error
{
return
nil
}
pkg/proc/native/proc_freebsd.go
浏览文件 @
3c8d4d52
...
...
@@ -22,18 +22,18 @@ import (
// Process statuses
const
(
S
tatusIdle
=
1
S
tatusRunning
=
2
S
tatusSleeping
=
3
S
tatusStopped
=
4
S
tatusZombie
=
5
S
tatusWaiting
=
6
S
tatusLocked
=
7
s
tatusIdle
=
1
s
tatusRunning
=
2
s
tatusSleeping
=
3
s
tatusStopped
=
4
s
tatusZombie
=
5
s
tatusWaiting
=
6
s
tatusLocked
=
7
)
//
OS
ProcessDetails contains FreeBSD specific
//
os
ProcessDetails contains FreeBSD specific
// process details.
type
OS
ProcessDetails
struct
{
type
os
ProcessDetails
struct
{
comm
string
tid
int
}
...
...
@@ -59,7 +59,7 @@ func Launch(cmd []string, wd string, foreground bool, debugInfoDirs []string) (*
foreground
=
false
}
dbp
:=
New
(
0
)
dbp
:=
newProcess
(
0
)
dbp
.
execPtraceFunc
(
func
()
{
process
=
exec
.
Command
(
cmd
[
0
])
process
.
Args
=
cmd
...
...
@@ -95,10 +95,10 @@ func Launch(cmd []string, wd string, foreground bool, debugInfoDirs []string) (*
// the DWARF information cannot be found in the binary, Delve will look
// for external debug files in the directories passed in.
func
Attach
(
pid
int
,
debugInfoDirs
[]
string
)
(
*
proc
.
Target
,
error
)
{
dbp
:=
New
(
pid
)
dbp
:=
newProcess
(
pid
)
var
err
error
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceAttach
(
dbp
.
pid
)
})
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceAttach
(
dbp
.
pid
)
})
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -115,7 +115,7 @@ func Attach(pid int, debugInfoDirs []string) (*proc.Target, error) {
return
tgt
,
nil
}
func
initialize
(
dbp
*
Process
)
error
{
func
initialize
(
dbp
*
native
Process
)
error
{
comm
,
_
:=
C
.
find_command_name
(
C
.
int
(
dbp
.
pid
))
defer
C
.
free
(
unsafe
.
Pointer
(
comm
))
comm_str
:=
C
.
GoString
(
comm
)
...
...
@@ -124,11 +124,11 @@ func initialize(dbp *Process) error {
}
// kill kills the target process.
func
(
dbp
*
Process
)
kill
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
kill
()
(
err
error
)
{
if
dbp
.
exited
{
return
nil
}
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
dbp
.
pid
,
int
(
sys
.
SIGKILL
))
})
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
dbp
.
pid
,
int
(
sys
.
SIGKILL
))
})
if
err
!=
nil
{
return
err
}
...
...
@@ -140,13 +140,13 @@ func (dbp *Process) kill() (err error) {
}
// Used by RequestManualStop
func
(
dbp
*
Process
)
requestManualStop
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
requestManualStop
()
(
err
error
)
{
return
sys
.
Kill
(
dbp
.
pid
,
sys
.
SIGTRAP
)
}
// Attach to a newly created thread, and store that thread in our list of
// known threads.
func
(
dbp
*
Process
)
addThread
(
tid
int
,
attach
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
addThread
(
tid
int
,
attach
bool
)
(
*
native
Thread
,
error
)
{
if
thread
,
ok
:=
dbp
.
threads
[
tid
];
ok
{
return
thread
,
nil
}
...
...
@@ -159,10 +159,10 @@ func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) {
}
}
dbp
.
threads
[
tid
]
=
&
Thread
{
dbp
.
threads
[
tid
]
=
&
native
Thread
{
ID
:
tid
,
dbp
:
dbp
,
os
:
new
(
OS
SpecificDetails
),
os
:
new
(
os
SpecificDetails
),
}
if
dbp
.
currentThread
==
nil
{
...
...
@@ -173,9 +173,9 @@ func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) {
}
// Used by initialize
func
(
dbp
*
Process
)
updateThreadList
()
error
{
func
(
dbp
*
native
Process
)
updateThreadList
()
error
{
var
tids
[]
int32
dbp
.
execPtraceFunc
(
func
()
{
tids
=
P
traceGetLwpList
(
dbp
.
pid
)
})
dbp
.
execPtraceFunc
(
func
()
{
tids
=
p
traceGetLwpList
(
dbp
.
pid
)
})
for
_
,
tid
:=
range
tids
{
if
_
,
err
:=
dbp
.
addThread
(
int
(
tid
),
false
);
err
!=
nil
{
return
err
...
...
@@ -195,12 +195,12 @@ func findExecutable(path string, pid int) string {
return
path
}
func
(
dbp
*
Process
)
trapWait
(
pid
int
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
trapWait
(
pid
int
)
(
*
native
Thread
,
error
)
{
return
dbp
.
trapWaitInternal
(
pid
,
false
)
}
// Used by stop and trapWait
func
(
dbp
*
Process
)
trapWaitInternal
(
pid
int
,
halt
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
trapWaitInternal
(
pid
int
,
halt
bool
)
(
*
native
Thread
,
error
)
{
for
{
wpid
,
status
,
err
:=
dbp
.
wait
(
pid
,
0
)
if
err
!=
nil
{
...
...
@@ -225,13 +225,13 @@ func (dbp *Process) trapWaitInternal(pid int, halt bool) (*Thread, error) {
pl_flags
:=
int
(
info
.
Flags
)
th
,
ok
:=
dbp
.
threads
[
tid
]
if
ok
{
th
.
Status
=
(
*
W
aitStatus
)(
status
)
th
.
Status
=
(
*
w
aitStatus
)(
status
)
}
if
status
.
StopSignal
()
==
sys
.
SIGTRAP
{
if
pl_flags
&
sys
.
PL_FLAG_EXITED
!=
0
{
delete
(
dbp
.
threads
,
tid
)
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
tid
,
0
)
})
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
tid
,
0
)
})
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -287,25 +287,25 @@ func status(pid int) rune {
// Used by stop and singleStep
// waitFast is like wait but does not handle process-exit correctly
func
(
dbp
*
Process
)
waitFast
(
pid
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
func
(
dbp
*
native
Process
)
waitFast
(
pid
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
var
s
sys
.
WaitStatus
wpid
,
err
:=
sys
.
Wait4
(
pid
,
&
s
,
0
,
nil
)
return
wpid
,
&
s
,
err
}
// Only used in this file
func
(
dbp
*
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
func
(
dbp
*
native
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
var
s
sys
.
WaitStatus
wpid
,
err
:=
sys
.
Wait4
(
pid
,
&
s
,
options
,
nil
)
return
wpid
,
&
s
,
err
}
// Only used in this file
func
(
dbp
*
Process
)
exitGuard
(
err
error
)
error
{
func
(
dbp
*
native
Process
)
exitGuard
(
err
error
)
error
{
if
err
!=
sys
.
ESRCH
{
return
err
}
if
status
(
dbp
.
pid
)
==
S
tatusZombie
{
if
status
(
dbp
.
pid
)
==
s
tatusZombie
{
_
,
err
:=
dbp
.
trapWaitInternal
(
-
1
,
false
)
return
err
}
...
...
@@ -314,7 +314,7 @@ func (dbp *Process) exitGuard(err error) error {
}
// Used by ContinueOnce
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
native
Process
)
resume
()
error
{
// all threads stopped over a breakpoint are made to step over it
for
_
,
thread
:=
range
dbp
.
threads
{
if
thread
.
CurrentBreakpoint
.
Breakpoint
!=
nil
{
...
...
@@ -326,13 +326,13 @@ func (dbp *Process) resume() error {
}
// all threads are resumed
var
err
error
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
dbp
.
pid
,
0
)
})
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
dbp
.
pid
,
0
)
})
return
err
}
// Used by ContinueOnce
// stop stops all running threads and sets breakpoints
func
(
dbp
*
Process
)
stop
(
trapthread
*
Thread
)
(
err
error
)
{
func
(
dbp
*
nativeProcess
)
stop
(
trapthread
*
native
Thread
)
(
err
error
)
{
if
dbp
.
exited
{
return
&
proc
.
ErrProcessExited
{
Pid
:
dbp
.
Pid
()}
}
...
...
@@ -348,13 +348,13 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
}
// Used by Detach
func
(
dbp
*
Process
)
detach
(
kill
bool
)
error
{
return
P
traceDetach
(
dbp
.
pid
)
func
(
dbp
*
native
Process
)
detach
(
kill
bool
)
error
{
return
p
traceDetach
(
dbp
.
pid
)
}
// Used by PostInitializationSetup
// EntryPoint will return the process entry point address, useful for debugging PIEs.
func
(
dbp
*
Process
)
EntryPoint
()
(
uint64
,
error
)
{
func
(
dbp
*
native
Process
)
EntryPoint
()
(
uint64
,
error
)
{
ep
,
err
:=
C
.
get_entry_point
(
C
.
int
(
dbp
.
pid
))
return
uint64
(
ep
),
err
}
...
...
pkg/proc/native/proc_linux.go
浏览文件 @
3c8d4d52
...
...
@@ -26,21 +26,21 @@ import (
// Process statuses
const
(
S
tatusSleeping
=
'S'
S
tatusRunning
=
'R'
S
tatusTraceStop
=
't'
S
tatusZombie
=
'Z'
s
tatusSleeping
=
'S'
s
tatusRunning
=
'R'
s
tatusTraceStop
=
't'
s
tatusZombie
=
'Z'
// Kernel 2.6 has TraceStop as T
// TODO(derekparker) Since this means something different based on the
// version of the kernel ('T' is job control stop on modern 3.x+ kernels) we
// may want to differentiate at some point.
S
tatusTraceStopT
=
'T'
s
tatusTraceStopT
=
'T'
)
//
OS
ProcessDetails contains Linux specific
//
os
ProcessDetails contains Linux specific
// process details.
type
OS
ProcessDetails
struct
{
type
os
ProcessDetails
struct
{
comm
string
}
...
...
@@ -65,7 +65,7 @@ func Launch(cmd []string, wd string, foreground bool, debugInfoDirs []string) (*
foreground
=
false
}
dbp
:=
New
(
0
)
dbp
:=
newProcess
(
0
)
dbp
.
execPtraceFunc
(
func
()
{
process
=
exec
.
Command
(
cmd
[
0
])
process
.
Args
=
cmd
...
...
@@ -101,10 +101,10 @@ func Launch(cmd []string, wd string, foreground bool, debugInfoDirs []string) (*
// the DWARF information cannot be found in the binary, Delve will look
// for external debug files in the directories passed in.
func
Attach
(
pid
int
,
debugInfoDirs
[]
string
)
(
*
proc
.
Target
,
error
)
{
dbp
:=
New
(
pid
)
dbp
:=
newProcess
(
pid
)
var
err
error
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceAttach
(
dbp
.
pid
)
})
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceAttach
(
dbp
.
pid
)
})
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -128,7 +128,7 @@ func Attach(pid int, debugInfoDirs []string) (*proc.Target, error) {
return
tgt
,
nil
}
func
initialize
(
dbp
*
Process
)
error
{
func
initialize
(
dbp
*
native
Process
)
error
{
comm
,
err
:=
ioutil
.
ReadFile
(
fmt
.
Sprintf
(
"/proc/%d/comm"
,
dbp
.
pid
))
if
err
==
nil
{
// removes newline character
...
...
@@ -156,7 +156,7 @@ func initialize(dbp *Process) error {
}
// kill kills the target process.
func
(
dbp
*
Process
)
kill
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
kill
()
(
err
error
)
{
if
dbp
.
exited
{
return
nil
}
...
...
@@ -173,13 +173,13 @@ func (dbp *Process) kill() (err error) {
return
}
func
(
dbp
*
Process
)
requestManualStop
()
(
err
error
)
{
func
(
dbp
*
native
Process
)
requestManualStop
()
(
err
error
)
{
return
sys
.
Kill
(
dbp
.
pid
,
sys
.
SIGTRAP
)
}
// Attach to a newly created thread, and store that thread in our list of
// known threads.
func
(
dbp
*
Process
)
addThread
(
tid
int
,
attach
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
addThread
(
tid
int
,
attach
bool
)
(
*
native
Thread
,
error
)
{
if
thread
,
ok
:=
dbp
.
threads
[
tid
];
ok
{
return
thread
,
nil
}
...
...
@@ -217,10 +217,10 @@ func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) {
}
}
dbp
.
threads
[
tid
]
=
&
Thread
{
dbp
.
threads
[
tid
]
=
&
native
Thread
{
ID
:
tid
,
dbp
:
dbp
,
os
:
new
(
OS
SpecificDetails
),
os
:
new
(
os
SpecificDetails
),
}
if
dbp
.
currentThread
==
nil
{
dbp
.
currentThread
=
dbp
.
threads
[
tid
]
...
...
@@ -228,7 +228,7 @@ func (dbp *Process) addThread(tid int, attach bool) (*Thread, error) {
return
dbp
.
threads
[
tid
],
nil
}
func
(
dbp
*
Process
)
updateThreadList
()
error
{
func
(
dbp
*
native
Process
)
updateThreadList
()
error
{
tids
,
_
:=
filepath
.
Glob
(
fmt
.
Sprintf
(
"/proc/%d/task/*"
,
dbp
.
pid
))
for
_
,
tidpath
:=
range
tids
{
tidstr
:=
filepath
.
Base
(
tidpath
)
...
...
@@ -250,7 +250,7 @@ func findExecutable(path string, pid int) string {
return
path
}
func
(
dbp
*
Process
)
trapWait
(
pid
int
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
trapWait
(
pid
int
)
(
*
native
Thread
,
error
)
{
return
dbp
.
trapWaitInternal
(
pid
,
0
)
}
...
...
@@ -261,7 +261,7 @@ const (
trapWaitNohang
)
func
(
dbp
*
Process
)
trapWaitInternal
(
pid
int
,
options
trapWaitOptions
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
trapWaitInternal
(
pid
int
,
options
trapWaitOptions
)
(
*
native
Thread
,
error
)
{
halt
:=
options
&
trapWaitHalt
!=
0
for
{
wopt
:=
0
...
...
@@ -280,7 +280,7 @@ func (dbp *Process) trapWaitInternal(pid int, options trapWaitOptions) (*Thread,
}
th
,
ok
:=
dbp
.
threads
[
wpid
]
if
ok
{
th
.
Status
=
(
*
W
aitStatus
)(
status
)
th
.
Status
=
(
*
w
aitStatus
)(
status
)
}
if
status
.
Exited
()
{
if
wpid
==
dbp
.
pid
{
...
...
@@ -387,13 +387,13 @@ func status(pid int, comm string) rune {
}
// waitFast is like wait but does not handle process-exit correctly
func
(
dbp
*
Process
)
waitFast
(
pid
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
func
(
dbp
*
native
Process
)
waitFast
(
pid
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
var
s
sys
.
WaitStatus
wpid
,
err
:=
sys
.
Wait4
(
pid
,
&
s
,
sys
.
WALL
,
nil
)
return
wpid
,
&
s
,
err
}
func
(
dbp
*
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
func
(
dbp
*
native
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
var
s
sys
.
WaitStatus
if
(
pid
!=
dbp
.
pid
)
||
(
options
!=
0
)
{
wpid
,
err
:=
sys
.
Wait4
(
pid
,
&
s
,
sys
.
WALL
|
options
,
nil
)
...
...
@@ -418,18 +418,18 @@ func (dbp *Process) wait(pid, options int) (int, *sys.WaitStatus, error) {
if
wpid
!=
0
{
return
wpid
,
&
s
,
err
}
if
status
(
pid
,
dbp
.
os
.
comm
)
==
S
tatusZombie
{
if
status
(
pid
,
dbp
.
os
.
comm
)
==
s
tatusZombie
{
return
pid
,
nil
,
nil
}
time
.
Sleep
(
200
*
time
.
Millisecond
)
}
}
func
(
dbp
*
Process
)
exitGuard
(
err
error
)
error
{
func
(
dbp
*
native
Process
)
exitGuard
(
err
error
)
error
{
if
err
!=
sys
.
ESRCH
{
return
err
}
if
status
(
dbp
.
pid
,
dbp
.
os
.
comm
)
==
S
tatusZombie
{
if
status
(
dbp
.
pid
,
dbp
.
os
.
comm
)
==
s
tatusZombie
{
_
,
err
:=
dbp
.
trapWaitInternal
(
-
1
,
0
)
return
err
}
...
...
@@ -437,7 +437,7 @@ func (dbp *Process) exitGuard(err error) error {
return
err
}
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
native
Process
)
resume
()
error
{
// all threads stopped over a breakpoint are made to step over it
for
_
,
thread
:=
range
dbp
.
threads
{
if
thread
.
CurrentBreakpoint
.
Breakpoint
!=
nil
{
...
...
@@ -457,7 +457,7 @@ func (dbp *Process) resume() error {
}
// stop stops all running threads and sets breakpoints
func
(
dbp
*
Process
)
stop
(
trapthread
*
Thread
)
(
err
error
)
{
func
(
dbp
*
nativeProcess
)
stop
(
trapthread
*
native
Thread
)
(
err
error
)
{
if
dbp
.
exited
{
return
&
proc
.
ErrProcessExited
{
Pid
:
dbp
.
Pid
()}
}
...
...
@@ -517,9 +517,9 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
return
nil
}
func
(
dbp
*
Process
)
detach
(
kill
bool
)
error
{
func
(
dbp
*
native
Process
)
detach
(
kill
bool
)
error
{
for
threadID
:=
range
dbp
.
threads
{
err
:=
P
traceDetach
(
threadID
,
0
)
err
:=
p
traceDetach
(
threadID
,
0
)
if
err
!=
nil
{
return
err
}
...
...
@@ -540,7 +540,7 @@ func (dbp *Process) detach(kill bool) error {
// EntryPoint will return the process entry point address, useful for
// debugging PIEs.
func
(
dbp
*
Process
)
EntryPoint
()
(
uint64
,
error
)
{
func
(
dbp
*
native
Process
)
EntryPoint
()
(
uint64
,
error
)
{
auxvbuf
,
err
:=
ioutil
.
ReadFile
(
fmt
.
Sprintf
(
"/proc/%d/auxv"
,
dbp
.
pid
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"could not read auxiliary vector: %v"
,
err
)
...
...
pkg/proc/native/proc_windows.go
浏览文件 @
3c8d4d52
...
...
@@ -15,8 +15,8 @@ import (
"github.com/go-delve/delve/pkg/proc"
)
//
OS
ProcessDetails holds Windows specific information.
type
OS
ProcessDetails
struct
{
//
os
ProcessDetails holds Windows specific information.
type
os
ProcessDetails
struct
{
hProcess
syscall
.
Handle
breakThread
int
entryPoint
uint64
...
...
@@ -58,7 +58,7 @@ func Launch(cmd []string, wd string, foreground bool, _ []string) (*proc.Target,
env
:=
proc
.
DisableAsyncPreemptEnv
()
var
p
*
os
.
Process
dbp
:=
New
(
0
)
dbp
:=
newProcess
(
0
)
dbp
.
execPtraceFunc
(
func
()
{
attr
:=
&
os
.
ProcAttr
{
Dir
:
wd
,
...
...
@@ -86,7 +86,7 @@ func Launch(cmd []string, wd string, foreground bool, _ []string) (*proc.Target,
return
tgt
,
nil
}
func
initialize
(
dbp
*
Process
)
error
{
func
initialize
(
dbp
*
native
Process
)
error
{
// It should not actually be possible for the
// call to waitForDebugEvent to fail, since Windows
// will always fire a CREATE_PROCESS_DEBUG_EVENT event
...
...
@@ -155,7 +155,7 @@ func findExePath(pid int) (string, error) {
// Attach to an existing process with the given PID.
func
Attach
(
pid
int
,
_
[]
string
)
(
*
proc
.
Target
,
error
)
{
dbp
:=
New
(
pid
)
dbp
:=
newProcess
(
pid
)
var
err
error
dbp
.
execPtraceFunc
(
func
()
{
// TODO: Probably should have SeDebugPrivilege before starting here.
...
...
@@ -177,7 +177,7 @@ func Attach(pid int, _ []string) (*proc.Target, error) {
}
// kill kills the process.
func
(
dbp
*
Process
)
kill
()
error
{
func
(
dbp
*
native
Process
)
kill
()
error
{
if
dbp
.
exited
{
return
nil
}
...
...
@@ -203,24 +203,24 @@ func (dbp *Process) kill() error {
return
nil
}
func
(
dbp
*
Process
)
requestManualStop
()
error
{
func
(
dbp
*
native
Process
)
requestManualStop
()
error
{
return
_DebugBreakProcess
(
dbp
.
os
.
hProcess
)
}
func
(
dbp
*
Process
)
updateThreadList
()
error
{
func
(
dbp
*
native
Process
)
updateThreadList
()
error
{
// We ignore this request since threads are being
// tracked as they are created/killed in waitForDebugEvent.
return
nil
}
func
(
dbp
*
Process
)
addThread
(
hThread
syscall
.
Handle
,
threadID
int
,
attach
,
suspendNewThreads
bool
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
addThread
(
hThread
syscall
.
Handle
,
threadID
int
,
attach
,
suspendNewThreads
bool
)
(
*
native
Thread
,
error
)
{
if
thread
,
ok
:=
dbp
.
threads
[
threadID
];
ok
{
return
thread
,
nil
}
thread
:=
&
Thread
{
thread
:=
&
native
Thread
{
ID
:
threadID
,
dbp
:
dbp
,
os
:
new
(
OS
SpecificDetails
),
os
:
new
(
os
SpecificDetails
),
}
thread
.
os
.
hThread
=
hThread
dbp
.
threads
[
threadID
]
=
thread
...
...
@@ -250,7 +250,7 @@ const (
const
_MS_VC_EXCEPTION
=
0x406D1388
// part of VisualC protocol to set thread names
func
(
dbp
*
Process
)
waitForDebugEvent
(
flags
waitForDebugEventFlags
)
(
threadID
,
exitCode
int
,
err
error
)
{
func
(
dbp
*
native
Process
)
waitForDebugEvent
(
flags
waitForDebugEventFlags
)
(
threadID
,
exitCode
int
,
err
error
)
{
var
debugEvent
_DEBUG_EVENT
shouldExit
:=
false
for
{
...
...
@@ -378,7 +378,7 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e
}
}
func
(
dbp
*
Process
)
trapWait
(
pid
int
)
(
*
Thread
,
error
)
{
func
(
dbp
*
nativeProcess
)
trapWait
(
pid
int
)
(
*
native
Thread
,
error
)
{
var
err
error
var
tid
,
exitCode
int
dbp
.
execPtraceFunc
(
func
()
{
...
...
@@ -395,15 +395,15 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
return
th
,
nil
}
func
(
dbp
*
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
func
(
dbp
*
native
Process
)
wait
(
pid
,
options
int
)
(
int
,
*
sys
.
WaitStatus
,
error
)
{
return
0
,
nil
,
fmt
.
Errorf
(
"not implemented: wait"
)
}
func
(
dbp
*
Process
)
exitGuard
(
err
error
)
error
{
func
(
dbp
*
native
Process
)
exitGuard
(
err
error
)
error
{
return
err
}
func
(
dbp
*
Process
)
resume
()
error
{
func
(
dbp
*
native
Process
)
resume
()
error
{
for
_
,
thread
:=
range
dbp
.
threads
{
if
thread
.
CurrentBreakpoint
.
Breakpoint
!=
nil
{
if
err
:=
thread
.
StepInstruction
();
err
!=
nil
{
...
...
@@ -424,7 +424,7 @@ func (dbp *Process) resume() error {
}
// stop stops all running threads threads and sets breakpoints
func
(
dbp
*
Process
)
stop
(
trapthread
*
Thread
)
(
err
error
)
{
func
(
dbp
*
nativeProcess
)
stop
(
trapthread
*
native
Thread
)
(
err
error
)
{
if
dbp
.
exited
{
return
&
proc
.
ErrProcessExited
{
Pid
:
dbp
.
Pid
()}
}
...
...
@@ -475,7 +475,7 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
return
nil
}
func
(
dbp
*
Process
)
detach
(
kill
bool
)
error
{
func
(
dbp
*
native
Process
)
detach
(
kill
bool
)
error
{
if
!
kill
{
//TODO(aarzilli): when debug.Target exist Detach should be moved to
// debug.Target and the call to RestoreAsyncPreempt should be moved there.
...
...
@@ -489,7 +489,7 @@ func (dbp *Process) detach(kill bool) error {
return
_DebugActiveProcessStop
(
uint32
(
dbp
.
pid
))
}
func
(
dbp
*
Process
)
EntryPoint
()
(
uint64
,
error
)
{
func
(
dbp
*
native
Process
)
EntryPoint
()
(
uint64
,
error
)
{
return
dbp
.
os
.
entryPoint
,
nil
}
...
...
pkg/proc/native/ptrace_darwin.go
浏览文件 @
3c8d4d52
...
...
@@ -4,23 +4,23 @@ package native
import
sys
"golang.org/x/sys/unix"
//
P
traceAttach executes the sys.PtraceAttach call.
func
P
traceAttach
(
pid
int
)
error
{
//
p
traceAttach executes the sys.PtraceAttach call.
func
p
traceAttach
(
pid
int
)
error
{
return
sys
.
PtraceAttach
(
pid
)
}
//
P
traceDetach executes the PT_DETACH ptrace call.
func
P
traceDetach
(
tid
,
sig
int
)
error
{
//
p
traceDetach executes the PT_DETACH ptrace call.
func
p
traceDetach
(
tid
,
sig
int
)
error
{
return
ptrace
(
sys
.
PT_DETACH
,
tid
,
1
,
uintptr
(
sig
))
}
//
P
traceCont executes the PTRACE_CONT ptrace call.
func
P
traceCont
(
tid
,
sig
int
)
error
{
//
p
traceCont executes the PTRACE_CONT ptrace call.
func
p
traceCont
(
tid
,
sig
int
)
error
{
return
ptrace
(
sys
.
PTRACE_CONT
,
tid
,
1
,
0
)
}
//
P
traceSingleStep returns PT_STEP ptrace call.
func
P
traceSingleStep
(
tid
int
)
error
{
//
p
traceSingleStep returns PT_STEP ptrace call.
func
p
traceSingleStep
(
tid
int
)
error
{
return
ptrace
(
sys
.
PT_STEP
,
tid
,
1
,
0
)
}
...
...
pkg/proc/native/ptrace_freebsd.go
浏览文件 @
3c8d4d52
...
...
@@ -17,31 +17,31 @@ import (
"github.com/go-delve/delve/pkg/proc/fbsdutil"
)
//
P
traceAttach executes the sys.PtraceAttach call.
//
p
traceAttach executes the sys.PtraceAttach call.
// pid must be a PID, not a LWPID
func
P
traceAttach
(
pid
int
)
error
{
func
p
traceAttach
(
pid
int
)
error
{
return
sys
.
PtraceAttach
(
pid
)
}
//
P
traceDetach calls ptrace(PTRACE_DETACH).
func
P
traceDetach
(
pid
int
)
error
{
//
p
traceDetach calls ptrace(PTRACE_DETACH).
func
p
traceDetach
(
pid
int
)
error
{
return
sys
.
PtraceDetach
(
pid
)
}
//
P
traceCont executes ptrace PTRACE_CONT
//
p
traceCont executes ptrace PTRACE_CONT
// id may be a PID or an LWPID
func
P
traceCont
(
id
,
sig
int
)
error
{
func
p
traceCont
(
id
,
sig
int
)
error
{
return
sys
.
PtraceCont
(
id
,
sig
)
}
//
P
traceSingleStep executes ptrace PTRACE_SINGLE_STEP.
//
p
traceSingleStep executes ptrace PTRACE_SINGLE_STEP.
// id may be a PID or an LWPID
func
P
traceSingleStep
(
id
int
)
error
{
func
p
traceSingleStep
(
id
int
)
error
{
return
sys
.
PtraceSingleStep
(
id
)
}
// Get a list of the thread ids of a process
func
P
traceGetLwpList
(
pid
int
)
(
tids
[]
int32
)
{
func
p
traceGetLwpList
(
pid
int
)
(
tids
[]
int32
)
{
num_lwps
,
_
:=
C
.
ptrace_get_num_lwps
(
C
.
int
(
pid
))
tids
=
make
([]
int32
,
num_lwps
)
n
,
_
:=
C
.
ptrace_get_lwp_list
(
C
.
int
(
pid
),
(
*
C
.
int
)(
unsafe
.
Pointer
(
&
tids
[
0
])),
C
.
size_t
(
num_lwps
))
...
...
@@ -54,7 +54,7 @@ func ptraceGetLwpInfo(wpid int) (info sys.PtraceLwpInfoStruct, err error) {
return
info
,
err
}
func
P
traceGetRegset
(
id
int
)
(
regset
fbsdutil
.
AMD64Xstate
,
err
error
)
{
func
p
traceGetRegset
(
id
int
)
(
regset
fbsdutil
.
AMD64Xstate
,
err
error
)
{
_
,
_
,
err
=
syscall
.
Syscall6
(
syscall
.
SYS_PTRACE
,
sys
.
PTRACE_GETFPREGS
,
uintptr
(
id
),
uintptr
(
unsafe
.
Pointer
(
&
regset
.
AMD64PtraceFpRegs
)),
0
,
0
,
0
)
if
err
==
syscall
.
Errno
(
0
)
||
err
==
syscall
.
ENODEV
{
var
xsave_len
C
.
size_t
...
...
pkg/proc/native/ptrace_linux.go
浏览文件 @
3c8d4d52
...
...
@@ -2,18 +2,17 @@ package native
import
(
"syscall"
"unsafe"
sys
"golang.org/x/sys/unix"
)
//
P
traceAttach executes the sys.PtraceAttach call.
func
P
traceAttach
(
pid
int
)
error
{
//
p
traceAttach executes the sys.PtraceAttach call.
func
p
traceAttach
(
pid
int
)
error
{
return
sys
.
PtraceAttach
(
pid
)
}
//
P
traceDetach calls ptrace(PTRACE_DETACH).
func
P
traceDetach
(
tid
,
sig
int
)
error
{
//
p
traceDetach calls ptrace(PTRACE_DETACH).
func
p
traceDetach
(
tid
,
sig
int
)
error
{
_
,
_
,
err
:=
sys
.
Syscall6
(
sys
.
SYS_PTRACE
,
sys
.
PTRACE_DETACH
,
uintptr
(
tid
),
1
,
uintptr
(
sig
),
0
,
0
)
if
err
!=
syscall
.
Errno
(
0
)
{
return
err
...
...
@@ -21,31 +20,7 @@ func PtraceDetach(tid, sig int) error {
return
nil
}
//
P
traceCont executes ptrace PTRACE_CONT
func
P
traceCont
(
tid
,
sig
int
)
error
{
//
p
traceCont executes ptrace PTRACE_CONT
func
p
traceCont
(
tid
,
sig
int
)
error
{
return
sys
.
PtraceCont
(
tid
,
sig
)
}
// PtraceSingleStep executes ptrace PTRACE_SINGLE_STEP.
func
PtraceSingleStep
(
tid
int
)
error
{
return
sys
.
PtraceSingleStep
(
tid
)
}
// PtracePokeUser execute ptrace PTRACE_POKE_USER.
func
PtracePokeUser
(
tid
int
,
off
,
addr
uintptr
)
error
{
_
,
_
,
err
:=
sys
.
Syscall6
(
sys
.
SYS_PTRACE
,
sys
.
PTRACE_POKEUSR
,
uintptr
(
tid
),
uintptr
(
off
),
uintptr
(
addr
),
0
,
0
)
if
err
!=
syscall
.
Errno
(
0
)
{
return
err
}
return
nil
}
// PtracePeekUser execute ptrace PTRACE_PEEK_USER.
func
PtracePeekUser
(
tid
int
,
off
uintptr
)
(
uintptr
,
error
)
{
var
val
uintptr
_
,
_
,
err
:=
syscall
.
Syscall6
(
syscall
.
SYS_PTRACE
,
syscall
.
PTRACE_PEEKUSR
,
uintptr
(
tid
),
uintptr
(
off
),
uintptr
(
unsafe
.
Pointer
(
&
val
)),
0
,
0
)
if
err
!=
syscall
.
Errno
(
0
)
{
return
0
,
err
}
return
val
,
nil
}
pkg/proc/native/ptrace_linux_386.go
浏览文件 @
3c8d4d52
...
...
@@ -12,12 +12,12 @@ import (
"github.com/go-delve/delve/pkg/proc/linutil"
)
//
P
traceGetRegset returns floating point registers of the specified thread
//
p
traceGetRegset returns floating point registers of the specified thread
// using PTRACE.
// See i386_linux_fetch_inferior_registers in gdb/i386-linux-nat.c.html
// and i386_supply_xsave in gdb/i386-tdep.c.html
// and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture
func
P
traceGetRegset
(
tid
int
)
(
regset
linutil
.
I386Xstate
,
err
error
)
{
func
p
traceGetRegset
(
tid
int
)
(
regset
linutil
.
I386Xstate
,
err
error
)
{
_
,
_
,
err
=
syscall
.
Syscall6
(
syscall
.
SYS_PTRACE
,
sys
.
PTRACE_GETFPREGS
,
uintptr
(
tid
),
uintptr
(
0
),
uintptr
(
unsafe
.
Pointer
(
&
regset
.
I386PtraceFpRegs
)),
0
,
0
)
if
err
==
syscall
.
Errno
(
0
)
||
err
==
syscall
.
ENODEV
{
// ignore ENODEV, it just means this CPU doesn't have X87 registers (??)
...
...
@@ -43,7 +43,7 @@ func PtraceGetRegset(tid int) (regset linutil.I386Xstate, err error) {
return
}
//
P
traceGetTls return the addr of tls by PTRACE_GET_THREAD_AREA for specify thread.
//
p
traceGetTls return the addr of tls by PTRACE_GET_THREAD_AREA for specify thread.
// See http://man7.org/linux/man-pages/man2/ptrace.2.html for detail about PTRACE_GET_THREAD_AREA.
// struct user_desc at https://golang.org/src/runtime/sys_linux_386.s
// type UserDesc struct {
...
...
@@ -52,7 +52,7 @@ func PtraceGetRegset(tid int) (regset linutil.I386Xstate, err error) {
// Limit uint32
// Flag uint32
// }
func
P
traceGetTls
(
gs
int32
,
tid
int
)
(
uint32
,
error
)
{
func
p
traceGetTls
(
gs
int32
,
tid
int
)
(
uint32
,
error
)
{
ud
:=
[
4
]
uint32
{}
// Gs usually is 0x33
...
...
@@ -64,8 +64,8 @@ func PtraceGetTls(gs int32, tid int) (uint32, error) {
return
uint32
(
ud
[
1
]),
nil
}
//
P
rocessVmRead calls process_vm_readv
func
P
rocessVmRead
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
//
p
rocessVmRead calls process_vm_readv
func
p
rocessVmRead
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
len_iov
:=
uint32
(
len
(
data
))
local_iov
:=
sys
.
Iovec
{
Base
:
&
data
[
0
],
Len
:
len_iov
}
remote_iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
addr
)),
Len
:
len_iov
}
...
...
@@ -78,8 +78,8 @@ func ProcessVmRead(tid int, addr uintptr, data []byte) (int, error) {
return
int
(
n
),
nil
}
//
P
rocessVmWrite calls process_vm_writev
func
P
rocessVmWrite
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
//
p
rocessVmWrite calls process_vm_writev
func
p
rocessVmWrite
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
len_iov
:=
uint32
(
len
(
data
))
local_iov
:=
sys
.
Iovec
{
Base
:
&
data
[
0
],
Len
:
len_iov
}
remote_iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
addr
)),
Len
:
len_iov
}
...
...
pkg/proc/native/ptrace_linux_64bit.go
浏览文件 @
3c8d4d52
...
...
@@ -9,8 +9,8 @@ import (
sys
"golang.org/x/sys/unix"
)
//
P
rocessVmRead calls process_vm_readv
func
P
rocessVmRead
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
//
p
rocessVmRead calls process_vm_readv
func
p
rocessVmRead
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
len_iov
:=
uint64
(
len
(
data
))
local_iov
:=
sys
.
Iovec
{
Base
:
&
data
[
0
],
Len
:
len_iov
}
remote_iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
addr
)),
Len
:
len_iov
}
...
...
@@ -23,8 +23,8 @@ func ProcessVmRead(tid int, addr uintptr, data []byte) (int, error) {
return
int
(
n
),
nil
}
//
P
rocessVmWrite calls process_vm_writev
func
P
rocessVmWrite
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
//
p
rocessVmWrite calls process_vm_writev
func
p
rocessVmWrite
(
tid
int
,
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
len_iov
:=
uint64
(
len
(
data
))
local_iov
:=
sys
.
Iovec
{
Base
:
&
data
[
0
],
Len
:
len_iov
}
remote_iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
addr
)),
Len
:
len_iov
}
...
...
pkg/proc/native/ptrace_linux_amd64.go
浏览文件 @
3c8d4d52
...
...
@@ -9,12 +9,12 @@ import (
"github.com/go-delve/delve/pkg/proc/linutil"
)
//
P
traceGetRegset returns floating point registers of the specified thread
//
p
traceGetRegset returns floating point registers of the specified thread
// using PTRACE.
// See amd64_linux_fetch_inferior_registers in gdb/amd64-linux-nat.c.html
// and amd64_supply_xsave in gdb/amd64-tdep.c.html
// and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture
func
P
traceGetRegset
(
tid
int
)
(
regset
linutil
.
AMD64Xstate
,
err
error
)
{
func
p
traceGetRegset
(
tid
int
)
(
regset
linutil
.
AMD64Xstate
,
err
error
)
{
_
,
_
,
err
=
syscall
.
Syscall6
(
syscall
.
SYS_PTRACE
,
sys
.
PTRACE_GETFPREGS
,
uintptr
(
tid
),
uintptr
(
0
),
uintptr
(
unsafe
.
Pointer
(
&
regset
.
AMD64PtraceFpRegs
)),
0
,
0
)
if
err
==
syscall
.
Errno
(
0
)
||
err
==
syscall
.
ENODEV
{
// ignore ENODEV, it just means this CPU doesn't have X87 registers (??)
...
...
@@ -38,4 +38,4 @@ func PtraceGetRegset(tid int) (regset linutil.AMD64Xstate, err error) {
regset
.
Xsave
=
xstateargs
[
:
iov
.
Len
]
err
=
linutil
.
AMD64XstateRead
(
regset
.
Xsave
,
false
,
&
regset
)
return
}
\ No newline at end of file
}
pkg/proc/native/register_linux_386.go
浏览文件 @
3c8d4d52
...
...
@@ -10,7 +10,7 @@ import (
)
// SetPC sets EIP to the value specified by 'pc'.
func
(
thread
*
Thread
)
SetPC
(
pc
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetPC
(
pc
uint64
)
error
{
ir
,
err
:=
registers
(
thread
,
false
)
if
err
!=
nil
{
return
err
...
...
@@ -22,7 +22,7 @@ func (thread *Thread) SetPC(pc uint64) error {
}
// SetSP sets ESP to the value specified by 'sp'
func
(
thread
*
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
var
ir
proc
.
Registers
ir
,
err
=
registers
(
thread
,
false
)
if
err
!=
nil
{
...
...
@@ -34,7 +34,7 @@ func (thread *Thread) SetSP(sp uint64) (err error) {
return
}
func
(
thread
*
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
var
ir
proc
.
Registers
ir
,
err
=
registers
(
thread
,
false
)
if
err
!=
nil
{
...
...
@@ -46,7 +46,7 @@ func (thread *Thread) SetDX(dx uint64) (err error) {
return
}
func
registers
(
thread
*
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
registers
(
thread
*
native
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
var
(
regs
linutil
.
I386PtraceRegs
err
error
...
...
@@ -65,7 +65,7 @@ func registers(thread *Thread, floatingPoint bool) (proc.Registers, error) {
}
}
thread
.
dbp
.
execPtraceFunc
(
func
()
{
tls
,
_
:=
P
traceGetTls
(
regs
.
Xgs
,
thread
.
ThreadID
())
tls
,
_
:=
p
traceGetTls
(
regs
.
Xgs
,
thread
.
ThreadID
())
r
.
Tls
=
uint64
(
tls
)
})
return
r
,
nil
...
...
@@ -81,8 +81,8 @@ const (
_XSAVE_SSE_REGION_LEN
=
416
)
func
(
thread
*
Thread
)
fpRegisters
()
(
regs
[]
proc
.
Register
,
fpregs
linutil
.
I386Xstate
,
err
error
)
{
thread
.
dbp
.
execPtraceFunc
(
func
()
{
fpregs
,
err
=
P
traceGetRegset
(
thread
.
ID
)
})
func
(
thread
*
native
Thread
)
fpRegisters
()
(
regs
[]
proc
.
Register
,
fpregs
linutil
.
I386Xstate
,
err
error
)
{
thread
.
dbp
.
execPtraceFunc
(
func
()
{
fpregs
,
err
=
p
traceGetRegset
(
thread
.
ID
)
})
regs
=
fpregs
.
Decode
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"could not get floating point registers: %v"
,
err
.
Error
())
...
...
pkg/proc/native/registers_darwin_amd64.go
浏览文件 @
3c8d4d52
...
...
@@ -111,7 +111,7 @@ func (r *Regs) GAddr() (uint64, bool) {
}
// SetPC sets the RIP register to the value specified by `pc`.
func
(
thread
*
Thread
)
SetPC
(
pc
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetPC
(
pc
uint64
)
error
{
kret
:=
C
.
set_pc
(
thread
.
os
.
threadAct
,
C
.
uint64_t
(
pc
))
if
kret
!=
C
.
KERN_SUCCESS
{
return
fmt
.
Errorf
(
"could not set pc"
)
...
...
@@ -120,11 +120,11 @@ func (thread *Thread) SetPC(pc uint64) error {
}
// SetSP sets the RSP register to the value specified by `pc`.
func
(
thread
*
Thread
)
SetSP
(
sp
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetSP
(
sp
uint64
)
error
{
return
errors
.
New
(
"not implemented"
)
}
func
(
thread
*
Thread
)
SetDX
(
dx
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetDX
(
dx
uint64
)
error
{
return
errors
.
New
(
"not implemented"
)
}
...
...
@@ -285,7 +285,7 @@ func (r *Regs) Get(n int) (uint64, error) {
return
0
,
proc
.
ErrUnknownRegister
}
func
registers
(
thread
*
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
registers
(
thread
*
native
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
var
state
C
.
x86_thread_state64_t
var
identity
C
.
thread_identifier_info_data_t
kret
:=
C
.
get_registers
(
C
.
mach_port_name_t
(
thread
.
os
.
threadAct
),
&
state
)
...
...
pkg/proc/native/registers_freebsd_amd64.go
浏览文件 @
3c8d4d52
...
...
@@ -10,7 +10,7 @@ import (
)
// SetPC sets RIP to the value specified by 'pc'.
func
(
thread
*
Thread
)
SetPC
(
pc
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetPC
(
pc
uint64
)
error
{
ir
,
err
:=
registers
(
thread
,
false
)
if
err
!=
nil
{
return
err
...
...
@@ -22,7 +22,7 @@ func (thread *Thread) SetPC(pc uint64) error {
}
// SetSP sets RSP to the value specified by 'sp'
func
(
thread
*
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
var
ir
proc
.
Registers
ir
,
err
=
registers
(
thread
,
false
)
if
err
!=
nil
{
...
...
@@ -34,7 +34,7 @@ func (thread *Thread) SetSP(sp uint64) (err error) {
return
}
func
(
thread
*
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
var
ir
proc
.
Registers
ir
,
err
=
registers
(
thread
,
false
)
if
err
!=
nil
{
...
...
@@ -46,7 +46,7 @@ func (thread *Thread) SetDX(dx uint64) (err error) {
return
}
func
registers
(
thread
*
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
registers
(
thread
*
native
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
var
(
regs
fbsdutil
.
AMD64PtraceRegs
err
error
...
...
@@ -82,8 +82,8 @@ const (
_XSAVE_SSE_REGION_LEN
=
416
)
func
(
thread
*
Thread
)
fpRegisters
()
(
regs
[]
proc
.
Register
,
fpregs
fbsdutil
.
AMD64Xstate
,
err
error
)
{
thread
.
dbp
.
execPtraceFunc
(
func
()
{
fpregs
,
err
=
P
traceGetRegset
(
thread
.
ID
)
})
func
(
thread
*
native
Thread
)
fpRegisters
()
(
regs
[]
proc
.
Register
,
fpregs
fbsdutil
.
AMD64Xstate
,
err
error
)
{
thread
.
dbp
.
execPtraceFunc
(
func
()
{
fpregs
,
err
=
p
traceGetRegset
(
thread
.
ID
)
})
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"could not get floating point registers: %v"
,
err
.
Error
())
}
...
...
pkg/proc/native/registers_linux_amd64.go
浏览文件 @
3c8d4d52
...
...
@@ -10,7 +10,7 @@ import (
)
// SetPC sets RIP to the value specified by 'pc'.
func
(
thread
*
Thread
)
SetPC
(
pc
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetPC
(
pc
uint64
)
error
{
ir
,
err
:=
registers
(
thread
,
false
)
if
err
!=
nil
{
return
err
...
...
@@ -22,7 +22,7 @@ func (thread *Thread) SetPC(pc uint64) error {
}
// SetSP sets RSP to the value specified by 'sp'
func
(
thread
*
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
var
ir
proc
.
Registers
ir
,
err
=
registers
(
thread
,
false
)
if
err
!=
nil
{
...
...
@@ -34,7 +34,7 @@ func (thread *Thread) SetSP(sp uint64) (err error) {
return
}
func
(
thread
*
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
var
ir
proc
.
Registers
ir
,
err
=
registers
(
thread
,
false
)
if
err
!=
nil
{
...
...
@@ -46,7 +46,7 @@ func (thread *Thread) SetDX(dx uint64) (err error) {
return
}
func
registers
(
thread
*
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
registers
(
thread
*
native
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
var
(
regs
linutil
.
AMD64PtraceRegs
err
error
...
...
@@ -77,8 +77,8 @@ const (
_XSAVE_SSE_REGION_LEN
=
416
)
func
(
thread
*
Thread
)
fpRegisters
()
(
regs
[]
proc
.
Register
,
fpregs
linutil
.
AMD64Xstate
,
err
error
)
{
thread
.
dbp
.
execPtraceFunc
(
func
()
{
fpregs
,
err
=
P
traceGetRegset
(
thread
.
ID
)
})
func
(
thread
*
native
Thread
)
fpRegisters
()
(
regs
[]
proc
.
Register
,
fpregs
linutil
.
AMD64Xstate
,
err
error
)
{
thread
.
dbp
.
execPtraceFunc
(
func
()
{
fpregs
,
err
=
p
traceGetRegset
(
thread
.
ID
)
})
regs
=
fpregs
.
Decode
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"could not get floating point registers: %v"
,
err
.
Error
())
...
...
pkg/proc/native/registers_linux_arm64.go
浏览文件 @
3c8d4d52
...
...
@@ -13,12 +13,12 @@ import (
)
const
(
AARCH64_GREGS_SIZE
=
34
*
8
AARCH64_FPREGS_SIZE
=
32
*
16
+
8
_
AARCH64_GREGS_SIZE
=
34
*
8
_
AARCH64_FPREGS_SIZE
=
32
*
16
+
8
)
func
ptraceGetGRegs
(
pid
int
,
regs
*
linutil
.
ARM64PtraceRegs
)
(
err
error
)
{
iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
regs
)),
Len
:
AARCH64_GREGS_SIZE
}
iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
regs
)),
Len
:
_
AARCH64_GREGS_SIZE
}
_
,
_
,
err
=
syscall
.
Syscall6
(
syscall
.
SYS_PTRACE
,
sys
.
PTRACE_GETREGSET
,
uintptr
(
pid
),
uintptr
(
elf
.
NT_PRSTATUS
),
uintptr
(
unsafe
.
Pointer
(
&
iov
)),
0
,
0
)
if
err
==
syscall
.
Errno
(
0
)
{
err
=
nil
...
...
@@ -27,7 +27,7 @@ func ptraceGetGRegs(pid int, regs *linutil.ARM64PtraceRegs) (err error) {
}
func
ptraceSetGRegs
(
pid
int
,
regs
*
linutil
.
ARM64PtraceRegs
)
(
err
error
)
{
iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
regs
)),
Len
:
AARCH64_GREGS_SIZE
}
iov
:=
sys
.
Iovec
{
Base
:
(
*
byte
)(
unsafe
.
Pointer
(
regs
)),
Len
:
_
AARCH64_GREGS_SIZE
}
_
,
_
,
err
=
syscall
.
Syscall6
(
syscall
.
SYS_PTRACE
,
sys
.
PTRACE_SETREGSET
,
uintptr
(
pid
),
uintptr
(
elf
.
NT_PRSTATUS
),
uintptr
(
unsafe
.
Pointer
(
&
iov
)),
0
,
0
)
if
err
==
syscall
.
Errno
(
0
)
{
err
=
nil
...
...
@@ -35,11 +35,11 @@ func ptraceSetGRegs(pid int, regs *linutil.ARM64PtraceRegs) (err error) {
return
}
//
P
traceGetFpRegset returns floating point registers of the specified thread
//
p
traceGetFpRegset returns floating point registers of the specified thread
// using PTRACE.
func
P
traceGetFpRegset
(
tid
int
)
(
fpregset
[]
byte
,
err
error
)
{
var
arm64_fpregs
[
AARCH64_FPREGS_SIZE
]
byte
iov
:=
sys
.
Iovec
{
Base
:
&
arm64_fpregs
[
0
],
Len
:
AARCH64_FPREGS_SIZE
}
func
p
traceGetFpRegset
(
tid
int
)
(
fpregset
[]
byte
,
err
error
)
{
var
arm64_fpregs
[
_
AARCH64_FPREGS_SIZE
]
byte
iov
:=
sys
.
Iovec
{
Base
:
&
arm64_fpregs
[
0
],
Len
:
_
AARCH64_FPREGS_SIZE
}
_
,
_
,
err
=
syscall
.
Syscall6
(
syscall
.
SYS_PTRACE
,
sys
.
PTRACE_GETREGSET
,
uintptr
(
tid
),
uintptr
(
elf
.
NT_FPREGSET
),
uintptr
(
unsafe
.
Pointer
(
&
iov
)),
0
,
0
)
if
err
!=
syscall
.
Errno
(
0
)
{
if
err
==
syscall
.
ENODEV
{
...
...
@@ -55,7 +55,7 @@ func PtraceGetFpRegset(tid int) (fpregset []byte, err error) {
}
// SetPC sets PC to the value specified by 'pc'.
func
(
thread
*
Thread
)
SetPC
(
pc
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetPC
(
pc
uint64
)
error
{
ir
,
err
:=
registers
(
thread
,
false
)
if
err
!=
nil
{
return
err
...
...
@@ -67,7 +67,7 @@ func (thread *Thread) SetPC(pc uint64) error {
}
// SetSP sets RSP to the value specified by 'sp'
func
(
thread
*
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetSP
(
sp
uint64
)
(
err
error
)
{
var
ir
proc
.
Registers
ir
,
err
=
registers
(
thread
,
false
)
if
err
!=
nil
{
...
...
@@ -79,11 +79,11 @@ func (thread *Thread) SetSP(sp uint64) (err error) {
return
}
func
(
thread
*
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
func
(
thread
*
native
Thread
)
SetDX
(
dx
uint64
)
(
err
error
)
{
return
fmt
.
Errorf
(
"not supported"
)
}
func
registers
(
thread
*
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
registers
(
thread
*
native
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
var
(
regs
linutil
.
ARM64PtraceRegs
err
error
...
...
pkg/proc/native/registers_windows_amd64.go
浏览文件 @
3c8d4d52
...
...
@@ -9,7 +9,7 @@ import (
)
// SetPC sets the RIP register to the value specified by `pc`.
func
(
thread
*
Thread
)
SetPC
(
pc
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetPC
(
pc
uint64
)
error
{
context
:=
winutil
.
NewCONTEXT
()
context
.
ContextFlags
=
_CONTEXT_ALL
...
...
@@ -24,7 +24,7 @@ func (thread *Thread) SetPC(pc uint64) error {
}
// SetSP sets the RSP register to the value specified by `sp`.
func
(
thread
*
Thread
)
SetSP
(
sp
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetSP
(
sp
uint64
)
error
{
context
:=
winutil
.
NewCONTEXT
()
context
.
ContextFlags
=
_CONTEXT_ALL
...
...
@@ -38,7 +38,7 @@ func (thread *Thread) SetSP(sp uint64) error {
return
_SetThreadContext
(
thread
.
os
.
hThread
,
context
)
}
func
(
thread
*
Thread
)
SetDX
(
dx
uint64
)
error
{
func
(
thread
*
native
Thread
)
SetDX
(
dx
uint64
)
error
{
context
:=
winutil
.
NewCONTEXT
()
context
.
ContextFlags
=
_CONTEXT_ALL
...
...
@@ -52,7 +52,7 @@ func (thread *Thread) SetDX(dx uint64) error {
return
_SetThreadContext
(
thread
.
os
.
hThread
,
context
)
}
func
registers
(
thread
*
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
registers
(
thread
*
native
Thread
,
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
context
:=
winutil
.
NewCONTEXT
()
context
.
ContextFlags
=
_CONTEXT_ALL
...
...
pkg/proc/native/threads.go
浏览文件 @
3c8d4d52
...
...
@@ -11,14 +11,14 @@ import (
// Process struct that contains info on the process as
// a whole, and Status represents the last result of a `wait` call
// on this thread.
type
Thread
struct
{
type
native
Thread
struct
{
ID
int
// Thread ID or mach port
Status
*
W
aitStatus
// Status returned from last wait call
Status
*
w
aitStatus
// Status returned from last wait call
CurrentBreakpoint
proc
.
BreakpointState
// Breakpoint thread is currently stopped at
dbp
*
Process
dbp
*
native
Process
singleStepping
bool
os
*
OS
SpecificDetails
os
*
os
SpecificDetails
common
proc
.
CommonThread
}
...
...
@@ -27,7 +27,7 @@ type Thread struct {
// If we are currently at a breakpoint, we'll clear it
// first and then resume execution. Thread will continue until
// it hits a breakpoint or is signaled.
func
(
t
*
Thread
)
Continue
()
error
{
func
(
t
*
native
Thread
)
Continue
()
error
{
pc
,
err
:=
t
.
PC
()
if
err
!=
nil
{
return
err
...
...
@@ -48,7 +48,7 @@ func (t *Thread) Continue() error {
// If the thread is at a breakpoint, we first clear it,
// execute the instruction, and then replace the breakpoint.
// Otherwise we simply execute the next instruction.
func
(
t
*
Thread
)
StepInstruction
()
(
err
error
)
{
func
(
t
*
native
Thread
)
StepInstruction
()
(
err
error
)
{
t
.
singleStepping
=
true
defer
func
()
{
t
.
singleStepping
=
false
...
...
@@ -85,7 +85,7 @@ func (t *Thread) StepInstruction() (err error) {
// Location returns the threads location, including the file:line
// of the corresponding source code, the function we're in
// and the current instruction address.
func
(
t
*
Thread
)
Location
()
(
*
proc
.
Location
,
error
)
{
func
(
t
*
native
Thread
)
Location
()
(
*
proc
.
Location
,
error
)
{
pc
,
err
:=
t
.
PC
()
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -95,19 +95,19 @@ func (t *Thread) Location() (*proc.Location, error) {
}
// BinInfo returns information on the binary.
func
(
t
*
Thread
)
BinInfo
()
*
proc
.
BinaryInfo
{
func
(
t
*
native
Thread
)
BinInfo
()
*
proc
.
BinaryInfo
{
return
t
.
dbp
.
bi
}
// Common returns information common across Process
// implementations.
func
(
t
*
Thread
)
Common
()
*
proc
.
CommonThread
{
func
(
t
*
native
Thread
)
Common
()
*
proc
.
CommonThread
{
return
&
t
.
common
}
// SetCurrentBreakpoint sets the current breakpoint that this
// thread is stopped at as CurrentBreakpoint on the thread struct.
func
(
t
*
Thread
)
SetCurrentBreakpoint
(
adjustPC
bool
)
error
{
func
(
t
*
native
Thread
)
SetCurrentBreakpoint
(
adjustPC
bool
)
error
{
t
.
CurrentBreakpoint
.
Clear
()
pc
,
err
:=
t
.
PC
()
if
err
!=
nil
{
...
...
@@ -139,17 +139,17 @@ func (t *Thread) SetCurrentBreakpoint(adjustPC bool) error {
// Breakpoint returns the current breakpoint that is active
// on this thread.
func
(
t
*
Thread
)
Breakpoint
()
*
proc
.
BreakpointState
{
func
(
t
*
native
Thread
)
Breakpoint
()
*
proc
.
BreakpointState
{
return
&
t
.
CurrentBreakpoint
}
// ThreadID returns the ID of this thread.
func
(
t
*
Thread
)
ThreadID
()
int
{
func
(
t
*
native
Thread
)
ThreadID
()
int
{
return
t
.
ID
}
// ClearBreakpoint clears the specified breakpoint.
func
(
t
*
Thread
)
ClearBreakpoint
(
bp
*
proc
.
Breakpoint
)
error
{
func
(
t
*
native
Thread
)
ClearBreakpoint
(
bp
*
proc
.
Breakpoint
)
error
{
if
_
,
err
:=
t
.
WriteMemory
(
uintptr
(
bp
.
Addr
),
bp
.
OriginalData
);
err
!=
nil
{
return
fmt
.
Errorf
(
"could not clear breakpoint %s"
,
err
)
}
...
...
@@ -157,18 +157,18 @@ func (t *Thread) ClearBreakpoint(bp *proc.Breakpoint) error {
}
// Registers obtains register values from the debugged process.
func
(
t
*
Thread
)
Registers
(
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
func
(
t
*
native
Thread
)
Registers
(
floatingPoint
bool
)
(
proc
.
Registers
,
error
)
{
return
registers
(
t
,
floatingPoint
)
}
// RestoreRegisters will set the value of the CPU registers to those
// passed in via 'savedRegs'.
func
(
t
*
Thread
)
RestoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
RestoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
return
t
.
restoreRegisters
(
savedRegs
)
}
// PC returns the current program counter value for this thread.
func
(
t
*
Thread
)
PC
()
(
uint64
,
error
)
{
func
(
t
*
native
Thread
)
PC
()
(
uint64
,
error
)
{
regs
,
err
:=
t
.
Registers
(
false
)
if
err
!=
nil
{
return
0
,
err
...
...
pkg/proc/native/threads_darwin.go
浏览文件 @
3c8d4d52
...
...
@@ -15,12 +15,12 @@ import (
"github.com/go-delve/delve/pkg/proc"
)
//
W
aitStatus is a synonym for the platform-specific WaitStatus
type
W
aitStatus
sys
.
WaitStatus
//
w
aitStatus is a synonym for the platform-specific WaitStatus
type
w
aitStatus
sys
.
WaitStatus
//
OS
SpecificDetails holds information specific to the OSX/Darwin
//
os
SpecificDetails holds information specific to the OSX/Darwin
// operating system / kernel.
type
OS
SpecificDetails
struct
{
type
os
SpecificDetails
struct
{
threadAct
C
.
thread_act_t
registers
C
.
x86_thread_state64_t
exists
bool
...
...
@@ -30,7 +30,7 @@ type OSSpecificDetails struct {
// be continued.
var
ErrContinueThread
=
fmt
.
Errorf
(
"could not continue thread"
)
func
(
t
*
Thread
)
stop
()
(
err
error
)
{
func
(
t
*
native
Thread
)
stop
()
(
err
error
)
{
kret
:=
C
.
thread_suspend
(
t
.
os
.
threadAct
)
if
kret
!=
C
.
KERN_SUCCESS
{
errStr
:=
C
.
GoString
(
C
.
mach_error_string
(
C
.
mach_error_t
(
kret
)))
...
...
@@ -49,7 +49,7 @@ func (t *Thread) stop() (err error) {
return
}
func
(
t
*
Thread
)
singleStep
()
error
{
func
(
t
*
native
Thread
)
singleStep
()
error
{
kret
:=
C
.
single_step
(
t
.
os
.
threadAct
)
if
kret
!=
C
.
KERN_SUCCESS
{
return
fmt
.
Errorf
(
"could not single step"
)
...
...
@@ -71,10 +71,10 @@ func (t *Thread) singleStep() error {
return
nil
}
func
(
t
*
Thread
)
resume
()
error
{
func
(
t
*
native
Thread
)
resume
()
error
{
// TODO(dp) set flag for ptrace stops
var
err
error
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
t
.
dbp
.
pid
,
0
)
})
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
t
.
dbp
.
pid
,
0
)
})
if
err
==
nil
{
return
nil
}
...
...
@@ -85,7 +85,7 @@ func (t *Thread) resume() error {
return
nil
}
func
(
t
*
Thread
)
Blocked
()
bool
{
func
(
t
*
native
Thread
)
Blocked
()
bool
{
// TODO(dp) cache the func pc to remove this lookup
regs
,
err
:=
t
.
Registers
(
false
)
if
err
!=
nil
{
...
...
@@ -106,11 +106,11 @@ func (t *Thread) Blocked() bool {
// Stopped returns whether the thread is stopped at
// the operating system level.
func
(
t
*
Thread
)
Stopped
()
bool
{
func
(
t
*
native
Thread
)
Stopped
()
bool
{
return
C
.
thread_blocked
(
t
.
os
.
threadAct
)
>
C
.
int
(
0
)
}
func
(
t
*
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
func
(
t
*
native
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
...
...
@@ -128,7 +128,7 @@ func (t *Thread) WriteMemory(addr uintptr, data []byte) (int, error) {
return
len
(
data
),
nil
}
func
(
t
*
Thread
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
int
,
error
)
{
func
(
t
*
native
Thread
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
int
,
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
...
...
@@ -148,6 +148,6 @@ func (t *Thread) ReadMemory(buf []byte, addr uintptr) (int, error) {
return
len
(
buf
),
nil
}
func
(
t
*
Thread
)
restoreRegisters
(
sr
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
restoreRegisters
(
sr
proc
.
Registers
)
error
{
return
errors
.
New
(
"not implemented"
)
}
pkg/proc/native/threads_freebsd.go
浏览文件 @
3c8d4d52
...
...
@@ -13,14 +13,14 @@ import (
"github.com/go-delve/delve/pkg/proc"
)
type
W
aitStatus
sys
.
WaitStatus
type
w
aitStatus
sys
.
WaitStatus
//
OS
SpecificDetails hold FreeBSD specific process details.
type
OS
SpecificDetails
struct
{
//
os
SpecificDetails hold FreeBSD specific process details.
type
os
SpecificDetails
struct
{
registers
sys
.
Reg
}
func
(
t
*
Thread
)
stop
()
(
err
error
)
{
func
(
t
*
native
Thread
)
stop
()
(
err
error
)
{
_
,
err
=
C
.
thr_kill2
(
C
.
pid_t
(
t
.
dbp
.
pid
),
C
.
long
(
t
.
ID
),
C
.
int
(
sys
.
SIGSTOP
))
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"stop err %s on thread %d"
,
err
,
t
.
ID
)
...
...
@@ -28,7 +28,7 @@ func (t *Thread) stop() (err error) {
}
// If the process is stopped, we must continue it so it can receive the
// signal
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
t
.
dbp
.
pid
,
0
)
})
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
t
.
dbp
.
pid
,
0
)
})
if
err
!=
nil
{
return
err
}
...
...
@@ -40,22 +40,22 @@ func (t *Thread) stop() (err error) {
return
}
func
(
t
*
Thread
)
Stopped
()
bool
{
func
(
t
*
native
Thread
)
Stopped
()
bool
{
state
:=
status
(
t
.
dbp
.
pid
)
return
state
==
S
tatusStopped
return
state
==
s
tatusStopped
}
func
(
t
*
Thread
)
resume
()
error
{
func
(
t
*
native
Thread
)
resume
()
error
{
return
t
.
resumeWithSig
(
0
)
}
func
(
t
*
Thread
)
resumeWithSig
(
sig
int
)
(
err
error
)
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
t
.
ID
,
sig
)
})
func
(
t
*
native
Thread
)
resumeWithSig
(
sig
int
)
(
err
error
)
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
t
.
ID
,
sig
)
})
return
}
func
(
t
*
Thread
)
singleStep
()
(
err
error
)
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceSingleStep
(
t
.
ID
)
})
func
(
t
*
native
Thread
)
singleStep
()
(
err
error
)
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceSingleStep
(
t
.
ID
)
})
if
err
!=
nil
{
return
err
}
...
...
@@ -67,7 +67,7 @@ func (t *Thread) singleStep() (err error) {
if
th
.
ID
==
t
.
ID
{
break
}
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
th
.
ID
,
0
)
})
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
th
.
ID
,
0
)
})
if
err
!=
nil
{
return
err
}
...
...
@@ -75,7 +75,7 @@ func (t *Thread) singleStep() (err error) {
return
nil
}
func
(
t
*
Thread
)
Blocked
()
bool
{
func
(
t
*
native
Thread
)
Blocked
()
bool
{
loc
,
err
:=
t
.
Location
()
if
err
!=
nil
{
return
false
...
...
@@ -86,7 +86,7 @@ func (t *Thread) Blocked() bool {
return
false
}
func
(
t
*
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
sr
:=
savedRegs
.
(
*
fbsdutil
.
AMD64Registers
)
var
restoreRegistersErr
error
...
...
@@ -110,7 +110,7 @@ func (t *Thread) restoreRegisters(savedRegs proc.Registers) error {
return
restoreRegistersErr
}
func
(
t
*
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
written
int
,
err
error
)
{
func
(
t
*
native
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
written
int
,
err
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
...
...
@@ -121,7 +121,7 @@ func (t *Thread) WriteMemory(addr uintptr, data []byte) (written int, err error)
return
written
,
err
}
func
(
t
*
Thread
)
ReadMemory
(
data
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
func
(
t
*
native
Thread
)
ReadMemory
(
data
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
...
...
pkg/proc/native/threads_linux.go
浏览文件 @
3c8d4d52
...
...
@@ -8,18 +8,18 @@ import (
"github.com/go-delve/delve/pkg/proc"
)
type
W
aitStatus
sys
.
WaitStatus
type
w
aitStatus
sys
.
WaitStatus
//
OS
SpecificDetails hold Linux specific
//
os
SpecificDetails hold Linux specific
// process details.
type
OS
SpecificDetails
struct
{
type
os
SpecificDetails
struct
{
delayedSignal
int
registers
sys
.
PtraceRegs
running
bool
setbp
bool
}
func
(
t
*
Thread
)
stop
()
(
err
error
)
{
func
(
t
*
native
Thread
)
stop
()
(
err
error
)
{
err
=
sys
.
Tgkill
(
t
.
dbp
.
pid
,
t
.
ID
,
sys
.
SIGSTOP
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"stop err %s on thread %d"
,
err
,
t
.
ID
)
...
...
@@ -30,24 +30,24 @@ func (t *Thread) stop() (err error) {
// Stopped returns whether the thread is stopped at
// the operating system level.
func
(
t
*
Thread
)
Stopped
()
bool
{
func
(
t
*
native
Thread
)
Stopped
()
bool
{
state
:=
status
(
t
.
ID
,
t
.
dbp
.
os
.
comm
)
return
state
==
StatusTraceStop
||
state
==
S
tatusTraceStopT
return
state
==
statusTraceStop
||
state
==
s
tatusTraceStopT
}
func
(
t
*
Thread
)
resume
()
error
{
func
(
t
*
native
Thread
)
resume
()
error
{
sig
:=
t
.
os
.
delayedSignal
t
.
os
.
delayedSignal
=
0
return
t
.
resumeWithSig
(
sig
)
}
func
(
t
*
Thread
)
resumeWithSig
(
sig
int
)
(
err
error
)
{
func
(
t
*
native
Thread
)
resumeWithSig
(
sig
int
)
(
err
error
)
{
t
.
os
.
running
=
true
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
P
traceCont
(
t
.
ID
,
sig
)
})
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
p
traceCont
(
t
.
ID
,
sig
)
})
return
}
func
(
t
*
Thread
)
singleStep
()
(
err
error
)
{
func
(
t
*
native
Thread
)
singleStep
()
(
err
error
)
{
for
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
err
=
sys
.
PtraceSingleStep
(
t
.
ID
)
})
if
err
!=
nil
{
...
...
@@ -71,7 +71,7 @@ func (t *Thread) singleStep() (err error) {
}
}
func
(
t
*
Thread
)
Blocked
()
bool
{
func
(
t
*
native
Thread
)
Blocked
()
bool
{
regs
,
err
:=
t
.
Registers
(
false
)
if
err
!=
nil
{
return
false
...
...
@@ -84,7 +84,7 @@ func (t *Thread) Blocked() bool {
return
false
}
func
(
t
*
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
written
int
,
err
error
)
{
func
(
t
*
native
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
written
int
,
err
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
...
...
@@ -94,7 +94,7 @@ func (t *Thread) WriteMemory(addr uintptr, data []byte) (written int, err error)
// ProcessVmWrite can't poke read-only memory like ptrace, so don't
// even bother for small writes -- likely breakpoints and such.
if
len
(
data
)
>
sys
.
SizeofPtr
{
written
,
_
=
P
rocessVmWrite
(
t
.
ID
,
addr
,
data
)
written
,
_
=
p
rocessVmWrite
(
t
.
ID
,
addr
,
data
)
}
if
written
==
0
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
written
,
err
=
sys
.
PtracePokeData
(
t
.
ID
,
addr
,
data
)
})
...
...
@@ -102,14 +102,14 @@ func (t *Thread) WriteMemory(addr uintptr, data []byte) (written int, err error)
return
}
func
(
t
*
Thread
)
ReadMemory
(
data
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
func
(
t
*
native
Thread
)
ReadMemory
(
data
[]
byte
,
addr
uintptr
)
(
n
int
,
err
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
if
len
(
data
)
==
0
{
return
}
n
,
_
=
P
rocessVmRead
(
t
.
ID
,
addr
,
data
)
n
,
_
=
p
rocessVmRead
(
t
.
ID
,
addr
,
data
)
if
n
==
0
{
t
.
dbp
.
execPtraceFunc
(
func
()
{
n
,
err
=
sys
.
PtracePeekData
(
t
.
ID
,
addr
,
data
)
})
}
...
...
pkg/proc/native/threads_linux_386.go
浏览文件 @
3c8d4d52
...
...
@@ -5,6 +5,6 @@ import (
"github.com/go-delve/delve/pkg/proc"
)
func
(
t
*
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
return
fmt
.
Errorf
(
"restore regs not supported on i386"
)
}
pkg/proc/native/threads_linux_amd64.go
浏览文件 @
3c8d4d52
...
...
@@ -10,7 +10,7 @@ import (
"github.com/go-delve/delve/pkg/proc/linutil"
)
func
(
t
*
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
sr
:=
savedRegs
.
(
*
linutil
.
AMD64Registers
)
var
restoreRegistersErr
error
...
...
pkg/proc/native/threads_linux_arm64.go
浏览文件 @
3c8d4d52
...
...
@@ -12,10 +12,10 @@ import (
"github.com/go-delve/delve/pkg/proc/linutil"
)
func
(
thread
*
Thread
)
fpRegisters
()
([]
proc
.
Register
,
[]
byte
,
error
)
{
func
(
thread
*
native
Thread
)
fpRegisters
()
([]
proc
.
Register
,
[]
byte
,
error
)
{
var
err
error
var
arm_fpregs
linutil
.
ARM64PtraceFpRegs
thread
.
dbp
.
execPtraceFunc
(
func
()
{
arm_fpregs
.
Vregs
,
err
=
P
traceGetFpRegset
(
thread
.
ID
)
})
thread
.
dbp
.
execPtraceFunc
(
func
()
{
arm_fpregs
.
Vregs
,
err
=
p
traceGetFpRegset
(
thread
.
ID
)
})
fpregs
:=
arm_fpregs
.
Decode
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"could not get floating point registers: %v"
,
err
.
Error
())
...
...
@@ -23,7 +23,7 @@ func (thread *Thread) fpRegisters() ([]proc.Register, []byte, error) {
return
fpregs
,
arm_fpregs
.
Vregs
,
err
}
func
(
t
*
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
sr
:=
savedRegs
.
(
*
linutil
.
ARM64Registers
)
var
restoreRegistersErr
error
...
...
pkg/proc/native/threads_windows.go
浏览文件 @
3c8d4d52
...
...
@@ -10,16 +10,16 @@ import (
"github.com/go-delve/delve/pkg/proc/winutil"
)
//
W
aitStatus is a synonym for the platform-specific WaitStatus
type
W
aitStatus
sys
.
WaitStatus
//
w
aitStatus is a synonym for the platform-specific WaitStatus
type
w
aitStatus
sys
.
WaitStatus
//
OS
SpecificDetails holds information specific to the Windows
//
os
SpecificDetails holds information specific to the Windows
// operating system / kernel.
type
OS
SpecificDetails
struct
{
type
os
SpecificDetails
struct
{
hThread
syscall
.
Handle
}
func
(
t
*
Thread
)
singleStep
()
error
{
func
(
t
*
native
Thread
)
singleStep
()
error
{
context
:=
winutil
.
NewCONTEXT
()
context
.
ContextFlags
=
_CONTEXT_ALL
...
...
@@ -101,7 +101,7 @@ func (t *Thread) singleStep() error {
return
_SetThreadContext
(
t
.
os
.
hThread
,
context
)
}
func
(
t
*
Thread
)
resume
()
error
{
func
(
t
*
native
Thread
)
resume
()
error
{
var
err
error
t
.
dbp
.
execPtraceFunc
(
func
()
{
//TODO: Note that we are ignoring the thread we were asked to continue and are continuing the
...
...
@@ -111,7 +111,7 @@ func (t *Thread) resume() error {
return
err
}
func
(
t
*
Thread
)
Blocked
()
bool
{
func
(
t
*
native
Thread
)
Blocked
()
bool
{
// TODO: Probably incorrect - what are the runtime functions that
// indicate blocking on Windows?
regs
,
err
:=
t
.
Registers
(
false
)
...
...
@@ -133,11 +133,11 @@ func (t *Thread) Blocked() bool {
// Stopped returns whether the thread is stopped at the operating system
// level. On windows this always returns true.
func
(
t
*
Thread
)
Stopped
()
bool
{
func
(
t
*
native
Thread
)
Stopped
()
bool
{
return
true
}
func
(
t
*
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
func
(
t
*
native
Thread
)
WriteMemory
(
addr
uintptr
,
data
[]
byte
)
(
int
,
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
...
...
@@ -154,7 +154,7 @@ func (t *Thread) WriteMemory(addr uintptr, data []byte) (int, error) {
var
ErrShortRead
=
errors
.
New
(
"short read"
)
func
(
t
*
Thread
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
int
,
error
)
{
func
(
t
*
native
Thread
)
ReadMemory
(
buf
[]
byte
,
addr
uintptr
)
(
int
,
error
)
{
if
t
.
dbp
.
exited
{
return
0
,
proc
.
ErrProcessExited
{
Pid
:
t
.
dbp
.
pid
}
}
...
...
@@ -169,6 +169,6 @@ func (t *Thread) ReadMemory(buf []byte, addr uintptr) (int, error) {
return
int
(
count
),
err
}
func
(
t
*
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
func
(
t
*
native
Thread
)
restoreRegisters
(
savedRegs
proc
.
Registers
)
error
{
return
_SetThreadContext
(
t
.
os
.
hThread
,
savedRegs
.
(
*
winutil
.
AMD64Registers
)
.
Context
)
}
pkg/proc/proc_test.go
浏览文件 @
3c8d4d52
...
...
@@ -239,12 +239,6 @@ func TestHalt(t *testing.T) {
withTestProcess
(
"loopprog"
,
t
,
func
(
p
*
proc
.
Target
,
fixture
protest
.
Fixture
)
{
setFunctionBreakpoint
(
p
,
t
,
"main.loop"
)
assertNoError
(
p
.
Continue
(),
t
,
"Continue"
)
if
p
,
ok
:=
p
.
Process
.
(
*
native
.
Process
);
ok
{
for
_
,
th
:=
range
p
.
ThreadList
()
{
_
,
err
:=
th
.
Registers
(
false
)
assertNoError
(
err
,
t
,
"Registers"
)
}
}
resumeChan
:=
make
(
chan
struct
{},
1
)
go
func
()
{
<-
resumeChan
...
...
@@ -258,21 +252,6 @@ func TestHalt(t *testing.T) {
if
err
,
ok
:=
retVal
.
(
error
);
ok
&&
err
!=
nil
{
t
.
Fatal
()
}
// Loop through threads and make sure they are all
// actually stopped, err will not be nil if the process
// is still running.
if
p
,
ok
:=
p
.
Process
.
(
*
native
.
Process
);
ok
{
for
_
,
th
:=
range
p
.
ThreadList
()
{
if
th
,
ok
:=
th
.
(
*
native
.
Thread
);
ok
{
if
!
th
.
Stopped
()
{
t
.
Fatal
(
"expected thread to be stopped, but was not"
)
}
}
_
,
err
:=
th
.
Registers
(
false
)
assertNoError
(
err
,
t
,
"Registers"
)
}
}
})
}
...
...
pkg/proc/test/support.go
浏览文件 @
3c8d4d52
...
...
@@ -35,13 +35,13 @@ type Fixture struct {
}
// FixtureKey holds the name and builds flags used for a test fixture.
type
F
ixtureKey
struct
{
type
f
ixtureKey
struct
{
Name
string
Flags
BuildFlags
}
// Fixtures is a map of fixtureKey{ Fixture.Name, buildFlags } to Fixture.
var
Fixtures
=
make
(
map
[
F
ixtureKey
]
Fixture
)
var
fixtures
=
make
(
map
[
f
ixtureKey
]
Fixture
)
// PathsToRemove is a list of files and directories to remove after running all the tests
var
PathsToRemove
[]
string
...
...
@@ -84,8 +84,8 @@ func BuildFixture(name string, flags BuildFlags) Fixture {
if
!
runningWithFixtures
{
panic
(
"RunTestsWithFixtures not called"
)
}
fk
:=
F
ixtureKey
{
name
,
flags
}
if
f
,
ok
:=
F
ixtures
[
fk
];
ok
{
fk
:=
f
ixtureKey
{
name
,
flags
}
if
f
,
ok
:=
f
ixtures
[
fk
];
ok
{
return
f
}
...
...
@@ -180,8 +180,8 @@ func BuildFixture(name string, flags BuildFlags) Fixture {
fixture
:=
Fixture
{
Name
:
name
,
Path
:
tmpfile
,
Source
:
source
,
BuildDir
:
absdir
}
F
ixtures
[
fk
]
=
fixture
return
F
ixtures
[
fk
]
f
ixtures
[
fk
]
=
fixture
return
f
ixtures
[
fk
]
}
// RunTestsWithFixtures will pre-compile test fixtures before running test
...
...
@@ -194,7 +194,7 @@ func RunTestsWithFixtures(m *testing.M) int {
status
:=
m
.
Run
()
// Remove the fixtures.
for
_
,
f
:=
range
F
ixtures
{
for
_
,
f
:=
range
f
ixtures
{
os
.
Remove
(
f
.
Path
)
}
...
...
pkg/terminal/command.go
浏览文件 @
3c8d4d52
...
...
@@ -85,23 +85,23 @@ type Commands struct {
}
var
(
//
L
ongLoadConfig loads more information:
//
l
ongLoadConfig loads more information:
// * Follows pointers
// * Loads more array values
// * Does not limit struct fields
L
ongLoadConfig
=
api
.
LoadConfig
{
FollowPointers
:
true
,
MaxVariableRecurse
:
1
,
MaxStringLen
:
64
,
MaxArrayValues
:
64
,
MaxStructFields
:
-
1
}
l
ongLoadConfig
=
api
.
LoadConfig
{
FollowPointers
:
true
,
MaxVariableRecurse
:
1
,
MaxStringLen
:
64
,
MaxArrayValues
:
64
,
MaxStructFields
:
-
1
}
// ShortLoadConfig loads less information, not following pointers
// and limiting struct fields loaded to 3.
ShortLoadConfig
=
api
.
LoadConfig
{
MaxStringLen
:
64
,
MaxStructFields
:
3
}
)
//
B
yFirstAlias will sort by the first
//
b
yFirstAlias will sort by the first
// alias of a command.
type
B
yFirstAlias
[]
command
type
b
yFirstAlias
[]
command
func
(
a
B
yFirstAlias
)
Len
()
int
{
return
len
(
a
)
}
func
(
a
B
yFirstAlias
)
Swap
(
i
,
j
int
)
{
a
[
i
],
a
[
j
]
=
a
[
j
],
a
[
i
]
}
func
(
a
B
yFirstAlias
)
Less
(
i
,
j
int
)
bool
{
return
a
[
i
]
.
aliases
[
0
]
<
a
[
j
]
.
aliases
[
0
]
}
func
(
a
b
yFirstAlias
)
Len
()
int
{
return
len
(
a
)
}
func
(
a
b
yFirstAlias
)
Swap
(
i
,
j
int
)
{
a
[
i
],
a
[
j
]
=
a
[
j
],
a
[
i
]
}
func
(
a
b
yFirstAlias
)
Less
(
i
,
j
int
)
bool
{
return
a
[
i
]
.
aliases
[
0
]
<
a
[
j
]
.
aliases
[
0
]
}
// DebugCommands returns a Commands struct with default commands defined.
func
DebugCommands
(
client
service
.
Client
)
*
Commands
{
...
...
@@ -443,7 +443,7 @@ Currently, only the rev step-instruction command is supported.`,
})
}
sort
.
Sort
(
B
yFirstAlias
(
c
.
cmds
))
sort
.
Sort
(
b
yFirstAlias
(
c
.
cmds
))
return
c
}
...
...
@@ -592,7 +592,7 @@ func threads(t *Term, ctx callContext, args string) error {
}
if
th
.
Function
!=
nil
{
fmt
.
Printf
(
"%sThread %d at %#v %s:%d %s
\n
"
,
prefix
,
th
.
ID
,
th
.
PC
,
S
hortenFilePath
(
th
.
File
),
prefix
,
th
.
ID
,
th
.
PC
,
s
hortenFilePath
(
th
.
File
),
th
.
Line
,
th
.
Function
.
Name
())
}
else
{
fmt
.
Printf
(
"%sThread %s
\n
"
,
prefix
,
formatThread
(
th
))
...
...
@@ -825,7 +825,7 @@ func (c *Commands) frameCommand(t *Term, ctx callContext, argstr string, directi
}
printcontext
(
t
,
state
)
th
:=
stack
[
frame
]
fmt
.
Printf
(
"Frame %d: %s:%d (PC: %x)
\n
"
,
frame
,
S
hortenFilePath
(
th
.
File
),
th
.
Line
,
th
.
PC
)
fmt
.
Printf
(
"Frame %d: %s:%d (PC: %x)
\n
"
,
frame
,
s
hortenFilePath
(
th
.
File
),
th
.
Line
,
th
.
PC
)
printfile
(
t
,
th
.
File
,
th
.
Line
,
true
)
return
nil
}
...
...
@@ -863,7 +863,7 @@ func formatThread(th *api.Thread) string {
if
th
==
nil
{
return
"<nil>"
}
return
fmt
.
Sprintf
(
"%d at %s:%d"
,
th
.
ID
,
S
hortenFilePath
(
th
.
File
),
th
.
Line
)
return
fmt
.
Sprintf
(
"%d at %s:%d"
,
th
.
ID
,
s
hortenFilePath
(
th
.
File
),
th
.
Line
)
}
type
formatGoroutineLoc
int
...
...
@@ -876,7 +876,7 @@ const (
)
func
formatLocation
(
loc
api
.
Location
)
string
{
return
fmt
.
Sprintf
(
"%s:%d %s (%#v)"
,
S
hortenFilePath
(
loc
.
File
),
loc
.
Line
,
loc
.
Function
.
Name
(),
loc
.
PC
)
return
fmt
.
Sprintf
(
"%s:%d %s (%#v)"
,
s
hortenFilePath
(
loc
.
File
),
loc
.
Line
,
loc
.
Function
.
Name
(),
loc
.
PC
)
}
func
formatGoroutine
(
g
*
api
.
Goroutine
,
fgl
formatGoroutineLoc
)
string
{
...
...
@@ -1325,19 +1325,19 @@ func clearAll(t *Term, ctx callContext, args string) error {
return
nil
}
//
B
yID sorts breakpoints by ID.
type
B
yID
[]
*
api
.
Breakpoint
//
b
yID sorts breakpoints by ID.
type
b
yID
[]
*
api
.
Breakpoint
func
(
a
B
yID
)
Len
()
int
{
return
len
(
a
)
}
func
(
a
B
yID
)
Swap
(
i
,
j
int
)
{
a
[
i
],
a
[
j
]
=
a
[
j
],
a
[
i
]
}
func
(
a
B
yID
)
Less
(
i
,
j
int
)
bool
{
return
a
[
i
]
.
ID
<
a
[
j
]
.
ID
}
func
(
a
b
yID
)
Len
()
int
{
return
len
(
a
)
}
func
(
a
b
yID
)
Swap
(
i
,
j
int
)
{
a
[
i
],
a
[
j
]
=
a
[
j
],
a
[
i
]
}
func
(
a
b
yID
)
Less
(
i
,
j
int
)
bool
{
return
a
[
i
]
.
ID
<
a
[
j
]
.
ID
}
func
breakpoints
(
t
*
Term
,
ctx
callContext
,
args
string
)
error
{
breakPoints
,
err
:=
t
.
client
.
ListBreakpoints
()
if
err
!=
nil
{
return
err
}
sort
.
Sort
(
B
yID
(
breakPoints
))
sort
.
Sort
(
b
yID
(
breakPoints
))
for
_
,
bp
:=
range
breakPoints
{
fmt
.
Printf
(
"%s at %v (%d)
\n
"
,
formatBreakpointName
(
bp
,
true
),
formatBreakpointLocation
(
bp
),
bp
.
TotalHitCount
)
...
...
@@ -1352,14 +1352,14 @@ func breakpoints(t *Term, ctx callContext, args string) error {
attrs
=
append
(
attrs
,
"
\t
goroutine"
)
}
if
bp
.
LoadArgs
!=
nil
{
if
*
(
bp
.
LoadArgs
)
==
L
ongLoadConfig
{
if
*
(
bp
.
LoadArgs
)
==
l
ongLoadConfig
{
attrs
=
append
(
attrs
,
"
\t
args -v"
)
}
else
{
attrs
=
append
(
attrs
,
"
\t
args"
)
}
}
if
bp
.
LoadLocals
!=
nil
{
if
*
(
bp
.
LoadLocals
)
==
L
ongLoadConfig
{
if
*
(
bp
.
LoadLocals
)
==
l
ongLoadConfig
{
attrs
=
append
(
attrs
,
"
\t
locals -v"
)
}
else
{
attrs
=
append
(
attrs
,
"
\t
locals"
)
...
...
@@ -1955,7 +1955,7 @@ func disassCommand(t *Term, ctx callContext, args string) error {
return
disasmErr
}
D
isasmPrint
(
disasm
,
os
.
Stdout
)
d
isasmPrint
(
disasm
,
os
.
Stdout
)
return
nil
}
...
...
@@ -2004,7 +2004,7 @@ func printStack(stack []api.Stackframe, ind string, offsets bool) {
continue
}
fmt
.
Printf
(
fmtstr
,
ind
,
i
,
stack
[
i
]
.
PC
,
stack
[
i
]
.
Function
.
Name
())
fmt
.
Printf
(
"%sat %s:%d
\n
"
,
s
,
S
hortenFilePath
(
stack
[
i
]
.
File
),
stack
[
i
]
.
Line
)
fmt
.
Printf
(
"%sat %s:%d
\n
"
,
s
,
s
hortenFilePath
(
stack
[
i
]
.
File
),
stack
[
i
]
.
Line
)
if
offsets
{
fmt
.
Printf
(
"%sframe: %+#x frame pointer %+#x
\n
"
,
s
,
stack
[
i
]
.
FrameOffset
,
stack
[
i
]
.
FramePointerOffset
)
...
...
@@ -2084,7 +2084,7 @@ func printcontext(t *Term, state *api.DebuggerState) {
}
func
printcontextLocation
(
loc
api
.
Location
)
{
fmt
.
Printf
(
"> %s() %s:%d (PC: %#v)
\n
"
,
loc
.
Function
.
Name
(),
S
hortenFilePath
(
loc
.
File
),
loc
.
Line
,
loc
.
PC
)
fmt
.
Printf
(
"> %s() %s:%d (PC: %#v)
\n
"
,
loc
.
Function
.
Name
(),
s
hortenFilePath
(
loc
.
File
),
loc
.
Line
,
loc
.
PC
)
if
loc
.
Function
!=
nil
&&
loc
.
Function
.
Optimized
{
fmt
.
Println
(
optimizedFunctionWarning
)
}
...
...
@@ -2137,7 +2137,7 @@ func printcontextThread(t *Term, th *api.Thread) {
bpname
,
fn
.
Name
(),
args
,
S
hortenFilePath
(
th
.
File
),
s
hortenFilePath
(
th
.
File
),
th
.
Line
,
th
.
GoroutineID
,
hitCount
,
...
...
@@ -2148,7 +2148,7 @@ func printcontextThread(t *Term, th *api.Thread) {
bpname
,
fn
.
Name
(),
args
,
S
hortenFilePath
(
th
.
File
),
s
hortenFilePath
(
th
.
File
),
th
.
Line
,
th
.
Breakpoint
.
TotalHitCount
,
th
.
PC
)
...
...
@@ -2172,14 +2172,14 @@ func printcontextThread(t *Term, th *api.Thread) {
}
for
_
,
v
:=
range
bpi
.
Locals
{
if
*
bp
.
LoadLocals
==
L
ongLoadConfig
{
if
*
bp
.
LoadLocals
==
l
ongLoadConfig
{
fmt
.
Printf
(
"
\t
%s: %s
\n
"
,
v
.
Name
,
v
.
MultilineString
(
"
\t
"
))
}
else
{
fmt
.
Printf
(
"
\t
%s: %s
\n
"
,
v
.
Name
,
v
.
SinglelineString
())
}
}
if
bp
.
LoadArgs
!=
nil
&&
*
bp
.
LoadArgs
==
L
ongLoadConfig
{
if
bp
.
LoadArgs
!=
nil
&&
*
bp
.
LoadArgs
==
l
ongLoadConfig
{
for
_
,
v
:=
range
bpi
.
Arguments
{
fmt
.
Printf
(
"
\t
%s: %s
\n
"
,
v
.
Name
,
v
.
MultilineString
(
"
\t
"
))
}
...
...
@@ -2302,9 +2302,9 @@ func conditionCmd(t *Term, ctx callContext, argstr string) error {
return
t
.
client
.
AmendBreakpoint
(
bp
)
}
//
S
hortenFilePath take a full file path and attempts to shorten
//
s
hortenFilePath take a full file path and attempts to shorten
// it by replacing the current directory to './'.
func
S
hortenFilePath
(
fullPath
string
)
string
{
func
s
hortenFilePath
(
fullPath
string
)
string
{
workingDir
,
_
:=
os
.
Getwd
()
return
strings
.
Replace
(
fullPath
,
workingDir
,
"."
,
1
)
}
...
...
@@ -2463,7 +2463,7 @@ func formatBreakpointLocation(bp *api.Breakpoint) string {
fmt
.
Fprintf
(
&
out
,
"%#x"
,
bp
.
Addr
)
}
fmt
.
Fprintf
(
&
out
,
" for "
)
p
:=
S
hortenFilePath
(
bp
.
File
)
p
:=
s
hortenFilePath
(
bp
.
File
)
if
bp
.
FunctionName
!=
""
{
fmt
.
Fprintf
(
&
out
,
"%s() "
,
bp
.
FunctionName
)
}
...
...
pkg/terminal/disasmprint.go
浏览文件 @
3c8d4d52
...
...
@@ -10,7 +10,7 @@ import (
"github.com/go-delve/delve/service/api"
)
func
D
isasmPrint
(
dv
api
.
AsmInstructions
,
out
io
.
Writer
)
{
func
d
isasmPrint
(
dv
api
.
AsmInstructions
,
out
io
.
Writer
)
{
bw
:=
bufio
.
NewWriter
(
out
)
defer
bw
.
Flush
()
if
len
(
dv
)
>
0
&&
dv
[
0
]
.
Loc
.
Function
!=
nil
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录