diff options
Diffstat (limited to 'camel/camel-debug.c')
-rw-r--r-- | camel/camel-debug.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/camel/camel-debug.c b/camel/camel-debug.c index 7c16c9a614..77a5d1cf8b 100644 --- a/camel/camel-debug.c +++ b/camel/camel-debug.c @@ -21,6 +21,9 @@ #include <stdlib.h> #include <string.h> +#include <stdio.h> + +#include <pthread.h> #include "camel-debug.h" @@ -113,3 +116,143 @@ gboolean camel_debug(const char *mode) return FALSE; } + +static pthread_mutex_t debug_lock = PTHREAD_MUTEX_INITIALIZER; +/** + * camel_debug_start: + * @mode: + * + * Start debug output for a given mode, used to make sure debug output + * is output atomically and not interspersed with unrelated stuff. + * + * Return value: Returns true if mode is set, and in which case, you must + * call debug_end when finished any screen output. + **/ +gboolean +camel_debug_start(const char *mode) +{ + if (camel_debug(mode)) { + pthread_mutex_lock(&debug_lock); + printf("Thread %lx >\n", pthread_self()); + return TRUE; + } + + return FALSE; +} + +/** + * camel_debug_end: + * + * Call this when you're done with your debug output. If and only if + * you called camel_debug_start, and if it returns TRUE. + **/ +void +camel_debug_end(void) +{ + printf("< %lx >\n", pthread_self()); + pthread_mutex_unlock(&debug_lock); +} + +#include <sys/debugreg.h> + +#if 0 +static unsigned +i386_length_and_rw_bits (int len, enum target_hw_bp_type type) +{ + unsigned rw; + + switch (type) + { + case hw_execute: + rw = DR_RW_EXECUTE; + break; + case hw_write: + rw = DR_RW_WRITE; + break; + case hw_read: /* x86 doesn't support data-read watchpoints */ + case hw_access: + rw = DR_RW_READ; + break; +#if 0 + case hw_io_access: /* not yet supported */ + rw = DR_RW_IORW; + break; +#endif + default: + internal_error (__FILE__, __LINE__, "\ +Invalid hw breakpoint type %d in i386_length_and_rw_bits.\n", (int)type); + } + + switch (len) + { + case 1: + return (DR_LEN_1 | rw); + case 2: + return (DR_LEN_2 | rw); + case 4: + return (DR_LEN_4 | rw); + case 8: + if (TARGET_HAS_DR_LEN_8) + return (DR_LEN_8 | rw); + default: + internal_error (__FILE__, __LINE__, "\ +Invalid hw breakpoint length %d in i386_length_and_rw_bits.\n", len); + } +} + +#define I386_DR_SET_RW_LEN(i,rwlen) \ + do { \ + dr_control_mirror &= ~(0x0f << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \ + dr_control_mirror |= ((rwlen) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \ + } while (0) + +#define I386_DR_LOCAL_ENABLE(i) \ + dr_control_mirror |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))) + + +#define set_dr(regnum, val) \ + __asm__("movl %0,%%db" #regnum \ + : /* no output */ \ + :"r" (val)) + +#define get_dr(regnum, val) \ + __asm__("movl %%db" #regnum ", %0" \ + :"=r" (val)) + +/* fine idea, but it doesn't work, crashes in get_dr :-/ */ +void +camel_debug_hwatch(int wp, void *addr) +{ + guint32 control, rw; + + g_assert(wp <= DR_LASTADDR); + g_assert(sizeof(addr) == 4); + + get_dr(7, control); + /* set watch mode + size */ + rw = DR_RW_WRITE | DR_LEN_4; + control &= ~(((1<<DR_CONTROL_SIZE)-1) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE * wp)); + control |= rw << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE*wp); + /* set watch enable */ + control |= ( 1<< (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * wp)); + control |= DR_LOCAL_SLOWDOWN; + control &= ~DR_CONTROL_RESERVED; + + switch (wp) { + case 0: + set_dr(0, addr); + break; + case 1: + set_dr(1, addr); + break; + case 2: + set_dr(2, addr); + break; + case 3: + set_dr(3, addr); + break; + } + set_dr(7, control); +} + +#endif |