On Wed, 4 Sep 2024 08:58:58 +0200 Sven Schnelle <svens@xxxxxxxxxxxxx> wrote: > Add a function to decode argument types with the help of BTF. Will > be used to display arguments in the function and function graph > tracer. > > Signed-off-by: Sven Schnelle <svens@xxxxxxxxxxxxx> > --- > kernel/trace/trace_output.c | 68 +++++++++++++++++++++++++++++++++++++ > kernel/trace/trace_output.h | 9 +++++ > 2 files changed, 77 insertions(+) > > diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c > index d8b302d01083..70405c4cceb6 100644 > --- a/kernel/trace/trace_output.c > +++ b/kernel/trace/trace_output.c > @@ -12,8 +12,11 @@ > #include <linux/sched/clock.h> > #include <linux/sched/mm.h> > #include <linux/idr.h> > +#include <linux/btf.h> > +#include <linux/bpf.h> > > #include "trace_output.h" > +#include "trace_btf.h" > > /* must be a power of 2 */ > #define EVENT_HASHSIZE 128 > @@ -669,6 +672,71 @@ int trace_print_lat_context(struct trace_iterator *iter) > return !trace_seq_has_overflowed(s); > } > > +#ifdef CONFIG_FUNCTION_TRACE_ARGS > +void print_function_args(struct trace_seq *s, struct ftrace_regs *fregs, > + unsigned long func) > +{ > + const struct btf_param *param; > + const struct btf_type *t; > + const char *param_name; > + char name[KSYM_NAME_LEN]; > + unsigned long arg; > + struct btf *btf; > + s32 tid, nr = 0; > + int i; > + > + trace_seq_printf(s, "("); > + > + if (!ftrace_regs_has_args(fregs)) > + goto out; > + if (lookup_symbol_name(func, name)) > + goto out; > + > + btf = bpf_get_btf_vmlinux(); > + if (IS_ERR_OR_NULL(btf)) > + goto out; > + > + t = btf_find_func_proto(name, &btf); > + if (IS_ERR_OR_NULL(t)) > + goto out; > + > + param = btf_get_func_param(t, &nr); > + if (!param) > + goto out_put; > + > + for (i = 0; i < nr; i++) { > + arg = ftrace_regs_get_argument(fregs, i); > + > + param_name = btf_name_by_offset(btf, param[i].name_off); > + if (param_name) > + trace_seq_printf(s, "%s = ", param_name); > + t = btf_type_skip_modifiers(btf, param[i].type, &tid); > + if (!t) > + continue; > + switch (BTF_INFO_KIND(t->info)) { > + case BTF_KIND_PTR: > + trace_seq_printf(s, "0x%lx", arg); > + break; > + case BTF_KIND_INT: > + trace_seq_printf(s, "%ld", arg); Don't we check the size and signed? :) > + break; > + case BTF_KIND_ENUM: > + trace_seq_printf(s, "%ld", arg); nit: %d? (enum is equal to the int type) BTW, this series splits the patches by coding, not functionality. For the first review, it is OK. But eventually those should be merged. Thank you, > + break; > + default: > + trace_seq_printf(s, "0x%lx (%d)", arg, BTF_INFO_KIND(param[i].type)); > + break; > + } > + if (i < nr - 1) > + trace_seq_printf(s, ", "); > + } > +out_put: > + btf_put(btf); > +out: > + trace_seq_printf(s, ")"); > +} > +#endif > + > /** > * ftrace_find_event - find a registered event > * @type: the type of event to look for > diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h > index dca40f1f1da4..a21d8ce606f7 100644 > --- a/kernel/trace/trace_output.h > +++ b/kernel/trace/trace_output.h > @@ -41,5 +41,14 @@ extern struct rw_semaphore trace_event_sem; > #define SEQ_PUT_HEX_FIELD(s, x) \ > trace_seq_putmem_hex(s, &(x), sizeof(x)) > > +#ifdef CONFIG_FUNCTION_TRACE_ARGS > +void print_function_args(struct trace_seq *s, struct ftrace_regs *fregs, > + unsigned long func); > +#else > +static inline void print_function_args(struct trace_seq *s, struct ftrace_regs *fregs, > + unsigned long func) { > + trace_seq_puts(s, "()"); > +} > +#endif > #endif > > -- > 2.43.0 > -- Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>