[PATCH 01/12] [WineDbg]: active targets

Eric Pouech eric.pouech at wanadoo.fr
Fri Feb 24 15:12:59 CST 2006


Move all code related to an 'active' target (ie a running process)
from winedbg.c to tgt_active.c

This patch is a no-op (apart from moving, it exports a couple of
static vars/funcs, that will handled with in next patches)

A+
---

 programs/winedbg/debugger.h   |   13 +
 programs/winedbg/tgt_active.c |  746 +++++++++++++++++++++++++++++++++++++++++
 programs/winedbg/winedbg.c    |  742 -----------------------------------------
 3 files changed, 755 insertions(+), 746 deletions(-)

diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index 89ff56f..3c4acbf 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -365,6 +365,15 @@ extern void             symbol_info(cons
 extern int              symbol_info_locals(void);
 extern BOOL             symbol_is_local(const char* name);
 
+  /* tgt_active.c */
+extern void             dbg_run_debuggee(const char* args);
+extern void             dbg_wait_next_exception(DWORD cont, int count, int mode);
+  /* temporary for tgt_active.c */
+extern enum dbg_action_mode {none_mode = 0, winedbg_mode, automatic_mode, gdb_mode} dbg_action_mode;
+extern char* dbg_last_cmd_line;
+extern unsigned         dbg_main_loop(HANDLE);
+extern unsigned         dbg_start_debuggee(LPSTR cmdLine);
+
   /* tgt_minidump.c */
 extern void             minidump_write(const char*, const EXCEPTION_RECORD*);
 
@@ -393,7 +402,6 @@ extern const struct dbg_internal_var* db
 extern BOOL             dbg_attach_debuggee(DWORD pid, BOOL cofe, BOOL wfe);
 extern BOOL             dbg_detach_debuggee(void);
 extern BOOL             dbg_interrupt_debuggee(void);
-extern void             dbg_run_debuggee(const char* args);
 extern struct dbg_process* dbg_add_process(DWORD pid, HANDLE h);
 extern void             dbg_set_process_name(struct dbg_process* p, const char* name);
 extern struct dbg_process* dbg_get_process(DWORD pid);
@@ -401,10 +409,9 @@ extern void             dbg_del_process(
 struct dbg_thread*	dbg_add_thread(struct dbg_process* p, DWORD tid, HANDLE h, void* teb);
 extern struct dbg_thread* dbg_get_thread(struct dbg_process* p, DWORD tid);
 extern void             dbg_del_thread(struct dbg_thread* t);
-extern void             dbg_wait_next_exception(DWORD cont, int count, int mode);
 extern BOOL             dbg_get_debuggee_info(HANDLE hProcess, IMAGEHLP_MODULE* imh_mod);
 
-/* gdbproxy.c */
+  /* gdbproxy.c */
 extern BOOL             gdb_remote(unsigned int);
 
 static inline BOOL dbg_read_memory(const void* addr, void* buffer, size_t len)
diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c
index 9644987..5c7dfbe 100644
--- a/programs/winedbg/tgt_active.c
+++ b/programs/winedbg/tgt_active.c
@@ -1,7 +1,7 @@
 /*
  * Wine debugger - back-end for an active target
  *
- * Copyright 2005 Eric Pouech
+ * Copyright 2000-2006 Eric Pouech
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -32,8 +32,752 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
 
+/*static*/ char*	        dbg_last_cmd_line = NULL;
+/*static*/ enum dbg_action_mode dbg_action_mode;
+
 struct be_process_io be_process_active_io =
 {
     ReadProcessMemory,
     WriteProcessMemory,
 };
+
+static void dbg_init_current_process(void)
+{
+}
+
+static void dbg_init_current_thread(void* start)
+{
+    if (start)
+    {
+	if (dbg_curr_process->threads && 
+            !dbg_curr_process->threads->next && /* first thread ? */
+	    DBG_IVAR(BreakAllThreadsStartup)) 
+        {
+	    ADDRESS     addr;
+
+            break_set_xpoints(FALSE);
+	    addr.Mode   = AddrModeFlat;
+	    addr.Offset = (DWORD)start;
+	    break_add_break(&addr, TRUE, TRUE);
+	    break_set_xpoints(TRUE);
+	}
+    } 
+}
+
+static unsigned dbg_handle_debug_event(DEBUG_EVENT* de);
+
+/******************************************************************
+ *		dbg_attach_debuggee
+ *
+ * Sets the debuggee to <pid>
+ * cofe instructs winedbg what to do when first exception is received 
+ * (break=FALSE, continue=TRUE)
+ * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events
+ * until the first exception is received (aka: attach to an already running process)
+ */
+BOOL dbg_attach_debuggee(DWORD pid, BOOL cofe, BOOL wfe)
+{
+    DEBUG_EVENT         de;
+
+    if (!(dbg_curr_process = dbg_add_process(pid, 0))) return FALSE;
+
+    if (!DebugActiveProcess(pid)) 
+    {
+        dbg_printf("Can't attach process %lx: error %ld\n", pid, GetLastError());
+        dbg_del_process(dbg_curr_process);
+	return FALSE;
+    }
+    dbg_curr_process->continue_on_first_exception = cofe;
+
+    if (wfe) /* shall we proceed all debug events until we get an exception ? */
+    {
+        dbg_interactiveP = FALSE;
+        while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
+        {
+            if (dbg_handle_debug_event(&de)) break;
+        }
+        if (dbg_curr_process) dbg_interactiveP = TRUE;
+    }
+    return TRUE;
+}
+
+BOOL dbg_detach_debuggee(void)
+{
+    /* remove all set breakpoints in debuggee code */
+    break_set_xpoints(FALSE);
+    /* needed for single stepping (ugly).
+     * should this be handled inside the server ??? 
+     */
+    be_cpu->single_step(&dbg_context, FALSE);
+    SetThreadContext(dbg_curr_thread->handle, &dbg_context);
+    if (dbg_curr_thread->in_exception)
+        ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE);
+    if (!DebugActiveProcessStop(dbg_curr_pid)) return FALSE;
+    dbg_del_process(dbg_curr_process);
+
+    return TRUE;
+}
+
+static unsigned dbg_fetch_context(void)
+{
+    dbg_context.ContextFlags = CONTEXT_CONTROL
+        | CONTEXT_INTEGER
+#ifdef CONTEXT_SEGMENTS
+        | CONTEXT_SEGMENTS
+#endif
+#ifdef CONTEXT_DEBUG_REGISTERS
+        | CONTEXT_DEBUG_REGISTERS
+#endif
+        ;
+    if (!GetThreadContext(dbg_curr_thread->handle, &dbg_context))
+    {
+        WINE_WARN("Can't get thread's context\n");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
+{
+    ADDRESS     addr;
+    BOOL        is_break;
+
+    memory_get_current_pc(&addr);
+    break_suspend_execution();
+    dbg_curr_thread->excpt_record = *rec;
+    dbg_curr_thread->in_exception = TRUE;
+
+    if (!is_debug)
+    {
+        switch (addr.Mode)
+        {
+        case AddrModeFlat: dbg_printf(" in 32-bit code (0x%08lx)", addr.Offset); break;
+        case AddrModeReal: dbg_printf(" in vm86 code (%04x:%04lx)", addr.Segment, addr.Offset); break;
+        case AddrMode1616: dbg_printf(" in 16-bit code (%04x:%04lx)", addr.Segment, addr.Offset); break;
+        case AddrMode1632: dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, addr.Offset); break;
+        default: dbg_printf(" bad address");
+        }
+	dbg_printf(".\n");
+    }
+
+    /* this will resynchronize builtin dbghelp's internal ELF module list */
+    SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0);
+
+    /*
+     * Do a quiet backtrace so that we have an idea of what the situation
+     * is WRT the source files.
+     */
+    stack_fetch_frames();
+    if (is_debug &&
+	break_should_continue(&addr, rec->ExceptionCode, &dbg_curr_thread->exec_count, &is_break))
+	return FALSE;
+
+    if (addr.Mode != dbg_curr_thread->addr_mode)
+    {
+        const char* name = NULL;
+        
+        switch (addr.Mode)
+        {
+        case AddrMode1616: name = "16 bit";     break;
+        case AddrMode1632: name = "32 bit";     break;
+        case AddrModeReal: name = "vm86";       break;
+        case AddrModeFlat: name = "32 bit";     break;
+        }
+        
+        dbg_printf("In %s mode.\n", name);
+        dbg_curr_thread->addr_mode = addr.Mode;
+    }
+    display_print();
+
+    if (!is_debug)
+    {
+	/* This is a real crash, dump some info */
+	be_cpu->print_context(dbg_curr_thread->handle, &dbg_context);
+	stack_info();
+        be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
+	stack_backtrace(dbg_curr_tid);
+    }
+    else
+    {
+        static char*        last_name;
+        static char*        last_file;
+
+        char                buffer[sizeof(SYMBOL_INFO) + 256];
+        SYMBOL_INFO*        si = (SYMBOL_INFO*)buffer;
+        void*               lin = memory_to_linear_addr(&addr);
+        DWORD64             disp64;
+        IMAGEHLP_LINE       il;
+        DWORD               disp;
+
+        si->SizeOfStruct = sizeof(*si);
+        si->MaxNameLen   = 256;
+        il.SizeOfStruct = sizeof(il);
+        if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) &&
+            SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il))
+        {
+            if ((!last_name || strcmp(last_name, si->Name)) ||
+                (!last_file || strcmp(last_file, il.FileName)))
+            {
+                HeapFree(GetProcessHeap(), 0, last_name);
+                HeapFree(GetProcessHeap(), 0, last_file);
+                last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name);
+                last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName);
+                dbg_printf("%s () at %s:%ld\n", last_name, last_file, il.LineNumber);
+            }
+        }
+    }
+    if (!is_debug || is_break ||
+        dbg_curr_thread->exec_mode == dbg_exec_step_over_insn ||
+        dbg_curr_thread->exec_mode == dbg_exec_step_into_insn)
+    {
+        ADDRESS tmp = addr;
+        /* Show where we crashed */
+        memory_disasm_one_insn(&tmp);
+    }
+    source_list_from_addr(&addr, 0);
+
+    return TRUE;
+}
+
+static void dbg_exception_epilog(void)
+{
+    break_restart_execution(dbg_curr_thread->exec_count);
+    /*
+     * This will have gotten absorbed into the breakpoint info
+     * if it was used.  Otherwise it would have been ignored.
+     * In any case, we don't mess with it any more.
+     */
+    if (dbg_curr_thread->exec_mode == dbg_exec_cont)
+	dbg_curr_thread->exec_count = 0;
+    dbg_curr_thread->in_exception = FALSE;
+}
+
+static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance)
+{
+    BOOL                is_debug = FALSE;
+    THREADNAME_INFO*    pThreadName;
+    struct dbg_thread*  pThread;
+
+    assert(dbg_curr_thread);
+
+    WINE_TRACE("exception=%lx first_chance=%c\n",
+               rec->ExceptionCode, first_chance ? 'Y' : 'N');
+
+    switch (rec->ExceptionCode)
+    {
+    case EXCEPTION_BREAKPOINT:
+    case EXCEPTION_SINGLE_STEP:
+        is_debug = TRUE;
+        break;
+    case EXCEPTION_NAME_THREAD:
+        pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
+        if (pThreadName->dwThreadID == -1)
+            pThread = dbg_curr_thread;
+        else
+            pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID);
+
+        if (dbg_read_memory(pThreadName->szName, pThread->name, 9))
+            dbg_printf("Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
+                       pThread->tid, pThread->name);
+        return DBG_CONTINUE;
+    }
+
+    if (first_chance && !is_debug && !DBG_IVAR(BreakOnFirstChance) &&
+	!(rec->ExceptionFlags & EH_STACK_INVALID))
+    {
+        /* pass exception to program except for debug exceptions */
+        return DBG_EXCEPTION_NOT_HANDLED;
+    }
+
+    if (!is_debug)
+    {
+        /* print some infos */
+        dbg_printf("%s: ",
+                   first_chance ? "First chance exception" : "Unhandled exception");
+        switch (rec->ExceptionCode)
+        {
+        case EXCEPTION_INT_DIVIDE_BY_ZERO:
+            dbg_printf("divide by zero");
+            break;
+        case EXCEPTION_INT_OVERFLOW:
+            dbg_printf("overflow");
+            break;
+        case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+            dbg_printf("array bounds");
+            break;
+        case EXCEPTION_ILLEGAL_INSTRUCTION:
+            dbg_printf("illegal instruction");
+            break;
+        case EXCEPTION_STACK_OVERFLOW:
+            dbg_printf("stack overflow");
+            break;
+        case EXCEPTION_PRIV_INSTRUCTION:
+            dbg_printf("privileged instruction");
+            break;
+        case EXCEPTION_ACCESS_VIOLATION:
+            if (rec->NumberParameters == 2)
+                dbg_printf("page fault on %s access to 0x%08lx",
+                           rec->ExceptionInformation[0] ? "write" : "read",
+                           rec->ExceptionInformation[1]);
+            else
+                dbg_printf("page fault");
+            break;
+        case EXCEPTION_DATATYPE_MISALIGNMENT:
+            dbg_printf("Alignment");
+            break;
+	case DBG_CONTROL_C:
+            dbg_printf("^C");
+            break;
+        case CONTROL_C_EXIT:
+            dbg_printf("^C");
+            break;
+        case STATUS_POSSIBLE_DEADLOCK:
+        {
+            ADDRESS         addr;
+
+            addr.Mode   = AddrModeFlat;
+            addr.Offset = rec->ExceptionInformation[0];
+
+            dbg_printf("wait failed on critical section ");
+            print_address(&addr, FALSE);
+        }
+        if (!DBG_IVAR(BreakOnCritSectTimeOut))
+        {
+            dbg_printf("\n");
+            return DBG_EXCEPTION_NOT_HANDLED;
+        }
+        break;
+        case EXCEPTION_WINE_STUB:
+        {
+            char dll[32], name[64];
+            memory_get_string(dbg_curr_process,
+                              (void*)rec->ExceptionInformation[0], TRUE, FALSE,
+                              dll, sizeof(dll));
+            if (HIWORD(rec->ExceptionInformation[1]))
+                memory_get_string(dbg_curr_process,
+                                  (void*)rec->ExceptionInformation[1], TRUE, FALSE,
+                                  name, sizeof(name));
+            else
+                sprintf( name, "%ld", rec->ExceptionInformation[1] );
+            dbg_printf("unimplemented function %s.%s called", dll, name);
+        }
+        break;
+        case EXCEPTION_WINE_ASSERTION:
+            dbg_printf("assertion failed");
+            break;
+        case EXCEPTION_VM86_INTx:
+            dbg_printf("interrupt %02lx in vm86 mode", rec->ExceptionInformation[0]);
+            break;
+        case EXCEPTION_VM86_STI:
+            dbg_printf("sti in vm86 mode");
+            break;
+        case EXCEPTION_VM86_PICRETURN:
+            dbg_printf("PIC return in vm86 mode");
+            break;
+	case EXCEPTION_FLT_DENORMAL_OPERAND:
+            dbg_printf("denormal float operand");
+            break;
+	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+            dbg_printf("divide by zero");
+            break;
+	case EXCEPTION_FLT_INEXACT_RESULT:
+            dbg_printf("inexact float result");
+            break;
+	case EXCEPTION_FLT_INVALID_OPERATION:
+            dbg_printf("invalid float operation");
+            break;
+	case EXCEPTION_FLT_OVERFLOW:
+            dbg_printf("floating pointer overflow");
+            break;
+	case EXCEPTION_FLT_UNDERFLOW:
+            dbg_printf("floating pointer underflow");
+            break;
+	case EXCEPTION_FLT_STACK_CHECK:
+            dbg_printf("floating point stack check");
+            break;
+        default:
+            dbg_printf("0x%08lx", rec->ExceptionCode);
+            break;
+        }
+    }
+    if( (rec->ExceptionFlags & EH_STACK_INVALID) ) {
+        dbg_printf( ", invalid program stack" );
+    }
+
+    if (dbg_action_mode == automatic_mode)
+    {
+        dbg_exception_prolog(is_debug, rec);
+        dbg_exception_epilog();
+        return 0;  /* terminate execution */
+    }
+
+    if (dbg_exception_prolog(is_debug, rec))
+    {
+	dbg_interactiveP = TRUE;
+        return 0;
+    }
+    dbg_exception_epilog();
+
+    return DBG_CONTINUE;
+}
+
+static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
+{
+    char	buffer[256];
+    DWORD       cont = DBG_CONTINUE;
+
+    dbg_curr_pid = de->dwProcessId;
+    dbg_curr_tid = de->dwThreadId;
+
+    if ((dbg_curr_process = dbg_get_process(de->dwProcessId)) != NULL)
+        dbg_curr_thread = dbg_get_thread(dbg_curr_process, de->dwThreadId);
+    else
+        dbg_curr_thread = NULL;
+
+    switch (de->dwDebugEventCode)
+    {
+    case EXCEPTION_DEBUG_EVENT:
+        if (!dbg_curr_thread)
+        {
+            WINE_ERR("%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
+                     de->dwProcessId, de->dwThreadId);
+            break;
+        }
+
+        WINE_TRACE("%08lx:%08lx: exception code=%08lx\n",
+                   de->dwProcessId, de->dwThreadId,
+                   de->u.Exception.ExceptionRecord.ExceptionCode);
+
+        if (dbg_curr_process->continue_on_first_exception)
+        {
+            dbg_curr_process->continue_on_first_exception = FALSE;
+            if (!DBG_IVAR(BreakOnAttach)) break;
+        }
+        if (dbg_fetch_context())
+        {
+            cont = dbg_handle_exception(&de->u.Exception.ExceptionRecord,
+                                        de->u.Exception.dwFirstChance);
+            if (cont && dbg_curr_thread)
+            {
+                SetThreadContext(dbg_curr_thread->handle, &dbg_context);
+            }
+        }
+        break;
+
+    case CREATE_PROCESS_DEBUG_EVENT:
+        dbg_curr_process = dbg_add_process(de->dwProcessId,
+                                           de->u.CreateProcessInfo.hProcess);
+        if (dbg_curr_process == NULL)
+        {
+            WINE_ERR("Couldn't create process\n");
+            break;
+        }
+        memory_get_string_indirect(dbg_curr_process,
+                                   de->u.CreateProcessInfo.lpImageName,
+                                   de->u.CreateProcessInfo.fUnicode,
+                                   buffer, sizeof(buffer));
+        if (!buffer[0]) strcpy(buffer, "<Debugged Process>");
+
+        WINE_TRACE("%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
+                   de->dwProcessId, de->dwThreadId,
+                   buffer, de->u.CreateProcessInfo.lpImageName,
+                   (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress,
+                   de->u.CreateProcessInfo.dwDebugInfoFileOffset,
+                   de->u.CreateProcessInfo.nDebugInfoSize);
+        dbg_set_process_name(dbg_curr_process, buffer);
+
+        if (!SymInitialize(dbg_curr_process->handle, NULL, TRUE))
+            dbg_printf("Couldn't initiate DbgHelp\n");
+
+        WINE_TRACE("%08lx:%08lx: create thread I @%08lx\n",
+                   de->dwProcessId, de->dwThreadId,
+                   (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress);
+
+        dbg_curr_thread = dbg_add_thread(dbg_curr_process,
+                                         de->dwThreadId,
+                                         de->u.CreateProcessInfo.hThread,
+                                         de->u.CreateProcessInfo.lpThreadLocalBase);
+        if (!dbg_curr_thread)
+        {
+            WINE_ERR("Couldn't create thread\n");
+            break;
+        }
+        dbg_init_current_process();
+        dbg_init_current_thread(de->u.CreateProcessInfo.lpStartAddress);
+        break;
+
+    case EXIT_PROCESS_DEBUG_EVENT:
+        WINE_TRACE("%08lx:%08lx: exit process (%ld)\n",
+                   de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
+
+        if (dbg_curr_process == NULL)
+        {
+            WINE_ERR("Unknown process\n");
+            break;
+        }
+        if (!SymCleanup(dbg_curr_process->handle))
+            dbg_printf("Couldn't initiate DbgHelp\n");
+        /* just in case */
+        break_set_xpoints(FALSE);
+        /* kill last thread */
+        dbg_del_thread(dbg_curr_process->threads);
+        dbg_del_process(dbg_curr_process);
+
+        dbg_printf("Process of pid=0x%08lx has terminated\n", dbg_curr_pid);
+        break;
+
+    case CREATE_THREAD_DEBUG_EVENT:
+        WINE_TRACE("%08lx:%08lx: create thread D @%08lx\n",
+                   de->dwProcessId, de->dwThreadId,
+                   (unsigned long)(void*)de->u.CreateThread.lpStartAddress);
+
+        if (dbg_curr_process == NULL)
+        {
+            WINE_ERR("Unknown process\n");
+            break;
+        }
+        if (dbg_get_thread(dbg_curr_process, de->dwThreadId) != NULL)
+        {
+            WINE_TRACE("Thread already listed, skipping\n");
+            break;
+        }
+
+        dbg_curr_thread = dbg_add_thread(dbg_curr_process,
+                                         de->dwThreadId,
+                                         de->u.CreateThread.hThread,
+                                         de->u.CreateThread.lpThreadLocalBase);
+        if (!dbg_curr_thread)
+        {
+            WINE_ERR("Couldn't create thread\n");
+            break;
+        }
+        dbg_init_current_thread(de->u.CreateThread.lpStartAddress);
+        break;
+
+    case EXIT_THREAD_DEBUG_EVENT:
+        WINE_TRACE("%08lx:%08lx: exit thread (%ld)\n",
+                   de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
+
+        if (dbg_curr_thread == NULL)
+        {
+            WINE_ERR("Unknown thread\n");
+            break;
+        }
+        /* FIXME: remove break point set on thread startup */
+        dbg_del_thread(dbg_curr_thread);
+        break;
+
+    case LOAD_DLL_DEBUG_EVENT:
+        if (dbg_curr_thread == NULL)
+        {
+            WINE_ERR("Unknown thread\n");
+            break;
+        }
+        memory_get_string_indirect(dbg_curr_process, 
+                                   de->u.LoadDll.lpImageName,
+                                   de->u.LoadDll.fUnicode,
+                                   buffer, sizeof(buffer));
+
+        WINE_TRACE("%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
+                   de->dwProcessId, de->dwThreadId,
+                   buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
+                   de->u.LoadDll.dwDebugInfoFileOffset,
+                   de->u.LoadDll.nDebugInfoSize);
+        SymLoadModule(dbg_curr_process->handle, de->u.LoadDll.hFile, buffer, NULL,
+                      (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
+        break_set_xpoints(FALSE);
+        break_check_delayed_bp();
+        break_set_xpoints(TRUE);
+        if (DBG_IVAR(BreakOnDllLoad))
+        {
+            dbg_printf("Stopping on DLL %s loading at 0x%08lx\n",
+                       buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
+            if (dbg_fetch_context()) cont = 0;
+        }
+        break;
+
+    case UNLOAD_DLL_DEBUG_EVENT:
+        WINE_TRACE("%08lx:%08lx: unload DLL @%08lx\n", 
+                   de->dwProcessId, de->dwThreadId,
+                   (unsigned long)de->u.UnloadDll.lpBaseOfDll);
+        break_delete_xpoints_from_module((unsigned long)de->u.UnloadDll.lpBaseOfDll);
+        SymUnloadModule(dbg_curr_process->handle, 
+                        (unsigned long)de->u.UnloadDll.lpBaseOfDll);
+        break;
+
+    case OUTPUT_DEBUG_STRING_EVENT:
+        if (dbg_curr_thread == NULL)
+        {
+            WINE_ERR("Unknown thread\n");
+            break;
+        }
+
+        memory_get_string(dbg_curr_process,
+                          de->u.DebugString.lpDebugStringData, TRUE,
+                          de->u.DebugString.fUnicode, buffer, sizeof(buffer));
+        WINE_TRACE("%08lx:%08lx: output debug string (%s)\n",
+                   de->dwProcessId, de->dwThreadId, buffer);
+        break;
+
+    case RIP_EVENT:
+        WINE_TRACE("%08lx:%08lx: rip error=%ld type=%ld\n",
+                   de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
+                   de->u.RipInfo.dwType);
+        break;
+
+    default:
+        WINE_TRACE("%08lx:%08lx: unknown event (%ld)\n",
+                   de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
+    }
+    if (!cont) return TRUE;  /* stop execution */
+    ContinueDebugEvent(de->dwProcessId, de->dwThreadId, cont);
+    return FALSE;  /* continue execution */
+}
+
+static void dbg_resume_debuggee(DWORD cont)
+{
+    if (dbg_curr_thread->in_exception)
+    {
+        ADDRESS         addr;
+
+        dbg_exception_epilog();
+        memory_get_current_pc(&addr);
+        WINE_TRACE("Exiting debugger      PC=0x%lx mode=%d count=%d\n",
+                   addr.Offset, dbg_curr_thread->exec_mode,
+                   dbg_curr_thread->exec_count);
+        if (dbg_curr_thread)
+        {
+            if (!SetThreadContext(dbg_curr_thread->handle, &dbg_context))
+                dbg_printf("Cannot set ctx on %lu\n", dbg_curr_tid);
+        }
+    }
+    dbg_interactiveP = FALSE;
+    if (!ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, cont))
+        dbg_printf("Cannot continue on %lu (%lu)\n", dbg_curr_tid, cont);
+}
+
+void dbg_wait_next_exception(DWORD cont, int count, int mode)
+{
+    DEBUG_EVENT         de;
+    ADDRESS             addr;
+
+    if (cont == DBG_CONTINUE)
+    {
+        dbg_curr_thread->exec_count = count;
+        dbg_curr_thread->exec_mode = mode;
+    }
+    dbg_resume_debuggee(cont);
+
+    while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
+    {
+        if (dbg_handle_debug_event(&de)) break;
+    }
+    if (!dbg_curr_process) return;
+    dbg_interactiveP = TRUE;
+
+    memory_get_current_pc(&addr);
+    WINE_TRACE("Entering debugger     PC=0x%lx mode=%d count=%d\n",
+               addr.Offset, dbg_curr_thread->exec_mode,
+               dbg_curr_thread->exec_count);
+}
+
+/*static*/	unsigned        dbg_main_loop(HANDLE hFile)
+{
+    DEBUG_EVENT		de;
+
+    if (dbg_curr_process)
+        dbg_printf("WineDbg starting on pid 0x%lx\n", dbg_curr_pid);
+
+    /* wait for first exception */
+    while (WaitForDebugEvent(&de, INFINITE))
+    {
+        if (dbg_handle_debug_event(&de)) break;
+    }
+    switch (dbg_action_mode)
+    {
+    case automatic_mode:
+        /* print some extra information */
+        dbg_printf("Modules:\n");
+        info_win32_module(0); /* print all modules */
+        dbg_printf("Threads:\n");
+        info_win32_threads();
+        break;
+    default:
+        dbg_interactiveP = TRUE;
+        parser_handle(hFile);
+    }
+    dbg_printf("WineDbg terminated on pid 0x%lx\n", dbg_curr_pid);
+
+    return 0;
+}
+
+/*static*/	unsigned dbg_start_debuggee(LPSTR cmdLine)
+{
+    PROCESS_INFORMATION	info;
+    STARTUPINFOA	startup;
+
+    memset(&startup, 0, sizeof(startup));
+    startup.cb = sizeof(startup);
+    startup.dwFlags = STARTF_USESHOWWINDOW;
+    startup.wShowWindow = SW_SHOWNORMAL;
+
+    /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
+     * while GUI:s don't
+     */
+    if (!CreateProcess(NULL, cmdLine, NULL, NULL,
+                       FALSE, 
+                       DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,
+                       NULL, NULL, &startup, &info))
+    {
+	dbg_printf("Couldn't start process '%s'\n", cmdLine);
+	return FALSE;
+    }
+    if (!info.dwProcessId)
+    {
+        /* this happens when the program being run is not a Wine binary
+         * (for example, a shell wrapper around a WineLib app)
+         */
+        /* Current fix: list running processes and let the user attach
+         * to one of them (sic)
+         * FIXME: implement a real fix => grab the process (from the
+         * running processes) from its name
+         */
+        dbg_printf("Debuggee has been started (%s)\n"
+                   "But WineDbg isn't attached to it. Maybe you're trying to debug a winelib wrapper ??\n"
+                   "Try to attach to one of those processes:\n", cmdLine);
+        /* FIXME: (HACK) we need some time before the wrapper executes the winelib app */
+        Sleep(100);
+        info_win32_processes();
+        return TRUE;
+    }
+    dbg_curr_pid = info.dwProcessId;
+    if (!(dbg_curr_process = dbg_add_process(dbg_curr_pid, 0))) return FALSE;
+
+    return TRUE;
+}
+
+void	dbg_run_debuggee(const char* args)
+{
+    if (args)
+    {
+        WINE_FIXME("Re-running current program with %s as args is broken\n", args);
+        return;
+    }
+    else 
+    {
+        DEBUG_EVENT     de;
+
+	if (!dbg_last_cmd_line)
+        {
+	    dbg_printf("Cannot find previously used command line.\n");
+	    return;
+	}
+	dbg_start_debuggee(dbg_last_cmd_line);
+        while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
+        {
+            if (dbg_handle_debug_event(&de)) break;
+        }
+        source_list_from_addr(NULL, 0);
+    }
+}
+
diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c
index fae7a42..7ed1410 100644
--- a/programs/winedbg/winedbg.c
+++ b/programs/winedbg/winedbg.c
@@ -93,10 +93,8 @@ DWORD		        dbg_curr_tid;
 DWORD		        dbg_curr_pid;
 CONTEXT                 dbg_context;
 BOOL    	        dbg_interactiveP = FALSE;
-static char*	        dbg_last_cmd_line = NULL;
 
 static struct dbg_process*      dbg_process_list = NULL;
-static enum {none_mode = 0, winedbg_mode, automatic_mode, gdb_mode} dbg_action_mode;
 
 struct dbg_internal_var         dbg_internal_vars[DBG_IV_LAST];
 const struct dbg_internal_var*  dbg_context_vars;
@@ -323,10 +321,6 @@ void dbg_del_process(struct dbg_process*
     HeapFree(GetProcessHeap(), 0, p);
 }
 
-static void dbg_init_current_process(void)
-{
-}
-
 struct mod_loader_info
 {
     HANDLE              handle;
@@ -409,25 +403,6 @@ struct dbg_thread* dbg_add_thread(struct
     return t;
 }
 
-static void dbg_init_current_thread(void* start)
-{
-    if (start)
-    {
-	if (dbg_curr_process->threads && 
-            !dbg_curr_process->threads->next && /* first thread ? */
-	    DBG_IVAR(BreakAllThreadsStartup)) 
-        {
-	    ADDRESS     addr;
-
-            break_set_xpoints(FALSE);
-	    addr.Mode   = AddrModeFlat;
-	    addr.Offset = (DWORD)start;
-	    break_add_break(&addr, TRUE, TRUE);
-	    break_set_xpoints(TRUE);
-	}
-    } 
-}
-
 void dbg_del_thread(struct dbg_thread* t)
 {
     HeapFree(GetProcessHeap(), 0, t->frames);
@@ -438,723 +413,6 @@ void dbg_del_thread(struct dbg_thread* t
     HeapFree(GetProcessHeap(), 0, t);
 }
 
-static unsigned dbg_handle_debug_event(DEBUG_EVENT* de);
-
-/******************************************************************
- *		dbg_attach_debuggee
- *
- * Sets the debuggee to <pid>
- * cofe instructs winedbg what to do when first exception is received 
- * (break=FALSE, continue=TRUE)
- * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events
- * until the first exception is received (aka: attach to an already running process)
- */
-BOOL dbg_attach_debuggee(DWORD pid, BOOL cofe, BOOL wfe)
-{
-    DEBUG_EVENT         de;
-
-    if (!(dbg_curr_process = dbg_add_process(pid, 0))) return FALSE;
-
-    if (!DebugActiveProcess(pid)) 
-    {
-        dbg_printf("Can't attach process %lx: error %ld\n", pid, GetLastError());
-        dbg_del_process(dbg_curr_process);
-	return FALSE;
-    }
-    dbg_curr_process->continue_on_first_exception = cofe;
-
-    if (wfe) /* shall we proceed all debug events until we get an exception ? */
-    {
-        dbg_interactiveP = FALSE;
-        while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
-        {
-            if (dbg_handle_debug_event(&de)) break;
-        }
-        if (dbg_curr_process) dbg_interactiveP = TRUE;
-    }
-    return TRUE;
-}
-
-BOOL dbg_detach_debuggee(void)
-{
-    /* remove all set breakpoints in debuggee code */
-    break_set_xpoints(FALSE);
-    /* needed for single stepping (ugly).
-     * should this be handled inside the server ??? 
-     */
-    be_cpu->single_step(&dbg_context, FALSE);
-    SetThreadContext(dbg_curr_thread->handle, &dbg_context);
-    if (dbg_curr_thread->in_exception)
-        ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, DBG_CONTINUE);
-    if (!DebugActiveProcessStop(dbg_curr_pid)) return FALSE;
-    dbg_del_process(dbg_curr_process);
-
-    return TRUE;
-}
-
-static unsigned dbg_fetch_context(void)
-{
-    dbg_context.ContextFlags = CONTEXT_CONTROL
-        | CONTEXT_INTEGER
-#ifdef CONTEXT_SEGMENTS
-        | CONTEXT_SEGMENTS
-#endif
-#ifdef CONTEXT_DEBUG_REGISTERS
-        | CONTEXT_DEBUG_REGISTERS
-#endif
-        ;
-    if (!GetThreadContext(dbg_curr_thread->handle, &dbg_context))
-    {
-        WINE_WARN("Can't get thread's context\n");
-        return FALSE;
-    }
-    return TRUE;
-}
-
-static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
-{
-    ADDRESS     addr;
-    BOOL        is_break;
-
-    memory_get_current_pc(&addr);
-    break_suspend_execution();
-    dbg_curr_thread->excpt_record = *rec;
-    dbg_curr_thread->in_exception = TRUE;
-
-    if (!is_debug)
-    {
-        switch (addr.Mode)
-        {
-        case AddrModeFlat: dbg_printf(" in 32-bit code (0x%08lx)", addr.Offset); break;
-        case AddrModeReal: dbg_printf(" in vm86 code (%04x:%04lx)", addr.Segment, addr.Offset); break;
-        case AddrMode1616: dbg_printf(" in 16-bit code (%04x:%04lx)", addr.Segment, addr.Offset); break;
-        case AddrMode1632: dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, addr.Offset); break;
-        default: dbg_printf(" bad address");
-        }
-	dbg_printf(".\n");
-    }
-
-    /* this will resynchronize builtin dbghelp's internal ELF module list */
-    SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0);
-
-    /*
-     * Do a quiet backtrace so that we have an idea of what the situation
-     * is WRT the source files.
-     */
-    stack_fetch_frames();
-    if (is_debug &&
-	break_should_continue(&addr, rec->ExceptionCode, &dbg_curr_thread->exec_count, &is_break))
-	return FALSE;
-
-    if (addr.Mode != dbg_curr_thread->addr_mode)
-    {
-        const char* name = NULL;
-        
-        switch (addr.Mode)
-        {
-        case AddrMode1616: name = "16 bit";     break;
-        case AddrMode1632: name = "32 bit";     break;
-        case AddrModeReal: name = "vm86";       break;
-        case AddrModeFlat: name = "32 bit";     break;
-        }
-        
-        dbg_printf("In %s mode.\n", name);
-        dbg_curr_thread->addr_mode = addr.Mode;
-    }
-    display_print();
-
-    if (!is_debug)
-    {
-	/* This is a real crash, dump some info */
-	be_cpu->print_context(dbg_curr_thread->handle, &dbg_context);
-	stack_info();
-        be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
-	stack_backtrace(dbg_curr_tid);
-    }
-    else
-    {
-        static char*        last_name;
-        static char*        last_file;
-
-        char                buffer[sizeof(SYMBOL_INFO) + 256];
-        SYMBOL_INFO*        si = (SYMBOL_INFO*)buffer;
-        void*               lin = memory_to_linear_addr(&addr);
-        DWORD64             disp64;
-        IMAGEHLP_LINE       il;
-        DWORD               disp;
-
-        si->SizeOfStruct = sizeof(*si);
-        si->MaxNameLen   = 256;
-        il.SizeOfStruct = sizeof(il);
-        if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) &&
-            SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il))
-        {
-            if ((!last_name || strcmp(last_name, si->Name)) ||
-                (!last_file || strcmp(last_file, il.FileName)))
-            {
-                HeapFree(GetProcessHeap(), 0, last_name);
-                HeapFree(GetProcessHeap(), 0, last_file);
-                last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name);
-                last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName);
-                dbg_printf("%s () at %s:%ld\n", last_name, last_file, il.LineNumber);
-            }
-        }
-    }
-    if (!is_debug || is_break ||
-        dbg_curr_thread->exec_mode == dbg_exec_step_over_insn ||
-        dbg_curr_thread->exec_mode == dbg_exec_step_into_insn)
-    {
-        ADDRESS tmp = addr;
-        /* Show where we crashed */
-        memory_disasm_one_insn(&tmp);
-    }
-    source_list_from_addr(&addr, 0);
-
-    return TRUE;
-}
-
-static void dbg_exception_epilog(void)
-{
-    break_restart_execution(dbg_curr_thread->exec_count);
-    /*
-     * This will have gotten absorbed into the breakpoint info
-     * if it was used.  Otherwise it would have been ignored.
-     * In any case, we don't mess with it any more.
-     */
-    if (dbg_curr_thread->exec_mode == dbg_exec_cont)
-	dbg_curr_thread->exec_count = 0;
-    dbg_curr_thread->in_exception = FALSE;
-}
-
-static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance)
-{
-    BOOL                is_debug = FALSE;
-    THREADNAME_INFO*    pThreadName;
-    struct dbg_thread*  pThread;
-
-    assert(dbg_curr_thread);
-
-    WINE_TRACE("exception=%lx first_chance=%c\n",
-               rec->ExceptionCode, first_chance ? 'Y' : 'N');
-
-    switch (rec->ExceptionCode)
-    {
-    case EXCEPTION_BREAKPOINT:
-    case EXCEPTION_SINGLE_STEP:
-        is_debug = TRUE;
-        break;
-    case EXCEPTION_NAME_THREAD:
-        pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
-        if (pThreadName->dwThreadID == -1)
-            pThread = dbg_curr_thread;
-        else
-            pThread = dbg_get_thread(dbg_curr_process, pThreadName->dwThreadID);
-
-        if (dbg_read_memory(pThreadName->szName, pThread->name, 9))
-            dbg_printf("Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
-                       pThread->tid, pThread->name);
-        return DBG_CONTINUE;
-    }
-
-    if (first_chance && !is_debug && !DBG_IVAR(BreakOnFirstChance) &&
-	!(rec->ExceptionFlags & EH_STACK_INVALID))
-    {
-        /* pass exception to program except for debug exceptions */
-        return DBG_EXCEPTION_NOT_HANDLED;
-    }
-
-    if (!is_debug)
-    {
-        /* print some infos */
-        dbg_printf("%s: ",
-                   first_chance ? "First chance exception" : "Unhandled exception");
-        switch (rec->ExceptionCode)
-        {
-        case EXCEPTION_INT_DIVIDE_BY_ZERO:
-            dbg_printf("divide by zero");
-            break;
-        case EXCEPTION_INT_OVERFLOW:
-            dbg_printf("overflow");
-            break;
-        case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
-            dbg_printf("array bounds");
-            break;
-        case EXCEPTION_ILLEGAL_INSTRUCTION:
-            dbg_printf("illegal instruction");
-            break;
-        case EXCEPTION_STACK_OVERFLOW:
-            dbg_printf("stack overflow");
-            break;
-        case EXCEPTION_PRIV_INSTRUCTION:
-            dbg_printf("privileged instruction");
-            break;
-        case EXCEPTION_ACCESS_VIOLATION:
-            if (rec->NumberParameters == 2)
-                dbg_printf("page fault on %s access to 0x%08lx",
-                           rec->ExceptionInformation[0] ? "write" : "read",
-                           rec->ExceptionInformation[1]);
-            else
-                dbg_printf("page fault");
-            break;
-        case EXCEPTION_DATATYPE_MISALIGNMENT:
-            dbg_printf("Alignment");
-            break;
-	case DBG_CONTROL_C:
-            dbg_printf("^C");
-            break;
-        case CONTROL_C_EXIT:
-            dbg_printf("^C");
-            break;
-        case STATUS_POSSIBLE_DEADLOCK:
-        {
-            ADDRESS         addr;
-
-            addr.Mode   = AddrModeFlat;
-            addr.Offset = rec->ExceptionInformation[0];
-
-            dbg_printf("wait failed on critical section ");
-            print_address(&addr, FALSE);
-        }
-        if (!DBG_IVAR(BreakOnCritSectTimeOut))
-        {
-            dbg_printf("\n");
-            return DBG_EXCEPTION_NOT_HANDLED;
-        }
-        break;
-        case EXCEPTION_WINE_STUB:
-        {
-            char dll[32], name[64];
-            memory_get_string(dbg_curr_process,
-                              (void*)rec->ExceptionInformation[0], TRUE, FALSE,
-                              dll, sizeof(dll));
-            if (HIWORD(rec->ExceptionInformation[1]))
-                memory_get_string(dbg_curr_process,
-                                  (void*)rec->ExceptionInformation[1], TRUE, FALSE,
-                                  name, sizeof(name));
-            else
-                sprintf( name, "%ld", rec->ExceptionInformation[1] );
-            dbg_printf("unimplemented function %s.%s called", dll, name);
-        }
-        break;
-        case EXCEPTION_WINE_ASSERTION:
-            dbg_printf("assertion failed");
-            break;
-        case EXCEPTION_VM86_INTx:
-            dbg_printf("interrupt %02lx in vm86 mode", rec->ExceptionInformation[0]);
-            break;
-        case EXCEPTION_VM86_STI:
-            dbg_printf("sti in vm86 mode");
-            break;
-        case EXCEPTION_VM86_PICRETURN:
-            dbg_printf("PIC return in vm86 mode");
-            break;
-	case EXCEPTION_FLT_DENORMAL_OPERAND:
-            dbg_printf("denormal float operand");
-            break;
-	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-            dbg_printf("divide by zero");
-            break;
-	case EXCEPTION_FLT_INEXACT_RESULT:
-            dbg_printf("inexact float result");
-            break;
-	case EXCEPTION_FLT_INVALID_OPERATION:
-            dbg_printf("invalid float operation");
-            break;
-	case EXCEPTION_FLT_OVERFLOW:
-            dbg_printf("floating pointer overflow");
-            break;
-	case EXCEPTION_FLT_UNDERFLOW:
-            dbg_printf("floating pointer underflow");
-            break;
-	case EXCEPTION_FLT_STACK_CHECK:
-            dbg_printf("floating point stack check");
-            break;
-        default:
-            dbg_printf("0x%08lx", rec->ExceptionCode);
-            break;
-        }
-    }
-    if( (rec->ExceptionFlags & EH_STACK_INVALID) ) {
-        dbg_printf( ", invalid program stack" );
-    }
-
-    if (dbg_action_mode == automatic_mode)
-    {
-        dbg_exception_prolog(is_debug, rec);
-        dbg_exception_epilog();
-        return 0;  /* terminate execution */
-    }
-
-    if (dbg_exception_prolog(is_debug, rec))
-    {
-	dbg_interactiveP = TRUE;
-        return 0;
-    }
-    dbg_exception_epilog();
-
-    return DBG_CONTINUE;
-}
-
-static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
-{
-    char	buffer[256];
-    DWORD       cont = DBG_CONTINUE;
-
-    dbg_curr_pid = de->dwProcessId;
-    dbg_curr_tid = de->dwThreadId;
-
-    if ((dbg_curr_process = dbg_get_process(de->dwProcessId)) != NULL)
-        dbg_curr_thread = dbg_get_thread(dbg_curr_process, de->dwThreadId);
-    else
-        dbg_curr_thread = NULL;
-
-    switch (de->dwDebugEventCode)
-    {
-    case EXCEPTION_DEBUG_EVENT:
-        if (!dbg_curr_thread)
-        {
-            WINE_ERR("%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
-                     de->dwProcessId, de->dwThreadId);
-            break;
-        }
-
-        WINE_TRACE("%08lx:%08lx: exception code=%08lx\n",
-                   de->dwProcessId, de->dwThreadId,
-                   de->u.Exception.ExceptionRecord.ExceptionCode);
-
-        if (dbg_curr_process->continue_on_first_exception)
-        {
-            dbg_curr_process->continue_on_first_exception = FALSE;
-            if (!DBG_IVAR(BreakOnAttach)) break;
-        }
-        if (dbg_fetch_context())
-        {
-            cont = dbg_handle_exception(&de->u.Exception.ExceptionRecord,
-                                        de->u.Exception.dwFirstChance);
-            if (cont && dbg_curr_thread)
-            {
-                SetThreadContext(dbg_curr_thread->handle, &dbg_context);
-            }
-        }
-        break;
-
-    case CREATE_PROCESS_DEBUG_EVENT:
-        dbg_curr_process = dbg_add_process(de->dwProcessId,
-                                           de->u.CreateProcessInfo.hProcess);
-        if (dbg_curr_process == NULL)
-        {
-            WINE_ERR("Couldn't create process\n");
-            break;
-        }
-        memory_get_string_indirect(dbg_curr_process,
-                                   de->u.CreateProcessInfo.lpImageName,
-                                   de->u.CreateProcessInfo.fUnicode,
-                                   buffer, sizeof(buffer));
-        if (!buffer[0]) strcpy(buffer, "<Debugged Process>");
-
-        WINE_TRACE("%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
-                   de->dwProcessId, de->dwThreadId,
-                   buffer, de->u.CreateProcessInfo.lpImageName,
-                   (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress,
-                   de->u.CreateProcessInfo.dwDebugInfoFileOffset,
-                   de->u.CreateProcessInfo.nDebugInfoSize);
-        dbg_set_process_name(dbg_curr_process, buffer);
-
-        if (!SymInitialize(dbg_curr_process->handle, NULL, TRUE))
-            dbg_printf("Couldn't initiate DbgHelp\n");
-
-        WINE_TRACE("%08lx:%08lx: create thread I @%08lx\n",
-                   de->dwProcessId, de->dwThreadId,
-                   (unsigned long)(void*)de->u.CreateProcessInfo.lpStartAddress);
-
-        dbg_curr_thread = dbg_add_thread(dbg_curr_process,
-                                         de->dwThreadId,
-                                         de->u.CreateProcessInfo.hThread,
-                                         de->u.CreateProcessInfo.lpThreadLocalBase);
-        if (!dbg_curr_thread)
-        {
-            WINE_ERR("Couldn't create thread\n");
-            break;
-        }
-        dbg_init_current_process();
-        dbg_init_current_thread(de->u.CreateProcessInfo.lpStartAddress);
-        break;
-
-    case EXIT_PROCESS_DEBUG_EVENT:
-        WINE_TRACE("%08lx:%08lx: exit process (%ld)\n",
-                   de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
-
-        if (dbg_curr_process == NULL)
-        {
-            WINE_ERR("Unknown process\n");
-            break;
-        }
-        if (!SymCleanup(dbg_curr_process->handle))
-            dbg_printf("Couldn't initiate DbgHelp\n");
-        /* just in case */
-        break_set_xpoints(FALSE);
-        /* kill last thread */
-        dbg_del_thread(dbg_curr_process->threads);
-        dbg_del_process(dbg_curr_process);
-
-        dbg_printf("Process of pid=0x%08lx has terminated\n", dbg_curr_pid);
-        break;
-
-    case CREATE_THREAD_DEBUG_EVENT:
-        WINE_TRACE("%08lx:%08lx: create thread D @%08lx\n",
-                   de->dwProcessId, de->dwThreadId,
-                   (unsigned long)(void*)de->u.CreateThread.lpStartAddress);
-
-        if (dbg_curr_process == NULL)
-        {
-            WINE_ERR("Unknown process\n");
-            break;
-        }
-        if (dbg_get_thread(dbg_curr_process, de->dwThreadId) != NULL)
-        {
-            WINE_TRACE("Thread already listed, skipping\n");
-            break;
-        }
-
-        dbg_curr_thread = dbg_add_thread(dbg_curr_process,
-                                         de->dwThreadId,
-                                         de->u.CreateThread.hThread,
-                                         de->u.CreateThread.lpThreadLocalBase);
-        if (!dbg_curr_thread)
-        {
-            WINE_ERR("Couldn't create thread\n");
-            break;
-        }
-        dbg_init_current_thread(de->u.CreateThread.lpStartAddress);
-        break;
-
-    case EXIT_THREAD_DEBUG_EVENT:
-        WINE_TRACE("%08lx:%08lx: exit thread (%ld)\n",
-                   de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
-
-        if (dbg_curr_thread == NULL)
-        {
-            WINE_ERR("Unknown thread\n");
-            break;
-        }
-        /* FIXME: remove break point set on thread startup */
-        dbg_del_thread(dbg_curr_thread);
-        break;
-
-    case LOAD_DLL_DEBUG_EVENT:
-        if (dbg_curr_thread == NULL)
-        {
-            WINE_ERR("Unknown thread\n");
-            break;
-        }
-        memory_get_string_indirect(dbg_curr_process, 
-                                   de->u.LoadDll.lpImageName,
-                                   de->u.LoadDll.fUnicode,
-                                   buffer, sizeof(buffer));
-
-        WINE_TRACE("%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
-                   de->dwProcessId, de->dwThreadId,
-                   buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
-                   de->u.LoadDll.dwDebugInfoFileOffset,
-                   de->u.LoadDll.nDebugInfoSize);
-        SymLoadModule(dbg_curr_process->handle, de->u.LoadDll.hFile, buffer, NULL,
-                      (unsigned long)de->u.LoadDll.lpBaseOfDll, 0);
-        break_set_xpoints(FALSE);
-        break_check_delayed_bp();
-        break_set_xpoints(TRUE);
-        if (DBG_IVAR(BreakOnDllLoad))
-        {
-            dbg_printf("Stopping on DLL %s loading at 0x%08lx\n",
-                       buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
-            if (dbg_fetch_context()) cont = 0;
-        }
-        break;
-
-    case UNLOAD_DLL_DEBUG_EVENT:
-        WINE_TRACE("%08lx:%08lx: unload DLL @%08lx\n", 
-                   de->dwProcessId, de->dwThreadId,
-                   (unsigned long)de->u.UnloadDll.lpBaseOfDll);
-        break_delete_xpoints_from_module((unsigned long)de->u.UnloadDll.lpBaseOfDll);
-        SymUnloadModule(dbg_curr_process->handle, 
-                        (unsigned long)de->u.UnloadDll.lpBaseOfDll);
-        break;
-
-    case OUTPUT_DEBUG_STRING_EVENT:
-        if (dbg_curr_thread == NULL)
-        {
-            WINE_ERR("Unknown thread\n");
-            break;
-        }
-
-        memory_get_string(dbg_curr_process,
-                          de->u.DebugString.lpDebugStringData, TRUE,
-                          de->u.DebugString.fUnicode, buffer, sizeof(buffer));
-        WINE_TRACE("%08lx:%08lx: output debug string (%s)\n",
-                   de->dwProcessId, de->dwThreadId, buffer);
-        break;
-
-    case RIP_EVENT:
-        WINE_TRACE("%08lx:%08lx: rip error=%ld type=%ld\n",
-                   de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
-                   de->u.RipInfo.dwType);
-        break;
-
-    default:
-        WINE_TRACE("%08lx:%08lx: unknown event (%ld)\n",
-                   de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
-    }
-    if (!cont) return TRUE;  /* stop execution */
-    ContinueDebugEvent(de->dwProcessId, de->dwThreadId, cont);
-    return FALSE;  /* continue execution */
-}
-
-static void dbg_resume_debuggee(DWORD cont)
-{
-    if (dbg_curr_thread->in_exception)
-    {
-        ADDRESS         addr;
-
-        dbg_exception_epilog();
-        memory_get_current_pc(&addr);
-        WINE_TRACE("Exiting debugger      PC=0x%lx mode=%d count=%d\n",
-                   addr.Offset, dbg_curr_thread->exec_mode,
-                   dbg_curr_thread->exec_count);
-        if (dbg_curr_thread)
-        {
-            if (!SetThreadContext(dbg_curr_thread->handle, &dbg_context))
-                dbg_printf("Cannot set ctx on %lu\n", dbg_curr_tid);
-        }
-    }
-    dbg_interactiveP = FALSE;
-    if (!ContinueDebugEvent(dbg_curr_pid, dbg_curr_tid, cont))
-        dbg_printf("Cannot continue on %lu (%lu)\n", dbg_curr_tid, cont);
-}
-
-void dbg_wait_next_exception(DWORD cont, int count, int mode)
-{
-    DEBUG_EVENT         de;
-    ADDRESS             addr;
-
-    if (cont == DBG_CONTINUE)
-    {
-        dbg_curr_thread->exec_count = count;
-        dbg_curr_thread->exec_mode = mode;
-    }
-    dbg_resume_debuggee(cont);
-
-    while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
-    {
-        if (dbg_handle_debug_event(&de)) break;
-    }
-    if (!dbg_curr_process) return;
-    dbg_interactiveP = TRUE;
-
-    memory_get_current_pc(&addr);
-    WINE_TRACE("Entering debugger     PC=0x%lx mode=%d count=%d\n",
-               addr.Offset, dbg_curr_thread->exec_mode,
-               dbg_curr_thread->exec_count);
-}
-
-static	unsigned        dbg_main_loop(HANDLE hFile)
-{
-    DEBUG_EVENT		de;
-
-    if (dbg_curr_process)
-        dbg_printf("WineDbg starting on pid 0x%lx\n", dbg_curr_pid);
-
-    /* wait for first exception */
-    while (WaitForDebugEvent(&de, INFINITE))
-    {
-        if (dbg_handle_debug_event(&de)) break;
-    }
-    switch (dbg_action_mode)
-    {
-    case automatic_mode:
-        /* print some extra information */
-        dbg_printf("Modules:\n");
-        info_win32_module(0); /* print all modules */
-        dbg_printf("Threads:\n");
-        info_win32_threads();
-        break;
-    default:
-        dbg_interactiveP = TRUE;
-        parser_handle(hFile);
-    }
-    dbg_printf("WineDbg terminated on pid 0x%lx\n", dbg_curr_pid);
-
-    return 0;
-}
-
-static	unsigned dbg_start_debuggee(LPSTR cmdLine)
-{
-    PROCESS_INFORMATION	info;
-    STARTUPINFOA	startup;
-
-    memset(&startup, 0, sizeof(startup));
-    startup.cb = sizeof(startup);
-    startup.dwFlags = STARTF_USESHOWWINDOW;
-    startup.wShowWindow = SW_SHOWNORMAL;
-
-    /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
-     * while GUI:s don't
-     */
-    if (!CreateProcess(NULL, cmdLine, NULL, NULL,
-                       FALSE, 
-                       DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,
-                       NULL, NULL, &startup, &info))
-    {
-	dbg_printf("Couldn't start process '%s'\n", cmdLine);
-	return FALSE;
-    }
-    if (!info.dwProcessId)
-    {
-        /* this happens when the program being run is not a Wine binary
-         * (for example, a shell wrapper around a WineLib app)
-         */
-        /* Current fix: list running processes and let the user attach
-         * to one of them (sic)
-         * FIXME: implement a real fix => grab the process (from the
-         * running processes) from its name
-         */
-        dbg_printf("Debuggee has been started (%s)\n"
-                   "But WineDbg isn't attached to it. Maybe you're trying to debug a winelib wrapper ??\n"
-                   "Try to attach to one of those processes:\n", cmdLine);
-        /* FIXME: (HACK) we need some time before the wrapper executes the winelib app */
-        Sleep(100);
-        info_win32_processes();
-        return TRUE;
-    }
-    dbg_curr_pid = info.dwProcessId;
-    if (!(dbg_curr_process = dbg_add_process(dbg_curr_pid, 0))) return FALSE;
-
-    return TRUE;
-}
-
-void	dbg_run_debuggee(const char* args)
-{
-    if (args)
-    {
-        WINE_FIXME("Re-running current program with %s as args is broken\n", args);
-        return;
-    }
-    else 
-    {
-        DEBUG_EVENT     de;
-
-	if (!dbg_last_cmd_line)
-        {
-	    dbg_printf("Cannot find previously used command line.\n");
-	    return;
-	}
-	dbg_start_debuggee(dbg_last_cmd_line);
-        while (dbg_curr_process && WaitForDebugEvent(&de, INFINITE))
-        {
-            if (dbg_handle_debug_event(&de)) break;
-        }
-        source_list_from_addr(NULL, 0);
-    }
-}
-
 BOOL dbg_interrupt_debuggee(void)
 {
     if (!dbg_process_list) return FALSE;





More information about the wine-patches mailing list