Blame view
samples/kprobes/kprobe_example.c
3.45 KB
09c434b8a
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
804defea1
|
2 3 4 |
/* * NOTE: This example is works on x86 and powerpc. * Here's a sample kernel module showing the use of kprobes to dump a |
54aea4542
|
5 |
* stack trace and selected registers when _do_fork() is called. |
804defea1
|
6 7 8 9 10 |
* * For more information on theory of operation of kprobes, see * Documentation/kprobes.txt * * You will see the trace data in /var/log/messages and on the console |
54aea4542
|
11 |
* whenever _do_fork() is invoked to create a new process. |
804defea1
|
12 13 14 15 16 |
*/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/kprobes.h> |
d04659ac9
|
17 18 19 |
#define MAX_SYMBOL_LEN 64 static char symbol[MAX_SYMBOL_LEN] = "_do_fork"; module_param_string(symbol, symbol, sizeof(symbol), 0644); |
804defea1
|
20 21 |
/* For each probe you need to allocate a kprobe structure */ static struct kprobe kp = { |
d04659ac9
|
22 |
.symbol_name = symbol, |
804defea1
|
23 24 25 26 27 28 |
}; /* kprobe pre_handler: called just before the probed instruction is executed */ static int handler_pre(struct kprobe *p, struct pt_regs *regs) { #ifdef CONFIG_X86 |
e708c1488
|
29 30 |
pr_info("<%s> pre_handler: p->addr = 0x%p, ip = %lx, flags = 0x%lx ", |
ea9b50133
|
31 |
p->symbol_name, p->addr, regs->ip, regs->flags); |
804defea1
|
32 33 |
#endif #ifdef CONFIG_PPC |
e708c1488
|
34 35 |
pr_info("<%s> pre_handler: p->addr = 0x%p, nip = 0x%lx, msr = 0x%lx ", |
ea9b50133
|
36 |
p->symbol_name, p->addr, regs->nip, regs->msr); |
804defea1
|
37 |
#endif |
8a1492370
|
38 |
#ifdef CONFIG_MIPS |
e708c1488
|
39 40 |
pr_info("<%s> pre_handler: p->addr = 0x%p, epc = 0x%lx, status = 0x%lx ", |
ea9b50133
|
41 |
p->symbol_name, p->addr, regs->cp0_epc, regs->cp0_status); |
8a1492370
|
42 |
#endif |
af78cede8
|
43 44 45 46 47 48 |
#ifdef CONFIG_ARM64 pr_info("<%s> pre_handler: p->addr = 0x%p, pc = 0x%lx," " pstate = 0x%lx ", p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate); #endif |
e16c5dd51
|
49 50 51 52 53 |
#ifdef CONFIG_S390 pr_info("<%s> pre_handler: p->addr, 0x%p, ip = 0x%lx, flags = 0x%lx ", p->symbol_name, p->addr, regs->psw.addr, regs->flags); #endif |
804defea1
|
54 55 56 57 58 59 60 61 62 63 |
/* A dump_stack() here will give a stack backtrace */ return 0; } /* kprobe post_handler: called after the probed instruction is executed */ static void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) { #ifdef CONFIG_X86 |
e708c1488
|
64 65 |
pr_info("<%s> post_handler: p->addr = 0x%p, flags = 0x%lx ", |
ea9b50133
|
66 |
p->symbol_name, p->addr, regs->flags); |
804defea1
|
67 68 |
#endif #ifdef CONFIG_PPC |
e708c1488
|
69 70 |
pr_info("<%s> post_handler: p->addr = 0x%p, msr = 0x%lx ", |
ea9b50133
|
71 |
p->symbol_name, p->addr, regs->msr); |
804defea1
|
72 |
#endif |
8a1492370
|
73 |
#ifdef CONFIG_MIPS |
e708c1488
|
74 75 |
pr_info("<%s> post_handler: p->addr = 0x%p, status = 0x%lx ", |
ea9b50133
|
76 |
p->symbol_name, p->addr, regs->cp0_status); |
8a1492370
|
77 |
#endif |
af78cede8
|
78 79 80 81 82 |
#ifdef CONFIG_ARM64 pr_info("<%s> post_handler: p->addr = 0x%p, pstate = 0x%lx ", p->symbol_name, p->addr, (long)regs->pstate); #endif |
e16c5dd51
|
83 84 85 86 87 |
#ifdef CONFIG_S390 pr_info("<%s> pre_handler: p->addr, 0x%p, flags = 0x%lx ", p->symbol_name, p->addr, regs->flags); #endif |
804defea1
|
88 89 90 91 92 93 94 95 96 |
} /* * fault_handler: this is called if an exception is generated for any * instruction within the pre- or post-handler, or when Kprobes * single-steps the probed instruction. */ static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) { |
e708c1488
|
97 |
pr_info("fault_handler: p->addr = 0x%p, trap #%dn", p->addr, trapnr); |
804defea1
|
98 99 100 101 102 103 104 105 106 107 108 109 110 |
/* Return 0 because we don't handle the fault. */ return 0; } static int __init kprobe_init(void) { int ret; kp.pre_handler = handler_pre; kp.post_handler = handler_post; kp.fault_handler = handler_fault; ret = register_kprobe(&kp); if (ret < 0) { |
e708c1488
|
111 112 |
pr_err("register_kprobe failed, returned %d ", ret); |
804defea1
|
113 114 |
return ret; } |
e708c1488
|
115 116 |
pr_info("Planted kprobe at %p ", kp.addr); |
804defea1
|
117 118 119 120 121 122 |
return 0; } static void __exit kprobe_exit(void) { unregister_kprobe(&kp); |
e708c1488
|
123 124 |
pr_info("kprobe at %p unregistered ", kp.addr); |
804defea1
|
125 126 127 128 129 |
} module_init(kprobe_init) module_exit(kprobe_exit) MODULE_LICENSE("GPL"); |