Linux-rt-users archive on lore.kernel.org
 help / color / Atom feed
From: Tom Zanussi <zanussi@kernel.org>
To: rostedt@goodmis.org
Cc: artem.bityutskiy@linux.intel.com, mhiramat@kernel.org,
	linux-kernel@vger.kernel.org, linux-rt-users@vger.kernel.org
Subject: [PATCH v2 10/12] tracing: Add kprobe event command generation functions
Date: Fri, 10 Jan 2020 14:35:16 -0600
Message-ID: <5f052546541d6cc5ad00e28aca6376c221db5c7e.1578688120.git.zanussi@kernel.org> (raw)
In-Reply-To: <cover.1578688120.git.zanussi@kernel.org>
In-Reply-To: <cover.1578688120.git.zanussi@kernel.org>

Add functions used to generate kprobe event commands, built on top of
the dynevent_cmd interface.

gen_kprobe_cmd() is used to create a kprobe event command using a
variable arg list.  add_probe_fields() can be used to add single
fields one by one or as a group.  Once all desired fields are added,
create_dynevent() is used to actually execute the command and create
the event.

gen_kprobe_cmd() can be used to create kretprobe commands as well.

Signed-off-by: Tom Zanussi <zanussi@kernel.org>
---
 include/linux/trace_events.h |  18 +++++
 kernel/trace/trace_kprobe.c  | 161 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 177 insertions(+), 2 deletions(-)

diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index c25b18db84eb..7ae9ad182b0e 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -464,6 +464,24 @@ extern int add_synth_val(const char *field_name, u64 val,
 			 struct synth_gen_state *gen_state);
 extern int trace_synth_event_end(struct synth_gen_state *gen_state);
 
