diff mbox series

[v3,05/11] libtracefs: Change tracefs_kprobe_info API

Message ID 20211103154417.246999-6-tz.stoyanov@gmail.com (mailing list archive)
State Superseded
Headers show
Series libtracefs dynamic events support | expand

Commit Message

Tzvetomir Stoyanov (VMware) Nov. 3, 2021, 3:44 p.m. UTC
In order to make kprobe APIs consistent with the other libtracefs APIs,
the tracefs_kprobe_info() API is reimplemented and changed to work with
the library dynamic event structure.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 include/tracefs.h     |  11 +--
 src/tracefs-kprobes.c | 172 ++++++++++++++++--------------------------
 2 files changed, 66 insertions(+), 117 deletions(-)

Comments

Steven Rostedt Nov. 4, 2021, 3:06 a.m. UTC | #1
On Wed,  3 Nov 2021 17:44:11 +0200
"Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote:

> -enum tracefs_kprobe_type tracefs_kprobe_info(const char *group, const char *event,
> -					     char **type, char **addr, char **format)
> +enum tracefs_dynevent_type tracefs_kprobe_info(struct tracefs_dynevent *kprobe,
> +					       char **system, char **event,
> +					       char **prefix, char **addr, char **format)
>  {
> -	enum tracefs_kprobe_type rtype = TRACEFS_ALL_KPROBES;
> -	char *saveptr;
> -	char *content;
> -	char *system;
> -	char *probe;
> -	char *ktype;
> -	char *kaddr;
> -	char *kfmt;
> -	int ret;
> -
> -	if (!group)
> -		group = KPROBE_DEFAULT_GROUP;
> -
> -	if (type)
> -		*type = NULL;
> +	if (system)
> +		*system = NULL;
> +	if (event)
> +		*event = NULL;
> +	if (prefix)
> +		*prefix = NULL;
>  	if (addr)
>  		*addr = NULL;
>  	if (format)
>  		*format = NULL;
>  
> -	content = tracefs_instance_file_read(NULL, KPROBE_EVENTS, NULL);
> -	if (!content)
> -		return rtype;
> -
> -	ret = parse_kprobe(content, &saveptr, &ktype, &system, &probe,
> -			   &kaddr, &kfmt);
> -
> -	while (!ret) {
> -
> -		if (!strcmp(system, group) && !strcmp(probe, event)) {
> -			if (type)
> -				*type = strdup(ktype);
> -			if (addr)
> -				*addr = strdup(kaddr);
> -			if (format)
> -				*format = strdup(kfmt);
> +	if (!kprobe)
> +		return TRACEFS_DYNEVENT_MAX;
>  
> -			switch (*ktype) {
> -			case 'p': rtype = TRACEFS_KPROBE; break;
> -			case 'r': rtype = TRACEFS_KRETPROBE; break;
> -			}
> -			break;
> +	if (system) {
> +		if (kprobe->system) {
> +			*system = strdup(kprobe->system);
> +			if (!(*system))
> +				goto error;
>  		}
> -		ret = parse_kprobe(NULL, &saveptr, &ktype, &system, &probe,
> -				   &kaddr, &kfmt);
>  	}
> -	free(content);
> -	return rtype;
> +	if (event) {
> +		*event = strdup(kprobe->event);
> +		if (!(*event))
> +			goto error;
> +	}
> +	if (prefix) {
> +		*prefix = strdup(kprobe->prefix);
> +		if (!(*prefix))
> +			goto error;
> +	}
> +	if (addr && kprobe->address) {
> +		*addr = strdup(kprobe->address);
> +		if (!(*addr))
> +			goto error;
> +	}
> +	if (format && kprobe->format) {
> +		*format = strdup(kprobe->format);
> +		if (!(*format))
> +			goto error;
> +	}
> +
> +	return kprobe->type;
> +
> +error:
> +	if (system)
> +		free(*system);
> +	if (event)
> +		free(*event);
> +	if (prefix)
> +		free(*prefix);
> +	if (addr)
> +		free(*addr);
> +	if (format)
> +		free(*format);
> +	return TRACEFS_DYNEVENT_MAX;
>  }



The above can be shorten to just:

enum tracefs_dynevent_type tracefs_kprobe_info(struct tracefs_dynevent *kprobe,
					       char **system, char **event,
					       char **prefix, char **addr, char **format)
{
	char **lvalues[] = { system, event, prefix, addr, format };
	char **rvalues[] = { &kprobe->system, &kprobe->event, &kprobe->prefix,
		&kprobe->address, &kprobe->format };
	int i;

	if (!kprobe)
		return TRACEFS_DYNEVENT_MAX;

	for (i = 0; i < 5; i++) {
		if (lvalues[i]) {
			if (*rvalues[i]) {
				*lvalues[i] = strdup(*rvalues[i]);
				if (!*lvalues[i])
					goto error;
			} else {
				*lvalues[i] = NULL;
			}
		}
	}

	return kprobe->type;

error:
	for (i--; i >= 0; i--) {
		if (lvalues[i])
			free(*lvalues[i]);
	}

	return TRACEFS_DYNEVENT_MAX;
}


 ;-)

-- Steve
diff mbox series

Patch

diff --git a/include/tracefs.h b/include/tracefs.h
index 6bf45c3..8ff9d12 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -261,12 +261,6 @@  void tracefs_dynevent_list_free(struct tracefs_dynevent **events);
 struct tracefs_dynevent **
 tracefs_dynevent_get_all(unsigned long type_mask, const char *system);
 
-enum tracefs_kprobe_type {
-	TRACEFS_ALL_KPROBES,
-	TRACEFS_KPROBE,
-	TRACEFS_KRETPROBE,
-};
-
 struct tracefs_dynevent *
 tracefs_kprobe_alloc(const char *system, const char *event, const char *addr, const char *format);
 struct tracefs_dynevent *
@@ -276,8 +270,9 @@  int tracefs_kprobe_raw(const char *system, const char *event,
 		       const char *addr, const char *format);
 int tracefs_kretprobe_raw(const char *system, const char *event,
 			  const char *addr, const char *format);
-enum tracefs_kprobe_type tracefs_kprobe_info(const char *group, const char *event,
-					     char **type, char **addr, char **format);
+enum tracefs_dynevent_type tracefs_kprobe_info(struct tracefs_dynevent *kprobe,
+					       char **system, char **event,
+					       char **prefix, char **addr, char **format);
 
 enum tracefs_hist_key_type {
 	TRACEFS_HIST_KEY_NORMAL = 0,
diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c
index 72a4a35..eb71df3 100644
--- a/src/tracefs-kprobes.c
+++ b/src/tracefs-kprobes.c
@@ -210,125 +210,79 @@  int tracefs_kretprobe_raw(const char *system, const char *event,
 	return insert_kprobe("r", system, event, addr, format);
 }
 
-/*
- * Helper function to parse kprobes.
- * @content: The content of kprobe_events on the first iteration.
- *           NULL on next iterations.
- * @saveptr: Same as saveptr for strtok_r
- * @type: Where to store the type (before ':')
- * @system: Store the system of the kprobe (NULL to have event contain
- *          both system and event, as in "kprobes/myprobe").
- * @event: Where to store the event.
- * @addr: Where to store the addr (may be NULL to ignore)
- * @format: Where to store the format (may be NULL to ignore)
- */
-static int parse_kprobe(char *content, char **saveptr,
-			char **type, char **system, char **event,
-			char **addr, char **format)
-{
-	char *p;
-
-	p = strtok_r(content, ":", saveptr);
-	if (!p)
-		return 1; /* eof */
-	*type = p;
-
-	if (system) {
-		p = strtok_r(NULL, "/", saveptr);
-		if (!p)
-			return -1;
-		*system = p;
-	}
-
-	p = strtok_r(NULL, " ", saveptr);
-	if (!p)
-		return -1;
-	*event = p;
-
-	if (addr || format) {
-		p = strtok_r(NULL, " ", saveptr);
-		if (!p)
-			return -1;
-		if (addr)
-			*addr = p;
-	}
-
-	p = strtok_r(NULL, "\n", saveptr);
-	if (!p)
-		return -1;
-	if (format)
-		*format = p;
-
-	return 0;
-}
-
 /**
- * tracefs_kprobe_info - return the type of kprobe specified.
- * @group: The group the kprobe is in (NULL for the default "kprobes")
- * @event: The name of the kprobe to find.
- * @type: String to return kprobe type (before ':') NULL to ignore.
- * @addr: String to return address kprobe is attached to. NULL to ignore.
- * @format: String to return kprobe format. NULL to ignore.
- *
- * If @type, @addr, or @format is non NULL, then the returned string
- * must be freed with free(). They will also be set to NULL, and
- * even on error, they may contain strings to be freed. If they are
- * not NULL, then they still need to be freed.
+ * tracefs_kprobe_info - return details of a kprobe
+ * @kprobe: A kprobe context, describing given kprobe.
+ * @group: return, group in which the kprobe is configured
+ * @event: return, name of the kprobe event
+ * @prefix: return, prefix string of the kprobe
+ *	    for kretprobes, the maxactive count is encoded in the prefix
+ * @addr: return, the function and offset (or address) of the kprobe
+ * @format: return, the format string of the kprobe
  *
- * Returns TRACEFS_ALL_KPROBES if an error occurs or the kprobe is not found,
- *            or the probe is of an unknown type.
- * TRACEFS_KPROBE if the type of kprobe found is a normal kprobe.
- * TRACEFS_KRETPROBE if the type of kprobe found is a kretprobe.
+ * Returns the type of the kprobe, or TRACEFS_DYNEVENT_MAX in case of an error.
+ * Any of the @group, @event, @prefix, @addr and @format parameters are optional.
+ * If a valid pointer is passed, in case of success - a string is allocated and returned.
+ * These strings must be freed with free().
  */
-enum tracefs_kprobe_type tracefs_kprobe_info(const char *group, const char *event,
-					     char **type, char **addr, char **format)
+enum tracefs_dynevent_type tracefs_kprobe_info(struct tracefs_dynevent *kprobe,
+					       char **system, char **event,
+					       char **prefix, char **addr, char **format)
 {
-	enum tracefs_kprobe_type rtype = TRACEFS_ALL_KPROBES;
-	char *saveptr;
-	char *content;
-	char *system;
-	char *probe;
-	char *ktype;
-	char *kaddr;
-	char *kfmt;
-	int ret;
-
-	if (!group)
-		group = KPROBE_DEFAULT_GROUP;
-
-	if (type)
-		*type = NULL;
+	if (system)
+		*system = NULL;
+	if (event)
+		*event = NULL;
+	if (prefix)
+		*prefix = NULL;
 	if (addr)
 		*addr = NULL;
 	if (format)
 		*format = NULL;
 
-	content = tracefs_instance_file_read(NULL, KPROBE_EVENTS, NULL);
-	if (!content)
-		return rtype;
-
-	ret = parse_kprobe(content, &saveptr, &ktype, &system, &probe,
-			   &kaddr, &kfmt);
-
-	while (!ret) {
-
-		if (!strcmp(system, group) && !strcmp(probe, event)) {
-			if (type)
-				*type = strdup(ktype);
-			if (addr)
-				*addr = strdup(kaddr);
-			if (format)
-				*format = strdup(kfmt);
+	if (!kprobe)
+		return TRACEFS_DYNEVENT_MAX;
 
-			switch (*ktype) {
-			case 'p': rtype = TRACEFS_KPROBE; break;
-			case 'r': rtype = TRACEFS_KRETPROBE; break;
-			}
-			break;
+	if (system) {
+		if (kprobe->system) {
+			*system = strdup(kprobe->system);
+			if (!(*system))
+				goto error;
 		}
-		ret = parse_kprobe(NULL, &saveptr, &ktype, &system, &probe,
-				   &kaddr, &kfmt);
 	}
-	free(content);
-	return rtype;
+	if (event) {
+		*event = strdup(kprobe->event);
+		if (!(*event))
+			goto error;
+	}
+	if (prefix) {
+		*prefix = strdup(kprobe->prefix);
+		if (!(*prefix))
+			goto error;
+	}
+	if (addr && kprobe->address) {
+		*addr = strdup(kprobe->address);
+		if (!(*addr))
+			goto error;
+	}
+	if (format && kprobe->format) {
+		*format = strdup(kprobe->format);
+		if (!(*format))
+			goto error;
+	}
+
+	return kprobe->type;
+
+error:
+	if (system)
+		free(*system);
+	if (event)
+		free(*event);
+	if (prefix)
+		free(*prefix);
+	if (addr)
+		free(*addr);
+	if (format)
+		free(*format);
+	return TRACEFS_DYNEVENT_MAX;
 }