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) {