1aba09b44SMasami Hiramatsu.. SPDX-License-Identifier: GPL-2.0 2aba09b44SMasami Hiramatsu 3aba09b44SMasami Hiramatsu================================== 4aba09b44SMasami HiramatsuFprobe - Function entry/exit probe 5aba09b44SMasami Hiramatsu================================== 6aba09b44SMasami Hiramatsu 7aba09b44SMasami Hiramatsu.. Author: Masami Hiramatsu <mhiramat@kernel.org> 8aba09b44SMasami Hiramatsu 9aba09b44SMasami HiramatsuIntroduction 10aba09b44SMasami Hiramatsu============ 11aba09b44SMasami Hiramatsu 12aba09b44SMasami HiramatsuFprobe is a function entry/exit probe mechanism based on ftrace. 13aba09b44SMasami HiramatsuInstead of using ftrace full feature, if you only want to attach callbacks 14aba09b44SMasami Hiramatsuon function entry and exit, similar to the kprobes and kretprobes, you can 15aba09b44SMasami Hiramatsuuse fprobe. Compared with kprobes and kretprobes, fprobe gives faster 16aba09b44SMasami Hiramatsuinstrumentation for multiple functions with single handler. This document 17aba09b44SMasami Hiramatsudescribes how to use fprobe. 18aba09b44SMasami Hiramatsu 19aba09b44SMasami HiramatsuThe usage of fprobe 20aba09b44SMasami Hiramatsu=================== 21aba09b44SMasami Hiramatsu 22aba09b44SMasami HiramatsuThe fprobe is a wrapper of ftrace (+ kretprobe-like return callback) to 23aba09b44SMasami Hiramatsuattach callbacks to multiple function entry and exit. User needs to set up 24aba09b44SMasami Hiramatsuthe `struct fprobe` and pass it to `register_fprobe()`. 25aba09b44SMasami Hiramatsu 26aba09b44SMasami HiramatsuTypically, `fprobe` data structure is initialized with the `entry_handler` 27aba09b44SMasami Hiramatsuand/or `exit_handler` as below. 28aba09b44SMasami Hiramatsu 29aba09b44SMasami Hiramatsu.. code-block:: c 30aba09b44SMasami Hiramatsu 31aba09b44SMasami Hiramatsu struct fprobe fp = { 32aba09b44SMasami Hiramatsu .entry_handler = my_entry_callback, 33aba09b44SMasami Hiramatsu .exit_handler = my_exit_callback, 34aba09b44SMasami Hiramatsu }; 35aba09b44SMasami Hiramatsu 36aba09b44SMasami HiramatsuTo enable the fprobe, call one of register_fprobe(), register_fprobe_ips(), and 37aba09b44SMasami Hiramatsuregister_fprobe_syms(). These functions register the fprobe with different types 38aba09b44SMasami Hiramatsuof parameters. 39aba09b44SMasami Hiramatsu 40aba09b44SMasami HiramatsuThe register_fprobe() enables a fprobe by function-name filters. 41aba09b44SMasami HiramatsuE.g. this enables @fp on "func*()" function except "func2()".:: 42aba09b44SMasami Hiramatsu 43aba09b44SMasami Hiramatsu register_fprobe(&fp, "func*", "func2"); 44aba09b44SMasami Hiramatsu 45aba09b44SMasami HiramatsuThe register_fprobe_ips() enables a fprobe by ftrace-location addresses. 46aba09b44SMasami HiramatsuE.g. 47aba09b44SMasami Hiramatsu 48aba09b44SMasami Hiramatsu.. code-block:: c 49aba09b44SMasami Hiramatsu 50aba09b44SMasami Hiramatsu unsigned long ips[] = { 0x.... }; 51aba09b44SMasami Hiramatsu 52aba09b44SMasami Hiramatsu register_fprobe_ips(&fp, ips, ARRAY_SIZE(ips)); 53aba09b44SMasami Hiramatsu 54aba09b44SMasami HiramatsuAnd the register_fprobe_syms() enables a fprobe by symbol names. 55aba09b44SMasami HiramatsuE.g. 56aba09b44SMasami Hiramatsu 57aba09b44SMasami Hiramatsu.. code-block:: c 58aba09b44SMasami Hiramatsu 59aba09b44SMasami Hiramatsu char syms[] = {"func1", "func2", "func3"}; 60aba09b44SMasami Hiramatsu 61aba09b44SMasami Hiramatsu register_fprobe_syms(&fp, syms, ARRAY_SIZE(syms)); 62aba09b44SMasami Hiramatsu 63aba09b44SMasami HiramatsuTo disable (remove from functions) this fprobe, call:: 64aba09b44SMasami Hiramatsu 65aba09b44SMasami Hiramatsu unregister_fprobe(&fp); 66aba09b44SMasami Hiramatsu 67aba09b44SMasami HiramatsuYou can temporally (soft) disable the fprobe by:: 68aba09b44SMasami Hiramatsu 69aba09b44SMasami Hiramatsu disable_fprobe(&fp); 70aba09b44SMasami Hiramatsu 71aba09b44SMasami Hiramatsuand resume by:: 72aba09b44SMasami Hiramatsu 73aba09b44SMasami Hiramatsu enable_fprobe(&fp); 74aba09b44SMasami Hiramatsu 75aba09b44SMasami HiramatsuThe above is defined by including the header:: 76aba09b44SMasami Hiramatsu 77aba09b44SMasami Hiramatsu #include <linux/fprobe.h> 78aba09b44SMasami Hiramatsu 79aba09b44SMasami HiramatsuSame as ftrace, the registered callbacks will start being called some time 80aba09b44SMasami Hiramatsuafter the register_fprobe() is called and before it returns. See 81aba09b44SMasami Hiramatsu:file:`Documentation/trace/ftrace.rst`. 82aba09b44SMasami Hiramatsu 83aba09b44SMasami HiramatsuAlso, the unregister_fprobe() will guarantee that the both enter and exit 84aba09b44SMasami Hiramatsuhandlers are no longer being called by functions after unregister_fprobe() 85aba09b44SMasami Hiramatsureturns as same as unregister_ftrace_function(). 86aba09b44SMasami Hiramatsu 87aba09b44SMasami HiramatsuThe fprobe entry/exit handler 88aba09b44SMasami Hiramatsu============================= 89aba09b44SMasami Hiramatsu 908be098a9SMasami Hiramatsu (Google)The prototype of the entry/exit callback function are as follows: 91aba09b44SMasami Hiramatsu 92aba09b44SMasami Hiramatsu.. code-block:: c 93aba09b44SMasami Hiramatsu 94*2a86ac30SMasami Hiramatsu (Google) int entry_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct pt_regs *regs, void *entry_data); 95aba09b44SMasami Hiramatsu 96*2a86ac30SMasami Hiramatsu (Google) void exit_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct pt_regs *regs, void *entry_data); 978be098a9SMasami Hiramatsu (Google) 988be098a9SMasami Hiramatsu (Google)Note that the @entry_ip is saved at function entry and passed to exit handler. 998be098a9SMasami Hiramatsu (Google)If the entry callback function returns !0, the corresponding exit callback will be cancelled. 100aba09b44SMasami Hiramatsu 101aba09b44SMasami Hiramatsu@fp 102aba09b44SMasami Hiramatsu This is the address of `fprobe` data structure related to this handler. 103aba09b44SMasami Hiramatsu You can embed the `fprobe` to your data structure and get it by 104aba09b44SMasami Hiramatsu container_of() macro from @fp. The @fp must not be NULL. 105aba09b44SMasami Hiramatsu 106aba09b44SMasami Hiramatsu@entry_ip 107aba09b44SMasami Hiramatsu This is the ftrace address of the traced function (both entry and exit). 108aba09b44SMasami Hiramatsu Note that this may not be the actual entry address of the function but 109aba09b44SMasami Hiramatsu the address where the ftrace is instrumented. 110aba09b44SMasami Hiramatsu 111*2a86ac30SMasami Hiramatsu (Google)@ret_ip 112*2a86ac30SMasami Hiramatsu (Google) This is the return address that the traced function will return to, 113*2a86ac30SMasami Hiramatsu (Google) somewhere in the caller. This can be used at both entry and exit. 114*2a86ac30SMasami Hiramatsu (Google) 115aba09b44SMasami Hiramatsu@regs 116aba09b44SMasami Hiramatsu This is the `pt_regs` data structure at the entry and exit. Note that 117aba09b44SMasami Hiramatsu the instruction pointer of @regs may be different from the @entry_ip 118aba09b44SMasami Hiramatsu in the entry_handler. If you need traced instruction pointer, you need 119aba09b44SMasami Hiramatsu to use @entry_ip. On the other hand, in the exit_handler, the instruction 120d56b699dSBjorn Helgaas pointer of @regs is set to the current return address. 121aba09b44SMasami Hiramatsu 1228be098a9SMasami Hiramatsu (Google)@entry_data 1238be098a9SMasami Hiramatsu (Google) This is a local storage to share the data between entry and exit handlers. 1248be098a9SMasami Hiramatsu (Google) This storage is NULL by default. If the user specify `exit_handler` field 1258be098a9SMasami Hiramatsu (Google) and `entry_data_size` field when registering the fprobe, the storage is 1268be098a9SMasami Hiramatsu (Google) allocated and passed to both `entry_handler` and `exit_handler`. 1278be098a9SMasami Hiramatsu (Google) 128aba09b44SMasami HiramatsuShare the callbacks with kprobes 129aba09b44SMasami Hiramatsu================================ 130aba09b44SMasami Hiramatsu 131aba09b44SMasami HiramatsuSince the recursion safeness of the fprobe (and ftrace) is a bit different 132aba09b44SMasami Hiramatsufrom the kprobes, this may cause an issue if user wants to run the same 133aba09b44SMasami Hiramatsucode from the fprobe and the kprobes. 134aba09b44SMasami Hiramatsu 135aba09b44SMasami HiramatsuKprobes has per-cpu 'current_kprobe' variable which protects the kprobe 136aba09b44SMasami Hiramatsuhandler from recursion in all cases. On the other hand, fprobe uses 137aba09b44SMasami Hiramatsuonly ftrace_test_recursion_trylock(). This allows interrupt context to 138aba09b44SMasami Hiramatsucall another (or same) fprobe while the fprobe user handler is running. 139aba09b44SMasami Hiramatsu 140aba09b44SMasami HiramatsuThis is not a matter if the common callback code has its own recursion 141aba09b44SMasami Hiramatsudetection, or it can handle the recursion in the different contexts 142aba09b44SMasami Hiramatsu(normal/interrupt/NMI.) 143aba09b44SMasami HiramatsuBut if it relies on the 'current_kprobe' recursion lock, it has to check 144aba09b44SMasami Hiramatsukprobe_running() and use kprobe_busy_*() APIs. 145aba09b44SMasami Hiramatsu 146aba09b44SMasami HiramatsuFprobe has FPROBE_FL_KPROBE_SHARED flag to do this. If your common callback 147aba09b44SMasami Hiramatsucode will be shared with kprobes, please set FPROBE_FL_KPROBE_SHARED 148aba09b44SMasami Hiramatsu*before* registering the fprobe, like: 149aba09b44SMasami Hiramatsu 150aba09b44SMasami Hiramatsu.. code-block:: c 151aba09b44SMasami Hiramatsu 152aba09b44SMasami Hiramatsu fprobe.flags = FPROBE_FL_KPROBE_SHARED; 153aba09b44SMasami Hiramatsu 154aba09b44SMasami Hiramatsu register_fprobe(&fprobe, "func*", NULL); 155aba09b44SMasami Hiramatsu 156aba09b44SMasami HiramatsuThis will protect your common callback from the nested call. 157aba09b44SMasami Hiramatsu 158aba09b44SMasami HiramatsuThe missed counter 159aba09b44SMasami Hiramatsu================== 160aba09b44SMasami Hiramatsu 161aba09b44SMasami HiramatsuThe `fprobe` data structure has `fprobe::nmissed` counter field as same as 162aba09b44SMasami Hiramatsukprobes. 163aba09b44SMasami HiramatsuThis counter counts up when; 164aba09b44SMasami Hiramatsu 165aba09b44SMasami Hiramatsu - fprobe fails to take ftrace_recursion lock. This usually means that a function 166aba09b44SMasami Hiramatsu which is traced by other ftrace users is called from the entry_handler. 167aba09b44SMasami Hiramatsu 168aba09b44SMasami Hiramatsu - fprobe fails to setup the function exit because of the shortage of rethook 169aba09b44SMasami Hiramatsu (the shadow stack for hooking the function return.) 170aba09b44SMasami Hiramatsu 171aba09b44SMasami HiramatsuThe `fprobe::nmissed` field counts up in both cases. Therefore, the former 172aba09b44SMasami Hiramatsuskips both of entry and exit callback and the latter skips the exit 173aba09b44SMasami Hiramatsucallback, but in both case the counter will increase by 1. 174aba09b44SMasami Hiramatsu 175aba09b44SMasami HiramatsuNote that if you set the FTRACE_OPS_FL_RECURSION and/or FTRACE_OPS_FL_RCU to 176aba09b44SMasami Hiramatsu`fprobe::ops::flags` (ftrace_ops::flags) when registering the fprobe, this 177aba09b44SMasami Hiramatsucounter may not work correctly, because ftrace skips the fprobe function which 178aba09b44SMasami Hiramatsuincrease the counter. 179aba09b44SMasami Hiramatsu 180aba09b44SMasami Hiramatsu 181aba09b44SMasami HiramatsuFunctions and structures 182aba09b44SMasami Hiramatsu======================== 183aba09b44SMasami Hiramatsu 184aba09b44SMasami Hiramatsu.. kernel-doc:: include/linux/fprobe.h 185aba09b44SMasami Hiramatsu.. kernel-doc:: kernel/trace/fprobe.c 186aba09b44SMasami Hiramatsu 187