From nobody Tue Jun 30 01:43:53 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A74B8C433FE for ; Sun, 30 Jan 2022 14:44:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355106AbiA3Oow (ORCPT ); Sun, 30 Jan 2022 09:44:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355094AbiA3Oou (ORCPT ); Sun, 30 Jan 2022 09:44:50 -0500 Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E5C73C06173B for ; Sun, 30 Jan 2022 06:44:49 -0800 (PST) Received: by mail-pl1-x62a.google.com with SMTP id b15so10328696plg.3 for ; Sun, 30 Jan 2022 06:44:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qmBc2fV0r1moivjZbcJeWcHeiDtMm4VRovCbcEge9wo=; b=pFzOuihs//feYMB8MtfCtzXJEDKXnf3g+zAJf496Mp+eNJCwOXX4sxXkeokno7XV74 NtKp4x82W+sob0FgXPHf9ZZK+Ujo5yN9j9tk1Y+sR8li1rjb96wzzwSJYXff/UQloc9K qbbJ/Vo4naHxURvsDG4x6QmMItOfgeSzVUyIyX9f0tfpeDlq6+GDMIFJvQrMiHlfLQAN wkIYJ5z7uoDz8FdUS3Wv8M9/r2Jp9F4Vghhs470utBsRx+JfjQzmmGXrjQ0f5c/sNNon S5kfARtbNfcyR39/rOnHy3H2VuNdLGY6gAAp2uNqIaRzq6BvlQOa0WnjIQiyw6U7Dgnw ZGbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qmBc2fV0r1moivjZbcJeWcHeiDtMm4VRovCbcEge9wo=; b=5nmB9xGBAerE4p5HLf1YeQIyctNHkNYr/2BCVytXaiKoCmyh1q13OpHX5KtmxQHCna IzNvWrtAdSQ3RexN/nE/j0S+foGS/Np7zcRUICqjwOTSXmcvEMVdvrssCBeoMN0uGB6Z jO7KhNEmVf089tWJjm7fqrxzAGRV0ZsKO/JpmnJ/89WdfsQcrSr4s7cRGBVHNjIyJ70Q b3VWI/6dWGRgBhcBatt6sXWoNh68Zmd6uueS2kxz66KtzdV2RFG5iZBR85wyZA8m3gcz ySxJN7lPASCOj1OYhA9nr6s9GwWa3wtd/m03B8zup+kXSo2qMJrzZ2vsaavKSY5POBnu U9yQ== X-Gm-Message-State: AOAM530kwacW9dB5SAUtICW83H38afTKG1a4658nLgy6X/QPpEQDuKXL b3KpRL/iVWHERiFK96bnSj8= X-Google-Smtp-Source: ABdhPJxh0cxc40HaUk8YN0SVJZ/F+r2eE/QyPPek/R0PJlYYKsnNSwkOZaG9a+15ag0BzQyXeYBUYA== X-Received: by 2002:a17:903:234e:: with SMTP id c14mr16758286plh.50.1643553888755; Sun, 30 Jan 2022 06:44:48 -0800 (PST) Received: from localhost.localdomain (li567-56.members.linode.com. [192.155.81.56]) by smtp.gmail.com with ESMTPSA id w8sm10502126pfu.128.2022.01.30.06.44.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 30 Jan 2022 06:44:48 -0800 (PST) From: Jeff Xie To: rostedt@goodmis.org Cc: mhiramat@kernel.org, mingo@redhat.com, zanussi@kernel.org, linux-kernel@vger.kernel.org, Jeff Xie Subject: [PATCH v8 1/4] trace: Add trace any kernel object Date: Sun, 30 Jan 2022 22:44:27 +0800 Message-Id: <20220130144430.453221-2-xiehuan09@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220130144430.453221-1-xiehuan09@gmail.com> References: <20220130144430.453221-1-xiehuan09@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Introduce objtrace trigger to get the call flow by tracing any kernel object in the function parameter. The objtrace trigger makes a list of the target object address from the given event parameter, and records all kernel function calls which has the object address in its parameter. Syntax: objtrace:add:obj[:count][if ] Usage: # echo 'p bio_add_page arg1=3D$arg1' > kprobe_events # cd events/kprobes/p_bio_add_page_0 # echo 'objtrace:add:arg1:1 if comm =3D=3D "cat"' > ./trigger # cat /test.txt Signed-off-by: Jeff Xie --- include/linux/trace_events.h | 1 + kernel/trace/Kconfig | 10 + kernel/trace/Makefile | 1 + kernel/trace/trace.c | 3 + kernel/trace/trace.h | 8 + kernel/trace/trace_entries.h | 17 + kernel/trace/trace_events_trigger.c | 1 + kernel/trace/trace_object.c | 465 ++++++++++++++++++++++++++++ kernel/trace/trace_output.c | 40 +++ 9 files changed, 546 insertions(+) create mode 100644 kernel/trace/trace_object.c diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 70c069aef02c..3ccdbc1d25dd 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -685,6 +685,7 @@ enum event_trigger_type { ETT_EVENT_HIST =3D (1 << 4), ETT_HIST_ENABLE =3D (1 << 5), ETT_EVENT_EPROBE =3D (1 << 6), + ETT_TRACE_OBJECT =3D (1 << 7), }; =20 extern int filter_match_preds(struct event_filter *filter, void *rec); diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index a5eb5e7fd624..c51b7eb1508d 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -250,6 +250,16 @@ config FUNCTION_PROFILER =20 If in doubt, say N. =20 +config TRACE_OBJECT + bool "Trace kernel object in function parameter" + depends on FUNCTION_TRACER + depends on HAVE_FUNCTION_ARG_ACCESS_API + select TRACING + default y + help + You can trace the kernel object in the kernel function parameter. + The kernel object is dynamically specified via event trigger. + config STACK_TRACER bool "Trace max stack" depends on HAVE_FUNCTION_TRACER diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index bedc5caceec7..b924b8e55922 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) +=3D trace_functions_= graph.o obj-$(CONFIG_TRACE_BRANCH_PROFILING) +=3D trace_branch.o obj-$(CONFIG_BLK_DEV_IO_TRACE) +=3D blktrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) +=3D fgraph.o +obj-$(CONFIG_TRACE_OBJECT) +=3D trace_object.o ifeq ($(CONFIG_BLOCK),y) obj-$(CONFIG_EVENT_TRACING) +=3D blktrace.o endif diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index a734d5ae34c8..b4513c2bbd52 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5605,6 +5605,9 @@ static const char readme_msg[] =3D "\t enable_hist::\n" "\t disable_hist::\n" #endif +#ifdef CONFIG_TRACE_OBJECT + "\t objtrace:add:obj[:count][if ]\n" +#endif #ifdef CONFIG_STACKTRACE "\t\t stacktrace\n" #endif diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 0f5e22238cd2..8b66515a36d5 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -54,6 +54,7 @@ enum trace_type { TRACE_TIMERLAT, TRACE_RAW_DATA, TRACE_FUNC_REPEATS, + TRACE_OBJECT, =20 __TRACE_LAST_TYPE, }; @@ -472,6 +473,7 @@ extern void __ftrace_bad_type(void); TRACE_GRAPH_RET); \ IF_ASSIGN(var, ent, struct func_repeats_entry, \ TRACE_FUNC_REPEATS); \ + IF_ASSIGN(var, ent, struct trace_object_entry, TRACE_OBJECT);\ __ftrace_bad_type(); \ } while (0) =20 @@ -1537,6 +1539,12 @@ static inline int register_trigger_hist_cmd(void) { = return 0; } static inline int register_trigger_hist_enable_disable_cmds(void) { return= 0; } #endif =20 +#ifdef CONFIG_TRACE_OBJECT +extern int register_trigger_object_cmd(void); +#else +static inline int register_trigger_object_cmd(void) { return 0; } +#endif + extern int register_trigger_cmds(void); extern void clear_event_triggers(struct trace_array *tr); =20 diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index cd41e863b51c..bb120d9498a9 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -401,3 +401,20 @@ FTRACE_ENTRY(timerlat, timerlat_entry, __entry->context, __entry->timer_latency) ); + +/* + * trace object entry: + */ +FTRACE_ENTRY(object, trace_object_entry, + + TRACE_OBJECT, + + F_STRUCT( + __field( unsigned long, ip ) + __field( unsigned long, parent_ip ) + __field( unsigned long, object ) + ), + + F_printk(" %ps <-- %ps object:%lx\n", + (void *)__entry->ip, (void *)__entry->parent_ip, __entry->object) +); diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_event= s_trigger.c index d00fee705f9c..c3371a6902af 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -2025,6 +2025,7 @@ __init int register_trigger_cmds(void) register_trigger_enable_disable_cmds(); register_trigger_hist_enable_disable_cmds(); register_trigger_hist_cmd(); + register_trigger_object_cmd(); =20 return 0; } diff --git a/kernel/trace/trace_object.c b/kernel/trace/trace_object.c new file mode 100644 index 000000000000..1eb485c513e9 --- /dev/null +++ b/kernel/trace/trace_object.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * trace the kernel object in the kernel function parameter + * Copyright (C) 2021 Jeff Xie + */ + +#define pr_fmt(fmt) "trace_object: " fmt + +#include "trace_output.h" + +#define MAX_TRACED_OBJECT 5 +static DEFINE_PER_CPU(unsigned int, trace_object_event_disable); +static DEFINE_RAW_SPINLOCK(trace_obj_lock); +static struct trace_event_file event_trace_file; +static const int max_args_num =3D 6; +static atomic_t trace_object_ref; +static atomic_t num_traced_obj; +static int exit_trace_object(void); +static int init_trace_object(void); + +static struct object_instance { + void *obj; +} traced_obj[MAX_TRACED_OBJECT]; + +static bool object_exist(void *obj) +{ + int i, max; + + max =3D atomic_read(&num_traced_obj); + smp_rmb(); + for (i =3D 0; i < max; i++) { + if (traced_obj[i].obj =3D=3D obj) + return true; + } + return false; +} + +static bool object_empty(void) +{ + return !atomic_read(&num_traced_obj); +} + +static void set_trace_object(void *obj) +{ + unsigned long flags; + + if (in_nmi()) + return; + + if (!obj) + return; + + if (object_exist(obj)) + return; + + /* only this place has write operations */ + raw_spin_lock_irqsave(&trace_obj_lock, flags); + if (atomic_read(&num_traced_obj) =3D=3D MAX_TRACED_OBJECT) { + trace_printk("object_pool is full, can't trace object:0x%px\n", obj); + goto out; + } + traced_obj[atomic_read(&num_traced_obj)].obj =3D obj; + /* make sure the num_traced_obj update always appears after traced_obj up= date */ + smp_wmb(); + atomic_inc(&num_traced_obj); +out: + raw_spin_unlock_irqrestore(&trace_obj_lock, flags); +} + +static void submit_trace_object(unsigned long ip, unsigned long parent_ip, + unsigned long object) +{ + + struct trace_buffer *buffer; + struct ring_buffer_event *event; + struct trace_object_entry *entry; + int pc; + + pc =3D preempt_count(); + event =3D trace_event_buffer_lock_reserve(&buffer, &event_trace_file, + TRACE_OBJECT, sizeof(*entry), pc); + if (!event) + return; + entry =3D ring_buffer_event_data(event); + entry->ip =3D ip; + entry->parent_ip =3D parent_ip; + entry->object =3D object; + + event_trigger_unlock_commit(&event_trace_file, buffer, event, + entry, pc); +} + +static void +trace_object_events_call(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *op, struct ftrace_regs *fregs) +{ + struct pt_regs *pt_regs =3D ftrace_get_regs(fregs); + unsigned long obj; + unsigned int disabled; + int n; + + preempt_disable_notrace(); + + disabled =3D this_cpu_inc_return(trace_object_event_disable); + if (disabled !=3D 1) + goto out; + + if (object_empty()) + goto out; + + for (n =3D 0; n < max_args_num; n++) { + obj =3D regs_get_kernel_argument(pt_regs, n); + if (object_exist((void *)obj)) + submit_trace_object(ip, parent_ip, obj); + /* The parameters of a function may match multiple objects */ + } +out: + this_cpu_dec(trace_object_event_disable); + preempt_enable_notrace(); +} + +static struct ftrace_ops trace_ops =3D { + .func =3D trace_object_events_call, + .flags =3D FTRACE_OPS_FL_SAVE_REGS, +}; + +static void +trace_object_trigger(struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) +{ + + struct ftrace_event_field *field =3D data->private_data; + void *obj =3D NULL; + + memcpy(&obj, rec + field->offset, sizeof(obj)); + set_trace_object(obj); +} + +static void +trace_object_trigger_free(struct event_trigger_ops *ops, + struct event_trigger_data *data) +{ + if (WARN_ON_ONCE(data->ref <=3D 0)) + return; + + data->ref--; + if (!data->ref) + trigger_data_free(data); +} + +static void +trace_object_count_trigger(struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) +{ + if (!data->count) + return; + + if (data->count !=3D -1) + (data->count)--; + + trace_object_trigger(data, buffer, rec, event); +} + +static int event_object_trigger_init(struct event_trigger_ops *ops, + struct event_trigger_data *data) +{ + data->ref++; + return 0; +} + +static int +event_trigger_print(const char *name, struct seq_file *m, + void *data, char *filter_str) +{ + long count =3D (long)data; + + seq_puts(m, name); + + if (count =3D=3D -1) + seq_puts(m, ":unlimited"); + else + seq_printf(m, ":count=3D%ld", count); + + if (filter_str) + seq_printf(m, " if %s\n", filter_str); + else + seq_putc(m, '\n'); + + return 0; +} + +static int +trace_object_trigger_print(struct seq_file *m, struct event_trigger_ops *o= ps, + struct event_trigger_data *data) +{ + return event_trigger_print("objtrace", m, (void *)data->count, + data->filter_str); +} + +static struct event_trigger_ops objecttrace_trigger_ops =3D { + .trigger =3D trace_object_trigger, + .print =3D trace_object_trigger_print, + .init =3D event_object_trigger_init, + .free =3D trace_object_trigger_free, +}; + +static struct event_trigger_ops objecttrace_count_trigger_ops =3D { + .trigger =3D trace_object_count_trigger, + .print =3D trace_object_trigger_print, + .init =3D event_object_trigger_init, + .free =3D trace_object_trigger_free, +}; + +static struct event_trigger_ops * +objecttrace_get_trigger_ops(char *cmd, char *param) +{ + return param ? &objecttrace_count_trigger_ops : &objecttrace_trigger_ops; +} + +static int register_object_trigger(char *glob, + struct event_trigger_data *data, + struct trace_event_file *file) +{ + struct event_trigger_data *test; + int ret =3D 0; + + lockdep_assert_held(&event_mutex); + + list_for_each_entry(test, &file->triggers, list) { + if (test->cmd_ops->trigger_type =3D=3D data->cmd_ops->trigger_type) { + ret =3D -EEXIST; + goto out; + } + } + + if (data->ops->init) { + ret =3D data->ops->init(data->ops, data); + if (ret < 0) + goto out; + } + + list_add_rcu(&data->list, &file->triggers); + ret++; + + update_cond_flag(file); + if (trace_event_trigger_enable_disable(file, 1) < 0) { + list_del_rcu(&data->list); + update_cond_flag(file); + ret--; + } + init_trace_object(); +out: + return ret; +} + +static void unregister_object_trigger(char *glob, + struct event_trigger_data *test, + struct trace_event_file *file) +{ + struct event_trigger_data *data; + bool unregistered =3D false; + + lockdep_assert_held(&event_mutex); + + list_for_each_entry(data, &file->triggers, list) { + if (data->cmd_ops->trigger_type =3D=3D test->cmd_ops->trigger_type) { + unregistered =3D true; + list_del_rcu(&data->list); + trace_event_trigger_enable_disable(file, 0); + update_cond_flag(file); + break; + } + } + + if (unregistered) { + if (data->ops->free) + data->ops->free(data->ops, data); + exit_trace_object(); + } +} + +static int +event_object_trigger_parse(struct event_command *cmd_ops, + struct trace_event_file *file, + char *glob, char *cmd, char *param) +{ + struct event_trigger_data *trigger_data; + struct event_trigger_ops *trigger_ops; + struct trace_event_call *call; + struct ftrace_event_field *field; + char *objtrace_cmd; + char *trigger =3D NULL; + char *arg; + char *number; + int ret; + + ret =3D -EINVAL; + if (!param) + goto out; + + /* separate the trigger from the filter (c:a:n [if filter]) */ + trigger =3D strsep(¶m, " \t"); + if (!trigger) + goto out; + if (param) { + param =3D skip_spaces(param); + if (!*param) + param =3D NULL; + } + + objtrace_cmd =3D strsep(&trigger, ":"); + if (!objtrace_cmd || strcmp(objtrace_cmd, "add")) + goto out; + + arg =3D strsep(&trigger, ":"); + if (!arg) + goto out; + call =3D file->event_call; + field =3D trace_find_event_field(call, arg); + if (!field) + goto out; + + if (field->size !=3D sizeof(void *)) + goto out; + + trigger_ops =3D cmd_ops->get_trigger_ops(cmd, trigger); + + ret =3D -ENOMEM; + trigger_data =3D kzalloc(sizeof(*trigger_data), GFP_KERNEL); + if (!trigger_data) + goto out; + + trigger_data->count =3D -1; + trigger_data->ops =3D trigger_ops; + trigger_data->cmd_ops =3D cmd_ops; + trigger_data->private_data =3D field; + INIT_LIST_HEAD(&trigger_data->list); + INIT_LIST_HEAD(&trigger_data->named_list); + + if (glob[0] =3D=3D '!') { + cmd_ops->unreg(glob+1, trigger_data, file); + kfree(trigger_data); + ret =3D 0; + goto out; + } + + if (trigger) { + number =3D strsep(&trigger, ":"); + + ret =3D -EINVAL; + if (!strlen(number)) + goto out_free; + + /* + * We use the callback data field (which is a pointer) + * as our counter. + */ + ret =3D kstrtoul(number, 0, &trigger_data->count); + if (ret) + goto out_free; + } + + if (!param) /* if param is non-empty, it's supposed to be a filter */ + goto out_reg; + + if (!cmd_ops->set_filter) + goto out_reg; + + ret =3D cmd_ops->set_filter(param, trigger_data, file); + if (ret < 0) + goto out_free; + + out_reg: + /* Up the trigger_data count to make sure reg doesn't free it on failure = */ + event_object_trigger_init(trigger_ops, trigger_data); + ret =3D cmd_ops->reg(glob, trigger_data, file); + /* + * The above returns on success the # of functions enabled, + * but if it didn't find any functions it returns zero. + * Consider no functions a failure too. + */ + if (!ret) { + cmd_ops->unreg(glob, trigger_data, file); + ret =3D -ENOENT; + } else if (ret > 0) + ret =3D 0; + + /* Down the counter of trigger_data or free it if not used anymore */ + trace_object_trigger_free(trigger_ops, trigger_data); + out: + return ret; + + out_free: + if (cmd_ops->set_filter) + cmd_ops->set_filter(NULL, trigger_data, NULL); + kfree(trigger_data); + goto out; +} + +static struct event_command trigger_object_cmd =3D { + .name =3D "objtrace", + .trigger_type =3D ETT_TRACE_OBJECT, + .flags =3D EVENT_CMD_FL_NEEDS_REC, + .parse =3D event_object_trigger_parse, + .reg =3D register_object_trigger, + .unreg =3D unregister_object_trigger, + .get_trigger_ops =3D objecttrace_get_trigger_ops, + .set_filter =3D set_trigger_filter, +}; + +__init int register_trigger_object_cmd(void) +{ + int ret; + + ret =3D register_event_command(&trigger_object_cmd); + WARN_ON(ret < 0); + + return ret; +} + +static int init_trace_object(void) +{ + int ret; + + if (atomic_inc_return(&trace_object_ref) !=3D 1) { + ret =3D 0; + goto out; + } + + event_trace_file.tr =3D top_trace_array(); + if (WARN_ON(!event_trace_file.tr)) { + ret =3D -1; + atomic_dec(&trace_object_ref); + goto out; + } + ret =3D register_ftrace_function(&trace_ops); +out: + return ret; +} + +static int exit_trace_object(void) +{ + int ret; + + if (WARN_ON_ONCE(atomic_read(&trace_object_ref) <=3D 0)) { + ret =3D -1; + goto out; + } + + if (atomic_dec_return(&trace_object_ref) !=3D 0) { + ret =3D 0; + goto out; + } + + ret =3D unregister_ftrace_function(&trace_ops); + if (ret) { + pr_err("can't unregister ftrace for trace object\n"); + goto out; + } + atomic_set(&num_traced_obj, 0); +out: + return ret; +} diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 8aa493d25c73..265428154638 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -1547,6 +1547,45 @@ static struct trace_event trace_func_repeats_event = =3D { .funcs =3D &trace_func_repeats_funcs, }; =20 +/* TRACE_OBJECT */ +static enum print_line_t trace_object_print(struct trace_iterator *iter, i= nt flags, + struct trace_event *event) +{ + struct trace_object_entry *field; + struct trace_seq *s =3D &iter->seq; + + trace_assign_type(field, iter->ent); + print_fn_trace(s, field->ip, field->parent_ip, flags); + trace_seq_printf(s, " object:0x%lx", field->object); + trace_seq_putc(s, '\n'); + + return trace_handle_return(s); +} + +static enum print_line_t trace_object_raw(struct trace_iterator *iter, int= flags, + struct trace_event *event) +{ + struct trace_object_entry *field; + + trace_assign_type(field, iter->ent); + + trace_seq_printf(&iter->seq, "%lx %lx\n", + field->ip, + field->parent_ip); + + return trace_handle_return(&iter->seq); +} + +static struct trace_event_functions trace_object_funcs =3D { + .trace =3D trace_object_print, + .raw =3D trace_object_raw, +}; + +static struct trace_event trace_object_event =3D { + .type =3D TRACE_OBJECT, + .funcs =3D &trace_object_funcs, +}; + static struct trace_event *events[] __initdata =3D { &trace_fn_event, &trace_ctx_event, @@ -1561,6 +1600,7 @@ static struct trace_event *events[] __initdata =3D { &trace_timerlat_event, &trace_raw_data_event, &trace_func_repeats_event, + &trace_object_event, NULL }; =20 --=20 2.25.1 From nobody Tue Jun 30 01:43:53 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6CDBFC433F5 for ; Sun, 30 Jan 2022 14:45:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355138AbiA3Oo7 (ORCPT ); Sun, 30 Jan 2022 09:44:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58704 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355093AbiA3Oow (ORCPT ); Sun, 30 Jan 2022 09:44:52 -0500 Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3AC1FC061714 for ; Sun, 30 Jan 2022 06:44:52 -0800 (PST) Received: by mail-pj1-x102b.google.com with SMTP id nn16-20020a17090b38d000b001b56b2bce31so11180288pjb.3 for ; Sun, 30 Jan 2022 06:44:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=66psKv/JXm9/Wr593dlqnm/Uu7uPX3XYGWB9MwbiDlE=; b=OvEbLoqEJxhsF2PxZFrmfGuDwOolt0HOF+/rcOhes7vh+2DahECFrHIkXYBqdmCRlB be4X86AJvpy22r63il4uFZuL6ijXPSWI5SkVXsp/yeg/tQQMKNFoo7nhWh1h8Exex9zF Q9AzF7YoJ4rePS+cpYewXEWR8xDW/Xxxt3Q1sw9T8/lag17KURoY3uQSFGBRe7SXZTOA z7sxfnRBernSgd5NbXK8a61BB/t0MHPxYTncH3kerBGpzDMWFYeyy1q/Y1/um1JDTsVV +v3PaZ6+sEP7Zmp83kJ5pnwsROx1dbJ4ozuBOR9cWzSQr7ciGk68fbLkBqooUXQyHkD0 n5lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=66psKv/JXm9/Wr593dlqnm/Uu7uPX3XYGWB9MwbiDlE=; b=NU2uTVwqTbE7thJJm7m4b7uS+j3LmrE5zgGe2PW5y7xRALXjESGwAe3npGEdIfIbzN qeEd48ypJMwg+QePgRTnLJ1HKbi85bUgyV6Cw5tSg5Ahw+jKBzh+o6/W3eyRVM3pOQtI uBQZmzwy6WmvicguSw1+ceJZ0/Lr+9gj3vOpX0rxfCJ3588F7RZSmKF47mQMbIeBmqrY yWVqyak8qZ6e8Ssnoe0lkDF/o1Ytqaf1zVcAHwyjseAbjj6m0QHBgWZfxWJDeB9s9DhB tU3qu1jKb0hqyoT0GPfk70iD+7nLrKQCVS49zPT2OHUtSGZwmPCnYNQ/xej5ZfrlfsoP 49WA== X-Gm-Message-State: AOAM532OAWYS30pZ4AtAhj9Qe0KDlPvpsvrPcaTaCD0/zzILTEnDEs+G nVrT5MYl6CpyidxU+WMEE0s= X-Google-Smtp-Source: ABdhPJxIQCxEl0+CMZs7yr4V19DXsAR3+BojsU295SzUcFJWKa25ZEKwfF36ZNbtYqgFp+kn/weKBw== X-Received: by 2002:a17:902:f54b:: with SMTP id h11mr17771588plf.58.1643553891705; Sun, 30 Jan 2022 06:44:51 -0800 (PST) Received: from localhost.localdomain (li567-56.members.linode.com. [192.155.81.56]) by smtp.gmail.com with ESMTPSA id w8sm10502126pfu.128.2022.01.30.06.44.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 30 Jan 2022 06:44:51 -0800 (PST) From: Jeff Xie To: rostedt@goodmis.org Cc: mhiramat@kernel.org, mingo@redhat.com, zanussi@kernel.org, linux-kernel@vger.kernel.org, Jeff Xie Subject: [PATCH v8 2/4] trace/objtrace: get the value of the object Date: Sun, 30 Jan 2022 22:44:28 +0800 Message-Id: <20220130144430.453221-3-xiehuan09@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220130144430.453221-1-xiehuan09@gmail.com> References: <20220130144430.453221-1-xiehuan09@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Using objtrace trigger to get the value of the object which from the kernel function parameter. Syntax: objtrace:add:obj[,offset][:type][:count][if ] Usage: # echo 'p bio_add_page arg1=3D$arg1' > ./kprobe_events # gdb vmlinux (gdb) p &(((struct bio *)0)->bi_iter.bi_size) $1 =3D (unsigned int *) 0x28 # echo 'objtrace:add:arg1,0x28:u32:1 if comm =3D=3D "cat"' > ./events/kpro= bes/ \ p_bio_add_page_0/trigger # cat /test.txt Signed-off-by: Jeff Xie --- kernel/trace/trace.c | 2 +- kernel/trace/trace_entries.h | 5 +- kernel/trace/trace_object.c | 214 +++++++++++++++++++++++++++++++---- kernel/trace/trace_output.c | 6 +- 4 files changed, 197 insertions(+), 30 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index b4513c2bbd52..5f145837d2ff 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5606,7 +5606,7 @@ static const char readme_msg[] =3D "\t disable_hist::\n" #endif #ifdef CONFIG_TRACE_OBJECT - "\t objtrace:add:obj[:count][if ]\n" + "\t objtrace:add:obj[,offset][:type][:count][if ]\n" #endif #ifdef CONFIG_STACKTRACE "\t\t stacktrace\n" diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index bb120d9498a9..2407c45a568c 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -413,8 +413,9 @@ FTRACE_ENTRY(object, trace_object_entry, __field( unsigned long, ip ) __field( unsigned long, parent_ip ) __field( unsigned long, object ) + __field( unsigned long, value ) ), =20 - F_printk(" %ps <-- %ps object:%lx\n", - (void *)__entry->ip, (void *)__entry->parent_ip, __entry->object) + F_printk(" %ps <-- %ps object:%lx value:%lx\n", (void *)__entry->ip, + (void *)__entry->parent_ip, __entry->object, __entry->value) ); diff --git a/kernel/trace/trace_object.c b/kernel/trace/trace_object.c index 1eb485c513e9..01821aa6be04 100644 --- a/kernel/trace/trace_object.c +++ b/kernel/trace/trace_object.c @@ -18,10 +18,35 @@ static atomic_t num_traced_obj; static int exit_trace_object(void); static int init_trace_object(void); =20 +/* + * get the offset from the special object and + * the type size of the value + */ static struct object_instance { void *obj; + int obj_offset; + int obj_value_type_size; } traced_obj[MAX_TRACED_OBJECT]; =20 +/* objtrace private data */ +struct objtrace_trigger_data { + struct ftrace_event_field *field; + int obj_offset; + int obj_value_type_size; +}; + +/* get the type size for the special object */ +struct objtrace_fetch_type { + char *name; + int type_size; +}; + +enum objattr { + OBJ_OFFSET, + OBJ_VAL_TYPE_SIZE, + MAX_OBJ_ATTR +}; + static bool object_exist(void *obj) { int i, max; @@ -35,13 +60,37 @@ static bool object_exist(void *obj) return false; } =20 +static int get_object_attr(void *obj, int objattr, int *result) +{ + int i, max; + + max =3D atomic_read(&num_traced_obj); + smp_rmb(); + for (i =3D 0; i < max; i++) { + if (traced_obj[i].obj =3D=3D obj) { + switch (objattr) { + case OBJ_OFFSET: + *result =3D traced_obj[i].obj_offset; + return 0; + case OBJ_VAL_TYPE_SIZE: + *result =3D traced_obj[i].obj_value_type_size; + return 0; + default: + return -EINVAL; + } + } + } + return -EINVAL; +} + static bool object_empty(void) { return !atomic_read(&num_traced_obj); } =20 -static void set_trace_object(void *obj) +static void set_trace_object(void *obj, int obj_offset, int obj_value_type= _size) { + unsigned int traced_objs; unsigned long flags; =20 if (in_nmi()) @@ -55,11 +104,14 @@ static void set_trace_object(void *obj) =20 /* only this place has write operations */ raw_spin_lock_irqsave(&trace_obj_lock, flags); - if (atomic_read(&num_traced_obj) =3D=3D MAX_TRACED_OBJECT) { + traced_objs =3D atomic_read(&num_traced_obj); + if (traced_objs =3D=3D MAX_TRACED_OBJECT) { trace_printk("object_pool is full, can't trace object:0x%px\n", obj); goto out; } - traced_obj[atomic_read(&num_traced_obj)].obj =3D obj; + traced_obj[traced_objs].obj =3D obj; + traced_obj[traced_objs].obj_value_type_size =3D obj_value_type_size; + traced_obj[traced_objs].obj_offset =3D obj_offset; /* make sure the num_traced_obj update always appears after traced_obj up= date */ smp_wmb(); atomic_inc(&num_traced_obj); @@ -68,7 +120,7 @@ static void set_trace_object(void *obj) } =20 static void submit_trace_object(unsigned long ip, unsigned long parent_ip, - unsigned long object) + unsigned long object, unsigned long value) { =20 struct trace_buffer *buffer; @@ -85,19 +137,52 @@ static void submit_trace_object(unsigned long ip, unsi= gned long parent_ip, entry->ip =3D ip; entry->parent_ip =3D parent_ip; entry->object =3D object; + entry->value =3D value; =20 event_trigger_unlock_commit(&event_trace_file, buffer, event, entry, pc); } =20 +static inline long get_object_value(unsigned long *val, void *obj, int typ= e_size) +{ + char tmp[sizeof(u64)]; + long ret =3D 0; + + ret =3D copy_from_kernel_nofault(tmp, obj, sizeof(tmp)); + if (ret) + return ret; + switch (type_size) { + case 1: { + *val =3D (unsigned long)*(u8 *)tmp; + break; + } + case 2: { + *val =3D (unsigned long)*(u16 *)tmp; + break; + } + case 4: { + *val =3D (unsigned long)*(u32 *)tmp; + break; + } + case 8: { + *val =3D (unsigned long)*(u64 *)tmp; + break; + } + default: + return -EINVAL; + } + + return 0; +} + static void trace_object_events_call(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { struct pt_regs *pt_regs =3D ftrace_get_regs(fregs); - unsigned long obj; + int n, ret, val_type_size, obj_offset; + unsigned long obj, val; unsigned int disabled; - int n; =20 preempt_disable_notrace(); =20 @@ -110,8 +195,19 @@ trace_object_events_call(unsigned long ip, unsigned lo= ng parent_ip, =20 for (n =3D 0; n < max_args_num; n++) { obj =3D regs_get_kernel_argument(pt_regs, n); - if (object_exist((void *)obj)) - submit_trace_object(ip, parent_ip, obj); + if (object_exist((void *)obj)) { + ret =3D get_object_attr((void *)obj, OBJ_OFFSET, &obj_offset); + if (unlikely(ret) < 0) + goto out; + + get_object_attr((void *)obj, OBJ_VAL_TYPE_SIZE, &val_type_size); + if (unlikely(ret) < 0) + goto out; + + if (get_object_value(&val, (void *)(obj + obj_offset), val_type_size)) + continue; + submit_trace_object(ip, parent_ip, obj, val); + } /* The parameters of a function may match multiple objects */ } out: @@ -129,12 +225,14 @@ trace_object_trigger(struct event_trigger_data *data, struct trace_buffer *buffer, void *rec, struct ring_buffer_event *event) { + struct objtrace_trigger_data *obj_data =3D data->private_data; + struct ftrace_event_field *field; + void *obj; =20 - struct ftrace_event_field *field =3D data->private_data; - void *obj =3D NULL; - + field =3D obj_data->field; memcpy(&obj, rec + field->offset, sizeof(obj)); - set_trace_object(obj); + /* set the offset from the special object and the type size of the value*/ + set_trace_object(obj, obj_data->obj_offset, obj_data->obj_value_type_size= ); } =20 static void @@ -145,8 +243,10 @@ trace_object_trigger_free(struct event_trigger_ops *op= s, return; =20 data->ref--; - if (!data->ref) + if (!data->ref) { + kfree(data->private_data); trigger_data_free(data); + } } =20 static void @@ -281,6 +381,22 @@ static void unregister_object_trigger(char *glob, } } =20 +static const struct objtrace_fetch_type objtrace_fetch_types[] =3D { + {"u8", 1}, + {"s8", 1}, + {"x8", 1}, + {"u16", 2}, + {"s16", 2}, + {"x16", 2}, + {"u32", 4}, + {"s32", 4}, + {"x32", 4}, + {"u64", 8}, + {"s64", 8}, + {"x64", 8}, + {} +}; + static int event_object_trigger_parse(struct event_command *cmd_ops, struct trace_event_file *file, @@ -288,19 +404,22 @@ event_object_trigger_parse(struct event_command *cmd_= ops, { struct event_trigger_data *trigger_data; struct event_trigger_ops *trigger_ops; + struct objtrace_trigger_data *obj_data; struct trace_event_call *call; struct ftrace_event_field *field; - char *objtrace_cmd; - char *trigger =3D NULL; - char *arg; - char *number; - int ret; + char *type, *tr, *obj, *tmp, *trigger =3D NULL; + char *number, *objtrace_cmd; + int ret, i, def_type_size, obj_value_type_size =3D 0; + long offset =3D 0; =20 ret =3D -EINVAL; if (!param) goto out; =20 - /* separate the trigger from the filter (c:a:n [if filter]) */ + /* + * separate the trigger from the filter: + * objtrace:add:OBJ[,OFFS][:TYPE][:COUNT] [if filter] + */ trigger =3D strsep(¶m, " \t"); if (!trigger) goto out; @@ -314,33 +433,79 @@ event_object_trigger_parse(struct event_command *cmd_= ops, if (!objtrace_cmd || strcmp(objtrace_cmd, "add")) goto out; =20 - arg =3D strsep(&trigger, ":"); - if (!arg) + obj =3D strsep(&trigger, ":"); + if (!obj) goto out; + + tr =3D strchr(obj, ','); + if (!tr) + offset =3D 0; + else { + *tr++ =3D '\0'; + ret =3D kstrtol(tr, 0, &offset); + if (ret) + goto out; + } + + ret =3D -EINVAL; call =3D file->event_call; - field =3D trace_find_event_field(call, arg); + field =3D trace_find_event_field(call, obj); if (!field) goto out; =20 if (field->size !=3D sizeof(void *)) goto out; + def_type_size =3D sizeof(void *); + if (!trigger) { + obj_value_type_size =3D def_type_size; + goto skip_get_type; + } =20 + tmp =3D trigger; + type =3D strsep(&trigger, ":"); + if (!type) + obj_value_type_size =3D def_type_size; + else if (isdigit(type[0])) { + obj_value_type_size =3D def_type_size; + trigger =3D tmp; + } else { + for (i =3D 0; objtrace_fetch_types[i].name; i++) { + if (strcmp(objtrace_fetch_types[i].name, type) =3D=3D 0) { + obj_value_type_size =3D objtrace_fetch_types[i].type_size; + break; + } + } + } + if (!obj_value_type_size) + goto out; +skip_get_type: trigger_ops =3D cmd_ops->get_trigger_ops(cmd, trigger); =20 ret =3D -ENOMEM; + obj_data =3D kzalloc(sizeof(*obj_data), GFP_KERNEL); + if (!obj_data) + goto out; + + obj_data->field =3D field; + obj_data->obj_offset =3D offset; + obj_data->obj_value_type_size =3D obj_value_type_size; + trigger_data =3D kzalloc(sizeof(*trigger_data), GFP_KERNEL); - if (!trigger_data) + if (!trigger_data) { + kfree(obj_data); goto out; + } =20 trigger_data->count =3D -1; trigger_data->ops =3D trigger_ops; trigger_data->cmd_ops =3D cmd_ops; - trigger_data->private_data =3D field; + trigger_data->private_data =3D obj_data; INIT_LIST_HEAD(&trigger_data->list); INIT_LIST_HEAD(&trigger_data->named_list); =20 if (glob[0] =3D=3D '!') { cmd_ops->unreg(glob+1, trigger_data, file); + kfree(obj_data); kfree(trigger_data); ret =3D 0; goto out; @@ -395,6 +560,7 @@ event_object_trigger_parse(struct event_command *cmd_op= s, out_free: if (cmd_ops->set_filter) cmd_ops->set_filter(NULL, trigger_data, NULL); + kfree(obj_data); kfree(trigger_data); goto out; } diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 265428154638..04804f53cadd 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -1557,6 +1557,7 @@ static enum print_line_t trace_object_print(struct tr= ace_iterator *iter, int fla trace_assign_type(field, iter->ent); print_fn_trace(s, field->ip, field->parent_ip, flags); trace_seq_printf(s, " object:0x%lx", field->object); + trace_seq_printf(s, " value:0x%lx", field->value); trace_seq_putc(s, '\n'); =20 return trace_handle_return(s); @@ -1569,9 +1570,8 @@ static enum print_line_t trace_object_raw(struct trac= e_iterator *iter, int flags =20 trace_assign_type(field, iter->ent); =20 - trace_seq_printf(&iter->seq, "%lx %lx\n", - field->ip, - field->parent_ip); + trace_seq_printf(&iter->seq, "%lx %lx %lx %lx\n", field->ip, + field->parent_ip, field->object, field->value); =20 return trace_handle_return(&iter->seq); } --=20 2.25.1 From nobody Tue Jun 30 01:43:53 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5BA8C433EF for ; Sun, 30 Jan 2022 14:45:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355172AbiA3OpN (ORCPT ); Sun, 30 Jan 2022 09:45:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58718 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355109AbiA3Ooz (ORCPT ); Sun, 30 Jan 2022 09:44:55 -0500 Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DCD88C061714 for ; Sun, 30 Jan 2022 06:44:54 -0800 (PST) Received: by mail-pf1-x435.google.com with SMTP id n32so10581866pfv.11 for ; Sun, 30 Jan 2022 06:44:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kryIRj8itYCF1TTsF9+Gx7ZLlBZd5qrSWyChaI+fLhg=; b=MMiKK8jwpOK13mc21HfEe654xK0nw4NOyaOMmklAJMgkLAR51PoZ34JqZExYOghXRF S6p926neaWY6GnSSe1PYLdRbIck7pqIO4fTDLLazAXbwm92LAs3n09TqiZXJi37bvgdk Xy0jYTN4F1qdb6Ameb+IC4l9KtAowmfc9wrsIjHGpKwS2FT3ucMJX+xDIXeTfYaDMzbo OHTbHk6pRxIQN/8JHvjiWwrACwb/jdVmjKzz/4OIhmAzSEWJn/9SU6aOq0TIAjq+OrJV bQIgwYWA4B2G4afkSqDHwFokT4XvLyXjPoZnNONHnR2wh0ZkZynCQmrMampYwPCnTh59 6JUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kryIRj8itYCF1TTsF9+Gx7ZLlBZd5qrSWyChaI+fLhg=; b=ePOGUh9QDPc0ObvkN12yygi9oCJUjlStgtl0URoL/+N2EscFW7rHu8s6r6NdwLOLWg QrsAV8tzMqRpRbSTzcnlkE7iTRzHLQsPqYWFnh5iWHZuH4Lx/+R1lEtRqP1PgYP/z/EH O97jPYe//Os/ST7PTLuqisRkLe8TWIXfdLQejjIFJlRiaKFBpSdndrWEFcIORxnP87ip FOD+fE2HrzPY6gA3WVTvLGqliJ73j/j65XCZUFDNQ2wu4leEUIiqhkZO0zZx+VeMDhDA 6Sbfl6+ioWKaSL4BPrcsC7WN+W7ZpUfEy9UU6WUbVdWlYz0396JBeTgBpVlYwh1FbMV1 9CwQ== X-Gm-Message-State: AOAM530+IBhD0p2t5eHdz8uXlmqQ6zE6EEWJretbt0T/fmZMljjBDWAQ iBDnxKXDkMquR5oMrd3WTxI= X-Google-Smtp-Source: ABdhPJwnxr6UdYT0cRgOgG2ljd+33yKK9/uhOnDOswx789vSX/GlSD2ICkvA1MUMEW0K1iqJctYWFA== X-Received: by 2002:a63:c106:: with SMTP id w6mr13600672pgf.313.1643553894499; Sun, 30 Jan 2022 06:44:54 -0800 (PST) Received: from localhost.localdomain (li567-56.members.linode.com. [192.155.81.56]) by smtp.gmail.com with ESMTPSA id w8sm10502126pfu.128.2022.01.30.06.44.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 30 Jan 2022 06:44:54 -0800 (PST) From: Jeff Xie To: rostedt@goodmis.org Cc: mhiramat@kernel.org, mingo@redhat.com, zanussi@kernel.org, linux-kernel@vger.kernel.org, Jeff Xie Subject: [PATCH v8 3/4] trace/objtrace: Add testcases for objtrace Date: Sun, 30 Jan 2022 22:44:29 +0800 Message-Id: <20220130144430.453221-4-xiehuan09@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220130144430.453221-1-xiehuan09@gmail.com> References: <20220130144430.453221-1-xiehuan09@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add a series of testcases to illustrate correct and incorrect usage of objtrace trigger. Signed-off-by: Jeff Xie --- .../ftrace/test.d/trigger/trigger-objtrace.tc | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/trigger/trigger-o= bjtrace.tc diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-objtrace= .tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-objtrace.tc new file mode 100644 index 000000000000..d71eb157c51f --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-objtrace.tc @@ -0,0 +1,39 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test objtrace-trigger +# requires: kprobe_events "objtrace":README + +fail() { #msg + echo $1 + exit_fail +} + +echo 'p bio_add_page arg1=3D$arg1' > kprobe_events + +FEATURE=3D`grep objtrace events/kprobes/p_bio_add_page_0/trigger` +if [ -z "$FEATURE" ]; then + echo "objtrace trigger is not supported" + exit_unsupported +fi + +echo "Test objtrace trigger" +echo 'objtrace:add:arg1,0x28:u32:1 if comm =3D=3D "cat"' > \ + events/kprobes/p_bio_add_page_0/trigger +if [ -z $? ]; then + fail "objtrace trigger syntax error" +fi + +echo "Test objtrace semantic errors" + +# Being lack of objtrace command +! echo 'objtrace:arg1,0x28:u32:1' > events/kprobes/p_bio_add_page_0/trigger +# Bad parameter name +! echo 'objtrace:add:argx:u32:1' > events/kprobes/p_bio_add_page_0/trigger + +echo "reset objtrace trigger" + +echo '!objtrace:add:arg1,0x28:u32' > \ + events/kprobes/p_bio_add_page_0/trigger +echo '-:p_bio_add_page_0' >> ./kprobe_events + +exit 0 --=20 2.25.1 From nobody Tue Jun 30 01:43:53 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B8ACC433F5 for ; Sun, 30 Jan 2022 14:45:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355152AbiA3OpP (ORCPT ); Sun, 30 Jan 2022 09:45:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355136AbiA3Oo6 (ORCPT ); Sun, 30 Jan 2022 09:44:58 -0500 Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F87CC061749 for ; Sun, 30 Jan 2022 06:44:57 -0800 (PST) Received: by mail-pj1-x1034.google.com with SMTP id o16-20020a17090aac1000b001b62f629953so8242238pjq.3 for ; Sun, 30 Jan 2022 06:44:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WGfvZ4r5TNIGEOPtoPqp/tnebkonKtzqdtDq9GKibjo=; b=DCQ4wOWh7wbjPwKsG2kS/BtCMPVysyqL9LOqvMGLG4V1toRNTEb16VJAT4wqd2pR1x 5hrF/f76JKpDU6AfJwPF9fztVwuonsFV+kNYBGGdhAh08FfUVUEEubME1MU+iZ6HrmPH dgc5C7ashZFBQuSFbJoGpAISr0s/6fb03gb/DLgPAq41JOAnOPYkTcoXsXPwRtjH1smI sjoji3hJt8ZuhXSwCTWaR1kMqu81Eq8Kf/5N2ueH7kfZOCdNdWwfOO3rlxh5t7VIL6Up e5IJxDqzhQR7v9ljussgD5QUXsPYoLonPyGdyDpTaB/nX0R5gr8EGWhQ4/K5oyP9win2 Az1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WGfvZ4r5TNIGEOPtoPqp/tnebkonKtzqdtDq9GKibjo=; b=l20EWyhUCvuP2XlUS6mzZYcT7Kb+7jAT2+LVywXLgmbV/RGWKfG6jMftgruRsOG0YM G2c003PIrfTzrN4vPZdMDtQGS9xoMifiEXju1DHNS5cGHWFyhA8wFXcZZbrBay3Lupa5 QIB6lmG4A2d4ZT3fQbgbVYvgZ157Idy3DI30+sV6QzX9FE6lGAXh0wRfxhY2UKxy1q7/ e5ka4XAbWRcCVedZAF5lzc90kZMtNDixQzksYmuGFp0kbSUIGEUKcQtl00nwnVp+dYHT Zlh+UIUvQzmOAOb/G/R3+J282sg52IeooeYJ20C13FV4x7EtR/UDClXcG624EcL2pe5q dZZw== X-Gm-Message-State: AOAM530I2C+icUwN4b2DtC8Tk20euwHd3/zRjQHHXZeTypJad7G5O58C Jdkz4pCat50A8zagPu7DCnc= X-Google-Smtp-Source: ABdhPJyAO/VWNHNdKZk29Qw2uZmLYX0jLr4thopMMI8bIQ/KbMZXevMquwGYprRYmUUNkwH3Sj/+6w== X-Received: by 2002:a17:90b:380f:: with SMTP id mq15mr20032842pjb.66.1643553897259; Sun, 30 Jan 2022 06:44:57 -0800 (PST) Received: from localhost.localdomain (li567-56.members.linode.com. [192.155.81.56]) by smtp.gmail.com with ESMTPSA id w8sm10502126pfu.128.2022.01.30.06.44.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 30 Jan 2022 06:44:56 -0800 (PST) From: Jeff Xie To: rostedt@goodmis.org Cc: mhiramat@kernel.org, mingo@redhat.com, zanussi@kernel.org, linux-kernel@vger.kernel.org, Jeff Xie Subject: [PATCH v8 4/4] trace/objtrace: Add documentation for objtrace Date: Sun, 30 Jan 2022 22:44:30 +0800 Message-Id: <20220130144430.453221-5-xiehuan09@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220130144430.453221-1-xiehuan09@gmail.com> References: <20220130144430.453221-1-xiehuan09@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Added documentation explaining how to use objtrace trigger to get the value of the object. Signed-off-by: Jeff Xie --- Documentation/trace/events.rst | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/Documentation/trace/events.rst b/Documentation/trace/events.rst index c47f381d0c00..383fff5ca9ba 100644 --- a/Documentation/trace/events.rst +++ b/Documentation/trace/events.rst @@ -546,6 +546,89 @@ The following commands are supported: =20 See Documentation/trace/histogram.rst for details and examples. =20 +- objtrace + + This command provides a way to get the value of any object, The object + can be obtained from the dynamic event(kprobe_event/uprobe_event) or the + static event(tracepoint). + + Usage: + When using the kprobe event, only need to set the objtrace(a new trigger= ), + we can get the value of the object. The object is from the setting of the + kprobe event. + + For example: + For the function bio_add_page(): + + int bio_add_page(struct bio *bio, struct page *page, + unsigned int len, unsigned int offset) + + Firstly, we can set the base of the object, thus the first string "arg1" + stands for the value of the first parameter of this function bio_add_gag= e(), + + # echo 'p bio_add_page arg1=3D$arg1' > ./kprobe_events + + Secondly, we can get the value dynamically based on above object. + + find the offset of the bi_size in struct bio: + $ gdb vmlinux + (gdb) p &(((struct bio *)0)->bi_iter.bi_size) + $1 =3D (unsigned int *) 0x28 + + # echo 'objtrace:add:arg1,0x28:u32:1 if comm =3D=3D "cat"' > ./events/kp= robes/ \ + p_bio_add_page_0/trigger + + # cd /sys/kernel/debug/tracing/ + # echo 'p bio_add_page arg1=3D$arg1' > ./kprobe_events + # echo 'objtrace:add:arg1,0x28:u32:1 if comm =3D=3D "cat"' > ./events/kp= robes/p_bio_add_page_0/trigger + + # du -sh /test.txt + 12.0K /test.txt + + # cat /test.txt > /dev/null + # cat ./trace + # tracer: nop + # + # entries-in-buffer/entries-written: 128/128 #P:4 + # + # _-----=3D> irqs-off/BH-disabled + # / _----=3D> need-resched + # | / _---=3D> hardirq/softirq + # || / _--=3D> preempt-depth + # ||| / _-=3D> migrate-disable + # |||| / delay + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + cat-117 [002] ...1. 1.602243: __bio_try_merge_page = <-bio_add_page object:0xffff88811bee4000 value:0x0 + cat-117 [002] ...1. 1.602244: __bio_add_page <-bio_= add_page object:0xffff88811bee4000 value:0x0 + cat-117 [002] ...2. 1.602244: bio_add_page <-ext4_m= page_readpages object:0xffff88811bee4000 value:0x1000 + cat-117 [002] ...1. 1.602245: __bio_try_merge_page = <-bio_add_page object:0xffff88811bee4000 value:0x1000 + cat-117 [002] ...1. 1.602245: __bio_add_page <-bio_= add_page object:0xffff88811bee4000 value:0x1000 + cat-117 [002] ...2. 1.602245: bio_add_page <-ext4_m= page_readpages object:0xffff88811bee4000 value:0x2000 + cat-117 [002] ...1. 1.602245: __bio_try_merge_page = <-bio_add_page object:0xffff88811bee4000 value:0x2000 + cat-117 [002] ...1. 1.602245: __bio_add_page <-bio_= add_page object:0xffff88811bee4000 value:0x2000 + cat-117 [002] ...1. 1.602245: submit_bio <-ext4_mpa= ge_readpages object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602245: submit_bio_noacct <-e= xt4_mpage_readpages object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602246: __submit_bio <-submit= _bio_noacct object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602246: submit_bio_checks <-_= _submit_bio object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602246: __cond_resched <-subm= it_bio_checks object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602246: should_fail_bio <-sub= mit_bio_checks object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602246: blk_mq_submit_bio <-s= ubmit_bio_noacct object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602246: blk_attempt_plug_merg= e <-blk_mq_submit_bio object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602246: blk_mq_sched_bio_merg= e <-blk_mq_submit_bio object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602247: __rcu_read_lock <-blk= _mq_submit_bio object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602247: __rcu_read_unlock <-b= lk_mq_submit_bio object:0xffff88811bee4000 value:0x3000 + cat-117 [002] ...1. 1.602247: __blk_mq_alloc_reques= ts <-blk_mq_submit_bio object:0xffff88811bee4000 value:0x3000 + -0 [002] d..3. 1.602298: bio_endio <-blk_updat= e_request object:0xffff88811bee4000 value:0x0 + -0 [002] d..3. 1.602298: mpage_end_io <-blk_up= date_request object:0xffff88811bee4000 value:0x0 + -0 [002] d..3. 1.602298: __read_end_io <-blk_u= pdate_request object:0xffff88811bee4000 value:0x0 + -0 [002] d..3. 1.602300: bio_put <-blk_update_= request object:0xffff88811bee4000 value:0x0 + -0 [002] d..3. 1.602300: bio_free <-blk_update= _request object:0xffff88811bee4000 value:0x0 + -0 [002] d..3. 1.602300: mempool_free <-blk_up= date_request object:0xffff88811bee4000 value:0x0 + -0 [002] d..3. 1.602300: mempool_free_slab <-b= lk_update_request object:0xffff88811bee4000 value:0x0 + -0 [002] d..3. 1.602300: kmem_cache_free <-blk= _update_request object:0xffff88811bee4000 value:0x0 + ... + 7. In-kernel trace event API =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D =20 --=20 2.25.1