aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/probes/kprobes
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-01-05 06:29:21 -0500
committerJon Medhurst <tixy@linaro.org>2015-01-13 11:10:06 -0500
commit6624cf651f1a14363d0385f36dc255d304ac7ebb (patch)
tree38cb38d33f5faa96e36814caa3fa63bfe322c193 /arch/arm/probes/kprobes
parent83803d97dae1eaf6850a45ef8ee179cc66e147dc (diff)
ARM: kprobes: collects stack consumption for store instructions
This patch uses the previously introduced checker functionality on store instructions to record their stack consumption information to arch_probes_insn. Signed-off-by: Wang Nan <wangnan0@huawei.com> Reviewed-by: Jon Medhurst <tixy@linaro.org> Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'arch/arm/probes/kprobes')
-rw-r--r--arch/arm/probes/kprobes/Makefile6
-rw-r--r--arch/arm/probes/kprobes/actions-arm.c3
-rw-r--r--arch/arm/probes/kprobes/actions-thumb.c5
-rw-r--r--arch/arm/probes/kprobes/checkers-arm.c99
-rw-r--r--arch/arm/probes/kprobes/checkers-common.c101
-rw-r--r--arch/arm/probes/kprobes/checkers-thumb.c110
-rw-r--r--arch/arm/probes/kprobes/checkers.h54
7 files changed, 372 insertions, 6 deletions
diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile
index eb38a428ecd6..bc8d504c3d78 100644
--- a/arch/arm/probes/kprobes/Makefile
+++ b/arch/arm/probes/kprobes/Makefile
@@ -1,11 +1,11 @@
1obj-$(CONFIG_KPROBES) += core.o actions-common.o 1obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o
2obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o 2obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o
3test-kprobes-objs := test-core.o 3test-kprobes-objs := test-core.o
4 4
5ifdef CONFIG_THUMB2_KERNEL 5ifdef CONFIG_THUMB2_KERNEL
6obj-$(CONFIG_KPROBES) += actions-thumb.o 6obj-$(CONFIG_KPROBES) += actions-thumb.o checkers-thumb.o
7test-kprobes-objs += test-thumb.o 7test-kprobes-objs += test-thumb.o
8else 8else
9obj-$(CONFIG_KPROBES) += actions-arm.o 9obj-$(CONFIG_KPROBES) += actions-arm.o checkers-arm.o
10test-kprobes-objs += test-arm.o 10test-kprobes-objs += test-arm.o
11endif 11endif
diff --git a/arch/arm/probes/kprobes/actions-arm.c b/arch/arm/probes/kprobes/actions-arm.c
index fbd93a9ada75..06988ef7eeb7 100644
--- a/arch/arm/probes/kprobes/actions-arm.c
+++ b/arch/arm/probes/kprobes/actions-arm.c
@@ -64,6 +64,7 @@
64 64
65#include "../decode-arm.h" 65#include "../decode-arm.h"
66#include "core.h" 66#include "core.h"
67#include "checkers.h"
67 68
68#if __LINUX_ARM_ARCH__ >= 6 69#if __LINUX_ARM_ARCH__ >= 6
69#define BLX(reg) "blx "reg" \n\t" 70#define BLX(reg) "blx "reg" \n\t"
@@ -340,4 +341,4 @@ const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
340 [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} 341 [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
341}; 342};
342 343
343const struct decode_checker *kprobes_arm_checkers[] = {NULL}; 344const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, NULL};
diff --git a/arch/arm/probes/kprobes/actions-thumb.c b/arch/arm/probes/kprobes/actions-thumb.c
index 2796121fe90e..07cfd9bef340 100644
--- a/arch/arm/probes/kprobes/actions-thumb.c
+++ b/arch/arm/probes/kprobes/actions-thumb.c
@@ -15,6 +15,7 @@
15 15
16#include "../decode-thumb.h" 16#include "../decode-thumb.h"
17#include "core.h" 17#include "core.h"
18#include "checkers.h"
18 19
19/* These emulation encodings are functionally equivalent... */ 20/* These emulation encodings are functionally equivalent... */
20#define t32_emulate_rd8rn16rm0ra12_noflags \ 21#define t32_emulate_rd8rn16rm0ra12_noflags \
@@ -665,5 +666,5 @@ const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = {
665 .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, 666 .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags},
666}; 667};
667 668
668const struct decode_checker *kprobes_t32_checkers[] = {NULL}; 669const struct decode_checker *kprobes_t32_checkers[] = {t32_stack_checker, NULL};
669const struct decode_checker *kprobes_t16_checkers[] = {NULL}; 670const struct decode_checker *kprobes_t16_checkers[] = {t16_stack_checker, NULL};
diff --git a/arch/arm/probes/kprobes/checkers-arm.c b/arch/arm/probes/kprobes/checkers-arm.c
new file mode 100644
index 000000000000..f8176631d2a5
--- /dev/null
+++ b/arch/arm/probes/kprobes/checkers-arm.c
@@ -0,0 +1,99 @@
1/*
2 * arch/arm/probes/kprobes/checkers-arm.c
3 *
4 * Copyright (C) 2014 Huawei Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15
16#include <linux/kernel.h>
17#include "../decode.h"
18#include "../decode-arm.h"
19#include "checkers.h"
20
21static enum probes_insn __kprobes arm_check_stack(probes_opcode_t insn,
22 struct arch_probes_insn *asi,
23 const struct decode_header *h)
24{
25 /*
26 * PROBES_LDRSTRD, PROBES_LDMSTM, PROBES_STORE,
27 * PROBES_STORE_EXTRA may get here. Simply mark all normal
28 * insns as STACK_USE_NONE.
29 */
30 static const union decode_item table[] = {
31 /*
32 * 'STR{,D,B,H}, Rt, [Rn, Rm]' should be marked as UNKNOWN
33 * if Rn or Rm is SP.
34 * x
35 * STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx
36 * STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx
37 */
38 DECODE_OR (0x0e10000f, 0x0600000d),
39 DECODE_OR (0x0e1f0000, 0x060d0000),
40
41 /*
42 * x
43 * STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx
44 * STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx
45 */
46 DECODE_OR (0x0e5000bf, 0x000000bd),
47 DECODE_CUSTOM (0x0e5f00b0, 0x000d00b0, STACK_USE_UNKNOWN),
48
49 /*
50 * For PROBES_LDMSTM, only stmdx sp, [...] need to examine
51 *
52 * Bit B/A (bit 24) encodes arithmetic operation order. 1 means
53 * before, 0 means after.
54 * Bit I/D (bit 23) encodes arithmetic operation. 1 means
55 * increment, 0 means decrement.
56 *
57 * So:
58 * B I
59 * / /
60 * A D | Rn |
61 * STMDX SP, [...] cccc 100x 00x0 xxxx xxxx xxxx xxxx xxxx
62 */
63 DECODE_CUSTOM (0x0edf0000, 0x080d0000, STACK_USE_STMDX),
64
65 /* P U W | Rn | Rt | imm12 |*/
66 /* STR (immediate) cccc 010x x0x0 1101 xxxx xxxx xxxx xxxx */
67 /* STRB (immediate) cccc 010x x1x0 1101 xxxx xxxx xxxx xxxx */
68 /* P U W | Rn | Rt |imm4| |imm4|*/
69 /* STRD (immediate) cccc 000x x1x0 1101 xxxx xxxx 1111 xxxx */
70 /* STRH (immediate) cccc 000x x1x0 1101 xxxx xxxx 1011 xxxx */
71 /*
72 * index = (P == '1'); add = (U == '1').
73 * Above insns with:
74 * index == 0 (str{,d,h} rx, [sp], #+/-imm) or
75 * add == 1 (str{,d,h} rx, [sp, #+<imm>])
76 * should be STACK_USE_NONE.
77 * Only str{,b,d,h} rx,[sp,#-n] (P == 1 and U == 0) are
78 * required to be examined.
79 */
80 /* STR{,B} Rt,[SP,#-n] cccc 0101 0xx0 1101 xxxx xxxx xxxx xxxx */
81 DECODE_CUSTOM (0x0f9f0000, 0x050d0000, STACK_USE_FIXED_XXX),
82
83 /* STR{D,H} Rt,[SP,#-n] cccc 0001 01x0 1101 xxxx xxxx 1x11 xxxx */
84 DECODE_CUSTOM (0x0fdf00b0, 0x014d00b0, STACK_USE_FIXED_X0X),
85
86 /* fall through */
87 DECODE_CUSTOM (0, 0, STACK_USE_NONE),
88 DECODE_END
89 };
90
91 return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL);
92}
93
94const struct decode_checker arm_stack_checker[NUM_PROBES_ARM_ACTIONS] = {
95 [PROBES_LDRSTRD] = {.checker = arm_check_stack},
96 [PROBES_STORE_EXTRA] = {.checker = arm_check_stack},
97 [PROBES_STORE] = {.checker = arm_check_stack},
98 [PROBES_LDMSTM] = {.checker = arm_check_stack},
99};
diff --git a/arch/arm/probes/kprobes/checkers-common.c b/arch/arm/probes/kprobes/checkers-common.c
new file mode 100644
index 000000000000..971119c29474
--- /dev/null
+++ b/arch/arm/probes/kprobes/checkers-common.c
@@ -0,0 +1,101 @@
1/*
2 * arch/arm/probes/kprobes/checkers-common.c
3 *
4 * Copyright (C) 2014 Huawei Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15
16#include <linux/kernel.h>
17#include "../decode.h"
18#include "../decode-arm.h"
19#include "checkers.h"
20
21enum probes_insn checker_stack_use_none(probes_opcode_t insn,
22 struct arch_probes_insn *asi,
23 const struct decode_header *h)
24{
25 asi->stack_space = 0;
26 return INSN_GOOD_NO_SLOT;
27}
28
29enum probes_insn checker_stack_use_unknown(probes_opcode_t insn,
30 struct arch_probes_insn *asi,
31 const struct decode_header *h)
32{
33 asi->stack_space = -1;
34 return INSN_GOOD_NO_SLOT;
35}
36
37#ifdef CONFIG_THUMB2_KERNEL
38enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn,
39 struct arch_probes_insn *asi,
40 const struct decode_header *h)
41{
42 int imm = insn & 0xff;
43 asi->stack_space = imm;
44 return INSN_GOOD_NO_SLOT;
45}
46
47/*
48 * Different from other insn uses imm8, the real addressing offset of
49 * STRD in T32 encoding should be imm8 * 4. See ARMARM description.
50 */
51enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
52 struct arch_probes_insn *asi,
53 const struct decode_header *h)
54{
55 int imm = insn & 0xff;
56 asi->stack_space = imm << 2;
57 return INSN_GOOD_NO_SLOT;
58}
59#else
60enum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn,
61 struct arch_probes_insn *asi,
62 const struct decode_header *h)
63{
64 int imm = ((insn & 0xf00) >> 4) + (insn & 0xf);
65 asi->stack_space = imm;
66 return INSN_GOOD_NO_SLOT;
67}
68#endif
69
70enum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn,
71 struct arch_probes_insn *asi,
72 const struct decode_header *h)
73{
74 int imm = insn & 0xfff;
75 asi->stack_space = imm;
76 return INSN_GOOD_NO_SLOT;
77}
78
79enum probes_insn checker_stack_use_stmdx(probes_opcode_t insn,
80 struct arch_probes_insn *asi,
81 const struct decode_header *h)
82{
83 unsigned int reglist = insn & 0xffff;
84 int pbit = insn & (1 << 24);
85 asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4;
86
87 return INSN_GOOD_NO_SLOT;
88}
89
90const union decode_action stack_check_actions[] = {
91 [STACK_USE_NONE] = {.decoder = checker_stack_use_none},
92 [STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown},
93#ifdef CONFIG_THUMB2_KERNEL
94 [STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx},
95 [STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd},
96#else
97 [STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x},
98#endif
99 [STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx},
100 [STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx},
101};
diff --git a/arch/arm/probes/kprobes/checkers-thumb.c b/arch/arm/probes/kprobes/checkers-thumb.c
new file mode 100644
index 000000000000..d608e3b9017a
--- /dev/null
+++ b/arch/arm/probes/kprobes/checkers-thumb.c
@@ -0,0 +1,110 @@
1/*
2 * arch/arm/probes/kprobes/checkers-thumb.c
3 *
4 * Copyright (C) 2014 Huawei Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15
16#include <linux/kernel.h>
17#include "../decode.h"
18#include "../decode-thumb.h"
19#include "checkers.h"
20
21static enum probes_insn __kprobes t32_check_stack(probes_opcode_t insn,
22 struct arch_probes_insn *asi,
23 const struct decode_header *h)
24{
25 /*
26 * PROBES_T32_LDMSTM, PROBES_T32_LDRDSTRD and PROBES_T32_LDRSTR
27 * may get here. Simply mark all normal insns as STACK_USE_NONE.
28 */
29 static const union decode_item table[] = {
30
31 /*
32 * First, filter out all ldr insns to make our life easier.
33 * Following load insns may come here:
34 * LDM, LDRD, LDR.
35 * In T32 encoding, bit 20 is enough for distinguishing
36 * load and store. All load insns have this bit set, when
37 * all store insns have this bit clear.
38 */
39 DECODE_CUSTOM (0x00100000, 0x00100000, STACK_USE_NONE),
40
41 /*
42 * Mark all 'STR{,B,H}, Rt, [Rn, Rm]' as STACK_USE_UNKNOWN
43 * if Rn or Rm is SP. T32 doesn't encode STRD.
44 */
45 /* xx | Rn | Rt | | Rm |*/
46 /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
47 /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
48 /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
49 /* INVALID INSN 1111 1000 0110 xxxx xxxx 0000 00xx xxxx */
50 /* By Introducing INVALID INSN, bit 21 and 22 can be ignored. */
51 DECODE_OR (0xff9f0fc0, 0xf80d0000),
52 DECODE_CUSTOM (0xff900fcf, 0xf800000d, STACK_USE_UNKNOWN),
53
54
55 /* xx | Rn | Rt | PUW| imm8 |*/
56 /* STR (imm 8) 1111 1000 0100 1101 xxxx 110x xxxx xxxx */
57 /* STRB (imm 8) 1111 1000 0000 1101 xxxx 110x xxxx xxxx */
58 /* STRH (imm 8) 1111 1000 0010 1101 xxxx 110x xxxx xxxx */
59 /* INVALID INSN 1111 1000 0110 1101 xxxx 110x xxxx xxxx */
60 /* Only consider U == 0 and P == 1: strx rx, [sp, #-<imm>] */
61 DECODE_CUSTOM (0xff9f0e00, 0xf80d0c00, STACK_USE_FIXED_0XX),
62
63 /* For STR{,B,H} (imm 12), offset is always positive, so ignore them. */
64
65 /* P U W | Rn | Rt | Rt2| imm8 |*/
66 /* STRD (immediate) 1110 1001 01x0 1101 xxxx xxxx xxxx xxxx */
67 /*
68 * Only consider U == 0 and P == 1.
69 * Also note that STRD in T32 encoding is special:
70 * imm = ZeroExtend(imm8:'00', 32)
71 */
72 DECODE_CUSTOM (0xffdf0000, 0xe94d0000, STACK_USE_T32STRD),
73
74 /* | Rn | */
75 /* STMDB 1110 1001 00x0 1101 xxxx xxxx xxxx xxxx */
76 DECODE_CUSTOM (0xffdf0000, 0xe90d0000, STACK_USE_STMDX),
77
78 /* fall through */
79 DECODE_CUSTOM (0, 0, STACK_USE_NONE),
80 DECODE_END
81 };
82
83 return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL);
84}
85
86const struct decode_checker t32_stack_checker[NUM_PROBES_T32_ACTIONS] = {
87 [PROBES_T32_LDMSTM] = {.checker = t32_check_stack},
88 [PROBES_T32_LDRDSTRD] = {.checker = t32_check_stack},
89 [PROBES_T32_LDRSTR] = {.checker = t32_check_stack},
90};
91
92/*
93 * See following comments. This insn must be 'push'.
94 */
95static enum probes_insn __kprobes t16_check_stack(probes_opcode_t insn,
96 struct arch_probes_insn *asi,
97 const struct decode_header *h)
98{
99 unsigned int reglist = insn & 0x1ff;
100 asi->stack_space = hweight32(reglist) * 4;
101 return INSN_GOOD;
102}
103
104/*
105 * T16 encoding is simple: only the 'push' insn can need extra stack space.
106 * Other insns, like str, can only use r0-r7 as Rn.
107 */
108const struct decode_checker t16_stack_checker[NUM_PROBES_T16_ACTIONS] = {
109 [PROBES_T16_PUSH] = {.checker = t16_check_stack},
110};
diff --git a/arch/arm/probes/kprobes/checkers.h b/arch/arm/probes/kprobes/checkers.h
new file mode 100644
index 000000000000..bddfa0e82389
--- /dev/null
+++ b/arch/arm/probes/kprobes/checkers.h
@@ -0,0 +1,54 @@
1/*
2 * arch/arm/probes/kprobes/checkers.h
3 *
4 * Copyright (C) 2014 Huawei Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15#ifndef _ARM_KERNEL_PROBES_CHECKERS_H
16#define _ARM_KERNEL_PROBES_CHECKERS_H
17
18#include <linux/kernel.h>
19#include <linux/types.h>
20#include "../decode.h"
21
22extern probes_check_t checker_stack_use_none;
23extern probes_check_t checker_stack_use_unknown;
24#ifdef CONFIG_THUMB2_KERNEL
25extern probes_check_t checker_stack_use_imm_0xx;
26#else
27extern probes_check_t checker_stack_use_imm_x0x;
28#endif
29extern probes_check_t checker_stack_use_imm_xxx;
30extern probes_check_t checker_stack_use_stmdx;
31
32enum {
33 STACK_USE_NONE,
34 STACK_USE_UNKNOWN,
35#ifdef CONFIG_THUMB2_KERNEL
36 STACK_USE_FIXED_0XX,
37 STACK_USE_T32STRD,
38#else
39 STACK_USE_FIXED_X0X,
40#endif
41 STACK_USE_FIXED_XXX,
42 STACK_USE_STMDX,
43 NUM_STACK_USE_TYPES
44};
45
46extern const union decode_action stack_check_actions[];
47
48#ifndef CONFIG_THUMB2_KERNEL
49extern const struct decode_checker arm_stack_checker[];
50#else
51#endif
52extern const struct decode_checker t32_stack_checker[];
53extern const struct decode_checker t16_stack_checker[];
54#endif