-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Wang Nan
authored and
Jon Medhurst
committed
Jan 13, 2015
1 parent
83803d9
commit 6624cf6
Showing
9 changed files
with
383 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
obj-$(CONFIG_KPROBES) += core.o actions-common.o | ||
obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o | ||
obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o | ||
test-kprobes-objs := test-core.o | ||
|
||
ifdef CONFIG_THUMB2_KERNEL | ||
obj-$(CONFIG_KPROBES) += actions-thumb.o | ||
obj-$(CONFIG_KPROBES) += actions-thumb.o checkers-thumb.o | ||
test-kprobes-objs += test-thumb.o | ||
else | ||
obj-$(CONFIG_KPROBES) += actions-arm.o | ||
obj-$(CONFIG_KPROBES) += actions-arm.o checkers-arm.o | ||
test-kprobes-objs += test-arm.o | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* arch/arm/probes/kprobes/checkers-arm.c | ||
* | ||
* Copyright (C) 2014 Huawei Inc. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include "../decode.h" | ||
#include "../decode-arm.h" | ||
#include "checkers.h" | ||
|
||
static enum probes_insn __kprobes arm_check_stack(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
/* | ||
* PROBES_LDRSTRD, PROBES_LDMSTM, PROBES_STORE, | ||
* PROBES_STORE_EXTRA may get here. Simply mark all normal | ||
* insns as STACK_USE_NONE. | ||
*/ | ||
static const union decode_item table[] = { | ||
/* | ||
* 'STR{,D,B,H}, Rt, [Rn, Rm]' should be marked as UNKNOWN | ||
* if Rn or Rm is SP. | ||
* x | ||
* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx | ||
* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx | ||
*/ | ||
DECODE_OR (0x0e10000f, 0x0600000d), | ||
DECODE_OR (0x0e1f0000, 0x060d0000), | ||
|
||
/* | ||
* x | ||
* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx | ||
* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx | ||
*/ | ||
DECODE_OR (0x0e5000bf, 0x000000bd), | ||
DECODE_CUSTOM (0x0e5f00b0, 0x000d00b0, STACK_USE_UNKNOWN), | ||
|
||
/* | ||
* For PROBES_LDMSTM, only stmdx sp, [...] need to examine | ||
* | ||
* Bit B/A (bit 24) encodes arithmetic operation order. 1 means | ||
* before, 0 means after. | ||
* Bit I/D (bit 23) encodes arithmetic operation. 1 means | ||
* increment, 0 means decrement. | ||
* | ||
* So: | ||
* B I | ||
* / / | ||
* A D | Rn | | ||
* STMDX SP, [...] cccc 100x 00x0 xxxx xxxx xxxx xxxx xxxx | ||
*/ | ||
DECODE_CUSTOM (0x0edf0000, 0x080d0000, STACK_USE_STMDX), | ||
|
||
/* P U W | Rn | Rt | imm12 |*/ | ||
/* STR (immediate) cccc 010x x0x0 1101 xxxx xxxx xxxx xxxx */ | ||
/* STRB (immediate) cccc 010x x1x0 1101 xxxx xxxx xxxx xxxx */ | ||
/* P U W | Rn | Rt |imm4| |imm4|*/ | ||
/* STRD (immediate) cccc 000x x1x0 1101 xxxx xxxx 1111 xxxx */ | ||
/* STRH (immediate) cccc 000x x1x0 1101 xxxx xxxx 1011 xxxx */ | ||
/* | ||
* index = (P == '1'); add = (U == '1'). | ||
* Above insns with: | ||
* index == 0 (str{,d,h} rx, [sp], #+/-imm) or | ||
* add == 1 (str{,d,h} rx, [sp, #+<imm>]) | ||
* should be STACK_USE_NONE. | ||
* Only str{,b,d,h} rx,[sp,#-n] (P == 1 and U == 0) are | ||
* required to be examined. | ||
*/ | ||
/* STR{,B} Rt,[SP,#-n] cccc 0101 0xx0 1101 xxxx xxxx xxxx xxxx */ | ||
DECODE_CUSTOM (0x0f9f0000, 0x050d0000, STACK_USE_FIXED_XXX), | ||
|
||
/* STR{D,H} Rt,[SP,#-n] cccc 0001 01x0 1101 xxxx xxxx 1x11 xxxx */ | ||
DECODE_CUSTOM (0x0fdf00b0, 0x014d00b0, STACK_USE_FIXED_X0X), | ||
|
||
/* fall through */ | ||
DECODE_CUSTOM (0, 0, STACK_USE_NONE), | ||
DECODE_END | ||
}; | ||
|
||
return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); | ||
} | ||
|
||
const struct decode_checker arm_stack_checker[NUM_PROBES_ARM_ACTIONS] = { | ||
[PROBES_LDRSTRD] = {.checker = arm_check_stack}, | ||
[PROBES_STORE_EXTRA] = {.checker = arm_check_stack}, | ||
[PROBES_STORE] = {.checker = arm_check_stack}, | ||
[PROBES_LDMSTM] = {.checker = arm_check_stack}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* arch/arm/probes/kprobes/checkers-common.c | ||
* | ||
* Copyright (C) 2014 Huawei Inc. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include "../decode.h" | ||
#include "../decode-arm.h" | ||
#include "checkers.h" | ||
|
||
enum probes_insn checker_stack_use_none(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
asi->stack_space = 0; | ||
return INSN_GOOD_NO_SLOT; | ||
} | ||
|
||
enum probes_insn checker_stack_use_unknown(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
asi->stack_space = -1; | ||
return INSN_GOOD_NO_SLOT; | ||
} | ||
|
||
#ifdef CONFIG_THUMB2_KERNEL | ||
enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
int imm = insn & 0xff; | ||
asi->stack_space = imm; | ||
return INSN_GOOD_NO_SLOT; | ||
} | ||
|
||
/* | ||
* Different from other insn uses imm8, the real addressing offset of | ||
* STRD in T32 encoding should be imm8 * 4. See ARMARM description. | ||
*/ | ||
enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
int imm = insn & 0xff; | ||
asi->stack_space = imm << 2; | ||
return INSN_GOOD_NO_SLOT; | ||
} | ||
#else | ||
enum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
int imm = ((insn & 0xf00) >> 4) + (insn & 0xf); | ||
asi->stack_space = imm; | ||
return INSN_GOOD_NO_SLOT; | ||
} | ||
#endif | ||
|
||
enum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
int imm = insn & 0xfff; | ||
asi->stack_space = imm; | ||
return INSN_GOOD_NO_SLOT; | ||
} | ||
|
||
enum probes_insn checker_stack_use_stmdx(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
unsigned int reglist = insn & 0xffff; | ||
int pbit = insn & (1 << 24); | ||
asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4; | ||
|
||
return INSN_GOOD_NO_SLOT; | ||
} | ||
|
||
const union decode_action stack_check_actions[] = { | ||
[STACK_USE_NONE] = {.decoder = checker_stack_use_none}, | ||
[STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown}, | ||
#ifdef CONFIG_THUMB2_KERNEL | ||
[STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx}, | ||
[STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd}, | ||
#else | ||
[STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x}, | ||
#endif | ||
[STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx}, | ||
[STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* arch/arm/probes/kprobes/checkers-thumb.c | ||
* | ||
* Copyright (C) 2014 Huawei Inc. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include "../decode.h" | ||
#include "../decode-thumb.h" | ||
#include "checkers.h" | ||
|
||
static enum probes_insn __kprobes t32_check_stack(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
/* | ||
* PROBES_T32_LDMSTM, PROBES_T32_LDRDSTRD and PROBES_T32_LDRSTR | ||
* may get here. Simply mark all normal insns as STACK_USE_NONE. | ||
*/ | ||
static const union decode_item table[] = { | ||
|
||
/* | ||
* First, filter out all ldr insns to make our life easier. | ||
* Following load insns may come here: | ||
* LDM, LDRD, LDR. | ||
* In T32 encoding, bit 20 is enough for distinguishing | ||
* load and store. All load insns have this bit set, when | ||
* all store insns have this bit clear. | ||
*/ | ||
DECODE_CUSTOM (0x00100000, 0x00100000, STACK_USE_NONE), | ||
|
||
/* | ||
* Mark all 'STR{,B,H}, Rt, [Rn, Rm]' as STACK_USE_UNKNOWN | ||
* if Rn or Rm is SP. T32 doesn't encode STRD. | ||
*/ | ||
/* xx | Rn | Rt | | Rm |*/ | ||
/* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ | ||
/* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ | ||
/* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ | ||
/* INVALID INSN 1111 1000 0110 xxxx xxxx 0000 00xx xxxx */ | ||
/* By Introducing INVALID INSN, bit 21 and 22 can be ignored. */ | ||
DECODE_OR (0xff9f0fc0, 0xf80d0000), | ||
DECODE_CUSTOM (0xff900fcf, 0xf800000d, STACK_USE_UNKNOWN), | ||
|
||
|
||
/* xx | Rn | Rt | PUW| imm8 |*/ | ||
/* STR (imm 8) 1111 1000 0100 1101 xxxx 110x xxxx xxxx */ | ||
/* STRB (imm 8) 1111 1000 0000 1101 xxxx 110x xxxx xxxx */ | ||
/* STRH (imm 8) 1111 1000 0010 1101 xxxx 110x xxxx xxxx */ | ||
/* INVALID INSN 1111 1000 0110 1101 xxxx 110x xxxx xxxx */ | ||
/* Only consider U == 0 and P == 1: strx rx, [sp, #-<imm>] */ | ||
DECODE_CUSTOM (0xff9f0e00, 0xf80d0c00, STACK_USE_FIXED_0XX), | ||
|
||
/* For STR{,B,H} (imm 12), offset is always positive, so ignore them. */ | ||
|
||
/* P U W | Rn | Rt | Rt2| imm8 |*/ | ||
/* STRD (immediate) 1110 1001 01x0 1101 xxxx xxxx xxxx xxxx */ | ||
/* | ||
* Only consider U == 0 and P == 1. | ||
* Also note that STRD in T32 encoding is special: | ||
* imm = ZeroExtend(imm8:'00', 32) | ||
*/ | ||
DECODE_CUSTOM (0xffdf0000, 0xe94d0000, STACK_USE_T32STRD), | ||
|
||
/* | Rn | */ | ||
/* STMDB 1110 1001 00x0 1101 xxxx xxxx xxxx xxxx */ | ||
DECODE_CUSTOM (0xffdf0000, 0xe90d0000, STACK_USE_STMDX), | ||
|
||
/* fall through */ | ||
DECODE_CUSTOM (0, 0, STACK_USE_NONE), | ||
DECODE_END | ||
}; | ||
|
||
return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); | ||
} | ||
|
||
const struct decode_checker t32_stack_checker[NUM_PROBES_T32_ACTIONS] = { | ||
[PROBES_T32_LDMSTM] = {.checker = t32_check_stack}, | ||
[PROBES_T32_LDRDSTRD] = {.checker = t32_check_stack}, | ||
[PROBES_T32_LDRSTR] = {.checker = t32_check_stack}, | ||
}; | ||
|
||
/* | ||
* See following comments. This insn must be 'push'. | ||
*/ | ||
static enum probes_insn __kprobes t16_check_stack(probes_opcode_t insn, | ||
struct arch_probes_insn *asi, | ||
const struct decode_header *h) | ||
{ | ||
unsigned int reglist = insn & 0x1ff; | ||
asi->stack_space = hweight32(reglist) * 4; | ||
return INSN_GOOD; | ||
} | ||
|
||
/* | ||
* T16 encoding is simple: only the 'push' insn can need extra stack space. | ||
* Other insns, like str, can only use r0-r7 as Rn. | ||
*/ | ||
const struct decode_checker t16_stack_checker[NUM_PROBES_T16_ACTIONS] = { | ||
[PROBES_T16_PUSH] = {.checker = t16_check_stack}, | ||
}; |
Oops, something went wrong.