summaryrefslogtreecommitdiff
path: root/src/bin/eina/eina_btlog.c
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2015-05-05 11:35:16 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2015-05-08 14:13:17 +0900
commit664708b817ab0cdc7177df3743b5d9c9ab7dd2b0 (patch)
tree04becb4abc16c79b2383629df16c661b20a36407 /src/bin/eina/eina_btlog.c
parent38faeacee1a1aa10eabebb52edfaf91e2a2c158b (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.c198
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
20typedef struct _Bt Bt;
21
22struct _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
32static void
33path_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
61static 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
103static Eina_List *
104bt_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
142int
143main(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}