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

Contents of /navit/navit/debug.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (show annotations) (download)
Mon Dec 12 13:41:30 2016 UTC (7 years, 3 months ago) by zoff99
File MIME type: text/plain
File size: 15069 byte(s)
v2.0.56
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 extern long global_last_spoken_base;
36
37 #ifdef HAVE_API_ANDROID
38 #include <android/log.h>
39 #endif
40
41 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
42 #include <windows.h>
43 #include <windowsx.h>
44 #endif
45
46 #ifdef HAVE_SOCKET
47 #include <stdlib.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 static int debug_socket=-1;
52 static struct sockaddr_in debug_sin;
53 #endif
54
55 int debug_level = 0;
56 int segv_level = 0;
57 int timestamp_prefix = 0;
58
59 int global_func_indent_counter = -1;
60 const char* global_func_indent_spaces = " ";
61
62 static int dummy;
63 static GHashTable *debug_hash;
64 static gchar *gdb_program;
65
66 static FILE *debug_fp;
67
68 // func def ------ this is bad!!
69 void android_send_generic_text(int id, char *text);
70 // func def ------ this is bad!!
71
72 #if defined(_WIN32) || defined(__CEGCC__)
73
74 static void sigsegv(int sig)
75 {
76 }
77
78 #else
79 #include <unistd.h>
80 static void sigsegv(int sig)
81 {
82 char buffer[256];
83 if (segv_level > 1)
84 sprintf(buffer, "gdb -ex bt %s %d", gdb_program, getpid());
85 else
86 sprintf(buffer, "gdb -ex bt -ex detach -ex quit %s %d", gdb_program, getpid());
87 system(buffer);
88 exit(1);
89 }
90 #endif
91
92 void debug_init(const char *program_name)
93 {
94 // gdb_program = g_strdup(program_name); // L
95 // signal(SIGSEGV, sigsegv); // L
96 debug_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free_func, NULL);
97 debug_fp = stderr;
98 }
99
100 static void debug_update_level(gpointer key, gpointer value, gpointer user_data)
101 {
102 if (debug_level < GPOINTER_TO_INT(value))
103 debug_level = GPOINTER_TO_INT(value);
104 }
105
106 void debug_level_set(const char *name, int level)
107 {
108 if (!strcmp(name, "segv"))
109 {
110 segv_level = level;
111 if (segv_level)
112 signal(SIGSEGV, sigsegv);
113 else
114 signal(SIGSEGV, NULL);
115 }
116 else if (!strcmp(name, "timestamps"))
117 {
118 timestamp_prefix = level;
119 }
120 else
121 {
122 debug_level = 0;
123 g_hash_table_insert(debug_hash, g_strdup(name), GINT_TO_POINTER(level));
124 g_hash_table_foreach(debug_hash, debug_update_level, NULL);
125 }
126 }
127
128 struct debug *
129 debug_new(struct attr *parent, struct attr **attrs)
130 {
131 struct attr *name, *level;
132 name = attr_search(attrs, NULL, attr_name);
133 level = attr_search(attrs, NULL, attr_level);
134 #ifdef HAVE_SOCKET
135 if (!name && !level)
136 {
137 struct attr *socket_attr=attr_search(attrs, NULL, attr_socket);
138 char *p,*s;
139
140 if (!socket_attr)
141 return NULL;
142
143 s=g_strdup(socket_attr->u.str);
144 p=strchr(s,':');
145 if (!p)
146 {
147 g_free(s);
148 return NULL;
149 }
150 *p++='\0';
151 debug_sin.sin_family=AF_INET;
152 if (!inet_aton(s, &debug_sin.sin_addr))
153 {
154 g_free(s);
155 return NULL;
156 }
157 debug_sin.sin_port=ntohs(atoi(p));
158 if (debug_socket == -1)
159 debug_socket=socket(PF_INET, SOCK_DGRAM, 0);
160 g_free(s);
161 return (struct debug *)&dummy;
162 }
163 #endif
164 if (!name || !level)
165 return NULL;
166
167 debug_level_set(name->u.str, level->u.num);
168
169 return (struct debug *) &dummy;
170 }
171
172 int debug_level_get(const char *name)
173 {
174 if (!debug_hash)
175 return 0;
176
177 return GPOINTER_TO_INT(g_hash_table_lookup(debug_hash, name));
178 }
179
180 void debug_get_timestamp_millis(long *ts_millis)
181 {
182
183 // struct timeval
184 // {
185 // time_t tv_sec; /* seconds */
186 // suseconds_t tv_usec; /* microseconds */
187 // };
188
189 struct timeval tv;
190
191 if (gettimeofday(&tv, NULL) == -1)
192 {
193 ts_millis = -1;
194 return;
195 }
196
197 if (global_last_spoken_base != 0)
198 {
199 *ts_millis = (((long)tv.tv_sec - global_last_spoken_base) * 1000) + ((int)tv.tv_usec / 1000);
200 }
201 else
202 {
203 *ts_millis = ((long)tv.tv_sec * 1000) + ((int)tv.tv_usec / 1000);
204 }
205 }
206
207
208 static void debug_timestamp(char *buffer)
209 {
210 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
211 LARGE_INTEGER counter, frequency;
212 double val;
213 QueryPerformanceCounter(&counter);
214 QueryPerformanceFrequency(&frequency);
215 val=counter.HighPart * 4294967296.0 + counter.LowPart;
216 val/=frequency.HighPart * 4294967296.0 + frequency.LowPart;
217 sprintf(buffer,"%.6f|",val);
218
219 #else
220 struct timeval tv;
221
222 if (gettimeofday(&tv, NULL) == -1)
223 return;
224 /* Timestamps are UTC */
225 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);
226 #endif
227 }
228
229 #ifdef HAVE_API_ANDROID
230
231 /* Android log priority values, in ascending priority order. */
232 /*
233 typedef enum android_LogPriority {
234 ANDROID_LOG_UNKNOWN = 0,
235 ANDROID_LOG_DEFAULT,
236 ANDROID_LOG_VERBOSE,
237 ANDROID_LOG_DEBUG,
238 ANDROID_LOG_INFO,
239 ANDROID_LOG_WARN,
240 ANDROID_LOG_ERROR,
241 ANDROID_LOG_FATAL,
242 ANDROID_LOG_SILENT,
243 } android_LogPriority;
244 */
245
246 static android_LogPriority
247 dbg_level_to_android(dbg_level level)
248 {
249 switch(level) {
250 case lvl_unset:
251 return ANDROID_LOG_UNKNOWN;
252 case lvl_error:
253 return ANDROID_LOG_ERROR;
254 case lvl_warning:
255 return ANDROID_LOG_WARN;
256 case lvl_info:
257 return ANDROID_LOG_INFO;
258 case lvl_debug:
259 return ANDROID_LOG_DEBUG;
260 }
261 return ANDROID_LOG_UNKNOWN;
262 }
263 #endif
264
265 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)
266 {
267 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
268 char buffer[4096];
269 #else
270 char buffer[mlen + flen + 3];
271 #endif
272
273 sprintf(buffer, "%s:%s", module, function);
274 if (debug_level_get(module) >= level || debug_level_get(buffer) >= level)
275 {
276 #if defined(DEBUG_WIN32_CE_MESSAGEBOX)
277 wchar_t muni[4096];
278 #endif
279 char xbuffer[4096];
280 xbuffer[0] = '\0';
281 if (prefix)
282 {
283 if (timestamp_prefix)
284 debug_timestamp(xbuffer);
285 strcpy(xbuffer + strlen(xbuffer), buffer);
286 strcpy(xbuffer + strlen(xbuffer), ":");
287 }
288 vsprintf(xbuffer + strlen(xbuffer), fmt, ap);
289 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
290 mbstowcs(muni, xbuffer, strlen(xbuffer)+1);
291 MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR);
292 #else
293 #ifdef HAVE_API_ANDROID
294 __android_log_print(dbg_level_to_android(lvl_info), "navit", "%s", xbuffer);
295 #else
296 #ifdef HAVE_SOCKET
297 if (debug_socket != -1)
298 {
299 sendto(debug_socket, xbuffer, strlen(xbuffer), 0, (struct sockaddr *)&debug_sin, sizeof(debug_sin));
300 return;
301 }
302 #endif
303 FILE *fp = debug_fp;
304
305 if (!fp)
306 {
307 fp = stderr;
308 }
309
310 fprintf(fp, "%s", xbuffer);
311 fflush(fp);
312 #endif
313 #endif
314 }
315 }
316
317
318
319 void debug_vprintf_func(int level, int indent, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, va_list ap)
320 {
321 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
322 char buffer[4096];
323 #else
324 char buffer[mlen + flen + 3];
325 #endif
326
327 sprintf(buffer, "FUNC:%.*s%s:%s", abs(2 * indent), global_func_indent_spaces, module, function);
328 if (debug_level_get(module) >= level || debug_level_get(buffer) >= level)
329 {
330 #if defined(DEBUG_WIN32_CE_MESSAGEBOX)
331 wchar_t muni[4096];
332 #endif
333 char xbuffer[4096];
334 xbuffer[0] = '\0';
335 if (prefix)
336 {
337 if (timestamp_prefix)
338 debug_timestamp(xbuffer);
339 strcpy(xbuffer + strlen(xbuffer), buffer);
340 strcpy(xbuffer + strlen(xbuffer), ":");
341 }
342 vsprintf(xbuffer + strlen(xbuffer), fmt, ap);
343 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
344 mbstowcs(muni, xbuffer, strlen(xbuffer)+1);
345 MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR);
346 #else
347 #ifdef HAVE_API_ANDROID
348 __android_log_print(dbg_level_to_android(lvl_info), "navit", "%s", xbuffer);
349 #else
350 #ifdef HAVE_SOCKET
351 if (debug_socket != -1)
352 {
353 sendto(debug_socket, xbuffer, strlen(xbuffer), 0, (struct sockaddr *)&debug_sin, sizeof(debug_sin));
354 return;
355 }
356 #endif
357 FILE *fp = debug_fp;
358
359 if (!fp)
360 {
361 fp = stderr;
362 }
363
364 fprintf(fp, "%s", xbuffer);
365 fflush(fp);
366 #endif
367 #endif
368 }
369 }
370
371
372 void debug_for_tests_vprintf(int level, const char *fmt, va_list ap)
373 {
374 #ifdef _CIDEBUG_BUILD_
375 #ifdef HAVE_API_ANDROID
376 char *xbuffer = g_malloc(40960);
377 xbuffer[0] = '\0';
378 vsprintf(xbuffer, fmt, ap);
379 android_send_generic_text(32, xbuffer);
380 g_free(xbuffer);
381 #endif
382 #endif
383 }
384
385
386 void debug_for_tests2_vprintf(int level, const char *fmt, va_list ap)
387 {
388 #ifdef HAVE_API_ANDROID
389 char *xbuffer = g_malloc(40960);
390 xbuffer[0] = '\0';
391 vsprintf(xbuffer, fmt, ap);
392 android_send_generic_text(33, xbuffer);
393 g_free(xbuffer);
394 #endif
395 }
396
397 void debug_for_tests2_printf(int level, const char *fmt, ...)
398 {
399 #ifdef HAVE_API_ANDROID
400 va_list ap;
401 va_start(ap, fmt);
402 debug_for_tests2_vprintf(level, fmt, ap);
403 va_end(ap);
404 #endif
405 }
406
407
408 void debug_for_tests_printf(int level, const char *fmt, ...)
409 {
410 #ifdef _CIDEBUG_BUILD_
411 #ifdef HAVE_API_ANDROID
412 va_list ap;
413 va_start(ap, fmt);
414 debug_for_tests_vprintf(level, fmt, ap);
415 va_end(ap);
416 #endif
417 #endif
418 }
419
420 void debug_printf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, ...)
421 {
422 #ifdef _DEBUG_BUILD_
423 va_list ap;
424 va_start(ap, fmt);
425 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
426 va_end(ap);
427 #endif
428 }
429
430 void debug_printf_func(int level, int indent, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, ...)
431 {
432 #ifdef _DEBUG_BUILD_
433 va_list ap;
434 va_start(ap, fmt);
435 debug_vprintf_func(level, indent, module, mlen, function, flen, prefix, fmt, ap);
436 va_end(ap);
437 #endif
438 }
439
440 void debug_printf2(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, ...)
441 {
442 va_list ap;
443 va_start(ap, fmt);
444 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
445 va_end(ap);
446 }
447
448 void debug_assert_fail(const char *module, const int mlen, const char *function, const int flen, const char *file, int line, const char *expr)
449 {
450 debug_printf2(0, module, mlen, function, flen, 1, "%s:%d assertion failed:%s\n", file, line, expr);
451 abort();
452 }
453
454 void debug_destroy(void)
455 {
456 if (!debug_fp)
457 return;
458 if (debug_fp == stderr || debug_fp == stdout)
459 return;
460 fclose(debug_fp);
461 debug_fp = NULL;
462 }
463
464 void debug_set_logfile(const char *path)
465 {
466 FILE *fp;
467 fp = fopen(path, "a");
468 if (fp)
469 {
470 debug_destroy();
471 debug_fp = fp;
472 fprintf(debug_fp, "Navit log started\n");
473 fflush(debug_fp);
474 }
475 }
476
477 struct malloc_head
478 {
479 int magic;
480 int size;
481 char *where;
482 void *return_address[8];
483 struct malloc_head *prev;
484 struct malloc_head *next;
485 }*malloc_heads;
486
487 struct malloc_tail
488 {
489 int magic;
490 };
491
492 int mallocs, malloc_size, malloc_size_m;
493
494 void debug_dump_mallocs(void)
495 {
496 struct malloc_head *head = malloc_heads;
497 int i;
498 dbg(0, "mallocs %d\n", mallocs);
499 while (head)
500 {
501 fprintf(stderr, "unfreed malloc from %s of size %d\n", head->where, head->size);
502 for (i = 0; i < 8; i++)
503 fprintf(stderr, "\tlist *%p\n", head->return_address[i]);
504 #if 0
505 fprintf(stderr,"%s\n",head+1);
506 #endif
507 head = head->next;
508 }
509 }
510
511 void *
512 debug_malloc(const char *where, int line, const char *func, int size)
513 {
514 struct malloc_head *head;
515 struct malloc_tail *tail;
516 if (!size)
517 return NULL;
518 mallocs++;
519 malloc_size += size;
520 if (malloc_size / (1024 * 1024) != malloc_size_m)
521 {
522 malloc_size_m = malloc_size / (1024 * 1024);
523 dbg(0, "malloced %d kb\n", malloc_size / 1024);
524 }
525 head = malloc(size + sizeof(*head) + sizeof(*tail));
526 head->magic = 0xdeadbeef;
527 head->size = size;
528 head->prev = NULL;
529 head->next = malloc_heads;
530 malloc_heads = head;
531 if (head->next)
532 head->next->prev = head;
533 head->where = g_strdup_printf("%s:%d %s", where, line, func);
534 #if !defined (__GNUC__)
535 #define __builtin_return_address(x) NULL
536 #endif
537 head->return_address[0] = __builtin_return_address(0);
538 head->return_address[1] = __builtin_return_address(1);
539 head->return_address[2] = __builtin_return_address(2);
540 head->return_address[3] = __builtin_return_address(3);
541 head->return_address[4] = __builtin_return_address(4);
542 head->return_address[5] = __builtin_return_address(5);
543 head->return_address[6] = __builtin_return_address(6);
544 head->return_address[7] = __builtin_return_address(7);
545 head++;
546 tail = (struct malloc_tail *) ((unsigned char *) head + size);
547 tail->magic = 0xdeadbef0;
548 return head;
549 }
550
551 void *
552 debug_malloc0(const char *where, int line, const char *func, int size)
553 {
554 void *ret = debug_malloc(where, line, func, size);
555 if (ret)
556 memset(ret, 0, size);
557 return ret;
558 }
559
560 void *
561 debug_realloc(const char *where, int line, const char *func, void *ptr, int size)
562 {
563 void *ret = debug_malloc(where, line, func, size);
564 if (ret && ptr)
565 memcpy(ret, ptr, size);
566 debug_free(where, line, func, ptr);
567 return ret;
568 }
569
570 char *
571 debug_strdup(const char *where, int line, const char *func, const char *ptr)
572 {
573 int size;
574 char *ret;
575
576 if (!ptr)
577 return NULL;
578 size = strlen(ptr) + 1;
579 ret = debug_malloc(where, line, func, size);
580 memcpy(ret, ptr, size);
581 return ret;
582 }
583
584 char *
585 debug_guard(const char *where, int line, const char *func, char *str)
586 {
587 char *ret = debug_strdup(where, line, func, str);
588 g_free(str);
589 return ret;
590 }
591
592 void debug_free(const char *where, int line, const char *func, void *ptr)
593 {
594 struct malloc_head *head;
595 struct malloc_tail *tail;
596 if (!ptr)
597 return;
598 mallocs--;
599 head = (struct malloc_head *) ((unsigned char *) ptr - sizeof(*head));
600 tail = (struct malloc_tail *) ((unsigned char *) ptr + head->size);
601 malloc_size -= head->size;
602 if (head->magic != 0xdeadbeef || tail->magic != 0xdeadbef0)
603 {
604 fprintf(stderr, "Invalid free from %s:%d %s\n", where, line, func);
605 }
606 head->magic = 0;
607 tail->magic = 0;
608 if (head->prev)
609 head->prev->next = head->next;
610 else
611 malloc_heads = head->next;
612 if (head->next)
613 head->next->prev = head->prev;
614 free(head->where);
615 free(head);
616 }
617
618 void debug_free_func(void *ptr)
619 {
620 debug_free("unknown", 0, "unknown", ptr);
621 }
622
623 clock_t debug_measure_start(void)
624 {
625 clock_t start = clock();
626 return start;
627 }
628
629 clock_t debug_measure_end(clock_t start_time)
630 {
631 clock_t diff_time = clock() - start_time;
632 return diff_time;
633 }
634
635 int debug_measure_end_tsecs(clock_t start_time)
636 {
637 clock_t diff_time = clock() - start_time;
638 return (int) (((double) diff_time / (double) CLOCKS_PER_SEC) * 1000);
639 }
640
641 void debug_measure_result_str(clock_t diff, char *buffer)
642 {
643 sprintf(buffer, "elapsed: %fs\n", (diff / CLOCKS_PER_SEC));
644 }
645
646 void debug_mrp(const char* function_name, clock_t diff)
647 {
648 dbg(0, "el:(%s) %fs\n", function_name, (double) ((double) diff / (double) CLOCKS_PER_SEC));
649 }
650
651 void debug_finished(void)
652 {
653 debug_dump_mallocs();
654 g_free(gdb_program);
655 g_hash_table_destroy(debug_hash);
656 debug_destroy();
657 }
658
659

   
Visit the ZANavi Wiki