The new method can print only a subset of the unique data fields of the trace event. The print format is derived from the parsing tokens (tep_print_parse objects) of the event. As a byproduct of this change the existing method tep_print_fields() gets upgraded to use the formats provided by the tokens. Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@xxxxxxxxx> --- src/event-parse.c | 87 ++++++++++++++++++++++++++++++++++++++++++----- src/event-parse.h | 3 ++ 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/event-parse.c b/src/event-parse.c index f42ae38..7302f3d 100644 --- a/src/event-parse.c +++ b/src/event-parse.c @@ -3585,6 +3585,8 @@ tep_find_field(struct tep_event *event, const char *name) return format; } + + /** * tep_find_any_field - find any field by name * @event: handle for the event @@ -5333,6 +5335,19 @@ static int is_printable_array(char *p, unsigned int len) return 1; } +static void dynamic_offset(struct tep_handle *tep, + struct tep_format_field *field, + void *data, + unsigned int *offset, + unsigned int *len) +{ + unsigned long long val; + + val = tep_read_number(tep, data + field->offset, field->size); + *offset = val & SHRT_MAX; + *len = val >> 16; +} + void tep_print_field(struct trace_seq *s, void *data, struct tep_format_field *field) { @@ -5343,12 +5358,9 @@ void tep_print_field(struct trace_seq *s, void *data, if (field->flags & TEP_FIELD_IS_ARRAY) { offset = field->offset; len = field->size; - if (field->flags & TEP_FIELD_IS_DYNAMIC) { - val = tep_read_number(tep, data + offset, len); - offset = val; - len = offset >> 16; - offset &= 0xffff; - } + if (field->flags & TEP_FIELD_IS_DYNAMIC) + dynamic_offset(tep, field, data, &offset, &len); + if (field->flags & TEP_FIELD_IS_STRING && is_printable_array(data + offset, len)) { trace_seq_printf(s, "%s", (char *)data + offset); @@ -5398,19 +5410,76 @@ void tep_print_field(struct trace_seq *s, void *data, } } -void tep_print_fields(struct trace_seq *s, void *data, - int size __maybe_unused, struct tep_event *event) +static struct tep_print_parse *parse_format_next(struct tep_print_parse *parse) +{ + while (parse) { + if (strncmp(parse->format, "%", 1) == 0) + break; + + parse = parse->next; + } + + return parse; +} + +static void tep_print_fmt_field(struct trace_seq *s, void *data, + const char *format, + struct tep_format_field *field) +{ + struct tep_handle *tep = field->event->tep; + unsigned int len, offset; + unsigned long long val; + + if (field->flags & TEP_FIELD_IS_DYNAMIC) { + dynamic_offset(tep, field, data, &offset, &len); + if (len) + trace_seq_printf(s, format, (char *)data + offset); + else + trace_seq_printf(s, format, "(nil)"); + } else { + val = tep_read_number(tep, data + field->offset, field->size); + trace_seq_printf(s, format, val); + } +} + +void tep_print_selected_fields(struct trace_seq *s, void *data, + struct tep_event *event, + int ignore_mask) { struct tep_format_field *field; + struct tep_print_parse *parse; + unsigned int len; + int field_mask = 1; + parse = event->print_fmt.print_cache; field = event->format.fields; while (field) { + parse = parse_format_next(parse); + + if (field_mask & ignore_mask) + goto next; + trace_seq_printf(s, " %s=", field->name); - tep_print_field(s, data, field); + + len = strlen(parse->format); + if (len > 0 && parse->format[len - 1] == 'x') + trace_seq_printf(s, "0x"); + + tep_print_fmt_field(s, data, parse->format, field); + + next: field = field->next; + parse = parse->next; + field_mask *= 2; } } +void tep_print_fields(struct trace_seq *s, void *data, + int size __maybe_unused, struct tep_event *event) +{ + tep_print_selected_fields(s, data, event, 0); +} + static int print_function(struct trace_seq *s, const char *format, void *data, int size, struct tep_event *event, struct tep_print_arg *arg) diff --git a/src/event-parse.h b/src/event-parse.h index d4a876f..fe0fbf4 100644 --- a/src/event-parse.h +++ b/src/event-parse.h @@ -547,6 +547,9 @@ void tep_print_field(struct trace_seq *s, void *data, struct tep_format_field *field); void tep_print_fields(struct trace_seq *s, void *data, int size __maybe_unused, struct tep_event *event); +void tep_print_selected_fields(struct trace_seq *s, void *data, + struct tep_event *event, + int ignore_mask); int tep_strerror(struct tep_handle *tep, enum tep_errno errnum, char *buf, size_t buflen); -- 2.30.2