diff options
author | Anton Arapov <anton@redhat.com> | 2013-04-03 12:00:32 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2013-04-13 09:31:54 -0400 |
commit | e78aebfd27256ca59ccd3e6cf62cfad2a80e02d3 (patch) | |
tree | 6655e753d20bf964fbdcb6eefb3087dd954e2a1f | |
parent | ea024870cf10687b3fded66a9deb6253888f30b7 (diff) |
uretprobes: Reserve the first slot in xol_vma for trampoline
Allocate trampoline page, as the very first one in uprobed
task xol area, and fill it with breakpoint opcode.
Also introduce get_trampoline_vaddr() helper, to wrap the
trampoline address extraction from area->vaddr. That removes
confusion and eases the debug experience in case ->vaddr
notion will be changed.
Signed-off-by: Anton Arapov <anton@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
-rw-r--r-- | kernel/events/uprobes.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index eb384e90ac92..d345b7c6cb2d 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1132,6 +1132,7 @@ static struct xol_area *get_xol_area(void) | |||
1132 | { | 1132 | { |
1133 | struct mm_struct *mm = current->mm; | 1133 | struct mm_struct *mm = current->mm; |
1134 | struct xol_area *area; | 1134 | struct xol_area *area; |
1135 | uprobe_opcode_t insn = UPROBE_SWBP_INSN; | ||
1135 | 1136 | ||
1136 | area = mm->uprobes_state.xol_area; | 1137 | area = mm->uprobes_state.xol_area; |
1137 | if (area) | 1138 | if (area) |
@@ -1149,7 +1150,12 @@ static struct xol_area *get_xol_area(void) | |||
1149 | if (!area->page) | 1150 | if (!area->page) |
1150 | goto free_bitmap; | 1151 | goto free_bitmap; |
1151 | 1152 | ||
1153 | /* allocate first slot of task's xol_area for the return probes */ | ||
1154 | set_bit(0, area->bitmap); | ||
1155 | copy_to_page(area->page, 0, &insn, UPROBE_SWBP_INSN_SIZE); | ||
1156 | atomic_set(&area->slot_count, 1); | ||
1152 | init_waitqueue_head(&area->wq); | 1157 | init_waitqueue_head(&area->wq); |
1158 | |||
1153 | if (!xol_add_vma(area)) | 1159 | if (!xol_add_vma(area)) |
1154 | return area; | 1160 | return area; |
1155 | 1161 | ||
@@ -1346,6 +1352,25 @@ static struct uprobe_task *get_utask(void) | |||
1346 | return current->utask; | 1352 | return current->utask; |
1347 | } | 1353 | } |
1348 | 1354 | ||
1355 | /* | ||
1356 | * Current area->vaddr notion assume the trampoline address is always | ||
1357 | * equal area->vaddr. | ||
1358 | * | ||
1359 | * Returns -1 in case the xol_area is not allocated. | ||
1360 | */ | ||
1361 | static unsigned long get_trampoline_vaddr(void) | ||
1362 | { | ||
1363 | struct xol_area *area; | ||
1364 | unsigned long trampoline_vaddr = -1; | ||
1365 | |||
1366 | area = current->mm->uprobes_state.xol_area; | ||
1367 | smp_read_barrier_depends(); | ||
1368 | if (area) | ||
1369 | trampoline_vaddr = area->vaddr; | ||
1370 | |||
1371 | return trampoline_vaddr; | ||
1372 | } | ||
1373 | |||
1349 | /* Prepare to single-step probed instruction out of line. */ | 1374 | /* Prepare to single-step probed instruction out of line. */ |
1350 | static int | 1375 | static int |
1351 | pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr) | 1376 | pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr) |