x86: Further reduce kprobes_{32|64}.c
PATCH 1/1 x86: Further reduce kprobes_{32|64}.c
Add X86_32 only static function to X86_64 file and add static X86_64 functions to X86_32 file. Produces compile warnings about defined but not used functions for now, will deal with these in final unified file.
Signed-off-by Harvey Harrison <[email protected]>
--- arch/x86/kernel/kprobes_32.c | 85 ++++++++++++++++++++++++++++++++++++++++- arch/x86/kernel/kprobes_64.c | 61 ++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 3 deletions(-)
arch/x86/kernel/kprobes_32.c +82 -3
@@ -37,13 +37,14 @@#include <asm/alternative.h> void jprobe_return_end (void ); +static void __kprobes arch_copy_kprobe (struct kprobe *p); DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);struct kretprobe_blackpoint kretprobe_blacklist[] = { {"__switch_to" , },/* This function switches only current task, but -doesn't switch kernel stack.*/ +doesn't switch kernel stack.*/ {NULL ,NULL }/* Terminator */ };const int kretprobe_blacklist_size =ARRAY_SIZE (kretprobe_blacklist);
@@ -156,7 +157,7 @@ twobyte_has_modrm[256 / sizeof(unsigned long)] = {#undef RF/* insert a jmp code */ -static __always_inline void set_jmp_op(void *from, void *to) +static inline void set_jmp_op (void *from,void *to) {struct __arch_jmp_op {char op;
@@ -170,7 +171,7 @@ static __always_inline void set_jmp_op(void *from, void *to)/* * returns non-zero if opcodes can be boosted. */ -static __always_inline int can_boost(kprobe_opcode_t *opcodes) +static inline int can_boost (kprobe_opcode_t *opcodes) {kprobe_opcode_t opcode;kprobe_opcode_t *orig_opcodes = opcodes;
@@ -248,6 +249,84 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)return 0 ; } +/* +* Determine if the instruction uses the %rip-relative addressing mode. +* If it does, return the address of the 32-bit displacement word. +* If not, return null. +*/ +static s32 __kprobes *is_riprel (u8 *insn) +{ +int need_modrm; + +/* Skip legacy instruction prefixes. */ +while (1 ) { +switch (*insn) { +case 0x66 : +case 0x67 : +case 0x2e : +case 0x3e : +case 0x26 : +case 0x64 : +case 0x65 : +case 0x36 : +case 0xf0 : +case 0xf3 : +case 0xf2 : + ++insn; +continue ; + } +break ; + } + +/* Skip REX instruction prefix. */ +if ((*insn &0xf0 ) ==0x40 ) + ++insn; + +if (*insn ==0x0f ) {/* Two-byte opcode. */ + ++insn; + need_modrm =test_bit (*insn, twobyte_has_modrm); + }else {/* One-byte opcode. */ + need_modrm =test_bit (*insn, onebyte_has_modrm); + } + +if (need_modrm) { +u8 modrm = *++insn; +if ((modrm &0xc7 ) ==0x05 ) {/* %rip+disp32 addressing mode */ +/* Displacement follows ModRM byte. */ +return (s32 *) ++insn; + } + } + +/* No %rip-relative addressing mode here. */ +return NULL ; +} + +static void __kprobes arch_copy_kprobe (struct kprobe *p) +{ +s32 *ripdisp; +memcpy (p->ainsn.insn, p->addr,MAX_INSN_SIZE ); + ripdisp =is_riprel (p->ainsn.insn); +if (ripdisp) { +/* +* The copied instruction uses the %rip-relative +* addressing mode. Adjust the displacement for the +* difference between the original location of this +* instruction and the location of the copy that will +* actually be run. The tricky bit here is making sure +* that the sign extension happens correctly in this +* calculation, since we need a signed 32-bit result to +* be sign-extended to 64 bits when it's added to the +* %rip value and yield the same 64-bit result that the +* sign-extension of the original signed 32-bit +* displacement would have given. +*/ +s64 disp = (u8 *) p->addr + *ripdisp - (u8 *) p->ainsn.insn; +BUG_ON ((s64 ) (s32 ) disp != disp);/* Sanity check. */ + *ripdisp = disp; + } + p->opcode = *p->addr; +} +void __kprobes arch_arm_kprobe (struct kprobe *p) {text_poke (p->addr, ((unsigned char []){BREAKPOINT_INSTRUCTION }),1 );
arch/x86/kernel/kprobes_64.c +61 -0
67 lines not on this page · raw message
Signature · 1 line
1.5.4.rc0.1083.gf568