linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] libtracefs: Facilitate adding and removing kprobes
@ 2021-06-29 20:53 Steven Rostedt
  2021-06-29 20:53 ` [PATCH 1/3] libtracefs: Implement tracefs_kprobe_raw() Steven Rostedt
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Steven Rostedt @ 2021-06-29 20:53 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt

Add a tracefs_kprobe_raw() to facilitate adding kprobe events. It's
denoted as "raw" because it still requires knowing the complex format of
a kprobe, but at least it helps with other formats:

 p:[[system/]event] addr fmt

The user only needs to know the "fmt" part above, and not worry about
what file to open, or how to open it.

Also add a tracefs_kprobe_clear() to clear all kprobes and a
tracefs_kprobe_clear_probe() to clear an individual kprobe. Both have a
"force" parameter, that if set, will then try to disable the kprobe in
all instances (including the top) and then remove the kprobe(s).

(Man pages coming after this).

Steven Rostedt (VMware) (3):
  libtracefs: Implement tracefs_kprobe_raw()
  libtracefs: Implement tracefs_kprobe_clear() to remove all kprobes
  libtracefs: Implement tracefs_kprobe_clear_probe()

 include/tracefs.h     |   5 +
 src/Makefile          |   1 +
 src/tracefs-kprobes.c | 242 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+)
 create mode 100644 src/tracefs-kprobes.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] libtracefs: Implement tracefs_kprobe_raw()
  2021-06-29 20:53 [PATCH 0/3] libtracefs: Facilitate adding and removing kprobes Steven Rostedt
@ 2021-06-29 20:53 ` Steven Rostedt
  2021-06-29 20:53 ` [PATCH 2/3] libtracefs: Implement tracefs_kprobe_clear() to remove all kprobes Steven Rostedt
  2021-06-29 20:53 ` [PATCH 3/3] libtracefs: Implement tracefs_kprobe_clear_probe() Steven Rostedt
  2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2021-06-29 20:53 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add a function to facilitate creating a kprobe event. It has the "raw" in
its name because it still requires knowing the format of the kprobe. But
does handle the kprobe naming better and writing to the kprobe_event file.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 include/tracefs.h     |  4 +++
 src/Makefile          |  1 +
 src/tracefs-kprobes.c | 70 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)
 create mode 100644 src/tracefs-kprobes.c

diff --git a/include/tracefs.h b/include/tracefs.h
index 048474240958..47b05b3f55e7 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -209,4 +209,8 @@ int tracefs_tracer_clear(struct tracefs_instance *instance);
 ssize_t tracefs_trace_pipe_stream(int fd, struct tracefs_instance *instance, int flags);
 ssize_t tracefs_trace_pipe_print(struct tracefs_instance *instance, int flags);
 void tracefs_trace_pipe_stop(struct tracefs_instance *instance);
+
+int tracefs_kprobe_raw(const char *system, const char *event,
+		       const char *addr, const char *format);
+
 #endif /* _TRACE_FS_H */
diff --git a/src/Makefile b/src/Makefile
index b4cff07efc50..0697a047f4bc 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -8,6 +8,7 @@ OBJS += tracefs-instance.o
 OBJS += tracefs-events.o
 OBJS += tracefs-tools.o
 OBJS += tracefs-marker.o
+OBJS += tracefs-kprobes.o
 
 OBJS := $(OBJS:%.o=$(bdir)/%.o)
 DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d)
diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c
new file mode 100644
index 000000000000..e4b28cff9f08
--- /dev/null
+++ b/src/tracefs-kprobes.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * Copyright (C) 2021 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
+ *
+ * Updates:
+ * Copyright (C) 2021, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com>
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include "tracefs.h"
+#include "tracefs-local.h"
+
+#define KPROBE_EVENTS "kprobe_events"
+
+/**
+ * tracefs_kprobe_raw - Create a kprobe using raw format
+ * @system: The system name (NULL for the default kprobes)
+ * @event: The event to create (NULL to use @addr for the event)
+ * @addr: The function and offset (or address) to insert the probe
+ * @format: The raw format string to define the probe.
+ *
+ * Create a kprobe that will be in the @system group (or kprobes if
+ * @system is NULL). Have the name of @event (or @addr if @event is
+ * NULL). Will be inserted to @addr (function name, with or without
+ * offset, or a address). And the @format will define the raw format
+ * of the kprobe. See the Linux documentation file under:
+ * Documentation/trace/kprobetrace.rst
+ *
+ * Return 0 on success, or -1 on error.
+ *   If the syntex of @format was incorrect, running
+ *   tracefs_error_last(NULL) may show what went wrong.
+ *
+ * errno will be set to EBADMSG if addr or format is NULL.
+ */
+int tracefs_kprobe_raw(const char *system, const char *event,
+		       const char *addr, const char *format)
+{
+	char *str;
+	int ret;
+
+	errno = EBADMSG;
+	if (!addr || !format)
+		return -1;
+
+	if (!event)
+		event = addr;
+
+	if (system)
+		ret = asprintf(&str, "p:%s/%s %s %s\n",
+			       system, event, addr, format);
+	else
+		ret = asprintf(&str, "p:%s %s %s\n",
+			       event, addr, format);
+
+	if (ret < 0)
+		return -1;
+
+	ret = tracefs_instance_file_append(NULL, KPROBE_EVENTS, str);
+	free(str);
+
+	return ret < 0 ? ret : 0;
+}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] libtracefs: Implement tracefs_kprobe_clear() to remove all kprobes
  2021-06-29 20:53 [PATCH 0/3] libtracefs: Facilitate adding and removing kprobes Steven Rostedt
  2021-06-29 20:53 ` [PATCH 1/3] libtracefs: Implement tracefs_kprobe_raw() Steven Rostedt
@ 2021-06-29 20:53 ` Steven Rostedt
  2021-06-29 20:53 ` [PATCH 3/3] libtracefs: Implement tracefs_kprobe_clear_probe() Steven Rostedt
  2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2021-06-29 20:53 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

A call to tracefs_kprobe_clear() will attempt to disable all kprobes. If
any kprobe is set, and the @force parameter is set, it will fail with
errno set to EBUSY. If @force is set, then it will attempt to disable all
the defined kprobe events and then clear it.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 include/tracefs.h     |   2 +-
 src/tracefs-kprobes.c | 136 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/include/tracefs.h b/include/tracefs.h
index 47b05b3f55e7..54c461e85a2b 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -212,5 +212,5 @@ void tracefs_trace_pipe_stop(struct tracefs_instance *instance);
 
 int tracefs_kprobe_raw(const char *system, const char *event,
 		       const char *addr, const char *format);
-
+int tracefs_kprobe_clear(bool force);
 #endif /* _TRACE_FS_H */
diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c
index e4b28cff9f08..48a4f090f041 100644
--- a/src/tracefs-kprobes.c
+++ b/src/tracefs-kprobes.c
@@ -68,3 +68,139 @@ int tracefs_kprobe_raw(const char *system, const char *event,
 
 	return ret < 0 ? ret : 0;
 }
+
+struct instance_list {
+	struct instance_list	*next;
+	struct tracefs_instance	*instance;
+};
+
+static int disable_events(const char *system, const char *event,
+			  struct instance_list *list)
+{
+	int ret;
+
+	ret = tracefs_event_disable(NULL, system, event);
+	if (ret < 0)
+		return ret;
+
+	while (list) {
+		ret = tracefs_event_disable(list->instance, system, event);
+		if (ret < 0)
+			return ret;
+		list = list->next;
+	}
+
+	return 0;
+}
+
+static int build_instances(const char *name, void *data)
+{
+	struct instance_list ***ptr_next = (struct instance_list ***)data;
+	struct instance_list **next = *ptr_next;
+	struct tracefs_instance *instance;
+	struct instance_list *list;
+
+	instance = tracefs_instance_alloc(NULL, name);
+	if (!instance)
+		return -1;
+
+	list = malloc(sizeof(*list));
+	if (!list) {
+		tracefs_instance_free(instance);
+		return -1;
+	}
+
+	list->instance = instance;
+	list->next = *next;
+	*next = list;
+	*ptr_next = &list->next;
+	return 0;
+}
+
+static void free_instance_list(struct instance_list *list)
+{
+	struct instance_list *n;
+
+	while (list) {
+		n = list->next;
+		tracefs_instance_free(list->instance);
+		free(list);
+		list = n;
+	}
+}
+
+/**
+ * tracefs_kprobe_clear - clear kprobe events
+ * @force: Will attempt to disable all kprobe events and clear them
+ *
+ * Will remove all defined kprobe events. If any of them are enabled,
+ * and @force is not set, then it will error with -1 and errno to be
+ * EBUSY. If @force is set, then it will attempt to disable all the kprobe
+ * events in all instances, and try again.
+ *
+ * Returns zero on success, -1 otherwise.
+ */
+int tracefs_kprobe_clear(bool force)
+{
+	struct instance_list *list = NULL;
+	struct instance_list **plist = &list;
+	char *content;
+	char *saveptr;
+	char *system;
+	char *event;
+	char *p;
+	int ret;
+
+	ret = tracefs_instance_file_clear(NULL, KPROBE_EVENTS);
+	if (!ret)
+		return 0;
+
+	if (!force)
+		return -1;
+
+	/* Attempt to disable all kprobe events */
+	content = tracefs_instance_file_read(NULL, KPROBE_EVENTS, NULL);
+	if (!content)
+		return -1;
+
+	ret = tracefs_instances_walk(build_instances, &plist);
+	if (ret < 0)
+		goto out;
+
+	ret = -1;
+	p = strtok_r(content, ":", &saveptr);
+	if (!p)
+		goto out;
+
+	for (;;) {
+		p = strtok_r(NULL, "/", &saveptr);
+		if (!p)
+			goto out;
+
+		system = p;
+
+		p = strtok_r(NULL," ", &saveptr);
+		if (!p)
+			goto out;
+		event = p;
+
+		if (disable_events(system, event, list) < 0)
+			goto out;
+
+		ret = tracefs_instance_file_clear(NULL, KPROBE_EVENTS);
+		/* On success stop the loop */
+		if (!ret)
+			goto out;
+
+		ret = -1;
+		p = strtok_r(NULL, "\n", &saveptr);
+		if (!p)
+			goto out;
+
+		p = strtok_r(NULL, ":", &saveptr);
+	}
+ out:
+	free(content);
+	free_instance_list(list);
+	return ret;
+}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] libtracefs: Implement tracefs_kprobe_clear_probe()
  2021-06-29 20:53 [PATCH 0/3] libtracefs: Facilitate adding and removing kprobes Steven Rostedt
  2021-06-29 20:53 ` [PATCH 1/3] libtracefs: Implement tracefs_kprobe_raw() Steven Rostedt
  2021-06-29 20:53 ` [PATCH 2/3] libtracefs: Implement tracefs_kprobe_clear() to remove all kprobes Steven Rostedt
@ 2021-06-29 20:53 ` Steven Rostedt
  2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2021-06-29 20:53 UTC (permalink / raw)
  To: linux-trace-devel; +Cc: Steven Rostedt (VMware)

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

