diff options
author | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2015-05-05 11:35:16 +0900 |
---|---|---|
committer | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2015-05-08 14:13:17 +0900 |
commit | 664708b817ab0cdc7177df3743b5d9c9ab7dd2b0 (patch) | |
tree | 04becb4abc16c79b2383629df16c661b20a36407 /src/bin/eina/eina_btlog.c | |
parent | 38faeacee1a1aa10eabebb52edfaf91e2a2c158b (diff) |
eina - start a much improved eina dbug infra and have eina_log use it
this makes eina_log give bt's for all error logs. this is very useful
in finding just where a problem happens. the problem int he past is
that these have not been too useful due to backtrace_symbols() being
"useless". thus use the eina_btlog tool i added too.
also started infra for a debug monitor that can use the backtrace
infra to collect runtime stats ANY TIME for a process (don't need to
run under a debugger).
@feat
Diffstat (limited to 'src/bin/eina/eina_btlog.c')
-rw-r--r-- | src/bin/eina/eina_btlog.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/bin/eina/eina_btlog.c b/src/bin/eina/eina_btlog.c new file mode 100644 index 0000000000..2b4d5303ab --- /dev/null +++ b/src/bin/eina/eina_btlog.c | |||
@@ -0,0 +1,198 @@ | |||
1 | #include <Eina.h> | ||
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | |||
6 | // right now this is quick and dirty and may have some parsing ... frailty, | ||
7 | // so don't put malicious data through it... :) but cat in eina bt's through | ||
8 | // this to get a nicely clean and readable bt with filenames of binaries, | ||
9 | // shared objects, source files, and line numbers. even nicely colored and | ||
10 | // columnated. this is more the start of a bunch of debug tools for efl to make | ||
11 | // it easier to identify issues. | ||
12 | // | ||
13 | // how to use: | ||
14 | // | ||
15 | // cat mybacktrace.txt | eina_btlog | ||
16 | // | ||
17 | // (or just run it and copy & paste in on stdin - what i do mostly, and out | ||
18 | // pops a nice backtrace, hit ctrl+d to end) | ||
19 | |||
20 | typedef struct _Bt Bt; | ||
21 | |||
22 | struct _Bt | ||
23 | { | ||
24 | char *bin_dir; | ||
25 | char *bin_name; | ||
26 | char *file_dir; | ||
27 | char *file_name; | ||
28 | char *func_name; | ||
29 | int line; | ||
30 | }; | ||
31 | |||
32 | static void | ||
33 | path_split(const char *path, char **dir, char **file) | ||
34 | { | ||
35 | const char *p = strrchr(path, '/'); | ||
36 | |||
37 | if (!path) | ||
38 | { | ||
39 | *dir = NULL; | ||
40 | *file = NULL; | ||
41 | return; | ||
42 | } | ||
43 | if (!p) | ||
44 | { | ||
45 | *dir = NULL; | ||
46 | *file = strdup(path); | ||
47 | return; | ||
48 | } | ||
49 | *dir = malloc(p - path + 1); | ||
50 | if (!dir) | ||
51 | { | ||
52 | *dir = NULL; | ||
53 | *file = NULL; | ||
54 | return; | ||
55 | } | ||
56 | strncpy(*dir, path, p - path); | ||
57 | (*dir)[p - path] = 0; | ||
58 | *file = strdup(p + 1); | ||
59 | } | ||
60 | |||
61 | static Eina_Bool | ||
62 | _addr2line(const char *bin_dir, const char *bin_name, unsigned long long addr, | ||
63 | char **file_dir, char **file_name, char **func_name, int *file_line) | ||
64 | { | ||
65 | char buf[4096], func[4096], *f1 = NULL, *f2 = NULL; | ||
66 | Eina_Bool ok = EINA_FALSE; | ||
67 | int line; | ||
68 | FILE *p; | ||
69 | |||
70 | snprintf(buf, sizeof(buf), "addr2line -f -e %s/%s -C -a 0x%llx", | ||
71 | bin_dir, bin_name, addr); | ||
72 | p = popen(buf, "r"); | ||
73 | if (!p) return EINA_FALSE; | ||
74 | fscanf(p, "%s\n", buf); | ||
75 | if (fscanf(p, "%s\n", func) == 1) | ||
76 | { | ||
77 | if (fscanf(p, "%[^:]:%i\n", buf, &line) == 2) | ||
78 | { | ||
79 | path_split(buf, &(f1), &(f2)); | ||
80 | if ((!f1) || (!f2)) | ||
81 | { | ||
82 | free(f1); | ||
83 | free(f2); | ||
84 | pclose(p); | ||
85 | return EINA_FALSE; | ||
86 | } | ||
87 | } | ||
88 | else | ||
89 | { | ||
90 | f1 = strdup("??"); | ||
91 | f2 = strdup("??"); | ||
92 | } | ||
93 | *file_dir = f1; | ||
94 | *file_name = f2; | ||
95 | *func_name = strdup(func); | ||
96 | *file_line = line; | ||
97 | ok = EINA_TRUE; | ||
98 | } | ||
99 | pclose(p); | ||
100 | return ok; | ||
101 | } | ||
102 | |||
103 | static Eina_List * | ||
104 | bt_append(Eina_List *btl, const char *btline) | ||
105 | { | ||
106 | Bt *bt = calloc(1, sizeof(Bt)); | ||
107 | if (!bt) return btl; | ||
108 | char *bin = strdup(btline); | ||
109 | unsigned long long offset = 0, base = 0; | ||
110 | |||
111 | // parse: | ||
112 | // /usr/local/lib/libeina.so.1 0x1ec88 | ||
113 | // /usr/local/lib/libelementary.so.1 0x10f695 | ||
114 | // /usr/local/lib/libeo.so.1 0xa474 | ||
115 | // /usr/local/lib/libelementary.so.1 0x139bd6 | ||
116 | // /usr/local/bin/elementary_test 0x8196d | ||
117 | // /usr/local/bin/elementary_test 0x81b6a | ||
118 | if (sscanf(btline, "%s %llx %llx", bin, &offset, &base) == 3) | ||
119 | { | ||
120 | path_split(bin, &(bt->bin_dir), &(bt->bin_name)); | ||
121 | if (!bt->bin_dir) bt->bin_dir = strdup(""); | ||
122 | if (!bt->bin_name) bt->bin_name = strdup(""); | ||
123 | if (!_addr2line(bt->bin_dir, bt->bin_name, offset - base, | ||
124 | &(bt->file_dir), &(bt->file_name), | ||
125 | &(bt->func_name), &(bt->line))) | ||
126 | { | ||
127 | if (!_addr2line(bt->bin_dir, bt->bin_name, offset, | ||
128 | &(bt->file_dir), &(bt->file_name), | ||
129 | &(bt->func_name), &(bt->line))) | ||
130 | { | ||
131 | bt->file_dir = strdup(""); | ||
132 | bt->file_name = strdup(""); | ||
133 | bt->func_name = strdup(""); | ||
134 | } | ||
135 | } | ||
136 | btl = eina_list_append(btl, bt); | ||
137 | } | ||
138 | free(bin); | ||
139 | return btl; | ||
140 | } | ||
141 | |||
142 | int | ||
143 | main(int argc, char **argv) | ||
144 | { | ||
145 | Eina_List *btl = NULL, *l; | ||
146 | char buf[4096]; | ||
147 | Bt *bt; | ||
148 | int cols[6] = { 0 }, len, i; | ||
149 | |||
150 | eina_init(); | ||
151 | while (fgets(buf, sizeof(buf) - 1, stdin)) | ||
152 | { | ||
153 | btl = bt_append(btl, buf); | ||
154 | } | ||
155 | EINA_LIST_FOREACH(btl, l, bt) | ||
156 | { | ||
157 | len = strlen(bt->bin_dir); | ||
158 | if (len > cols[0]) cols[0] = len; | ||
159 | len = strlen(bt->bin_name); | ||
160 | if (len > cols[1]) cols[1] = len; | ||
161 | |||
162 | len = strlen(bt->file_dir); | ||
163 | if (len > cols[2]) cols[2] = len; | ||
164 | len = strlen(bt->file_name); | ||
165 | if (len > cols[3]) cols[3] = len; | ||
166 | |||
167 | snprintf(buf, sizeof(buf), "%i", bt->line); | ||
168 | len = strlen(buf); | ||
169 | if (len > cols[4]) cols[4] = len; | ||
170 | |||
171 | len = strlen(bt->func_name); | ||
172 | if (len > cols[5]) cols[5] = len; | ||
173 | } | ||
174 | EINA_LIST_FOREACH(btl, l, bt) | ||
175 | { | ||
176 | len = strlen(bt->bin_dir); | ||
177 | for (i = 0; i < (cols[0] - len); i++) printf(" "); | ||
178 | printf("\033[34m%s\033[01m\033[36m/\033[37m%s\033[0m", | ||
179 | bt->bin_dir, bt->bin_name); | ||
180 | len = strlen(bt->bin_name); | ||
181 | for (i = 0; i < (cols[1] - len); i++) printf(" "); | ||
182 | printf(" | "); | ||
183 | len = strlen(bt->file_dir); | ||
184 | for (i = 0; i < (cols[2] - len); i++) printf(" "); | ||
185 | printf("\033[34m%s\033[01m\033[36m/\033[37m%s\033[0m", | ||
186 | bt->file_dir, bt->file_name); | ||
187 | len = strlen(bt->file_name); | ||
188 | for (i = 0; i < (cols[3] - len); i++) printf(" "); | ||
189 | |||
190 | printf(" : "); | ||
191 | snprintf(buf, sizeof(buf), "%i", bt->line); | ||
192 | len = strlen(buf); | ||
193 | for (i = 0; i < (cols[4] - len); i++) printf(" "); | ||
194 | printf("\033[01m\033[33m%s\033[0m @ \033[32m%s\033[36m()", buf, bt->func_name); | ||
195 | printf("\033[0m\n"); | ||
196 | } | ||
197 | return 0; | ||
198 | } | ||