19a50bad172cb4d053a209d46d69d72c2705858e
[ldtrace] / loader / w / wrap.c
1 #define clock_gettime __real_clock_gettime
2 #define open __real_open
3 #define __syscall __real___syscall
4 #define mmap __real_mmap
5 #define ftruncate __real_ftruncate
6 #define dprintf __real_dprintf
7 #define _exit __real__exit
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <sys/uio.h>
14 #include <sys/syscall.h>
15 #include <sys/mman.h>
16 #include <time.h>
17
18 #include "stub.h"
19
20 static struct {
21         char *s;
22         size_t len;
23 } nametab[] = {
24 #define T(i,f) {#f "\n", sizeof #f},
25 #include "tab.h"
26 #undef T
27 };
28
29 static struct {
30         uint64_t c;
31         uint64_t t;
32 } *tab;
33
34 static void tab_init(void)
35 {
36         // todo: argv[0] ".ldtrace"
37         int fd = open("/tmp/wrap", O_CREAT|O_TRUNC|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK, 0666);
38         if (fd == -1) {
39                 dprintf(2, "open /tmp/wrap failed: %m\n");
40                 _exit(127);
41         }
42         if (ftruncate(fd, 2000 * sizeof *tab)) {
43                 dprintf(2, "ftruncate: %m\n");
44                 _exit(127);
45         }
46         tab = mmap(0, 2000 * sizeof *tab, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
47         if (tab == MAP_FAILED) {
48                 dprintf(2, "mmap: %m\n");
49                 _exit(127);
50         }
51 }
52
53 static int show_trace=1;
54 static int log_time=1;
55
56 // todo: tls
57 static struct entry {
58         void *ret;
59         uint64_t t;
60         int n;
61 } stack[100];
62 static struct entry *sp;
63
64 long __syscall(long,...);
65 static void after(void);
66
67 __attribute__((used))
68 static void enter(int n, void **retaddr)
69 {
70         if (!tab) {
71                 tab_init();
72                 sp = stack;
73         }
74         if (show_trace)
75                 __syscall(SYS_write, 2, nametab[n].s, nametab[n].len);
76         tab[n].c++;
77         sp->n = n;
78         sp->ret = *retaddr;
79         *retaddr = after;
80         if (log_time) {
81                 struct timespec ts;
82                 clock_gettime(CLOCK_REALTIME, &ts);
83                 sp->t = ts.tv_sec*1000000000ULL + ts.tv_nsec;
84         }
85         sp++;
86 }
87
88 __attribute__((used))
89 static void *leave(void)
90 {
91         sp--;
92         if (log_time) {
93                 struct timespec ts;
94                 clock_gettime(CLOCK_REALTIME, &ts);
95                 tab[sp->n].t += ts.tv_sec*1000000000ULL + ts.tv_nsec - sp->t;
96         }
97         return sp->ret;
98 }