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:
Eric Pouech 2000-05-05 18:14:34 +00:00 committed by Alexandre Julliard
parent 47bea26a2a
commit b971745ca0
7 changed files with 161 additions and 84 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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 );

View File

@ -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)

View File

@ -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);
}

View File

@ -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;

View File

@ -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());