Fixed some buffer overflows.
Made stab parsing more robust (now ignores C++ stabs). Display correct backtrace at first when invoked on unhandled exception. Loads stabs from .so files when those are loaded.
This commit is contained in:
parent
47bea26a2a
commit
b971745ca0
|
@ -178,7 +178,7 @@ void DEBUG_SetBreakpoints( BOOL set )
|
|||
case DBG_BREAK:
|
||||
{
|
||||
#ifdef __i386__
|
||||
char ch = set ? INT3 : breakpoints[i].u.opcode;
|
||||
char ch = set ? INT3 : breakpoints[i].u.b.opcode;
|
||||
#endif
|
||||
|
||||
if (!DEBUG_WRITE_MEM( (void*)DEBUG_ToLinear(&breakpoints[i].addr),
|
||||
|
@ -322,7 +322,7 @@ static BOOL DEBUG_GetWatchedValue( int num, LPDWORD val )
|
|||
*
|
||||
* Add a breakpoint.
|
||||
*/
|
||||
void DEBUG_AddBreakpoint( const DBG_VALUE *_value )
|
||||
void DEBUG_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) )
|
||||
{
|
||||
DBG_VALUE value = *_value;
|
||||
int num;
|
||||
|
@ -358,7 +358,8 @@ void DEBUG_AddBreakpoint( const DBG_VALUE *_value )
|
|||
if ((num = DEBUG_InitXPoint(DBG_BREAK, &value.addr)) == -1)
|
||||
return;
|
||||
|
||||
breakpoints[num].u.opcode = ch;
|
||||
breakpoints[num].u.b.opcode = ch;
|
||||
breakpoints[num].u.b.func = func;
|
||||
|
||||
DEBUG_Printf( DBG_CHN_MESG, "Breakpoint %d at ", num );
|
||||
DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? 32 : 16,
|
||||
|
@ -628,7 +629,7 @@ static BOOL DEBUG_ShallBreak( int bpnum )
|
|||
if ( breakpoints[bpnum].skipcount > 0 && --breakpoints[bpnum].skipcount > 0 )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return (breakpoints[bpnum].u.b.func) ? (breakpoints[bpnum].u.b.func)() : TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -881,7 +882,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
|
|||
breakpoints[0].enabled = TRUE;
|
||||
breakpoints[0].refcount = 1;
|
||||
breakpoints[0].skipcount = 0;
|
||||
DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].u.opcode,
|
||||
DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].u.b.opcode,
|
||||
sizeof(char));
|
||||
DEBUG_SetBreakpoints( TRUE );
|
||||
break;
|
||||
|
@ -899,7 +900,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
|
|||
breakpoints[0].enabled = TRUE;
|
||||
breakpoints[0].refcount = 1;
|
||||
breakpoints[0].skipcount = 0;
|
||||
DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].u.opcode,
|
||||
DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].u.b.opcode,
|
||||
sizeof(char));
|
||||
DEBUG_SetBreakpoints( TRUE );
|
||||
break;
|
||||
|
|
|
@ -197,12 +197,12 @@ print_command:
|
|||
DEBUG_FreeExprMem(); }
|
||||
|
||||
break_command:
|
||||
tBREAK '*' expr_addr tEOL { DEBUG_AddBreakpoint( &$3 );
|
||||
tBREAK '*' expr_addr tEOL { DEBUG_AddBreakpoint( &$3, NULL );
|
||||
DEBUG_FreeExprMem(); }
|
||||
| tBREAK tIDENTIFIER tEOL { DBG_VALUE value;
|
||||
if( DEBUG_GetSymbolValue($2, -1, &value, TRUE) )
|
||||
{
|
||||
DEBUG_AddBreakpoint( &value );
|
||||
DEBUG_AddBreakpoint( &value, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -212,7 +212,7 @@ break_command:
|
|||
| tBREAK tIDENTIFIER ':' tNUM tEOL { DBG_VALUE value;
|
||||
if( DEBUG_GetSymbolValue($2, $4, &value, TRUE) )
|
||||
{
|
||||
DEBUG_AddBreakpoint( &value );
|
||||
DEBUG_AddBreakpoint( &value, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -229,7 +229,7 @@ break_command:
|
|||
DEBUG_GetLineNumberAddr(nh, $2, &value.addr, TRUE);
|
||||
value.type = NULL;
|
||||
value.cookie = DV_TARGET;
|
||||
DEBUG_AddBreakpoint( &value );
|
||||
DEBUG_AddBreakpoint( &value, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -241,7 +241,7 @@ break_command:
|
|||
DEBUG_GetCurrentAddress( &value.addr );
|
||||
value.type = NULL;
|
||||
value.cookie = DV_TARGET;
|
||||
DEBUG_AddBreakpoint( &value );
|
||||
DEBUG_AddBreakpoint( &value, NULL );
|
||||
}
|
||||
|
||||
watch_command:
|
||||
|
|
|
@ -115,8 +115,8 @@ enum exec_mode
|
|||
EXEC_KILL /* terminate debugging session */
|
||||
};
|
||||
|
||||
#define DBG_BREAK 0
|
||||
#define DBG_WATCH 1
|
||||
#define DBG_BREAK 0
|
||||
#define DBG_WATCH 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -127,7 +127,10 @@ typedef struct
|
|||
refcount : 13;
|
||||
WORD skipcount;
|
||||
union {
|
||||
BYTE opcode;
|
||||
struct {
|
||||
BYTE opcode;
|
||||
BOOL (*func)(void);
|
||||
} b;
|
||||
struct {
|
||||
BYTE rw : 1,
|
||||
len : 2;
|
||||
|
@ -158,7 +161,9 @@ typedef struct tagDBG_PROCESS {
|
|||
DWORD pid;
|
||||
DBG_THREAD* threads;
|
||||
int num_threads;
|
||||
unsigned continue_on_first_exception;
|
||||
struct tagDBG_MODULE* modules;
|
||||
unsigned long dbg_hdr_addr;
|
||||
/*
|
||||
* This is an index we use to keep track of the debug information
|
||||
* when we have multiple sources. We use the same database to also
|
||||
|
@ -219,7 +224,7 @@ typedef struct {
|
|||
|
||||
/* debugger/break.c */
|
||||
extern void DEBUG_SetBreakpoints( BOOL set );
|
||||
extern void DEBUG_AddBreakpoint( const DBG_VALUE *addr );
|
||||
extern void DEBUG_AddBreakpoint( const DBG_VALUE *addr, BOOL (*func)(void) );
|
||||
extern void DEBUG_AddWatchpoint( const DBG_VALUE *addr, int is_write );
|
||||
extern void DEBUG_DelBreakpoint( int num );
|
||||
extern void DEBUG_EnableBreakpoint( int num, BOOL enable );
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/* break handling */
|
||||
INTERNAL_VAR(BreakAllThreadsStartup, FALSE, NULL, DEBUG_TypeIntConst)
|
||||
INTERNAL_VAR(BreakOnCritSectTimeOut, FALSE, NULL, DEBUG_TypeIntConst)
|
||||
INTERNAL_VAR(BreakOnAttach, FALSE, NULL, DEBUG_TypeIntConst)
|
||||
|
||||
/* output handling */
|
||||
INTERNAL_VAR(ConChannelMask, DBG_CHN_MESG, NULL, DEBUG_TypeIntConst)
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "file.h"
|
||||
#include "debugger.h"
|
||||
#include "toolhelp.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Creates and links a new module to the current process
|
||||
|
@ -235,7 +237,7 @@ static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleA
|
|||
void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
||||
{
|
||||
DBG_VALUE value;
|
||||
char buffer[256];
|
||||
char buffer[512];
|
||||
char bufstr[256];
|
||||
int i;
|
||||
IMAGE_NT_HEADERS pe_header;
|
||||
|
@ -273,7 +275,7 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
|||
DEBUG_AddSymbol(name, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
||||
|
||||
/* Add entry point */
|
||||
sprintf(buffer, "%s.EntryPoint", name);
|
||||
wsnprintf(buffer, sizeof(buffer), "%s.EntryPoint", name);
|
||||
value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
|
||||
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
||||
|
||||
|
@ -284,7 +286,7 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
|||
for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
|
||||
if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
|
||||
continue;
|
||||
sprintf(buffer, "%s.%s", name, pe_seg.Name);
|
||||
wsnprintf(buffer, sizeof(buffer), "%s.%s", name, pe_seg.Name);
|
||||
value.addr.off = base + pe_seg.VirtualAddress;
|
||||
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
||||
}
|
||||
|
@ -320,7 +322,7 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
|||
!DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
|
||||
continue;
|
||||
bufstr[sizeof(bufstr) - 1] = 0;
|
||||
sprintf(buffer, "%s.%s", name, bufstr);
|
||||
wsnprintf(buffer, sizeof(buffer), "%s.%s", name, bufstr);
|
||||
value.addr.off = base + (DWORD)functions[ordinals[i]];
|
||||
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
||||
}
|
||||
|
@ -331,7 +333,7 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
|||
for (j = 0; j < exports.NumberOfNames; j++)
|
||||
if ((ordinals[j] == i) && names[j]) break;
|
||||
if (j < exports.NumberOfNames) continue;
|
||||
sprintf(buffer, "%s.%ld", name, i + exports.Base);
|
||||
wsnprintf(buffer, sizeof(buffer), "%s.%ld", name, i + exports.Base);
|
||||
value.addr.off = base + (DWORD)functions[i];
|
||||
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
||||
}
|
||||
|
|
132
debugger/stabs.c
132
debugger/stabs.c
|
@ -120,16 +120,17 @@ static unsigned int stab_hash( const char * name )
|
|||
}
|
||||
|
||||
|
||||
static void stab_strcpy(char * dest, const char * source)
|
||||
static void stab_strcpy(char * dest, int sz, const char * source)
|
||||
{
|
||||
/*
|
||||
* A strcpy routine that stops when we hit the ':' character.
|
||||
* Faster than copying the whole thing, and then nuking the
|
||||
* ':'.
|
||||
*/
|
||||
while(*source != '\0' && *source != ':')
|
||||
while(*source != '\0' && *source != ':' && sz-- > 0)
|
||||
*dest++ = *source++;
|
||||
*dest++ = '\0';
|
||||
*dest = '\0';
|
||||
assert(sz > 0);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -402,7 +403,7 @@ DEBUG_HandlePreviousTypedef(const char * name, const char * stab)
|
|||
expect = DT_FUNC;
|
||||
break;
|
||||
default:
|
||||
DEBUG_Printf(DBG_CHN_MESG, "Unknown type (%c).\n",ptr[1]);
|
||||
DEBUG_Printf(DBG_CHN_FIXME, "Unknown type (%c).\n",ptr[1]);
|
||||
return FALSE;
|
||||
}
|
||||
if( expect != -1 && expect != DEBUG_GetType(ktd->types[count]) )
|
||||
|
@ -521,7 +522,7 @@ DEBUG_ParseTypedefStab(char * ptr, const char * typename)
|
|||
curr_types[ntypes++] = *dt;
|
||||
break;
|
||||
case 'x':
|
||||
stab_strcpy(element_name, c + 3);
|
||||
stab_strcpy(element_name, sizeof(element_name), c + 3);
|
||||
*dt = DEBUG_NewDataType(DT_STRUCT, element_name);
|
||||
curr_types[ntypes++] = *dt;
|
||||
break;
|
||||
|
@ -534,7 +535,8 @@ DEBUG_ParseTypedefStab(char * ptr, const char * typename)
|
|||
curr_types[ntypes++] = *dt;
|
||||
break;
|
||||
default:
|
||||
DEBUG_Printf(DBG_CHN_MESG, "Unknown type (%c).\n",c[1]);
|
||||
DEBUG_Printf(DBG_CHN_FIXME, "Unknown type (%c).\n",c[1]);
|
||||
return FALSE;
|
||||
}
|
||||
typename = NULL;
|
||||
|
||||
|
@ -722,8 +724,8 @@ DEBUG_ParseTypedefStab(char * ptr, const char * typename)
|
|||
strcpy(c, tc + 1);
|
||||
break;
|
||||
default:
|
||||
DEBUG_Printf(DBG_CHN_MESG, "Unknown type (%c).\n",c[1]);
|
||||
break;
|
||||
DEBUG_Printf(DBG_CHN_FIXME, "Unknown type (%c).\n",c[1]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -838,8 +840,12 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
strcpy(stabbuff, ptr);
|
||||
ptr = stabbuff;
|
||||
}
|
||||
stab_strcpy(symname, ptr);
|
||||
DEBUG_ParseTypedefStab(ptr, symname);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
if (!DEBUG_ParseTypedefStab(ptr, symname)) {
|
||||
/* skip this definition */
|
||||
stabbuff[0] = '\0';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch(stab_ptr->n_type)
|
||||
|
@ -858,7 +864,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
new_value.addr.off = load_offset + stab_ptr->n_value;
|
||||
new_value.cookie = DV_TARGET;
|
||||
|
||||
stab_strcpy(symname, ptr);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
#ifdef __ELF__
|
||||
curr_sym = DEBUG_AddSymbol( symname, &new_value, currpath,
|
||||
SYM_WINE | SYM_DATA | SYM_INVALID );
|
||||
|
@ -887,7 +893,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
new_value.addr.off = load_offset + stab_ptr->n_value;
|
||||
new_value.cookie = DV_TARGET;
|
||||
|
||||
stab_strcpy(symname, ptr);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
curr_sym = DEBUG_AddSymbol( symname, &new_value, currpath,
|
||||
SYM_WINE | SYM_DATA );
|
||||
break;
|
||||
|
@ -897,7 +903,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
*/
|
||||
if( curr_func != NULL && !in_external_file )
|
||||
{
|
||||
stab_strcpy(symname, ptr);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
curr_loc = DEBUG_AddLocal( curr_func, 0,
|
||||
stab_ptr->n_value, 0, 0, symname );
|
||||
DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr) );
|
||||
|
@ -906,7 +912,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
case N_RSYM:
|
||||
if( curr_func != NULL && !in_external_file )
|
||||
{
|
||||
stab_strcpy(symname, ptr);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
curr_loc = DEBUG_AddLocal( curr_func, stab_ptr->n_value + 1,
|
||||
0, 0, 0, symname );
|
||||
DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr) );
|
||||
|
@ -915,7 +921,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
case N_LSYM:
|
||||
if( curr_func != NULL && !in_external_file )
|
||||
{
|
||||
stab_strcpy(symname, ptr);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
curr_loc = DEBUG_AddLocal( curr_func, 0,
|
||||
stab_ptr->n_value, 0, 0, symname );
|
||||
DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr) );
|
||||
|
@ -957,7 +963,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
*/
|
||||
if( !in_external_file)
|
||||
{
|
||||
stab_strcpy(symname, ptr);
|
||||
stab_strcpy(symname, sizeof(symname), ptr);
|
||||
if (*symname)
|
||||
{
|
||||
new_value.addr.seg = 0;
|
||||
|
@ -1302,15 +1308,61 @@ leave:
|
|||
return rtn;
|
||||
}
|
||||
|
||||
static BOOL DEBUG_WalkList(struct r_debug* dbg_hdr)
|
||||
{
|
||||
u_long lm_addr;
|
||||
struct link_map lm;
|
||||
Elf32_Ehdr ehdr;
|
||||
char bufstr[256];
|
||||
|
||||
/*
|
||||
* Now walk the linked list. In all known ELF implementations,
|
||||
* the dynamic loader maintains this linked list for us. In some
|
||||
* cases the first entry doesn't appear with a name, in other cases it
|
||||
* does.
|
||||
*/
|
||||
for (lm_addr = (u_long)dbg_hdr->r_map; lm_addr; lm_addr = (u_long)lm.l_next) {
|
||||
if (!DEBUG_READ_MEM_VERBOSE((void*)lm_addr, &lm, sizeof(lm)))
|
||||
return FALSE;
|
||||
if (lm.l_addr != 0 &&
|
||||
DEBUG_READ_MEM_VERBOSE((void*)lm.l_addr, &ehdr, sizeof(ehdr)) &&
|
||||
ehdr.e_type == ET_DYN && /* only look at dynamic modules */
|
||||
lm.l_name != NULL &&
|
||||
DEBUG_READ_MEM_VERBOSE(lm.l_name, bufstr, sizeof(bufstr))) {
|
||||
bufstr[sizeof(bufstr) - 1] = '\0';
|
||||
DEBUG_ProcessElfObject(bufstr, lm.l_addr);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DEBUG_RescanElf(void)
|
||||
{
|
||||
struct r_debug dbg_hdr;
|
||||
|
||||
if (!DEBUG_CurrProcess ||
|
||||
!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_CurrProcess->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)))
|
||||
return FALSE;
|
||||
|
||||
switch (dbg_hdr.r_state) {
|
||||
case RT_CONSISTENT:
|
||||
DEBUG_WalkList(&dbg_hdr);
|
||||
break;
|
||||
case RT_ADD:
|
||||
break;
|
||||
case RT_DELETE:
|
||||
/*FIXME: this is not currently handled, would need some kind of mark&sweep algo */
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
||||
{
|
||||
Elf32_Dyn dyn;
|
||||
struct r_debug dbg_hdr;
|
||||
u_long lm_addr;
|
||||
struct link_map lm;
|
||||
Elf32_Ehdr ehdr;
|
||||
char bufstr[256];
|
||||
int rtn = FALSE;
|
||||
DBG_VALUE val;
|
||||
|
||||
|
@ -1341,27 +1393,25 @@ DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
|||
if (!DEBUG_READ_MEM_VERBOSE((void*)dyn.d_un.d_ptr, &dbg_hdr, sizeof(dbg_hdr)))
|
||||
goto leave;
|
||||
|
||||
/*
|
||||
* Now walk the linked list. In all known ELF implementations,
|
||||
* the dynamic loader maintains this linked list for us. In some
|
||||
* cases the first entry doesn't appear with a name, in other cases it
|
||||
* does.
|
||||
*/
|
||||
for (lm_addr = (u_long)dbg_hdr.r_map; lm_addr; lm_addr = (u_long)lm.l_next)
|
||||
{
|
||||
if (!DEBUG_READ_MEM_VERBOSE((void*)lm_addr, &lm, sizeof(lm)))
|
||||
goto leave;
|
||||
if (lm.l_addr != 0 &&
|
||||
DEBUG_READ_MEM_VERBOSE((void*)lm.l_addr, &ehdr, sizeof(ehdr)) &&
|
||||
ehdr.e_type == ET_DYN && /* only look at dynamic modules */
|
||||
lm.l_name != NULL &&
|
||||
DEBUG_READ_MEM_VERBOSE(lm.l_name, bufstr, sizeof(bufstr))) {
|
||||
bufstr[sizeof(bufstr) - 1] = '\0';
|
||||
DEBUG_ProcessElfObject(bufstr, lm.l_addr);
|
||||
}
|
||||
}
|
||||
|
||||
rtn = TRUE;
|
||||
assert(!DEBUG_CurrProcess->dbg_hdr_addr);
|
||||
DEBUG_CurrProcess->dbg_hdr_addr = (u_long)dyn.d_un.d_ptr;
|
||||
|
||||
if (dbg_hdr.r_brk) {
|
||||
DBG_VALUE value;
|
||||
|
||||
DEBUG_Printf(DBG_CHN_TRACE, "Setting up a breakpoint on r_brk(%lx)\n",
|
||||
dbg_hdr.r_brk);
|
||||
|
||||
DEBUG_SetBreakpoints(FALSE);
|
||||
value.type = NULL;
|
||||
value.cookie = DV_TARGET;
|
||||
value.addr.seg = 0;
|
||||
value.addr.off = dbg_hdr.r_brk;
|
||||
DEBUG_AddBreakpoint(&value, DEBUG_RescanElf);
|
||||
DEBUG_SetBreakpoints(TRUE);
|
||||
}
|
||||
|
||||
rtn = DEBUG_WalkList(&dbg_hdr);
|
||||
|
||||
leave:
|
||||
return rtn;
|
||||
|
|
|
@ -44,8 +44,14 @@ int DEBUG_Printf(int chn, const char* format, ...)
|
|||
int len;
|
||||
|
||||
va_start(valist, format);
|
||||
len = vsprintf(buf, format, valist);
|
||||
len = wvsnprintf(buf, sizeof(buf), format, valist);
|
||||
va_end(valist);
|
||||
|
||||
if (len <= -1) {
|
||||
len = sizeof(buf) - 1;
|
||||
buf[len] = 0;
|
||||
buf[len - 1] = buf[len - 2] = buf[len - 3] = '.';
|
||||
}
|
||||
DEBUG_Output(chn, buf, len);
|
||||
return len;
|
||||
}
|
||||
|
@ -110,8 +116,8 @@ DBG_INTVAR* DEBUG_GetIntVar(const char* name)
|
|||
|
||||
static WINE_EXCEPTION_FILTER(wine_dbg)
|
||||
{
|
||||
DEBUG_Printf(DBG_CHN_MESG, "\nwine_dbg: Exception (%lx) inside debugger, continuing...\n", GetExceptionCode());
|
||||
DEBUG_ExternalDebugger();
|
||||
DEBUG_Printf(DBG_CHN_MESG, "\nwine_dbg: Exception %lx\n", GetExceptionCode());
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
|
@ -133,8 +139,10 @@ static DBG_PROCESS* DEBUG_AddProcess(DWORD pid, HANDLE h)
|
|||
p->pid = pid;
|
||||
p->threads = NULL;
|
||||
p->num_threads = 0;
|
||||
p->continue_on_first_exception = FALSE;
|
||||
p->modules = NULL;
|
||||
p->next_index = 0;
|
||||
p->dbg_hdr_addr = 0;
|
||||
|
||||
p->next = proc;
|
||||
p->prev = NULL;
|
||||
|
@ -229,7 +237,7 @@ static void DEBUG_InitCurrThread(void)
|
|||
value.cookie = DV_TARGET;
|
||||
value.addr.seg = 0;
|
||||
value.addr.off = (DWORD)DEBUG_CurrThread->start;
|
||||
DEBUG_AddBreakpoint(&value);
|
||||
DEBUG_AddBreakpoint(&value, NULL);
|
||||
DEBUG_SetBreakpoints(TRUE);
|
||||
}
|
||||
} else {
|
||||
|
@ -268,7 +276,7 @@ static BOOL DEBUG_HandleException( EXCEPTION_RECORD *rec, BOOL first_chance, BOO
|
|||
/* print some infos */
|
||||
DEBUG_Printf( DBG_CHN_MESG, "%s: ",
|
||||
first_chance ? "First chance exception" : "Unhandled exception" );
|
||||
switch(rec->ExceptionCode)
|
||||
switch (rec->ExceptionCode)
|
||||
{
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
DEBUG_Printf( DBG_CHN_MESG, "divide by zero" );
|
||||
|
@ -312,10 +320,9 @@ static BOOL DEBUG_HandleException( EXCEPTION_RECORD *rec, BOOL first_chance, BOO
|
|||
DEBUG_Printf( DBG_CHN_MESG, "%08lx", rec->ExceptionCode );
|
||||
break;
|
||||
}
|
||||
DEBUG_Printf(DBG_CHN_MESG, "\n");
|
||||
}
|
||||
|
||||
DEBUG_Printf(DBG_CHN_MESG, "\n");
|
||||
|
||||
DEBUG_Printf(DBG_CHN_TRACE,
|
||||
"Entering debugger PC=%lx EFL=%08lx mode=%d count=%d\n",
|
||||
DEBUG_context.Eip, DEBUG_context.EFlags,
|
||||
|
@ -353,20 +360,24 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
|
|||
break;
|
||||
}
|
||||
|
||||
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx %d\n",
|
||||
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx\n",
|
||||
de->dwProcessId, de->dwThreadId,
|
||||
de->u.Exception.ExceptionRecord.ExceptionCode,
|
||||
DEBUG_CurrThread->wait_for_first_exception);
|
||||
|
||||
de->u.Exception.ExceptionRecord.ExceptionCode);
|
||||
|
||||
if (DEBUG_CurrProcess->continue_on_first_exception) {
|
||||
DEBUG_CurrProcess->continue_on_first_exception = FALSE;
|
||||
if (!DBG_IVAR(BreakOnAttach)) {
|
||||
*cont = DBG_CONTINUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_context.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS|CONTEXT_DEBUG_REGISTERS;
|
||||
if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) {
|
||||
DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n");
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG_Printf(DBG_CHN_TRACE, "%p:%p\n", de->u.Exception.ExceptionRecord.ExceptionAddress,
|
||||
(void*)DEBUG_context.Eip);
|
||||
|
||||
*cont = DEBUG_HandleException(&de->u.Exception.ExceptionRecord,
|
||||
de->u.Exception.dwFirstChance,
|
||||
DEBUG_CurrThread->wait_for_first_exception);
|
||||
|
@ -416,15 +427,19 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
|
|||
de->u.CreateProcessInfo.dwDebugInfoFileOffset,
|
||||
de->u.CreateProcessInfo.nDebugInfoSize);
|
||||
|
||||
if (DEBUG_GetProcess(de->dwProcessId) != NULL) {
|
||||
DEBUG_Printf(DBG_CHN_TRACE, "Skipping already defined process\n");
|
||||
break;
|
||||
}
|
||||
DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
|
||||
de->u.CreateProcessInfo.hProcess);
|
||||
if (DEBUG_CurrProcess == NULL) {
|
||||
DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
|
||||
break;
|
||||
if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) {
|
||||
if (DEBUG_CurrProcess->handle) {
|
||||
DEBUG_Printf(DBG_CHN_ERR, "Skipping already defined process\n");
|
||||
break;
|
||||
}
|
||||
DEBUG_CurrProcess->handle = de->u.CreateProcessInfo.hProcess;
|
||||
} else {
|
||||
DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
|
||||
de->u.CreateProcessInfo.hProcess);
|
||||
if (DEBUG_CurrProcess == NULL) {
|
||||
DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%p\n",
|
||||
|
@ -566,7 +581,7 @@ int DEBUG_main(int argc, char** argv)
|
|||
DEBUG_InitTypes();
|
||||
DEBUG_InitCVDataTypes();
|
||||
|
||||
/* Initialize internal vars */
|
||||
/* Initialize internal vars (types must be initialized before) */
|
||||
if (!DEBUG_IntVarsRW(TRUE)) return -1;
|
||||
|
||||
/* keep it as a guiexe for now, so that Wine won't touch the Unix stdin,
|
||||
|
@ -585,6 +600,9 @@ int DEBUG_main(int argc, char** argv)
|
|||
HANDLE hEvent;
|
||||
|
||||
if ((pid = atoi(argv[1])) != 0 && (hEvent = atoi(argv[2])) != 0) {
|
||||
if (!(DEBUG_CurrProcess = DEBUG_AddProcess(pid, 0))) goto leave;
|
||||
DEBUG_CurrProcess->continue_on_first_exception = TRUE;
|
||||
|
||||
if (!DebugActiveProcess(pid)) {
|
||||
DEBUG_Printf(DBG_CHN_ERR, "Can't attach process %ld: %ld\n",
|
||||
pid, GetLastError());
|
||||
|
|
Loading…
Reference in New Issue