]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Add trace_dump tool
authorDJ Delorie <dj@delorie.com>
Thu, 14 Jul 2016 02:50:28 +0000 (22:50 -0400)
committerDJ Delorie <dj@delorie.com>
Thu, 14 Jul 2016 02:50:28 +0000 (22:50 -0400)
trace_dump <binary-trace-or-workload>
autodetects trace file vs workload, outputs the contents thereof

malloc/Makefile
malloc/trace_dump.c [new file with mode: 0644]

index 4146c2a9b49367728c21f9401eb3ace40b3eec30..bbfa2db0c00a17ffdde410e7679c27462307e020 100644 (file)
@@ -50,12 +50,15 @@ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
 libmtracectl-routines = mtrace-ctl
 libmtracectl-inhibit-o = $(filter-out .os,$(object-suffixes))
 
-others: $(objpfx)trace_run $(objpfx)trace2wl
-install-bin = trace_run trace2wl
+others: $(objpfx)trace_run $(objpfx)trace2wl $(objpfx)trace_dump
+install-bin = trace_run trace2wl trace_dump
 
 $(objpfx)trace_run: $(objpfx)trace_run.o
        $(LINK.o) -o $@ $(objpfx)trace_run.o -lpthread
 
+$(objpfx)trace_dump: $(objpfx)trace_dump.o
+       $(LINK.o) -o $@ $(objpfx)trace_dump.o
+
 ifeq (${CXX},)
 CXX = g++
 endif
diff --git a/malloc/trace_dump.c b/malloc/trace_dump.c
new file mode 100644 (file)
index 0000000..d3a72f2
--- /dev/null
@@ -0,0 +1,198 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+// The trace file looks like an array of struct __malloc_trace_buffer_s
+#include "mtrace.h"
+
+static size_t
+get_int (unsigned char **ptr)
+{
+  size_t rv = 0;
+  while (1)
+  {
+    unsigned char c = *(*ptr)++;
+    rv |= (c & 0x7f);
+    if (c & 0x80)
+      rv <<= 7;
+    else
+      return rv;
+  }
+}
+
+
+int
+data_looks_like_raw_trace (unsigned char *data, long n_data)
+{
+  long lim = n_data > 1024 ? 1020 : (n_data - 4);
+  long i;
+
+  // free and malloc calls will have a NULL we can look for
+  for (i=0; i<lim; i++)
+    if (memcmp (data+i, "\0\0\0\0", 4) == 0)
+       return 1;
+
+  return 0;
+}
+
+const char * const typenames[] = {
+  "unused  ",
+  "malloc  ",
+  "calloc  ",
+  "free    ",
+  "realloc ",
+  "memalign",
+  "valloc  ",
+  "pvalloc  ",
+};
+
+void
+dump_raw_trace (unsigned char *data, long n_data)
+{
+  unsigned char *edata = data + n_data;
+  long head;
+
+  head = n_data / sizeof (struct __malloc_trace_buffer_s);
+
+  printf ("%ld out of %ld events captured (I think)\n", head, head);
+
+  printf ("threadid type     path     ptr1             size             ptr2\n");
+
+  while (data <= edata - sizeof (struct __malloc_trace_buffer_s))
+    {
+      struct __malloc_trace_buffer_s *t = (struct __malloc_trace_buffer_s *)data;
+
+      switch (t->type)
+       {
+       case __MTB_TYPE_UNUSED:
+         break;
+       default:
+         printf ("%08x %s %c%c%c%c%c%c%c%c %016llx %016llx %016llx\n",
+                 t->thread,
+                 t->type == __MTB_TYPE_MAGIC ? "magic   " : typenames[t->type],
+                 t->path_thread_cache ? 'T' : '-',
+                 t->path_cpu_cache ? 'c' : '-',
+                 t->path_cpu_cache2 ? 'C' : '-',
+                 t->path_sbrk ? 's' : '-',
+                 t->path_mmap ? 'M' : '-',
+                 t->path_munmap ? 'U' : '-',
+                 t->path_m_f_realloc ? 'R' : '-',
+                 t->path_hook ? 'H' : '-',
+                 (long long unsigned int) (size_t) t->ptr1,
+                 (long long unsigned int) t->size,
+                 (long long unsigned int) (size_t) t->ptr2);
+         break;
+       }
+
+      data += sizeof (struct __malloc_trace_buffer_s);
+    }
+}
+
+void
+dump_workload (unsigned char *data, long n_data)
+{
+  unsigned char *orig_data = data;
+  unsigned char *edata = data + n_data;
+  int thread_idx = 0;
+  int n_ptrs, n_syncs, n_threads, idx, p1, p2, sz;
+
+  while (data < edata)
+    {
+      printf("%016lx: %4d: ", data - orig_data, thread_idx);
+      switch (*data++)
+       {
+       case C_NOP:
+         break;
+       case C_ALLOC_PTRS:
+         n_ptrs = get_int(&data);
+         printf("AllocPtrs: %d\n", n_ptrs);
+         break;
+       case C_ALLOC_SYNCS:
+         n_syncs = get_int(&data);
+         printf("AllocSyncs: %d\n", n_syncs);
+         break;
+       case C_NTHREADS:
+         n_threads = get_int (&data);
+         printf("NThreads: %d\n", n_threads);
+         break;
+       case C_START_THREAD:
+         idx = get_int (&data);
+         printf("StartThread: 0x%x\n", idx);
+         break;
+       case C_DONE:
+         printf("Done\n");
+         thread_idx ++;
+         break;
+
+       case C_MALLOC:
+         p2 = get_int (&data);
+         sz = get_int (&data);
+         printf("Malloc (%d) -> %d\n", sz, p2);
+         break;
+
+       case C_CALLOC:
+         p2 = get_int (&data);
+         sz = get_int (&data);
+         printf("Calloc (%d) -> %d\n", sz, p2);
+         break;
+
+       case C_REALLOC:
+         p2 = get_int (&data);
+         p1 = get_int (&data);
+         sz = get_int (&data);
+         printf("Realloc (%d, %d) -> %d\n", p1, sz, p2);
+         break;
+
+       case C_FREE:
+         p1 = get_int (&data);
+         printf("Free (%d)\n", p1);
+         break;
+
+       case C_SYNC_W:
+         p1 = get_int(&data);
+         printf("SyncW (%d)\n", p1);
+         break;
+
+       case C_SYNC_R:
+         p1 = get_int(&data);
+         printf("SyncR (%d)\n", p1);
+         break;
+
+       default:
+         printf("(unknown:%d)\n", *--data);
+         exit(1);
+       }
+    }
+}
+
+int
+main (int argc, char **argv)
+{
+  int fd;
+  struct stat statb;
+  unsigned char *data;
+
+  fd = open(argv[1], O_RDONLY);
+  if (fd < 0)
+    {
+      fprintf(stderr, "Unable to open %s for reading\n", argv[1]);
+      perror("The error was");
+      exit(1);
+    }
+  fstat (fd, &statb);
+
+  data = (unsigned char *) mmap (NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+
+  if (data_looks_like_raw_trace (data, statb.st_size))
+    dump_raw_trace (data, statb.st_size);
+  else
+    dump_workload (data, statb.st_size);
+
+  return 0;
+}