On Sat, 26 Oct 2024 13:38:46 +0900 "Masami Hiramatsu (Google)" <mhiramat@xxxxxxxxxx> wrote: > From: Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx> > > Update fprobe documentation for the new fprobe on function-graph > tracer. This includes some bahvior changes and pt_regs to > ftrace_regs interface change. > > Signed-off-by: Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx> > --- > Changes in v2: > - Update @fregs parameter explanation. > --- > Documentation/trace/fprobe.rst | 42 ++++++++++++++++++++++++++-------------- > 1 file changed, 27 insertions(+), 15 deletions(-) > > diff --git a/Documentation/trace/fprobe.rst b/Documentation/trace/fprobe.rst > index 196f52386aaa..f58bdc64504f 100644 > --- a/Documentation/trace/fprobe.rst > +++ b/Documentation/trace/fprobe.rst > @@ -9,9 +9,10 @@ Fprobe - Function entry/exit probe > Introduction > ============ > > -Fprobe is a function entry/exit probe mechanism based on ftrace. > -Instead of using ftrace full feature, if you only want to attach callbacks > -on function entry and exit, similar to the kprobes and kretprobes, you can > +Fprobe is a function entry/exit probe mechanism based on the function-graph > +tracer. You could still say "ftrace" as function-graph is part of the "ftrace" infrastructure. But I don't care either way. > +Instead of tracing all functions, if you want to attach callbacks on specific > +function entry and exit, similar to the kprobes and kretprobes, you can > use fprobe. Compared with kprobes and kretprobes, fprobe gives faster > instrumentation for multiple functions with single handler. This document > describes how to use fprobe. > @@ -91,12 +92,14 @@ The prototype of the entry/exit callback function are as follows: > > .. code-block:: c > > - int entry_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct pt_regs *regs, void *entry_data); > + int entry_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct ftrace_regs *fregs, void *entry_data); > > - void exit_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct pt_regs *regs, void *entry_data); > + void exit_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long ret_ip, struct ftrace_regs *fregs, void *entry_data); > > -Note that the @entry_ip is saved at function entry and passed to exit handler. > -If the entry callback function returns !0, the corresponding exit callback will be cancelled. > +Note that the @entry_ip is saved at function entry and passed to exit > +handler. > +If the entry callback function returns !0, the corresponding exit callback > +will be cancelled. > > @fp > This is the address of `fprobe` data structure related to this handler. > @@ -112,12 +115,10 @@ If the entry callback function returns !0, the corresponding exit callback will > This is the return address that the traced function will return to, > somewhere in the caller. This can be used at both entry and exit. > > -@regs > - This is the `pt_regs` data structure at the entry and exit. Note that > - the instruction pointer of @regs may be different from the @entry_ip > - in the entry_handler. If you need traced instruction pointer, you need > - to use @entry_ip. On the other hand, in the exit_handler, the instruction > - pointer of @regs is set to the current return address. > +@fregs > + This is the `ftrace_regs` data structure at the entry and exit. This > + includes the function parameters, or the return values. So user can > + access thos values via appropriate `ftrace_regs_*` APIs. > > @entry_data > This is a local storage to share the data between entry and exit handlers. > @@ -125,6 +126,17 @@ If the entry callback function returns !0, the corresponding exit callback will > and `entry_data_size` field when registering the fprobe, the storage is > allocated and passed to both `entry_handler` and `exit_handler`. > > +Entry data size and exit handlers on the same function > +====================================================== > + > +Since the entry data is passed via per-task stack and it is has limited size, "and it has limited size" > +the entry data size per probe is limited to `15 * sizeof(long)`. You also need > +to take care that the different fprobes are probing on the same function, this > +limit becomes smaller. The entry data size is aligned to `sizeof(long)` and > +each fprobe which has exit handler uses a `sizeof(long)` space on the stack, > +you should keep the number of fprobes on the same function as small as > +possible. -- Steve > + > Share the callbacks with kprobes > ================================ > > @@ -165,8 +177,8 @@ This counter counts up when; > - fprobe fails to take ftrace_recursion lock. This usually means that a function > which is traced by other ftrace users is called from the entry_handler. > > - - fprobe fails to setup the function exit because of the shortage of rethook > - (the shadow stack for hooking the function return.) > + - fprobe fails to setup the function exit because of failing to allocate the > + data buffer from the per-task shadow stack. > > The `fprobe::nmissed` field counts up in both cases. Therefore, the former > skips both of entry and exit callback and the latter skips the exit