[RFC PATCH] libtraceevent: Add tep_print_selected_fields()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux