diff mbox series

[v2,2/4] libtracefs: Implement tracefs_kprobe_raw()

Message ID 20210630154729.129873-3-rostedt@goodmis.org (mailing list archive)
State Superseded
Headers show
Series libtracefs: Facilitate adding and removing kprobes | expand

Commit Message

Steven Rostedt June 30, 2021, 3:47 p.m. UTC
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

Comments

Yordan Karadzhov June 30, 2021, 7:46 p.m. UTC | #1
On 30.06.21 г. 18:47, Steven Rostedt wrote:
> 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 a21d2d2f22a6..bc504bcb0188 100644
> --- a/include/tracefs.h
> +++ b/include/tracefs.h
> @@ -214,4 +214,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);

I wonder what will be the way to register a "return value" ("r:") 
kprobe. Do you consider having a separate API for them?

Thanks!
Yordan

> +
> +	if (ret < 0)
> +		return -1;
> +
> +	ret = tracefs_instance_file_append(NULL, KPROBE_EVENTS, str);
> +	free(str);
> +
> +	return ret < 0 ? ret : 0;
> +}
>
Steven Rostedt June 30, 2021, 7:53 p.m. UTC | #2
On Wed, 30 Jun 2021 22:46:19 +0300
"Yordan Karadzhov (VMware)" <y.karadz@gmail.com> wrote:

> > +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);  
> 
> I wonder what will be the way to register a "return value" ("r:") 
> kprobe. Do you consider having a separate API for them?

Yes, I was thinking about having a "tracefs_kretprobe_raw()" as well.

I also thought of adding a flag in the parameter, but thought that a
separate function would be better instead.

I wanted to play with this interface before creating the retprobe one.
If you are happy with the current design, I can add that too.

-- Steve
Yordan Karadzhov June 30, 2021, 8:05 p.m. UTC | #3
On 30.06.21 г. 22:53, Steven Rostedt wrote:
> On Wed, 30 Jun 2021 22:46:19 +0300
> "Yordan Karadzhov (VMware)" <y.karadz@gmail.com> wrote:
> 
>>> +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);
>>
>> I wonder what will be the way to register a "return value" ("r:")
>> kprobe. Do you consider having a separate API for them?
> 
> Yes, I was thinking about having a "tracefs_kretprobe_raw()" as well.
> 
> I also thought of adding a flag in the parameter, but thought that a
> separate function would be better instead.
> 
> I wanted to play with this interface before creating the retprobe one.
> If you are happy with the current design, I can add that too.
> 

The design looks good to me.

Thanks!
Y.

> -- Steve
>
diff mbox series

Patch

diff --git a/include/tracefs.h b/include/tracefs.h
index a21d2d2f22a6..bc504bcb0188 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -214,4 +214,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;
+}