aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/probes/decode.c
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-01-05 06:29:18 -0500
committerJon Medhurst <tixy@linaro.org>2015-01-09 04:36:51 -0500
commit83803d97dae1eaf6850a45ef8ee179cc66e147dc (patch)
treee2b1124f1c7896dcadb2af471a0570b019dad551 /arch/arm/probes/decode.c
parent832607e79d7423c67ef8a3de8dfa3d25b5b0bf86 (diff)
ARM: kprobes: introduces checker
This patch introdces 'checker' to decoding phase, and calls checkers when instruction decoding. This allows further decoding for specific instructions. This patch introduces a stub call of checkers in kprobe arch_prepare_kprobe() as an example and for further expansion. Signed-off-by: Wang Nan <wangnan0@huawei.com> Reviewed-by: Jon Medhurst <tixy@linaro.org> Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'arch/arm/probes/decode.c')
-rw-r--r--arch/arm/probes/decode.c60
1 files changed, 54 insertions, 6 deletions
diff --git a/arch/arm/probes/decode.c b/arch/arm/probes/decode.c
index 3b05d5742359..c7d442018902 100644
--- a/arch/arm/probes/decode.c
+++ b/arch/arm/probes/decode.c
@@ -342,6 +342,31 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
342 [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) 342 [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
343}; 343};
344 344
345static int run_checkers(const struct decode_checker *checkers[],
346 int action, probes_opcode_t insn,
347 struct arch_probes_insn *asi,
348 const struct decode_header *h)
349{
350 const struct decode_checker **p;
351
352 if (!checkers)
353 return INSN_GOOD;
354
355 p = checkers;
356 while (*p != NULL) {
357 int retval;
358 probes_check_t *checker_func = (*p)[action].checker;
359
360 retval = INSN_GOOD;
361 if (checker_func)
362 retval = checker_func(insn, asi, h);
363 if (retval == INSN_REJECTED)
364 return retval;
365 p++;
366 }
367 return INSN_GOOD;
368}
369
345/* 370/*
346 * probes_decode_insn operates on data tables in order to decode an ARM 371 * probes_decode_insn operates on data tables in order to decode an ARM
347 * architecture instruction onto which a kprobe has been placed. 372 * architecture instruction onto which a kprobe has been placed.
@@ -388,11 +413,17 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
388int __kprobes 413int __kprobes
389probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, 414probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
390 const union decode_item *table, bool thumb, 415 const union decode_item *table, bool thumb,
391 bool emulate, const union decode_action *actions) 416 bool emulate, const union decode_action *actions,
417 const struct decode_checker *checkers[])
392{ 418{
393 const struct decode_header *h = (struct decode_header *)table; 419 const struct decode_header *h = (struct decode_header *)table;
394 const struct decode_header *next; 420 const struct decode_header *next;
395 bool matched = false; 421 bool matched = false;
422 /*
423 * @insn can be modified by decode_regs. Save its original
424 * value for checkers.
425 */
426 probes_opcode_t origin_insn = insn;
396 427
397 if (emulate) 428 if (emulate)
398 insn = prepare_emulated_insn(insn, asi, thumb); 429 insn = prepare_emulated_insn(insn, asi, thumb);
@@ -422,24 +453,41 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
422 } 453 }
423 454
424 case DECODE_TYPE_CUSTOM: { 455 case DECODE_TYPE_CUSTOM: {
456 int err;
425 struct decode_custom *d = (struct decode_custom *)h; 457 struct decode_custom *d = (struct decode_custom *)h;
426 return actions[d->decoder.action].decoder(insn, asi, h); 458 int action = d->decoder.action;
459
460 err = run_checkers(checkers, action, origin_insn, asi, h);
461 if (err == INSN_REJECTED)
462 return INSN_REJECTED;
463 return actions[action].decoder(insn, asi, h);
427 } 464 }
428 465
429 case DECODE_TYPE_SIMULATE: { 466 case DECODE_TYPE_SIMULATE: {
467 int err;
430 struct decode_simulate *d = (struct decode_simulate *)h; 468 struct decode_simulate *d = (struct decode_simulate *)h;
431 asi->insn_handler = actions[d->handler.action].handler; 469 int action = d->handler.action;
470
471 err = run_checkers(checkers, action, origin_insn, asi, h);
472 if (err == INSN_REJECTED)
473 return INSN_REJECTED;
474 asi->insn_handler = actions[action].handler;
432 return INSN_GOOD_NO_SLOT; 475 return INSN_GOOD_NO_SLOT;
433 } 476 }
434 477
435 case DECODE_TYPE_EMULATE: { 478 case DECODE_TYPE_EMULATE: {
479 int err;
436 struct decode_emulate *d = (struct decode_emulate *)h; 480 struct decode_emulate *d = (struct decode_emulate *)h;
481 int action = d->handler.action;
482
483 err = run_checkers(checkers, action, origin_insn, asi, h);
484 if (err == INSN_REJECTED)
485 return INSN_REJECTED;
437 486
438 if (!emulate) 487 if (!emulate)
439 return actions[d->handler.action].decoder(insn, 488 return actions[action].decoder(insn, asi, h);
440 asi, h);
441 489
442 asi->insn_handler = actions[d->handler.action].handler; 490 asi->insn_handler = actions[action].handler;
443 set_emulated_insn(insn, asi, thumb); 491 set_emulated_insn(insn, asi, thumb);
444 return INSN_GOOD; 492 return INSN_GOOD;
445 } 493 }