diff options
-rw-r--r-- | arch/arm/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 92 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-common.c | 105 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes.h | 2 |
4 files changed, 109 insertions, 92 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 914c7a6f1706..a22b8f1c7b14 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -37,7 +37,7 @@ obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o | |||
37 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 37 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
38 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 38 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
39 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 39 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
40 | obj-$(CONFIG_KPROBES) += kprobes.o | 40 | obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o |
41 | obj-$(CONFIG_KPROBES) += kprobes-arm.o | 41 | obj-$(CONFIG_KPROBES) += kprobes-arm.o |
42 | obj-$(CONFIG_ATAGS_PROC) += atags.o | 42 | obj-$(CONFIG_ATAGS_PROC) += atags.o |
43 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 43 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 976ce14c5576..8d4464f9471b 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
@@ -1523,96 +1523,6 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi) | |||
1523 | return INSN_REJECTED; | 1523 | return INSN_REJECTED; |
1524 | } | 1524 | } |
1525 | 1525 | ||
1526 | static unsigned long __kprobes __check_eq(unsigned long cpsr) | ||
1527 | { | ||
1528 | return cpsr & PSR_Z_BIT; | ||
1529 | } | ||
1530 | |||
1531 | static unsigned long __kprobes __check_ne(unsigned long cpsr) | ||
1532 | { | ||
1533 | return (~cpsr) & PSR_Z_BIT; | ||
1534 | } | ||
1535 | |||
1536 | static unsigned long __kprobes __check_cs(unsigned long cpsr) | ||
1537 | { | ||
1538 | return cpsr & PSR_C_BIT; | ||
1539 | } | ||
1540 | |||
1541 | static unsigned long __kprobes __check_cc(unsigned long cpsr) | ||
1542 | { | ||
1543 | return (~cpsr) & PSR_C_BIT; | ||
1544 | } | ||
1545 | |||
1546 | static unsigned long __kprobes __check_mi(unsigned long cpsr) | ||
1547 | { | ||
1548 | return cpsr & PSR_N_BIT; | ||
1549 | } | ||
1550 | |||
1551 | static unsigned long __kprobes __check_pl(unsigned long cpsr) | ||
1552 | { | ||
1553 | return (~cpsr) & PSR_N_BIT; | ||
1554 | } | ||
1555 | |||
1556 | static unsigned long __kprobes __check_vs(unsigned long cpsr) | ||
1557 | { | ||
1558 | return cpsr & PSR_V_BIT; | ||
1559 | } | ||
1560 | |||
1561 | static unsigned long __kprobes __check_vc(unsigned long cpsr) | ||
1562 | { | ||
1563 | return (~cpsr) & PSR_V_BIT; | ||
1564 | } | ||
1565 | |||
1566 | static unsigned long __kprobes __check_hi(unsigned long cpsr) | ||
1567 | { | ||
1568 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
1569 | return cpsr & PSR_C_BIT; | ||
1570 | } | ||
1571 | |||
1572 | static unsigned long __kprobes __check_ls(unsigned long cpsr) | ||
1573 | { | ||
1574 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
1575 | return (~cpsr) & PSR_C_BIT; | ||
1576 | } | ||
1577 | |||
1578 | static unsigned long __kprobes __check_ge(unsigned long cpsr) | ||
1579 | { | ||
1580 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
1581 | return (~cpsr) & PSR_N_BIT; | ||
1582 | } | ||
1583 | |||
1584 | static unsigned long __kprobes __check_lt(unsigned long cpsr) | ||
1585 | { | ||
1586 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
1587 | return cpsr & PSR_N_BIT; | ||
1588 | } | ||
1589 | |||
1590 | static unsigned long __kprobes __check_gt(unsigned long cpsr) | ||
1591 | { | ||
1592 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
1593 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
1594 | return (~temp) & PSR_N_BIT; | ||
1595 | } | ||
1596 | |||
1597 | static unsigned long __kprobes __check_le(unsigned long cpsr) | ||
1598 | { | ||
1599 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
1600 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
1601 | return temp & PSR_N_BIT; | ||
1602 | } | ||
1603 | |||
1604 | static unsigned long __kprobes __check_al(unsigned long cpsr) | ||
1605 | { | ||
1606 | return true; | ||
1607 | } | ||
1608 | |||
1609 | static kprobe_check_cc * const condition_checks[16] = { | ||
1610 | &__check_eq, &__check_ne, &__check_cs, &__check_cc, | ||
1611 | &__check_mi, &__check_pl, &__check_vs, &__check_vc, | ||
1612 | &__check_hi, &__check_ls, &__check_ge, &__check_lt, | ||
1613 | &__check_gt, &__check_le, &__check_al, &__check_al | ||
1614 | }; | ||
1615 | |||
1616 | /* Return: | 1526 | /* Return: |
1617 | * INSN_REJECTED If instruction is one not allowed to kprobe, | 1527 | * INSN_REJECTED If instruction is one not allowed to kprobe, |
1618 | * INSN_GOOD If instruction is supported and uses instruction slot, | 1528 | * INSN_GOOD If instruction is supported and uses instruction slot, |
@@ -1628,7 +1538,7 @@ static kprobe_check_cc * const condition_checks[16] = { | |||
1628 | enum kprobe_insn __kprobes | 1538 | enum kprobe_insn __kprobes |
1629 | arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 1539 | arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) |
1630 | { | 1540 | { |
1631 | asi->insn_check_cc = condition_checks[insn>>28]; | 1541 | asi->insn_check_cc = kprobe_condition_checks[insn>>28]; |
1632 | asi->insn[1] = KPROBE_RETURN_INSTRUCTION; | 1542 | asi->insn[1] = KPROBE_RETURN_INSTRUCTION; |
1633 | 1543 | ||
1634 | if ((insn & 0xf0000000) == 0xf0000000) | 1544 | if ((insn & 0xf0000000) == 0xf0000000) |
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c new file mode 100644 index 000000000000..794827ec27d7 --- /dev/null +++ b/arch/arm/kernel/kprobes-common.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/kprobes-common.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | ||
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 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/kprobes.h> | ||
13 | |||
14 | #include "kprobes.h" | ||
15 | |||
16 | |||
17 | static unsigned long __kprobes __check_eq(unsigned long cpsr) | ||
18 | { | ||
19 | return cpsr & PSR_Z_BIT; | ||
20 | } | ||
21 | |||
22 | static unsigned long __kprobes __check_ne(unsigned long cpsr) | ||
23 | { | ||
24 | return (~cpsr) & PSR_Z_BIT; | ||
25 | } | ||
26 | |||
27 | static unsigned long __kprobes __check_cs(unsigned long cpsr) | ||
28 | { | ||
29 | return cpsr & PSR_C_BIT; | ||
30 | } | ||
31 | |||
32 | static unsigned long __kprobes __check_cc(unsigned long cpsr) | ||
33 | { | ||
34 | return (~cpsr) & PSR_C_BIT; | ||
35 | } | ||
36 | |||
37 | static unsigned long __kprobes __check_mi(unsigned long cpsr) | ||
38 | { | ||
39 | return cpsr & PSR_N_BIT; | ||
40 | } | ||
41 | |||
42 | static unsigned long __kprobes __check_pl(unsigned long cpsr) | ||
43 | { | ||
44 | return (~cpsr) & PSR_N_BIT; | ||
45 | } | ||
46 | |||
47 | static unsigned long __kprobes __check_vs(unsigned long cpsr) | ||
48 | { | ||
49 | return cpsr & PSR_V_BIT; | ||
50 | } | ||
51 | |||
52 | static unsigned long __kprobes __check_vc(unsigned long cpsr) | ||
53 | { | ||
54 | return (~cpsr) & PSR_V_BIT; | ||
55 | } | ||
56 | |||
57 | static unsigned long __kprobes __check_hi(unsigned long cpsr) | ||
58 | { | ||
59 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
60 | return cpsr & PSR_C_BIT; | ||
61 | } | ||
62 | |||
63 | static unsigned long __kprobes __check_ls(unsigned long cpsr) | ||
64 | { | ||
65 | cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ | ||
66 | return (~cpsr) & PSR_C_BIT; | ||
67 | } | ||
68 | |||
69 | static unsigned long __kprobes __check_ge(unsigned long cpsr) | ||
70 | { | ||
71 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
72 | return (~cpsr) & PSR_N_BIT; | ||
73 | } | ||
74 | |||
75 | static unsigned long __kprobes __check_lt(unsigned long cpsr) | ||
76 | { | ||
77 | cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
78 | return cpsr & PSR_N_BIT; | ||
79 | } | ||
80 | |||
81 | static unsigned long __kprobes __check_gt(unsigned long cpsr) | ||
82 | { | ||
83 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
84 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
85 | return (~temp) & PSR_N_BIT; | ||
86 | } | ||
87 | |||
88 | static unsigned long __kprobes __check_le(unsigned long cpsr) | ||
89 | { | ||
90 | unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ | ||
91 | temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ | ||
92 | return temp & PSR_N_BIT; | ||
93 | } | ||
94 | |||
95 | static unsigned long __kprobes __check_al(unsigned long cpsr) | ||
96 | { | ||
97 | return true; | ||
98 | } | ||
99 | |||
100 | kprobe_check_cc * const kprobe_condition_checks[16] = { | ||
101 | &__check_eq, &__check_ne, &__check_cs, &__check_cc, | ||
102 | &__check_mi, &__check_pl, &__check_vs, &__check_vc, | ||
103 | &__check_hi, &__check_ls, &__check_ge, &__check_lt, | ||
104 | &__check_gt, &__check_le, &__check_al, &__check_al | ||
105 | }; | ||
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h index 87a5241b2f18..792f2316227a 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/kernel/kprobes.h | |||
@@ -34,4 +34,6 @@ enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t, | |||
34 | 34 | ||
35 | void __init arm_kprobe_decode_init(void); | 35 | void __init arm_kprobe_decode_init(void); |
36 | 36 | ||
37 | extern kprobe_check_cc * const kprobe_condition_checks[16]; | ||
38 | |||
37 | #endif /* _ARM_KERNEL_KPROBES_H */ | 39 | #endif /* _ARM_KERNEL_KPROBES_H */ |