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

Contents of /navit/navit/debug.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 51 - (show annotations) (download)
Mon Jul 25 19:29:08 2016 UTC (7 years, 8 months ago) by zoff99
File MIME type: text/plain
File size: 14633 byte(s)
v2.0.52
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_tests_printf(int level, const char *fmt, ...)
387 {
388 #ifdef _CIDEBUG_BUILD_
389 #ifdef HAVE_API_ANDROID
390 va_list ap;
391 va_start(ap, fmt);
392 debug_for_tests_vprintf(level, fmt, ap);
393 va_end(ap);
394 #endif
395 #endif
396 }
397
398 void debug_printf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, ...)
399 {
400 #ifdef _DEBUG_BUILD_
401 va_list ap;
402 va_start(ap, fmt);
403 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
404 va_end(ap);
405 #endif
406 }
407
408 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, ...)
409 {
410 #ifdef _DEBUG_BUILD_
411 va_list ap;
412 va_start(ap, fmt);
413 debug_vprintf_func(level, indent, module, mlen, function, flen, prefix, fmt, ap);
414 va_end(ap);
415 #endif
416 }
417
418 void debug_printf2(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, ...)
419 {
420 va_list ap;
421 va_start(ap, fmt);
422 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
423 va_end(ap);
424 }
425
426 void debug_assert_fail(const char *module, const int mlen, const char *function, const int flen, const char *file, int line, const char *expr)
427 {
428 debug_printf2(0, module, mlen, function, flen, 1, "%s:%d assertion failed:%s\n", file, line, expr);
429 abort();
430 }
431
432 void debug_destroy(void)
433 {
434 if (!debug_fp)
435 return;
436 if (debug_fp == stderr || debug_fp == stdout)
437 return;
438 fclose(debug_fp);
439 debug_fp = NULL;
440 }
441
442 void debug_set_logfile(const char *path)
443 {
444 FILE *fp;
445 fp = fopen(path, "a");
446 if (fp)
447 {
448 debug_destroy();
449 debug_fp = fp;
450 fprintf(debug_fp, "Navit log started\n");
451 fflush(debug_fp);
452 }
453 }
454
455 struct malloc_head
456 {
457 int magic;
458 int size;
459 char *where;
460 void *return_address[8];
461 struct malloc_head *prev;
462 struct malloc_head *next;
463 }*malloc_heads;
464
465 struct malloc_tail
466 {
467 int magic;
468 };
469
470 int mallocs, malloc_size, malloc_size_m;
471
472 void debug_dump_mallocs(void)
473 {
474 struct malloc_head *head = malloc_heads;
475 int i;
476 dbg(0, "mallocs %d\n", mallocs);
477 while (head)
478 {
479 fprintf(stderr, "unfreed malloc from %s of size %d\n", head->where, head->size);
480 for (i = 0; i < 8; i++)
481 fprintf(stderr, "\tlist *%p\n", head->return_address[i]);
482 #if 0
483 fprintf(stderr,"%s\n",head+1);
484 #endif
485 head = head->next;
486 }
487 }
488
489 void *
490 debug_malloc(const char *where, int line, const char *func, int size)
491 {
492 struct malloc_head *head;
493 struct malloc_tail *tail;
494 if (!size)
495 return NULL;
496 mallocs++;
497 malloc_size += size;
498 if (malloc_size / (1024 * 1024) != malloc_size_m)
499 {
500 malloc_size_m = malloc_size / (1024 * 1024);
501 dbg(0, "malloced %d kb\n", malloc_size / 1024);
502 }
503 head = malloc(size + sizeof(*head) + sizeof(*tail));
504 head->magic = 0xdeadbeef;
505 head->size = size;
506 head->prev = NULL;
507 head->next = malloc_heads;
508 malloc_heads = head;
509 if (head->next)
510 head->next->prev = head;
511 head->where = g_strdup_printf("%s:%d %s", where, line, func);
512 #if !defined (__GNUC__)
513 #define __builtin_return_address(x) NULL
514 #endif
515 head->return_address[0] = __builtin_return_address(0);
516 head->return_address[1] = __builtin_return_address(1);
517 head->return_address[2] = __builtin_return_address(2);
518 head->return_address[3] = __builtin_return_address(3);
519 head->return_address[4] = __builtin_return_address(4);
520 head->return_address[5] = __builtin_return_address(5);
521 head->return_address[6] = __builtin_return_address(6);
522 head->return_address[7] = __builtin_return_address(7);
523 head++;
524 tail = (struct malloc_tail *) ((unsigned char *) head + size);
525 tail->magic = 0xdeadbef0;
526 return head;
527 }
528
529 void *
530 debug_malloc0(const char *where, int line, const char *func, int size)
531 {
532 void *ret = debug_malloc(where, line, func, size);
533 if (ret)
534 memset(ret, 0, size);
535 return ret;
536 }
537
538 void *
539 debug_realloc(const char *where, int line, const char *func, void *ptr, int size)
540 {
541 void *ret = debug_malloc(where, line, func, size);
542 if (ret && ptr)
543 memcpy(ret, ptr, size);
544 debug_free(where, line, func, ptr);
545 return ret;
546 }
547
548 char *
549 debug_strdup(const char *where, int line, const char *func, const char *ptr)
550 {
551 int size;
552 char *ret;
553
554 if (!ptr)
555 return NULL;
556 size = strlen(ptr) + 1;
557 ret = debug_malloc(where, line, func, size);
558 memcpy(ret, ptr, size);
559 return ret;
560 }
561
562 char *
563 debug_guard(const char *where, int line, const char *func, char *str)
564 {
565 char *ret = debug_strdup(where, line, func, str);
566 g_free(str);
567 return ret;
568 }
569
570 void debug_free(const char *where, int line, const char *func, void *ptr)
571 {
572 struct malloc_head *head;
573 struct malloc_tail *tail;
574 if (!ptr)
575 return;
576 mallocs--;
577 head = (struct malloc_head *) ((unsigned char *) ptr - sizeof(*head));
578 tail = (struct malloc_tail *) ((unsigned char *) ptr + head->size);
579 malloc_size -= head->size;
580 if (head->magic != 0xdeadbeef || tail->magic != 0xdeadbef0)
581 {
582 fprintf(stderr, "Invalid free from %s:%d %s\n", where, line, func);
583 }
584 head->magic = 0;
585 tail->magic = 0;
586 if (head->prev)
587 head->prev->next = head->next;
588 else
589 malloc_heads = head->next;
590 if (head->next)
591 head->next->prev = head->prev;
592 free(head->where);
593 free(head);
594 }
595
596 void debug_free_func(void *ptr)
597 {
598 debug_free("unknown", 0, "unknown", ptr);
599 }
600
601 clock_t debug_measure_start(void)
602 {
603 clock_t start = clock();
604 return start;
605 }
606
607 clock_t debug_measure_end(clock_t start_time)
608 {
609 clock_t diff_time = clock() - start_time;
610 return diff_time;
611 }
612
613 int debug_measure_end_tsecs(clock_t start_time)
614 {
615 clock_t diff_time = clock() - start_time;
616 return (int) (((double) diff_time / (double) CLOCKS_PER_SEC) * 1000);
617 }
618
619 void debug_measure_result_str(clock_t diff, char *buffer)
620 {
621 sprintf(buffer, "elapsed: %fs\n", (diff / CLOCKS_PER_SEC));
622 }
623
624 void debug_mrp(const char* function_name, clock_t diff)
625 {
626 dbg(0, "el:(%s) %fs\n", function_name, (double) ((double) diff / (double) CLOCKS_PER_SEC));
627 }
628
629 void debug_finished(void)
630 {
631 debug_dump_mallocs();
632 g_free(gdb_program);
633 g_hash_table_destroy(debug_hash);
634 debug_destroy();
635 }
636
637

   
Visit the ZANavi Wiki