Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 323848
b: refs/heads/master
c: bdc1e47
h: refs/heads/master
v: v3
  • Loading branch information
Sebastian Andrzej Siewior authored and Oleg Nesterov committed Sep 15, 2012
1 parent 5715599 commit 5a5089b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9d778782266f95e5c6ec43ed8195ba331c821018
refs/heads/master: bdc1e47217315be14ba04881b0a4c8ecb3ff320c
2 changes: 2 additions & 0 deletions trunk/arch/x86/include/asm/uprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ struct arch_uprobe_task {
#ifdef CONFIG_X86_64
unsigned long saved_scratch_register;
#endif
#define UPROBE_CLEAR_TF (1 << 0)
unsigned int restore_flags;
};

extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
Expand Down
33 changes: 33 additions & 0 deletions trunk/arch/x86/kernel/uprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
/* Adjust the return address of a call insn */
#define UPROBE_FIX_CALL 0x2

/* Instruction will modify TF, don't change it */
#define UPROBE_FIX_SETF 0x4

#define UPROBE_FIX_RIP_AX 0x8000
#define UPROBE_FIX_RIP_CX 0x4000

Expand Down Expand Up @@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn)
insn_get_opcode(insn); /* should be a nop */

switch (OPCODE1(insn)) {
case 0x9d:
/* popf */
auprobe->fixups |= UPROBE_FIX_SETF;
break;
case 0xc3: /* ret/lret */
case 0xcb:
case 0xc2:
Expand Down Expand Up @@ -673,3 +680,29 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
}
return false;
}

void arch_uprobe_enable_step(struct arch_uprobe *auprobe)
{
struct uprobe_task *utask = current->utask;
struct arch_uprobe_task *autask = &utask->autask;

autask->restore_flags = 0;
if (!test_tsk_thread_flag(current, TIF_SINGLESTEP) &&
!(auprobe->fixups & UPROBE_FIX_SETF))
autask->restore_flags |= UPROBE_CLEAR_TF;
/*
* The state of TIF_BLOCKSTEP is not saved. With the TF flag set we
* would to examine the opcode and the flags to make it right. Without
* TF block stepping makes no sense.
*/
user_enable_single_step(current);
}

void arch_uprobe_disable_step(struct arch_uprobe *auprobe)
{
struct uprobe_task *utask = current->utask;
struct arch_uprobe_task *autask = &utask->autask;

if (autask->restore_flags & UPROBE_CLEAR_TF)
user_disable_single_step(current);
}

0 comments on commit 5a5089b

Please sign in to comment.