Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
408133e9
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
408133e9
编写于
4月 29, 2011
作者:
R
Russell King
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'kprobes' of
git://git.linaro.org/people/nico/linux
into fixes
上级
ef267500
cdc25361
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
462 addition
and
321 deletion
+462
-321
arch/arm/include/asm/kprobes.h
arch/arm/include/asm/kprobes.h
+3
-0
arch/arm/kernel/kprobes-decode.c
arch/arm/kernel/kprobes-decode.c
+457
-320
arch/arm/kernel/kprobes.c
arch/arm/kernel/kprobes.c
+2
-1
未找到文件。
arch/arm/include/asm/kprobes.h
浏览文件 @
408133e9
...
@@ -39,10 +39,13 @@ typedef u32 kprobe_opcode_t;
...
@@ -39,10 +39,13 @@ typedef u32 kprobe_opcode_t;
struct
kprobe
;
struct
kprobe
;
typedef
void
(
kprobe_insn_handler_t
)(
struct
kprobe
*
,
struct
pt_regs
*
);
typedef
void
(
kprobe_insn_handler_t
)(
struct
kprobe
*
,
struct
pt_regs
*
);
typedef
unsigned
long
(
kprobe_check_cc
)(
unsigned
long
);
/* Architecture specific copy of original instruction. */
/* Architecture specific copy of original instruction. */
struct
arch_specific_insn
{
struct
arch_specific_insn
{
kprobe_opcode_t
*
insn
;
kprobe_opcode_t
*
insn
;
kprobe_insn_handler_t
*
insn_handler
;
kprobe_insn_handler_t
*
insn_handler
;
kprobe_check_cc
*
insn_check_cc
;
};
};
struct
prev_kprobe
{
struct
prev_kprobe
{
...
...
arch/arm/kernel/kprobes-decode.c
浏览文件 @
408133e9
...
@@ -34,9 +34,6 @@
...
@@ -34,9 +34,6 @@
*
*
* *) If the PC is written to by the instruction, the
* *) If the PC is written to by the instruction, the
* instruction must be fully simulated in software.
* instruction must be fully simulated in software.
* If it is a conditional instruction, the handler
* will use insn[0] to copy its condition code to
* set r0 to 1 and insn[1] to "mov pc, lr" to return.
*
*
* *) Otherwise, a modified form of the instruction is
* *) Otherwise, a modified form of the instruction is
* directly executed. Its handler calls the
* directly executed. Its handler calls the
...
@@ -68,13 +65,17 @@
...
@@ -68,13 +65,17 @@
#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
/*
* Test if load/store instructions writeback the address register.
* if P (bit 24) == 0 or W (bit 21) == 1
*/
#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
#define PSR_fs (PSR_f|PSR_s)
#define PSR_fs (PSR_f|PSR_s)
#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e
/* mov pc, lr */
#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e
/* mov pc, lr */
#define SET_R0_TRUE_INSTRUCTION 0xe3a00001
/* mov r0, #1 */
#define truecc_insn(insn) (((insn) & 0xf0000000) | \
(SET_R0_TRUE_INSTRUCTION & 0x0fffffff))
typedef
long
(
insn_0arg_fn_t
)(
void
);
typedef
long
(
insn_0arg_fn_t
)(
void
);
typedef
long
(
insn_1arg_fn_t
)(
long
);
typedef
long
(
insn_1arg_fn_t
)(
long
);
...
@@ -419,14 +420,10 @@ insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
...
@@ -419,14 +420,10 @@ insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
static
void
__kprobes
simulate_bbl
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
simulate_bbl
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
kprobe_opcode_t
insn
=
p
->
opcode
;
long
iaddr
=
(
long
)
p
->
addr
;
long
iaddr
=
(
long
)
p
->
addr
;
int
disp
=
branch_displacement
(
insn
);
int
disp
=
branch_displacement
(
insn
);
if
(
!
insnslot_1arg_rflags
(
0
,
regs
->
ARM_cpsr
,
i_fn
))
return
;
if
(
insn
&
(
1
<<
24
))
if
(
insn
&
(
1
<<
24
))
regs
->
ARM_lr
=
iaddr
+
4
;
regs
->
ARM_lr
=
iaddr
+
4
;
...
@@ -446,14 +443,10 @@ static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
...
@@ -446,14 +443,10 @@ static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
static
void
__kprobes
simulate_blx2bx
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
simulate_blx2bx
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rm
=
insn
&
0xf
;
int
rm
=
insn
&
0xf
;
long
rmv
=
regs
->
uregs
[
rm
];
long
rmv
=
regs
->
uregs
[
rm
];
if
(
!
insnslot_1arg_rflags
(
0
,
regs
->
ARM_cpsr
,
i_fn
))
return
;
if
(
insn
&
(
1
<<
5
))
if
(
insn
&
(
1
<<
5
))
regs
->
ARM_lr
=
(
long
)
p
->
addr
+
4
;
regs
->
ARM_lr
=
(
long
)
p
->
addr
+
4
;
...
@@ -463,9 +456,16 @@ static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
...
@@ -463,9 +456,16 @@ static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
regs
->
ARM_cpsr
|=
PSR_T_BIT
;
regs
->
ARM_cpsr
|=
PSR_T_BIT
;
}
}
static
void
__kprobes
simulate_mrs
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
unsigned
long
mask
=
0xf8ff03df
;
/* Mask out execution state */
regs
->
uregs
[
rd
]
=
regs
->
ARM_cpsr
&
mask
;
}
static
void
__kprobes
simulate_ldm1stm1
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
simulate_ldm1stm1
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
lbit
=
insn
&
(
1
<<
20
);
int
lbit
=
insn
&
(
1
<<
20
);
...
@@ -476,9 +476,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
...
@@ -476,9 +476,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
int
reg_bit_vector
;
int
reg_bit_vector
;
int
reg_count
;
int
reg_count
;
if
(
!
insnslot_1arg_rflags
(
0
,
regs
->
ARM_cpsr
,
i_fn
))
return
;
reg_count
=
0
;
reg_count
=
0
;
reg_bit_vector
=
insn
&
0xffff
;
reg_bit_vector
=
insn
&
0xffff
;
while
(
reg_bit_vector
)
{
while
(
reg_bit_vector
)
{
...
@@ -510,11 +507,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
...
@@ -510,11 +507,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
static
void
__kprobes
simulate_stm1_pc
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
simulate_stm1_pc
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
if
(
!
insnslot_1arg_rflags
(
0
,
regs
->
ARM_cpsr
,
i_fn
))
return
;
regs
->
ARM_pc
=
(
long
)
p
->
addr
+
str_pc_offset
;
regs
->
ARM_pc
=
(
long
)
p
->
addr
+
str_pc_offset
;
simulate_ldm1stm1
(
p
,
regs
);
simulate_ldm1stm1
(
p
,
regs
);
regs
->
ARM_pc
=
(
long
)
p
->
addr
+
4
;
regs
->
ARM_pc
=
(
long
)
p
->
addr
+
4
;
...
@@ -525,24 +517,16 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
...
@@ -525,24 +517,16 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
regs
->
uregs
[
12
]
=
regs
->
uregs
[
13
];
regs
->
uregs
[
12
]
=
regs
->
uregs
[
13
];
}
}
static
void
__kprobes
emulate_ldcstc
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
long
rnv
=
regs
->
uregs
[
rn
];
/* Save Rn in case of writeback. */
regs
->
uregs
[
rn
]
=
insnslot_1arg_rflags
(
rnv
,
regs
->
ARM_cpsr
,
i_fn
);
}
static
void
__kprobes
emulate_ldrd
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_ldrd
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_2arg_fn_t
*
i_fn
=
(
insn_2arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
insn_2arg_fn_t
*
i_fn
=
(
insn_2arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
kprobe_opcode_t
insn
=
p
->
opcode
;
long
ppc
=
(
long
)
p
->
addr
+
8
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
rm
=
insn
&
0xf
;
/* rm may be invalid, don't care. */
int
rm
=
insn
&
0xf
;
/* rm may be invalid, don't care. */
long
rmv
=
(
rm
==
15
)
?
ppc
:
regs
->
uregs
[
rm
];
long
rnv
=
(
rn
==
15
)
?
ppc
:
regs
->
uregs
[
rn
];
/* Not following the C calling convention here, so need asm(). */
/* Not following the C calling convention here, so need asm(). */
__asm__
__volatile__
(
__asm__
__volatile__
(
...
@@ -554,29 +538,36 @@ static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
...
@@ -554,29 +538,36 @@ static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
"str r0, %[rn]
\n\t
"
/* in case of writeback */
"str r0, %[rn]
\n\t
"
/* in case of writeback */
"str r2, %[rd0]
\n\t
"
"str r2, %[rd0]
\n\t
"
"str r3, %[rd1]
\n\t
"
"str r3, %[rd1]
\n\t
"
:
[
rn
]
"+m"
(
r
egs
->
uregs
[
rn
]
),
:
[
rn
]
"+m"
(
r
nv
),
[
rd0
]
"=m"
(
regs
->
uregs
[
rd
]),
[
rd0
]
"=m"
(
regs
->
uregs
[
rd
]),
[
rd1
]
"=m"
(
regs
->
uregs
[
rd
+
1
])
[
rd1
]
"=m"
(
regs
->
uregs
[
rd
+
1
])
:
[
rm
]
"m"
(
r
egs
->
uregs
[
rm
]
),
:
[
rm
]
"m"
(
r
mv
),
[
cpsr
]
"r"
(
regs
->
ARM_cpsr
),
[
cpsr
]
"r"
(
regs
->
ARM_cpsr
),
[
i_fn
]
"r"
(
i_fn
)
[
i_fn
]
"r"
(
i_fn
)
:
"r0"
,
"r1"
,
"r2"
,
"r3"
,
"lr"
,
"cc"
:
"r0"
,
"r1"
,
"r2"
,
"r3"
,
"lr"
,
"cc"
);
);
if
(
is_writeback
(
insn
))
regs
->
uregs
[
rn
]
=
rnv
;
}
}
static
void
__kprobes
emulate_strd
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_strd
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_4arg_fn_t
*
i_fn
=
(
insn_4arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
insn_4arg_fn_t
*
i_fn
=
(
insn_4arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
kprobe_opcode_t
insn
=
p
->
opcode
;
long
ppc
=
(
long
)
p
->
addr
+
8
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
rm
=
insn
&
0xf
;
int
rm
=
insn
&
0xf
;
long
rnv
=
regs
->
uregs
[
rn
];
long
rnv
=
(
rn
==
15
)
?
ppc
:
regs
->
uregs
[
rn
];
long
rmv
=
regs
->
uregs
[
rm
];
/* rm/rmv may be invalid, don't care. */
/* rm/rmv may be invalid, don't care. */
long
rmv
=
(
rm
==
15
)
?
ppc
:
regs
->
uregs
[
rm
];
long
rnv_wb
;
r
egs
->
uregs
[
rn
]
=
insnslot_4arg_rflags
(
rnv
,
rmv
,
regs
->
uregs
[
rd
],
r
nv_wb
=
insnslot_4arg_rflags
(
rnv
,
rmv
,
regs
->
uregs
[
rd
],
regs
->
uregs
[
rd
+
1
],
regs
->
uregs
[
rd
+
1
],
regs
->
ARM_cpsr
,
i_fn
);
regs
->
ARM_cpsr
,
i_fn
);
if
(
is_writeback
(
insn
))
regs
->
uregs
[
rn
]
=
rnv_wb
;
}
}
static
void
__kprobes
emulate_ldr
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_ldr
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
...
@@ -630,31 +621,6 @@ static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
...
@@ -630,31 +621,6 @@ static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
regs
->
uregs
[
rn
]
=
rnv_wb
;
/* Save Rn in case of writeback. */
regs
->
uregs
[
rn
]
=
rnv_wb
;
/* Save Rn in case of writeback. */
}
}
static
void
__kprobes
emulate_mrrc
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
insn_llret_0arg_fn_t
*
i_fn
=
(
insn_llret_0arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
union
reg_pair
fnr
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
fnr
.
dr
=
insnslot_llret_0arg_rflags
(
regs
->
ARM_cpsr
,
i_fn
);
regs
->
uregs
[
rn
]
=
fnr
.
r0
;
regs
->
uregs
[
rd
]
=
fnr
.
r1
;
}
static
void
__kprobes
emulate_mcrr
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
insn_2arg_fn_t
*
i_fn
=
(
insn_2arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
long
rnv
=
regs
->
uregs
[
rn
];
long
rdv
=
regs
->
uregs
[
rd
];
insnslot_2arg_rflags
(
rnv
,
rdv
,
regs
->
ARM_cpsr
,
i_fn
);
}
static
void
__kprobes
emulate_sat
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_sat
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
...
@@ -688,32 +654,32 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
...
@@ -688,32 +654,32 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
insnslot_0arg_rflags
(
regs
->
ARM_cpsr
,
i_fn
);
insnslot_0arg_rflags
(
regs
->
ARM_cpsr
,
i_fn
);
}
}
static
void
__kprobes
emulate_
rd12
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_
nop
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_0arg_fn_t
*
i_fn
=
(
insn_0arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
regs
->
uregs
[
rd
]
=
insnslot_0arg_rflags
(
regs
->
ARM_cpsr
,
i_fn
);
}
}
static
void
__kprobes
emulate_ird12
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_rd12_modify
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
kprobe_opcode_t
insn
=
p
->
opcode
;
int
ird
=
(
insn
>>
12
)
&
0xf
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
long
rdv
=
regs
->
uregs
[
rd
];
insnslot_1arg_rflags
(
regs
->
uregs
[
ird
]
,
regs
->
ARM_cpsr
,
i_fn
);
regs
->
uregs
[
rd
]
=
insnslot_1arg_rflags
(
rdv
,
regs
->
ARM_cpsr
,
i_fn
);
}
}
static
void
__kprobes
emulate_rn16
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_rd12rn0_modify
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
insn_
1arg_fn_t
*
i_fn
=
(
insn_1
arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
insn_
2arg_fn_t
*
i_fn
=
(
insn_2
arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
rd
=
(
insn
>>
12
)
&
0xf
;
int
rn
=
insn
&
0xf
;
long
rdv
=
regs
->
uregs
[
rd
];
long
rnv
=
regs
->
uregs
[
rn
];
long
rnv
=
regs
->
uregs
[
rn
];
insnslot_1arg_rflags
(
rnv
,
regs
->
ARM_cpsr
,
i_fn
);
regs
->
uregs
[
rd
]
=
insnslot_2arg_rflags
(
rdv
,
rnv
,
regs
->
ARM_cpsr
,
i_fn
);
}
}
static
void
__kprobes
emulate_rd12rm0
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
static
void
__kprobes
emulate_rd12rm0
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
...
@@ -818,6 +784,17 @@ emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
...
@@ -818,6 +784,17 @@ emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
regs
->
uregs
[
rd
]
=
insnslot_1arg_rwflags
(
rnv
,
&
regs
->
ARM_cpsr
,
i_fn
);
regs
->
uregs
[
rd
]
=
insnslot_1arg_rwflags
(
rnv
,
&
regs
->
ARM_cpsr
,
i_fn
);
}
}
static
void
__kprobes
emulate_alu_tests_imm
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
insn_1arg_fn_t
*
i_fn
=
(
insn_1arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
long
rnv
=
(
rn
==
15
)
?
(
long
)
p
->
addr
+
8
:
regs
->
uregs
[
rn
];
insnslot_1arg_rwflags
(
rnv
,
&
regs
->
ARM_cpsr
,
i_fn
);
}
static
void
__kprobes
static
void
__kprobes
emulate_alu_rflags
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
emulate_alu_rflags
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
{
...
@@ -854,14 +831,34 @@ emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
...
@@ -854,14 +831,34 @@ emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
insnslot_3arg_rwflags
(
rnv
,
rmv
,
rsv
,
&
regs
->
ARM_cpsr
,
i_fn
);
insnslot_3arg_rwflags
(
rnv
,
rmv
,
rsv
,
&
regs
->
ARM_cpsr
,
i_fn
);
}
}
static
void
__kprobes
emulate_alu_tests
(
struct
kprobe
*
p
,
struct
pt_regs
*
regs
)
{
insn_3arg_fn_t
*
i_fn
=
(
insn_3arg_fn_t
*
)
&
p
->
ainsn
.
insn
[
0
];
kprobe_opcode_t
insn
=
p
->
opcode
;
long
ppc
=
(
long
)
p
->
addr
+
8
;
int
rn
=
(
insn
>>
16
)
&
0xf
;
int
rs
=
(
insn
>>
8
)
&
0xf
;
/* rs/rsv may be invalid, don't care. */
int
rm
=
insn
&
0xf
;
long
rnv
=
(
rn
==
15
)
?
ppc
:
regs
->
uregs
[
rn
];
long
rmv
=
(
rm
==
15
)
?
ppc
:
regs
->
uregs
[
rm
];
long
rsv
=
regs
->
uregs
[
rs
];
insnslot_3arg_rwflags
(
rnv
,
rmv
,
rsv
,
&
regs
->
ARM_cpsr
,
i_fn
);
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
prep_emulate_ldr_str
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
prep_emulate_ldr_str
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
int
ibit
=
(
insn
&
(
1
<<
26
))
?
25
:
22
;
int
not_imm
=
(
insn
&
(
1
<<
26
))
?
(
insn
&
(
1
<<
25
))
:
(
~
insn
&
(
1
<<
22
));
if
(
is_writeback
(
insn
)
&&
is_r15
(
insn
,
16
))
return
INSN_REJECTED
;
/* Writeback to PC */
insn
&=
0xfff00fff
;
insn
&=
0xfff00fff
;
insn
|=
0x00001000
;
/* Rn = r0, Rd = r1 */
insn
|=
0x00001000
;
/* Rn = r0, Rd = r1 */
if
(
insn
&
(
1
<<
ibit
)
)
{
if
(
not_imm
)
{
insn
&=
~
0xf
;
insn
&=
~
0xf
;
insn
|=
2
;
/* Rm = r2 */
insn
|=
2
;
/* Rm = r2 */
}
}
...
@@ -871,20 +868,40 @@ prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -871,20 +868,40 @@ prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
prep_emulate_rd12
rm0
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
prep_emulate_rd12
_modify
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
insn
&=
0xffff0ff0
;
/* Rd = r0, Rm = r0 */
if
(
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xffff0fff
;
/* Rd = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_rd12
rm0
;
asi
->
insn_handler
=
emulate_rd12
_modify
;
return
INSN_GOOD
;
return
INSN_GOOD
;
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
prep_emulate_rd12
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
prep_emulate_rd12rn0_modify
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
insn
&=
0xffff0fff
;
/* Rd = r0 */
if
(
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xffff0ff0
;
/* Rd = r0 */
insn
|=
0x00000001
;
/* Rn = r1 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_rd12rn0_modify
;
return
INSN_GOOD
;
}
static
enum
kprobe_insn
__kprobes
prep_emulate_rd12rm0
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
if
(
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xffff0ff0
;
/* Rd = r0, Rm = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_rd12
;
asi
->
insn_handler
=
emulate_rd12
rm0
;
return
INSN_GOOD
;
return
INSN_GOOD
;
}
}
...
@@ -892,6 +909,9 @@ static enum kprobe_insn __kprobes
...
@@ -892,6 +909,9 @@ static enum kprobe_insn __kprobes
prep_emulate_rd12rn16rm0_wflags
(
kprobe_opcode_t
insn
,
prep_emulate_rd12rn16rm0_wflags
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
struct
arch_specific_insn
*
asi
)
{
{
if
(
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xfff00ff0
;
/* Rd = r0, Rn = r0 */
insn
&=
0xfff00ff0
;
/* Rd = r0, Rn = r0 */
insn
|=
0x00000001
;
/* Rm = r1 */
insn
|=
0x00000001
;
/* Rm = r1 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
...
@@ -903,6 +923,9 @@ static enum kprobe_insn __kprobes
...
@@ -903,6 +923,9 @@ static enum kprobe_insn __kprobes
prep_emulate_rd16rs8rm0_wflags
(
kprobe_opcode_t
insn
,
prep_emulate_rd16rs8rm0_wflags
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
struct
arch_specific_insn
*
asi
)
{
{
if
(
is_r15
(
insn
,
16
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xfff0f0f0
;
/* Rd = r0, Rs = r0 */
insn
&=
0xfff0f0f0
;
/* Rd = r0, Rs = r0 */
insn
|=
0x00000001
;
/* Rm = r1 */
insn
|=
0x00000001
;
/* Rm = r1 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
...
@@ -914,6 +937,9 @@ static enum kprobe_insn __kprobes
...
@@ -914,6 +937,9 @@ static enum kprobe_insn __kprobes
prep_emulate_rd16rn12rs8rm0_wflags
(
kprobe_opcode_t
insn
,
prep_emulate_rd16rn12rs8rm0_wflags
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
struct
arch_specific_insn
*
asi
)
{
{
if
(
is_r15
(
insn
,
16
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xfff000f0
;
/* Rd = r0, Rn = r0 */
insn
&=
0xfff000f0
;
/* Rd = r0, Rn = r0 */
insn
|=
0x00000102
;
/* Rs = r1, Rm = r2 */
insn
|=
0x00000102
;
/* Rs = r1, Rm = r2 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
...
@@ -925,6 +951,9 @@ static enum kprobe_insn __kprobes
...
@@ -925,6 +951,9 @@ static enum kprobe_insn __kprobes
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
kprobe_opcode_t
insn
,
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
struct
arch_specific_insn
*
asi
)
{
{
if
(
is_r15
(
insn
,
16
)
||
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* RdHi or RdLo is PC */
insn
&=
0xfff000f0
;
/* RdHi = r0, RdLo = r1 */
insn
&=
0xfff000f0
;
/* RdHi = r0, RdLo = r1 */
insn
|=
0x00001203
;
/* Rs = r2, Rm = r3 */
insn
|=
0x00001203
;
/* Rs = r2, Rm = r3 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
...
@@ -945,20 +974,13 @@ prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
...
@@ -945,20 +974,13 @@ prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
space_1111
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
space_1111
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
/* CPS mmod == 1 : 1111 0001 0000 xx10 xxxx xxxx xx0x xxxx */
/* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */
/* RFE : 1111 100x x0x1 xxxx xxxx 1010 xxxx xxxx */
/* PLDI : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */
/* SRS : 1111 100x x1x0 1101 xxxx 0101 xxxx xxxx */
/* PLDW : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */
if
((
insn
&
0xfff30020
)
==
0xf1020000
||
/* PLD : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */
(
insn
&
0xfe500f00
)
==
0xf8100a00
||
if
((
insn
&
0xfe300000
)
==
0xf4100000
)
{
(
insn
&
0xfe5f0f00
)
==
0xf84d0500
)
asi
->
insn_handler
=
emulate_nop
;
return
INSN_REJECTED
;
return
INSN_GOOD_NO_SLOT
;
/* PLD : 1111 01x1 x101 xxxx xxxx xxxx xxxx xxxx : */
if
((
insn
&
0xfd700000
)
==
0xf4500000
)
{
insn
&=
0xfff0ffff
;
/* Rn = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_rn16
;
return
INSN_GOOD
;
}
}
/* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
/* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
...
@@ -967,41 +989,22 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -967,41 +989,22 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return
INSN_GOOD_NO_SLOT
;
return
INSN_GOOD_NO_SLOT
;
}
}
/* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
/* CPS : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
/* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
/* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
if
((
insn
&
0xffff00f0
)
==
0xf1010000
||
(
insn
&
0xff000010
)
==
0xfe000000
)
{
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_none
;
return
INSN_GOOD
;
}
/* SRS : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
/* RFE : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
/* Coprocessor instructions... */
/* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
/* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
/* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
/* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
if
((
insn
&
0xffe00000
)
==
0xfc400000
)
{
/* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
insn
&=
0xfff00fff
;
/* Rn = r0 */
/* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
insn
|=
0x00001000
;
/* Rd = r1 */
/* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
asi
->
insn
[
0
]
=
insn
;
/* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
asi
->
insn_handler
=
/* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
(
insn
&
(
1
<<
20
))
?
emulate_mrrc
:
emulate_mcrr
;
return
INSN_GOOD
;
}
/* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
return
INSN_REJECTED
;
/* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
if
((
insn
&
0xfe000000
)
==
0xfc000000
)
{
insn
&=
0xfff0ffff
;
/* Rn = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_ldcstc
;
return
INSN_GOOD
;
}
/* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
/* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
insn
&=
0xffff0fff
;
/* Rd = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
(
insn
&
(
1
<<
20
))
?
emulate_rd12
:
emulate_ird12
;
return
INSN_GOOD
;
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
...
@@ -1010,19 +1013,18 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1010,19 +1013,18 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
if
((
insn
&
0x0f900010
)
==
0x01000000
)
{
if
((
insn
&
0x0f900010
)
==
0x01000000
)
{
/* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
/* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
/* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
if
((
insn
&
0x0ff000f0
)
==
0x01000000
)
{
if
((
insn
&
0x0ff000f0
)
==
0x01200020
||
if
(
is_r15
(
insn
,
12
))
(
insn
&
0x0fb000f0
)
==
0x01200000
)
return
INSN_REJECTED
;
/* Rd is PC */
return
INSN_REJECTED
;
asi
->
insn_handler
=
simulate_mrs
;
return
INSN_GOOD_NO_SLOT
;
/* MRS : cccc 0001 0x00 xxxx xxxx xxxx 0000 xxxx */
}
if
((
insn
&
0x0fb00010
)
==
0x01000000
)
return
prep_emulate_rd12
(
insn
,
asi
);
/* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
/* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
if
((
insn
&
0x0ff00090
)
==
0x01400080
)
if
((
insn
&
0x0ff00090
)
==
0x01400080
)
return
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
insn
,
asi
);
return
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
insn
,
asi
);
/* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
/* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
/* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
/* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
...
@@ -1031,24 +1033,29 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1031,24 +1033,29 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return
prep_emulate_rd16rs8rm0_wflags
(
insn
,
asi
);
return
prep_emulate_rd16rs8rm0_wflags
(
insn
,
asi
);
/* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
/* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
/* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 0x00 xxxx : Q */
/* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
if
((
insn
&
0x0ff00090
)
==
0x01000080
||
(
insn
&
0x0ff000b0
)
==
0x01200080
)
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
/* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
/* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
/* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
/* Other instruction encodings aren't yet defined */
return
INSN_REJECTED
;
}
}
/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
else
if
((
insn
&
0x0f900090
)
==
0x01000010
)
{
else
if
((
insn
&
0x0f900090
)
==
0x01000010
)
{
/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
if
((
insn
&
0xfff000f0
)
==
0xe1200070
)
return
INSN_REJECTED
;
/* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
/* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
/* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
/* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
if
((
insn
&
0x0ff000d0
)
==
0x01200010
)
{
if
((
insn
&
0x0ff000d0
)
==
0x01200010
)
{
asi
->
insn
[
0
]
=
truecc_insn
(
insn
);
if
((
insn
&
0x0ff000ff
)
==
0x0120003f
)
return
INSN_REJECTED
;
/* BLX pc */
asi
->
insn_handler
=
simulate_blx2bx
;
asi
->
insn_handler
=
simulate_blx2bx
;
return
INSN_GOOD
;
return
INSN_GOOD
_NO_SLOT
;
}
}
/* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
/* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
...
@@ -1059,17 +1066,27 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1059,17 +1066,27 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* QSUB : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
/* QSUB : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
/* QDADD : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
/* QDADD : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
/* QDSUB : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
/* QDSUB : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
if
((
insn
&
0x0f9000f0
)
==
0x01000050
)
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
/* SMC : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
/* Other instruction encodings aren't yet defined */
return
INSN_REJECTED
;
}
}
/* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
/* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
else
if
((
insn
&
0x0f0000
9
0
)
==
0x00000090
)
{
else
if
((
insn
&
0x0f0000
f
0
)
==
0x00000090
)
{
/* MUL : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx : */
/* MUL : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx : */
/* MULS : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
/* MULS : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
/* MLA : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx : */
/* MLA : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx : */
/* MLAS : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
/* MLAS : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
/* UMAAL : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx : */
/* UMAAL : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx : */
/* undef : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx : */
/* MLS : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx : */
/* undef : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx : */
/* UMULL : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx : */
/* UMULL : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx : */
/* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
/* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
/* UMLAL : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx : */
/* UMLAL : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx : */
...
@@ -1078,13 +1095,15 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1078,13 +1095,15 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
/* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
/* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */
/* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */
/* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
/* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
if
((
insn
&
0x0fe000f0
)
==
0x00000090
)
{
if
((
insn
&
0x00d00000
)
==
0x00500000
)
return
prep_emulate_rd16rs8rm0_wflags
(
insn
,
asi
);
return
INSN_REJECTED
;
}
else
if
((
insn
&
0x0fe000f0
)
==
0x00200090
)
{
else
if
((
insn
&
0x00e00000
)
==
0x00000000
)
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
return
prep_emulate_rd16rs8rm0_wflags
(
insn
,
asi
);
}
else
{
else
if
((
insn
&
0x00a00000
)
==
0x00200000
)
return
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
insn
,
asi
);
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
}
else
return
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
insn
,
asi
);
}
}
/* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
/* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
...
@@ -1092,23 +1111,45 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1092,23 +1111,45 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* SWP : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
/* SWP : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
/* SWPB : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
/* SWPB : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
/* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
/* ??? : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
/* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
/* ??? : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
/* ??? : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
/* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
/* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
/* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
/* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
/* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
/* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
/* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
/* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
/* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
/* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */
/* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
/* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
/* LDRH : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
/* LDRH : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
/* STRH : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
/* STRH : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
/* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
/* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
/* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
/* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
if
((
insn
&
0x0fb000f0
)
==
0x01000090
)
{
if
((
insn
&
0x0f0000f0
)
==
0x01000090
)
{
/* SWP/SWPB */
if
((
insn
&
0x0fb000f0
)
==
0x01000090
)
{
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
/* SWP/SWPB */
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
}
else
{
/* STREX/LDREX variants and unallocaed space */
return
INSN_REJECTED
;
}
}
else
if
((
insn
&
0x0e1000d0
)
==
0x00000d0
)
{
}
else
if
((
insn
&
0x0e1000d0
)
==
0x00000d0
)
{
/* STRD/LDRD */
/* STRD/LDRD */
if
((
insn
&
0x0000e000
)
==
0x0000e000
)
return
INSN_REJECTED
;
/* Rd is LR or PC */
if
(
is_writeback
(
insn
)
&&
is_r15
(
insn
,
16
))
return
INSN_REJECTED
;
/* Writeback to PC */
insn
&=
0xfff00fff
;
insn
&=
0xfff00fff
;
insn
|=
0x00002000
;
/* Rn = r0, Rd = r2 */
insn
|=
0x00002000
;
/* Rn = r0, Rd = r2 */
if
(
insn
&
(
1
<<
22
))
{
if
(
!
(
insn
&
(
1
<<
22
)
))
{
/*
I bit
*/
/*
Register index
*/
insn
&=
~
0xf
;
insn
&=
~
0xf
;
insn
|=
1
;
/* Rm = r1 */
insn
|=
1
;
/* Rm = r1 */
}
}
...
@@ -1118,6 +1159,9 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1118,6 +1159,9 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return
INSN_GOOD
;
return
INSN_GOOD
;
}
}
/* LDRH/STRH/LDRSB/LDRSH */
if
(
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* Rd is PC */
return
prep_emulate_ldr_str
(
insn
,
asi
);
return
prep_emulate_ldr_str
(
insn
,
asi
);
}
}
...
@@ -1125,7 +1169,7 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1125,7 +1169,7 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/*
/*
* ALU op with S bit and Rd == 15 :
* ALU op with S bit and Rd == 15 :
*
cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
* cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
*/
*/
if
((
insn
&
0x0e10f000
)
==
0x0010f000
)
if
((
insn
&
0x0e10f000
)
==
0x0010f000
)
return
INSN_REJECTED
;
return
INSN_REJECTED
;
...
@@ -1154,22 +1198,61 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1154,22 +1198,61 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
insn
|=
0x00000200
;
/* Rs = r2 */
insn
|=
0x00000200
;
/* Rs = r2 */
}
}
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
(
insn
&
(
1
<<
20
))
?
/* S-bit */
if
((
insn
&
0x0f900000
)
==
0x01100000
)
{
/*
* TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
* TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
* CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
* CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
*/
asi
->
insn_handler
=
emulate_alu_tests
;
}
else
{
/* ALU ops which write to Rd */
asi
->
insn_handler
=
(
insn
&
(
1
<<
20
))
?
/* S-bit */
emulate_alu_rwflags
:
emulate_alu_rflags
;
emulate_alu_rwflags
:
emulate_alu_rflags
;
}
return
INSN_GOOD
;
return
INSN_GOOD
;
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
space_cccc_001x
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
space_cccc_001x
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
/* MOVW : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
/* MOVT : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
if
((
insn
&
0x0fb00000
)
==
0x03000000
)
return
prep_emulate_rd12_modify
(
insn
,
asi
);
/* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
if
((
insn
&
0x0fff0000
)
==
0x03200000
)
{
unsigned
op2
=
insn
&
0x000000ff
;
if
(
op2
==
0x01
||
op2
==
0x04
)
{
/* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
/* SEV : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_none
;
return
INSN_GOOD
;
}
else
if
(
op2
<=
0x03
)
{
/* NOP : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
/* WFE : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
/* WFI : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
/*
* We make WFE and WFI true NOPs to avoid stalls due
* to missing events whilst processing the probe.
*/
asi
->
insn_handler
=
emulate_nop
;
return
INSN_GOOD_NO_SLOT
;
}
/* For DBG and unallocated hints it's safest to reject them */
return
INSN_REJECTED
;
}
/*
/*
* MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
* MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
* Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx
* ALU op with S bit and Rd == 15 :
* ALU op with S bit and Rd == 15 :
* cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
* cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
*/
*/
if
((
insn
&
0x0fb00000
)
==
0x03200000
||
/* MSR */
if
((
insn
&
0x0fb00000
)
==
0x03200000
||
/* MSR */
(
insn
&
0x0ff00000
)
==
0x03400000
||
/* Undef */
(
insn
&
0x0e10f000
)
==
0x0210f000
)
/* ALU s-bit, R15 */
(
insn
&
0x0e10f000
)
==
0x0210f000
)
/* ALU s-bit, R15 */
return
INSN_REJECTED
;
return
INSN_REJECTED
;
...
@@ -1180,10 +1263,22 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1180,10 +1263,22 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
* *S (bit 20) updates condition codes
* *S (bit 20) updates condition codes
* ADC/SBC/RSC reads the C flag
* ADC/SBC/RSC reads the C flag
*/
*/
insn
&=
0xfff
f0fff
;
/*
Rd = r0 */
insn
&=
0xfff
00fff
;
/* Rn = r0 and
Rd = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
(
insn
&
(
1
<<
20
))
?
/* S-bit */
if
((
insn
&
0x0f900000
)
==
0x03100000
)
{
/*
* TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx
* TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx
* CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx
* CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx
*/
asi
->
insn_handler
=
emulate_alu_tests_imm
;
}
else
{
/* ALU ops which write to Rd */
asi
->
insn_handler
=
(
insn
&
(
1
<<
20
))
?
/* S-bit */
emulate_alu_imm_rwflags
:
emulate_alu_imm_rflags
;
emulate_alu_imm_rwflags
:
emulate_alu_imm_rflags
;
}
return
INSN_GOOD
;
return
INSN_GOOD
;
}
}
...
@@ -1192,6 +1287,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1192,6 +1287,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
{
/* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
/* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
if
((
insn
&
0x0ff000f0
)
==
0x068000b0
)
{
if
((
insn
&
0x0ff000f0
)
==
0x068000b0
)
{
if
(
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xfff00ff0
;
/* Rd = r0, Rn = r0 */
insn
&=
0xfff00ff0
;
/* Rd = r0, Rn = r0 */
insn
|=
0x00000001
;
/* Rm = r1 */
insn
|=
0x00000001
;
/* Rm = r1 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
...
@@ -1205,6 +1302,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1205,6 +1302,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
/* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
if
((
insn
&
0x0fa00030
)
==
0x06a00010
||
if
((
insn
&
0x0fa00030
)
==
0x06a00010
||
(
insn
&
0x0fb000f0
)
==
0x06a00030
)
{
(
insn
&
0x0fb000f0
)
==
0x06a00030
)
{
if
(
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* Rd is PC */
insn
&=
0xffff0ff0
;
/* Rd = r0, Rm = r0 */
insn
&=
0xffff0ff0
;
/* Rd = r0, Rm = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_sat
;
asi
->
insn_handler
=
emulate_sat
;
...
@@ -1213,57 +1312,101 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1213,57 +1312,101 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* REV : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
/* REV : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
/* REV16 : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
/* REV16 : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
/* RBIT : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
/* REVSH : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
/* REVSH : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
if
((
insn
&
0x0ff00070
)
==
0x06b00030
||
if
((
insn
&
0x0ff00070
)
==
0x06b00030
||
(
insn
&
0x0ff000
f0
)
==
0x06f000b
0
)
(
insn
&
0x0ff000
70
)
==
0x06f0003
0
)
return
prep_emulate_rd12rm0
(
insn
,
asi
);
return
prep_emulate_rd12rm0
(
insn
,
asi
);
/* ??? : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx : */
/* SADD16 : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
/* SADD16 : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
/* SADDSUBX : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
/* SADDSUBX : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
/* SSUBADDX : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
/* SSUBADDX : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
/* SSUB16 : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
/* SSUB16 : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
/* SADD8 : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
/* SADD8 : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
/* ??? : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx : */
/* ??? : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx : */
/* SSUB8 : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
/* SSUB8 : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
/* QADD16 : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx : */
/* QADD16 : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx : */
/* QADDSUBX : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx : */
/* QADDSUBX : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx : */
/* QSUBADDX : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx : */
/* QSUBADDX : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx : */
/* QSUB16 : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx : */
/* QSUB16 : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx : */
/* QADD8 : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx : */
/* QADD8 : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx : */
/* ??? : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx : */
/* ??? : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx : */
/* QSUB8 : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx : */
/* QSUB8 : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx : */
/* SHADD16 : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx : */
/* SHADD16 : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx : */
/* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx : */
/* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx : */
/* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx : */
/* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx : */
/* SHSUB16 : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx : */
/* SHSUB16 : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx : */
/* SHADD8 : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx : */
/* SHADD8 : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx : */
/* ??? : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx : */
/* ??? : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx : */
/* SHSUB8 : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx : */
/* SHSUB8 : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx : */
/* ??? : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx : */
/* UADD16 : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
/* UADD16 : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
/* UADDSUBX : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
/* UADDSUBX : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
/* USUBADDX : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
/* USUBADDX : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
/* USUB16 : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
/* USUB16 : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
/* UADD8 : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
/* UADD8 : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
/* ??? : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx : */
/* ??? : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx : */
/* USUB8 : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
/* USUB8 : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
/* UQADD16 : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx : */
/* UQADD16 : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx : */
/* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx : */
/* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx : */
/* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx : */
/* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx : */
/* UQSUB16 : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx : */
/* UQSUB16 : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx : */
/* UQADD8 : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx : */
/* UQADD8 : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx : */
/* ??? : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx : */
/* ??? : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx : */
/* UQSUB8 : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx : */
/* UQSUB8 : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx : */
/* UHADD16 : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx : */
/* UHADD16 : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx : */
/* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx : */
/* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx : */
/* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx : */
/* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx : */
/* UHSUB16 : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx : */
/* UHSUB16 : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx : */
/* UHADD8 : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx : */
/* UHADD8 : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx : */
/* ??? : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx : */
/* ??? : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx : */
/* UHSUB8 : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx : */
/* UHSUB8 : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx : */
if
((
insn
&
0x0f800010
)
==
0x06000010
)
{
if
((
insn
&
0x00300000
)
==
0x00000000
||
(
insn
&
0x000000e0
)
==
0x000000a0
||
(
insn
&
0x000000e0
)
==
0x000000c0
)
return
INSN_REJECTED
;
/* Unallocated space */
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
}
/* PKHBT : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx : */
/* PKHBT : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx : */
/* PKHTB : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx : */
/* PKHTB : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx : */
if
((
insn
&
0x0ff00030
)
==
0x06800010
)
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
/* SXTAB16 : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx : */
/* SXTAB16 : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx : */
/* SXTB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */
/* SXTB16 : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx : */
/* ??? : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx : */
/* SXTAB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */
/* SXTAB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */
/* SXTB : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx : */
/* SXTAH : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx : */
/* SXTAH : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx : */
/* SXTH : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx : */
/* UXTAB16 : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx : */
/* UXTAB16 : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx : */
/* UXTB16 : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx : */
/* ??? : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx : */
/* UXTAB : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx : */
/* UXTAB : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx : */
/* UXTB : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx : */
/* UXTAH : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx : */
/* UXTAH : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx : */
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
/* UXTH : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx : */
if
((
insn
&
0x0f8000f0
)
==
0x06800070
)
{
if
((
insn
&
0x00300000
)
==
0x00100000
)
return
INSN_REJECTED
;
/* Unallocated space */
if
((
insn
&
0x000f0000
)
==
0x000f0000
)
return
prep_emulate_rd12rm0
(
insn
,
asi
);
else
return
prep_emulate_rd12rn16rm0_wflags
(
insn
,
asi
);
}
/* Other instruction encodings aren't yet defined */
return
INSN_REJECTED
;
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
...
@@ -1273,29 +1416,49 @@ space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1273,29 +1416,49 @@ space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
if
((
insn
&
0x0ff000f0
)
==
0x03f000f0
)
if
((
insn
&
0x0ff000f0
)
==
0x03f000f0
)
return
INSN_REJECTED
;
return
INSN_REJECTED
;
/* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
/* USAD8 : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
if
((
insn
&
0x0ff000f0
)
==
0x07800010
)
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
/* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
/* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
/* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
/* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
if
((
insn
&
0x0ff00090
)
==
0x07400010
)
if
((
insn
&
0x0ff00090
)
==
0x07400010
)
return
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
insn
,
asi
);
return
prep_emulate_rdhi16rdlo12rs8rm0_wflags
(
insn
,
asi
);
/* SMLAD : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
/* SMLAD : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
/* SMUAD : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
/* SMLSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
/* SMLSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
/* SMUSD : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx : */
/* SMMLA : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx : */
/* SMMLA : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx : */
/* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */
/* SMMUL : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx : */
/* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx : */
/* USAD8 : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx : */
if
((
insn
&
0x0ff00090
)
==
0x07000010
||
if
((
insn
&
0x0ff00090
)
==
0x07000010
||
(
insn
&
0x0ff000d0
)
==
0x07500010
||
(
insn
&
0x0ff000d0
)
==
0x07500010
||
(
insn
&
0x0ff000d0
)
==
0x075000d0
)
(
insn
&
0x0ff000f0
)
==
0x07800010
)
{
if
((
insn
&
0x0000f000
)
==
0x0000f000
)
return
prep_emulate_rd16rs8rm0_wflags
(
insn
,
asi
);
else
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
}
/* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */
if
((
insn
&
0x0ff000d0
)
==
0x075000d0
)
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
return
prep_emulate_rd16rn12rs8rm0_wflags
(
insn
,
asi
);
/* SMUSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx : */
/* SBFX : cccc 0111 101x xxxx xxxx xxxx x101 xxxx : */
/* SMUAD : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
/* UBFX : cccc 0111 111x xxxx xxxx xxxx x101 xxxx : */
/* SMMUL : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx : */
if
((
insn
&
0x0fa00070
)
==
0x07a00050
)
return
prep_emulate_rd16rs8rm0_wflags
(
insn
,
asi
);
return
prep_emulate_rd12rm0
(
insn
,
asi
);
/* BFI : cccc 0111 110x xxxx xxxx xxxx x001 xxxx : */
/* BFC : cccc 0111 110x xxxx xxxx xxxx x001 1111 : */
if
((
insn
&
0x0fe00070
)
==
0x07c00010
)
{
if
((
insn
&
0x0000000f
)
==
0x0000000f
)
return
prep_emulate_rd12_modify
(
insn
,
asi
);
else
return
prep_emulate_rd12rn0_modify
(
insn
,
asi
);
}
return
INSN_REJECTED
;
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
...
@@ -1309,6 +1472,10 @@ space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1309,6 +1472,10 @@ space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* STRB : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
/* STRB : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
/* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
/* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
/* STRT : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
/* STRT : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
if
((
insn
&
0x00500000
)
==
0x00500000
&&
is_r15
(
insn
,
12
))
return
INSN_REJECTED
;
/* LDRB into PC */
return
prep_emulate_ldr_str
(
insn
,
asi
);
return
prep_emulate_ldr_str
(
insn
,
asi
);
}
}
...
@@ -1323,10 +1490,9 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1323,10 +1490,9 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
/* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
/* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
/* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
/* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
asi
->
insn
[
0
]
=
truecc_insn
(
insn
);
asi
->
insn_handler
=
((
insn
&
0x108000
)
==
0x008000
)
?
/* STM & R15 */
asi
->
insn_handler
=
((
insn
&
0x108000
)
==
0x008000
)
?
/* STM & R15 */
simulate_stm1_pc
:
simulate_ldm1stm1
;
simulate_stm1_pc
:
simulate_ldm1stm1
;
return
INSN_GOOD
;
return
INSN_GOOD
_NO_SLOT
;
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
...
@@ -1334,58 +1500,117 @@ space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1334,58 +1500,117 @@ space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
{
/* B : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
/* B : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
/* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
/* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
asi
->
insn
[
0
]
=
truecc_insn
(
insn
);
asi
->
insn_handler
=
simulate_bbl
;
asi
->
insn_handler
=
simulate_bbl
;
return
INSN_GOOD
;
return
INSN_GOOD
_NO_SLOT
;
}
}
static
enum
kprobe_insn
__kprobes
static
enum
kprobe_insn
__kprobes
space_cccc_11
00_010
x
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
space_cccc_11
x
x
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
/* Coprocessor instructions... */
/* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
/* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
/* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
/* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
insn
&=
0xfff00fff
;
/* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
insn
|=
0x00001000
;
/* Rn = r0, Rd = r1 */
/* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
asi
->
insn
[
0
]
=
insn
;
/* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
asi
->
insn_handler
=
(
insn
&
(
1
<<
20
))
?
emulate_mrrc
:
emulate_mcrr
;
/* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
return
INSN_GOOD
;
/* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
/* SVC : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
return
INSN_REJECTED
;
}
}
static
enum
kprobe_insn
__kprobes
static
unsigned
long
__kprobes
__check_eq
(
unsigned
long
cpsr
)
space_cccc_110x
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
/* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
return
cpsr
&
PSR_Z_BIT
;
/* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
insn
&=
0xfff0ffff
;
/* Rn = r0 */
asi
->
insn
[
0
]
=
insn
;
asi
->
insn_handler
=
emulate_ldcstc
;
return
INSN_GOOD
;
}
}
static
enum
kprobe_insn
__kprobes
static
unsigned
long
__kprobes
__check_ne
(
unsigned
long
cpsr
)
space_cccc_111x
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
return
(
~
cpsr
)
&
PSR_Z_BIT
;
/* SWI : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
}
if
((
insn
&
0xfff000f0
)
==
0xe1200070
||
(
insn
&
0x0f000000
)
==
0x0f000000
)
return
INSN_REJECTED
;
/* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
static
unsigned
long
__kprobes
__check_cs
(
unsigned
long
cpsr
)
if
((
insn
&
0x0f000010
)
==
0x0e000000
)
{
{
asi
->
insn
[
0
]
=
insn
;
return
cpsr
&
PSR_C_BIT
;
asi
->
insn_handler
=
emulate_none
;
}
return
INSN_GOOD
;
}
/* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
static
unsigned
long
__kprobes
__check_cc
(
unsigned
long
cpsr
)
/* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
{
insn
&=
0xffff0fff
;
/* Rd = r0 */
return
(
~
cpsr
)
&
PSR_C_BIT
;
asi
->
insn
[
0
]
=
insn
;
}
asi
->
insn_handler
=
(
insn
&
(
1
<<
20
))
?
emulate_rd12
:
emulate_ird12
;
return
INSN_GOOD
;
static
unsigned
long
__kprobes
__check_mi
(
unsigned
long
cpsr
)
{
return
cpsr
&
PSR_N_BIT
;
}
static
unsigned
long
__kprobes
__check_pl
(
unsigned
long
cpsr
)
{
return
(
~
cpsr
)
&
PSR_N_BIT
;
}
static
unsigned
long
__kprobes
__check_vs
(
unsigned
long
cpsr
)
{
return
cpsr
&
PSR_V_BIT
;
}
static
unsigned
long
__kprobes
__check_vc
(
unsigned
long
cpsr
)
{
return
(
~
cpsr
)
&
PSR_V_BIT
;
}
static
unsigned
long
__kprobes
__check_hi
(
unsigned
long
cpsr
)
{
cpsr
&=
~
(
cpsr
>>
1
);
/* PSR_C_BIT &= ~PSR_Z_BIT */
return
cpsr
&
PSR_C_BIT
;
}
}
static
unsigned
long
__kprobes
__check_ls
(
unsigned
long
cpsr
)
{
cpsr
&=
~
(
cpsr
>>
1
);
/* PSR_C_BIT &= ~PSR_Z_BIT */
return
(
~
cpsr
)
&
PSR_C_BIT
;
}
static
unsigned
long
__kprobes
__check_ge
(
unsigned
long
cpsr
)
{
cpsr
^=
(
cpsr
<<
3
);
/* PSR_N_BIT ^= PSR_V_BIT */
return
(
~
cpsr
)
&
PSR_N_BIT
;
}
static
unsigned
long
__kprobes
__check_lt
(
unsigned
long
cpsr
)
{
cpsr
^=
(
cpsr
<<
3
);
/* PSR_N_BIT ^= PSR_V_BIT */
return
cpsr
&
PSR_N_BIT
;
}
static
unsigned
long
__kprobes
__check_gt
(
unsigned
long
cpsr
)
{
unsigned
long
temp
=
cpsr
^
(
cpsr
<<
3
);
/* PSR_N_BIT ^= PSR_V_BIT */
temp
|=
(
cpsr
<<
1
);
/* PSR_N_BIT |= PSR_Z_BIT */
return
(
~
temp
)
&
PSR_N_BIT
;
}
static
unsigned
long
__kprobes
__check_le
(
unsigned
long
cpsr
)
{
unsigned
long
temp
=
cpsr
^
(
cpsr
<<
3
);
/* PSR_N_BIT ^= PSR_V_BIT */
temp
|=
(
cpsr
<<
1
);
/* PSR_N_BIT |= PSR_Z_BIT */
return
temp
&
PSR_N_BIT
;
}
static
unsigned
long
__kprobes
__check_al
(
unsigned
long
cpsr
)
{
return
true
;
}
static
kprobe_check_cc
*
const
condition_checks
[
16
]
=
{
&
__check_eq
,
&
__check_ne
,
&
__check_cs
,
&
__check_cc
,
&
__check_mi
,
&
__check_pl
,
&
__check_vs
,
&
__check_vc
,
&
__check_hi
,
&
__check_ls
,
&
__check_ge
,
&
__check_lt
,
&
__check_gt
,
&
__check_le
,
&
__check_al
,
&
__check_al
};
/* Return:
/* Return:
* INSN_REJECTED If instruction is one not allowed to kprobe,
* INSN_REJECTED If instruction is one not allowed to kprobe,
* INSN_GOOD If instruction is supported and uses instruction slot,
* INSN_GOOD If instruction is supported and uses instruction slot,
...
@@ -1401,133 +1626,45 @@ space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
...
@@ -1401,133 +1626,45 @@ space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
enum
kprobe_insn
__kprobes
enum
kprobe_insn
__kprobes
arm_kprobe_decode_insn
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
arm_kprobe_decode_insn
(
kprobe_opcode_t
insn
,
struct
arch_specific_insn
*
asi
)
{
{
asi
->
insn_check_cc
=
condition_checks
[
insn
>>
28
];
asi
->
insn
[
1
]
=
KPROBE_RETURN_INSTRUCTION
;
asi
->
insn
[
1
]
=
KPROBE_RETURN_INSTRUCTION
;
if
((
insn
&
0xf0000000
)
==
0xf0000000
)
{
if
((
insn
&
0xf0000000
)
==
0xf0000000
)
return
space_1111
(
insn
,
asi
);
return
space_1111
(
insn
,
asi
);
}
else
if
((
insn
&
0x0e000000
)
==
0x00000000
)
{
else
if
((
insn
&
0x0e000000
)
==
0x00000000
)
return
space_cccc_000x
(
insn
,
asi
);
return
space_cccc_000x
(
insn
,
asi
);
}
else
if
((
insn
&
0x0e000000
)
==
0x02000000
)
{
else
if
((
insn
&
0x0e000000
)
==
0x02000000
)
return
space_cccc_001x
(
insn
,
asi
);
return
space_cccc_001x
(
insn
,
asi
);
}
else
if
((
insn
&
0x0f000010
)
==
0x06000010
)
{
else
if
((
insn
&
0x0f000010
)
==
0x06000010
)
return
space_cccc_0110__1
(
insn
,
asi
);
return
space_cccc_0110__1
(
insn
,
asi
);
}
else
if
((
insn
&
0x0f000010
)
==
0x07000010
)
{
else
if
((
insn
&
0x0f000010
)
==
0x07000010
)
return
space_cccc_0111__1
(
insn
,
asi
);
return
space_cccc_0111__1
(
insn
,
asi
);
}
else
if
((
insn
&
0x0c000000
)
==
0x04000000
)
{
else
if
((
insn
&
0x0c000000
)
==
0x04000000
)
return
space_cccc_01xx
(
insn
,
asi
);
return
space_cccc_01xx
(
insn
,
asi
);
}
else
if
((
insn
&
0x0e000000
)
==
0x08000000
)
{
else
if
((
insn
&
0x0e000000
)
==
0x08000000
)
return
space_cccc_100x
(
insn
,
asi
);
return
space_cccc_100x
(
insn
,
asi
);
}
else
if
((
insn
&
0x0e000000
)
==
0x0a000000
)
{
else
if
((
insn
&
0x0e000000
)
==
0x0a000000
)
return
space_cccc_101x
(
insn
,
asi
);
return
space_cccc_101x
(
insn
,
asi
);
}
else
if
((
insn
&
0x0fe00000
)
==
0x0c400000
)
{
return
space_cccc_11xx
(
insn
,
asi
);
return
space_cccc_1100_010x
(
insn
,
asi
);
}
else
if
((
insn
&
0x0e000000
)
==
0x0c000000
)
{
return
space_cccc_110x
(
insn
,
asi
);
}
return
space_cccc_111x
(
insn
,
asi
);
}
}
void
__init
arm_kprobe_decode_init
(
void
)
void
__init
arm_kprobe_decode_init
(
void
)
{
{
find_str_pc_offset
();
find_str_pc_offset
();
}
}
/*
* All ARM instructions listed below.
*
* Instructions and their general purpose registers are given.
* If a particular register may not use R15, it is prefixed with a "!".
* If marked with a "*" means the value returned by reading R15
* is implementation defined.
*
* ADC/ADD/AND/BIC/CMN/CMP/EOR/MOV/MVN/ORR/RSB/RSC/SBC/SUB/TEQ
* TST: Rd, Rn, Rm, !Rs
* BX: Rm
* BLX(2): !Rm
* BX: Rm (R15 legal, but discouraged)
* BXJ: !Rm,
* CLZ: !Rd, !Rm
* CPY: Rd, Rm
* LDC/2,STC/2 immediate offset & unindex: Rn
* LDC/2,STC/2 immediate pre/post-indexed: !Rn
* LDM(1/3): !Rn, register_list
* LDM(2): !Rn, !register_list
* LDR,STR,PLD immediate offset: Rd, Rn
* LDR,STR,PLD register offset: Rd, Rn, !Rm
* LDR,STR,PLD scaled register offset: Rd, !Rn, !Rm
* LDR,STR immediate pre/post-indexed: Rd, !Rn
* LDR,STR register pre/post-indexed: Rd, !Rn, !Rm
* LDR,STR scaled register pre/post-indexed: Rd, !Rn, !Rm
* LDRB,STRB immediate offset: !Rd, Rn
* LDRB,STRB register offset: !Rd, Rn, !Rm
* LDRB,STRB scaled register offset: !Rd, !Rn, !Rm
* LDRB,STRB immediate pre/post-indexed: !Rd, !Rn
* LDRB,STRB register pre/post-indexed: !Rd, !Rn, !Rm
* LDRB,STRB scaled register pre/post-indexed: !Rd, !Rn, !Rm
* LDRT,LDRBT,STRBT immediate pre/post-indexed: !Rd, !Rn
* LDRT,LDRBT,STRBT register pre/post-indexed: !Rd, !Rn, !Rm
* LDRT,LDRBT,STRBT scaled register pre/post-indexed: !Rd, !Rn, !Rm
* LDRH/SH/SB/D,STRH/SH/SB/D immediate offset: !Rd, Rn
* LDRH/SH/SB/D,STRH/SH/SB/D register offset: !Rd, Rn, !Rm
* LDRH/SH/SB/D,STRH/SH/SB/D immediate pre/post-indexed: !Rd, !Rn
* LDRH/SH/SB/D,STRH/SH/SB/D register pre/post-indexed: !Rd, !Rn, !Rm
* LDREX: !Rd, !Rn
* MCR/2: !Rd
* MCRR/2,MRRC/2: !Rd, !Rn
* MLA: !Rd, !Rn, !Rm, !Rs
* MOV: Rd
* MRC/2: !Rd (if Rd==15, only changes cond codes, not the register)
* MRS,MSR: !Rd
* MUL: !Rd, !Rm, !Rs
* PKH{BT,TB}: !Rd, !Rn, !Rm
* QDADD,[U]QADD/16/8/SUBX: !Rd, !Rm, !Rn
* QDSUB,[U]QSUB/16/8/ADDX: !Rd, !Rm, !Rn
* REV/16/SH: !Rd, !Rm
* RFE: !Rn
* {S,U}[H]ADD{16,8,SUBX},{S,U}[H]SUB{16,8,ADDX}: !Rd, !Rn, !Rm
* SEL: !Rd, !Rn, !Rm
* SMLA<x><y>,SMLA{D,W<y>},SMLSD,SMML{A,S}: !Rd, !Rn, !Rm, !Rs
* SMLAL<x><y>,SMLA{D,LD},SMLSLD,SMMULL,SMULW<y>: !RdHi, !RdLo, !Rm, !Rs
* SMMUL,SMUAD,SMUL<x><y>,SMUSD: !Rd, !Rm, !Rs
* SSAT/16: !Rd, !Rm
* STM(1/2): !Rn, register_list* (R15 in reg list not recommended)
* STRT immediate pre/post-indexed: Rd*, !Rn
* STRT register pre/post-indexed: Rd*, !Rn, !Rm
* STRT scaled register pre/post-indexed: Rd*, !Rn, !Rm
* STREX: !Rd, !Rn, !Rm
* SWP/B: !Rd, !Rn, !Rm
* {S,U}XTA{B,B16,H}: !Rd, !Rn, !Rm
* {S,U}XT{B,B16,H}: !Rd, !Rm
* UM{AA,LA,UL}L: !RdHi, !RdLo, !Rm, !Rs
* USA{D8,A8,T,T16}: !Rd, !Rm, !Rs
*
* May transfer control by writing R15 (possible mode changes or alternate
* mode accesses marked by "*"):
* ALU op (* with s-bit), B, BL, BKPT, BLX(1/2), BX, BXJ, CPS*, CPY,
* LDM(1), LDM(2/3)*, LDR, MOV, RFE*, SWI*
*
* Instructions that do not take general registers, nor transfer control:
* CDP/2, SETEND, SRS*
*/
arch/arm/kernel/kprobes.c
浏览文件 @
408133e9
...
@@ -134,7 +134,8 @@ static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
...
@@ -134,7 +134,8 @@ static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
struct
kprobe_ctlblk
*
kcb
)
struct
kprobe_ctlblk
*
kcb
)
{
{
regs
->
ARM_pc
+=
4
;
regs
->
ARM_pc
+=
4
;
p
->
ainsn
.
insn_handler
(
p
,
regs
);
if
(
p
->
ainsn
.
insn_check_cc
(
regs
->
ARM_cpsr
))
p
->
ainsn
.
insn_handler
(
p
,
regs
);
}
}
/*
/*
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录