Linux Audio

Check our new training course

Linux kernel drivers training

May 6-19, 2025
Register
Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * kretprobe_example.c
  4 *
  5 * Here's a sample kernel module showing the use of return probes to
  6 * report the return value and total time taken for probed function
  7 * to run.
  8 *
  9 * usage: insmod kretprobe_example.ko func=<func_name>
 10 *
 11 * If no func_name is specified, _do_fork is instrumented
 12 *
 13 * For more information on theory of operation of kretprobes, see
 14 * Documentation/staging/kprobes.rst
 15 *
 16 * Build and insert the kernel module as done in the kprobe example.
 17 * You will see the trace data in /var/log/messages and on the console
 18 * whenever the probed function returns. (Some messages may be suppressed
 19 * if syslogd is configured to eliminate duplicate messages.)
 20 */
 21
 22#include <linux/kernel.h>
 23#include <linux/module.h>
 24#include <linux/kprobes.h>
 25#include <linux/ktime.h>
 26#include <linux/limits.h>
 27#include <linux/sched.h>
 28
 29static char func_name[NAME_MAX] = "_do_fork";
 30module_param_string(func, func_name, NAME_MAX, S_IRUGO);
 31MODULE_PARM_DESC(func, "Function to kretprobe; this module will report the"
 32			" function's execution time");
 33
 34/* per-instance private data */
 35struct my_data {
 36	ktime_t entry_stamp;
 37};
 38
 39/* Here we use the entry_hanlder to timestamp function entry */
 40static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 41{
 42	struct my_data *data;
 43
 44	if (!current->mm)
 45		return 1;	/* Skip kernel threads */
 46
 47	data = (struct my_data *)ri->data;
 48	data->entry_stamp = ktime_get();
 49	return 0;
 50}
 51NOKPROBE_SYMBOL(entry_handler);
 52
 53/*
 54 * Return-probe handler: Log the return value and duration. Duration may turn
 55 * out to be zero consistently, depending upon the granularity of time
 56 * accounting on the platform.
 57 */
 58static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 59{
 60	unsigned long retval = regs_return_value(regs);
 61	struct my_data *data = (struct my_data *)ri->data;
 62	s64 delta;
 63	ktime_t now;
 64
 65	now = ktime_get();
 66	delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
 67	pr_info("%s returned %lu and took %lld ns to execute\n",
 68			func_name, retval, (long long)delta);
 69	return 0;
 70}
 71NOKPROBE_SYMBOL(ret_handler);
 72
 73static struct kretprobe my_kretprobe = {
 74	.handler		= ret_handler,
 75	.entry_handler		= entry_handler,
 76	.data_size		= sizeof(struct my_data),
 77	/* Probe up to 20 instances concurrently. */
 78	.maxactive		= 20,
 79};
 80
 81static int __init kretprobe_init(void)
 82{
 83	int ret;
 84
 85	my_kretprobe.kp.symbol_name = func_name;
 86	ret = register_kretprobe(&my_kretprobe);
 87	if (ret < 0) {
 88		pr_err("register_kretprobe failed, returned %d\n", ret);
 89		return -1;
 90	}
 91	pr_info("Planted return probe at %s: %p\n",
 92			my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr);
 93	return 0;
 94}
 95
 96static void __exit kretprobe_exit(void)
 97{
 98	unregister_kretprobe(&my_kretprobe);
 99	pr_info("kretprobe at %p unregistered\n", my_kretprobe.kp.addr);
100
101	/* nmissed > 0 suggests that maxactive was set too low. */
102	pr_info("Missed probing %d instances of %s\n",
103		my_kretprobe.nmissed, my_kretprobe.kp.symbol_name);
104}
105
106module_init(kretprobe_init)
107module_exit(kretprobe_exit)
 
108MODULE_LICENSE("GPL");
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * kretprobe_example.c
  4 *
  5 * Here's a sample kernel module showing the use of return probes to
  6 * report the return value and total time taken for probed function
  7 * to run.
  8 *
  9 * usage: insmod kretprobe_example.ko func=<func_name>
 10 *
 11 * If no func_name is specified, kernel_clone is instrumented
 12 *
 13 * For more information on theory of operation of kretprobes, see
 14 * Documentation/trace/kprobes.rst
 15 *
 16 * Build and insert the kernel module as done in the kprobe example.
 17 * You will see the trace data in /var/log/messages and on the console
 18 * whenever the probed function returns. (Some messages may be suppressed
 19 * if syslogd is configured to eliminate duplicate messages.)
 20 */
 21
 22#include <linux/kernel.h>
 23#include <linux/module.h>
 24#include <linux/kprobes.h>
 25#include <linux/ktime.h>
 
 26#include <linux/sched.h>
 27
 28static char func_name[KSYM_NAME_LEN] = "kernel_clone";
 29module_param_string(func, func_name, KSYM_NAME_LEN, 0644);
 30MODULE_PARM_DESC(func, "Function to kretprobe; this module will report the"
 31			" function's execution time");
 32
 33/* per-instance private data */
 34struct my_data {
 35	ktime_t entry_stamp;
 36};
 37
 38/* Here we use the entry_handler to timestamp function entry */
 39static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 40{
 41	struct my_data *data;
 42
 43	if (!current->mm)
 44		return 1;	/* Skip kernel threads */
 45
 46	data = (struct my_data *)ri->data;
 47	data->entry_stamp = ktime_get();
 48	return 0;
 49}
 50NOKPROBE_SYMBOL(entry_handler);
 51
 52/*
 53 * Return-probe handler: Log the return value and duration. Duration may turn
 54 * out to be zero consistently, depending upon the granularity of time
 55 * accounting on the platform.
 56 */
 57static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 58{
 59	unsigned long retval = regs_return_value(regs);
 60	struct my_data *data = (struct my_data *)ri->data;
 61	s64 delta;
 62	ktime_t now;
 63
 64	now = ktime_get();
 65	delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
 66	pr_info("%s returned %lu and took %lld ns to execute\n",
 67			func_name, retval, (long long)delta);
 68	return 0;
 69}
 70NOKPROBE_SYMBOL(ret_handler);
 71
 72static struct kretprobe my_kretprobe = {
 73	.handler		= ret_handler,
 74	.entry_handler		= entry_handler,
 75	.data_size		= sizeof(struct my_data),
 76	/* Probe up to 20 instances concurrently. */
 77	.maxactive		= 20,
 78};
 79
 80static int __init kretprobe_init(void)
 81{
 82	int ret;
 83
 84	my_kretprobe.kp.symbol_name = func_name;
 85	ret = register_kretprobe(&my_kretprobe);
 86	if (ret < 0) {
 87		pr_err("register_kretprobe failed, returned %d\n", ret);
 88		return ret;
 89	}
 90	pr_info("Planted return probe at %s: %p\n",
 91			my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr);
 92	return 0;
 93}
 94
 95static void __exit kretprobe_exit(void)
 96{
 97	unregister_kretprobe(&my_kretprobe);
 98	pr_info("kretprobe at %p unregistered\n", my_kretprobe.kp.addr);
 99
100	/* nmissed > 0 suggests that maxactive was set too low. */
101	pr_info("Missed probing %d instances of %s\n",
102		my_kretprobe.nmissed, my_kretprobe.kp.symbol_name);
103}
104
105module_init(kretprobe_init)
106module_exit(kretprobe_exit)
107MODULE_DESCRIPTION("sample kernel module showing the use of return probes");
108MODULE_LICENSE("GPL");