Re: [PATCH] libtraceevent plugins: Add plugin_net to handle bswap during print

Steven Rostedt <[email protected]> Mon, 14 Apr 2025 11:41:17 -0400
Newsgroups org.kernel.vger.linux-trace-devel
Message-ID <[email protected]>
On Wed, 9 Apr 2025 22:56:08 -0400
Steven Rostedt <[email protected]> wrote:

> As the else block will have args[0] already swapped wrt to host that's
> reading the information. libtraceevent does a byte swap on values read when
> the host and file do not match endianess.

Does this patch work for you?

I only compiled it, I haven't tested it against real functions.

-- Steve

diff --git a/include/traceevent/event-parse.h b/include/traceevent/event-parse.h
index d3ce0a4..99a7214 100644
--- a/include/traceevent/event-parse.h
+++ b/include/traceevent/event-parse.h
@@ -181,7 +181,9 @@ struct tep_print_arg_dynarray {
 	struct tep_print_arg	*index;
 };
 
-struct tep_print_arg;
+struct tep_print_arg_bswap {
+	struct tep_print_arg	*field;
+};
 
 struct tep_print_arg_op {
 	char			*op;
@@ -215,6 +217,9 @@ enum tep_print_arg_type {
 	TEP_PRINT_DYNAMIC_ARRAY_LEN,
 	TEP_PRINT_HEX_STR,
 	TEP_PRINT_CPUMASK,
+	TEP_PRINT_BSWAP16,
+	TEP_PRINT_BSWAP32,
+	TEP_PRINT_BSWAP64,
 };
 
 struct tep_print_arg {
@@ -233,6 +238,7 @@ struct tep_print_arg {
 		struct tep_print_arg_bitmask	bitmask;
 		struct tep_print_arg_op		op;
 		struct tep_print_arg_dynarray	dynarray;
+		struct tep_print_arg_bswap	bswap;
 	};
 };
 
diff --git a/src/event-parse.c b/src/event-parse.c
index 6317ff6..ae19dee 100644
--- a/src/event-parse.c
+++ b/src/event-parse.c
@@ -1129,6 +1129,11 @@ static void free_arg(struct tep_print_arg *arg)
 		free_arg(arg->op.left);
 		free_arg(arg->op.right);
 		break;
+	case TEP_PRINT_BSWAP16:
+	case TEP_PRINT_BSWAP32:
+	case TEP_PRINT_BSWAP64:
+		free_arg(arg->bswap.field);
+		break;
 	case TEP_PRINT_FUNC:
 		while (arg->func.args) {
 			farg = arg->func.args;
@@ -2879,6 +2884,25 @@ static int arg_num_eval(struct tep_print_arg *arg, long long *val)
 		}
 		break;
 
+	case TEP_PRINT_BSWAP16:
+		ret = arg_num_eval(arg->bswap.field, val);
+		if (!ret)
+			break;
+		*val = __builtin_bswap16((uint16_t)(*val));
+		return ret;
+	case TEP_PRINT_BSWAP32:
+		ret = arg_num_eval(arg->bswap.field, val);
+		if (!ret)
+			break;
+		*val = __builtin_bswap32((uint32_t)(*val));
+		return ret;
+	case TEP_PRINT_BSWAP64:
+		ret = arg_num_eval(arg->bswap.field, val);
+		if (!ret)
+			break;
+		*val = __builtin_bswap16(*val);
+		return ret;
+
 	case TEP_PRINT_NULL:
 	case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL:
 	case TEP_PRINT_STRING:
@@ -3525,6 +3549,55 @@ out_free:
 	return TEP_EVENT_ERROR;
 }
 
+static enum tep_event_type
+process_builtin_bswap(struct tep_event *event, char *num, struct tep_print_arg *arg, char **tok)
+{
+	struct tep_handle *tep = event->tep;
+	struct tep_print_arg *field;
+	enum tep_event_type type;
+	char *token = NULL;
+	int n;
+
+	field = alloc_arg();
+	if (!field) {
+		do_warning_event(event, "%s(%d): not enough memory!",
+				 __func__, __LINE__);
+		return TEP_EVENT_ERROR;
+	}
+
+	type = process_arg(event, field, &token);
+	if (test_type_token(type, token,  TEP_EVENT_DELIM, ")"))
+		goto out_free;
+
+	tep_free_token(token);
+	token = NULL;
+
+	/* Do not need to swap if host and file do not match */
+	if (tep->host_bigendian != tep->file_bigendian) {
+		*arg = *field;
+		free_arg(field);
+		return read_token_item(event->tep, tok);
+	}
+
+	n = atoi(num);
+
+	switch (n) {
+	case 16: arg->type = TEP_PRINT_BSWAP16; break;
+	case 32: arg->type = TEP_PRINT_BSWAP32; break;
+	case 64: arg->type = TEP_PRINT_BSWAP64; break;
+	default: goto out_free;
+	}
+
+	arg->bswap.field = field;
+	return read_token_item(event->tep, tok);
+
+out_free:
+	free_arg(field);
+	tep_free_token(token);
+	*tok = NULL;
+	return TEP_EVENT_ERROR;
+}
+
 static enum tep_event_type
 process_sizeof(struct tep_event *event, struct tep_print_arg *arg, char **tok)
 {
@@ -3696,6 +3769,13 @@ process_function(struct tep_event *event, struct tep_print_arg *arg,
 		tep_free_token(token);
 		return process_sizeof(event, arg, tok);
 	}
+	if (strncmp(token, "__builtin_bswap", 15) == 0) {
+		enum tep_event_type type;
+
+		type = process_builtin_bswap(event, token + 15, arg, tok);
+		tep_free_token(token);
+		return type;
+	}
 
 	func = find_func_handler(event->tep, token);
 	if (func) {