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

Contents of /navit/navit/debug.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki