/[zanavi_public1]/navit/navit/debug.c
ZANavi

Contents of /navit/navit/debug.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (7 years, 6 months ago) by zoff99
File MIME type: text/plain
File size: 11391 byte(s)
new map version, lots of fixes and experimental new features
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <signal.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <glib.h>
27 #ifndef _MSC_VER
28 #include <sys/time.h>
29 #endif /* _MSC_VER */
30 #include "config.h"
31 #include "file.h"
32 #include "item.h"
33 #include "debug.h"
34
35 #ifdef HAVE_API_ANDROID
36 #include <android/log.h>
37 #endif
38
39 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
40 #include <windows.h>
41 #include <windowsx.h>
42 #endif
43
44 #ifdef HAVE_SOCKET
45 #include <stdlib.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49 static int debug_socket=-1;
50 static struct sockaddr_in debug_sin;
51 #endif
52
53 int debug_level = 0;
54 int segv_level = 0;
55 int timestamp_prefix = 0;
56
57 static int dummy;
58 static GHashTable *debug_hash;
59 static gchar *gdb_program;
60
61 static FILE *debug_fp;
62
63 #if defined(_WIN32) || defined(__CEGCC__)
64
65 static void sigsegv(int sig)
66 {
67 }
68
69 #else
70 #include <unistd.h>
71 static void sigsegv(int sig)
72 {
73 char buffer[256];
74 if (segv_level > 1)
75 sprintf(buffer, "gdb -ex bt %s %d", gdb_program, getpid());
76 else
77 sprintf(buffer, "gdb -ex bt -ex detach -ex quit %s %d", gdb_program, getpid());
78 system(buffer);
79 exit(1);
80 }
81 #endif
82
83 void debug_init(const char *program_name)
84 {
85 gdb_program = g_strdup(program_name);
86 signal(SIGSEGV, sigsegv);
87 debug_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free_func, NULL);
88 debug_fp = stderr;
89 }
90
91 static void debug_update_level(gpointer key, gpointer value, gpointer user_data)
92 {
93 if (debug_level < GPOINTER_TO_INT(value))
94 debug_level = GPOINTER_TO_INT(value);
95 }
96
97 void debug_level_set(const char *name, int level)
98 {
99 if (!strcmp(name, "segv"))
100 {
101 segv_level = level;
102 if (segv_level)
103 signal(SIGSEGV, sigsegv);
104 else
105 signal(SIGSEGV, NULL);
106 }
107 else if (!strcmp(name, "timestamps"))
108 {
109 timestamp_prefix = level;
110 }
111 else
112 {
113 debug_level = 0;
114 g_hash_table_insert(debug_hash, g_strdup(name), GINT_TO_POINTER(level));
115 g_hash_table_foreach(debug_hash, debug_update_level, NULL);
116 }
117 }
118
119 struct debug *
120 debug_new(struct attr *parent, struct attr **attrs)
121 {
122 struct attr *name, *level;
123 name = attr_search(attrs, NULL, attr_name);
124 level = attr_search(attrs, NULL, attr_level);
125 #ifdef HAVE_SOCKET
126 if (!name && !level)
127 {
128 struct attr *socket_attr=attr_search(attrs, NULL, attr_socket);
129 char *p,*s;
130 if (!socket_attr)
131 return NULL;
132 s=g_strdup(socket_attr->u.str);
133 p=strchr(s,':');
134 if (!p)
135 {
136 g_free(s);
137 return NULL;
138 }
139 *p++='\0';
140 debug_sin.sin_family=AF_INET;
141 if (!inet_aton(s, &debug_sin.sin_addr))
142 {
143 g_free(s);
144 return NULL;
145 }
146 debug_sin.sin_port=ntohs(atoi(p));
147 if (debug_socket == -1)
148 debug_socket=socket(PF_INET, SOCK_DGRAM, 0);
149 g_free(s);
150 return (struct debug *)&dummy;
151 }
152 #endif
153 if (!name || !level)
154 return NULL;
155 debug_level_set(name->u.str, level->u.num);
156 return (struct debug *) &dummy;
157 }
158
159 int debug_level_get(const char *name)
160 {
161 if (!debug_hash)
162 return 0;
163 return GPOINTER_TO_INT(g_hash_table_lookup(debug_hash, name));
164 }
165
166 static void debug_timestamp(char *buffer)
167 {
168 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
169 LARGE_INTEGER counter, frequency;
170 double val;
171 QueryPerformanceCounter(&counter);
172 QueryPerformanceFrequency(&frequency);
173 val=counter.HighPart * 4294967296.0 + counter.LowPart;
174 val/=frequency.HighPart * 4294967296.0 + frequency.LowPart;
175 sprintf(buffer,"%.6f|",val);
176
177 #else
178 struct timeval tv;
179
180 if (gettimeofday(&tv, NULL) == -1)
181 return;
182 /* Timestamps are UTC */
183 sprintf(buffer, "%02d:%02d:%02d.%03d|", (int) (tv.tv_sec / 3600) % 24, (int) (tv.tv_sec / 60) % 60, (int) tv.tv_sec % 60, (int) tv.tv_usec / 1000);
184 #endif
185 }
186
187 void debug_vprintf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, va_list ap)
188 {
189 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
190 char buffer[4096];
191 #else
192 char buffer[mlen + flen + 3];
193 #endif
194 FILE *fp = debug_fp;
195
196 sprintf(buffer, "%s:%s", module, function);
197 if (debug_level_get(module) >= level || debug_level_get(buffer) >= level)
198 {
199 #if defined(DEBUG_WIN32_CE_MESSAGEBOX)
200 wchar_t muni[4096];
201 #endif
202 char xbuffer[4096];
203 xbuffer[0] = '\0';
204 if (prefix)
205 {
206 if (timestamp_prefix)
207 debug_timestamp(xbuffer);
208 strcpy(xbuffer + strlen(xbuffer), buffer);
209 strcpy(xbuffer + strlen(xbuffer), ":");
210 }
211 vsprintf(xbuffer + strlen(xbuffer), fmt, ap);
212 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
213 mbstowcs(muni, xbuffer, strlen(xbuffer)+1);
214 MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR);
215 #else
216 #ifdef HAVE_API_ANDROID
217 /*
218 * Android log priority values, in ascending priority order.
219 */
220 /*
221 typedef enum android_LogPriority
222 {
223 ANDROID_LOG_UNKNOWN = 0,
224 ANDROID_LOG_DEFAULT, // only for SetMinPriority()
225 ANDROID_LOG_VERBOSE,
226 ANDROID_LOG_DEBUG,
227 ANDROID_LOG_INFO,
228 ANDROID_LOG_WARN,
229 ANDROID_LOG_ERROR,
230 ANDROID_LOG_FATAL,
231 ANDROID_LOG_SILENT, // only for SetMinPriority(); must be last
232 } android_LogPriority;
233 */
234
235 __android_log_print(ANDROID_LOG_DEBUG,"navit", "%s", xbuffer);
236 #else
237 #ifdef HAVE_SOCKET
238 if (debug_socket != -1)
239 {
240 sendto(debug_socket, xbuffer, strlen(xbuffer), 0, (struct sockaddr *)&debug_sin, sizeof(debug_sin));
241 return;
242 }
243 #endif
244 if (!fp)
245 fp = stderr;
246 fprintf(fp, "%s", xbuffer);
247 fflush(fp);
248 #endif
249 #endif
250 }
251 }
252
253 void debug_printf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, ...)
254 {
255 #ifdef _DEBUG_BUILD_
256 va_list ap;
257 va_start(ap, fmt);
258 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
259 va_end(ap);
260 #endif
261 }
262
263 void debug_printf2(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, ...)
264 {
265 va_list ap;
266 va_start(ap, fmt);
267 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
268 va_end(ap);
269 }
270
271 void debug_assert_fail(const char *module, const int mlen, const char *function, const int flen, const char *file, int line, const char *expr)
272 {
273 debug_printf2(0, module, mlen, function, flen, 1, "%s:%d assertion failed:%s\n", file, line, expr);
274 abort();
275 }
276
277 void debug_destroy(void)
278 {
279 if (!debug_fp)
280 return;
281 if (debug_fp == stderr || debug_fp == stdout)
282 return;
283 fclose(debug_fp);
284 debug_fp = NULL;
285 }
286
287 void debug_set_logfile(const char *path)
288 {
289 FILE *fp;
290 fp = fopen(path, "a");
291 if (fp)
292 {
293 debug_destroy();
294 debug_fp = fp;
295 fprintf(debug_fp, "Navit log started\n");
296 fflush(debug_fp);
297 }
298 }
299
300 struct malloc_head
301 {
302 int magic;
303 int size;
304 char *where;
305 void *return_address[8];
306 struct malloc_head *prev;
307 struct malloc_head *next;
308 }*malloc_heads;
309
310 struct malloc_tail
311 {
312 int magic;
313 };
314
315 int mallocs, malloc_size, malloc_size_m;
316
317 void debug_dump_mallocs(void)
318 {
319 struct malloc_head *head = malloc_heads;
320 int i;
321 dbg(0, "mallocs %d\n", mallocs);
322 while (head)
323 {
324 fprintf(stderr, "unfreed malloc from %s of size %d\n", head->where, head->size);
325 for (i = 0; i < 8; i++)
326 fprintf(stderr, "\tlist *%p\n", head->return_address[i]);
327 #if 0
328 fprintf(stderr,"%s\n",head+1);
329 #endif
330 head = head->next;
331 }
332 }
333
334 void *
335 debug_malloc(const char *where, int line, const char *func, int size)
336 {
337 struct malloc_head *head;
338 struct malloc_tail *tail;
339 if (!size)
340 return NULL;
341 mallocs++;
342 malloc_size += size;
343 if (malloc_size / (1024 * 1024) != malloc_size_m)
344 {
345 malloc_size_m = malloc_size / (1024 * 1024);
346 dbg(0, "malloced %d kb\n", malloc_size / 1024);
347 }
348 head = malloc(size + sizeof(*head) + sizeof(*tail));
349 head->magic = 0xdeadbeef;
350 head->size = size;
351 head->prev = NULL;
352 head->next = malloc_heads;
353 malloc_heads = head;
354 if (head->next)
355 head->next->prev = head;
356 head->where = g_strdup_printf("%s:%d %s", where, line, func);
357 #if !defined (__GNUC__)
358 #define __builtin_return_address(x) NULL
359 #endif
360 head->return_address[0] = __builtin_return_address(0);
361 head->return_address[1] = __builtin_return_address(1);
362 head->return_address[2] = __builtin_return_address(2);
363 head->return_address[3] = __builtin_return_address(3);
364 head->return_address[4] = __builtin_return_address(4);
365 head->return_address[5] = __builtin_return_address(5);
366 head->return_address[6] = __builtin_return_address(6);
367 head->return_address[7] = __builtin_return_address(7);
368 head++;
369 tail = (struct malloc_tail *) ((unsigned char *) head + size);
370 tail->magic = 0xdeadbef0;
371 return head;
372 }
373
374 void *
375 debug_malloc0(const char *where, int line, const char *func, int size)
376 {
377 void *ret = debug_malloc(where, line, func, size);
378 if (ret)
379 memset(ret, 0, size);
380 return ret;
381 }
382
383 void *
384 debug_realloc(const char *where, int line, const char *func, void *ptr, int size)
385 {
386 void *ret = debug_malloc(where, line, func, size);
387 if (ret && ptr)
388 memcpy(ret, ptr, size);
389 debug_free(where, line, func, ptr);
390 return ret;
391 }
392
393 char *
394 debug_strdup(const char *where, int line, const char *func, const char *ptr)
395 {
396 int size;
397 char *ret;
398
399 if (!ptr)
400 return NULL;
401 size = strlen(ptr) + 1;
402 ret = debug_malloc(where, line, func, size);
403 memcpy(ret, ptr, size);
404 return ret;
405 }
406
407 char *
408 debug_guard(const char *where, int line, const char *func, char *str)
409 {
410 char *ret = debug_strdup(where, line, func, str);
411 g_free(str);
412 return ret;
413 }
414
415 void debug_free(const char *where, int line, const char *func, void *ptr)
416 {
417 struct malloc_head *head;
418 struct malloc_tail *tail;
419 if (!ptr)
420 return;
421 mallocs--;
422 head = (struct malloc_head *) ((unsigned char *) ptr - sizeof(*head));
423 tail = (struct malloc_tail *) ((unsigned char *) ptr + head->size);
424 malloc_size -= head->size;
425 if (head->magic != 0xdeadbeef || tail->magic != 0xdeadbef0)
426 {
427 fprintf(stderr, "Invalid free from %s:%d %s\n", where, line, func);
428 }
429 head->magic = 0;
430 tail->magic = 0;
431 if (head->prev)
432 head->prev->next = head->next;
433 else
434 malloc_heads = head->next;
435 if (head->next)
436 head->next->prev = head->prev;
437 free(head->where);
438 free(head);
439 }
440
441 void debug_free_func(void *ptr)
442 {
443 debug_free("unknown", 0, "unknown", ptr);
444 }
445
446 clock_t debug_measure_start(void)
447 {
448 clock_t start = clock();
449 return start;
450 }
451
452 clock_t debug_measure_end(clock_t start_time)
453 {
454 clock_t diff_time = clock() - start_time;
455 return diff_time;
456 }
457
458 int debug_measure_end_tsecs(clock_t start_time)
459 {
460 clock_t diff_time = clock() - start_time;
461 return (int) (((double) diff_time / (double) CLOCKS_PER_SEC) * 1000);
462 }
463
464 void debug_measure_result_str(clock_t diff, char *buffer)
465 {
466 sprintf(buffer, "elapsed: %fs\n", (diff / CLOCKS_PER_SEC));
467 }
468
469 void debug_mrp(const char* function_name, clock_t diff)
470 {
471 dbg(0, "el:(%s) %fs\n", function_name, (double) ((double) diff / (double) CLOCKS_PER_SEC));
472 }
473
474 void debug_finished(void)
475 {
476 debug_dump_mallocs();
477 g_free(gdb_program);
478 g_hash_table_destroy(debug_hash);
479 debug_destroy();
480 }
481

   
Visit the ZANavi Wiki