aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2014-04-22 10:20:55 -0400
committerOleg Nesterov <oleg@redhat.com>2014-04-30 13:10:37 -0400
commit97aa5cddbe9e01521137f337624469374e3cbde5 (patch)
tree6a813750457cd69b24e2ef46edf7db198dd99578 /arch
parent220ef8dc9a7a63fe202aacd3fc61e5104f6dd98c (diff)
uprobes/x86: Move default_xol_ops's data into arch_uprobe->def
Finally we can move arch_uprobe->fixups/rip_rela_target_address into the new "def" struct and place this struct in the union, they are only used by default_xol_ops paths. The patch also renames rip_rela_target_address to riprel_target just to make this name shorter. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Jim Keniston <jkenisto@us.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/uprobes.h12
-rw-r--r--arch/x86/kernel/uprobes.c43
2 files changed, 28 insertions, 27 deletions
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index 93bee7b93854..72caff7afbde 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -41,18 +41,20 @@ struct arch_uprobe {
41 u8 ixol[MAX_UINSN_BYTES]; 41 u8 ixol[MAX_UINSN_BYTES];
42 }; 42 };
43 43
44 u16 fixups;
45 const struct uprobe_xol_ops *ops; 44 const struct uprobe_xol_ops *ops;
46 45
47 union { 46 union {
48#ifdef CONFIG_X86_64
49 unsigned long rip_rela_target_address;
50#endif
51 struct { 47 struct {
52 s32 offs; 48 s32 offs;
53 u8 ilen; 49 u8 ilen;
54 u8 opc1; 50 u8 opc1;
55 } branch; 51 } branch;
52 struct {
53#ifdef CONFIG_X86_64
54 long riprel_target;
55#endif
56 u16 fixups;
57 } def;
56 }; 58 };
57}; 59};
58 60
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index b2bca293fc57..7824ce248f8f 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -251,10 +251,9 @@ static inline bool is_64bit_mm(struct mm_struct *mm)
251 * If arch_uprobe->insn doesn't use rip-relative addressing, return 251 * If arch_uprobe->insn doesn't use rip-relative addressing, return
252 * immediately. Otherwise, rewrite the instruction so that it accesses 252 * immediately. Otherwise, rewrite the instruction so that it accesses
253 * its memory operand indirectly through a scratch register. Set 253 * its memory operand indirectly through a scratch register. Set
254 * arch_uprobe->fixups and arch_uprobe->rip_rela_target_address 254 * def->fixups and def->riprel_target accordingly. (The contents of the
255 * accordingly. (The contents of the scratch register will be saved 255 * scratch register will be saved before we single-step the modified
256 * before we single-step the modified instruction, and restored 256 * instruction, and restored afterward).
257 * afterward.)
258 * 257 *
259 * We do this because a rip-relative instruction can access only a 258 * We do this because a rip-relative instruction can access only a
260 * relatively small area (+/- 2 GB from the instruction), and the XOL 259 * relatively small area (+/- 2 GB from the instruction), and the XOL
@@ -308,18 +307,18 @@ handle_riprel_insn(struct arch_uprobe *auprobe, struct insn *insn)
308 * is NOT the register operand, so we use %rcx (register 307 * is NOT the register operand, so we use %rcx (register
309 * #1) for the scratch register. 308 * #1) for the scratch register.
310 */ 309 */
311 auprobe->fixups = UPROBE_FIX_RIP_CX; 310 auprobe->def.fixups = UPROBE_FIX_RIP_CX;
312 /* Change modrm from 00 000 101 to 00 000 001. */ 311 /* Change modrm from 00 000 101 to 00 000 001. */
313 *cursor = 0x1; 312 *cursor = 0x1;
314 } else { 313 } else {
315 /* Use %rax (register #0) for the scratch register. */ 314 /* Use %rax (register #0) for the scratch register. */
316 auprobe->fixups = UPROBE_FIX_RIP_AX; 315 auprobe->def.fixups = UPROBE_FIX_RIP_AX;
317 /* Change modrm from 00 xxx 101 to 00 xxx 000 */ 316 /* Change modrm from 00 xxx 101 to 00 xxx 000 */
318 *cursor = (reg << 3); 317 *cursor = (reg << 3);
319 } 318 }
320 319
321 /* Target address = address of next instruction + (signed) offset */ 320 /* Target address = address of next instruction + (signed) offset */
322 auprobe->rip_rela_target_address = (long)insn->length + insn->displacement.value; 321 auprobe->def.riprel_target = (long)insn->length + insn->displacement.value;
323 322
324 /* Displacement field is gone; slide immediate field (if any) over. */ 323 /* Displacement field is gone; slide immediate field (if any) over. */
325 if (insn->immediate.nbytes) { 324 if (insn->immediate.nbytes) {
@@ -336,25 +335,25 @@ static void
336pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs, 335pre_xol_rip_insn(struct arch_uprobe *auprobe, struct pt_regs *regs,
337 struct arch_uprobe_task *autask) 336 struct arch_uprobe_task *autask)
338{ 337{
339 if (auprobe->fixups & UPROBE_FIX_RIP_AX) { 338 if (auprobe->def.fixups & UPROBE_FIX_RIP_AX) {
340 autask->saved_scratch_register = regs->ax; 339 autask->saved_scratch_register = regs->ax;
341 regs->ax = current->utask->vaddr; 340 regs->ax = current->utask->vaddr;
342 regs->ax += auprobe->rip_rela_target_address; 341 regs->ax += auprobe->def.riprel_target;
343 } else if (auprobe->fixups & UPROBE_FIX_RIP_CX) { 342 } else if (auprobe->def.fixups & UPROBE_FIX_RIP_CX) {
344 autask->saved_scratch_register = regs->cx; 343 autask->saved_scratch_register = regs->cx;
345 regs->cx = current->utask->vaddr; 344 regs->cx = current->utask->vaddr;
346 regs->cx += auprobe->rip_rela_target_address; 345 regs->cx += auprobe->def.riprel_target;
347 } 346 }
348} 347}
349 348
350static void 349static void
351handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction) 350handle_riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs, long *correction)
352{ 351{
353 if (auprobe->fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) { 352 if (auprobe->def.fixups & (UPROBE_FIX_RIP_AX | UPROBE_FIX_RIP_CX)) {
354 struct arch_uprobe_task *autask; 353 struct arch_uprobe_task *autask;
355 354
356 autask = &current->utask->autask; 355 autask = &current->utask->autask;
357 if (auprobe->fixups & UPROBE_FIX_RIP_AX) 356 if (auprobe->def.fixups & UPROBE_FIX_RIP_AX)
358 regs->ax = autask->saved_scratch_register; 357 regs->ax = autask->saved_scratch_register;
359 else 358 else
360 regs->cx = autask->saved_scratch_register; 359 regs->cx = autask->saved_scratch_register;
@@ -432,17 +431,17 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs
432 long correction = (long)(utask->vaddr - utask->xol_vaddr); 431 long correction = (long)(utask->vaddr - utask->xol_vaddr);
433 432
434 handle_riprel_post_xol(auprobe, regs, &correction); 433 handle_riprel_post_xol(auprobe, regs, &correction);
435 if (auprobe->fixups & UPROBE_FIX_IP) 434 if (auprobe->def.fixups & UPROBE_FIX_IP)
436 regs->ip += correction; 435 regs->ip += correction;
437 436
438 if (auprobe->fixups & UPROBE_FIX_CALL) { 437 if (auprobe->def.fixups & UPROBE_FIX_CALL) {
439 if (adjust_ret_addr(regs->sp, correction)) { 438 if (adjust_ret_addr(regs->sp, correction)) {
440 regs->sp += sizeof_long(); 439 regs->sp += sizeof_long();
441 return -ERESTART; 440 return -ERESTART;
442 } 441 }
443 } 442 }
444 /* popf; tell the caller to not touch TF */ 443 /* popf; tell the caller to not touch TF */
445 if (auprobe->fixups & UPROBE_FIX_SETF) 444 if (auprobe->def.fixups & UPROBE_FIX_SETF)
446 utask->autask.saved_tf = true; 445 utask->autask.saved_tf = true;
447 446
448 return 0; 447 return 0;
@@ -646,13 +645,13 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
646 return ret; 645 return ret;
647 646
648 /* 647 /*
649 * Figure out which fixups arch_uprobe_post_xol() will need to perform, 648 * Figure out which fixups default_post_xol_op() will need to perform,
650 * and annotate arch_uprobe->fixups accordingly. To start with, ->fixups 649 * and annotate def->fixups accordingly. To start with, ->fixups is
651 * is either zero or it reflects rip-related fixups. 650 * either zero or it reflects rip-related fixups.
652 */ 651 */
653 switch (OPCODE1(&insn)) { 652 switch (OPCODE1(&insn)) {
654 case 0x9d: /* popf */ 653 case 0x9d: /* popf */
655 auprobe->fixups |= UPROBE_FIX_SETF; 654 auprobe->def.fixups |= UPROBE_FIX_SETF;
656 break; 655 break;
657 case 0xc3: /* ret or lret -- ip is correct */ 656 case 0xc3: /* ret or lret -- ip is correct */
658 case 0xcb: 657 case 0xcb:
@@ -680,9 +679,9 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
680 } 679 }
681 680
682 if (fix_ip) 681 if (fix_ip)
683 auprobe->fixups |= UPROBE_FIX_IP; 682 auprobe->def.fixups |= UPROBE_FIX_IP;
684 if (fix_call) 683 if (fix_call)
685 auprobe->fixups |= UPROBE_FIX_CALL; 684 auprobe->def.fixups |= UPROBE_FIX_CALL;
686 685
687 auprobe->ops = &default_xol_ops; 686 auprobe->ops = &default_xol_ops;
688 return 0; 687 return 0;