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

Contents of /navit/navit/debug.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations) (download)
Sun Jun 17 08:12:47 2012 UTC (11 years, 10 months ago) by zoff99
File MIME type: text/plain
File size: 10813 byte(s)
lots of new stuff and fixes
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
54 int debug_level=0;
55 int segv_level=0;
56 int timestamp_prefix=0;
57
58 static int dummy;
59 static GHashTable *debug_hash;
60 static gchar *gdb_program;
61
62 static FILE *debug_fp;
63
64 #if defined(_WIN32) || defined(__CEGCC__)
65
66 static void sigsegv(int sig)
67 {
68 }
69
70 #else
71 #include <unistd.h>
72 static void sigsegv(int sig)
73 {
74 char buffer[256];
75 if (segv_level > 1)
76 sprintf(buffer, "gdb -ex bt %s %d", gdb_program, getpid());
77 else
78 sprintf(buffer, "gdb -ex bt -ex detach -ex quit %s %d", gdb_program, getpid());
79 system(buffer);
80 exit(1);
81 }
82 #endif
83
84 void
85 debug_init(const char *program_name)
86 {
87 gdb_program=g_strdup(program_name);
88 signal(SIGSEGV, sigsegv);
89 debug_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
90 debug_fp = stderr;
91 }
92
93
94 static void
95 debug_update_level(gpointer key, gpointer value, gpointer user_data)
96 {
97 if (debug_level < GPOINTER_TO_INT(value))
98 debug_level = GPOINTER_TO_INT(value);
99 }
100
101 void
102 debug_level_set(const char *name, int level)
103 {
104 if (!strcmp(name, "segv")) {
105 segv_level=level;
106 if (segv_level)
107 signal(SIGSEGV, sigsegv);
108 else
109 signal(SIGSEGV, NULL);
110 } else if (!strcmp(name, "timestamps")) {
111 timestamp_prefix=level;
112 } else {
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 struct attr *socket_attr=attr_search(attrs, NULL, attr_socket);
128 char *p,*s;
129 if (!socket_attr)
130 return NULL;
131 s=g_strdup(socket_attr->u.str);
132 p=strchr(s,':');
133 if (!p) {
134 g_free(s);
135 return NULL;
136 }
137 *p++='\0';
138 debug_sin.sin_family=AF_INET;
139 if (!inet_aton(s, &debug_sin.sin_addr)) {
140 g_free(s);
141 return NULL;
142 }
143 debug_sin.sin_port=ntohs(atoi(p));
144 if (debug_socket == -1)
145 debug_socket=socket(PF_INET, SOCK_DGRAM, 0);
146 g_free(s);
147 return (struct debug *)&dummy;
148 }
149 #endif
150 if (!name || !level)
151 return NULL;
152 debug_level_set(name->u.str, level->u.num);
153 return (struct debug *)&dummy;
154 }
155
156
157 int
158 debug_level_get(const char *name)
159 {
160 if (!debug_hash)
161 return 0;
162 return GPOINTER_TO_INT(g_hash_table_lookup(debug_hash, name));
163 }
164
165 static void debug_timestamp(char *buffer)
166 {
167 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
168 LARGE_INTEGER counter, frequency;
169 double val;
170 QueryPerformanceCounter(&counter);
171 QueryPerformanceFrequency(&frequency);
172 val=counter.HighPart * 4294967296.0 + counter.LowPart;
173 val/=frequency.HighPart * 4294967296.0 + frequency.LowPart;
174 sprintf(buffer,"%.6f|",val);
175
176 #else
177 struct timeval tv;
178
179 if (gettimeofday(&tv, NULL) == -1)
180 return;
181 /* Timestamps are UTC */
182 sprintf(buffer,
183 "%02d:%02d:%02d.%03d|",
184 (int)(tv.tv_sec/3600)%24,
185 (int)(tv.tv_sec/60)%60,
186 (int)tv.tv_sec % 60,
187 (int)tv.tv_usec/1000);
188 #endif
189 }
190
191 void
192 debug_vprintf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, va_list ap)
193 {
194 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
195 char buffer[4096];
196 #else
197 char buffer[mlen+flen+3];
198 #endif
199 FILE *fp=debug_fp;
200
201 sprintf(buffer, "%s:%s", module, function);
202 if (debug_level_get(module) >= level || debug_level_get(buffer) >= level) {
203 #if defined(DEBUG_WIN32_CE_MESSAGEBOX)
204 wchar_t muni[4096];
205 #endif
206 char xbuffer[4096];
207 xbuffer[0]='\0';
208 if (prefix) {
209 if (timestamp_prefix)
210 debug_timestamp(xbuffer);
211 strcpy(xbuffer+strlen(xbuffer),buffer);
212 strcpy(xbuffer+strlen(xbuffer),":");
213 }
214 vsprintf(xbuffer+strlen(xbuffer),fmt,ap);
215 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
216 mbstowcs(muni, xbuffer, strlen(xbuffer)+1);
217 MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR);
218 #else
219 #ifdef HAVE_API_ANDROID
220 __android_log_print(ANDROID_LOG_ERROR,"navit", "%s", xbuffer);
221 #else
222 #ifdef HAVE_SOCKET
223 if (debug_socket != -1) {
224 sendto(debug_socket, xbuffer, strlen(xbuffer), 0, (struct sockaddr *)&debug_sin, sizeof(debug_sin));
225 return;
226 }
227 #endif
228 if (! fp)
229 fp = stderr;
230 fprintf(fp,"%s",xbuffer);
231 fflush(fp);
232 #endif
233 #endif
234 }
235 }
236
237 void
238 debug_printf(int level, const char *module, const int mlen,const char *function, const int flen, int prefix, const char *fmt, ...)
239 {
240 #ifdef _DEBUG_BUILD_
241 va_list ap;
242 va_start(ap, fmt);
243 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
244 va_end(ap);
245 #endif
246 }
247
248 void
249 debug_printf2(int level, const char *module, const int mlen,const char *function, const int flen, int prefix, const char *fmt, ...)
250 {
251 va_list ap;
252 va_start(ap, fmt);
253 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
254 va_end(ap);
255 }
256
257 void
258 debug_assert_fail(const char *module, const int mlen,const char *function, const int flen, const char *file, int line, const char *expr)
259 {
260 debug_printf2(0,module,mlen,function,flen,1,"%s:%d assertion failed:%s\n", file, line, expr);
261 abort();
262 }
263
264 void
265 debug_destroy(void)
266 {
267 if (!debug_fp)
268 return;
269 if (debug_fp == stderr || debug_fp == stdout)
270 return;
271 fclose(debug_fp);
272 debug_fp = NULL;
273 }
274
275 void debug_set_logfile(const char *path)
276 {
277 FILE *fp;
278 fp = fopen(path, "a");
279 if (fp) {
280 debug_destroy();
281 debug_fp = fp;
282 fprintf(debug_fp, "Navit log started\n");
283 fflush(debug_fp);
284 }
285 }
286
287 struct malloc_head {
288 int magic;
289 int size;
290 char *where;
291 void *return_address[8];
292 struct malloc_head *prev;
293 struct malloc_head *next;
294 } *malloc_heads;
295
296 struct malloc_tail {
297 int magic;
298 };
299
300 int mallocs,malloc_size,malloc_size_m;
301
302 void
303 debug_dump_mallocs(void)
304 {
305 struct malloc_head *head=malloc_heads;
306 int i;
307 dbg(0,"mallocs %d\n",mallocs);
308 while (head) {
309 fprintf(stderr,"unfreed malloc from %s of size %d\n",head->where,head->size);
310 for (i = 0 ; i < 8 ; i++)
311 fprintf(stderr,"\tlist *%p\n",head->return_address[i]);
312 #if 0
313 fprintf(stderr,"%s\n",head+1);
314 #endif
315 head=head->next;
316 }
317 }
318
319 void *
320 debug_malloc(const char *where, int line, const char *func, int size)
321 {
322 struct malloc_head *head;
323 struct malloc_tail *tail;
324 if (!size)
325 return NULL;
326 mallocs++;
327 malloc_size+=size;
328 if (malloc_size/(1024*1024) != malloc_size_m) {
329 malloc_size_m=malloc_size/(1024*1024);
330 dbg(0,"malloced %d kb\n",malloc_size/1024);
331 }
332 head=malloc(size+sizeof(*head)+sizeof(*tail));
333 head->magic=0xdeadbeef;
334 head->size=size;
335 head->prev=NULL;
336 head->next=malloc_heads;
337 malloc_heads=head;
338 if (head->next)
339 head->next->prev=head;
340 head->where=g_strdup_printf("%s:%d %s",where,line,func);
341 #if !defined (__GNUC__)
342 #define __builtin_return_address(x) NULL
343 #endif
344 head->return_address[0]=__builtin_return_address(0);
345 head->return_address[1]=__builtin_return_address(1);
346 head->return_address[2]=__builtin_return_address(2);
347 head->return_address[3]=__builtin_return_address(3);
348 head->return_address[4]=__builtin_return_address(4);
349 head->return_address[5]=__builtin_return_address(5);
350 head->return_address[6]=__builtin_return_address(6);
351 head->return_address[7]=__builtin_return_address(7);
352 head++;
353 tail=(struct malloc_tail *)((unsigned char *)head+size);
354 tail->magic=0xdeadbef0;
355 return head;
356 }
357
358
359 void *
360 debug_malloc0(const char *where, int line, const char *func, int size)
361 {
362 void *ret=debug_malloc(where, line, func, size);
363 if (ret)
364 memset(ret, 0, size);
365 return ret;
366 }
367
368 void *
369 debug_realloc(const char *where, int line, const char *func, void *ptr, int size)
370 {
371 void *ret=debug_malloc(where, line, func, size);
372 if (ret && ptr)
373 memcpy(ret, ptr, size);
374 debug_free(where, line, func, ptr);
375 return ret;
376 }
377
378 char *
379 debug_strdup(const char *where, int line, const char *func, const char *ptr)
380 {
381 int size;
382 char *ret;
383
384 if (!ptr)
385 return NULL;
386 size=strlen(ptr)+1;
387 ret=debug_malloc(where, line, func, size);
388 memcpy(ret, ptr, size);
389 return ret;
390 }
391
392 char *
393 debug_guard(const char *where, int line, const char *func, char *str)
394 {
395 char *ret=debug_strdup(where, line, func, str);
396 g_free(str);
397 return ret;
398 }
399
400 void
401 debug_free(const char *where, int line, const char *func, void *ptr)
402 {
403 struct malloc_head *head;
404 struct malloc_tail *tail;
405 if (!ptr)
406 return;
407 mallocs--;
408 head=(struct malloc_head *)((unsigned char *)ptr-sizeof(*head));
409 tail=(struct malloc_tail *)((unsigned char *)ptr+head->size);
410 malloc_size-=head->size;
411 if (head->magic != 0xdeadbeef || tail->magic != 0xdeadbef0) {
412 fprintf(stderr,"Invalid free from %s:%d %s\n",where,line,func);
413 }
414 head->magic=0;
415 tail->magic=0;
416 if (head->prev)
417 head->prev->next=head->next;
418 else
419 malloc_heads=head->next;
420 if (head->next)
421 head->next->prev=head->prev;
422 free(head->where);
423 free(head);
424 }
425
426 void
427 debug_free_func(void *ptr)
428 {
429 debug_free("unknown",0,"unknown",ptr);
430 }
431
432 clock_t
433 debug_measure_start(void)
434 {
435 clock_t start = clock();
436 return start;
437 }
438
439 clock_t
440 debug_measure_end(clock_t start_time)
441 {
442 clock_t diff_time = clock() - start_time;
443 return diff_time;
444 }
445
446 int
447 debug_measure_end_tsecs(clock_t start_time)
448 {
449 clock_t diff_time = clock() - start_time;
450 return (int)( ((double)diff_time / (double)CLOCKS_PER_SEC)*1000 );
451 }
452
453 void
454 debug_measure_result_str(clock_t diff, char *buffer)
455 {
456 sprintf(buffer, "elapsed: %fs\n", (diff / CLOCKS_PER_SEC));
457 }
458
459 void
460 debug_mrp(const char* function_name, clock_t diff)
461 {
462 dbg(0, "el:(%s) %fs\n", function_name, (double)((double)diff / (double)CLOCKS_PER_SEC));
463 }
464
465 void debug_finished(void)
466 {
467 debug_dump_mallocs();
468 g_free(gdb_program);
469 g_hash_table_destroy(debug_hash);
470 debug_destroy();
471 }
472

   
Visit the ZANavi Wiki