|
@@ -399,23 +399,36 @@ int __copy_instruction(u8 *dest, u8 *src)
|
|
|
return length;
|
|
|
}
|
|
|
|
|
|
+/* Prepare reljump right after instruction to boost */
|
|
|
+static void prepare_boost(struct kprobe *p, int length)
|
|
|
+{
|
|
|
+ if (can_boost(p->ainsn.insn, p->addr) &&
|
|
|
+ MAX_INSN_SIZE - length >= RELATIVEJUMP_SIZE) {
|
|
|
+ /*
|
|
|
+ * These instructions can be executed directly if it
|
|
|
+ * jumps back to correct address.
|
|
|
+ */
|
|
|
+ synthesize_reljump(p->ainsn.insn + length, p->addr + length);
|
|
|
+ p->ainsn.boostable = 1;
|
|
|
+ } else {
|
|
|
+ p->ainsn.boostable = -1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int arch_copy_kprobe(struct kprobe *p)
|
|
|
{
|
|
|
- int ret;
|
|
|
+ int len;
|
|
|
|
|
|
/* Copy an instruction with recovering if other optprobe modifies it.*/
|
|
|
- ret = __copy_instruction(p->ainsn.insn, p->addr);
|
|
|
- if (!ret)
|
|
|
+ len = __copy_instruction(p->ainsn.insn, p->addr);
|
|
|
+ if (!len)
|
|
|
return -EINVAL;
|
|
|
|
|
|
/*
|
|
|
* __copy_instruction can modify the displacement of the instruction,
|
|
|
* but it doesn't affect boostable check.
|
|
|
*/
|
|
|
- if (can_boost(p->ainsn.insn, p->addr))
|
|
|
- p->ainsn.boostable = 0;
|
|
|
- else
|
|
|
- p->ainsn.boostable = -1;
|
|
|
+ prepare_boost(p, len);
|
|
|
|
|
|
/* Check whether the instruction modifies Interrupt Flag or not */
|
|
|
p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn);
|
|
@@ -878,21 +891,6 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (p->ainsn.boostable == 0) {
|
|
|
- if ((regs->ip > copy_ip) &&
|
|
|
- (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
|
|
|
- /*
|
|
|
- * These instructions can be executed directly if it
|
|
|
- * jumps back to correct address.
|
|
|
- */
|
|
|
- synthesize_reljump((void *)regs->ip,
|
|
|
- (void *)orig_ip + (regs->ip - copy_ip));
|
|
|
- p->ainsn.boostable = 1;
|
|
|
- } else {
|
|
|
- p->ainsn.boostable = -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
regs->ip += orig_ip - copy_ip;
|
|
|
|
|
|
no_change:
|