+extern void kprobe_dynevent_cmd_init(struct dynevent_cmd *cmd,
+				     char *buf, int maxlen);
+
+#define gen_kprobe_cmd(cmd, name, loc, ...)		\
+	__gen_kprobe_cmd(cmd, name, loc, false, ## __VA_ARGS__, NULL)
+
+#define gen_kretprobe_cmd(cmd, name, loc, ...)		\
+	__gen_kprobe_cmd(cmd, name, loc, true, ## __VA_ARGS__, NULL)
+
+extern int __gen_kprobe_cmd(struct dynevent_cmd *cmd, const char *name,
+			    const char *loc, bool kretprobe, ...);
+
+#define add_probe_fields(cmd, ...)	\
+	__add_probe_fields(cmd, ## __VA_ARGS__, NULL)
+
+extern int __add_probe_fields(struct dynevent_cmd *cmd, ...);
+extern int delete_kprobe_event(const char *name);
+
 /*
  * Event file flags:
  *  ENABLED	  - The event is enabled
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 25dac3745afb..f911b3d74b46 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -902,11 +902,168 @@ static int create_or_delete_trace_kprobe(int argc, char **argv)
 	return ret == -ECANCELED ? -EINVAL : ret;
 }
 
-int trace_kprobe_run_command(const char *command)
+static int trace_kprobe_run_command(struct dynevent_cmd *cmd)
 {
-	return trace_run_command(command, create_or_delete_trace_kprobe);
+	return trace_run_command(cmd->buf, create_or_delete_trace_kprobe);
 }
 
+/**
+ * kprobe_dynevent_cmd_init - Initialize a kprobe event command object
+ * @cmd: A pointer to the dynevent_cmd struct representing the new event
+ * @buf: A pointer to the buffer used to build the command
+ * @maxlen: The length of the buffer passed in @buf
+ *
+ * Initialize a synthetic event command object.  Use this before
+ * calling any of the other dyenvent_cmd functions.
+ */
+void kprobe_dynevent_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen)
+{
+	dynevent_cmd_init(cmd, buf, maxlen, DYNEVENT_TYPE_KPROBE,
+			  trace_kprobe_run_command);
+}
+EXPORT_SYMBOL_GPL(kprobe_dynevent_cmd_init);
+
+/**
+ * __gen_kprobe_cmd - Generate a synthetic event command from arg list
+ * @cmd: A pointer to the dynevent_cmd struct representing the new event
+ * @name: The name of the kprobe event
+ * @loc: The location of the kprobe event
+ * @kretprobe: Is this a return probe?
+ * @args: Variable number of arg (pairs), one pair for each field
+ *
+ * NOTE: Users normally won't want to call this function directly, but
+ * rather use the gen_kprobe_cmd() wrapper, which automatically adds a
+ * NULL to the end of the arg list.  If this function is used
+ * directly, make suer he last arg in the variable arg list is NULL.
+ *
+ * Generate a kprobe event command to be executed by
+ * create_dynevent().  This function can be used to generate the
+ * complete command or only the first part of it; in the latter case,
+ * add_probe_fields() can be used to add more fields following this.
+ *
+ * Return: 0 if successful, error otherwise.
+ */
+int __gen_kprobe_cmd(struct dynevent_cmd *cmd, const char *name,
+		     const char *loc, bool kretprobe, ...)
+{
+	char buf[MAX_EVENT_NAME_LEN];
+	struct dynevent_arg arg;
+	va_list args;
+	int ret;
+
+	if (cmd->type != DYNEVENT_TYPE_KPROBE)
+		return -EINVAL;
+
+	if (kretprobe)
+		snprintf(buf, MAX_EVENT_NAME_LEN, "r:%s", name);
+	else
+		snprintf(buf, MAX_EVENT_NAME_LEN, "p:%s", name);
+
+	dynevent_arg_init(&arg, NULL, 0);
+	arg.str = buf;
+	ret = add_dynevent_arg(cmd, &arg);
+	if (ret)
+		return ret;
+
+	dynevent_arg_init(&arg, NULL, 0);
+	arg.str = loc;
+	ret = add_dynevent_arg(cmd, &arg);
+	if (ret)
+		return ret;
+
+	va_start(args, kretprobe);
+	for (;;) {
+		const char *field;
+
+		field = va_arg(args, const char *);
+		if (!field)
+			break;
+
+		if (++cmd->n_fields > MAX_TRACE_ARGS) {
+			ret = -EINVAL;
+			break;
+		}
+
+		dynevent_arg_init(&arg, NULL, 0);
+		arg.str = field;
+		ret = add_dynevent_arg(cmd, &arg);
+		if (ret)
+			break;
+	}
+	va_end(args);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__gen_kprobe_cmd);
+
+/**
+ * __add_probe_fields - Add probe fields to a kprobe command from arg list
+ * @cmd: A pointer to the dynevent_cmd struct representing the new event
+ * @args: Variable number of arg (pairs), one pair for each field
+ *
+ * NOTE: Users normally won't want to call this function directly, but
+ * rather use the add_probe_fields() wrapper, which automatically adds a
+ * NULL to the end of the arg list.  If this function is used
+ * directly, make suer he last arg in the variable arg list is NULL.
+ *
+ * Add probe fields to an existing kprobe command using a variable
+ * list of args.  Fields are added in the same order they're listed.
+ *
+ * Return: 0 if successful, error otherwise.
+ */
+int __add_probe_fields(struct dynevent_cmd *cmd, ...)
+{
+	struct dynevent_arg arg;
+	va_list args;
+	int ret;
+
+	if (cmd->type != DYNEVENT_TYPE_KPROBE)
+		return -EINVAL;
+
+	va_start(args, cmd);
+	for (;;) {
+		const char *field;
+
+		field = va_arg(args, const char *);
+		if (!field)
+			break;
+
+		if (++cmd->n_fields > MAX_TRACE_ARGS) {
+			ret = -EINVAL;
+			break;
+		}
+
+		dynevent_arg_init(&arg, NULL, 0);
+		arg.str = field;
+		ret = add_dynevent_arg(cmd, &arg);
+		if (ret)
+			break;
+	}
+	va_end(args);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__add_probe_fields);
+
+/**
+ * delete_kprobe_event - Delete a kprobe event
+ * @name: The name of the kprobe event to delete
+ *
+ * Delete a kprobe event with the give @name from kernel code rather
+ * than directly from the command line.
+ *
+ * Return: 0 if successful, error otherwise.
+ */
+int delete_kprobe_event(const char *name)
+{
+	char buf[MAX_EVENT_NAME_LEN];
+
+	snprintf(buf, MAX_EVENT_NAME_LEN, "-:%s", name);
+
+	return trace_run_command(buf, create_or_delete_trace_kprobe);
+}
+EXPORT_SYMBOL_GPL(delete_kprobe_event);
+
 static int trace_kprobe_release(struct dyn_event *ev)
 {
 	struct trace_kprobe *tk = to_trace_kprobe(ev);
-- 
2.14.1


  parent reply index

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-10 20:35 [PATCH v2 00/12] tracing: Add support for in-kernel dynamic event API Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 01/12] tracing: Add trace_array_find() to find instance trace arrays Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 02/12] tracing: Add get/put_event_file() Tom Zanussi
2020-01-13 13:15   ` Masami Hiramatsu
2020-01-13 15:15     ` Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 03/12] tracing: Add delete_synth_event() Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 04/12] tracing: Add dynamic event command creation interface Tom Zanussi
2020-01-14 12:14   ` Masami Hiramatsu
2020-01-14 15:19     ` Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 05/12] tracing: Add synth_event_run_command() Tom Zanussi
2020-01-21 16:53   ` Steven Rostedt
2020-01-10 20:35 ` [PATCH v2 06/12] tracing: Add synthetic event command generation functions Tom Zanussi
2020-01-21 16:57   ` Steven Rostedt
2020-01-21 19:20     ` Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 07/12] tracing: Add trace_synth_event() and related functions Tom Zanussi
2020-01-21 17:03   ` Steven Rostedt
2020-01-21 19:22     ` Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 08/12] tracing: Add synth event generation test module Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 09/12] tracing: Add trace_kprobe_run_command() Tom Zanussi
2020-01-10 20:35 ` Tom Zanussi [this message]
2020-01-10 20:35 ` [PATCH v2 11/12] tracing: Add kprobe event command generation test module Tom Zanussi
2020-01-10 20:35 ` [PATCH v2 12/12] tracing: Documentation for in-kernel synthetic event API Tom Zanussi

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5f052546541d6cc5ad00e28aca6376c221db5c7e.1578688120.git.zanussi@kernel.org \
    --to=zanussi@kernel.org \
    --cc=artem.bityutskiy@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-rt-users archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-rt-users/0 linux-rt-users/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-rt-users linux-rt-users/ https://lore.kernel.org/linux-rt-users \
		linux-rt-users@vger.kernel.org
	public-inbox-index linux-rt-users

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-rt-users


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git