summaryrefslogtreecommitdiff
path: root/src/bin
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
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')
-rw-r--r--src/bin/efl/.gitignore2
-rw-r--r--src/bin/efl/efl_debug.c179
-rw-r--r--src/bin/efl/efl_debugd.c219
-rw-r--r--src/bin/eina/.gitignore1
-rw-r--r--src/bin/eina/eina_btlog.c198
5 files changed, 599 insertions, 0 deletions
diff --git a/src/bin/efl/.gitignore b/src/bin/efl/.gitignore
new file mode 100644
index 0000000000..b38a2ee5ea
--- /dev/null
+++ b/src/bin/efl/.gitignore
@@ -0,0 +1,2 @@
1efl_debugd
2efl_debug
diff --git a/src/bin/efl/efl_debug.c b/src/bin/efl/efl_debug.c
new file mode 100644
index 0000000000..b1cd730ea4
--- /dev/null
+++ b/src/bin/efl/efl_debug.c
@@ -0,0 +1,179 @@
1#include <Eina.h>
2#include <Ecore.h>
3#include <Ecore_Con.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <string.h>
8
9static unsigned char *buf;
10static unsigned int buf_size;
11
12static int my_argc;
13static char **my_argv;
14static const char *expect = NULL;
15
16static Ecore_Con_Server *svr;
17
18static void
19_proto(unsigned char *d, unsigned int size)
20{
21 if (size >= 4)
22 {
23 char *cmd = (char *)d;
24
25 if (!strncmp(cmd, "CLST", 4))
26 {
27 int i, n;
28
29 n = (size - 4) / sizeof(int);
30 if (n < 10000)
31 {
32 int *pids = malloc(n * sizeof(int));
33 memcpy(pids, d + 4, n * sizeof(int));
34 for (i = 0; i < n; i++)
35 {
36 if (pids[i] > 0) printf("%i\n", pids[i]);
37 }
38 free(pids);
39 }
40 }
41 if ((expect) && (!strncmp(cmd, expect, 4)))
42 ecore_main_loop_quit();
43 }
44}
45
46
47static Eina_Bool
48_server_proto(void)
49{
50 unsigned int size, newsize;
51 unsigned char *b;
52 if (!buf) return EINA_FALSE;
53 if (buf_size < 4) return EINA_FALSE;
54 memcpy(&size, buf, 4);
55 if (buf_size < (size + 4)) return EINA_FALSE;
56 _proto(buf + 4, size);
57 newsize = buf_size - (size + 4);
58 if (buf_size == newsize)
59 {
60 free(buf);
61 buf = NULL;
62 buf_size = 0;
63 }
64 else
65 {
66 b = malloc(newsize);
67 memcpy(b, buf + size + 4, newsize);
68 free(buf);
69 buf = b;
70 buf_size = newsize;
71 }
72 return EINA_TRUE;
73}
74
75Eina_Bool
76_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Add *ev)
77{
78 int i;
79 for (i = 1; i < my_argc; i++)
80 {
81 if (!strcmp(my_argv[i], "list"))
82 {
83 unsigned int size = 4;
84 char *head = "LIST";
85 expect = "CLST";
86 ecore_con_server_send(svr, &size, 4);
87 ecore_con_server_send(svr, head, 4);
88 }
89 else if ((!strcmp(my_argv[i], "pon")) &&
90 (i < (my_argc - 2)))
91 {
92 unsigned int size = 12;
93 char *head = "PLON";
94 int pid = atoi(my_argv[i + 1]);
95 unsigned int freq = atoi(my_argv[i + 2]);
96 i++;
97 ecore_con_server_send(svr, &size, 4);
98 ecore_con_server_send(svr, head, 4);
99 ecore_con_server_send(svr, &pid, 4);
100 ecore_con_server_send(svr, &freq, 4);
101 ecore_main_loop_quit();
102 }
103 else if ((!strcmp(my_argv[i], "poff")) &&
104 (i < (my_argc - 1)))
105 {
106 unsigned int size = 8;
107 char *head = "PLOFF";
108 int pid = atoi(my_argv[i + 1]);
109 i++;
110 ecore_con_server_send(svr, &size, 4);
111 ecore_con_server_send(svr, head, 4);
112 ecore_con_server_send(svr, &pid, 4);
113 ecore_main_loop_quit();
114 }
115 }
116 return ECORE_CALLBACK_RENEW;
117}
118
119Eina_Bool
120_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Del *ev)
121{
122 ecore_main_loop_quit();
123 return ECORE_CALLBACK_RENEW;
124}
125
126static Eina_Bool
127_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Server_Data *ev)
128{
129 if (!buf)
130 {
131 buf = malloc(ev->size);
132 if (buf)
133 {
134 buf_size = ev->size;
135 memcpy(buf, ev->data, ev->size);
136 }
137 }
138 else
139 {
140 unsigned char *b = realloc(buf, buf_size + ev->size);
141 if (b)
142 {
143 buf = b;
144 memcpy(buf + buf_size, ev->data, ev->size);
145 buf_size += ev->size;
146 }
147 }
148 while (_server_proto());
149 return ECORE_CALLBACK_RENEW;
150}
151
152int
153main(int argc, char **argv)
154{
155 eina_init();
156 ecore_init();
157 ecore_con_init();
158
159 my_argc = argc;
160 my_argv = argv;
161
162 svr = ecore_con_server_connect(ECORE_CON_LOCAL_USER, "efl_debug", 0, NULL);
163 if (!svr)
164 {
165 fprintf(stderr, "ERROR: Cannot connetc to debug daemon.\n");
166 return -1;
167 }
168
169 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, (Ecore_Event_Handler_Cb)_server_add, NULL);
170 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, (Ecore_Event_Handler_Cb)_server_del, NULL);
171 ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, (Ecore_Event_Handler_Cb)_server_data, NULL);
172
173 ecore_main_loop_begin();
174 ecore_con_server_flush(svr);
175
176 ecore_con_shutdown();
177 ecore_shutdown();
178 eina_shutdown();
179}
diff --git a/src/bin/efl/efl_debugd.c b/src/bin/efl/efl_debugd.c
new file mode 100644
index 0000000000..7f369ac636
--- /dev/null
+++ b/src/bin/efl/efl_debugd.c
@@ -0,0 +1,219 @@
1#include <Eina.h>
2#include <Ecore.h>
3#include <Ecore_Con.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <string.h>
8
9typedef struct _Client Client;
10
11struct _Client
12{
13 Ecore_Con_Client *client;
14 int version;
15 pid_t pid;
16 unsigned char *buf;
17 unsigned int buf_size;
18};
19
20static Ecore_Con_Server *svr = NULL;
21static Eina_List *clients = NULL;
22
23static void
24_proto(Client *c, unsigned char *d, unsigned int size)
25{
26 if (size >= 4)
27 {
28 char *cmd = (char *)d;
29
30 if (!strncmp(cmd, "HELO", 4))
31 {
32 int version;
33 int pid;
34
35 memcpy(&version, d + 4, 4);
36 memcpy(&pid, d + 8, 4);
37 c->version = version;
38 c->pid = pid;
39 }
40 else if (!strncmp(cmd, "LIST", 4))
41 {
42 int n = eina_list_count(clients), i;
43 unsigned int *pids, size2;
44 Client *c2;
45 Eina_List *l;
46 char *head = "CLST";
47
48 pids = malloc(n * sizeof(int));
49 i = 0;
50 size2 = 4 + (n * sizeof(int));
51 EINA_LIST_FOREACH(clients, l, c2)
52 {
53 pids[i] = c2->pid;
54 i++;
55 }
56 ecore_con_client_send(c->client, &size2, 4);
57 ecore_con_client_send(c->client, head, 4);
58 ecore_con_client_send(c->client, pids, n * sizeof(int));
59 free(pids);
60 }
61 else if (!strncmp(cmd, "PLON", 4))
62 {
63 int pid;
64 unsigned int freq = 1000;
65 Client *c2;
66 Eina_List *l;
67
68 memcpy(&pid, d + 4, 4);
69 memcpy(&freq, d + 8, 4);
70 if (pid > 0)
71 {
72 EINA_LIST_FOREACH(clients, l, c2)
73 {
74 if (c2->pid == pid)
75 {
76 unsigned int size2 = 8;
77
78 ecore_con_client_send(c2->client, &size2, 4);
79 ecore_con_client_send(c2->client, d, 4);
80 ecore_con_client_send(c2->client, &freq, 4);
81 break;
82 }
83 }
84 }
85 }
86 else if (!strncmp(cmd, "PLOF", 4))
87 {
88 int pid;
89 Client *c2;
90 Eina_List *l;
91
92 memcpy(&pid, d + 4, 4);
93 if (pid > 0)
94 {
95 EINA_LIST_FOREACH(clients, l, c2)
96 {
97 if (c2->pid == pid)
98 {
99 unsigned int size2 = 4;
100
101 ecore_con_client_send(c2->client, &size2, 4);
102 ecore_con_client_send(c2->client, d, 4);
103 break;
104 }
105 }
106 }
107 }
108 }
109}
110
111static Eina_Bool
112_client_proto(Client *c)
113{
114 unsigned int size, newsize;
115 unsigned char *b;
116 if (!c->buf) return EINA_FALSE;
117 if (c->buf_size < 4) return EINA_FALSE;
118 memcpy(&size, c->buf, 4);
119 if (c->buf_size < (size + 4)) return EINA_FALSE;
120 _proto(c, c->buf + 4, size);
121 newsize = c->buf_size - (size + 4);
122 if (c->buf_size == newsize)
123 {
124 free(c->buf);
125 c->buf = NULL;
126 c->buf_size = 0;
127 }
128 else
129 {
130 b = malloc(newsize);
131 memcpy(b, c->buf + size + 4, newsize);
132 free(c->buf);
133 c->buf = b;
134 c->buf_size = newsize;
135 }
136 return EINA_TRUE;
137}
138
139static Eina_Bool
140_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Client_Add *ev)
141{
142 Client *c = calloc(1, sizeof(Client));
143 if (c)
144 {
145 c->client = ev->client;
146 clients = eina_list_append(clients, c);
147 ecore_con_client_data_set(c->client, c);
148 }
149 return ECORE_CALLBACK_RENEW;
150}
151
152static Eina_Bool
153_client_del(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Client_Del *ev)
154{
155 Client *c = ecore_con_client_data_get(ev->client);
156 if (c)
157 {
158 clients = eina_list_remove(clients, c);
159 free(c);
160 }
161 return ECORE_CALLBACK_RENEW;
162}
163
164static Eina_Bool
165_client_data(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Client_Data *ev)
166{
167 Client *c = ecore_con_client_data_get(ev->client);
168 if (c)
169 {
170 if (!c->buf)
171 {
172 c->buf = malloc(ev->size);
173 if (c->buf)
174 {
175 c->buf_size = ev->size;
176 memcpy(c->buf, ev->data, ev->size);
177 }
178 }
179 else
180 {
181 unsigned char *b = realloc(c->buf, c->buf_size + ev->size);
182 if (b)
183 {
184 c->buf = b;
185 memcpy(c->buf + c->buf_size, ev->data, ev->size);
186 c->buf_size += ev->size;
187 }
188 }
189 while (_client_proto(c));
190 }
191 return ECORE_CALLBACK_RENEW;
192}
193
194int
195main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
196{
197 eina_init();
198 ecore_init();
199 ecore_con_init();
200
201 svr = ecore_con_server_add(ECORE_CON_LOCAL_USER, "efl_debug", 0, NULL);
202 if (!svr)
203 {
204 fprintf(stderr, "ERROR: Cannot create debug daemon.\n");
205 return -1;
206 }
207
208 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb)_client_add, NULL);
209 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, (Ecore_Event_Handler_Cb)_client_del, NULL);
210 ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, (Ecore_Event_Handler_Cb)_client_data, NULL);
211
212 ecore_main_loop_begin();
213
214 ecore_con_server_del(svr);
215
216 ecore_con_shutdown();
217 ecore_shutdown();
218 eina_shutdown();
219}
diff --git a/src/bin/eina/.gitignore b/src/bin/eina/.gitignore
new file mode 100644
index 0000000000..ec4ebaa080
--- /dev/null
+++ b/src/bin/eina/.gitignore
@@ -0,0 +1 @@
eina_btlog
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}