Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
HugeYuan
delve
提交
63b8fa82
D
delve
项目概览
HugeYuan
/
delve
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
delve
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
63b8fa82
编写于
11月 10, 2016
作者:
A
aarzilli
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
proc: support for ver. 10.12.1 the OS formerly known as Mac OS X
Fixes #645
上级
ee6d2734
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
186 addition
and
29 deletion
+186
-29
Makefile
Makefile
+1
-1
proc/exec_darwin.c
proc/exec_darwin.c
+2
-0
proc/proc_darwin.c
proc/proc_darwin.c
+56
-10
proc/proc_darwin.go
proc/proc_darwin.go
+99
-11
proc/proc_darwin.h
proc/proc_darwin.h
+10
-1
proc/proc_windows.go
proc/proc_windows.go
+1
-1
proc/test/support.go
proc/test/support.go
+5
-2
proc/threads_darwin.go
proc/threads_darwin.go
+12
-2
proc/variables.go
proc/variables.go
+0
-1
未找到文件。
Makefile
浏览文件 @
63b8fa82
...
...
@@ -64,7 +64,7 @@ else
endif
test-proc-run
:
go
test
$(TEST_FLAGS)
$(BUILD_FLAGS)
-test
.run
=
"
$(RUN)
"
$(PREFIX)
/proc
go
test
$(TEST_FLAGS)
$(BUILD_FLAGS)
-test
.
v
-test
.
run
=
"
$(RUN)
"
$(PREFIX)
/proc
test-integration-run
:
go
test
$(TEST_FLAGS)
$(BUILD_FLAGS)
-test
.run
=
"
$(RUN)
"
$(PREFIX)
/service/test
proc/exec_darwin.c
浏览文件 @
63b8fa82
...
...
@@ -97,6 +97,8 @@ fork_exec(char *argv0, char **argv, int size,
exit
(
1
);
}
sleep
(
1
);
// Create the child process.
execve
(
argv0
,
argv
,
environ
);
...
...
proc/proc_darwin.c
浏览文件 @
63b8fa82
...
...
@@ -68,6 +68,23 @@ acquire_mach_task(int tid,
return
mach_port_move_member
(
self
,
*
notification_port
,
*
port_set
);
}
kern_return_t
reset_exception_ports
(
task_t
task
,
mach_port_t
*
exception_port
,
mach_port_t
*
notification_port
)
{
kern_return_t
kret
;
mach_port_t
prev_not
;
mach_port_t
self
=
mach_task_self
();
kret
=
task_set_exception_ports
(
task
,
EXC_MASK_BREAKPOINT
|
EXC_MASK_SOFTWARE
,
*
exception_port
,
EXCEPTION_DEFAULT
,
THREAD_STATE_NONE
);
if
(
kret
!=
KERN_SUCCESS
)
return
kret
;
kret
=
mach_port_request_notification
(
self
,
task
,
MACH_NOTIFY_DEAD_NAME
,
0
,
*
notification_port
,
MACH_MSG_TYPE_MAKE_SEND_ONCE
,
&
prev_not
);
if
(
kret
!=
KERN_SUCCESS
)
return
kret
;
return
KERN_SUCCESS
;
}
char
*
find_executable
(
int
pid
)
{
static
char
pathbuf
[
PATH_MAX
];
...
...
@@ -115,7 +132,7 @@ thread_count(task_t task) {
}
mach_port_t
mach_port_wait
(
mach_port_t
port_set
,
int
nonblocking
)
{
mach_port_wait
(
mach_port_t
port_set
,
task_t
*
task
,
int
nonblocking
)
{
kern_return_t
kret
;
thread_act_t
thread
;
NDR_record_t
*
ndr
;
...
...
@@ -136,14 +153,20 @@ mach_port_wait(mach_port_t port_set, int nonblocking) {
if
(
kret
==
MACH_RCV_INTERRUPTED
)
return
kret
;
if
(
kret
!=
MACH_MSG_SUCCESS
)
return
0
;
mach_msg_body_t
*
bod
=
(
mach_msg_body_t
*
)(
&
msg
.
hdr
+
1
);
mach_msg_port_descriptor_t
*
desc
=
(
mach_msg_port_descriptor_t
*
)(
bod
+
1
);
thread
=
desc
[
0
].
name
;
ndr
=
(
NDR_record_t
*
)(
desc
+
2
);
data
=
(
integer_t
*
)(
ndr
+
1
);
switch
(
msg
.
hdr
.
msgh_id
)
{
case
2401
:
// Exception
case
2401
:
{
// Exception
// 2401 is the exception_raise event, defined in:
// http://opensource.apple.com/source/xnu/xnu-2422.1.72/osfmk/mach/exc.defs?txt
// compile this file with mig to get the C version of the description
mach_msg_body_t
*
bod
=
(
mach_msg_body_t
*
)(
&
msg
.
hdr
+
1
);
mach_msg_port_descriptor_t
*
desc
=
(
mach_msg_port_descriptor_t
*
)(
bod
+
1
);
thread
=
desc
[
0
].
name
;
*
task
=
desc
[
1
].
name
;
ndr
=
(
NDR_record_t
*
)(
desc
+
2
);
data
=
(
integer_t
*
)(
ndr
+
1
);
if
(
thread_suspend
(
thread
)
!=
KERN_SUCCESS
)
return
0
;
// Send our reply back so the kernel knows this exception has been handled.
kret
=
mach_send_reply
(
msg
.
hdr
);
...
...
@@ -151,13 +174,20 @@ mach_port_wait(mach_port_t port_set, int nonblocking) {
if
(
data
[
2
]
==
EXC_SOFT_SIGNAL
)
{
if
(
data
[
3
]
!=
SIGTRAP
)
{
if
(
thread_resume
(
thread
)
!=
KERN_SUCCESS
)
return
0
;
return
mach_port_wait
(
port_set
,
nonblocking
);
return
mach_port_wait
(
port_set
,
task
,
nonblocking
);
}
}
return
thread
;
case
72
:
// Death
}
case
72
:
{
// Death
// 72 is mach_notify_dead_name, defined in:
// https://opensource.apple.com/source/xnu/xnu-1228.7.58/osfmk/mach/notify.defs?txt
// compile this file with mig to get the C version of the description
ndr
=
(
NDR_record_t
*
)(
&
msg
.
hdr
+
1
);
*
task
=
*
((
mach_port_name_t
*
)(
ndr
+
1
));
return
msg
.
hdr
.
msgh_local_port
;
}
}
return
0
;
}
...
...
@@ -183,3 +213,19 @@ kern_return_t
raise_exception
(
mach_port_t
task
,
mach_port_t
thread
,
mach_port_t
exception_port
,
exception_type_t
exception
)
{
return
exception_raise
(
exception_port
,
thread
,
task
,
exception
,
0
,
0
);
}
task_t
get_task_for_pid
(
int
pid
)
{
task_t
task
=
0
;
mach_port_t
self
=
mach_task_self
();
task_for_pid
(
self
,
pid
,
&
task
);
return
task
;
}
int
task_is_valid
(
task_t
task
)
{
struct
task_basic_info
info
;
mach_msg_type_number_t
count
=
TASK_BASIC_INFO_COUNT
;
return
task_info
(
task
,
TASK_BASIC_INFO
,
(
task_info_t
)
&
info
,
&
count
)
==
KERN_SUCCESS
;
}
proc/proc_darwin.go
浏览文件 @
63b8fa82
...
...
@@ -27,6 +27,7 @@ type OSProcessDetails 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).
initialized
bool
// the main port we use, will return messages from both the
// exception and notification ports.
...
...
@@ -81,11 +82,51 @@ func Launch(cmd []string, wd string) (*Process, error) {
C
.
free
(
unsafe
.
Pointer
(
argvSlice
[
i
]))
}
// Initialize enough of the Process state so that we can use resume and
// trapWait to wait until the child process calls execve.
for
{
err
=
dbp
.
updateThreadListForTask
(
C
.
get_task_for_pid
(
C
.
int
(
dbp
.
Pid
)))
if
err
==
nil
{
break
}
if
err
!=
couldNotGetThreadCount
&&
err
!=
couldNotGetThreadList
{
return
nil
,
err
}
}
if
err
:=
dbp
.
resume
();
err
!=
nil
{
return
nil
,
err
}
dbp
.
allGCache
=
nil
for
_
,
th
:=
range
dbp
.
Threads
{
th
.
clearBreakpointState
()
}
trapthread
,
err
:=
dbp
.
trapWait
(
-
1
)
if
err
!=
nil
{
return
nil
,
err
}
if
err
:=
dbp
.
Halt
();
err
!=
nil
{
return
nil
,
dbp
.
exitGuard
(
err
)
}
_
,
err
=
dbp
.
waitForStop
()
if
err
!=
nil
{
return
nil
,
err
}
dbp
.
os
.
initialized
=
true
dbp
,
err
=
initializeDebugProcess
(
dbp
,
argv0Go
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
err
=
dbp
.
Continue
()
if
err
:=
dbp
.
SwitchThread
(
trapthread
.
ID
);
err
!=
nil
{
return
nil
,
err
}
return
dbp
,
err
}
...
...
@@ -101,6 +142,8 @@ func Attach(pid int) (*Process, error) {
return
nil
,
fmt
.
Errorf
(
"could not attach to %d"
,
pid
)
}
dbp
.
os
.
initialized
=
true
return
initializeDebugProcess
(
dbp
,
""
,
true
)
}
...
...
@@ -119,7 +162,8 @@ func (dbp *Process) Kill() (err error) {
}
}
for
{
port
:=
C
.
mach_port_wait
(
dbp
.
os
.
portSet
,
C
.
int
(
0
))
var
task
C
.
task_t
port
:=
C
.
mach_port_wait
(
dbp
.
os
.
portSet
,
&
task
,
C
.
int
(
0
))
if
port
==
dbp
.
os
.
notificationPort
{
break
}
...
...
@@ -141,7 +185,14 @@ func (dbp *Process) requestManualStop() (err error) {
return
nil
}
var
couldNotGetThreadCount
=
errors
.
New
(
"could not get thread count"
)
var
couldNotGetThreadList
=
errors
.
New
(
"could not get thread list"
)
func
(
dbp
*
Process
)
updateThreadList
()
error
{
return
dbp
.
updateThreadListForTask
(
dbp
.
os
.
task
)
}
func
(
dbp
*
Process
)
updateThreadListForTask
(
task
C
.
task_t
)
error
{
var
(
err
error
kret
C
.
kern_return_t
...
...
@@ -150,30 +201,42 @@ func (dbp *Process) updateThreadList() error {
)
for
{
count
=
C
.
thread_count
(
dbp
.
os
.
task
)
count
=
C
.
thread_count
(
task
)
if
count
==
-
1
{
return
fmt
.
Errorf
(
"could not get thread count"
)
return
couldNotGetThreadCount
}
list
=
make
([]
uint32
,
count
)
// TODO(dp) might be better to malloc mem in C and then free it here
// instead of getting count above and passing in a slice
kret
=
C
.
get_threads
(
dbp
.
os
.
task
,
unsafe
.
Pointer
(
&
list
[
0
]),
count
)
kret
=
C
.
get_threads
(
task
,
unsafe
.
Pointer
(
&
list
[
0
]),
count
)
if
kret
!=
-
2
{
break
}
}
if
kret
!=
C
.
KERN_SUCCESS
{
return
fmt
.
Errorf
(
"could not get thread list"
)
return
couldNotGetThreadList
}
for
_
,
thread
:=
range
dbp
.
Threads
{
thread
.
os
.
exists
=
false
}
for
_
,
port
:=
range
list
{
if
_
,
ok
:=
dbp
.
Threads
[
int
(
port
)];
!
ok
{
_
,
err
=
dbp
.
addThread
(
int
(
port
),
false
)
thread
,
ok
:=
dbp
.
Threads
[
int
(
port
)]
if
!
ok
{
thread
,
err
=
dbp
.
addThread
(
int
(
port
),
false
)
if
err
!=
nil
{
return
err
}
}
thread
.
os
.
exists
=
true
}
for
threadID
,
thread
:=
range
dbp
.
Threads
{
if
!
thread
.
os
.
exists
{
delete
(
dbp
.
Threads
,
threadID
)
}
}
return
nil
...
...
@@ -293,10 +356,23 @@ func (dbp *Process) findExecutable(path string) (*macho.File, error) {
func
(
dbp
*
Process
)
trapWait
(
pid
int
)
(
*
Thread
,
error
)
{
for
{
port
:=
C
.
mach_port_wait
(
dbp
.
os
.
portSet
,
C
.
int
(
0
))
task
:=
dbp
.
os
.
task
port
:=
C
.
mach_port_wait
(
dbp
.
os
.
portSet
,
&
task
,
C
.
int
(
0
))
switch
port
{
case
dbp
.
os
.
notificationPort
:
// on macOS >= 10.12.1 the task_t changes after an execve, we could
// receive the notification for the death of the pre-execve task_t,
// this could also happen *before* we are notified that our task_t has
// changed.
if
dbp
.
os
.
task
!=
task
{
continue
}
if
!
dbp
.
os
.
initialized
{
if
pidtask
:=
C
.
get_task_for_pid
(
C
.
int
(
dbp
.
Pid
));
pidtask
!=
0
&&
dbp
.
os
.
task
!=
pidtask
{
continue
}
}
_
,
status
,
err
:=
dbp
.
wait
(
dbp
.
Pid
,
0
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -317,6 +393,17 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
return
nil
,
fmt
.
Errorf
(
"error while waiting for task"
)
}
// In macOS 10.12.1 if we received a notification for a task other than
// the inferior's task and the inferior's task is no longer valid, this
// means inferior called execve and its task_t changed.
if
dbp
.
os
.
task
!=
task
&&
C
.
task_is_valid
(
dbp
.
os
.
task
)
==
0
{
dbp
.
os
.
task
=
task
kret
:=
C
.
reset_exception_ports
(
dbp
.
os
.
task
,
&
dbp
.
os
.
exceptionPort
,
&
dbp
.
os
.
notificationPort
)
if
kret
!=
C
.
KERN_SUCCESS
{
return
nil
,
fmt
.
Errorf
(
"could not follow task across exec: %d
\n
"
,
kret
)
}
}
// Since we cannot be notified of new threads on OS X
// this is as good a time as any to check for them.
dbp
.
updateThreadList
()
...
...
@@ -343,8 +430,9 @@ func (dbp *Process) waitForStop() ([]int, error) {
ports
:=
make
([]
int
,
0
,
len
(
dbp
.
Threads
))
count
:=
0
for
{
port
:=
C
.
mach_port_wait
(
dbp
.
os
.
portSet
,
C
.
int
(
1
))
if
port
!=
0
{
var
task
C
.
task_t
port
:=
C
.
mach_port_wait
(
dbp
.
os
.
portSet
,
&
task
,
C
.
int
(
1
))
if
port
!=
0
&&
port
!=
dbp
.
os
.
notificationPort
&&
port
!=
C
.
MACH_RCV_INTERRUPTED
{
count
=
0
ports
=
append
(
ports
,
int
(
port
))
}
else
{
...
...
proc/proc_darwin.h
浏览文件 @
63b8fa82
...
...
@@ -36,10 +36,19 @@ int
thread_count
(
task_t
task
);
mach_port_t
mach_port_wait
(
mach_port_t
,
int
);
mach_port_wait
(
mach_port_t
,
task_t
*
,
int
);
kern_return_t
mach_send_reply
(
mach_msg_header_t
);
kern_return_t
raise_exception
(
mach_port_t
,
mach_port_t
,
mach_port_t
,
exception_type_t
);
kern_return_t
reset_exception_ports
(
task_t
task
,
mach_port_t
*
exception_port
,
mach_port_t
*
notification_port
);
task_t
get_task_for_pid
(
int
pid
);
int
task_is_valid
(
task_t
task
);
proc/proc_windows.go
浏览文件 @
63b8fa82
...
...
@@ -82,7 +82,7 @@ func Launch(cmd []string, wd string) (*Process, error) {
return
nil
,
err
}
}
var
workingDir
*
uint16
if
wd
!=
""
{
if
workingDir
,
err
=
syscall
.
UTF16PtrFromString
(
wd
);
err
!=
nil
{
...
...
proc/test/support.go
浏览文件 @
63b8fa82
...
...
@@ -54,10 +54,13 @@ func BuildFixture(name string) Fixture {
// Work-around for https://github.com/golang/go/issues/13154
buildFlags
=
append
(
buildFlags
,
"-ldflags=-linkmode internal"
)
}
buildFlags
=
append
(
buildFlags
,
"-gcflags=-N -l"
,
"-o"
,
tmpfile
,
path
)
buildFlags
=
append
(
buildFlags
,
"-gcflags=-N -l"
,
"-o"
,
tmpfile
,
name
+
".go"
)
cmd
:=
exec
.
Command
(
"go"
,
buildFlags
...
)
cmd
.
Dir
=
fixturesDir
// Build the test binary
if
err
:=
exec
.
Command
(
"go"
,
buildFlags
...
)
.
Run
();
err
!=
nil
{
if
err
:=
cmd
.
Run
();
err
!=
nil
{
fmt
.
Printf
(
"Error compiling %s: %s
\n
"
,
path
,
err
)
os
.
Exit
(
1
)
}
...
...
proc/threads_darwin.go
浏览文件 @
63b8fa82
...
...
@@ -17,6 +17,7 @@ type WaitStatus sys.WaitStatus
type
OSSpecificDetails
struct
{
threadAct
C
.
thread_act_t
registers
C
.
x86_thread_state64_t
exists
bool
}
// ErrContinueThread is the error returned when a thread could not
...
...
@@ -27,8 +28,17 @@ func (t *Thread) halt() (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
)))
err
=
fmt
.
Errorf
(
"could not suspend thread %d %s"
,
t
.
ID
,
errStr
)
return
// check that the thread still exists before complaining
err2
:=
t
.
dbp
.
updateThreadList
()
if
err2
!=
nil
{
err
=
fmt
.
Errorf
(
"could not suspend thread %d %s (additionally could not update thread list: %v)"
,
t
.
ID
,
errStr
,
err2
)
return
}
if
_
,
ok
:=
t
.
dbp
.
Threads
[
t
.
ID
];
ok
{
err
=
fmt
.
Errorf
(
"could not suspend thread %d %s"
,
t
.
ID
,
errStr
)
return
}
}
return
}
...
...
proc/variables.go
浏览文件 @
63b8fa82
...
...
@@ -834,7 +834,6 @@ func (v *Variable) setValue(y *Variable) error {
imag
,
_
:=
constant
.
Float64Val
(
constant
.
Imag
(
y
.
Value
))
err
=
v
.
writeComplex
(
real
,
imag
,
v
.
RealType
.
Size
())
default
:
fmt
.
Printf
(
"default
\n
"
)
if
t
,
isptr
:=
v
.
RealType
.
(
*
dwarf
.
PtrType
);
isptr
{
err
=
v
.
writeUint
(
uint64
(
y
.
Children
[
0
]
.
Addr
),
int64
(
t
.
ByteSize
))
}
else
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录