aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2015-06-09 22:24:28 -0400
committerSteven Rostedt <rostedt@goodmis.org>2015-06-10 15:12:15 -0400
commita1f6bec35b6097cf6f3df43688a281da3c997a09 (patch)
tree8e6932a769459105621104b90b680fa557ad4230
parent8cdbccd5ef422dc518e7246aa1c41922e834120b (diff)
downloadtrace-cmd-a1f6bec35b6097cf6f3df43688a281da3c997a09.tar.gz
trace-cmd: Add more debugging to see various internal ring buffer entries
When trace-cmd report --debug is set, show the internal ring buffer entries like time-extends and padding. This requires adding new kbuffer API to retrieve these items. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--kbuffer-parse.c49
-rw-r--r--kbuffer.h13
-rw-r--r--trace-cmd.h9
-rw-r--r--trace-input.c28
-rw-r--r--trace-read.c39
5 files changed, 137 insertions, 1 deletions
diff --git a/kbuffer-parse.c b/kbuffer-parse.c
index fca326ca..cd13a921 100644
--- a/kbuffer-parse.c
+++ b/kbuffer-parse.c
@@ -767,3 +767,52 @@ int kbuffer_start_of_data(struct kbuffer *kbuf)
{
return kbuf->start;
}
+
+/**
+ * kbuffer_raw_get - get raw buffer info
+ * @kbuf: The kbuffer
+ * @subbuf: Start of mapped subbuffer
+ * @info: Info descriptor to fill in
+ *
+ * For debugging. This can return internals of the ring buffer.
+ * Expects to have info->next set to what it will read.
+ * The type, length and timestamp delta will be filled in, and
+ * @info->next will be updated to the next element.
+ * The @subbuf is used to know if the info is passed the end of
+ * data and NULL will be returned if it is.
+ */
+struct kbuffer_raw_info *
+kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, struct kbuffer_raw_info *info)
+{
+ unsigned long long flags;
+ unsigned long long delta;
+ unsigned int type_len;
+ unsigned int size;
+ int start;
+ int length;
+ void *ptr = info->next;
+
+ if (!kbuf || !subbuf)
+ return NULL;
+
+ if (kbuf->flags & KBUFFER_FL_LONG_8)
+ start = 16;
+ else
+ start = 12;
+
+ flags = read_long(kbuf, subbuf + 8);
+ size = (unsigned int)flags & COMMIT_MASK;
+
+ if (ptr < subbuf || ptr >= subbuf + start + size)
+ return NULL;
+
+ type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
+
+ info->next = ptr + length;
+
+ info->type = type_len;
+ info->delta = delta;
+ info->length = length;
+
+ return info;
+}
diff --git a/kbuffer.h b/kbuffer.h
index 45dbeca6..5fa8292e 100644
--- a/kbuffer.h
+++ b/kbuffer.h
@@ -67,4 +67,17 @@ int kbuffer_subbuffer_size(struct kbuffer *kbuf);
void kbuffer_set_old_format(struct kbuffer *kbuf);
int kbuffer_start_of_data(struct kbuffer *kbuf);
+/* Debugging */
+
+struct kbuffer_raw_info {
+ int type;
+ int length;
+ unsigned long long delta;
+ void *next;
+};
+
+/* Read raw data */
+struct kbuffer_raw_info *kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf,
+ struct kbuffer_raw_info *info);
+
#endif /* _K_BUFFER_H */
diff --git a/trace-cmd.h b/trace-cmd.h
index a6983448..c9b9b955 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -320,4 +320,13 @@ void tracecmd_free_hooks(struct hook_list *hooks);
/* --- Hack! --- */
int tracecmd_blk_hack(struct tracecmd_input *handle);
+
+/* --- Debugging --- */
+struct kbuffer *tracecmd_record_kbuf(struct tracecmd_input *handle,
+ struct pevent_record *record);
+void *tracecmd_record_page(struct tracecmd_input *handle,
+ struct pevent_record *record);
+void *tracecmd_record_offset(struct tracecmd_input *handle,
+ struct pevent_record *record);
+
#endif /* _TRACE_CMD_H */
diff --git a/trace-input.c b/trace-input.c
index a7e0ff2a..76f03ee3 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -2847,6 +2847,34 @@ unsigned int tracecmd_record_ts_delta(struct tracecmd_input *handle,
return kbuffer_ptr_delta(kbuf, page->map + offset);
}
+struct kbuffer *tracecmd_record_kbuf(struct tracecmd_input *handle,
+ struct pevent_record *record)
+{
+ return handle->cpu_data[record->cpu].kbuf;
+}
+
+void *tracecmd_record_page(struct tracecmd_input *handle,
+ struct pevent_record *record)
+{
+ struct page *page = record->priv;
+
+ return page ? page->map : NULL;
+}
+
+void *tracecmd_record_offset(struct tracecmd_input *handle,
+ struct pevent_record *record)
+{
+ struct page *page = record->priv;
+ int offset;
+
+ if (!page)
+ return NULL;
+
+ offset = record->offset - page->offset;
+
+ return page->map + offset;
+}
+
int tracecmd_buffer_instances(struct tracecmd_input *handle)
{
return handle->nr_buffers;
diff --git a/trace-read.c b/trace-read.c
index e496ef0f..fe8f98b7 100644
--- a/trace-read.c
+++ b/trace-read.c
@@ -37,6 +37,7 @@
#include "trace-local.h"
#include "trace-hash.h"
+#include "kbuffer.h"
#include "list.h"
static struct filter_str {
@@ -774,9 +775,45 @@ void trace_show_data(struct tracecmd_input *handle, struct pevent_record *record
pevent_print_event(pevent, &s, record, use_trace_clock);
if (s.len && *(s.buffer + s.len - 1) == '\n')
s.len--;
- if (debug)
+ if (debug) {
+ struct kbuffer *kbuf;
+ struct kbuffer_raw_info info;
+ void *page;
+ void *offset;
+
trace_seq_printf(&s, " [%d]",
tracecmd_record_ts_delta(handle, record));
+ kbuf = tracecmd_record_kbuf(handle, record);
+ page = tracecmd_record_page(handle, record);
+ offset = tracecmd_record_offset(handle, record);
+
+ if (kbuf && page && offset) {
+ struct kbuffer_raw_info *pi = &info;
+
+ /* We need to get the record raw data to get next */
+ pi->next = offset;
+ pi = kbuffer_raw_get(kbuf, page, pi);
+ while ((pi = kbuffer_raw_get(kbuf, page, pi))) {
+ if (pi->type < KBUFFER_TYPE_PADDING)
+ break;
+ switch (pi->type) {
+ case KBUFFER_TYPE_PADDING:
+ trace_seq_printf(&s, "\n PADDING: ");
+ break;
+ case KBUFFER_TYPE_TIME_EXTEND:
+ trace_seq_printf(&s, "\n TIME EXTEND: ");
+ break;
+ case KBUFFER_TYPE_TIME_STAMP:
+ trace_seq_printf(&s, "\n TIME STAMP?: ");
+ break;
+ }
+ trace_seq_printf(&s, "delta:%lld length:%d",
+ pi->delta,
+ pi->length);
+ }
+ }
+ }
+
trace_seq_do_printf(&s);
trace_seq_destroy(&s);