Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
547f1125
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
547f1125
编写于
1月 18, 2013
作者:
V
Vineet Gupta
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ARC: ptrace support
Signed-off-by:
N
Vineet Gupta
<
vgupta@synopsys.com
>
Acked-by:
N
Arnd Bergmann
<
arnd@arndb.de
>
上级
080c3747
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
206 addition
and
2 deletion
+206
-2
arch/arc/Kconfig
arch/arc/Kconfig
+1
-0
arch/arc/kernel/Makefile
arch/arc/kernel/Makefile
+3
-0
arch/arc/kernel/entry.S
arch/arc/kernel/entry.S
+68
-0
arch/arc/kernel/ptrace.c
arch/arc/kernel/ptrace.c
+134
-2
未找到文件。
arch/arc/Kconfig
浏览文件 @
547f1125
...
...
@@ -22,6 +22,7 @@ config ARC
select GENERIC_PENDING_IRQ if SMP
select GENERIC_SIGALTSTACK
select GENERIC_SMP_IDLE_THREAD
select HAVE_ARCH_TRACEHOOK
select HAVE_GENERIC_HARDIRQS
select HAVE_MEMBLOCK
select IRQ_DOMAIN
...
...
arch/arc/kernel/Makefile
浏览文件 @
547f1125
...
...
@@ -5,6 +5,9 @@
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
# Pass UTS_MACHINE for user_regset definition
CFLAGS_ptrace.o
+=
-DUTS_MACHINE
=
'"
$(UTS_MACHINE)
"'
obj-y
:=
arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
obj-y
+=
signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
obj-y
+=
devtree.o
...
...
arch/arc/kernel/entry.S
浏览文件 @
547f1125
...
...
@@ -7,6 +7,13 @@
*
it
under
the
terms
of
the
GNU
General
Public
License
version
2
as
*
published
by
the
Free
Software
Foundation
.
*
*
vineetg
:
Feb
2011
(
ptrace
low
level
code
fixes
)
*
-
traced
syscall
return
code
(
r0
)
was
not
saved
into
pt_regs
for
restoring
*
into
user
reg
-
file
when
traded
task
rets
to
user
space
.
*
-
syscalls
needing
arch
-
wrappers
(
mainly
for
passing
sp
as
pt_regs
)
*
were
not
invoking
post
-
syscall
trace
hook
(
jumping
directly
into
*
ret_from_system_call
)
*
*
vineetg
:
Nov
2010
:
*
-
Vector
table
jumps
(@
8
bytes
)
converted
into
branches
(
@
4
bytes
)
*
-
To
maintain
the
slot
size
of
8
bytes
/
vector
,
added
nop
,
which
is
...
...
@@ -347,6 +354,50 @@ ARC_ENTRY EV_Extension
b
ret_from_exception
ARC_EXIT
EV_Extension
;######################### System Call Tracing #########################
tracesys
:
; save EFA in case tracer wants the PC of traced task
; using ERET won't work since next-PC has already committed
lr
r12
,
[
efa
]
GET_CURR_TASK_FIELD_PTR
TASK_THREAD
,
r11
st
r12
,
[
r11
,
THREAD_FAULT_ADDR
]
; PRE Sys Call Ptrace hook
mov
r0
,
sp
; pt_regs needed
bl
@
syscall_trace_entry
; Tracing code now returns the syscall num (orig or modif)
mov
r8
,
r0
; Do the Sys Call as we normally would.
; Validate the Sys Call number
cmp
r8
,
NR_syscalls
mov.hi
r0
,
-
ENOSYS
bhi
tracesys_exit
; Restore the sys-call args. Mere invocation of the hook abv could have
; clobbered them (since they are in scratch regs). The tracer could also
; have deliberately changed the syscall args: r0-r7
ld
r0
,
[
sp
,
PT_r0
]
ld
r1
,
[
sp
,
PT_r1
]
ld
r2
,
[
sp
,
PT_r2
]
ld
r3
,
[
sp
,
PT_r3
]
ld
r4
,
[
sp
,
PT_r4
]
ld
r5
,
[
sp
,
PT_r5
]
ld
r6
,
[
sp
,
PT_r6
]
ld
r7
,
[
sp
,
PT_r7
]
ld.as
r9
,
[
sys_call_table
,
r8
]
jl
[
r9
]
; Entry into Sys Call Handler
tracesys_exit
:
st
r0
,
[
sp
,
PT_r0
]
; sys call return value in pt_regs
;POST Sys Call Ptrace Hook
bl
@
syscall_trace_exit
b
ret_from_exception
; NOT ret_from_system_call at is saves r0 which
; we'd done before calling post hook above
;################### Break Point TRAP ##########################
; ======= (5b) Trap is due to Break-Point =========
...
...
@@ -412,6 +463,11 @@ ARC_ENTRY EV_Trap
; Before doing anything, return from CPU Exception Mode
FAKE_RET_FROM_EXCPN
r11
; If syscall tracing ongoing, invoke pre-pos-hooks
GET_CURR_THR_INFO_FLAGS
r10
btst
r10
,
TIF_SYSCALL_TRACE
bnz
tracesys
; this never comes back
;============ This is normal System Call case ==========
; Sys-call num shd not exceed the total system calls avail
cmp
r8
,
NR_syscalls
...
...
@@ -608,6 +664,10 @@ ARC_ENTRY sys_fork_wrapper
bl
@
sys_fork
DISCARD_CALLEE_SAVED_USER
GET_CURR_THR_INFO_FLAGS
r10
btst
r10
,
TIF_SYSCALL_TRACE
bnz
tracesys_exit
b
ret_from_system_call
ARC_EXIT
sys_fork_wrapper
...
...
@@ -616,6 +676,10 @@ ARC_ENTRY sys_vfork_wrapper
bl
@
sys_vfork
DISCARD_CALLEE_SAVED_USER
GET_CURR_THR_INFO_FLAGS
r10
btst
r10
,
TIF_SYSCALL_TRACE
bnz
tracesys_exit
b
ret_from_system_call
ARC_EXIT
sys_vfork_wrapper
...
...
@@ -624,5 +688,9 @@ ARC_ENTRY sys_clone_wrapper
bl
@
sys_clone
DISCARD_CALLEE_SAVED_USER
GET_CURR_THR_INFO_FLAGS
r10
btst
r10
,
TIF_SYSCALL_TRACE
bnz
tracesys_exit
b
ret_from_system_call
ARC_EXIT
sys_clone_wrapper
arch/arc/kernel/ptrace.c
浏览文件 @
547f1125
...
...
@@ -7,6 +7,122 @@
*/
#include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <linux/regset.h>
#include <linux/unistd.h>
#include <linux/elf.h>
static
struct
callee_regs
*
task_callee_regs
(
struct
task_struct
*
tsk
)
{
struct
callee_regs
*
tmp
=
(
struct
callee_regs
*
)
tsk
->
thread
.
callee_reg
;
return
tmp
;
}
static
int
genregs_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
void
*
kbuf
,
void
__user
*
ubuf
)
{
const
struct
pt_regs
*
ptregs
=
task_pt_regs
(
target
);
const
struct
callee_regs
*
cregs
=
task_callee_regs
(
target
);
int
ret
=
0
;
unsigned
int
stop_pc_val
;
#define REG_O_CHUNK(START, END, PTR) \
if (!ret) \
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
offsetof(struct user_regs_struct, START), \
offsetof(struct user_regs_struct, END));
#define REG_O_ONE(LOC, PTR) \
if (!ret) \
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
offsetof(struct user_regs_struct, LOC), \
offsetof(struct user_regs_struct, LOC) + 4);
REG_O_CHUNK
(
scratch
,
callee
,
ptregs
);
REG_O_CHUNK
(
callee
,
efa
,
cregs
);
REG_O_CHUNK
(
efa
,
stop_pc
,
&
target
->
thread
.
fault_address
);
if
(
!
ret
)
{
if
(
in_brkpt_trap
(
ptregs
))
{
stop_pc_val
=
target
->
thread
.
fault_address
;
pr_debug
(
"
\t\t
stop_pc (brk-pt)
\n
"
);
}
else
{
stop_pc_val
=
ptregs
->
ret
;
pr_debug
(
"
\t\t
stop_pc (others)
\n
"
);
}
REG_O_ONE
(
stop_pc
,
&
stop_pc_val
);
}
return
ret
;
}
static
int
genregs_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
const
struct
pt_regs
*
ptregs
=
task_pt_regs
(
target
);
const
struct
callee_regs
*
cregs
=
task_callee_regs
(
target
);
int
ret
=
0
;
#define REG_IN_CHUNK(FIRST, NEXT, PTR) \
if (!ret) \
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
(void *)(PTR), \
offsetof(struct user_regs_struct, FIRST), \
offsetof(struct user_regs_struct, NEXT));
#define REG_IN_ONE(LOC, PTR) \
if (!ret) \
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
(void *)(PTR), \
offsetof(struct user_regs_struct, LOC), \
offsetof(struct user_regs_struct, LOC) + 4);
#define REG_IGNORE_ONE(LOC) \
if (!ret) \
ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
offsetof(struct user_regs_struct, LOC), \
offsetof(struct user_regs_struct, LOC) + 4);
/* TBD: disallow updates to STATUS32, orig_r8 etc*/
REG_IN_CHUNK
(
scratch
,
callee
,
ptregs
);
/* pt_regs[bta..orig_r8] */
REG_IN_CHUNK
(
callee
,
efa
,
cregs
);
/* callee_regs[r25..r13] */
REG_IGNORE_ONE
(
efa
);
/* efa update invalid */
REG_IN_ONE
(
stop_pc
,
&
ptregs
->
ret
);
/* stop_pc: PC update */
return
ret
;
}
enum
arc_getset
{
REGSET_GENERAL
,
};
static
const
struct
user_regset
arc_regsets
[]
=
{
[
REGSET_GENERAL
]
=
{
.
core_note_type
=
NT_PRSTATUS
,
.
n
=
ELF_NGREG
,
.
size
=
sizeof
(
unsigned
long
),
.
align
=
sizeof
(
unsigned
long
),
.
get
=
genregs_get
,
.
set
=
genregs_set
,
}
};
static
const
struct
user_regset_view
user_arc_view
=
{
.
name
=
UTS_MACHINE
,
.
e_machine
=
EM_ARCOMPACT
,
.
regsets
=
arc_regsets
,
.
n
=
ARRAY_SIZE
(
arc_regsets
)
};
const
struct
user_regset_view
*
task_user_regset_view
(
struct
task_struct
*
task
)
{
return
&
user_arc_view
;
}
void
ptrace_disable
(
struct
task_struct
*
child
)
{
...
...
@@ -16,11 +132,27 @@ long arch_ptrace(struct task_struct *child, long request,
unsigned
long
addr
,
unsigned
long
data
)
{
int
ret
=
-
EIO
;
pr_debug
(
"REQ=%ld: ADDR =0x%lx, DATA=0x%lx)
\n
"
,
request
,
addr
,
data
);
switch
(
request
)
{
default:
ret
=
ptrace_request
(
child
,
request
,
addr
,
data
);
break
;
}
return
ret
;
}
asmlinkage
int
syscall_trace_entry
(
struct
pt_regs
*
regs
)
{
if
(
tracehook_report_syscall_entry
(
regs
))
return
ULONG_MAX
;
const
struct
user_regset_view
*
task_user_regset_view
(
struct
task_struct
*
task
)
return
regs
->
r8
;
}
asmlinkage
void
syscall_trace_exit
(
struct
pt_regs
*
regs
)
{
return
(
const
struct
user_regset_view
*
)
NULL
;
tracehook_report_syscall_exit
(
regs
,
0
)
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录