diff options
author | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2010-11-21 21:30:12 +0000 |
---|---|---|
committer | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2010-11-21 21:30:12 +0000 |
commit | faf1817409cbd5550123e0e9feef562e98e4e75e (patch) | |
tree | 42de5c5f0b347aa865b9670fa3bad59d45a01904 /navit/debug.c | |
parent | 9c466478ff2dac553e14a97e62979cdeccec19fe (diff) | |
parent | 0a095f392cd1f4f45cb34061d64414108572926f (diff) | |
download | navit-svn-R0_2_0.tar.gz |
Now correct tagR0_2_0
git-svn-id: http://svn.code.sf.net/p/navit/code/tags/R0_2_0/navit@3708 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'navit/debug.c')
-rw-r--r-- | navit/debug.c | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/navit/debug.c b/navit/debug.c new file mode 100644 index 00000000..fe352814 --- /dev/null +++ b/navit/debug.c @@ -0,0 +1,423 @@ +/** + * Navit, a modular navigation system. + * Copyright (C) 2005-2008 Navit Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include <glib.h> +#include "config.h" +#include "file.h" +#include "item.h" +#include "debug.h" + +#ifdef HAVE_API_ANDROID +#include <android/log.h> +#endif + +#ifdef HAVE_API_WIN32_CE +#include <windows.h> +#include <windowsx.h> +#endif + +#ifdef HAVE_SOCKET +#include <stdlib.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +static int debug_socket=-1; +static struct sockaddr_in debug_sin; +#endif + + +int debug_level=0; +int segv_level=0; +int timestamp_prefix=0; + +static int dummy; +static GHashTable *debug_hash; +static const gchar *gdb_program; + +static FILE *debug_fp; + +#if defined(_WIN32) || defined(__CEGCC__) + +static void sigsegv(int sig) +{ +} + +#else +#include <unistd.h> +static void sigsegv(int sig) +{ + char buffer[256]; + if (segv_level > 1) + sprintf(buffer, "gdb -ex bt %s %d", gdb_program, getpid()); + else + sprintf(buffer, "gdb -ex bt -ex detach -ex quit %s %d", gdb_program, getpid()); + system(buffer); + exit(1); +} +#endif + +void +debug_init(const char *program_name) +{ + gdb_program=g_strdup(program_name); + signal(SIGSEGV, sigsegv); + debug_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + debug_fp = stderr; +} + + +static void +debug_update_level(gpointer key, gpointer value, gpointer user_data) +{ + if (debug_level < GPOINTER_TO_INT(value)) + debug_level = GPOINTER_TO_INT(value); +} + +void +debug_level_set(const char *name, int level) +{ + if (!strcmp(name, "segv")) { + segv_level=level; + if (segv_level) + signal(SIGSEGV, sigsegv); + else + signal(SIGSEGV, NULL); + } else if (!strcmp(name, "timestamps")) { + timestamp_prefix=level; + } else { + debug_level=0; + g_hash_table_insert(debug_hash, g_strdup(name), GINT_TO_POINTER(level)); + g_hash_table_foreach(debug_hash, debug_update_level, NULL); + } +} + +struct debug * +debug_new(struct attr *parent, struct attr **attrs) +{ + struct attr *name,*level; + name=attr_search(attrs, NULL, attr_name); + level=attr_search(attrs, NULL, attr_level); +#ifdef HAVE_SOCKET + if (!name && !level) { + struct attr *socket_attr=attr_search(attrs, NULL, attr_socket); + char *p,*s; + if (!socket_attr) + return NULL; + s=g_strdup(socket_attr->u.str); + p=strchr(s,':'); + if (!p) { + g_free(s); + return NULL; + } + *p++='\0'; + debug_sin.sin_family=AF_INET; + if (!inet_aton(s, &debug_sin.sin_addr)) { + g_free(s); + return NULL; + } + debug_sin.sin_port=ntohs(atoi(p)); + if (debug_socket == -1) + debug_socket=socket(PF_INET, SOCK_DGRAM, 0); + g_free(s); + return (struct debug *)&dummy; + } +#endif + if (!name || !level) + return NULL; + debug_level_set(name->u.str, level->u.num); + return (struct debug *)&dummy; +} + + +int +debug_level_get(const char *name) +{ + if (!debug_hash) + return 0; + return GPOINTER_TO_INT(g_hash_table_lookup(debug_hash, name)); +} + +static void debug_timestamp(char *buffer) +{ +#ifdef HAVE_API_WIN32_CE + LARGE_INTEGER counter, frequency; + double val; + QueryPerformanceCounter(&counter); + QueryPerformanceFrequency(&frequency); + val=counter.HighPart * 4294967296.0 + counter.LowPart; + val/=frequency.HighPart * 4294967296.0 + frequency.LowPart; + sprintf(buffer,"%.6f|",val); + +#else + struct timeval tv; + + if (gettimeofday(&tv, NULL) == -1) + return; + /* Timestamps are UTC */ + sprintf(buffer, + "%02d:%02d:%02d.%03d|", + (int)(tv.tv_sec/3600)%24, + (int)(tv.tv_sec/60)%60, + (int)tv.tv_sec % 60, + (int)tv.tv_usec/1000); +#endif +} + +void +debug_vprintf(int level, const char *module, const int mlen, const char *function, const int flen, int prefix, const char *fmt, va_list ap) +{ +#ifdef HAVE_API_WIN32_CE + char buffer[4096]; +#else + char buffer[mlen+flen+3]; +#endif + FILE *fp=debug_fp; + + sprintf(buffer, "%s:%s", module, function); + if (debug_level_get(module) >= level || debug_level_get(buffer) >= level) { +#if defined(DEBUG_WIN32_CE_MESSAGEBOX) + wchar_t muni[4096]; +#endif + char xbuffer[4096]; + xbuffer[0]='\0'; + if (prefix) { + if (timestamp_prefix) + debug_timestamp(xbuffer); + strcpy(xbuffer+strlen(xbuffer),buffer); + strcpy(xbuffer+strlen(xbuffer),":"); + } + vsprintf(xbuffer+strlen(xbuffer),fmt,ap); +#ifdef DEBUG_WIN32_CE_MESSAGEBOX + mbstowcs(muni, xbuffer, strlen(xbuffer)+1); + MessageBoxW(NULL, muni, TEXT("Navit - Error"), MB_APPLMODAL|MB_OK|MB_ICONERROR); +#else +#ifdef HAVE_API_ANDROID + __android_log_print(ANDROID_LOG_ERROR,"navit", "%s", xbuffer); +#else +#ifdef HAVE_SOCKET + if (debug_socket != -1) { + sendto(debug_socket, xbuffer, strlen(xbuffer), 0, (struct sockaddr *)&debug_sin, sizeof(debug_sin)); + return; + } +#endif + if (! fp) + fp = stderr; + fprintf(fp,"%s",xbuffer); + fflush(fp); +#endif +#endif + } +} + +void +debug_printf(int level, const char *module, const int mlen,const char *function, const int flen, int prefix, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + debug_vprintf(level, module, mlen, function, flen, prefix, fmt, ap); + va_end(ap); +} + +void +debug_assert_fail(const char *module, const int mlen,const char *function, const int flen, const char *file, int line, const char *expr) +{ + debug_printf(0,module,mlen,function,flen,1,"%s:%d assertion failed:%s\n", file, line, expr); + abort(); +} + +void +debug_destroy(void) +{ + if (!debug_fp) + return; + if (debug_fp == stderr || debug_fp == stdout) + return; + fclose(debug_fp); + debug_fp = NULL; +} + +void debug_set_logfile(const char *path) +{ + FILE *fp; + fp = fopen(path, "a"); + if (fp) { + debug_destroy(); + debug_fp = fp; + fprintf(debug_fp, "Navit log started\n"); + fflush(debug_fp); + } +} + +struct malloc_head { + int magic; + int size; + char *where; + void *return_address[8]; + struct malloc_head *prev; + struct malloc_head *next; +} *malloc_heads; + +struct malloc_tail { + int magic; +}; + +int mallocs,malloc_size,malloc_size_m; + +void +debug_dump_mallocs(void) +{ + struct malloc_head *head=malloc_heads; + int i; + dbg(0,"mallocs %d\n",mallocs); + while (head) { + fprintf(stderr,"unfreed malloc from %s of size %d\n",head->where,head->size); + for (i = 0 ; i < 8 ; i++) + fprintf(stderr,"\tlist *%p\n",head->return_address[i]); +#if 0 + fprintf(stderr,"%s\n",head+1); +#endif + head=head->next; + } +} + +void * +debug_malloc(const char *where, int line, const char *func, int size) +{ + struct malloc_head *head; + struct malloc_tail *tail; + if (!size) + return NULL; + mallocs++; + malloc_size+=size; + if (malloc_size/(1024*1024) != malloc_size_m) { + malloc_size_m=malloc_size/(1024*1024); + dbg(0,"malloced %d kb\n",malloc_size/1024); + } + head=malloc(size+sizeof(*head)+sizeof(*tail)); + head->magic=0xdeadbeef; + head->size=size; + head->prev=NULL; + head->next=malloc_heads; + malloc_heads=head; + if (head->next) + head->next->prev=head; + head->where=g_strdup_printf("%s:%d %s",where,line,func); + head->return_address[0]=__builtin_return_address(0); + head->return_address[1]=__builtin_return_address(1); + head->return_address[2]=__builtin_return_address(2); + head->return_address[3]=__builtin_return_address(3); + head->return_address[4]=__builtin_return_address(4); + head->return_address[5]=__builtin_return_address(5); + head->return_address[6]=__builtin_return_address(6); + head->return_address[7]=__builtin_return_address(7); + head++; + tail=(struct malloc_tail *)((unsigned char *)head+size); + tail->magic=0xdeadbef0; + return head; +} + + +void * +debug_malloc0(const char *where, int line, const char *func, int size) +{ + void *ret=debug_malloc(where, line, func, size); + if (ret) + memset(ret, 0, size); + return ret; +} + +void * +debug_realloc(const char *where, int line, const char *func, void *ptr, int size) +{ + void *ret=debug_malloc(where, line, func, size); + if (ret && ptr) + memcpy(ret, ptr, size); + debug_free(where, line, func, ptr); + return ret; +} + +char * +debug_strdup(const char *where, int line, const char *func, const char *ptr) +{ + int size; + char *ret; + + if (!ptr) + return NULL; + size=strlen(ptr)+1; + ret=debug_malloc(where, line, func, size); + memcpy(ret, ptr, size); + return ret; +} + +char * +debug_guard(const char *where, int line, const char *func, char *str) +{ + char *ret=debug_strdup(where, line, func, str); + g_free(str); + return ret; +} + +void +debug_free(const char *where, int line, const char *func, void *ptr) +{ + struct malloc_head *head; + struct malloc_tail *tail; + if (!ptr) + return; + mallocs--; + head=(struct malloc_head *)((unsigned char *)ptr-sizeof(*head)); + tail=(struct malloc_tail *)((unsigned char *)ptr+head->size); + malloc_size-=head->size; + if (head->magic != 0xdeadbeef || tail->magic != 0xdeadbef0) { + fprintf(stderr,"Invalid free from %s:%d %s\n",where,line,func); + } + head->magic=0; + tail->magic=0; + if (head->prev) + head->prev->next=head->next; + else + malloc_heads=head->next; + if (head->next) + head->next->prev=head->prev; + free(head->where); + free(head); +} + +void +debug_free_func(void *ptr) +{ + debug_free("unknown",0,"unknown",ptr); +} + +void debug_finished(void) { + debug_dump_mallocs(); + g_free(gdb_program); + g_hash_table_destroy(debug_hash); + debug_destroy(); +} + |