From 9ce1f327ad03584fcaab0604e7d398ea80be2acb Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 19 Jan 2014 18:58:31 +0100 Subject: [PATCH] loader based trace using musl --- loader/config.mak | 22 +++++++++++ loader/run.sh | 4 ++ loader/w/dump.c | 37 ++++++++++++++++++ loader/w/stub.h | 25 ++++++++++++ loader/w/wrap.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 186 insertions(+) create mode 100644 loader/config.mak create mode 100755 loader/run.sh create mode 100644 loader/w/dump.c create mode 100644 loader/w/stub.h create mode 100644 loader/w/wrap.c diff --git a/loader/config.mak b/loader/config.mak new file mode 100644 index 0000000..888cea8 --- /dev/null +++ b/loader/config.mak @@ -0,0 +1,22 @@ +# add at the end of musl config.mak + +all: lib/libw.so w/dump + +w/dump: w/dump.o + $(CC) -o $@ $^ + +w/redef: lib/libc.so + nm -D lib/libc.so |awk '/^[0-9a-f]* [T|W]/{print $$3 " __real_" $$3}' >$@ + +w/tab.h: w/redef + awk 'BEGIN{n=0} {print "T(" n++ "," $$1 ")"}' $< >$@ + +%.wo: %.lo + objcopy --redefine-syms w/redef $< $@ + +w/wrap.lo: w/tab.h w/stub.h + +lib/libw.so: w/wrap.lo $(LOBJS:%.lo=%.wo) + $(CC) $(CFLAGS_ALL_SHARED) $(LDFLAGS) -nostdlib -shared \ + -Wl,-e,__real__start -Wl,-Bsymbolic-functions \ + -o $@ $^ $(LIBCC) diff --git a/loader/run.sh b/loader/run.sh new file mode 100755 index 0000000..b38bd4d --- /dev/null +++ b/loader/run.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +LD_PRELOAD=lib/libw.so "$@" +w/dump diff --git a/loader/w/dump.c b/loader/w/dump.c new file mode 100644 index 0000000..f3ce32e --- /dev/null +++ b/loader/w/dump.c @@ -0,0 +1,37 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include +#include + +static struct { + uint64_t c; + uint64_t t; +} *tab; + +static char *names[] = { +#define T(i,f) [i] = #f, +#include "tab.h" +#undef T +}; + +int main() +{ + int i; + int fd = open("/tmp/wrap", O_RDONLY); + if (fd == -1) { + dprintf(2, "open /tmp/wrap failed: %m\n"); + return 1; + } + tab = mmap(0, 2000 * sizeof *tab, PROT_READ, MAP_PRIVATE, fd, 0); + if (tab == MAP_FAILED) { + dprintf(2, "mmap: %m\n"); + return 1; + } + for (i = 0; i < sizeof names/sizeof *names; i++) + if (tab[i].c) + dprintf(1, "%s: %llu calls %llu ns %f us/call\n", + names[i], tab[i].c, tab[i].t, (double)tab[i].t/(1000*tab[i].c)); + return 0; +} diff --git a/loader/w/stub.h b/loader/w/stub.h new file mode 100644 index 0000000..5d20a7d --- /dev/null +++ b/loader/w/stub.h @@ -0,0 +1,25 @@ +__asm__( +#define T(i,f) "\n" \ +".global " #f "\n" \ +".type " #f ",@function\n" \ +#f ":\n" \ +" pushl %esp\n" \ +" pushl $" #i "\n" \ +" call enter\n" \ +" pop %eax\n" \ +" pop %eax\n" \ +" jmp __real_" #f "\n" + +#include "tab.h" +#undef T +"\n" +"after:\n" +" push %eax\n" +" push %edx\n" +" call leave\n" +" mov %eax,%ecx\n" +" pop %edx\n" +" pop %eax\n" +" push %ecx\n" +" ret\n" +); diff --git a/loader/w/wrap.c b/loader/w/wrap.c new file mode 100644 index 0000000..19a50ba --- /dev/null +++ b/loader/w/wrap.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} -- 2.20.1