diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-04-27 12:13:31 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2014-04-30 13:10:41 -0400 |
commit | c90a6950120a7e45f31a22653fe6543507ae64d0 (patch) | |
tree | 1a842e0e6929ad050ddc696bc44c7c5c39af13dd /arch | |
parent | 7f55e82bacaaa2c41b8e14d6bc78129b096b67b8 (diff) |
uprobes/x86: Simplify riprel_{pre,post}_xol() and make them similar
Ignoring the "correction" logic riprel_pre_xol() and riprel_post_xol()
are very similar but look quite differently.
1. Add the "UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX" check at the start
of riprel_pre_xol(), like the same check in riprel_post_xol().
2. Add the trivial scratch_reg() helper which returns the address of
scratch register pre_xol/post_xol need to change.
3. Change these functions to use the new helper and avoid copy-and-paste
under if/else branches.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/uprobes.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 5df1bca7c2bc..2ebadb252093 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -326,22 +326,24 @@ static void riprel_analyze(struct arch_uprobe *auprobe, struct insn *insn) | |||
326 | } | 326 | } |
327 | } | 327 | } |
328 | 328 | ||
329 | static inline unsigned long * | ||
330 | scratch_reg(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
331 | { | ||
332 | return (auprobe->def.fixups & UPROBE_FIX_RIP_AX) ? ®s->ax : ®s->cx; | ||
333 | } | ||
334 | |||
329 | /* | 335 | /* |
330 | * If we're emulating a rip-relative instruction, save the contents | 336 | * If we're emulating a rip-relative instruction, save the contents |
331 | * of the scratch register and store the target address in that register. | 337 | * of the scratch register and store the target address in that register. |
332 | */ | 338 | */ |
333 | static void riprel_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | 339 | static void riprel_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) |
334 | { | 340 | { |
335 | struct uprobe_task *utask = current->utask; | 341 | if (auprobe->def.fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) { |
342 | struct uprobe_task *utask = current->utask; | ||
343 | unsigned long *sr = scratch_reg(auprobe, regs); | ||
336 | 344 | ||
337 | if (auprobe->def.fixups & UPROBE_FIX_RIP_AX) { | 345 | utask->autask.saved_scratch_register = *sr; |
338 | utask->autask.saved_scratch_register = regs->ax; | 346 | *sr = utask->vaddr + auprobe->def.riprel_target; |
339 | regs->ax = utask->vaddr; | ||
340 | regs->ax += auprobe->def.riprel_target; | ||
341 | } else if (auprobe->def.fixups & UPROBE_FIX_RIP_CX) { | ||
342 | utask->autask.saved_scratch_register = regs->cx; | ||
343 | regs->cx = utask->vaddr; | ||
344 | regs->cx += auprobe->def.riprel_target; | ||
345 | } | 347 | } |
346 | } | 348 | } |
347 | 349 | ||
@@ -349,14 +351,10 @@ static void riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, | |||
349 | long *correction) | 351 | long *correction) |
350 | { | 352 | { |
351 | if (auprobe->def.fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) { | 353 | if (auprobe->def.fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) { |
352 | struct arch_uprobe_task *autask; | 354 | struct uprobe_task *utask = current->utask; |
353 | 355 | unsigned long *sr = scratch_reg(auprobe, regs); | |
354 | autask = ¤t->utask->autask; | ||
355 | if (auprobe->def.fixups & UPROBE_FIX_RIP_AX) | ||
356 | regs->ax = autask->saved_scratch_register; | ||
357 | else | ||
358 | regs->cx = autask->saved_scratch_register; | ||
359 | 356 | ||
357 | *sr = utask->autask.saved_scratch_register; | ||
360 | /* | 358 | /* |
361 | * The original instruction includes a displacement, and so | 359 | * The original instruction includes a displacement, and so |
362 | * is 4 bytes longer than what we've just single-stepped. | 360 | * is 4 bytes longer than what we've just single-stepped. |