static int arch_copy_kprobe(struct kprobe *p) { int ret; /* Copy an instruction with recovering if other optprobe modifies it.*/ ret = __copy_instruction(p->ainsn.insn, p->addr); if (!ret) 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->ainsn.boostable = 0; else p->ainsn.boostable = -1; /* Check whether the instruction modifies Interrupt Flag or not */ p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn); /* Also, displacement change doesn't affect the first byte */ p->opcode = p->ainsn.insn[0]; return 0; }
static void __kprobes arch_copy_kprobe(struct kprobe *p) { memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); fix_riprel(p); if (can_boost(p->addr)) p->ainsn.boostable = 0; else p->ainsn.boostable = -1; p->opcode = *p->addr; }
static void __kprobes arch_copy_kprobe(struct kprobe *p) { /* * Copy an instruction without recovering int3, because it will be * put by another subsystem. */ __copy_instruction(p->ainsn.insn, p->addr, 0); if (can_boost(p->addr)) p->ainsn.boostable = 0; else p->ainsn.boostable = -1; p->opcode = *p->addr; }
int __kprobes arch_prepare_kprobe(struct kprobe *p) { /* insn: must be on special executable page on i386. */ p->ainsn.insn = get_insn_slot(); if (!p->ainsn.insn) return -ENOMEM; memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; if (can_boost(p->addr)) { p->ainsn.boostable = 0; } else { p->ainsn.boostable = -1; } return 0; }
static void __kprobes arch_copy_kprobe(struct kprobe *p) { /* Copy an instruction with recovering if other optprobe modifies it.*/ __copy_instruction(p->ainsn.insn, p->addr); /* * __copy_instruction can modify the displacement of the instruction, * but it doesn't affect boostable check. */ if (can_boost(p->ainsn.insn)) p->ainsn.boostable = 0; else p->ainsn.boostable = -1; /* Also, displacement change doesn't affect the first byte */ p->opcode = p->ainsn.insn[0]; }
/* Prepare reljump right after instruction to boost */ static int prepare_boost(kprobe_opcode_t *buf, struct kprobe *p, struct insn *insn) { int len = insn->length; if (can_boost(insn, p->addr) && MAX_INSN_SIZE - len >= RELATIVEJUMP_SIZE) { /* * These instructions can be executed directly if it * jumps back to correct address. */ synthesize_reljump(buf + len, p->ainsn.insn + len, p->addr + insn->length); len += RELATIVEJUMP_SIZE; p->ainsn.boostable = true; } else { p->ainsn.boostable = false; } return len; }