Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
pubx
delve
提交
f09ef23f
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,发现更多精彩内容 >>
提交
f09ef23f
编写于
8月 04, 2016
作者:
A
Alex Brainman
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
proc: implement attach on windows
Updates #363
上级
c3ade94b
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
106 addition
and
41 deletion
+106
-41
proc/proc.go
proc/proc.go
+5
-5
proc/proc_windows.go
proc/proc_windows.go
+56
-24
proc/syscall_windows.go
proc/syscall_windows.go
+5
-0
proc/zsyscall_windows.go
proc/zsyscall_windows.go
+40
-12
未找到文件。
proc/proc.go
浏览文件 @
f09ef23f
...
@@ -79,6 +79,11 @@ func New(pid int) *Process {
...
@@ -79,6 +79,11 @@ func New(pid int) *Process {
ptraceChan
:
make
(
chan
func
()),
ptraceChan
:
make
(
chan
func
()),
ptraceDoneChan
:
make
(
chan
interface
{}),
ptraceDoneChan
:
make
(
chan
interface
{}),
}
}
// TODO: find better way to determine proc arch (perhaps use executable file info)
switch
runtime
.
GOARCH
{
case
"amd64"
:
dbp
.
arch
=
AMD64Arch
()
}
go
dbp
.
handlePtraceFuncs
()
go
dbp
.
handlePtraceFuncs
()
return
dbp
return
dbp
}
}
...
@@ -704,11 +709,6 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
...
@@ -704,11 +709,6 @@ func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, e
return
nil
,
err
return
nil
,
err
}
}
switch
runtime
.
GOARCH
{
case
"amd64"
:
dbp
.
arch
=
AMD64Arch
()
}
if
err
:=
dbp
.
updateThreadList
();
err
!=
nil
{
if
err
:=
dbp
.
updateThreadList
();
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
proc/proc_windows.go
浏览文件 @
f09ef23f
...
@@ -8,21 +8,15 @@ import (
...
@@ -8,21 +8,15 @@ import (
"os"
"os"
"os/exec"
"os/exec"
"path/filepath"
"path/filepath"
"runtime"
"sync"
"sync"
"syscall"
"syscall"
"unsafe"
"unsafe"
sys
"golang.org/x/sys/windows"
sys
"golang.org/x/sys/windows"
"golang.org/x/debug/dwarf"
"github.com/derekparker/delve/dwarf/frame"
"github.com/derekparker/delve/dwarf/frame"
"github.com/derekparker/delve/dwarf/line"
"github.com/derekparker/delve/dwarf/line"
)
"golang.org/x/debug/dwarf"
const
(
// DEBUGONLYTHISPROCESS tracks https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
DEBUGONLYTHISPROCESS
=
0x00000002
)
)
// OSProcessDetails holds Windows specific information.
// OSProcessDetails holds Windows specific information.
...
@@ -97,24 +91,25 @@ func Launch(cmd []string) (*Process, error) {
...
@@ -97,24 +91,25 @@ func Launch(cmd []string) (*Process, error) {
si
.
StdOutput
=
sys
.
Handle
(
fd
[
1
])
si
.
StdOutput
=
sys
.
Handle
(
fd
[
1
])
si
.
StdErr
=
sys
.
Handle
(
fd
[
2
])
si
.
StdErr
=
sys
.
Handle
(
fd
[
2
])
pi
:=
new
(
sys
.
ProcessInformation
)
pi
:=
new
(
sys
.
ProcessInformation
)
err
=
sys
.
CreateProcess
(
argv0
,
cmdLine
,
nil
,
nil
,
true
,
DEBUGONLYTHIS
PROCESS
,
nil
,
nil
,
si
,
pi
)
err
=
sys
.
CreateProcess
(
argv0
,
cmdLine
,
nil
,
nil
,
true
,
_DEBUG_ONLY_THIS_
PROCESS
,
nil
,
nil
,
si
,
pi
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Process
))
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Process
))
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Thread
))
sys
.
CloseHandle
(
sys
.
Handle
(
pi
.
Thread
))
dbp
:=
New
(
int
(
pi
.
ProcessId
))
return
newDebugProcess
(
int
(
pi
.
ProcessId
),
argv0Go
)
}
switch
runtime
.
GOARCH
{
case
"amd64"
:
dbp
.
arch
=
AMD64Arch
()
}
// Note - it should not actually be possible for the
// newDebugProcess prepares process pid for debugging.
func
newDebugProcess
(
pid
int
,
exepath
string
)
(
*
Process
,
error
)
{
dbp
:=
New
(
pid
)
// It should not actually be possible for the
// call to waitForDebugEvent to fail, since Windows
// call to waitForDebugEvent to fail, since Windows
// will always fire a CreateProcess event immediately
// will always fire a CREATE_PROCESS_DEBUG_EVENT event
// after launching under DEBUGONLYTHISPROCESS.
// immediately after launching under DEBUG_ONLY_THIS_PROCESS.
// Attaching with DebugActiveProcess has similar effect.
var
err
error
var
tid
,
exitCode
int
var
tid
,
exitCode
int
dbp
.
execPtraceFunc
(
func
()
{
dbp
.
execPtraceFunc
(
func
()
{
tid
,
exitCode
,
err
=
dbp
.
waitForDebugEvent
()
tid
,
exitCode
,
err
=
dbp
.
waitForDebugEvent
()
...
@@ -126,13 +121,55 @@ func Launch(cmd []string) (*Process, error) {
...
@@ -126,13 +121,55 @@ func Launch(cmd []string) (*Process, error) {
dbp
.
postExit
()
dbp
.
postExit
()
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
Pid
,
Status
:
exitCode
}
return
nil
,
ProcessExitedError
{
Pid
:
dbp
.
Pid
,
Status
:
exitCode
}
}
}
return
initializeDebugProcess
(
dbp
,
exepath
,
false
)
}
// findExePath searches for process pid, and returns its executable path.
func
findExePath
(
pid
int
)
(
string
,
error
)
{
// Original code suggested different approach (see below).
// Maybe it could be useful in the future.
//
// Find executable path from PID/handle on Windows:
// https://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx
p
,
err
:=
syscall
.
OpenProcess
(
syscall
.
PROCESS_QUERY_INFORMATION
,
false
,
uint32
(
pid
))
if
err
!=
nil
{
return
""
,
err
}
defer
syscall
.
CloseHandle
(
p
)
return
initializeDebugProcess
(
dbp
,
argv0Go
,
false
)
n
:=
uint32
(
128
)
for
{
buf
:=
make
([]
uint16
,
int
(
n
))
err
=
_QueryFullProcessImageName
(
p
,
0
,
&
buf
[
0
],
&
n
)
switch
err
{
case
syscall
.
ERROR_INSUFFICIENT_BUFFER
:
// try bigger buffer
n
*=
2
// but stop if it gets too big
if
n
>
10000
{
return
""
,
err
}
case
nil
:
return
syscall
.
UTF16ToString
(
buf
[
:
n
]),
nil
default
:
return
""
,
err
}
}
}
}
// Attach to an existing process with the given PID.
// Attach to an existing process with the given PID.
func
Attach
(
pid
int
)
(
*
Process
,
error
)
{
func
Attach
(
pid
int
)
(
*
Process
,
error
)
{
return
nil
,
fmt
.
Errorf
(
"not implemented: Attach"
)
// TODO: Probably should have SeDebugPrivilege before starting here.
err
:=
_DebugActiveProcess
(
uint32
(
pid
))
if
err
!=
nil
{
return
nil
,
err
}
exepath
,
err
:=
findExePath
(
pid
)
if
err
!=
nil
{
return
nil
,
err
}
return
newDebugProcess
(
pid
,
exepath
)
}
}
// Kill kills the process.
// Kill kills the process.
...
@@ -316,11 +353,6 @@ func (dbp *Process) parseDebugLineInfo(exe *pe.File, wg *sync.WaitGroup) {
...
@@ -316,11 +353,6 @@ func (dbp *Process) parseDebugLineInfo(exe *pe.File, wg *sync.WaitGroup) {
var
UnsupportedArchErr
=
errors
.
New
(
"unsupported architecture of windows/386 - only windows/amd64 is supported"
)
var
UnsupportedArchErr
=
errors
.
New
(
"unsupported architecture of windows/386 - only windows/amd64 is supported"
)
func
(
dbp
*
Process
)
findExecutable
(
path
string
)
(
*
pe
.
File
,
error
)
{
func
(
dbp
*
Process
)
findExecutable
(
path
string
)
(
*
pe
.
File
,
error
)
{
if
path
==
""
{
// TODO: Find executable path from PID/handle on Windows:
// https://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx
return
nil
,
fmt
.
Errorf
(
"not yet implemented"
)
}
peFile
,
err
:=
openExecutablePath
(
path
)
peFile
,
err
:=
openExecutablePath
(
path
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
proc/syscall_windows.go
浏览文件 @
f09ef23f
...
@@ -69,6 +69,9 @@ const (
...
@@ -69,6 +69,9 @@ const (
_UNLOAD_DLL_DEBUG_EVENT
=
7
_UNLOAD_DLL_DEBUG_EVENT
=
7
_OUTPUT_DEBUG_STRING_EVENT
=
8
_OUTPUT_DEBUG_STRING_EVENT
=
8
_RIP_EVENT
=
9
_RIP_EVENT
=
9
// DEBUG_ONLY_THIS_PROCESS tracks https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
_DEBUG_ONLY_THIS_PROCESS
=
0x00000002
)
)
func
_NT_SUCCESS
(
x
_NTSTATUS
)
bool
{
func
_NT_SUCCESS
(
x
_NTSTATUS
)
bool
{
...
@@ -85,3 +88,5 @@ func _NT_SUCCESS(x _NTSTATUS) bool {
...
@@ -85,3 +88,5 @@ func _NT_SUCCESS(x _NTSTATUS) bool {
//sys _ReadProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, bytesread *uintptr) (err error) = kernel32.ReadProcessMemory
//sys _ReadProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, bytesread *uintptr) (err error) = kernel32.ReadProcessMemory
//sys _DebugBreakProcess(process syscall.Handle) (err error) = kernel32.DebugBreakProcess
//sys _DebugBreakProcess(process syscall.Handle) (err error) = kernel32.DebugBreakProcess
//sys _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err error) = kernel32.WaitForDebugEvent
//sys _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err error) = kernel32.WaitForDebugEvent
//sys _DebugActiveProcess(processid uint32) (err error) = kernel32.DebugActiveProcess
//sys _QueryFullProcessImageName(process syscall.Handle, flags uint32, exename *uint16, size *uint32) (err error) = kernel32.QueryFullProcessImageNameW
proc/zsyscall_windows.go
浏览文件 @
f09ef23f
...
@@ -2,8 +2,10 @@
...
@@ -2,8 +2,10 @@
package
proc
package
proc
import
"unsafe"
import
(
import
"syscall"
"syscall"
"unsafe"
)
var
_
unsafe
.
Pointer
var
_
unsafe
.
Pointer
...
@@ -21,6 +23,8 @@ var (
...
@@ -21,6 +23,8 @@ var (
procReadProcessMemory
=
modkernel32
.
NewProc
(
"ReadProcessMemory"
)
procReadProcessMemory
=
modkernel32
.
NewProc
(
"ReadProcessMemory"
)
procDebugBreakProcess
=
modkernel32
.
NewProc
(
"DebugBreakProcess"
)
procDebugBreakProcess
=
modkernel32
.
NewProc
(
"DebugBreakProcess"
)
procWaitForDebugEvent
=
modkernel32
.
NewProc
(
"WaitForDebugEvent"
)
procWaitForDebugEvent
=
modkernel32
.
NewProc
(
"WaitForDebugEvent"
)
procDebugActiveProcess
=
modkernel32
.
NewProc
(
"DebugActiveProcess"
)
procQueryFullProcessImageNameW
=
modkernel32
.
NewProc
(
"QueryFullProcessImageNameW"
)
)
)
func
_NtQueryInformationThread
(
threadHandle
syscall
.
Handle
,
infoclass
int32
,
info
uintptr
,
infolen
uint32
,
retlen
*
uint32
)
(
status
_NTSTATUS
)
{
func
_NtQueryInformationThread
(
threadHandle
syscall
.
Handle
,
infoclass
int32
,
info
uintptr
,
infolen
uint32
,
retlen
*
uint32
)
(
status
_NTSTATUS
)
{
...
@@ -138,3 +142,27 @@ func _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err erro
...
@@ -138,3 +142,27 @@ func _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err erro
}
}
return
return
}
}
func
_DebugActiveProcess
(
processid
uint32
)
(
err
error
)
{
r1
,
_
,
e1
:=
syscall
.
Syscall
(
procDebugActiveProcess
.
Addr
(),
1
,
uintptr
(
processid
),
0
,
0
)
if
r1
==
0
{
if
e1
!=
0
{
err
=
error
(
e1
)
}
else
{
err
=
syscall
.
EINVAL
}
}
return
}
func
_QueryFullProcessImageName
(
process
syscall
.
Handle
,
flags
uint32
,
exename
*
uint16
,
size
*
uint32
)
(
err
error
)
{
r1
,
_
,
e1
:=
syscall
.
Syscall6
(
procQueryFullProcessImageNameW
.
Addr
(),
4
,
uintptr
(
process
),
uintptr
(
flags
),
uintptr
(
unsafe
.
Pointer
(
exename
)),
uintptr
(
unsafe
.
Pointer
(
size
)),
0
,
0
)
if
r1
==
0
{
if
e1
!=
0
{
err
=
error
(
e1
)
}
else
{
err
=
syscall
.
EINVAL
}
}
return
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录