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

Contents of /navit/navit/debug.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (11 years, 3 months ago) by zoff99
File MIME type: text/plain
File size: 10182 byte(s)
import files
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 #ifdef _DEBUG_BUILD_
242 va_list ap;
243 va_start(ap, fmt);
244 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
245 va_end(ap);
246 #endif
247 }
248
249 void
250 debug_printf2(int level, const char *module, const int mlen,const char *function, const int flen, int prefix, const char *fmt, ...)
251 {
252 va_list ap;
253 va_start(ap, fmt);
254 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
255 va_end(ap);
256 }
257
258 void
259 debug_assert_fail(const char *module, const int mlen,const char *function, const int flen, const char *file, int line, const char *expr)
260 {
261 debug_printf2(0,module,mlen,function,flen,1,"%s:%d assertion failed:%s\n", file, line, expr);
262 abort();
263 }
264
265 void
266 debug_destroy(void)
267 {
268 if (!debug_fp)
269 return;
270 if (debug_fp == stderr || debug_fp == stdout)
271 return;
272 fclose(debug_fp);
273 debug_fp = NULL;
274 }
275
276 void debug_set_logfile(const char *path)
277 {
278 FILE *fp;
279 fp = fopen(path, "a");
280 if (fp) {
281 debug_destroy();
282 debug_fp = fp;
283 fprintf(debug_fp, "Navit log started\n");
284 fflush(debug_fp);
285 }
286 }
287
288 struct malloc_head {
289 int magic;
290 int size;
291 char *where;
292 void *return_address[8];
293 struct malloc_head *prev;
294 struct malloc_head *next;
295 } *malloc_heads;
296
297 struct malloc_tail {
298 int magic;
299 };
300
301 int mallocs,malloc_size,malloc_size_m;
302
303 void
304 debug_dump_mallocs(void)
305 {
306 struct malloc_head *head=malloc_heads;
307 int i;
308 dbg(0,"mallocs %d\n",mallocs);
309 while (head) {
310 fprintf(stderr,"unfreed malloc from %s of size %d\n",head->where,head->size);
311 for (i = 0 ; i < 8 ; i++)
312 fprintf(stderr,"\tlist *%p\n",head->return_address[i]);
313 #if 0
314 fprintf(stderr,"%s\n",head+1);
315 #endif
316 head=head->next;
317 }
318 }
319
320 void *
321 debug_malloc(const char *where, int line, const char *func, int size)
322 {
323 struct malloc_head *head;
324 struct malloc_tail *tail;
325 if (!size)
326 return NULL;
327 mallocs++;
328 malloc_size+=size;
329 if (malloc_size/(1024*1024) != malloc_size_m) {
330 malloc_size_m=malloc_size/(1024*1024);
331 dbg(0,"malloced %d kb\n",malloc_size/1024);
332 }
333 head=malloc(size+sizeof(*head)+sizeof(*tail));
334 head->magic=0xdeadbeef;
335 head->size=size;
336 head->prev=NULL;
337 head->next=malloc_heads;
338 malloc_heads=head;
339 if (head->next)
340 head->next->prev=head;
341 head->where=g_strdup_printf("%s:%d %s",where,line,func);
342 #if !defined (__GNUC__)
343 #define __builtin_return_address(x) NULL
344 #endif
345 head->return_address[0]=__builtin_return_address(0);
346 head->return_address[1]=__builtin_return_address(1);
347 head->return_address[2]=__builtin_return_address(2);
348 head->return_address[3]=__builtin_return_address(3);
349 head->return_address[4]=__builtin_return_address(4);
350 head->return_address[5]=__builtin_return_address(5);
351 head->return_address[6]=__builtin_return_address(6);
352 head->return_address[7]=__builtin_return_address(7);
353 head++;
354 tail=(struct malloc_tail *)((unsigned char *)head+size);
355 tail->magic=0xdeadbef0;
356 return head;
357 }
358
359
360 void *
361 debug_malloc0(const char *where, int line, const char *func, int size)
362 {
363 void *ret=debug_malloc(where, line, func, size);
364 if (ret)
365 memset(ret, 0, size);
366 return ret;
367 }
368
369 void *
370 debug_realloc(const char *where, int line, const char *func, void *ptr, int size)
371 {
372 void *ret=debug_malloc(where, line, func, size);
373 if (ret && ptr)
374 memcpy(ret, ptr, size);
375 debug_free(where, line, func, ptr);
376 return ret;
377 }
378
379 char *
380 debug_strdup(const char *where, int line, const char *func, const char *ptr)
381 {
382 int size;
383 char *ret;
384
385 if (!ptr)
386 return NULL;
387 size=strlen(ptr)+1;
388 ret=debug_malloc(where, line, func, size);
389 memcpy(ret, ptr, size);
390 return ret;
391 }
392
393 char *
394 debug_guard(const char *where, int line, const char *func, char *str)
395 {
396 char *ret=debug_strdup(where, line, func, str);
397 g_free(str);
398 return ret;
399 }
400
401 void
402 debug_free(const char *where, int line, const char *func, void *ptr)
403 {
404 struct malloc_head *head;
405 struct malloc_tail *tail;
406 if (!ptr)
407 return;
408 mallocs--;
409 head=(struct malloc_head *)((unsigned char *)ptr-sizeof(*head));
410 tail=(struct malloc_tail *)((unsigned char *)ptr+head->size);
411 malloc_size-=head->size;
412 if (head->magic != 0xdeadbeef || tail->magic != 0xdeadbef0) {
413 fprintf(stderr,"Invalid free from %s:%d %s\n",where,line,func);
414 }
415 head->magic=0;
416 tail->magic=0;
417 if (head->prev)
418 head->prev->next=head->next;
419 else
420 malloc_heads=head->next;
421 if (head->next)
422 head->next->prev=head->prev;
423 free(head->where);
424 free(head);
425 }
426
427 void
428 debug_free_func(void *ptr)
429 {
430 debug_free("unknown",0,"unknown",ptr);
431 }
432
433 void debug_finished(void) {
434 debug_dump_mallocs();
435 g_free(gdb_program);
436 g_hash_table_destroy(debug_hash);
437 debug_destroy();
438 }
439

   
Visit the ZANavi Wiki