diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-12-30 09:54:08 -0500 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2013-02-08 11:47:11 -0500 |
commit | 74e59dfc6b19e3472a7c16ad57bc831e6e647895 (patch) | |
tree | 5047f177b6c604f83d4b9f62614acf93a08d34bd /kernel | |
parent | cf31ec3f7fece93f3fce3ee5964e27857141ea47 (diff) |
uprobes: Change handle_swbp() to expose bp_vaddr to handler_chain()
Change handle_swbp() to set regs->ip = bp_vaddr in advance, this is
what consumer->handler() needs but uprobe_get_swbp_addr() is not
exported.
This also simplifies the code and makes it more consistent across
the supported architectures. handle_swbp() becomes the only caller
of uprobe_get_swbp_addr().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/events/uprobes.c | 15 | ||||
-rw-r--r-- | kernel/trace/trace_uprobe.c | 4 |
2 files changed, 9 insertions, 10 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 04c104ad9522..f1b807831fc2 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1504,6 +1504,10 @@ static void handle_swbp(struct pt_regs *regs) | |||
1504 | } | 1504 | } |
1505 | return; | 1505 | return; |
1506 | } | 1506 | } |
1507 | |||
1508 | /* change it in advance for ->handler() and restart */ | ||
1509 | instruction_pointer_set(regs, bp_vaddr); | ||
1510 | |||
1507 | /* | 1511 | /* |
1508 | * TODO: move copy_insn/etc into _register and remove this hack. | 1512 | * TODO: move copy_insn/etc into _register and remove this hack. |
1509 | * After we hit the bp, _unregister + _register can install the | 1513 | * After we hit the bp, _unregister + _register can install the |
@@ -1511,14 +1515,14 @@ static void handle_swbp(struct pt_regs *regs) | |||
1511 | */ | 1515 | */ |
1512 | smp_rmb(); /* pairs with wmb() in install_breakpoint() */ | 1516 | smp_rmb(); /* pairs with wmb() in install_breakpoint() */ |
1513 | if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) | 1517 | if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) |
1514 | goto restart; | 1518 | goto out; |
1515 | 1519 | ||
1516 | utask = current->utask; | 1520 | utask = current->utask; |
1517 | if (!utask) { | 1521 | if (!utask) { |
1518 | utask = add_utask(); | 1522 | utask = add_utask(); |
1519 | /* Cannot allocate; re-execute the instruction. */ | 1523 | /* Cannot allocate; re-execute the instruction. */ |
1520 | if (!utask) | 1524 | if (!utask) |
1521 | goto restart; | 1525 | goto out; |
1522 | } | 1526 | } |
1523 | 1527 | ||
1524 | handler_chain(uprobe, regs); | 1528 | handler_chain(uprobe, regs); |
@@ -1531,12 +1535,7 @@ static void handle_swbp(struct pt_regs *regs) | |||
1531 | return; | 1535 | return; |
1532 | } | 1536 | } |
1533 | 1537 | ||
1534 | restart: | 1538 | /* can_skip_sstep() succeeded, or restart if can't singlestep */ |
1535 | /* | ||
1536 | * cannot singlestep; cannot skip instruction; | ||
1537 | * re-execute the instruction. | ||
1538 | */ | ||
1539 | instruction_pointer_set(regs, bp_vaddr); | ||
1540 | out: | 1539 | out: |
1541 | put_uprobe(uprobe); | 1540 | put_uprobe(uprobe); |
1542 | } | 1541 | } |
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index e668024773d4..17d9b2bcc28d 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
@@ -492,7 +492,7 @@ static void uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs) | |||
492 | return; | 492 | return; |
493 | 493 | ||
494 | entry = ring_buffer_event_data(event); | 494 | entry = ring_buffer_event_data(event); |
495 | entry->ip = uprobe_get_swbp_addr(task_pt_regs(current)); | 495 | entry->ip = instruction_pointer(task_pt_regs(current)); |
496 | data = (u8 *)&entry[1]; | 496 | data = (u8 *)&entry[1]; |
497 | for (i = 0; i < tu->nr_args; i++) | 497 | for (i = 0; i < tu->nr_args; i++) |
498 | call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); | 498 | call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); |
@@ -667,7 +667,7 @@ static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs) | |||
667 | if (!entry) | 667 | if (!entry) |
668 | goto out; | 668 | goto out; |
669 | 669 | ||
670 | entry->ip = uprobe_get_swbp_addr(task_pt_regs(current)); | 670 | entry->ip = instruction_pointer(task_pt_regs(current)); |
671 | data = (u8 *)&entry[1]; | 671 | data = (u8 *)&entry[1]; |
672 | for (i = 0; i < tu->nr_args; i++) | 672 | for (i = 0; i < tu->nr_args; i++) |
673 | call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); | 673 | call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset); |