(re-xmit) Kprobes
PATCH 1/1 (re-xmit) Kprobes
Linus, please apply.
Thanks,
Rusty.
Name: Kprobes for i386
Author: Vamsi Krishna S
Status: Tested on 2.5.31 SMP
D: This patch allows trapping at almost any kernel address, useful for
D: various kernel-hacking tasks, and building on for more
D: infrastructure. This patch is x86 only, but other archs can add
D: support as required.
arch/i386/Config.help +6 -0
@@ -967,3 +967,9 @@ CONFIG_SOFTWARE_SUSPEND absence of features. For more information take a look at Documentation/swsusp.txt. + +CONFIG_KPROBES + Kprobes allows you to trap at almost any kernel address, using + register_kprobe(), and providing a callback function. This is useful + for kernel debugging, non-intrusive instrumentation and testing. If + in doubt, say "N".
arch/i386/config.in +1 -0
@@ -414,6 +414,7 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; th if [ "$CONFIG_HIGHMEM" = "y" ]; then bool ' Highmem debugging' CONFIG_DEBUG_HIGHMEM fi + bool ' Kprobes' CONFIG_KPROBES fi endmenu
arch/i386/kernel/Makefile +1 -0
@@ -25,6 +25,7 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o tr obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o +obj-$(CONFIG_KPROBES) += kprobes.o ifdef CONFIG_VISWS obj-y += setup-visws.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
arch/i386/kernel/entry.S +18 -4
@@ -430,9 +430,16 @@ device_not_available_emulate: jmp ret_from_exception ENTRY(debug) + pushl $-1 # mark this as an int + SAVE_ALL + movl %esp,%edx pushl $0 - pushl $do_debug - jmp error_code + pushl %edx + call do_debug + addl $8,%esp + testl %eax,%eax + jnz restore_all + jmp ret_from_exception ENTRY(nmi) pushl %eax
@@ -445,9 +452,16 @@ ENTRY(nmi) RESTORE_ALL ENTRY(int3) + pushl $-1 # mark this as an int + SAVE_ALL + movl %esp,%edx pushl $0 - pushl $do_int3 - jmp error_code + pushl %edx + call do_int3 + addl $8,%esp + cmpl $0,%eax + jnz restore_all + jmp ret_from_exception ENTRY(overflow) pushl $0
arch/i386/kernel/kprobes.c +160 -0
160 lines not on this page · raw message
arch/i386/kernel/traps.c +31 -7
@@ -23,6 +23,7 @@#include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/highmem.h> +#include <linux/kprobes.h> #ifdef CONFIG_EISA #include <linux/ioport.h>
@@ -325,6 +326,8 @@ static void inline do_trap(int trapnr, i panic("do_trap: can't hit this"); }#endif + if (kprobe_running() && kprobe_fault_handler(regs, trapnr)) +return ;if (!(regs->xcs &3 )) goto kernel_trap;
@@ -391,7 +394,6 @@ asmlinkage void do_##name(struct pt_regs } DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip) -DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)DO_ERROR_INFO (6 ,SIGILL ,"invalid operand" , invalid_op,ILL_ILLOPN , regs->eip)
@@ -407,6 +409,9 @@ asmlinkage void do_general_protection(st {if (regs->eflags &VM_MASK ) goto gp_in_vm86; + +if (kprobe_running () &&kprobe_fault_handler (regs,13 )) +return ;if (!(regs->xcs &3 )) goto gp_in_kernel;
@@ -507,6 +512,17 @@ asmlinkage void do_nmi(struct pt_regs *inb (0x71 );/* dummy */ } +asmlinkage int do_int3(struct pt_regs *regs, long error_code) +{ +if (kprobe_handler (regs)) +return 1 ; +/* This is an interrupt gate, because kprobes wants interrupts +disabled. Normal trap handlers don't. */ +restore_interrupts (regs); +do_trap (3 ,SIGTRAP ,"int3" ,1 , regs, error_code,NULL ); +return 0 ; +} +/* * Our handling of the processor debug registers is non-trivial. * We do not clear them on entry and exit from the kernel. Therefore
@@ -529,7 +545,7 @@ asmlinkage void do_nmi(struct pt_regs ** find every occurrence of the TF bit that could be saved away even * by user code) */ -asmlinkage void do_debug(struct pt_regs * regs, long error_code) +asmlinkage int do_debug(struct pt_regs * regs, long error_code) {unsigned int condition;struct task_struct *tsk = current;
@@ -537,6 +553,12 @@ asmlinkage void do_debug(struct pt_regs __asm__ __volatile__("movl %%db6,%0" :"=r" (condition)); +if (post_kprobe_handler (regs)) +return 1 ; + +/* Interrupts not disabled for normal trap handling. */ +restore_interrupts (regs); +/* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0 |DR_TRAP1 |DR_TRAP2 |DR_TRAP3 )) {if (!tsk->thread.debugreg[7 ])
@@ -587,15 +609,15 @@ clear_dr7: __asm__("movl %0,%%db7" :/* no output */ :"r" (0 )); -return ; +return 0 ; debug_vm86:handle_vm86_trap ((struct kernel_vm86_regs *) regs, error_code,1 ); -return ; +return 0 ; clear_TF: regs->eflags &= ~TF_MASK ; -return ; +return 0 ; }/*
@@ -759,6 +781,8 @@ asmlinkage void math_state_restore(strucstruct task_struct *tsk = current;clts ();/* Allow maths ops (or we recurse) */ +if (kprobe_running () &&kprobe_fault_handler (®s,7 )) +return ;if (!tsk->used_math)init_fpu (tsk);restore_fpu (tsk);
@@ -942,9 +966,9 @@ void __init trap_init(void)#endif set_trap_gate (0 ,÷_error); -set_trap_gate (1 ,&debug); +_set_gate (idt_table+1 ,14 ,3 ,&debug);/* debug trap for kprobes */ set_intr_gate (2 ,&nmi); -set_system_gate (3 ,&int3);/* int3-5 can be called from all */ +_set_gate (idt_table+3 ,14 ,3 ,&int3);/* int3-5 can be called from all */ set_system_gate (4 ,&overflow);set_system_gate (5 ,&bounds);set_trap_gate (6 ,&invalid_op);
arch/i386/mm/fault.c +4 -0
@@ -19,6 +19,7 @@#include <linux/init.h> #include <linux/tty.h> #include <linux/vt_kern.h> /* For unblank_screen() */ +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h>
@@ -155,6 +156,9 @@ asmlinkage void do_page_fault(struct pt_/* get the address */ __asm__("movl %%cr2,%0" :"=r" (address)); +if (kprobe_running () &&kprobe_fault_handler (regs,14 )) +return ; +/* It's safe to allow irq's after cr2 has been saved */ if (regs->eflags &X86_EFLAGS_IF )local_irq_enable ();
include/asm-i386/kprobes.h +34 -0
@@ -0,0 +1,34 @@ +#ifndef _ASM_KPROBES_H +#define _ASM_KPROBES_H +/* +* Dynamic Probes (kprobes) support +* Vamsi Krishna S <[email protected]>, July, 2002 +* Mailing list: [email protected] +*/ +#include <linux/types.h> +#include <linux/ptrace.h> + +struct pt_regs ; + +typedef u8 kprobe_opcode_t ; +#define BREAKPOINT_INSTRUCTION 0xcc + +/* trap3/1 are intr gates for kprobes. So, restore the status of IF, +* if necessary, before executing the original int3/1 (trap) handler. +*/ +static inline void restore_interrupts (struct pt_regs *regs) +{ +if (regs->eflags &IF_MASK ) + __asm__ __volatile__ ("sti" ); +} + +#ifdef CONFIG_KPROBES +extern int kprobe_fault_handler (struct pt_regs *regs,int trapnr); +extern int post_kprobe_handler (struct pt_regs *regs); +extern int kprobe_handler (struct pt_regs *regs); +#else /* !CONFIG_KPROBES */ +static inline int kprobe_fault_handler (struct pt_regs *regs,int trapnr) {return 0 ; } +static inline int post_kprobe_handler (struct pt_regs *regs) {return 0 ; } +static inline int kprobe_handler (struct pt_regs *regs) {return 0 ; } +#endif +#endif /* _ASM_KPROBES_H */
include/linux/kprobes.h +60 -0
60 lines not on this page · raw message
kernel/Makefile +2 -1
@@ -10,7 +10,7 @@ O_TARGET := kernel.o export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \ - printk.o platform.o suspend.o dma.o + printk.o platform.o suspend.o dma.o kprobes.o obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o time.o softirq.o resource.o \
@@ -24,6 +24,7 @@ obj-$(CONFIG_MODULES) += ksyms.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o +obj-$(CONFIG_KPROBES) += kprobes.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
kernel/kprobes.c +89 -0
89 lines not on this page · raw message
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.