/* vmlog - high-speed logging for free VMs */ /* Copyright (C) 2006 Edwin Steiner */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _VMLOG_H_ #define _VMLOG_H_ #define VMLOG_PAD_TO_8 #include /*** constants *******************************************************/ /* CAUTION: these are indices into the vmlog_tag_definitions table! */ #define VMLOG_TAG_ENTER 0 #define VMLOG_TAG_LEAVE 1 #define VMLOG_TAG_THROW 2 #define VMLOG_TAG_CATCH 3 #define VMLOG_TAG_UNWND 4 #define VMLOG_TAG_SIGNL 5 #define VMLOG_TAG_UNROL 6 #define VMLOG_TAG_REROL 7 /*** memory management macros ****************************************/ #ifndef VMLOG_NEW #define VMLOG_NEW(type) (type*)malloc(sizeof(type)) #endif #ifndef VMLOG_FREE #define VMLOG_FREE(type,ptr) free(ptr) #endif #ifndef VMLOG_NEW_ARRAY #define VMLOG_NEW_ARRAY(type,n) (type*)malloc(sizeof(type)*(n)) #endif #ifndef VMLOG_FREE_ARRAY #define VMLOG_FREE_ARRAY(type,n,ptr) free(ptr) #endif /*** struct typedefs *************************************************/ typedef struct vmlog_tag_definition vmlog_tag_definition; typedef struct vmlog_hash_entry vmlog_hash_entry; typedef struct vmlog_hash_table vmlog_hash_table; typedef struct vmlog_string_entry vmlog_string_entry; typedef struct vmlog_log_entry vmlog_log_entry; typedef struct vmlog_thread_log vmlog_thread_log; typedef struct vmlog_file vmlog_file; typedef struct vmlog_frame vmlog_frame; typedef struct vmlog_ringbuf vmlog_ringbuf; typedef struct vmlog_log vmlog_log; typedef struct vmlog_options vmlog_options; /*** integer types ***************************************************/ typedef long long vmlog_fofs_t; typedef long long vmlog_seq_t; #define VMLOG_SEQ_FMT "%lld" #define VMLOG_SEQ_FMT_W "%10lld" #ifdef LLONG_MAX #define VMLOG_SEQ_MAX LLONG_MAX #else #define VMLOG_SEQ_MAX 9223372036854775807LL #endif #ifndef VMLOG_HAVE_PTRINT typedef int ptrint; /* XXX */ #endif /*** enums ***********************************************************/ typedef enum { vmlogRead, vmlogAppend, vmlogTruncateAppend } vmlog_fmode; /*** function types **************************************************/ typedef void (*vmlog_hash_entry_destructor)(vmlog_hash_entry *entry); typedef void (*vmlog_log_function)(vmlog_log *vml,void *threadid, const char *name,int namelen); /*** structs *********************************************************/ struct vmlog_tag_definition { char *name; char *fixname; int depth; }; struct vmlog_hash_entry { unsigned int hash; int len; int index; void *data; vmlog_hash_entry *hashlink; }; struct vmlog_hash_table { int size; int nentries; vmlog_hash_entry *table; }; struct vmlog_string_entry { vmlog_fofs_t ofs; int len; #if defined(VMLOG_PAD_TO_8) int dummy; #endif }; struct vmlog_log_entry { int tag:8; int index:24; }; struct vmlog_file { int fd; char *fname; int fnamelen; vmlog_fofs_t ofs; vmlog_fofs_t size; }; struct vmlog_frame { int index; vmlog_seq_t seq; }; struct vmlog_thread_log { void *threadid; int threadidx; int depth; int ignoredepth; vmlog_file logfile; vmlog_log_entry *logbuf; vmlog_log_entry *logbufend; vmlog_log_entry *logbufptr; int logbufcap; vmlog_frame *frames; int framescap; vmlog_seq_t seq; }; struct vmlog_log { vmlog_hash_table threadhash; vmlog_hash_table stringhash; vmlog_file idxfile; vmlog_file strfile; char *prefix; int prefixlen; int ignorelistlen; }; struct vmlog_ringbuf { vmlog_file file; vmlog_log_entry *buf; vmlog_log_entry *bufend; vmlog_log_entry *start; vmlog_log_entry *end; vmlog_log_entry *cur; int bufsize; vmlog_seq_t seq; int debug_availbefore; int debug_availafter; }; struct vmlog_options { char *progname; char *prefix; char *stringprefix; char *ignoreprefix; }; /*** variables *******************************************************/ extern vmlog_tag_definition vmlog_tag_definitions[]; /*** public functions ************************************************/ /* constructor / destructor */ vmlog_log * vmlog_log_new(const char *prefix,int truncate); void vmlog_log_free(vmlog_log *vml); /* configuration */ void vmlog_log_load_ignorelist(vmlog_log *vml,const char *prefix); /* logging */ void vmlog_log_enter(vmlog_log *vml,void *threadid,const char *name,int namelen); void vmlog_log_leave(vmlog_log *vml,void *threadid,const char *name,int namelen); void vmlog_log_throw(vmlog_log *vml,void *threadid,const char *name,int namelen); void vmlog_log_catch(vmlog_log *vml,void *threadid,const char *name,int namelen); void vmlog_log_unwnd(vmlog_log *vml,void *threadid,const char *name,int namelen); void vmlog_log_signl(vmlog_log *vml,void *threadid,const char *name,int namelen); void vmlog_log_unrol(vmlog_log *vml,void *threadid,const char *name,int namelen); void vmlog_log_rerol(vmlog_log *vml,void *threadid,const char *name,int namelen); /* tag definitions */ int vmlog_tag_from_name(const char *name,int namelen); /* thread logging */ vmlog_thread_log *vmlog_thread_log_new(vmlog_log *vml,void *threadid,int index); void vmlog_thread_log_free(vmlog_thread_log *tlog); vmlog_frame * vmlog_thread_log_enter(vmlog_thread_log *tlog,int index,vmlog_seq_t seq); vmlog_frame * vmlog_thread_log_leave(vmlog_thread_log *tlog,int index,vmlog_seq_t seq); void vmlog_thread_log_append(vmlog_thread_log *tlog,vmlog_log_entry *logent); /* string/index handling */ int vmlog_get_string_index(vmlog_log *vml,const char *data,int len); void vmlog_load_stringhash(vmlog_log *vml,const char *prefix); /* string helpers */ char *vmlog_concat3(const char *a,const char *b,const char *c,int *plen); char *vmlog_concat4len(const char *a,int alen,const char *b,int blen, const char *c,int clen,const char *d,int dlen,int *plen); /* error reporting */ void vmlog_set_progname(const char *progname); void vmlog_die(const char *fmt,...); void vmlog_warn(const char *fmt,...); void vmlog_die_usage(const char *usage,int error); /* file handling */ void vmlog_file_open(vmlog_file *file,const char *fname,vmlog_fmode fmode); void vmlog_file_close(vmlog_file *file); void vmlog_file_append(vmlog_file *file,const void *data,int len); void * vmlog_file_mmap(const char *fname,int *plen); void vmlog_file_munmap(void *m,int len); void vmlog_file_stat(vmlog_file *file); void vmlog_file_seek(vmlog_file *file,vmlog_fofs_t ofs); /* log entry ring buffer */ vmlog_ringbuf * vmlog_ringbuf_new(const char *fname,int bufsize); void vmlog_ringbuf_free(vmlog_ringbuf *ring); void vmlog_ringbuf_seek(vmlog_ringbuf *ring,vmlog_seq_t seq); int vmlog_ringbuf_fill(vmlog_ringbuf *ring,int len); vmlog_log_entry * vmlog_ringbuf_next(vmlog_ringbuf *ring,int prefetch); vmlog_log_entry * vmlog_ringbuf_prev(vmlog_ringbuf *ring,int prefetch); /* option parsing */ vmlog_options *vmlog_opt_new(void); void vmlog_opt_set_prefix(vmlog_options *opts, const char *arg); void vmlog_opt_set_stringprefix(vmlog_options *opts, const char *arg); void vmlog_opt_set_ignoreprefix(vmlog_options *opts, const char *arg); int vmlog_opt_parse_seq(const char *arg,int len,vmlog_seq_t *seq); int vmlog_opt_parse_range(const char *arg,vmlog_seq_t *start,vmlog_seq_t *end); vmlog_options *vmlog_opt_parse_cmd_line(int *pargc,char **argv); void vmlog_opt_free(vmlog_options *opts); /*** memory allocation helpers ***************************************/ /* allocate, check, and zero memory */ #define VMLOG_XZNEW(var,type) \ do { var = VMLOG_NEW(type); \ if (!(var)) vmlog_die("out of memory"); \ memset((var),0,sizeof(type)); \ } while (0) /* allocate, check, and zero memory for array */ #define VMLOG_XZNEW_ARRAY(var,type,n) \ do { var = VMLOG_NEW_ARRAY(type,n); \ if (!(var)) vmlog_die("out of memory"); \ memset((var),0,(n)*sizeof(type)); \ } while (0) #endif /* vim: noet ts=8 sw=8 */