loader based trace using musl
[ldtrace] / loader / w / wrap.c
diff --git a/loader/w/wrap.c b/loader/w/wrap.c
new file mode 100644 (file)
index 0000000..19a50ba
--- /dev/null
@@ -0,0 +1,98 @@
+#define clock_gettime __real_clock_gettime
+#define open __real_open
+#define __syscall __real___syscall
+#define mmap __real_mmap
+#define ftruncate __real_ftruncate
+#define dprintf __real_dprintf
+#define _exit __real__exit
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+#include <time.h>
+
+#include "stub.h"
+
+static struct {
+       char *s;
+       size_t len;
+} nametab[] = {
+#define T(i,f) {#f "\n", sizeof #f},
+#include "tab.h"
+#undef T
+};
+
+static struct {
+       uint64_t c;
+       uint64_t t;
+} *tab;
+
+static void tab_init(void)
+{
+       // todo: argv[0] ".ldtrace"
+       int fd = open("/tmp/wrap", O_CREAT|O_TRUNC|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK, 0666);
+       if (fd == -1) {
+               dprintf(2, "open /tmp/wrap failed: %m\n");
+               _exit(127);
+       }
+       if (ftruncate(fd, 2000 * sizeof *tab)) {
+               dprintf(2, "ftruncate: %m\n");
+               _exit(127);
+       }
+       tab = mmap(0, 2000 * sizeof *tab, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+       if (tab == MAP_FAILED) {
+               dprintf(2, "mmap: %m\n");
+               _exit(127);
+       }
+}
+
+static int show_trace=1;
+static int log_time=1;
+
+// todo: tls
+static struct entry {
+       void *ret;
+       uint64_t t;
+       int n;
+} stack[100];
+static struct entry *sp;
+
+long __syscall(long,...);
+static void after(void);
+
+__attribute__((used))
+static void enter(int n, void **retaddr)
+{
+       if (!tab) {
+               tab_init();
+               sp = stack;
+       }
+       if (show_trace)
+               __syscall(SYS_write, 2, nametab[n].s, nametab[n].len);
+       tab[n].c++;
+       sp->n = n;
+       sp->ret = *retaddr;
+       *retaddr = after;
+       if (log_time) {
+               struct timespec ts;
+               clock_gettime(CLOCK_REALTIME, &ts);
+               sp->t = ts.tv_sec*1000000000ULL + ts.tv_nsec;
+       }
+       sp++;
+}
+
+__attribute__((used))
+static void *leave(void)
+{
+       sp--;
+       if (log_time) {
+               struct timespec ts;
+               clock_gettime(CLOCK_REALTIME, &ts);
+               tab[sp->n].t += ts.tv_sec*1000000000ULL + ts.tv_nsec - sp->t;
+       }
+       return sp->ret;
+}