Add the function tracefs_kprobe_clear_probe() that will remove a single
kprobe. If the @force parameter is set, it will disable that probe in all
instances (including the top level instance) before removing it.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 include/tracefs.h     |  1 +
 src/tracefs-kprobes.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/include/tracefs.h b/include/tracefs.h
index 54c461e85a2b..447821e65ce2 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -213,4 +213,5 @@ void tracefs_trace_pipe_stop(struct tracefs_instance *instance);
 int tracefs_kprobe_raw(const char *system, const char *event,
 		       const char *addr, const char *format);
 int tracefs_kprobe_clear(bool force);
+int tracefs_kprobe_clear_probe(const char *system, const char *event, bool force);
 #endif /* _TRACE_FS_H */
diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c
index 48a4f090f041..27d4c2181404 100644
--- a/src/tracefs-kprobes.c
+++ b/src/tracefs-kprobes.c
@@ -204,3 +204,39 @@ int tracefs_kprobe_clear(bool force)
 	free_instance_list(list);
 	return ret;
 }
+
+int tracefs_kprobe_clear_probe(const char *system, const char *event, bool force)
+{
+	struct instance_list *list = NULL;
+	struct instance_list **plist = &list;
+	char *content;
+	int ret;
+
+	if (!system)
+		system = "kprobes";
+
+	ret = asprintf(&content, "-:%s/%s", system, event);
+	if (ret < 0)
+		return -1;
+
+	/*
+	 * Since we know we are disabling a specific event, try
+	 * to disable it first before clearing it.
+	 */
+	if (force) {
+		ret = tracefs_instances_walk(build_instances, &plist);
+		if (ret < 0)
+			goto out;
+
+		ret = disable_events(system, event, list);
+		if (ret < 0)
+			goto out;
+	}
+
+	ret = tracefs_instance_file_append(NULL, KPROBE_EVENTS, content);
+ out:
+	free(content);
+	free_instance_list(list);
+
+	return ret < 0 ? -1 : 0;
+}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-06-29 20:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-29 20:53 [PATCH 0/3] libtracefs: Facilitate adding and removing kprobes Steven Rostedt
2021-06-29 20:53 ` [PATCH 1/3] libtracefs: Implement tracefs_kprobe_raw() Steven Rostedt
2021-06-29 20:53 ` [PATCH 2/3] libtracefs: Implement tracefs_kprobe_clear() to remove all kprobes Steven Rostedt
2021-06-29 20:53 ` [PATCH 3/3] libtracefs: Implement tracefs_kprobe_clear_probe() Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).