New scheme for keeping track of debug channels that doesn't require
maintaining a list of all loaded dlls.
This commit is contained in:
parent
9c559cf385
commit
cbc38965c0
|
@ -43,7 +43,8 @@ enum __wine_debug_class
|
|||
__WINE_DBCL_ERR,
|
||||
__WINE_DBCL_WARN,
|
||||
__WINE_DBCL_TRACE,
|
||||
__WINE_DBCL_COUNT
|
||||
|
||||
__WINE_DBCL_INIT = 7 /* lazy init flag */
|
||||
};
|
||||
|
||||
struct __wine_debug_channel
|
||||
|
@ -70,8 +71,9 @@ struct __wine_debug_channel
|
|||
#define __WINE_GET_DEBUGGING_ERR(dbch) ((dbch)->flags & (1 << __WINE_DBCL_ERR))
|
||||
|
||||
#define __WINE_GET_DEBUGGING(dbcl,dbch) __WINE_GET_DEBUGGING##dbcl(dbch)
|
||||
#define __WINE_SET_DEBUGGING(dbcl,dbch,on) \
|
||||
((on) ? ((dbch)[0] |= 1 << (dbcl)) : ((dbch)[0] &= ~(1 << (dbcl))))
|
||||
|
||||
#define __WINE_IS_DEBUG_ON(dbcl,dbch) \
|
||||
(__WINE_GET_DEBUGGING##dbcl(dbch) && wine_dbg_log(__WINE_DBCL##dbcl, (dbch), 0, 0) != -1)
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
|
@ -128,7 +130,7 @@ struct __wine_debug_channel
|
|||
|
||||
#define __WINE_DPRINTF(dbcl,dbch) \
|
||||
(!__WINE_GET_DEBUGGING(dbcl,(dbch)) || \
|
||||
(wine_dbg_log(__WINE_DBCL##dbcl,(dbch),__FILE__,"%d: ",__LINE__),0)) ? \
|
||||
(wine_dbg_log(__WINE_DBCL##dbcl,(dbch),__FILE__,"%d: ",__LINE__) == -1)) ? \
|
||||
(void)0 : (void)wine_dbg_printf
|
||||
|
||||
#define __WINE_PRINTF_ATTR(fmt, args)
|
||||
|
@ -213,23 +215,23 @@ static inline const char *wine_dbgstr_longlong( ULONGLONG ll )
|
|||
#define WINE_TRACE __WINE_DPRINTF(_TRACE,__wine_dbch___default)
|
||||
#define WINE_TRACE_(ch) __WINE_DPRINTF(_TRACE,&__wine_dbch_##ch)
|
||||
#endif
|
||||
#define WINE_TRACE_ON(ch) __WINE_GET_DEBUGGING(_TRACE,&__wine_dbch_##ch)
|
||||
#define WINE_TRACE_ON(ch) __WINE_IS_DEBUG_ON(_TRACE,&__wine_dbch_##ch)
|
||||
|
||||
#ifndef WINE_WARN
|
||||
#define WINE_WARN __WINE_DPRINTF(_WARN,__wine_dbch___default)
|
||||
#define WINE_WARN_(ch) __WINE_DPRINTF(_WARN,&__wine_dbch_##ch)
|
||||
#endif
|
||||
#define WINE_WARN_ON(ch) __WINE_GET_DEBUGGING(_WARN,&__wine_dbch_##ch)
|
||||
#define WINE_WARN_ON(ch) __WINE_IS_DEBUG_ON(_WARN,&__wine_dbch_##ch)
|
||||
|
||||
#ifndef WINE_FIXME
|
||||
#define WINE_FIXME __WINE_DPRINTF(_FIXME,__wine_dbch___default)
|
||||
#define WINE_FIXME_(ch) __WINE_DPRINTF(_FIXME,&__wine_dbch_##ch)
|
||||
#endif
|
||||
#define WINE_FIXME_ON(ch) __WINE_GET_DEBUGGING(_FIXME,&__wine_dbch_##ch)
|
||||
#define WINE_FIXME_ON(ch) __WINE_IS_DEBUG_ON(_FIXME,&__wine_dbch_##ch)
|
||||
|
||||
#define WINE_ERR __WINE_DPRINTF(_ERR,__wine_dbch___default)
|
||||
#define WINE_ERR_(ch) __WINE_DPRINTF(_ERR,&__wine_dbch_##ch)
|
||||
#define WINE_ERR_ON(ch) __WINE_GET_DEBUGGING(_ERR,&__wine_dbch_##ch)
|
||||
#define WINE_ERR_ON(ch) __WINE_IS_DEBUG_ON(_ERR,&__wine_dbch_##ch)
|
||||
|
||||
#define WINE_DECLARE_DEBUG_CHANNEL(ch) \
|
||||
extern struct __wine_debug_channel __wine_dbch_##ch
|
||||
|
|
|
@ -31,126 +31,98 @@
|
|||
#include "wine/library.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
struct dll
|
||||
{
|
||||
struct dll *next; /* linked list of dlls */
|
||||
struct dll *prev;
|
||||
struct __wine_debug_channel * const *channels; /* array of channels */
|
||||
int nb_channels; /* number of channels in array */
|
||||
};
|
||||
|
||||
static struct dll *first_dll;
|
||||
|
||||
struct debug_option
|
||||
{
|
||||
struct debug_option *next; /* next option in list */
|
||||
unsigned char set; /* bits to set */
|
||||
unsigned char clear; /* bits to clear */
|
||||
char name[14]; /* channel name, or empty for "all" */
|
||||
};
|
||||
|
||||
static struct debug_option *first_option;
|
||||
static struct debug_option *last_option;
|
||||
static struct __wine_debug_functions funcs;
|
||||
|
||||
static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
|
||||
|
||||
#define MAX_DEBUG_OPTIONS 256
|
||||
|
||||
static unsigned char default_flags = (1 << __WINE_DBCL_ERR) | (1 << __WINE_DBCL_FIXME);
|
||||
static unsigned int nb_debug_options = 0;
|
||||
static struct __wine_debug_channel debug_options[MAX_DEBUG_OPTIONS];
|
||||
|
||||
static struct __wine_debug_functions funcs;
|
||||
|
||||
static int cmp_name( const void *p1, const void *p2 )
|
||||
{
|
||||
const char *name = p1;
|
||||
const struct __wine_debug_channel * const *chan = p2;
|
||||
return strcmp( name, (*chan)->name );
|
||||
const struct __wine_debug_channel *chan = p2;
|
||||
return strcmp( name, chan->name );
|
||||
}
|
||||
|
||||
/* apply a debug option to the channels of a given dll */
|
||||
static void apply_option( struct dll *dll, const struct debug_option *opt )
|
||||
/* get the flags to use for a given channel, possibly setting them too in case of lazy init */
|
||||
static inline unsigned char get_channel_flags( struct __wine_debug_channel *channel )
|
||||
{
|
||||
if (opt->name[0])
|
||||
if (nb_debug_options)
|
||||
{
|
||||
struct __wine_debug_channel * const *dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
|
||||
sizeof(*dll->channels), cmp_name );
|
||||
if (dbch) (*dbch)->flags = ((*dbch)->flags & ~opt->clear) | opt->set;
|
||||
}
|
||||
else /* all */
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dll->nb_channels; i++)
|
||||
dll->channels[i]->flags = (dll->channels[i]->flags & ~opt->clear) | opt->set;
|
||||
struct __wine_debug_channel *opt = bsearch( channel->name, debug_options, nb_debug_options,
|
||||
sizeof(debug_options[0]), cmp_name );
|
||||
if (opt) return opt->flags;
|
||||
}
|
||||
/* no option for this channel */
|
||||
if (channel->flags & (1 << __WINE_DBCL_INIT)) channel->flags = default_flags;
|
||||
return default_flags;
|
||||
}
|
||||
|
||||
/* register a new set of channels for a dll */
|
||||
void *__wine_dbg_register( struct __wine_debug_channel * const *channels, int nb )
|
||||
{
|
||||
struct debug_option *opt = first_option;
|
||||
struct dll *dll = malloc( sizeof(*dll) );
|
||||
if (dll)
|
||||
{
|
||||
dll->channels = channels;
|
||||
dll->nb_channels = nb;
|
||||
dll->prev = NULL;
|
||||
if ((dll->next = first_dll)) dll->next->prev = dll;
|
||||
first_dll = dll;
|
||||
int i;
|
||||
|
||||
/* apply existing options to this dll */
|
||||
while (opt)
|
||||
for (i = 0; i < nb; i++)
|
||||
{
|
||||
apply_option( dll, opt );
|
||||
opt = opt->next;
|
||||
channels[i]->flags = ~0;
|
||||
get_channel_flags( channels[i] );
|
||||
}
|
||||
}
|
||||
return dll;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
|
||||
void __wine_dbg_unregister( void *channel )
|
||||
{
|
||||
struct dll *dll = channel;
|
||||
if (dll)
|
||||
{
|
||||
if (dll->next) dll->next->prev = dll->prev;
|
||||
if (dll->prev) dll->prev->next = dll->next;
|
||||
else first_dll = dll->next;
|
||||
free( dll );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* add a new debug option at the end of the option list */
|
||||
void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear )
|
||||
static void add_option( const char *name, unsigned char set, unsigned char clear )
|
||||
{
|
||||
struct dll *dll = first_dll;
|
||||
struct debug_option *opt;
|
||||
size_t len = strlen(name);
|
||||
int min = 0, max = nb_debug_options - 1, pos, res;
|
||||
|
||||
if (!(opt = malloc( sizeof(*opt) ))) return;
|
||||
opt->next = NULL;
|
||||
opt->set = set;
|
||||
opt->clear = clear;
|
||||
if (len >= sizeof(opt->name)) len = sizeof(opt->name) - 1;
|
||||
memcpy( opt->name, name, len );
|
||||
opt->name[len] = 0;
|
||||
if (last_option) last_option->next = opt;
|
||||
else first_option = opt;
|
||||
last_option = opt;
|
||||
|
||||
/* apply option to all existing dlls */
|
||||
while (dll)
|
||||
if (!name[0]) /* "all" option */
|
||||
{
|
||||
apply_option( dll, opt );
|
||||
dll = dll->next;
|
||||
default_flags = (default_flags & ~clear) | set;
|
||||
return;
|
||||
}
|
||||
if (strlen(name) >= sizeof(debug_options[0].name)) return;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
pos = (min + max) / 2;
|
||||
res = strcmp( name, debug_options[pos].name );
|
||||
if (!res)
|
||||
{
|
||||
debug_options[pos].flags = (debug_options[pos].flags & ~clear) | set;
|
||||
return;
|
||||
}
|
||||
if (res < 0) max = pos - 1;
|
||||
else min = pos + 1;
|
||||
}
|
||||
if (nb_debug_options >= MAX_DEBUG_OPTIONS) return;
|
||||
|
||||
pos = min;
|
||||
if (pos < nb_debug_options) memmove( &debug_options[pos + 1], &debug_options[pos],
|
||||
(nb_debug_options - pos) * sizeof(debug_options[0]) );
|
||||
strcpy( debug_options[pos].name, name );
|
||||
debug_options[pos].flags = (default_flags & ~clear) | set;
|
||||
nb_debug_options++;
|
||||
}
|
||||
|
||||
/* parse a set of debugging option specifications and add them to the option list */
|
||||
int wine_dbg_parse_options( const char *str )
|
||||
static void parse_options( const char *str )
|
||||
{
|
||||
char *opt, *next, *options;
|
||||
unsigned int i;
|
||||
int errors = 0;
|
||||
|
||||
if (!(options = strdup(str))) return -1;
|
||||
if (!(options = strdup(str))) return;
|
||||
for (opt = options; opt; opt = next)
|
||||
{
|
||||
const char *p;
|
||||
|
@ -175,27 +147,49 @@ int wine_dbg_parse_options( const char *str )
|
|||
}
|
||||
}
|
||||
if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
|
||||
{
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == '-') clear = ~0;
|
||||
else set = ~0;
|
||||
}
|
||||
if (*p == '+' || *p == '-') p++;
|
||||
if (!p[0])
|
||||
{
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp( p, "all" )) p = ""; /* empty string means all */
|
||||
wine_dbg_add_option( p, set, clear );
|
||||
if (!p[0]) continue;
|
||||
|
||||
if (!strcmp( p, "all" ))
|
||||
default_flags = (default_flags & ~clear) | set;
|
||||
else
|
||||
add_option( p, set, clear );
|
||||
}
|
||||
free( options );
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
/* print the usage message */
|
||||
static void debug_usage(void)
|
||||
{
|
||||
static const char usage[] =
|
||||
"Syntax of the WINEDEBUG variable:\n"
|
||||
" WINEDEBUG=[class]+xxx,[class]-yyy,...\n\n"
|
||||
"Example: WINEDEBUG=+all,warn-heap\n"
|
||||
" turns on all messages except warning heap messages\n"
|
||||
"Available message classes: err, warn, fixme, trace\n";
|
||||
write( 2, usage, sizeof(usage) - 1 );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* initialize all options at startup */
|
||||
void debug_init(void)
|
||||
{
|
||||
char *wine_debug;
|
||||
|
||||
if ((wine_debug = getenv("WINEDEBUG")))
|
||||
{
|
||||
if (!strcmp( wine_debug, "help" )) debug_usage();
|
||||
parse_options( wine_debug );
|
||||
}
|
||||
}
|
||||
|
||||
/* varargs wrapper for funcs.dbg_vprintf */
|
||||
|
@ -235,6 +229,9 @@ int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *chan
|
|||
int ret;
|
||||
va_list valist;
|
||||
|
||||
if (!(get_channel_flags( channel ) & (1 << cls))) return -1;
|
||||
if (!format) return 0;
|
||||
|
||||
va_start(valist, format);
|
||||
ret = funcs.dbg_vlog( cls, channel, func, format, valist );
|
||||
va_end(valist);
|
||||
|
|
|
@ -80,6 +80,7 @@ static int nb_dll_paths;
|
|||
static int dll_path_maxlen;
|
||||
|
||||
extern void mmap_init(void);
|
||||
extern void debug_init(void);
|
||||
|
||||
/* build the dll load path from the WINEDLLPATH variable */
|
||||
static void build_dll_path(void)
|
||||
|
@ -524,22 +525,6 @@ int wine_dll_get_owner( const char *name, char *buffer, int size, int *exists )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* debug_usage
|
||||
*/
|
||||
static void debug_usage(void)
|
||||
{
|
||||
static const char usage[] =
|
||||
"Syntax of the WINEDEBUG variable:\n"
|
||||
" WINEDEBUG=[class]+xxx,[class]-yyy,...\n\n"
|
||||
"Example: WINEDEBUG=+all,warn-heap\n"
|
||||
" turns on all messages except warning heap messages\n"
|
||||
"Available message classes: err, warn, fixme, trace\n";
|
||||
write( 2, usage, sizeof(usage) - 1 );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wine_init
|
||||
*
|
||||
|
@ -549,7 +534,6 @@ void wine_init( int argc, char *argv[], char *error, int error_size )
|
|||
{
|
||||
struct dll_path_context context;
|
||||
char *path;
|
||||
char *wine_debug;
|
||||
void *ntdll = NULL;
|
||||
void (*init_func)(void);
|
||||
|
||||
|
@ -559,12 +543,7 @@ void wine_init( int argc, char *argv[], char *error, int error_size )
|
|||
__wine_main_argv = argv;
|
||||
__wine_main_environ = environ;
|
||||
mmap_init();
|
||||
|
||||
if ((wine_debug = getenv("WINEDEBUG")))
|
||||
{
|
||||
if (!strcmp( wine_debug, "help" )) debug_usage();
|
||||
wine_dbg_parse_options( wine_debug );
|
||||
}
|
||||
debug_init();
|
||||
|
||||
for (path = first_dll_path( "ntdll.dll", ".so", &context ); path; path = next_dll_path( &context ))
|
||||
{
|
||||
|
|
|
@ -10,9 +10,7 @@ EXPORTS
|
|||
__wine_main_environ
|
||||
__wine_main_wargv
|
||||
wine_anon_mmap
|
||||
wine_dbg_add_option
|
||||
wine_dbg_log
|
||||
wine_dbg_parse_options
|
||||
wine_dbg_printf
|
||||
wine_dbg_sprintf
|
||||
wine_dbgstr_a
|
||||
|
|
|
@ -10,9 +10,7 @@ WINE_1.0
|
|||
__wine_main_environ;
|
||||
__wine_main_wargv;
|
||||
wine_anon_mmap;
|
||||
wine_dbg_add_option;
|
||||
wine_dbg_log;
|
||||
wine_dbg_parse_options;
|
||||
wine_dbg_printf;
|
||||
wine_dbg_sprintf;
|
||||
wine_dbgstr_a;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
|
||||
#include <windows.h>
|
||||
#include <ctype.h>
|
||||
#include <commctrl.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
@ -34,7 +35,7 @@
|
|||
#include "taskmgr.h"
|
||||
#include "perfdata.h"
|
||||
#include "column.h"
|
||||
#include <ctype.h>
|
||||
#include "wine/debug.h"
|
||||
|
||||
/* TODO:
|
||||
* - the dialog box could be non modal
|
||||
|
@ -104,7 +105,7 @@ static DWORD get_selected_pid(void)
|
|||
return dwProcessId;
|
||||
}
|
||||
|
||||
static int list_channel_CB(HANDLE hProcess, void* addr, char* buffer, void* user)
|
||||
static int list_channel_CB(HANDLE hProcess, void* addr, struct __wine_debug_channel* channel, void* user)
|
||||
{
|
||||
int j;
|
||||
char val[2];
|
||||
|
@ -115,7 +116,7 @@ static int list_channel_CB(HANDLE hProcess, void* addr, char* buffer, void*
|
|||
memset(&lvi, 0, sizeof(lvi));
|
||||
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.pszText = buffer + 1;
|
||||
lvi.pszText = channel->name;
|
||||
|
||||
index = ListView_InsertItem(hChannelLV, &lvi);
|
||||
if (index == -1) return 0;
|
||||
|
@ -123,7 +124,7 @@ static int list_channel_CB(HANDLE hProcess, void* addr, char* buffer, void*
|
|||
val[1] = '\0';
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
val[0] = (buffer[0] & (1 << j)) ? 'x' : ' ';
|
||||
val[0] = (channel->flags & (1 << j)) ? 'x' : ' ';
|
||||
ListView_SetItemText(hChannelLV, index, j + 1, val);
|
||||
}
|
||||
return 1;
|
||||
|
@ -142,14 +143,14 @@ struct cce_user
|
|||
*
|
||||
* Callback used for changing a given channel attributes
|
||||
*/
|
||||
static int change_channel_CB(HANDLE hProcess, void* addr, char* buffer, void* pmt)
|
||||
static int change_channel_CB(HANDLE hProcess, void* addr, struct __wine_debug_channel *channel, void* pmt)
|
||||
{
|
||||
struct cce_user* user = (struct cce_user*)pmt;
|
||||
|
||||
if (!user->name || !strcmp(buffer + 1, user->name))
|
||||
if (!user->name || !strcmp(channel->name, user->name))
|
||||
{
|
||||
buffer[0] = (buffer[0] & ~user->mask) | (user->value & user->mask);
|
||||
if (WriteProcessMemory(hProcess, addr, buffer, 1, NULL))
|
||||
channel->flags = (channel->flags & ~user->mask) | (user->value & user->mask);
|
||||
if (WriteProcessMemory(hProcess, addr, channel, sizeof(*channel), NULL))
|
||||
user->done++;
|
||||
else
|
||||
user->notdone++;
|
||||
|
@ -187,7 +188,7 @@ struct dll_option_layout
|
|||
int nb_channels;
|
||||
};
|
||||
|
||||
typedef int (*EnumChannelCB)(HANDLE, void*, char*, void*);
|
||||
typedef int (*EnumChannelCB)(HANDLE, void*, struct __wine_debug_channel*, void*);
|
||||
|
||||
/******************************************************************
|
||||
* enum_channel
|
||||
|
@ -197,49 +198,25 @@ typedef int (*EnumChannelCB)(HANDLE, void*, char*, void*);
|
|||
*/
|
||||
static int enum_channel(HANDLE hProcess, EnumChannelCB ce, void* user, unsigned unique)
|
||||
{
|
||||
struct dll_option_layout dol;
|
||||
int i, ret = 1;
|
||||
struct __wine_debug_channel channel;
|
||||
int ret = 1;
|
||||
unsigned int j;
|
||||
void* buf_addr;
|
||||
char buffer[32];
|
||||
void* addr;
|
||||
const char** cache = NULL;
|
||||
unsigned num_cache, used_cache;
|
||||
|
||||
if (!(addr = get_symbol(hProcess, "first_dll", "libwine.so"))) return -1;
|
||||
if (!(addr = get_symbol(hProcess, "debug_options", "libwine.so"))) return -1;
|
||||
if (unique)
|
||||
cache = HeapAlloc(GetProcessHeap(), 0, (num_cache = 32) * sizeof(char*));
|
||||
else
|
||||
num_cache = 0;
|
||||
used_cache = 0;
|
||||
|
||||
for (;
|
||||
ret && addr && ReadProcessMemory(hProcess, addr, &dol, sizeof(dol), NULL);
|
||||
addr = dol.next)
|
||||
while (ret && addr && ReadProcessMemory(hProcess, addr, &channel, sizeof(channel), NULL))
|
||||
{
|
||||
for (i = 0; i < dol.nb_channels; i++)
|
||||
{
|
||||
if (ReadProcessMemory(hProcess, (void const *)(dol.channels + i), &buf_addr, sizeof(buf_addr), NULL) &&
|
||||
ReadProcessMemory(hProcess, buf_addr, buffer, sizeof(buffer), NULL))
|
||||
{
|
||||
if (unique)
|
||||
{
|
||||
/* since some channels are defined in multiple compilation units,
|
||||
* they will appear several times...
|
||||
* so cache the channel's names we already reported and don't report
|
||||
* them again
|
||||
*/
|
||||
for (j = 0; j < used_cache; j++)
|
||||
if (!strcmp(cache[j], buffer + 1)) break;
|
||||
if (j != used_cache) continue;
|
||||
if (used_cache == num_cache)
|
||||
cache = HeapReAlloc(GetProcessHeap(), 0, cache, (num_cache *= 2) * sizeof(char*));
|
||||
cache[used_cache++] = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(buffer + 1) + 1),
|
||||
buffer + 1);
|
||||
}
|
||||
ret = ce(hProcess, buf_addr, buffer, user);
|
||||
}
|
||||
}
|
||||
if (!channel.name[0]) break;
|
||||
ret = ce(hProcess, addr, &channel, user);
|
||||
addr = (struct __wine_debug_channel *)addr + 1;
|
||||
}
|
||||
if (unique)
|
||||
{
|
||||
|
|
|
@ -678,21 +678,10 @@ void info_win32_virtual(DWORD pid)
|
|||
if (pid != dbg_curr_pid) CloseHandle(hProc);
|
||||
}
|
||||
|
||||
struct dll_option_layout
|
||||
{
|
||||
void* next;
|
||||
void* prev;
|
||||
char* const* channels;
|
||||
int nb_channels;
|
||||
};
|
||||
|
||||
void info_wine_dbg_channel(BOOL turn_on, const char* chnl, const char* name)
|
||||
void info_wine_dbg_channel(BOOL turn_on, const char* cls, const char* name)
|
||||
{
|
||||
struct dbg_lvalue lvalue;
|
||||
struct dll_option_layout dol;
|
||||
int i;
|
||||
char* str;
|
||||
char buffer[32];
|
||||
struct __wine_debug_channel channel;
|
||||
unsigned char mask;
|
||||
int done = 0;
|
||||
BOOL bAll;
|
||||
|
@ -704,32 +693,34 @@ void info_wine_dbg_channel(BOOL turn_on, const char* chnl, const char* name)
|
|||
return;
|
||||
}
|
||||
|
||||
if (symbol_get_lvalue("first_dll", -1, &lvalue, FALSE) != sglv_found)
|
||||
if (symbol_get_lvalue("debug_options", -1, &lvalue, FALSE) != sglv_found)
|
||||
{
|
||||
return;
|
||||
}
|
||||
addr = memory_to_linear_addr(&lvalue.addr);
|
||||
if (!chnl) mask = 15;
|
||||
else if (!strcmp(chnl, "fixme")) mask = 1;
|
||||
else if (!strcmp(chnl, "err")) mask = 2;
|
||||
else if (!strcmp(chnl, "warn")) mask = 4;
|
||||
else if (!strcmp(chnl, "trace")) mask = 8;
|
||||
else { dbg_printf("Unknown channel %s\n", chnl); return; }
|
||||
|
||||
if (!cls) mask = ~0;
|
||||
else if (!strcmp(cls, "fixme")) mask = (1 << __WINE_DBCL_FIXME);
|
||||
else if (!strcmp(cls, "err")) mask = (1 << __WINE_DBCL_ERR);
|
||||
else if (!strcmp(cls, "warn")) mask = (1 << __WINE_DBCL_WARN);
|
||||
else if (!strcmp(cls, "trace")) mask = (1 << __WINE_DBCL_TRACE);
|
||||
else
|
||||
{
|
||||
dbg_printf("Unknown debug class %s\n", cls);
|
||||
return;
|
||||
}
|
||||
|
||||
bAll = !strcmp("all", name);
|
||||
while (addr && dbg_read_memory(addr, &dol, sizeof(dol)))
|
||||
while (addr && dbg_read_memory(addr, &channel, sizeof(channel)))
|
||||
{
|
||||
for (i = 0; i < dol.nb_channels; i++)
|
||||
if (!channel.name[0]) break;
|
||||
if (bAll || !strcmp( channel.name, name ))
|
||||
{
|
||||
if (dbg_read_memory(dol.channels + i, &str, sizeof(str)) &&
|
||||
dbg_read_memory(str, buffer, sizeof(buffer)) &&
|
||||
(!strcmp(buffer + 1, name) || bAll))
|
||||
{
|
||||
if (turn_on) buffer[0] |= mask; else buffer[0] &= ~mask;
|
||||
if (dbg_write_memory(str, buffer, 1)) done++;
|
||||
if (turn_on) channel.flags |= mask;
|
||||
else channel.flags &= ~mask;
|
||||
if (dbg_write_memory(addr, &channel, sizeof(channel))) done++;
|
||||
}
|
||||
}
|
||||
addr = dol.next;
|
||||
addr = (struct __wine_debug_channel *)addr + 1;
|
||||
}
|
||||
if (!done) dbg_printf("Unable to find debug channel %s\n", name);
|
||||
else WINE_TRACE("Changed %d channel instances\n", done);
|
||||
|
|
Loading…
Reference in New Issue