Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
1e56f6d2
K
Kernel
项目概览
openeuler
/
Kernel
大约 2 年 前同步成功
通知
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看板
提交
1e56f6d2
编写于
7月 27, 2020
作者:
A
Al Viro
浏览文件
操作
浏览文件
下载
差异文件
Merge branches 'regset.x86', 'regset.ia64', 'regset.sparc' and 'regset.arm64' into work.regset
上级
b4e9c954
4dfa103e
e3fdfa37
b7e46c52
d547175b
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
588 addition
and
410 deletion
+588
-410
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/ptrace.c
+38
-29
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/ptrace.c
+98
-177
arch/sparc/kernel/ptrace_32.c
arch/sparc/kernel/ptrace_32.c
+155
-71
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/ptrace_64.c
+291
-110
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/fpu/internal.h
+0
-1
arch/x86/kernel/fpu/regset.c
arch/x86/kernel/fpu/regset.c
+0
-16
arch/x86/kernel/fpu/signal.c
arch/x86/kernel/fpu/signal.c
+6
-6
未找到文件。
arch/arm64/kernel/ptrace.c
浏览文件 @
1e56f6d2
...
@@ -1237,6 +1237,22 @@ enum compat_regset {
...
@@ -1237,6 +1237,22 @@ enum compat_regset {
REGSET_COMPAT_VFP
,
REGSET_COMPAT_VFP
,
};
};
static
inline
compat_ulong_t
compat_get_user_reg
(
struct
task_struct
*
task
,
int
idx
)
{
struct
pt_regs
*
regs
=
task_pt_regs
(
task
);
switch
(
idx
)
{
case
15
:
return
regs
->
pc
;
case
16
:
return
pstate_to_compat_psr
(
regs
->
pstate
);
case
17
:
return
regs
->
orig_x0
;
default:
return
regs
->
regs
[
idx
];
}
}
static
int
compat_gpr_get
(
struct
task_struct
*
target
,
static
int
compat_gpr_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
unsigned
int
pos
,
unsigned
int
count
,
...
@@ -1255,23 +1271,7 @@ static int compat_gpr_get(struct task_struct *target,
...
@@ -1255,23 +1271,7 @@ static int compat_gpr_get(struct task_struct *target,
return
-
EIO
;
return
-
EIO
;
for
(
i
=
0
;
i
<
num_regs
;
++
i
)
{
for
(
i
=
0
;
i
<
num_regs
;
++
i
)
{
unsigned
int
idx
=
start
+
i
;
compat_ulong_t
reg
=
compat_get_user_reg
(
target
,
start
+
i
);
compat_ulong_t
reg
;
switch
(
idx
)
{
case
15
:
reg
=
task_pt_regs
(
target
)
->
pc
;
break
;
case
16
:
reg
=
task_pt_regs
(
target
)
->
pstate
;
reg
=
pstate_to_compat_psr
(
reg
);
break
;
case
17
:
reg
=
task_pt_regs
(
target
)
->
orig_x0
;
break
;
default:
reg
=
task_pt_regs
(
target
)
->
regs
[
idx
];
}
if
(
kbuf
)
{
if
(
kbuf
)
{
memcpy
(
kbuf
,
&
reg
,
sizeof
(
reg
));
memcpy
(
kbuf
,
&
reg
,
sizeof
(
reg
));
...
@@ -1541,9 +1541,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
...
@@ -1541,9 +1541,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
else
if
(
off
==
COMPAT_PT_TEXT_END_ADDR
)
else
if
(
off
==
COMPAT_PT_TEXT_END_ADDR
)
tmp
=
tsk
->
mm
->
end_code
;
tmp
=
tsk
->
mm
->
end_code
;
else
if
(
off
<
sizeof
(
compat_elf_gregset_t
))
else
if
(
off
<
sizeof
(
compat_elf_gregset_t
))
return
copy_regset_to_user
(
tsk
,
&
user_aarch32_view
,
tmp
=
compat_get_user_reg
(
tsk
,
off
>>
2
);
REGSET_COMPAT_GPR
,
off
,
sizeof
(
compat_ulong_t
),
ret
);
else
if
(
off
>=
COMPAT_USER_SZ
)
else
if
(
off
>=
COMPAT_USER_SZ
)
return
-
EIO
;
return
-
EIO
;
else
else
...
@@ -1555,8 +1553,8 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
...
@@ -1555,8 +1553,8 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
static
int
compat_ptrace_write_user
(
struct
task_struct
*
tsk
,
compat_ulong_t
off
,
static
int
compat_ptrace_write_user
(
struct
task_struct
*
tsk
,
compat_ulong_t
off
,
compat_ulong_t
val
)
compat_ulong_t
val
)
{
{
int
ret
;
struct
pt_regs
newregs
=
*
task_pt_regs
(
tsk
)
;
mm_segment_t
old_fs
=
get_fs
()
;
unsigned
int
idx
=
off
/
4
;
if
(
off
&
3
||
off
>=
COMPAT_USER_SZ
)
if
(
off
&
3
||
off
>=
COMPAT_USER_SZ
)
return
-
EIO
;
return
-
EIO
;
...
@@ -1564,14 +1562,25 @@ static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
...
@@ -1564,14 +1562,25 @@ static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
if
(
off
>=
sizeof
(
compat_elf_gregset_t
))
if
(
off
>=
sizeof
(
compat_elf_gregset_t
))
return
0
;
return
0
;
set_fs
(
KERNEL_DS
);
switch
(
idx
)
{
ret
=
copy_regset_from_user
(
tsk
,
&
user_aarch32_view
,
case
15
:
REGSET_COMPAT_GPR
,
off
,
newregs
.
pc
=
val
;
sizeof
(
compat_ulong_t
),
break
;
&
val
);
case
16
:
set_fs
(
old_fs
);
newregs
.
pstate
=
compat_psr_to_pstate
(
val
);
break
;
case
17
:
newregs
.
orig_x0
=
val
;
break
;
default:
newregs
.
regs
[
idx
]
=
val
;
}
if
(
!
valid_user_regs
(
&
newregs
.
user_regs
,
tsk
))
return
-
EINVAL
;
return
ret
;
*
task_pt_regs
(
tsk
)
=
newregs
;
return
0
;
}
}
#ifdef CONFIG_HAVE_HW_BREAKPOINT
#ifdef CONFIG_HAVE_HW_BREAKPOINT
...
...
arch/ia64/kernel/ptrace.c
浏览文件 @
1e56f6d2
...
@@ -1273,52 +1273,43 @@ struct regset_getset {
...
@@ -1273,52 +1273,43 @@ struct regset_getset {
int
ret
;
int
ret
;
};
};
static
const
ptrdiff_t
pt_offsets
[
32
]
=
{
#define R(n) offsetof(struct pt_regs, r##n)
[
0
]
=
-
1
,
R
(
1
),
R
(
2
),
R
(
3
),
[
4
]
=
-
1
,
[
5
]
=
-
1
,
[
6
]
=
-
1
,
[
7
]
=
-
1
,
R
(
8
),
R
(
9
),
R
(
10
),
R
(
11
),
R
(
12
),
R
(
13
),
R
(
14
),
R
(
15
),
R
(
16
),
R
(
17
),
R
(
18
),
R
(
19
),
R
(
20
),
R
(
21
),
R
(
22
),
R
(
23
),
R
(
24
),
R
(
25
),
R
(
26
),
R
(
27
),
R
(
28
),
R
(
29
),
R
(
30
),
R
(
31
),
#undef R
};
static
int
static
int
access_elf_gpreg
(
struct
task_struct
*
target
,
struct
unw_frame_info
*
info
,
access_elf_gpreg
(
struct
task_struct
*
target
,
struct
unw_frame_info
*
info
,
unsigned
long
addr
,
unsigned
long
*
data
,
int
write_access
)
unsigned
long
addr
,
unsigned
long
*
data
,
int
write_access
)
{
{
struct
pt_regs
*
pt
;
struct
pt_regs
*
pt
=
task_pt_regs
(
target
);
unsigned
long
*
ptr
=
NULL
;
unsigned
reg
=
addr
/
sizeof
(
unsigned
long
);
int
ret
;
ptrdiff_t
d
=
pt_offsets
[
reg
];
char
nat
=
0
;
pt
=
task_pt_regs
(
target
);
if
(
d
>=
0
)
{
switch
(
addr
)
{
unsigned
long
*
ptr
=
(
void
*
)
pt
+
d
;
case
ELF_GR_OFFSET
(
1
):
if
(
write_access
)
ptr
=
&
pt
->
r1
;
*
ptr
=
*
data
;
break
;
else
case
ELF_GR_OFFSET
(
2
):
*
data
=
*
ptr
;
case
ELF_GR_OFFSET
(
3
):
return
0
;
ptr
=
(
void
*
)
&
pt
->
r2
+
(
addr
-
ELF_GR_OFFSET
(
2
));
}
else
{
break
;
char
nat
=
0
;
case
ELF_GR_OFFSET
(
4
)
...
ELF_GR_OFFSET
(
7
):
if
(
write_access
)
{
if
(
write_access
)
{
/* read NaT bit first: */
/* read NaT bit first: */
unsigned
long
dummy
;
unsigned
long
dummy
;
int
ret
=
unw_get_gr
(
info
,
reg
,
&
dummy
,
&
nat
);
ret
=
unw_get_gr
(
info
,
addr
/
8
,
&
dummy
,
&
nat
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
}
}
return
unw_access_gr
(
info
,
addr
/
8
,
data
,
&
nat
,
write_access
);
return
unw_access_gr
(
info
,
reg
,
data
,
&
nat
,
write_access
);
case
ELF_GR_OFFSET
(
8
)
...
ELF_GR_OFFSET
(
11
):
ptr
=
(
void
*
)
&
pt
->
r8
+
addr
-
ELF_GR_OFFSET
(
8
);
break
;
case
ELF_GR_OFFSET
(
12
):
case
ELF_GR_OFFSET
(
13
):
ptr
=
(
void
*
)
&
pt
->
r12
+
addr
-
ELF_GR_OFFSET
(
12
);
break
;
case
ELF_GR_OFFSET
(
14
):
ptr
=
&
pt
->
r14
;
break
;
case
ELF_GR_OFFSET
(
15
):
ptr
=
&
pt
->
r15
;
}
}
if
(
write_access
)
*
ptr
=
*
data
;
else
*
data
=
*
ptr
;
return
0
;
}
}
static
int
static
int
...
@@ -1490,7 +1481,7 @@ static int
...
@@ -1490,7 +1481,7 @@ static int
access_elf_reg
(
struct
task_struct
*
target
,
struct
unw_frame_info
*
info
,
access_elf_reg
(
struct
task_struct
*
target
,
struct
unw_frame_info
*
info
,
unsigned
long
addr
,
unsigned
long
*
data
,
int
write_access
)
unsigned
long
addr
,
unsigned
long
*
data
,
int
write_access
)
{
{
if
(
addr
>=
ELF_GR_OFFSET
(
1
)
&&
addr
<=
ELF_GR_OFFSET
(
15
))
if
(
addr
>=
ELF_GR_OFFSET
(
1
)
&&
addr
<=
ELF_GR_OFFSET
(
31
))
return
access_elf_gpreg
(
target
,
info
,
addr
,
data
,
write_access
);
return
access_elf_gpreg
(
target
,
info
,
addr
,
data
,
write_access
);
else
if
(
addr
>=
ELF_BR_OFFSET
(
0
)
&&
addr
<=
ELF_BR_OFFSET
(
7
))
else
if
(
addr
>=
ELF_BR_OFFSET
(
0
)
&&
addr
<=
ELF_BR_OFFSET
(
7
))
return
access_elf_breg
(
target
,
info
,
addr
,
data
,
write_access
);
return
access_elf_breg
(
target
,
info
,
addr
,
data
,
write_access
);
...
@@ -1500,10 +1491,7 @@ access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
...
@@ -1500,10 +1491,7 @@ access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
void
do_gpregs_get
(
struct
unw_frame_info
*
info
,
void
*
arg
)
void
do_gpregs_get
(
struct
unw_frame_info
*
info
,
void
*
arg
)
{
{
struct
pt_regs
*
pt
;
struct
regset_getset
*
dst
=
arg
;
struct
regset_getset
*
dst
=
arg
;
elf_greg_t
tmp
[
16
];
unsigned
int
i
,
index
,
min_copy
;
if
(
unw_unwind_to_user
(
info
)
<
0
)
if
(
unw_unwind_to_user
(
info
)
<
0
)
return
;
return
;
...
@@ -1526,160 +1514,70 @@ void do_gpregs_get(struct unw_frame_info *info, void *arg)
...
@@ -1526,160 +1514,70 @@ void do_gpregs_get(struct unw_frame_info *info, void *arg)
&
dst
->
u
.
get
.
kbuf
,
&
dst
->
u
.
get
.
kbuf
,
&
dst
->
u
.
get
.
ubuf
,
&
dst
->
u
.
get
.
ubuf
,
0
,
ELF_GR_OFFSET
(
1
));
0
,
ELF_GR_OFFSET
(
1
));
if
(
dst
->
ret
||
dst
->
count
==
0
)
if
(
dst
->
ret
)
return
;
}
/* gr1 - gr15 */
if
(
dst
->
count
>
0
&&
dst
->
pos
<
ELF_GR_OFFSET
(
16
))
{
index
=
(
dst
->
pos
-
ELF_GR_OFFSET
(
1
))
/
sizeof
(
elf_greg_t
);
min_copy
=
ELF_GR_OFFSET
(
16
)
>
(
dst
->
pos
+
dst
->
count
)
?
(
dst
->
pos
+
dst
->
count
)
:
ELF_GR_OFFSET
(
16
);
for
(
i
=
dst
->
pos
;
i
<
min_copy
;
i
+=
sizeof
(
elf_greg_t
),
index
++
)
if
(
access_elf_reg
(
dst
->
target
,
info
,
i
,
&
tmp
[
index
],
0
)
<
0
)
{
dst
->
ret
=
-
EIO
;
return
;
}
dst
->
ret
=
user_regset_copyout
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
get
.
kbuf
,
&
dst
->
u
.
get
.
ubuf
,
tmp
,
ELF_GR_OFFSET
(
1
),
ELF_GR_OFFSET
(
16
));
if
(
dst
->
ret
||
dst
->
count
==
0
)
return
;
}
/* r16-r31 */
if
(
dst
->
count
>
0
&&
dst
->
pos
<
ELF_NAT_OFFSET
)
{
pt
=
task_pt_regs
(
dst
->
target
);
dst
->
ret
=
user_regset_copyout
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
get
.
kbuf
,
&
dst
->
u
.
get
.
ubuf
,
&
pt
->
r16
,
ELF_GR_OFFSET
(
16
),
ELF_NAT_OFFSET
);
if
(
dst
->
ret
||
dst
->
count
==
0
)
return
;
return
;
}
}
/* nat, pr, b0 - b7 */
while
(
dst
->
count
&&
dst
->
pos
<
ELF_AR_END_OFFSET
)
{
if
(
dst
->
count
>
0
&&
dst
->
pos
<
ELF_CR_IIP_OFFSET
)
{
unsigned
int
n
,
from
,
to
;
index
=
(
dst
->
pos
-
ELF_NAT_OFFSET
)
/
sizeof
(
elf_greg_t
);
elf_greg_t
tmp
[
16
];
min_copy
=
ELF_CR_IIP_OFFSET
>
(
dst
->
pos
+
dst
->
count
)
?
(
dst
->
pos
+
dst
->
count
)
:
ELF_CR_IIP_OFFSET
;
from
=
dst
->
pos
;
for
(
i
=
dst
->
pos
;
i
<
min_copy
;
i
+=
sizeof
(
elf_greg_t
),
to
=
from
+
min
(
dst
->
count
,
(
unsigned
)
sizeof
(
tmp
));
index
++
)
if
(
to
>
ELF_AR_END_OFFSET
)
if
(
access_elf_reg
(
dst
->
target
,
info
,
i
,
to
=
ELF_AR_END_OFFSET
;
&
tmp
[
index
],
0
)
<
0
)
{
for
(
n
=
0
;
from
<
to
;
from
+=
sizeof
(
elf_greg_t
),
n
++
)
{
if
(
access_elf_reg
(
dst
->
target
,
info
,
from
,
&
tmp
[
n
],
0
)
<
0
)
{
dst
->
ret
=
-
EIO
;
dst
->
ret
=
-
EIO
;
return
;
return
;
}
}
}
dst
->
ret
=
user_regset_copyout
(
&
dst
->
pos
,
&
dst
->
count
,
dst
->
ret
=
user_regset_copyout
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
get
.
kbuf
,
&
dst
->
u
.
get
.
ubuf
,
tmp
,
&
dst
->
u
.
get
.
kbuf
,
&
dst
->
u
.
get
.
ubuf
,
tmp
,
ELF_NAT_OFFSET
,
ELF_CR_IIP_OFFSET
);
dst
->
pos
,
to
);
if
(
dst
->
ret
||
dst
->
count
==
0
)
if
(
dst
->
ret
)
return
;
return
;
}
}
/* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
* ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
*/
if
(
dst
->
count
>
0
&&
dst
->
pos
<
(
ELF_AR_END_OFFSET
))
{
index
=
(
dst
->
pos
-
ELF_CR_IIP_OFFSET
)
/
sizeof
(
elf_greg_t
);
min_copy
=
ELF_AR_END_OFFSET
>
(
dst
->
pos
+
dst
->
count
)
?
(
dst
->
pos
+
dst
->
count
)
:
ELF_AR_END_OFFSET
;
for
(
i
=
dst
->
pos
;
i
<
min_copy
;
i
+=
sizeof
(
elf_greg_t
),
index
++
)
if
(
access_elf_reg
(
dst
->
target
,
info
,
i
,
&
tmp
[
index
],
0
)
<
0
)
{
dst
->
ret
=
-
EIO
;
return
;
}
dst
->
ret
=
user_regset_copyout
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
get
.
kbuf
,
&
dst
->
u
.
get
.
ubuf
,
tmp
,
ELF_CR_IIP_OFFSET
,
ELF_AR_END_OFFSET
);
}
}
}
void
do_gpregs_set
(
struct
unw_frame_info
*
info
,
void
*
arg
)
void
do_gpregs_set
(
struct
unw_frame_info
*
info
,
void
*
arg
)
{
{
struct
pt_regs
*
pt
;
struct
regset_getset
*
dst
=
arg
;
struct
regset_getset
*
dst
=
arg
;
elf_greg_t
tmp
[
16
];
unsigned
int
i
,
index
;
if
(
unw_unwind_to_user
(
info
)
<
0
)
if
(
unw_unwind_to_user
(
info
)
<
0
)
return
;
return
;
if
(
!
dst
->
count
)
return
;
/* Skip r0 */
/* Skip r0 */
if
(
dst
->
count
>
0
&&
dst
->
pos
<
ELF_GR_OFFSET
(
1
))
{
if
(
dst
->
pos
<
ELF_GR_OFFSET
(
1
))
{
dst
->
ret
=
user_regset_copyin_ignore
(
&
dst
->
pos
,
&
dst
->
count
,
dst
->
ret
=
user_regset_copyin_ignore
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
set
.
kbuf
,
&
dst
->
u
.
set
.
kbuf
,
&
dst
->
u
.
set
.
ubuf
,
&
dst
->
u
.
set
.
ubuf
,
0
,
ELF_GR_OFFSET
(
1
));
0
,
ELF_GR_OFFSET
(
1
));
if
(
dst
->
ret
||
dst
->
count
==
0
)
return
;
}
/* gr1-gr15 */
if
(
dst
->
count
>
0
&&
dst
->
pos
<
ELF_GR_OFFSET
(
16
))
{
i
=
dst
->
pos
;
index
=
(
dst
->
pos
-
ELF_GR_OFFSET
(
1
))
/
sizeof
(
elf_greg_t
);
dst
->
ret
=
user_regset_copyin
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
set
.
kbuf
,
&
dst
->
u
.
set
.
ubuf
,
tmp
,
ELF_GR_OFFSET
(
1
),
ELF_GR_OFFSET
(
16
));
if
(
dst
->
ret
)
if
(
dst
->
ret
)
return
;
return
;
for
(
;
i
<
dst
->
pos
;
i
+=
sizeof
(
elf_greg_t
),
index
++
)
if
(
access_elf_reg
(
dst
->
target
,
info
,
i
,
&
tmp
[
index
],
1
)
<
0
)
{
dst
->
ret
=
-
EIO
;
return
;
}
if
(
dst
->
count
==
0
)
return
;
}
}
/* gr16-gr31 */
while
(
dst
->
count
&&
dst
->
pos
<
ELF_AR_END_OFFSET
)
{
if
(
dst
->
count
>
0
&&
dst
->
pos
<
ELF_NAT_OFFSET
)
{
unsigned
int
n
,
from
,
to
;
pt
=
task_pt_regs
(
dst
->
target
);
elf_greg_t
tmp
[
16
];
dst
->
ret
=
user_regset_copyin
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
set
.
kbuf
,
&
dst
->
u
.
set
.
ubuf
,
&
pt
->
r16
,
ELF_GR_OFFSET
(
16
),
ELF_NAT_OFFSET
);
if
(
dst
->
ret
||
dst
->
count
==
0
)
return
;
}
/* nat, pr, b0 - b7 */
if
(
dst
->
count
>
0
&&
dst
->
pos
<
ELF_CR_IIP_OFFSET
)
{
i
=
dst
->
pos
;
index
=
(
dst
->
pos
-
ELF_NAT_OFFSET
)
/
sizeof
(
elf_greg_t
);
dst
->
ret
=
user_regset_copyin
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
set
.
kbuf
,
&
dst
->
u
.
set
.
ubuf
,
tmp
,
ELF_NAT_OFFSET
,
ELF_CR_IIP_OFFSET
);
if
(
dst
->
ret
)
return
;
for
(;
i
<
dst
->
pos
;
i
+=
sizeof
(
elf_greg_t
),
index
++
)
if
(
access_elf_reg
(
dst
->
target
,
info
,
i
,
&
tmp
[
index
],
1
)
<
0
)
{
dst
->
ret
=
-
EIO
;
return
;
}
if
(
dst
->
count
==
0
)
return
;
}
/* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
from
=
dst
->
pos
;
* ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
to
=
from
+
sizeof
(
tmp
);
*/
if
(
to
>
ELF_AR_END_OFFSET
)
if
(
dst
->
count
>
0
&&
dst
->
pos
<
(
ELF_AR_END_OFFSET
))
{
to
=
ELF_AR_END_OFFSET
;
i
=
dst
->
pos
;
/* get up to 16 values */
index
=
(
dst
->
pos
-
ELF_CR_IIP_OFFSET
)
/
sizeof
(
elf_greg_t
);
dst
->
ret
=
user_regset_copyin
(
&
dst
->
pos
,
&
dst
->
count
,
dst
->
ret
=
user_regset_copyin
(
&
dst
->
pos
,
&
dst
->
count
,
&
dst
->
u
.
set
.
kbuf
,
&
dst
->
u
.
set
.
ubuf
,
tmp
,
&
dst
->
u
.
set
.
kbuf
,
&
dst
->
u
.
set
.
ubuf
,
tmp
,
ELF_CR_IIP_OFFSET
,
ELF_AR_END_OFFSET
);
from
,
to
);
if
(
dst
->
ret
)
if
(
dst
->
ret
)
return
;
return
;
for
(
;
i
<
dst
->
pos
;
i
+=
sizeof
(
elf_greg_t
),
index
++
)
/* now copy them into registers */
if
(
access_elf_reg
(
dst
->
target
,
info
,
i
,
for
(
n
=
0
;
from
<
dst
->
pos
;
from
+=
sizeof
(
elf_greg_t
),
n
++
)
&
tmp
[
index
],
1
)
<
0
)
{
if
(
access_elf_reg
(
dst
->
target
,
info
,
from
,
&
tmp
[
n
],
1
)
<
0
)
{
dst
->
ret
=
-
EIO
;
dst
->
ret
=
-
EIO
;
return
;
return
;
}
}
...
@@ -1913,7 +1811,6 @@ access_uarea(struct task_struct *child, unsigned long addr,
...
@@ -1913,7 +1811,6 @@ access_uarea(struct task_struct *child, unsigned long addr,
unsigned
long
*
data
,
int
write_access
)
unsigned
long
*
data
,
int
write_access
)
{
{
unsigned
int
pos
=
-
1
;
/* an invalid value */
unsigned
int
pos
=
-
1
;
/* an invalid value */
int
ret
;
unsigned
long
*
ptr
,
regnum
;
unsigned
long
*
ptr
,
regnum
;
if
((
addr
&
0x7
)
!=
0
)
{
if
((
addr
&
0x7
)
!=
0
)
{
...
@@ -1945,14 +1842,39 @@ access_uarea(struct task_struct *child, unsigned long addr,
...
@@ -1945,14 +1842,39 @@ access_uarea(struct task_struct *child, unsigned long addr,
}
}
if
(
pos
!=
-
1
)
{
if
(
pos
!=
-
1
)
{
if
(
write_access
)
unsigned
reg
=
pos
/
sizeof
(
elf_fpreg_t
);
ret
=
fpregs_set
(
child
,
NULL
,
pos
,
int
which_half
=
(
pos
/
sizeof
(
unsigned
long
))
&
1
;
sizeof
(
unsigned
long
),
data
,
NULL
);
else
if
(
reg
<
32
)
{
/* fr2-fr31 */
ret
=
fpregs_get
(
child
,
NULL
,
pos
,
struct
unw_frame_info
info
;
sizeof
(
unsigned
long
),
data
,
NULL
);
elf_fpreg_t
fpreg
;
if
(
ret
!=
0
)
return
-
1
;
memset
(
&
info
,
0
,
sizeof
(
info
));
unw_init_from_blocked_task
(
&
info
,
child
);
if
(
unw_unwind_to_user
(
&
info
)
<
0
)
return
0
;
if
(
unw_get_fr
(
&
info
,
reg
,
&
fpreg
))
return
-
1
;
if
(
write_access
)
{
fpreg
.
u
.
bits
[
which_half
]
=
*
data
;
if
(
unw_set_fr
(
&
info
,
reg
,
fpreg
))
return
-
1
;
}
else
{
*
data
=
fpreg
.
u
.
bits
[
which_half
];
}
}
else
{
/* fph */
elf_fpreg_t
*
p
=
&
child
->
thread
.
fph
[
reg
-
32
];
unsigned
long
*
bits
=
&
p
->
u
.
bits
[
which_half
];
ia64_sync_fph
(
child
);
if
(
write_access
)
*
bits
=
*
data
;
else
if
(
child
->
thread
.
flags
&
IA64_THREAD_FPH_VALID
)
*
data
=
*
bits
;
else
*
data
=
0
;
}
return
0
;
return
0
;
}
}
...
@@ -2038,15 +1960,14 @@ access_uarea(struct task_struct *child, unsigned long addr,
...
@@ -2038,15 +1960,14 @@ access_uarea(struct task_struct *child, unsigned long addr,
}
}
if
(
pos
!=
-
1
)
{
if
(
pos
!=
-
1
)
{
if
(
write_access
)
struct
unw_frame_info
info
;
ret
=
gpregs_set
(
child
,
NULL
,
pos
,
sizeof
(
unsigned
long
),
data
,
NULL
);
memset
(
&
info
,
0
,
sizeof
(
info
));
else
unw_init_from_blocked_task
(
&
info
,
child
);
ret
=
gpregs_get
(
child
,
NULL
,
pos
,
if
(
unw_unwind_to_user
(
&
info
)
<
0
)
sizeof
(
unsigned
long
),
data
,
NULL
);
return
0
;
if
(
ret
!=
0
)
return
-
1
;
return
access_elf_reg
(
child
,
&
info
,
pos
,
data
,
write_access
);
return
0
;
}
}
/* access debug registers */
/* access debug registers */
...
...
arch/sparc/kernel/ptrace_32.c
浏览文件 @
1e56f6d2
...
@@ -99,15 +99,13 @@ static int genregs32_get(struct task_struct *target,
...
@@ -99,15 +99,13 @@ static int genregs32_get(struct task_struct *target,
if
(
ret
||
!
count
)
if
(
ret
||
!
count
)
return
ret
;
return
ret
;
if
(
pos
<
32
*
sizeof
(
u32
))
{
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
return
-
EFAULT
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
uregs
,
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
if
(
ret
)
if
(
ret
||
!
count
)
return
ret
;
return
ret
;
}
uregs
[
0
]
=
regs
->
psr
;
uregs
[
0
]
=
regs
->
psr
;
uregs
[
1
]
=
regs
->
pc
;
uregs
[
1
]
=
regs
->
pc
;
...
@@ -139,19 +137,18 @@ static int genregs32_set(struct task_struct *target,
...
@@ -139,19 +137,18 @@ static int genregs32_set(struct task_struct *target,
if
(
ret
||
!
count
)
if
(
ret
||
!
count
)
return
ret
;
return
ret
;
if
(
pos
<
32
*
sizeof
(
u32
))
{
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
if
(
regwindow32_get
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
return
-
EFAULT
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
uregs
,
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
16
*
sizeof
(
u32
),
32
*
sizeof
(
u32
));
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
if
(
regwindow32_set
(
target
,
regs
,
uregs
))
if
(
regwindow32_set
(
target
,
regs
,
uregs
))
return
-
EFAULT
;
return
-
EFAULT
;
if
(
!
count
)
if
(
!
count
)
return
0
;
return
0
;
}
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
psr
,
&
psr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
...
@@ -243,13 +240,11 @@ static int fpregs32_set(struct task_struct *target,
...
@@ -243,13 +240,11 @@ static int fpregs32_set(struct task_struct *target,
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
32
*
sizeof
(
u32
),
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
33
*
sizeof
(
u32
));
if
(
!
ret
&&
count
>
0
)
{
if
(
!
ret
)
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
target
->
thread
.
fsr
,
&
target
->
thread
.
fsr
,
33
*
sizeof
(
u32
),
33
*
sizeof
(
u32
),
34
*
sizeof
(
u32
));
34
*
sizeof
(
u32
));
}
if
(
!
ret
)
if
(
!
ret
)
ret
=
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
ret
=
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
34
*
sizeof
(
u32
),
-
1
);
34
*
sizeof
(
u32
),
-
1
);
...
@@ -288,6 +283,125 @@ static const struct user_regset sparc32_regsets[] = {
...
@@ -288,6 +283,125 @@ static const struct user_regset sparc32_regsets[] = {
},
},
};
};
static
int
getregs_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
*
regs
=
target
->
thread
.
kregs
;
u32
v
[
4
];
int
ret
;
if
(
target
==
current
)
flush_user_windows
();
v
[
0
]
=
regs
->
psr
;
v
[
1
]
=
regs
->
pc
;
v
[
2
]
=
regs
->
npc
;
v
[
3
]
=
regs
->
y
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
v
,
0
*
sizeof
(
u32
),
4
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
return
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
+
1
,
4
*
sizeof
(
u32
),
19
*
sizeof
(
u32
));
}
static
int
setregs_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
struct
pt_regs
*
regs
=
target
->
thread
.
kregs
;
u32
v
[
4
];
int
ret
;
if
(
target
==
current
)
flush_user_windows
();
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
v
,
0
,
4
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
regs
->
psr
=
(
regs
->
psr
&
~
(
PSR_ICC
|
PSR_SYSCALL
))
|
(
v
[
0
]
&
(
PSR_ICC
|
PSR_SYSCALL
));
regs
->
pc
=
v
[
1
];
regs
->
npc
=
v
[
2
];
regs
->
y
=
v
[
3
];
return
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
+
1
,
4
*
sizeof
(
u32
)
,
19
*
sizeof
(
u32
));
}
static
int
getfpregs_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
void
*
kbuf
,
void
__user
*
ubuf
)
{
const
unsigned
long
*
fpregs
=
target
->
thread
.
float_regs
;
int
ret
=
0
;
#if 0
if (target == current)
save_and_clear_fpu();
#endif
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
target
->
thread
.
fsr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
return
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
33
*
sizeof
(
u32
),
68
*
sizeof
(
u32
));
}
static
int
setfpregs_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
unsigned
long
*
fpregs
=
target
->
thread
.
float_regs
;
int
ret
;
#if 0
if (target == current)
save_and_clear_fpu();
#endif
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
return
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
target
->
thread
.
fsr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
}
static
const
struct
user_regset
ptrace32_regsets
[]
=
{
[
REGSET_GENERAL
]
=
{
.
n
=
19
,
.
size
=
sizeof
(
u32
),
.
get
=
getregs_get
,
.
set
=
setregs_set
,
},
[
REGSET_FP
]
=
{
.
n
=
68
,
.
size
=
sizeof
(
u32
),
.
get
=
getfpregs_get
,
.
set
=
setfpregs_set
,
},
};
static
const
struct
user_regset_view
ptrace32_view
=
{
.
regsets
=
ptrace32_regsets
,
.
n
=
ARRAY_SIZE
(
ptrace32_regsets
)
};
static
const
struct
user_regset_view
user_sparc32_view
=
{
static
const
struct
user_regset_view
user_sparc32_view
=
{
.
name
=
"sparc"
,
.
e_machine
=
EM_SPARC
,
.
name
=
"sparc"
,
.
e_machine
=
EM_SPARC
,
.
regsets
=
sparc32_regsets
,
.
n
=
ARRAY_SIZE
(
sparc32_regsets
)
.
regsets
=
sparc32_regsets
,
.
n
=
ARRAY_SIZE
(
sparc32_regsets
)
...
@@ -315,74 +429,44 @@ long arch_ptrace(struct task_struct *child, long request,
...
@@ -315,74 +429,44 @@ long arch_ptrace(struct task_struct *child, long request,
{
{
unsigned
long
addr2
=
current
->
thread
.
kregs
->
u_regs
[
UREG_I4
];
unsigned
long
addr2
=
current
->
thread
.
kregs
->
u_regs
[
UREG_I4
];
void
__user
*
addr2p
;
void
__user
*
addr2p
;
const
struct
user_regset_view
*
view
;
struct
pt_regs
__user
*
pregs
;
struct
pt_regs
__user
*
pregs
;
struct
fps
__user
*
fps
;
struct
fps
__user
*
fps
;
int
ret
;
int
ret
;
view
=
task_user_regset_view
(
current
);
addr2p
=
(
void
__user
*
)
addr2
;
addr2p
=
(
void
__user
*
)
addr2
;
pregs
=
(
struct
pt_regs
__user
*
)
addr
;
pregs
=
(
struct
pt_regs
__user
*
)
addr
;
fps
=
(
struct
fps
__user
*
)
addr
;
fps
=
(
struct
fps
__user
*
)
addr
;
switch
(
request
)
{
switch
(
request
)
{
case
PTRACE_GETREGS
:
{
case
PTRACE_GETREGS
:
{
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
ret
=
copy_regset_to_user
(
child
,
&
ptrace32_view
,
32
*
sizeof
(
u32
),
REGSET_GENERAL
,
0
,
4
*
sizeof
(
u32
),
19
*
sizeof
(
u32
),
&
pregs
->
psr
);
pregs
);
if
(
!
ret
)
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
1
*
sizeof
(
u32
),
15
*
sizeof
(
u32
),
&
pregs
->
u_regs
[
0
]);
break
;
break
;
}
}
case
PTRACE_SETREGS
:
{
case
PTRACE_SETREGS
:
{
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
ret
=
copy_regset_from_user
(
child
,
&
ptrace32_view
,
32
*
sizeof
(
u32
),
REGSET_GENERAL
,
0
,
4
*
sizeof
(
u32
),
19
*
sizeof
(
u32
),
&
pregs
->
psr
);
pregs
);
if
(
!
ret
)
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
1
*
sizeof
(
u32
),
15
*
sizeof
(
u32
),
&
pregs
->
u_regs
[
0
]);
break
;
break
;
}
}
case
PTRACE_GETFPREGS
:
{
case
PTRACE_GETFPREGS
:
{
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_FP
,
ret
=
copy_regset_to_user
(
child
,
&
ptrace32_view
,
0
*
sizeof
(
u32
),
REGSET_FP
,
0
,
32
*
sizeof
(
u32
),
68
*
sizeof
(
u32
),
&
fps
->
regs
[
0
]);
fps
);
if
(
!
ret
)
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_FP
,
33
*
sizeof
(
u32
),
1
*
sizeof
(
u32
),
&
fps
->
fsr
);
if
(
!
ret
)
{
if
(
__put_user
(
0
,
&
fps
->
fpqd
)
||
__put_user
(
0
,
&
fps
->
flags
)
||
__put_user
(
0
,
&
fps
->
extra
)
||
clear_user
(
fps
->
fpq
,
sizeof
(
fps
->
fpq
)))
ret
=
-
EFAULT
;
}
break
;
break
;
}
}
case
PTRACE_SETFPREGS
:
{
case
PTRACE_SETFPREGS
:
{
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_FP
,
ret
=
copy_regset_from_user
(
child
,
&
ptrace32_view
,
0
*
sizeof
(
u32
),
REGSET_FP
,
0
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
),
&
fps
->
regs
[
0
]);
fps
);
if
(
!
ret
)
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_FP
,
33
*
sizeof
(
u32
),
1
*
sizeof
(
u32
),
&
fps
->
fsr
);
break
;
break
;
}
}
...
...
arch/sparc/kernel/ptrace_64.c
浏览文件 @
1e56f6d2
...
@@ -258,7 +258,7 @@ static int genregs64_get(struct task_struct *target,
...
@@ -258,7 +258,7 @@ static int genregs64_get(struct task_struct *target,
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
,
regs
->
u_regs
,
0
,
16
*
sizeof
(
u64
));
0
,
16
*
sizeof
(
u64
));
if
(
!
ret
&&
count
&&
pos
<
(
32
*
sizeof
(
u64
))
)
{
if
(
!
ret
&&
count
)
{
struct
reg_window
window
;
struct
reg_window
window
;
if
(
regwindow64_get
(
target
,
regs
,
&
window
))
if
(
regwindow64_get
(
target
,
regs
,
&
window
))
...
@@ -506,6 +506,112 @@ static const struct user_regset sparc64_regsets[] = {
...
@@ -506,6 +506,112 @@ static const struct user_regset sparc64_regsets[] = {
},
},
};
};
static
int
getregs64_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
*
regs
=
task_pt_regs
(
target
);
int
ret
;
if
(
target
==
current
)
flushw_user
();
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
+
1
,
0
,
15
*
sizeof
(
u64
));
if
(
!
ret
)
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
15
*
sizeof
(
u64
),
16
*
sizeof
(
u64
));
if
(
!
ret
)
{
/* TSTATE, TPC, TNPC */
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
regs
->
tstate
,
16
*
sizeof
(
u64
),
19
*
sizeof
(
u64
));
}
if
(
!
ret
)
{
unsigned
long
y
=
regs
->
y
;
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
y
,
19
*
sizeof
(
u64
),
20
*
sizeof
(
u64
));
}
return
ret
;
}
static
int
setregs64_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
unsigned
long
y
=
regs
->
y
;
unsigned
long
tstate
;
int
ret
;
if
(
target
==
current
)
flushw_user
();
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
regs
->
u_regs
+
1
,
0
*
sizeof
(
u64
),
15
*
sizeof
(
u64
));
if
(
ret
)
return
ret
;
ret
=
user_regset_copyin_ignore
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
15
*
sizeof
(
u64
),
16
*
sizeof
(
u64
));
if
(
ret
)
return
ret
;
/* TSTATE */
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
tstate
,
16
*
sizeof
(
u64
),
17
*
sizeof
(
u64
));
if
(
ret
)
return
ret
;
/* Only the condition codes and the "in syscall"
* state can be modified in the %tstate register.
*/
tstate
&=
(
TSTATE_ICC
|
TSTATE_XCC
|
TSTATE_SYSCALL
);
regs
->
tstate
&=
~
(
TSTATE_ICC
|
TSTATE_XCC
|
TSTATE_SYSCALL
);
regs
->
tstate
|=
tstate
;
/* TPC, TNPC */
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
regs
->
tpc
,
17
*
sizeof
(
u64
),
19
*
sizeof
(
u64
));
if
(
ret
)
return
ret
;
/* Y */
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
y
,
19
*
sizeof
(
u64
),
20
*
sizeof
(
u64
));
if
(
!
ret
)
regs
->
y
=
y
;
return
ret
;
}
static
const
struct
user_regset
ptrace64_regsets
[]
=
{
/* Format is:
* G1 --> G7
* O0 --> O7
* 0
* TSTATE, TPC, TNPC, Y
*/
[
REGSET_GENERAL
]
=
{
.
n
=
20
,
.
size
=
sizeof
(
u64
),
.
get
=
getregs64_get
,
.
set
=
setregs64_set
,
},
};
static
const
struct
user_regset_view
ptrace64_view
=
{
.
regsets
=
ptrace64_regsets
,
.
n
=
ARRAY_SIZE
(
ptrace64_regsets
)
};
static
const
struct
user_regset_view
user_sparc64_view
=
{
static
const
struct
user_regset_view
user_sparc64_view
=
{
.
name
=
"sparc64"
,
.
e_machine
=
EM_SPARCV9
,
.
name
=
"sparc64"
,
.
e_machine
=
EM_SPARCV9
,
.
regsets
=
sparc64_regsets
,
.
n
=
ARRAY_SIZE
(
sparc64_regsets
)
.
regsets
=
sparc64_regsets
,
.
n
=
ARRAY_SIZE
(
sparc64_regsets
)
...
@@ -518,10 +624,10 @@ static int genregs32_get(struct task_struct *target,
...
@@ -518,10 +624,10 @@ static int genregs32_get(struct task_struct *target,
void
*
kbuf
,
void
__user
*
ubuf
)
void
*
kbuf
,
void
__user
*
ubuf
)
{
{
const
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
const
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
compat_ulong_t
__user
*
reg_window
;
compat_ulong_t
*
k
=
kbuf
;
compat_ulong_t
*
k
=
kbuf
;
compat_ulong_t
__user
*
u
=
ubuf
;
compat_ulong_t
__user
*
u
=
ubuf
;
compat_ulong_t
reg
;
u32
uregs
[
16
];
u32
reg
;
if
(
target
==
current
)
if
(
target
==
current
)
flushw_user
();
flushw_user
();
...
@@ -533,52 +639,25 @@ static int genregs32_get(struct task_struct *target,
...
@@ -533,52 +639,25 @@ static int genregs32_get(struct task_struct *target,
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
*
k
++
=
regs
->
u_regs
[
pos
++
];
*
k
++
=
regs
->
u_regs
[
pos
++
];
reg_window
=
(
compat_ulong_t
__user
*
)
regs
->
u_regs
[
UREG_I6
];
if
(
count
)
{
reg_window
-=
16
;
if
(
get_from_target
(
target
,
regs
->
u_regs
[
UREG_I6
],
if
(
target
==
current
)
{
uregs
,
sizeof
(
uregs
)))
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
return
-
EFAULT
;
if
(
get_user
(
*
k
++
,
&
reg_window
[
pos
++
]))
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
return
-
EFAULT
;
*
k
++
=
uregs
[
pos
++
-
16
];
}
}
else
{
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
if
(
access_process_vm
(
target
,
(
unsigned
long
)
&
reg_window
[
pos
],
k
,
sizeof
(
*
k
),
FOLL_FORCE
)
!=
sizeof
(
*
k
))
return
-
EFAULT
;
k
++
;
pos
++
;
}
}
}
}
else
{
}
else
{
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
{
for
(;
count
>
0
&&
pos
<
16
;
count
--
)
if
(
put_user
((
compat_ulong_t
)
regs
->
u_regs
[
pos
++
],
u
++
))
if
(
put_user
((
compat_ulong_t
)
regs
->
u_regs
[
pos
++
],
u
++
))
return
-
EFAULT
;
return
-
EFAULT
;
}
if
(
count
)
{
if
(
get_from_target
(
target
,
regs
->
u_regs
[
UREG_I6
],
reg_window
=
(
compat_ulong_t
__user
*
)
regs
->
u_regs
[
UREG_I6
];
uregs
,
sizeof
(
uregs
)))
reg_window
-=
16
;
return
-
EFAULT
;
if
(
target
==
current
)
{
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
if
(
put_user
(
uregs
[
pos
++
-
16
],
u
++
))
if
(
get_user
(
reg
,
&
reg_window
[
pos
++
])
||
put_user
(
reg
,
u
++
))
return
-
EFAULT
;
}
}
else
{
for
(;
count
>
0
&&
pos
<
32
;
count
--
)
{
if
(
access_process_vm
(
target
,
(
unsigned
long
)
&
reg_window
[
pos
++
],
&
reg
,
sizeof
(
reg
),
FOLL_FORCE
)
!=
sizeof
(
reg
))
return
-
EFAULT
;
if
(
put_user
(
reg
,
u
++
))
return
-
EFAULT
;
return
-
EFAULT
;
}
}
}
}
}
while
(
count
>
0
)
{
while
(
count
>
0
)
{
...
@@ -867,6 +946,150 @@ static const struct user_regset sparc32_regsets[] = {
...
@@ -867,6 +946,150 @@ static const struct user_regset sparc32_regsets[] = {
},
},
};
};
static
int
getregs_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
*
regs
=
task_pt_regs
(
target
);
u32
uregs
[
19
];
int
i
;
if
(
target
==
current
)
flushw_user
();
uregs
[
0
]
=
tstate_to_psr
(
regs
->
tstate
);
uregs
[
1
]
=
regs
->
tpc
;
uregs
[
2
]
=
regs
->
tnpc
;
uregs
[
3
]
=
regs
->
y
;
for
(
i
=
1
;
i
<
16
;
i
++
)
uregs
[
3
+
i
]
=
regs
->
u_regs
[
i
];
return
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
0
,
19
*
sizeof
(
u32
));
}
static
int
setregs_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
struct
pt_regs
*
regs
=
task_pt_regs
(
target
);
unsigned
long
tstate
;
u32
uregs
[
19
];
int
i
,
ret
;
if
(
target
==
current
)
flushw_user
();
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
uregs
,
0
,
19
*
sizeof
(
u32
));
if
(
ret
)
return
ret
;
tstate
=
regs
->
tstate
;
tstate
&=
~
(
TSTATE_ICC
|
TSTATE_XCC
|
TSTATE_SYSCALL
);
tstate
|=
psr_to_tstate_icc
(
uregs
[
0
]);
if
(
uregs
[
0
]
&
PSR_SYSCALL
)
tstate
|=
TSTATE_SYSCALL
;
regs
->
tstate
=
tstate
;
regs
->
tpc
=
uregs
[
1
];
regs
->
tnpc
=
uregs
[
2
];
regs
->
y
=
uregs
[
3
];
for
(
i
=
1
;
i
<
15
;
i
++
)
regs
->
u_regs
[
i
]
=
uregs
[
3
+
i
];
return
0
;
}
static
int
getfpregs_get
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
void
*
kbuf
,
void
__user
*
ubuf
)
{
const
unsigned
long
*
fpregs
=
task_thread_info
(
target
)
->
fpregs
;
unsigned
long
fprs
;
compat_ulong_t
fsr
;
int
ret
=
0
;
if
(
target
==
current
)
save_and_clear_fpu
();
fprs
=
task_thread_info
(
target
)
->
fpsaved
[
0
];
if
(
fprs
&
FPRS_FEF
)
{
fsr
=
task_thread_info
(
target
)
->
xfsr
[
0
];
}
else
{
fsr
=
0
;
}
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
!
ret
)
ret
=
user_regset_copyout
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
fsr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
if
(
!
ret
)
ret
=
user_regset_copyout_zero
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
33
*
sizeof
(
u32
),
68
*
sizeof
(
u32
));
return
ret
;
}
static
int
setfpregs_set
(
struct
task_struct
*
target
,
const
struct
user_regset
*
regset
,
unsigned
int
pos
,
unsigned
int
count
,
const
void
*
kbuf
,
const
void
__user
*
ubuf
)
{
unsigned
long
*
fpregs
=
task_thread_info
(
target
)
->
fpregs
;
unsigned
long
fprs
;
int
ret
;
if
(
target
==
current
)
save_and_clear_fpu
();
fprs
=
task_thread_info
(
target
)
->
fpsaved
[
0
];
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
fpregs
,
0
,
32
*
sizeof
(
u32
));
if
(
!
ret
)
{
compat_ulong_t
fsr
;
unsigned
long
val
;
ret
=
user_regset_copyin
(
&
pos
,
&
count
,
&
kbuf
,
&
ubuf
,
&
fsr
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
));
if
(
!
ret
)
{
val
=
task_thread_info
(
target
)
->
xfsr
[
0
];
val
&=
0xffffffff00000000UL
;
val
|=
fsr
;
task_thread_info
(
target
)
->
xfsr
[
0
]
=
val
;
}
}
fprs
|=
(
FPRS_FEF
|
FPRS_DL
);
task_thread_info
(
target
)
->
fpsaved
[
0
]
=
fprs
;
return
ret
;
}
static
const
struct
user_regset
ptrace32_regsets
[]
=
{
[
REGSET_GENERAL
]
=
{
.
n
=
19
,
.
size
=
sizeof
(
u32
),
.
get
=
getregs_get
,
.
set
=
setregs_set
,
},
[
REGSET_FP
]
=
{
.
n
=
68
,
.
size
=
sizeof
(
u32
),
.
get
=
getfpregs_get
,
.
set
=
setfpregs_set
,
},
};
static
const
struct
user_regset_view
ptrace32_view
=
{
.
regsets
=
ptrace32_regsets
,
.
n
=
ARRAY_SIZE
(
ptrace32_regsets
)
};
static
const
struct
user_regset_view
user_sparc32_view
=
{
static
const
struct
user_regset_view
user_sparc32_view
=
{
.
name
=
"sparc"
,
.
e_machine
=
EM_SPARC
,
.
name
=
"sparc"
,
.
e_machine
=
EM_SPARC
,
.
regsets
=
sparc32_regsets
,
.
n
=
ARRAY_SIZE
(
sparc32_regsets
)
.
regsets
=
sparc32_regsets
,
.
n
=
ARRAY_SIZE
(
sparc32_regsets
)
...
@@ -898,7 +1121,6 @@ struct compat_fps {
...
@@ -898,7 +1121,6 @@ struct compat_fps {
long
compat_arch_ptrace
(
struct
task_struct
*
child
,
compat_long_t
request
,
long
compat_arch_ptrace
(
struct
task_struct
*
child
,
compat_long_t
request
,
compat_ulong_t
caddr
,
compat_ulong_t
cdata
)
compat_ulong_t
caddr
,
compat_ulong_t
cdata
)
{
{
const
struct
user_regset_view
*
view
=
task_user_regset_view
(
current
);
compat_ulong_t
caddr2
=
task_pt_regs
(
current
)
->
u_regs
[
UREG_I4
];
compat_ulong_t
caddr2
=
task_pt_regs
(
current
)
->
u_regs
[
UREG_I4
];
struct
pt_regs32
__user
*
pregs
;
struct
pt_regs32
__user
*
pregs
;
struct
compat_fps
__user
*
fps
;
struct
compat_fps
__user
*
fps
;
...
@@ -916,58 +1138,31 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
...
@@ -916,58 +1138,31 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
break
;
break
;
case
PTRACE_GETREGS
:
case
PTRACE_GETREGS
:
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
ret
=
copy_regset_to_user
(
child
,
&
ptrace32_view
,
32
*
sizeof
(
u32
),
REGSET_GENERAL
,
0
,
4
*
sizeof
(
u32
),
19
*
sizeof
(
u32
),
&
pregs
->
psr
);
pregs
);
if
(
!
ret
)
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
1
*
sizeof
(
u32
),
15
*
sizeof
(
u32
),
&
pregs
->
u_regs
[
0
]);
break
;
break
;
case
PTRACE_SETREGS
:
case
PTRACE_SETREGS
:
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
ret
=
copy_regset_from_user
(
child
,
&
ptrace32_view
,
32
*
sizeof
(
u32
),
REGSET_GENERAL
,
0
,
4
*
sizeof
(
u32
),
19
*
sizeof
(
u32
),
&
pregs
->
psr
);
pregs
);
if
(
!
ret
)
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
1
*
sizeof
(
u32
),
15
*
sizeof
(
u32
),
&
pregs
->
u_regs
[
0
]);
break
;
break
;
case
PTRACE_GETFPREGS
:
case
PTRACE_GETFPREGS
:
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_FP
,
ret
=
copy_regset_to_user
(
child
,
&
ptrace32_view
,
0
*
sizeof
(
u32
),
REGSET_FP
,
0
,
32
*
sizeof
(
u32
),
68
*
sizeof
(
u32
),
&
fps
->
regs
[
0
]);
fps
);
if
(
!
ret
)
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_FP
,
33
*
sizeof
(
u32
),
1
*
sizeof
(
u32
),
&
fps
->
fsr
);
if
(
!
ret
)
{
if
(
__put_user
(
0
,
&
fps
->
flags
)
||
__put_user
(
0
,
&
fps
->
extra
)
||
__put_user
(
0
,
&
fps
->
fpqd
)
||
clear_user
(
&
fps
->
fpq
[
0
],
32
*
sizeof
(
unsigned
int
)))
ret
=
-
EFAULT
;
}
break
;
break
;
case
PTRACE_SETFPREGS
:
case
PTRACE_SETFPREGS
:
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_FP
,
ret
=
copy_regset_from_user
(
child
,
&
ptrace32_view
,
0
*
sizeof
(
u32
),
REGSET_FP
,
0
,
32
*
sizeof
(
u32
),
33
*
sizeof
(
u32
),
&
fps
->
regs
[
0
]);
fps
);
if
(
!
ret
)
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_FP
,
33
*
sizeof
(
u32
),
1
*
sizeof
(
u32
),
&
fps
->
fsr
);
break
;
break
;
case
PTRACE_READTEXT
:
case
PTRACE_READTEXT
:
...
@@ -1026,31 +1221,17 @@ long arch_ptrace(struct task_struct *child, long request,
...
@@ -1026,31 +1221,17 @@ long arch_ptrace(struct task_struct *child, long request,
break
;
break
;
case
PTRACE_GETREGS64
:
case
PTRACE_GETREGS64
:
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
ret
=
copy_regset_to_user
(
child
,
&
ptrace64_view
,
1
*
sizeof
(
u64
),
REGSET_GENERAL
,
0
,
15
*
sizeof
(
u64
),
19
*
sizeof
(
u64
),
&
pregs
->
u_regs
[
0
]);
pregs
);
if
(
!
ret
)
{
/* XXX doesn't handle 'y' register correctly XXX */
ret
=
copy_regset_to_user
(
child
,
view
,
REGSET_GENERAL
,
32
*
sizeof
(
u64
),
4
*
sizeof
(
u64
),
&
pregs
->
tstate
);
}
break
;
break
;
case
PTRACE_SETREGS64
:
case
PTRACE_SETREGS64
:
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
ret
=
copy_regset_from_user
(
child
,
&
ptrace64_view
,
1
*
sizeof
(
u64
),
REGSET_GENERAL
,
0
,
15
*
sizeof
(
u64
),
19
*
sizeof
(
u64
),
&
pregs
->
u_regs
[
0
]);
pregs
);
if
(
!
ret
)
{
/* XXX doesn't handle 'y' register correctly XXX */
ret
=
copy_regset_from_user
(
child
,
view
,
REGSET_GENERAL
,
32
*
sizeof
(
u64
),
4
*
sizeof
(
u64
),
&
pregs
->
tstate
);
}
break
;
break
;
case
PTRACE_GETFPREGS64
:
case
PTRACE_GETFPREGS64
:
...
...
arch/x86/include/asm/fpu/internal.h
浏览文件 @
1e56f6d2
...
@@ -34,7 +34,6 @@ extern int fpu__copy(struct task_struct *dst, struct task_struct *src);
...
@@ -34,7 +34,6 @@ extern int fpu__copy(struct task_struct *dst, struct task_struct *src);
extern
void
fpu__clear_user_states
(
struct
fpu
*
fpu
);
extern
void
fpu__clear_user_states
(
struct
fpu
*
fpu
);
extern
void
fpu__clear_all
(
struct
fpu
*
fpu
);
extern
void
fpu__clear_all
(
struct
fpu
*
fpu
);
extern
int
fpu__exception_code
(
struct
fpu
*
fpu
,
int
trap_nr
);
extern
int
fpu__exception_code
(
struct
fpu
*
fpu
,
int
trap_nr
);
extern
int
dump_fpu
(
struct
pt_regs
*
ptregs
,
struct
user_i387_struct
*
fpstate
);
/*
/*
* Boot time FPU initialization functions:
* Boot time FPU initialization functions:
...
...
arch/x86/kernel/fpu/regset.c
浏览文件 @
1e56f6d2
...
@@ -356,20 +356,4 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
...
@@ -356,20 +356,4 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
return
ret
;
return
ret
;
}
}
/*
* FPU state for core dumps.
* This is only used for a.out dumps now.
* It is declared generically using elf_fpregset_t (which is
* struct user_i387_struct) but is in fact only used for 32-bit
* dumps, so on 64-bit it is really struct user_i387_ia32_struct.
*/
int
dump_fpu
(
struct
pt_regs
*
regs
,
struct
user_i387_struct
*
ufpu
)
{
struct
task_struct
*
tsk
=
current
;
return
!
fpregs_get
(
tsk
,
NULL
,
0
,
sizeof
(
struct
user_i387_ia32_struct
),
ufpu
,
NULL
);
}
EXPORT_SYMBOL
(
dump_fpu
);
#endif
/* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
#endif
/* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
arch/x86/kernel/fpu/signal.c
浏览文件 @
1e56f6d2
...
@@ -170,14 +170,14 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
...
@@ -170,14 +170,14 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
ia32_fxstate
&=
(
IS_ENABLED
(
CONFIG_X86_32
)
||
ia32_fxstate
&=
(
IS_ENABLED
(
CONFIG_X86_32
)
||
IS_ENABLED
(
CONFIG_IA32_EMULATION
));
IS_ENABLED
(
CONFIG_IA32_EMULATION
));
if
(
!
static_cpu_has
(
X86_FEATURE_FPU
))
{
struct
user_i387_ia32_struct
fp
;
fpregs_soft_get
(
current
,
NULL
,
0
,
sizeof
(
fp
),
&
fp
,
NULL
);
return
copy_to_user
(
buf
,
&
fp
,
sizeof
(
fp
))
?
-
EFAULT
:
0
;
}
if
(
!
access_ok
(
buf
,
size
))
if
(
!
access_ok
(
buf
,
size
))
return
-
EACCES
;
return
-
EACCES
;
if
(
!
static_cpu_has
(
X86_FEATURE_FPU
))
return
fpregs_soft_get
(
current
,
NULL
,
0
,
sizeof
(
struct
user_i387_ia32_struct
),
NULL
,
(
struct
_fpstate_32
__user
*
)
buf
)
?
-
1
:
1
;
retry:
retry:
/*
/*
* Load the FPU registers if they are not valid for the current task.
* Load the FPU registers if they are not valid for the current task.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录