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

Contents of /navit/navit/debug.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 10182 byte(s)
import files
1 zoff99 2 /**
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