2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
35 #ifdef HAVE_API_ANDROID
36 #include <android/log.h>
39 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
50 static int debug_socket=-1;
51 static struct sockaddr_in debug_sin;
55 int max_debug_level=0;
56 int global_debug_level=0;
58 int timestamp_prefix=0;
61 static GHashTable *debug_hash;
62 static gchar *gdb_program;
64 static FILE *debug_fp;
66 #if defined(_WIN32) || defined(__CEGCC__)
68 static void sigsegv(int sig)
74 static void sigsegv(int sig)
78 sprintf(buffer, "gdb -ex bt %s %d", gdb_program, getpid());
80 sprintf(buffer, "gdb -ex bt -ex detach -ex quit %s %d", gdb_program, getpid());
87 debug_init(const char *program_name)
89 gdb_program=g_strdup(program_name);
90 signal(SIGSEGV, sigsegv);
91 debug_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
92 #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
101 debug_update_level(gpointer key, gpointer value, gpointer user_data)
103 if (max_debug_level < GPOINTER_TO_INT(value))
104 max_debug_level = GPOINTER_TO_INT(value);
108 debug_level_set(const char *name, int level)
110 if (!strcmp(name, "segv")) {
113 signal(SIGSEGV, sigsegv);
115 signal(SIGSEGV, NULL);
116 } else if (!strcmp(name, "timestamps")) {
117 timestamp_prefix=level;
118 } else if (!strcmp(name, DEBUG_MODULE_GLOBAL)) {
119 global_debug_level=level;
120 if (max_debug_level < global_debug_level){
121 max_debug_level = global_debug_level;
124 g_hash_table_insert(debug_hash, g_strdup(name), GINT_TO_POINTER(level));
125 g_hash_table_foreach(debug_hash, debug_update_level, NULL);
130 debug_new(struct attr *parent, struct attr **attrs)
132 struct attr *name,*level;
133 name=attr_search(attrs, NULL, attr_name);
134 level=attr_search(attrs, NULL, attr_level);
136 if (!name && !level) {
137 struct attr *socket_attr=attr_search(attrs, NULL, attr_socket);
141 s=g_strdup(socket_attr->u.str);
148 debug_sin.sin_family=AF_INET;
149 if (!inet_aton(s, &debug_sin.sin_addr)) {
153 debug_sin.sin_port=ntohs(atoi(p));
154 if (debug_socket == -1)
155 debug_socket=socket(PF_INET, SOCK_DGRAM, 0);
157 return (struct debug *)&dummy;
162 debug_level_set(name->u.str, level->u.num);
163 return (struct debug *)&dummy;
168 debug_level_get(const char *name)
172 return GPOINTER_TO_INT(g_hash_table_lookup(debug_hash, name));
175 static void debug_timestamp(char *buffer)
177 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
178 LARGE_INTEGER counter, frequency;
180 QueryPerformanceCounter(&counter);
181 QueryPerformanceFrequency(&frequency);
182 val=counter.HighPart * 4294967296.0 + counter.LowPart;
183 val/=frequency.HighPart * 4294967296.0 + frequency.LowPart;
184 sprintf(buffer,"%.6f|",val);
189 if (gettimeofday(&tv, NULL) == -1)
191 /* Timestamps are UTC */
193 "%02d:%02d:%02d.%03d|",
194 (int)(tv.tv_sec/3600)%24,
195 (int)(tv.tv_sec/60)%60,
197 (int)tv.tv_usec/1000);
202 debug_vprintf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, va_list ap)
204 #if defined HAVE_API_WIN32_CE || defined _MSC_VER
207 char buffer[mlen+flen+3];
211 sprintf(buffer, "%s:%s", module, function);
212 if (global_debug_level >= level || debug_level_get(module) >= level || debug_level_get(buffer) >= level) {
213 #if defined(DEBUG_WIN32_CE_MESSAGEBOX)
219 if (timestamp_prefix)
220 debug_timestamp(xbuffer);
221 strcpy(xbuffer+strlen(xbuffer),buffer);
222 strcpy(xbuffer+strlen(xbuffer),":");
224 vsprintf(xbuffer+strlen(xbuffer),fmt,ap);
225 #ifdef DEBUG_WIN32_CE_MESSAGEBOX
226 mbstowcs(muni, xbuffer, strlen(xbuffer)+1);
227 MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR);
229 #ifdef HAVE_API_ANDROID
230 __android_log_print(ANDROID_LOG_ERROR,"navit", "%s", xbuffer);
233 if (debug_socket != -1) {
234 sendto(debug_socket, xbuffer, strlen(xbuffer), 0, (struct sockaddr *)&debug_sin, sizeof(debug_sin));
240 fprintf(fp,"%s",xbuffer);
248 debug_printf(int level, const char *module, const int mlen,const char *function, const int flen, int prefix, const char *fmt, ...)
252 debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap);
257 debug_assert_fail(const char *module, const int mlen,const char *function, const int flen, const char *file, int line, const char *expr)
259 debug_printf(0,module,mlen,function,flen,1,"%s:%d assertion failed:%s\n", file, line, expr);
268 if (debug_fp == stderr || debug_fp == stdout)
274 void debug_set_logfile(const char *path)
277 fp = fopen(path, "a");
281 fprintf(debug_fp, "Navit log started\n");
290 void *return_address[8];
291 struct malloc_head *prev;
292 struct malloc_head *next;
299 int mallocs,debug_malloc_size,debug_malloc_size_m;
302 debug_dump_mallocs(void)
304 struct malloc_head *head=malloc_heads;
306 dbg(0,"mallocs %d\n",mallocs);
308 fprintf(stderr,"unfreed malloc from %s of size %d\n",head->where,head->size);
309 for (i = 0 ; i < 8 ; i++)
310 fprintf(stderr,"\tlist *%p\n",head->return_address[i]);
312 fprintf(stderr,"%s\n",head+1);
319 debug_malloc(const char *where, int line, const char *func, int size)
321 struct malloc_head *head;
322 struct malloc_tail *tail;
326 debug_malloc_size+=size;
327 if (debug_malloc_size/(1024*1024) != debug_malloc_size_m) {
328 debug_malloc_size_m=debug_malloc_size/(1024*1024);
329 dbg(0,"malloced %d kb\n",debug_malloc_size/1024);
331 head=malloc(size+sizeof(*head)+sizeof(*tail));
332 head->magic=0xdeadbeef;
335 head->next=malloc_heads;
338 head->next->prev=head;
339 head->where=g_strdup_printf("%s:%d %s",where,line,func);
340 #if !defined (__GNUC__)
341 #define __builtin_return_address(x) NULL
343 head->return_address[0]=__builtin_return_address(0);
344 head->return_address[1]=__builtin_return_address(1);
345 head->return_address[2]=__builtin_return_address(2);
346 head->return_address[3]=__builtin_return_address(3);
347 head->return_address[4]=__builtin_return_address(4);
348 head->return_address[5]=__builtin_return_address(5);
349 head->return_address[6]=__builtin_return_address(6);
350 head->return_address[7]=__builtin_return_address(7);
352 tail=(struct malloc_tail *)((unsigned char *)head+size);
353 tail->magic=0xdeadbef0;
359 debug_malloc0(const char *where, int line, const char *func, int size)
361 void *ret=debug_malloc(where, line, func, size);
363 memset(ret, 0, size);
368 debug_realloc(const char *where, int line, const char *func, void *ptr, int size)
370 void *ret=debug_malloc(where, line, func, size);
372 memcpy(ret, ptr, size);
373 debug_free(where, line, func, ptr);
378 debug_strdup(const char *where, int line, const char *func, const char *ptr)
386 ret=debug_malloc(where, line, func, size);
387 memcpy(ret, ptr, size);
392 debug_guard(const char *where, int line, const char *func, char *str)
394 char *ret=debug_strdup(where, line, func, str);
400 debug_free(const char *where, int line, const char *func, void *ptr)
402 struct malloc_head *head;
403 struct malloc_tail *tail;
407 head=(struct malloc_head *)((unsigned char *)ptr-sizeof(*head));
408 tail=(struct malloc_tail *)((unsigned char *)ptr+head->size);
409 debug_malloc_size-=head->size;
410 if (head->magic != 0xdeadbeef || tail->magic != 0xdeadbef0) {
411 fprintf(stderr,"Invalid free from %s:%d %s\n",where,line,func);
416 head->prev->next=head->next;
418 malloc_heads=head->next;
420 head->next->prev=head->prev;
426 debug_free_func(void *ptr)
428 debug_free("unknown",0,"unknown",ptr);
431 void debug_finished(void) {
432 debug_dump_mallocs();
434 g_hash_table_destroy(debug_hash);