Re: [RFC PATCH] libtraceevent: Add tep_print_selected_fields()

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

 



Steven,

The implementation of static void tep_print_fmt_field() is incomplete.
If you compare the logic there with the implementation of
void tep_print_field() you will see that I am not handling the case of
a field that is an "ARRAY".

Any ideas what is the best way to handle this case?

Thanks!
Yordan


On 2.08.21 г. 14:27, Yordan Karadzhov (VMware) wrote:
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);



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

  Powered by Linux