From ac11a68f3e9e99e77480ed4fac2d402e4cb1d9ea Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 26 Mar 2000 13:37:39 +0000 Subject: [PATCH] improved exception handling merged all module handling code in new module.c file reenabled 'walk module' and 'info module' commands added ability to drive break on thread startup --- debugger/Makefile.in | 3 +- debugger/break.c | 2 - debugger/dbg.y | 5 +- debugger/debugger.h | 88 ++++++--- debugger/hash.c | 257 ------------------------- debugger/info.c | 10 - debugger/module.c | 519 +++++++++++++++++++++++++++++++++++++++++++++++++++ debugger/msc.c | 467 +++++++++++++++++++-------------------------- debugger/stabs.c | 4 +- debugger/winedbg.c | 232 ++++++++++++++--------- 10 files changed, 921 insertions(+), 666 deletions(-) create mode 100644 debugger/module.c diff --git a/debugger/Makefile.in b/debugger/Makefile.in index a5524d7e35a..54328b4cfd8 100644 --- a/debugger/Makefile.in +++ b/debugger/Makefile.in @@ -15,7 +15,8 @@ C_SRCS = \ hash.c \ info.c \ memory.c \ - msc.c \ + module.c \ + msc.c \ registers.c \ source.c \ stabs.c \ diff --git a/debugger/break.c b/debugger/break.c index 21995057f41..f38cb2f33df 100644 --- a/debugger/break.c +++ b/debugger/break.c @@ -208,7 +208,6 @@ void DEBUG_SetBreakpoints( BOOL set ) } *lpdr = DEBUG_ToLinear(&breakpoints[i].addr); - fprintf(stderr, "Setting DR%d %08lx\n", (lpdr - &DEBUG_context.Dr0) / 4, *lpdr); bits = (breakpoints[i].u.w.rw) ? DR7_RW_WRITE : DR7_RW_READ; switch (breakpoints[i].u.w.len + 1) { @@ -226,7 +225,6 @@ void DEBUG_SetBreakpoints( BOOL set ) break; } } - fprintf(stderr, "Setting DR7 %08lx\n", DEBUG_context.Dr7); } /*********************************************************************** diff --git a/debugger/dbg.y b/debugger/dbg.y index f4c38992422..1ed882bee30 100644 --- a/debugger/dbg.y +++ b/debugger/dbg.y @@ -398,8 +398,9 @@ static void mode_command(int newmode) else fprintf(stderr,"Invalid mode (use 16 or 32)\n"); } -static WINE_EXCEPTION_FILTER(wine_dbg) +static WINE_EXCEPTION_FILTER(wine_dbg_cmd) { + fprintf(stderr, "\nwine_dbg_cmd: "); switch (GetExceptionCode()) { case DEBUG_STATUS_INTERNAL_ERROR: fprintf(stderr, "WineDbg internal error\n"); @@ -537,7 +538,7 @@ BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code ) if ((ret_ok = DEBUG_ValidateRegisters())) ret_ok = DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, 1 ); } - __EXCEPT(wine_dbg) + __EXCEPT(wine_dbg_cmd) { ret_ok = 0; } diff --git a/debugger/debugger.h b/debugger/debugger.h index 104bfdebf8a..d95ce57c662 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -11,6 +11,7 @@ #include #include "windef.h" #include "winbase.h" +#include "wine/exception.h" #ifdef __i386__ #define STEP_FLAG 0x00000100 /* single step flag */ @@ -135,8 +136,8 @@ typedef struct struct expr * condition; } BREAKPOINT; -typedef struct tagWINE_DBG_THREAD { - struct tagWINE_DBG_PROCESS* process; +typedef struct tagDBG_THREAD { + struct tagDBG_PROCESS* process; HANDLE handle; DWORD tid; LPVOID start; @@ -146,21 +147,30 @@ typedef struct tagWINE_DBG_THREAD { enum exec_mode dbg_exec_mode; int dbg_exec_count; BREAKPOINT stepOverBP; - struct tagWINE_DBG_THREAD* next; - struct tagWINE_DBG_THREAD* prev; -} WINE_DBG_THREAD; + struct tagDBG_THREAD* next; + struct tagDBG_THREAD* prev; +} DBG_THREAD; -typedef struct tagWINE_DBG_PROCESS { +typedef struct tagDBG_PROCESS { HANDLE handle; DWORD pid; - WINE_DBG_THREAD* threads; - struct tagWINE_DBG_PROCESS* next; - struct tagWINE_DBG_PROCESS* prev; -} WINE_DBG_PROCESS; - -extern WINE_DBG_PROCESS* DEBUG_CurrProcess; -extern WINE_DBG_THREAD* DEBUG_CurrThread; -extern CONTEXT DEBUG_context; + DBG_THREAD* threads; + int num_threads; + struct tagDBG_MODULE* modules; + /* + * 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 + * allow us to do an 'info shared' type of deal, and we use the index + * to eliminate duplicates. + */ + int next_index; + struct tagDBG_PROCESS* next; + struct tagDBG_PROCESS* prev; +} DBG_PROCESS; + +extern DBG_PROCESS* DEBUG_CurrProcess; +extern DBG_THREAD* DEBUG_CurrThread; +extern CONTEXT DEBUG_context; #define DEBUG_READ_MEM(addr, buf, len) \ (ReadProcessMemory(DEBUG_CurrProcess->handle, (addr), (buf), (len), NULL)) @@ -174,6 +184,28 @@ extern CONTEXT DEBUG_context; #define DEBUG_WRITE_MEM_VERBOSE(addr, buf, len) \ (DEBUG_WRITE_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0)) +typedef struct tagDBG_MODULE { + struct tagDBG_MODULE* next; + void* load_addr; + char* module_name; + char status; + char type; + short int dbg_index; + HMODULE handle; + void* extra_info; +} DBG_MODULE; + +/* status field */ +#define DM_STATUS_NEW 0 +#define DM_STATUS_LOADED 1 +#define DM_STATUS_ERROR 2 + +/* type field */ +#define DM_TYPE_UNKNOWN 0 +#define DM_TYPE_ELF 1 +#define DM_TYPE_NE 2 +#define DM_TYPE_PE 3 + #ifdef __i386__ #ifdef REG_SP /* Some Sun includes define this */ #undef REG_SP @@ -249,7 +281,6 @@ extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag, unsigned int ebp, struct list_id * source); extern void DEBUG_ReadSymbolTable( const char * filename ); -extern int DEBUG_LoadEntryPoints( const char * prefix ); extern void DEBUG_AddLineNumber( struct name_hash * func, int line_num, unsigned long offset ); extern struct wine_locals * @@ -270,7 +301,7 @@ extern BOOL DEBUG_GetLineNumberAddr( struct name_hash *, const int lineno, extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym, struct datatype * type); -BOOL DEBUG_Normalize(struct name_hash * nh ); +extern BOOL DEBUG_Normalize(struct name_hash * nh ); /* debugger/info.c */ extern void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format ); @@ -309,6 +340,24 @@ extern int DEBUG_GetSelectorType( WORD sel ); extern int DEBUG_IsSelectorSystem( WORD sel ); #endif + /* debugger/module.c */ +extern int DEBUG_LoadEntryPoints( const char * prefix ); +extern void DEBUG_LoadModule32( const char* name, DWORD base ); +extern DBG_MODULE* DEBUG_AddModule(const char* name, int type, + void* mod_addr, HMODULE hmod); +extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type); +extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type); +extern DBG_MODULE* DEBUG_RegisterPEModule(HMODULE, u_long load_addr, const char* name); +extern DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name); +extern int DEBUG_ProcessDeferredDebug(void); +extern void DEBUG_InfoShare(void); + + /* debugger/msc.c */ +extern int DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, void* nth, unsigned long nth_ofs); +extern int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, void* nth, unsigned long nth_ofs); +extern void DEBUG_InitCVDataTypes(void); +extern int DEBUG_ProcessMSCDebugInfo(DBG_MODULE* module); + /* debugger/registers.c */ extern void DEBUG_SetRegister( enum debug_regs reg, int val ); extern int DEBUG_GetRegister( enum debug_regs reg ); @@ -330,13 +379,6 @@ extern int DEBUG_ReadExecutableDbgInfo(void); extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff, int stablen, unsigned int strtaboff, int strtablen); - /* debugger/msc.c */ -extern int DEBUG_RegisterDebugInfo( HMODULE, const char *); -extern int DEBUG_ProcessDeferredDebug(void); -extern int DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, const char * name); -extern void DEBUG_InfoShare(void); -extern void DEBUG_InitCVDataTypes(void); - /* debugger/types.c */ extern int DEBUG_nchar; extern void DEBUG_InitTypes(void); diff --git a/debugger/hash.c b/debugger/hash.c index cd6cd190014..1eaf5ce971a 100644 --- a/debugger/hash.c +++ b/debugger/hash.c @@ -11,11 +11,7 @@ #include #include #include -#include "neexe.h" -#include "module.h" -#include "process.h" #include "debugger.h" -#include "toolhelp.h" #define NR_NAME_HASH 16384 #ifndef PATH_MAX @@ -771,259 +767,6 @@ void DEBUG_ReadSymbolTable( const char * filename ) } -/*********************************************************************** - * DEBUG_LoadEntryPoints16 - * - * Load the entry points of a Win16 module into the hash table. - */ -static void DEBUG_LoadEntryPoints16( HMODULE16 hModule, NE_MODULE *pModule, - const char *name ) -{ - DBG_VALUE value; - char buffer[256]; - FARPROC16 address; - unsigned char *cpnt = (unsigned char *)pModule + pModule->name_table; - - value.type = NULL; - value.cookie = DV_TARGET; - value.addr.seg = 0; - value.addr.off = 0; - - /* First search the resident names */ - - while (*cpnt) - { - cpnt += *cpnt + 1 + sizeof(WORD); - sprintf( buffer, "%s.%.*s", name, *cpnt, cpnt + 1 ); - if ((address = NE_GetEntryPoint(hModule, *(WORD *)(cpnt + *cpnt + 1)))) - { - value.addr.seg = HIWORD(address); - value.addr.off = LOWORD(address); - DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC ); - } - } - - /* Now search the non-resident names table */ - - if (!pModule->nrname_handle) return; /* No non-resident table */ - cpnt = (char *)GlobalLock16( pModule->nrname_handle ); - while (*cpnt) - { - cpnt += *cpnt + 1 + sizeof(WORD); - sprintf( buffer, "%s.%.*s", name, *cpnt, cpnt + 1 ); - if ((address = NE_GetEntryPoint(hModule, *(WORD *)(cpnt + *cpnt + 1)))) - { - value.addr.seg = HIWORD(address); - value.addr.off = LOWORD(address); - DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC ); - } - } -} - - -/*********************************************************************** - * DEBUG_LoadEntryPoints32 - * - * Load the entry points of a Win32 module into the hash table. - */ -static void DEBUG_LoadEntryPoints32( HMODULE hModule, const char *name ) -{ -#define RVA(x) (hModule+(DWORD)(x)) - - DBG_VALUE value; - char buffer[256]; - int i, j; - IMAGE_SECTION_HEADER *pe_seg; - IMAGE_EXPORT_DIRECTORY *exports; - IMAGE_DATA_DIRECTORY *dir; - WORD *ordinals; - void **functions; - const char **names; - - value.type = NULL; - value.cookie = DV_TARGET; - value.addr.seg = 0; - value.addr.off = 0; - - /* Add start of DLL */ - - value.addr.off = hModule; - DEBUG_AddSymbol( name, &value, NULL, SYM_WIN32 | SYM_FUNC ); - - /* Add entry point */ - - sprintf( buffer, "%s.EntryPoint", name ); - value.addr.off = (DWORD)RVA_PTR( hModule, OptionalHeader.AddressOfEntryPoint ); - DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC ); - - /* Add start of sections */ - - pe_seg = PE_SECTIONS(hModule); - for (i = 0; i < PE_HEADER(hModule)->FileHeader.NumberOfSections; i++) - { - sprintf( buffer, "%s.%s", name, pe_seg->Name ); - value.addr.off = RVA(pe_seg->VirtualAddress ); - DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC ); - pe_seg++; - } - - /* Add exported functions */ - - dir = &PE_HEADER(hModule)->OptionalHeader. - DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; - if (dir->Size) - { - exports = (IMAGE_EXPORT_DIRECTORY *)RVA( dir->VirtualAddress ); - ordinals = (WORD *)RVA( exports->AddressOfNameOrdinals ); - names = (const char **)RVA( exports->AddressOfNames ); - functions = (void **)RVA( exports->AddressOfFunctions ); - - for (i = 0; i < exports->NumberOfNames; i++) - { - if (!names[i]) continue; - sprintf( buffer, "%s.%s", name, (char *)RVA(names[i]) ); - value.addr.off = RVA( functions[ordinals[i]] ); - DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC ); - } - - for (i = 0; i < exports->NumberOfFunctions; i++) - { - if (!functions[i]) continue; - /* Check if we already added it with a name */ - 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 ); - value.addr.off = (DWORD)RVA( functions[i] ); - DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC ); - } - } - DEBUG_RegisterDebugInfo(hModule, name); -#undef RVA -} - -typedef struct tag_lmr{ - char* module_name; - BOOL is16; - struct tag_lmr* next; -} DBG_LoadedModuleRef; - -typedef struct { - int rowcount; - int first; - const char* pfx; -} DBG_LEPData; - -static BOOL DEBUG_LEPHelper(const char* mod_name, BOOL is16, DBG_LEPData* lep) -{ -static DBG_LoadedModuleRef* lmr = NULL; - DBG_LoadedModuleRef* p; - DBG_LoadedModuleRef** pp1; - DBG_LoadedModuleRef* p2; - int len = strlen(mod_name); - int cmp; - - for (p = lmr; p; p = p->next) { - cmp = strcasecmp(p->module_name, mod_name); - if (cmp == 0 && p->is16 == is16) - return FALSE; - if (cmp >= 0) - break; - } - - if (!lep->first) { - if (lep->pfx) fprintf( stderr, lep->pfx ); - fprintf( stderr, " " ); - lep->first++; - lep->rowcount = 3; - } - - if ((lep->rowcount + len) > 76) - { - fprintf( stderr, "\n "); - lep->rowcount = 3; - } - fprintf( stderr, " %s", mod_name ); - lep->rowcount += len + 1; - - p = DBG_alloc(sizeof(*lmr)); - p->module_name = DBG_strdup(mod_name); - p->is16 = is16; - - p2 = NULL; - for (pp1 = &lmr; *pp1; pp1 = &(*pp1)->next) { - if (strcasecmp((*pp1)->module_name, mod_name) > 0) - break; - p2 = *pp1; - } - if (p2 == NULL) - { - p->next = lmr; - lmr = p; - } - else if (*pp1 == NULL) - { - p->next = NULL; - *pp1 = p; - } - else - { - p->next = *pp1; - p2->next = p; - } - - return TRUE; -} - -/*********************************************************************** - * DEBUG_LoadEntryPoints - * - * Load the entry points of all the modules into the hash table. - */ -int DEBUG_LoadEntryPoints(const char* pfx) -{ - MODULEENTRY entry; - NE_MODULE* pModule; - BOOL ok; - WINE_MODREF*wm; - DBG_LEPData lep; - PDB* current = PROCESS_Current(); - - lep.first = 0; - lep.pfx = pfx; - - /* FIXME: we assume that a module is never removed from memory */ - - for (ok = ModuleFirst16(&entry); ok; ok = ModuleNext16(&entry)) - { - if (!(pModule = NE_GetPtr( entry.hModule ))) continue; - if (!(pModule->flags & NE_FFLAGS_WIN32) && /* NE module */ - DEBUG_LEPHelper( entry.szModule, TRUE, &lep )) - DEBUG_LoadEntryPoints16( entry.hModule, pModule, entry.szModule ); - } - - for (wm = current->modref_list; wm; wm=wm->next) - { - if ((wm->flags & WINE_MODREF_INTERNAL)) - { - if (DEBUG_LEPHelper( wm->modname, FALSE, &lep )) - DEBUG_LoadEntryPoints32( wm->module, wm->modname ); - } - } - if (lep.first) fprintf( stderr, " $"); - for (wm = current->modref_list; wm; wm=wm->next) - { - if (!(wm->flags & WINE_MODREF_INTERNAL)) - { - if (DEBUG_LEPHelper( wm->modname, FALSE, &lep )) - DEBUG_LoadEntryPoints32( wm->module, wm->modname ); - } - } - if (lep.first) fprintf( stderr, "\n" ); - return lep.first; -} - - void DEBUG_AddLineNumber( struct name_hash * func, int line_num, unsigned long offset ) diff --git a/debugger/info.c b/debugger/info.c index 7f1f64f0705..19ca90c356c 100644 --- a/debugger/info.c +++ b/debugger/info.c @@ -344,16 +344,6 @@ void DEBUG_WalkClasses(void) DBG_free(cw.table); } -void DEBUG_DumpModule(DWORD mod) -{ - fprintf(stderr, "No longer doing info module '0x%08lx'\n", mod); -} - -void DEBUG_WalkModules(void) -{ - fprintf(stderr, "No longer walking modules list\n"); -} - void DEBUG_DumpQueue(DWORD q) { fprintf(stderr, "No longer doing info queue '0x%08lx'\n", q); diff --git a/debugger/module.c b/debugger/module.c new file mode 100644 index 00000000000..f73dfb294a1 --- /dev/null +++ b/debugger/module.c @@ -0,0 +1,519 @@ +/* -*- tab-width: 8; c-basic-offset: 4 -*- */ +/* + * File module.c - module handling for the wine debugger + * + * Copyright (C) 1993, Eric Youngdale. + * 2000, Eric Pouech + */ +#include "config.h" +#include +#include +#include +#include "neexe.h" +#include "peexe.h" +#include "module.h" +#include "debugger.h" +#include "toolhelp.h" + +/*********************************************************************** + * Creates and links a new module to the current process + * + */ +DBG_MODULE* DEBUG_AddModule(const char* name, int type, + void* mod_addr, HMODULE hmodule) +{ + DBG_MODULE* wmod; + + if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod)))) + return NULL; + + memset(wmod, 0, sizeof(*wmod)); + + wmod->next = DEBUG_CurrProcess->modules; + wmod->status = DM_STATUS_NEW; + wmod->type = type; + wmod->load_addr = mod_addr; + wmod->handle = hmodule; + wmod->dbg_index = DEBUG_CurrProcess->next_index; + wmod->module_name = DBG_strdup(name); + DEBUG_CurrProcess->modules = wmod; + + return wmod; +} + +/*********************************************************************** + * DEBUG_FindModuleByName + * + */ +DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type) +{ + DBG_MODULE* wmod; + + for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) { + if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && + !strcasecmp(name, wmod->module_name)) break; + } + return wmod; +} + +/*********************************************************************** + * DEBUG_FindModuleByAddr + * + * either the addr where module is loaded, or any address inside the + * module + */ +DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, int type) +{ + DBG_MODULE* wmod; + DBG_MODULE* res = NULL; + + for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) { + if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && + (u_long)addr >= (u_long)wmod->load_addr && + (!res || res->load_addr < wmod->load_addr)) + res = wmod; + } + return res; +} + +/*********************************************************************** + * DEBUG_FindModuleByHandle + */ +DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type) +{ + DBG_MODULE* wmod; + + for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) { + if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break; + } + return wmod; +} + +/*********************************************************************** + * DEBUG_RegisterELFModule + * + * ELF modules are also entered into the list - this is so that we + * can make 'info shared' types of displays possible. + */ +DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name) +{ + DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0); + + if (!wmod) return NULL; + + wmod->status = DM_STATUS_LOADED; + DEBUG_CurrProcess->next_index++; + + return wmod; +} + +/*********************************************************************** + * DEBUG_RegisterPEModule + * + */ +DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name) +{ + DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule); + + if (!wmod) return NULL; + + DEBUG_CurrProcess->next_index++; + + return wmod; +} + +/*********************************************************************** + * DEBUG_RegisterNEModule + * + */ +DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name) +{ + DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule); + + if (!wmod) return NULL; + + wmod->status = DM_STATUS_LOADED; + DEBUG_CurrProcess->next_index++; + return wmod; +} + +/*********************************************************************** + * DEBUG_GetEP16 + * + * Helper function fo DEBUG_LoadModuleEPs16: + * finds the address of a given entry point from a given module + */ +static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module, + WORD ordinal, DBG_ADDR* addr) +{ + void* idx; + ET_ENTRY entry; + ET_BUNDLE bundle; + SEGTABLEENTRY ste; + + bundle.next = module->entry_table; + do { + if (!bundle.next) + return FALSE; + idx = moduleAddr + bundle.next; + if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle))) + return FALSE; + } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last)); + + if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) + + (ordinal - bundle.first - 1) * sizeof(ET_ENTRY), + &entry, sizeof(ET_ENTRY))) + return FALSE; + + addr->seg = entry.segnum; + addr->off = entry.offs; + + if (addr->seg == 0xfe) addr->seg = 0xffff; /* constant entry */ + else { + if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table + + sizeof(ste) * (addr->seg - 1), + &ste, sizeof(ste))) + return FALSE; + addr->seg = GlobalHandleToSel16(ste.hSeg); + } + return TRUE; +} + +/*********************************************************************** + * DEBUG_LoadModule16 + * + * Load the entry points of a Win16 module into the hash table. + */ +static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name) +{ + DBG_VALUE value; + BYTE buf[1 + 256 + 2]; + char epname[512]; + char* cpnt; + DBG_MODULE* wmod; + + wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name); + + value.type = NULL; + value.cookie = DV_TARGET; + value.addr.seg = 0; + value.addr.off = 0; + + cpnt = moduleAddr + module->name_table; + + /* First search the resident names */ + + /* skip module name */ + if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0]) + return; + cpnt += 1 + buf[0] + sizeof(WORD); + + while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) { + sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]); + if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) { + DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC); + } + cpnt += buf[0] + 1 + sizeof(WORD); + } + + /* Now search the non-resident names table */ + if (!module->nrname_handle) return; /* No non-resident table */ + cpnt = (char *)GlobalLock16(module->nrname_handle); + while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) { + sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]); + if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) { + DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC); + } + cpnt += buf[0] + 1 + sizeof(WORD); + } + GlobalUnlock16(module->nrname_handle); +} + +/*********************************************************************** + * DEBUG_LoadModule32 + */ +void DEBUG_LoadModule32(const char* name, DWORD base) +{ + DBG_VALUE value; + char buffer[256]; + char bufstr[256]; + int i; + IMAGE_NT_HEADERS pe_header; + DWORD pe_header_ofs; + IMAGE_SECTION_HEADER pe_seg; + DWORD pe_seg_ofs; + IMAGE_DATA_DIRECTORY dir; + DWORD dir_ofs; + DBG_MODULE* wmod; + + /* FIXME: we make the assumption that hModule == base */ + wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name); + + fprintf(stderr, "Registring 32bit DLL '%s' at %08lx\n", name, base); + + value.type = NULL; + value.cookie = DV_TARGET; + value.addr.seg = 0; + value.addr.off = 0; + + /* grab PE Header */ + if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)), + &pe_header_ofs, sizeof(pe_header_ofs)) || + !DEBUG_READ_MEM_VERBOSE((void*)(base + pe_header_ofs), + &pe_header, sizeof(pe_header))) + return; + + if (wmod) { + DEBUG_RegisterMSCDebugInfo(wmod, &pe_header, pe_header_ofs); + DEBUG_RegisterStabsDebugInfo(wmod, &pe_header, pe_header_ofs); + } + + /* Add start of DLL */ + value.addr.off = base; + DEBUG_AddSymbol(name, &value, NULL, SYM_WIN32 | SYM_FUNC); + + /* Add entry point */ + sprintf(buffer, "%s.EntryPoint", name); + value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint; + DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC); + + /* Add start of sections */ + pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) + + pe_header.FileHeader.SizeOfOptionalHeader; + + 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)) || + !DEBUG_READ_MEM_VERBOSE((void*)pe_seg.Name, bufstr, sizeof(bufstr))) + continue; + bufstr[sizeof(bufstr) - 1] = 0; + sprintf(buffer, "%s.%s", name, bufstr); + value.addr.off = base + pe_seg.VirtualAddress; + DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC); + } + + /* Add exported functions */ + dir_ofs = pe_header_ofs + + OFFSET_OF(IMAGE_NT_HEADERS, + OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]); + if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) { + IMAGE_EXPORT_DIRECTORY exports; + WORD* ordinals = NULL; + void** functions = NULL; + DWORD* names = NULL; + int j; + + if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress), + &exports, sizeof(exports)) && + + ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) && + DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions), + functions, sizeof(functions[0]) * exports.NumberOfFunctions) && + + ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) && + DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals), + ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) && + + ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) && + DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames), + names, sizeof(names[0]) * exports.NumberOfNames)) { + + for (i = 0; i < exports.NumberOfNames; i++) { + if (!names[i] || + !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr))) + continue; + bufstr[sizeof(bufstr) - 1] = 0; + sprintf(buffer, "%s.%s", name, bufstr); + value.addr.off = base + (DWORD)functions[ordinals[i]]; + DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC); + } + + for (i = 0; i < exports.NumberOfFunctions; i++) { + if (!functions[i]) continue; + /* Check if we already added it with a name */ + 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); + value.addr.off = base + (DWORD)functions[i]; + DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC); + } + } + DBG_free(functions); + DBG_free(ordinals); + DBG_free(names); + } +} + +/*********************************************************************** + * DEBUG_LoadEntryPoints + * + * Load the entry points of all the modules into the hash table. + */ +int DEBUG_LoadEntryPoints(const char* pfx) +{ + MODULEENTRY entry; + NE_MODULE module; + void* moduleAddr; + int first = 0; + int rowcount = 0; + int len; + + /* FIXME: we assume that a module is never removed from memory */ + if (ModuleFirst16(&entry)) do { + if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) || + !(moduleAddr = NE_GetPtr(entry.hModule)) || + !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) || + (module.flags & NE_FFLAGS_WIN32) /* NE module */) + continue; + if (!first) { + if (pfx) fprintf(stderr, pfx); + fprintf(stderr, " "); + rowcount = 3 + (pfx ? strlen(pfx) : 0); + first = 1; + } + + len = strlen(entry.szModule); + if ((rowcount + len) > 76) { + fprintf(stderr, "\n "); + rowcount = 3; + } + fprintf(stderr, " %s", entry.szModule); + rowcount += len + 1; + + DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule); + } while (ModuleNext16(&entry)); + + if (first) fprintf(stderr, "\n"); + return first; +} + +/*********************************************************************** + * DEBUG_ProcessDeferredDebug + * + */ +int DEBUG_ProcessDeferredDebug(void) +{ + DBG_MODULE* wmod; + int sts; + int last_proc = -1; + int need_print = 0; + int rowcount = 0; + int len; + + for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) { + if (wmod->status != DM_STATUS_NEW) continue; + + if (last_proc != wmod->dbg_index) { + if (!need_print) { + fprintf(stderr, "DeferredDebug for:"); + rowcount = 18; + need_print = 1; + } + if (rowcount + (len = strlen(wmod->module_name)) > 76) { + rowcount = 0; + fprintf(stderr, "\n"); + } else { + fprintf(stderr, " "); + rowcount++; + } + rowcount += len; + fprintf(stderr, wmod->module_name); + last_proc = wmod->dbg_index; + } + + sts = (wmod->extra_info) ? DEBUG_ProcessMSCDebugInfo(wmod) : TRUE; + wmod->status = (sts) ? DM_STATUS_LOADED : DM_STATUS_ERROR; + } + if (need_print) fprintf(stderr, "\n"); + return TRUE; +} + +/*********************************************************************** + * DEBUG_InfoShare + * + * Display shared libarary information. + */ +void DEBUG_InfoShare(void) +{ + DBG_MODULE* wmod; + const char* xtype; + + fprintf(stderr, "Address\t\tModule\tName\n"); + + for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) { + switch (wmod->type) { + case DM_TYPE_NE: xtype = "NE"; break; + case DM_TYPE_PE: xtype = "PE"; break; + case DM_TYPE_ELF: xtype = "ELF"; break; + default: xtype = "???"; break; + } + fprintf(stderr, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr, + xtype, wmod->module_name); + } +} + +static const char* DEBUG_GetModuleType(int type) +{ + switch (type) { + case DM_TYPE_NE: return "NE"; + case DM_TYPE_PE: return "PE"; + case DM_TYPE_ELF: return "ELF"; + default: return "???";; + } +} + +static const char* DEBUG_GetModuleStatus(int status) +{ + switch (status) { + case DM_STATUS_NEW: return "deferred"; + case DM_STATUS_LOADED: return "ok"; + case DM_STATUS_ERROR: return "error"; + default: return "???"; + } +} + +/*********************************************************************** + * DEBUG_ + * Display information about a given module (DLL or EXE) + */ +void DEBUG_DumpModule(DWORD mod) +{ + DBG_MODULE* wmod; + + if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) && + !(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) { + fprintf(stderr, "'0x%08lx' is not a valid module handle or address\n", mod); + return; + } + + fprintf(stderr, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n", + wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr, + DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status)); +} + +/*********************************************************************** + * DEBUG_WalkModules + * + * Display information about all modules (DLLs and EXEs) + */ +void DEBUG_WalkModules(void) +{ + DBG_MODULE* wmod; + const char* xtype; + + fprintf(stderr, "Address\t\tModule\tName\n"); + + for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) { + switch (wmod->type) { + case DM_TYPE_NE: xtype = "NE"; break; + case DM_TYPE_PE: xtype = "PE"; break; + case DM_TYPE_ELF: continue; + default: xtype = "???"; break; + } + + fprintf(stderr, "0x%8.8x\t(%s)\t%s\n", + (unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type), + wmod->module_name); + } +} + diff --git a/debugger/msc.c b/debugger/msc.c index 8842f34fe5d..24bc6804961 100644 --- a/debugger/msc.c +++ b/debugger/msc.c @@ -36,9 +36,19 @@ #include "peexe.h" #include "file.h" +typedef struct { + IMAGE_DEBUG_DIRECTORY dbgdir; + u_long sect_ofs; + int nsect; + char* dbg_info; + int dbg_size; +} MSC_DBG_INFO; + +#define MSC_INFO(module) ((MSC_DBG_INFO*)((module)->extra_info)) + /* - *dbg_filename must be at least MAX_PATHNAME_LEN bytes in size -*/ + * dbg_filename must be at least MAX_PATHNAME_LEN bytes in size + */ static void LocateDebugInfoFile(char *filename, char *dbg_filename) { char *str1 = DBG_alloc(MAX_PATHNAME_LEN*10); @@ -75,13 +85,6 @@ ok: DBG_free(str2); return; } -/* - * 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 - * allow us to do an 'info shared' type of deal, and we use the index - * to eliminate duplicates. - */ -static int DEBUG_next_index = 0; union any_size { @@ -690,30 +693,6 @@ struct codeview_linetab_hdr /* - ******************************************************************** - */ -struct deferred_debug_info -{ - struct deferred_debug_info * next; - char * load_addr; - char * module_name; - char * dbg_info; - int dbg_size; - HMODULE module; - PIMAGE_DEBUG_DIRECTORY dbgdir; - PIMAGE_SECTION_HEADER sectp; - int nsect; - short int dbg_index; - char status; -}; - -#define DF_STATUS_NEW 0 -#define DF_STATUS_LOADED 1 -#define DF_STATUS_ERROR 2 - -struct deferred_debug_info * dbglist = NULL; - -/* * A simple macro that tells us whether a given COFF symbol is a * function or not. */ @@ -1295,36 +1274,37 @@ DEBUG_InitCVDataTypes(void) * We don't fully process it here for performance reasons. */ int -DEBUG_RegisterDebugInfo( HMODULE hModule, const char *module_name) +DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, void* _nth, unsigned long nth_ofs) { int has_codeview = FALSE; int rtn = FALSE; - int orig_size; - PIMAGE_DEBUG_DIRECTORY dbgptr; - u_long v_addr, size; - PIMAGE_NT_HEADERS nth = PE_HEADER(hModule); + IMAGE_DEBUG_DIRECTORY dbg; + u_long v_addr, size, orig_size; + PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth; - size = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; - if (size) { + orig_size = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if (orig_size) { v_addr = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; - dbgptr = (PIMAGE_DEBUG_DIRECTORY) (hModule + v_addr); - orig_size = size; - for(; size >= sizeof(*dbgptr); size -= sizeof(*dbgptr), dbgptr++ ) + for(size = orig_size; size >= sizeof(dbg); size -= sizeof(dbg)) { - switch(dbgptr->Type) + if (!DEBUG_READ_MEM_VERBOSE((void*)(module->load_addr + v_addr), &dbg, sizeof(dbg))) continue; + + switch(dbg.Type) { case IMAGE_DEBUG_TYPE_CODEVIEW: case IMAGE_DEBUG_TYPE_MISC: has_codeview = TRUE; break; } + v_addr += sizeof(dbg); } - size = orig_size; - dbgptr = (PIMAGE_DEBUG_DIRECTORY) (hModule + v_addr); - for(; size >= sizeof(*dbgptr); size -= sizeof(*dbgptr), dbgptr++ ) + v_addr = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + for(size = orig_size; size >= sizeof(dbg); size -= sizeof(dbg)) { - switch(dbgptr->Type) + if (!DEBUG_READ_MEM_VERBOSE((void*)(module->load_addr + v_addr), &dbg, sizeof(dbg))) continue; + + switch(dbg.Type) { case IMAGE_DEBUG_TYPE_COFF: /* @@ -1352,22 +1332,14 @@ DEBUG_RegisterDebugInfo( HMODULE hModule, const char *module_name) * it just points to itself, and we can ignore this. */ - - - - - - if( (dbgptr->Type != IMAGE_DEBUG_TYPE_MISC) || - (PE_HEADER(hModule)->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0 ) + if( (dbg.Type != IMAGE_DEBUG_TYPE_MISC) || + (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0 ) { - char fn[PATH_MAX]; - int fd = -1; - DOS_FULL_NAME full_name; - struct deferred_debug_info* deefer = (struct deferred_debug_info *) DBG_alloc(sizeof(*deefer)); - - deefer->module = hModule; - deefer->load_addr = (char *)hModule; - + char fn[PATH_MAX]; + int fd = -1; + DOS_FULL_NAME full_name; + char* dbg_info; + /* * Read the important bits. What we do after this depends * upon the type, but this is always enough so we are able @@ -1377,60 +1349,72 @@ DEBUG_RegisterDebugInfo( HMODULE hModule, const char *module_name) * the DataDirectory array's content. One its entry contains the *beloved* * debug information. (Note the DataDirectory is mapped, not its content) */ - - if (GetModuleFileNameA(hModule, fn, sizeof(fn)) > 0 && + /* FIXME: the module->handle value is not usable in the debugger's process */ + if (GetModuleFileNameA(module->handle, fn, sizeof(fn)) > 0 && DOSFS_GetFullName(fn, TRUE, &full_name) && (fd = open(full_name.long_name, O_RDONLY)) > 0) - { - deefer->dbg_info = mmap(NULL, dbgptr->SizeOfData, - PROT_READ, MAP_PRIVATE, fd, dbgptr->PointerToRawData); + { + dbg_info = mmap(NULL, dbg.SizeOfData, + PROT_READ, MAP_PRIVATE, fd, dbg.PointerToRawData); close(fd); - if( deefer->dbg_info == (char *) 0xffffffff ) - { - DBG_free(deefer); - break; - } + if( dbg_info == (char *) 0xffffffff ) break; } else { - DBG_free(deefer); - fprintf(stderr, " (not mapped: fn=%s, lfn=%s, fd=%d)", fn, full_name.long_name, fd); + fprintf(stderr, " (not mapped: fn='%s', lfn='%s', fd=%d)\n", fn, full_name.long_name, fd); break; } - deefer->dbg_size = dbgptr->SizeOfData; - deefer->dbgdir = dbgptr; - deefer->next = dbglist; - deefer->status = DF_STATUS_NEW; - deefer->dbg_index = DEBUG_next_index; - deefer->module_name = DBG_strdup(module_name); - - deefer->sectp = PE_SECTIONS(hModule); - deefer->nsect = PE_HEADER(hModule)->FileHeader.NumberOfSections; - - dbglist = deefer; + if (!(module->extra_info = DBG_alloc(sizeof(MSC_DBG_INFO)))) + break; + + MSC_INFO(module)->dbg_info = dbg_info; + MSC_INFO(module)->dbg_size = dbg.SizeOfData; + MSC_INFO(module)->dbgdir = dbg; + MSC_INFO(module)->sect_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) + + nth->FileHeader.SizeOfOptionalHeader; + MSC_INFO(module)->nsect = nth->FileHeader.NumberOfSections; } break; #if 0 default: #endif } + v_addr += sizeof(dbg); } - DEBUG_next_index++; + DEBUG_CurrProcess->next_index++; } - /* look for .stabs/.stabstr sections */ - { - PIMAGE_SECTION_HEADER pe_seg = PE_SECTIONS(hModule); - int i,stabsize=0,stabstrsize=0; - unsigned int stabs=0,stabstr=0; - - for (i=0;iFileHeader.NumberOfSections;i++) { - if (!strcasecmp(pe_seg[i].Name,".stab")) { - stabs = pe_seg[i].VirtualAddress; - stabsize = pe_seg[i].SizeOfRawData; - } - if (!strncasecmp(pe_seg[i].Name,".stabstr",8)) { - stabstr = pe_seg[i].VirtualAddress; - stabstrsize = pe_seg[i].SizeOfRawData; + + return rtn; +} + +/* look for stabs information in PE header (it's how mingw compiler provides its + * debugging information + */ +int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, void* _nth, unsigned long nth_ofs) +{ + IMAGE_SECTION_HEADER pe_seg; + unsigned long pe_seg_ofs; + int i, stabsize = 0, stabstrsize = 0; + unsigned int stabs = 0, stabstr = 0; + char bufstr[256]; + PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth; + + pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) + + nth->FileHeader.SizeOfOptionalHeader; + + for (i = 0; i < nth->FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) { + if (!DEBUG_READ_MEM_VERBOSE((void*)(module->load_addr + pe_seg_ofs), + &pe_seg, sizeof(pe_seg)) || + !DEBUG_READ_MEM_VERBOSE((void*)pe_seg.Name, bufstr, sizeof(bufstr))) + {fprintf(stderr, "err3\n");continue;} + bufstr[sizeof(bufstr) - 1] = 0; + + if (!strcasecmp(bufstr, ".stab")) { + stabs = pe_seg.VirtualAddress; + stabsize = pe_seg.SizeOfRawData; + } else if (!strncasecmp(bufstr, ".stabstr", 8)) { + stabstr = pe_seg.VirtualAddress; + stabstrsize = pe_seg.SizeOfRawData; } } if (stabstrsize && stabsize) { @@ -1438,56 +1422,21 @@ DEBUG_RegisterDebugInfo( HMODULE hModule, const char *module_name) /* Won't work currently, since MINGW32 uses some special typedefs * which we do not handle yet. Support for them is a bit difficult. */ - DEBUG_ParseStabs(hModule,0,stabs,stabsize,stabstr,stabstrsize); + /* FIXME: load_addr is in a different address space... */ + DEBUG_ParseStabs(module->load_addr, 0, stabs, stabsize, stabstr, stabstrsize); #endif fprintf(stderr,"(stabs not loaded)"); } - } - return (rtn); -} - -/* - * ELF modules are also entered into the list - this is so that we - * can make 'info shared' types of displays possible. - */ -int -DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, const char * name) -{ - struct deferred_debug_info * deefer; - - deefer = (struct deferred_debug_info *) DBG_alloc(sizeof(*deefer)); - deefer->module = 0; - - /* - * Read the important bits. What we do after this depends - * upon the type, but this is always enough so we are able - * to proceed if we know what we need to do next. - */ - deefer->dbg_size = size; - deefer->dbg_info = (char *) NULL; - - deefer->load_addr = (char *) load_addr; - deefer->dbgdir = NULL; - deefer->next = dbglist; - deefer->status = DF_STATUS_LOADED; - deefer->dbg_index = DEBUG_next_index; - deefer->module_name = DBG_strdup(name); - dbglist = deefer; - - DEBUG_next_index++; - - return (TRUE); + return TRUE; } - - /* * Process COFF debugging information embedded in a Win32 application. * */ static int -DEBUG_ProcessCoff(struct deferred_debug_info * deefer) +DEBUG_ProcessCoff(DBG_MODULE* module) { struct CoffAuxSection * aux; struct CoffDebug * coff; @@ -1512,7 +1461,7 @@ DEBUG_ProcessCoff(struct deferred_debug_info * deefer) int rtn = FALSE; char * this_file = NULL; - coff = (struct CoffDebug *) deefer->dbg_info; + coff = (struct CoffDebug *) MSC_INFO(module)->dbg_info; coff_symbol = (struct CoffSymbol *) ((unsigned int) coff + coff->SymbolOffset); coff_linetab = (struct CoffLinenum *) ((unsigned int) coff + coff->LinenumberOffset); @@ -1679,7 +1628,7 @@ DEBUG_ProcessCoff(struct deferred_debug_info * deefer) } new_value.addr.seg = 0; - new_value.addr.off = (int) (deefer->load_addr + coff_sym->Value); + new_value.addr.off = (int) (module->load_addr + coff_sym->Value); if( curr_file->neps + 1 >= curr_file->neps_alloc ) { @@ -1719,7 +1668,7 @@ DEBUG_ProcessCoff(struct deferred_debug_info * deefer) } new_value.addr.seg = 0; - new_value.addr.off = (int) (deefer->load_addr + coff_sym->Value); + new_value.addr.off = (int) (module->load_addr + coff_sym->Value); #if 0 fprintf(stderr, "%d: %x %s\n", i, new_value.addr.off, nampnt); @@ -1778,7 +1727,7 @@ DEBUG_ProcessCoff(struct deferred_debug_info * deefer) } new_value.addr.seg = 0; - new_value.addr.off = (int) (deefer->load_addr + coff_sym->Value); + new_value.addr.off = (int) (module->load_addr + coff_sym->Value); #if 0 fprintf(stderr, "%d: %x %s\n", i, new_value.addr.off, nampnt); @@ -1860,7 +1809,7 @@ DEBUG_ProcessCoff(struct deferred_debug_info * deefer) { if (i+1 >= coff_files[j].neps) break; DEBUG_GetSymbolAddr(coff_files[j].entries[i+1], &new_value.addr); - if( (((unsigned int)deefer->load_addr + + if( (((unsigned int)module->load_addr + linepnt->VirtualAddr) >= new_value.addr.off) ) { i++; @@ -1875,7 +1824,7 @@ DEBUG_ProcessCoff(struct deferred_debug_info * deefer) DEBUG_GetSymbolAddr(coff_files[j].entries[i], &new_value.addr); DEBUG_AddLineNumber(coff_files[j].entries[i], linepnt->Linenum, - (unsigned int) deefer->load_addr + (unsigned int) module->load_addr + linepnt->VirtualAddr - new_value.addr.off); } @@ -2006,9 +1955,9 @@ leave: } static int -DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, - char * cv_data, - int size, +DEBUG_SnarfCodeView( DBG_MODULE * module, + char * cv_data, + int size, struct codeview_linetab_hdr * linetab) { struct name_hash * curr_func = NULL; @@ -2025,8 +1974,12 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, struct name_hash * thunk_sym = NULL; ptr.c = cv_data; - nsect = deefer->nsect; - sectp = deefer->sectp; + nsect = MSC_INFO(module)->nsect; + sectp = DBG_alloc(sizeof(*sectp) * nsect); + if (!sectp || + !DEBUG_READ_MEM_VERBOSE(module->load_addr + MSC_INFO(module)->sect_ofs, + sectp, sizeof(*sectp) * nsect)) + return FALSE; /* * Loop over the different types of records and whenever we @@ -2075,7 +2028,7 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, memcpy(symname, sym->data.name, sym->data.namelen); new_value.addr.seg = 0; new_value.type = DEBUG_GetCVType(sym->data.symtype); - new_value.addr.off = (unsigned int) deefer->load_addr + + new_value.addr.off = (unsigned int) module->load_addr + sectp[sym->data.seg - 1].VirtualAddress + sym->data.offset; new_value.cookie = DV_TARGET; @@ -2105,7 +2058,7 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, memcpy(symname, sym->data32.name, sym->data32.namelen); new_value.addr.seg = 0; new_value.type = DEBUG_GetCVType(sym->data32.symtype); - new_value.addr.off = (unsigned int) deefer->load_addr + + new_value.addr.off = (unsigned int) module->load_addr + sectp[sym->data32.seg - 1].VirtualAddress + sym->data32.offset; new_value.cookie = DV_TARGET; @@ -2120,7 +2073,7 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, memcpy(symname, sym->thunk.name, sym->thunk.namelen); new_value.addr.seg = 0; new_value.type = NULL; - new_value.addr.off = (unsigned int) deefer->load_addr + + new_value.addr.off = (unsigned int) module->load_addr + sectp[sym->thunk.segment - 1].VirtualAddress + sym->thunk.offset; new_value.cookie = DV_TARGET; @@ -2136,7 +2089,7 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, memcpy(symname, sym->proc.name, sym->proc.namelen); new_value.addr.seg = 0; new_value.type = DEBUG_GetCVType(sym->proc.proctype); - new_value.addr.off = (unsigned int) deefer->load_addr + + new_value.addr.off = (unsigned int) module->load_addr + sectp[sym->proc.segment - 1].VirtualAddress + sym->proc.offset; new_value.cookie = DV_TARGET; @@ -2147,10 +2100,10 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, */ for(i=0; linetab && linetab[i].linetab != NULL; i++) { - if( ((unsigned int) deefer->load_addr + if( ((unsigned int) module->load_addr + sectp[linetab[i].segno - 1].VirtualAddress + linetab[i].start <= new_value.addr.off) - && ((unsigned int) deefer->load_addr + && ((unsigned int) module->load_addr + sectp[linetab[i].segno - 1].VirtualAddress + linetab[i].end > new_value.addr.off) ) { @@ -2202,7 +2155,7 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, memcpy(symname, sym->proc32.name, sym->proc32.namelen); new_value.addr.seg = 0; new_value.type = DEBUG_GetCVType(sym->proc32.proctype); - new_value.addr.off = (unsigned int) deefer->load_addr + + new_value.addr.off = (unsigned int) module->load_addr + sectp[sym->proc32.segment - 1].VirtualAddress + sym->proc32.offset; new_value.cookie = DV_TARGET; @@ -2213,10 +2166,10 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, */ for(i=0; linetab && linetab[i].linetab != NULL; i++) { - if( ((unsigned int) deefer->load_addr + if( ((unsigned int) module->load_addr + sectp[linetab[i].segno - 1].VirtualAddress + linetab[i].start <= new_value.addr.off) - && ((unsigned int) deefer->load_addr + && ((unsigned int) module->load_addr + sectp[linetab[i].segno - 1].VirtualAddress + linetab[i].end > new_value.addr.off) ) { @@ -2316,6 +2269,7 @@ DEBUG_SnarfCodeView( struct deferred_debug_info * deefer, DBG_free(linetab); } + DBG_free(sectp); return TRUE; } @@ -2593,7 +2547,7 @@ static void pdb_convert_symbols_header( PDB_SYMBOLS *symbols, } } -int DEBUG_ProcessPDBFile( struct deferred_debug_info *deefer, char *full_filename ) +static int DEBUG_ProcessPDBFile( DBG_MODULE* module, char *full_filename ) { char filename[MAX_PATHNAME_LEN]; struct stat statbuf; @@ -2690,7 +2644,7 @@ int DEBUG_ProcessPDBFile( struct deferred_debug_info *deefer, char *full_filenam */ if ( root->TimeDateStamp - != ((struct CodeViewDebug *)deefer->dbg_info)->cv_timestamp ) + != ((struct CodeViewDebug *)MSC_INFO(module)->dbg_info)->cv_timestamp ) { fprintf(stderr, "-Wrong time stamp of .PDB file %s\n", filename); goto leave; @@ -2719,7 +2673,7 @@ int DEBUG_ProcessPDBFile( struct deferred_debug_info *deefer, char *full_filenam modimage = pdb_read_file( image, toc, symbols.gsym_file ); if ( modimage ) { - DEBUG_SnarfCodeView( deefer, modimage, + DEBUG_SnarfCodeView( module, modimage, toc->file[symbols.gsym_file].size, NULL ); pdb_free( modimage ); } @@ -2762,7 +2716,7 @@ int DEBUG_ProcessPDBFile( struct deferred_debug_info *deefer, char *full_filenam linetab = DEBUG_SnarfLinetab( modimage + symbol_size, lineno_size ); if ( symbol_size ) - DEBUG_SnarfCodeView( deefer, modimage + sizeof(DWORD), + DEBUG_SnarfCodeView( module, modimage + sizeof(DWORD), symbol_size - sizeof(DWORD), linetab ); pdb_free( modimage ); @@ -2794,16 +2748,16 @@ int DEBUG_ProcessPDBFile( struct deferred_debug_info *deefer, char *full_filenam /* * Process DBG file which contains debug information. */ -/* static */ +static int -DEBUG_ProcessDBGFile(struct deferred_debug_info * deefer, char * filename) +DEBUG_ProcessDBGFile(DBG_MODULE* module, char * filename) { char * addr = (char *) 0xffffffff; char * codeview; struct CV4_DirHead * codeview_dir; struct CV4_DirEnt * codeview_dent; PIMAGE_DEBUG_DIRECTORY dbghdr; - struct deferred_debug_info deefer2; + DBG_MODULE module2; int fd = -1; int i; int j; @@ -2847,7 +2801,7 @@ DEBUG_ProcessDBGFile(struct deferred_debug_info * deefer, char * filename) pdbg = (PIMAGE_SEPARATE_DEBUG_HEADER) addr; - if( pdbg->TimeDateStamp != deefer->dbgdir->TimeDateStamp ) + if( pdbg->TimeDateStamp != MSC_INFO(module)->dbgdir.TimeDateStamp ) { fprintf(stderr, "Warning - %s has incorrect internal timestamp\n", dbg_file); @@ -2877,12 +2831,12 @@ DEBUG_ProcessDBGFile(struct deferred_debug_info * deefer, char * filename) * Dummy up a deferred debug header to handle the * COFF stuff embedded within the DBG file. */ - memset((char *) &deefer2, 0, sizeof(deefer2)); - deefer2.dbg_info = (addr + dbghdr->PointerToRawData); - deefer2.dbg_size = dbghdr->SizeOfData; - deefer2.load_addr = deefer->load_addr; + memset((char *) &module2, 0, sizeof(module2)); + MSC_INFO(&module2)->dbg_info = (addr + dbghdr->PointerToRawData); + MSC_INFO(&module2)->dbg_size = dbghdr->SizeOfData; + module2.load_addr = module->load_addr; - DEBUG_ProcessCoff(&deefer2); + DEBUG_ProcessCoff(&module2); break; case IMAGE_DEBUG_TYPE_CODEVIEW: /* @@ -2950,7 +2904,7 @@ DEBUG_ProcessDBGFile(struct deferred_debug_info * deefer, char * filename) /* * Now process the CV stuff. */ - DEBUG_SnarfCodeView(deefer, + DEBUG_SnarfCodeView(module, codeview + codeview_dent->offset + sizeof(DWORD), codeview_dent->size - sizeof(DWORD), linetab); @@ -2978,126 +2932,83 @@ leave: } int -DEBUG_ProcessDeferredDebug(void) +DEBUG_ProcessMSCDebugInfo(DBG_MODULE* module) { - struct deferred_debug_info * deefer; struct CodeViewDebug * cvd; struct MiscDebug * misc; char * filename; - int last_proc = -1; - int need_print =0; int sts; - - for(deefer = dbglist; deefer; deefer = deefer->next) - { - if( deefer->status != DF_STATUS_NEW ) - { - continue; - } - - if( last_proc != deefer->dbg_index ) - { - if (!need_print) - { - fprintf(stderr, "DeferredDebug for:"); - need_print=1; - } - fprintf(stderr, " %s",deefer->module_name); - last_proc = deefer->dbg_index; - } - - switch(deefer->dbgdir->Type) - { - case IMAGE_DEBUG_TYPE_COFF: - /* - * Standard COFF debug information that VC++ adds when you - * use /debugtype:both with the linker. - */ + + switch (MSC_INFO(module)->dbgdir.Type) + { + case IMAGE_DEBUG_TYPE_COFF: + /* + * Standard COFF debug information that VC++ adds when you + * use /debugtype:both with the linker. + */ #if 0 - fprintf(stderr, "Processing COFF symbols...\n"); + fprintf(stderr, "Processing COFF symbols...\n"); #endif - sts = DEBUG_ProcessCoff(deefer); - break; - case IMAGE_DEBUG_TYPE_CODEVIEW: - /* - * This is a pointer to a PDB file of some sort. - */ - cvd = (struct CodeViewDebug *) deefer->dbg_info; - - if( strcmp(cvd->cv_nbtype, "NB10") != 0 ) - { + sts = DEBUG_ProcessCoff(module); + break; + case IMAGE_DEBUG_TYPE_CODEVIEW: + /* + * This is a pointer to a PDB file of some sort. + */ + cvd = (struct CodeViewDebug *) MSC_INFO(module)->dbg_info; + + if( strcmp(cvd->cv_nbtype, "NB10") != 0 ) + { /* * Whatever this is, we don't know how to deal with * it yet. */ sts = FALSE; break; - } - sts = DEBUG_ProcessPDBFile(deefer, cvd->cv_name); + } + sts = DEBUG_ProcessPDBFile(module, cvd->cv_name); #if 0 - fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name); + fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name); #endif - break; - case IMAGE_DEBUG_TYPE_MISC: - /* - * A pointer to a .DBG file of some sort. These files - * can contain either CV4 or COFF information. Open - * the file, and try to do the right thing with it. - */ - misc = (struct MiscDebug *) deefer->dbg_info; - - filename = strrchr((char *) &misc->Data, '.'); - - /* - * Ignore the file if it doesn't have a .DBG extension. - */ - if( (filename == NULL) - || ( (strcmp(filename, ".dbg") != 0) - && (strcmp(filename, ".DBG") != 0)) ) - { - sts = FALSE; - break; - } - - filename = (char *) &misc->Data; - - /* - * Do the dirty deed... - */ - sts = DEBUG_ProcessDBGFile(deefer, filename); - - break; - default: - /* - * We should never get here... - */ - sts = FALSE; - break; - } - deefer->status = (sts) ? DF_STATUS_LOADED : DF_STATUS_ERROR; - - } - if(need_print) - fprintf(stderr, "\n"); - return TRUE; - + break; + case IMAGE_DEBUG_TYPE_MISC: + /* + * A pointer to a .DBG file of some sort. These files + * can contain either CV4 or COFF information. Open + * the file, and try to do the right thing with it. + */ + misc = (struct MiscDebug *) MSC_INFO(module)->dbg_info; + + filename = strrchr((char *) &misc->Data, '.'); + + /* + * Ignore the file if it doesn't have a .DBG extension. + */ + if( (filename == NULL) + || ( (strcmp(filename, ".dbg") != 0) + && (strcmp(filename, ".DBG") != 0)) ) + { + sts = FALSE; + break; + } + + filename = (char *) &misc->Data; + + /* + * Do the dirty deed... + */ + sts = DEBUG_ProcessDBGFile(module, filename); + + break; + default: + /* + * We should never get here... + */ + sts = FALSE; + break; + } + return sts; } -/*********************************************************************** - * DEBUG_InfoShare - * - * Display shared libarary information. - */ -void DEBUG_InfoShare(void) -{ - struct deferred_debug_info * deefer; - - fprintf(stderr,"Address\t\tModule\tName\n"); - for(deefer = dbglist; deefer; deefer = deefer->next) - { - fprintf(stderr,"0x%8.8x\t(%s)\t%s\n", (unsigned int) deefer->load_addr, - deefer->module ? "Win32" : "ELF", deefer->module_name); - } -} diff --git a/debugger/stabs.c b/debugger/stabs.c index b240a01ee06..f7b8dd6a940 100644 --- a/debugger/stabs.c +++ b/debugger/stabs.c @@ -1237,9 +1237,9 @@ DEBUG_ProcessElfObject(const char * filename, unsigned int load_offset) ehptr = (Elf32_Ehdr *) addr; if( load_offset == 0 ) - DEBUG_RegisterELFDebugInfo(ehptr->e_entry, statbuf.st_size, filename); + DEBUG_RegisterELFModule(ehptr->e_entry, filename); else - DEBUG_RegisterELFDebugInfo(load_offset, statbuf.st_size, filename); + DEBUG_RegisterELFModule(load_offset, filename); spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff); nsect = ehptr->e_shnum; diff --git a/debugger/winedbg.c b/debugger/winedbg.c index f98a80c16d9..be37c110c32 100644 --- a/debugger/winedbg.c +++ b/debugger/winedbg.c @@ -9,7 +9,12 @@ #include #include #include "debugger.h" -#include "winbase.h" + +#include "thread.h" +#include "process.h" +#include "wingdi.h" +#include "winuser.h" + #include "winreg.h" #include "debugtools.h" #include "options.h" @@ -20,29 +25,56 @@ HANDLE dbg_heap = 0; DEFAULT_DEBUG_CHANNEL(winedbg); -WINE_DBG_PROCESS* DEBUG_CurrProcess = NULL; -WINE_DBG_THREAD* DEBUG_CurrThread = NULL; -CONTEXT DEBUG_context; +DBG_PROCESS* DEBUG_CurrProcess = NULL; +DBG_THREAD* DEBUG_CurrThread = NULL; +CONTEXT DEBUG_context; -static WINE_DBG_PROCESS* proc = NULL; +static DBG_PROCESS* proc = NULL; +static BOOL bBreakAllThreads = FALSE; + +static BOOL DEBUG_Init(void) +{ + HKEY hkey; + DWORD type; + DWORD val; + DWORD count = sizeof(val); + + if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey)) { + if (!RegQueryValueExA(hkey, "BreakAllThreadsStartup", 0, &type, (LPSTR)&val, &count)) { + bBreakAllThreads = val; + } + RegCloseKey(hkey); + } + return TRUE; +} + +static WINE_EXCEPTION_FILTER(wine_dbg) +{ + DEBUG_ExternalDebugger(); + fprintf(stderr, "\nwine_dbg: Exception %lx\n", GetExceptionCode()); + return EXCEPTION_EXECUTE_HANDLER; +} -static WINE_DBG_PROCESS* DEBUG_GetProcess(DWORD pid) +static DBG_PROCESS* DEBUG_GetProcess(DWORD pid) { - WINE_DBG_PROCESS* p; + DBG_PROCESS* p; for (p = proc; p; p = p->next) if (p->pid == pid) break; return p; } -static WINE_DBG_PROCESS* DEBUG_AddProcess(DWORD pid, HANDLE h) +static DBG_PROCESS* DEBUG_AddProcess(DWORD pid, HANDLE h) { - WINE_DBG_PROCESS* p = DBG_alloc(sizeof(WINE_DBG_PROCESS)); + DBG_PROCESS* p = DBG_alloc(sizeof(DBG_PROCESS)); if (!p) return NULL; p->handle = h; p->pid = pid; p->threads = NULL; + p->num_threads = 0; + p->modules = NULL; + p->next_index = 0; p->next = proc; p->prev = NULL; @@ -51,9 +83,9 @@ static WINE_DBG_PROCESS* DEBUG_AddProcess(DWORD pid, HANDLE h) return p; } -static void DEBUG_DelThread(WINE_DBG_THREAD* p); +static void DEBUG_DelThread(DBG_THREAD* p); -static void DEBUG_DelProcess(WINE_DBG_PROCESS* p) +static void DEBUG_DelProcess(DBG_PROCESS* p) { if (p->threads != NULL) { ERR("Shouldn't happen\n"); @@ -138,19 +170,19 @@ static BOOL DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LP return FALSE; } -static WINE_DBG_THREAD* DEBUG_GetThread(WINE_DBG_PROCESS* p, DWORD tid) +static DBG_THREAD* DEBUG_GetThread(DBG_PROCESS* p, DWORD tid) { - WINE_DBG_THREAD* t; + DBG_THREAD* t; for (t = p->threads; t; t = t->next) if (t->tid == tid) break; return t; } -static WINE_DBG_THREAD* DEBUG_AddThread(WINE_DBG_PROCESS* p, DWORD tid, - HANDLE h, LPVOID start, LPVOID teb) +static DBG_THREAD* DEBUG_AddThread(DBG_PROCESS* p, DWORD tid, + HANDLE h, LPVOID start, LPVOID teb) { - WINE_DBG_THREAD* t = DBG_alloc(sizeof(WINE_DBG_THREAD)); + DBG_THREAD* t = DBG_alloc(sizeof(DBG_THREAD)); if (!t) return NULL; @@ -162,7 +194,8 @@ static WINE_DBG_THREAD* DEBUG_AddThread(WINE_DBG_PROCESS* p, DWORD tid, t->wait_for_first_exception = 0; t->dbg_exec_mode = EXEC_CONT; t->dbg_exec_count = 0; - + + p->num_threads++; t->next = p->threads; t->prev = NULL; if (p->threads) p->threads->prev = t; @@ -176,25 +209,28 @@ static void DEBUG_InitCurrThread(void) if (!Options.debug) return; if (DEBUG_CurrThread->start) { - DBG_VALUE value; - - DEBUG_SetBreakpoints(FALSE); - value.type = NULL; - value.cookie = DV_TARGET; - value.addr.seg = 0; - value.addr.off = (DWORD)DEBUG_CurrThread->start; - DEBUG_AddBreakpoint(&value); - DEBUG_SetBreakpoints(TRUE); + if (DEBUG_CurrThread->process->num_threads == 1 || bBreakAllThreads) { + DBG_VALUE value; + + DEBUG_SetBreakpoints(FALSE); + value.type = NULL; + value.cookie = DV_TARGET; + value.addr.seg = 0; + value.addr.off = (DWORD)DEBUG_CurrThread->start; + DEBUG_AddBreakpoint(&value); + DEBUG_SetBreakpoints(TRUE); + } } else { DEBUG_CurrThread->wait_for_first_exception = 1; } } -static void DEBUG_DelThread(WINE_DBG_THREAD* t) +static void DEBUG_DelThread(DBG_THREAD* t) { if (t->prev) t->prev->next = t->next; if (t->next) t->next->prev = t->prev; if (t == t->process->threads) t->process->threads = t->next; + t->process->num_threads--; DBG_free(t); } @@ -281,42 +317,41 @@ static BOOL DEBUG_HandleException( EXCEPTION_RECORD *rec, BOOL first_chance, BOO return ret; } -static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) +static DWORD DEBUG_HandleDebugEvent(DEBUG_EVENT* de) { - DEBUG_EVENT de; char buffer[256]; DWORD cont; - - while (WaitForDebugEvent(&de, INFINITE)) { + + __TRY { cont = 0L; - - if ((DEBUG_CurrProcess = DEBUG_GetProcess(de.dwProcessId)) != NULL) - DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de.dwThreadId); + + if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) + DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId); else DEBUG_CurrThread = NULL; - - switch (de.dwDebugEventCode) { + + switch (de->dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: if (!DEBUG_CurrThread) break; - + TRACE("%08lx:%08lx: exception code=%08lx %d\n", - de.dwProcessId, de.dwThreadId, - de.u.Exception.ExceptionRecord.ExceptionCode, + de->dwProcessId, de->dwThreadId, + de->u.Exception.ExceptionRecord.ExceptionCode, DEBUG_CurrThread->wait_for_first_exception); - + DEBUG_context.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS|CONTEXT_DEBUG_REGISTERS; if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) { WARN("Can't get thread's context\n"); break; } - - TRACE("%p:%p\n", de.u.Exception.ExceptionRecord.ExceptionAddress, + + TRACE("%p:%p\n", de->u.Exception.ExceptionRecord.ExceptionAddress, (void*)DEBUG_context.Eip); - - cont = DEBUG_HandleException(&de.u.Exception.ExceptionRecord, - de.u.Exception.dwFirstChance, + + cont = DEBUG_HandleException(&de->u.Exception.ExceptionRecord, + de->u.Exception.dwFirstChance, DEBUG_CurrThread->wait_for_first_exception); - + if (DEBUG_CurrThread->wait_for_first_exception) { DEBUG_CurrThread->wait_for_first_exception = 0; #ifdef __i386__ @@ -327,23 +362,23 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) break; case CREATE_THREAD_DEBUG_EVENT: - TRACE("%08lx:%08lx: create thread D @%p\n", de.dwProcessId, de.dwThreadId, - de.u.CreateThread.lpStartAddress); + TRACE("%08lx:%08lx: create thread D @%p\n", de->dwProcessId, de->dwThreadId, + de->u.CreateThread.lpStartAddress); if (DEBUG_CurrProcess == NULL) { ERR("Unknown process\n"); break; } - if (DEBUG_GetThread(DEBUG_CurrProcess, de.dwThreadId) != NULL) { + if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL) { TRACE("Thread already listed, skipping\n"); break; } - + DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess, - de.dwThreadId, - de.u.CreateThread.hThread, - de.u.CreateThread.lpStartAddress, - de.u.CreateThread.lpThreadLocalBase); + de->dwThreadId, + de->u.CreateThread.hThread, + de->u.CreateThread.lpStartAddress, + de->u.CreateThread.lpThreadLocalBase); if (!DEBUG_CurrThread) { ERR("Couldn't create thread\n"); break; @@ -353,34 +388,34 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) case CREATE_PROCESS_DEBUG_EVENT: DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), - de.u.CreateProcessInfo.hProcess, - de.u.LoadDll.lpImageName); + de->u.CreateProcessInfo.hProcess, + de->u.LoadDll.lpImageName); - /* FIXME unicode ? de.u.CreateProcessInfo.fUnicode */ + /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */ TRACE("%08lx:%08lx: create process %s @%p\n", - de.dwProcessId, de.dwThreadId, + de->dwProcessId, de->dwThreadId, buffer, - de.u.CreateProcessInfo.lpStartAddress); + de->u.CreateProcessInfo.lpStartAddress); - if (DEBUG_GetProcess(de.dwProcessId) != NULL) { + if (DEBUG_GetProcess(de->dwProcessId) != NULL) { TRACE("Skipping already defined process\n"); break; } - DEBUG_CurrProcess = DEBUG_AddProcess(de.dwProcessId, - de.u.CreateProcessInfo.hProcess); + DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId, + de->u.CreateProcessInfo.hProcess); if (DEBUG_CurrProcess == NULL) { ERR("Unknown process\n"); break; } - TRACE("%08lx:%08lx: create thread I @%p\n", de.dwProcessId, de.dwThreadId, - de.u.CreateProcessInfo.lpStartAddress); + TRACE("%08lx:%08lx: create thread I @%p\n", de->dwProcessId, de->dwThreadId, + de->u.CreateProcessInfo.lpStartAddress); DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess, - de.dwThreadId, - de.u.CreateProcessInfo.hThread, - de.u.CreateProcessInfo.lpStartAddress, - de.u.CreateProcessInfo.lpThreadLocalBase); + de->dwThreadId, + de->u.CreateProcessInfo.hThread, + de->u.CreateProcessInfo.lpStartAddress, + de->u.CreateProcessInfo.lpThreadLocalBase); if (!DEBUG_CurrThread) { ERR("Couldn't create thread\n"); break; @@ -390,15 +425,15 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) DEBUG_InitCurrThread(); #ifdef _WE_SUPPORT_THE_STAB_TYPES_USED_BY_MINGW_TOO /* so far, process name is not set */ - DEBUG_RegisterDebugInfo((DWORD)de.u.CreateProcessInfo.lpBaseOfImage, + DEBUG_RegisterDebugInfo((DWORD)de->u.CreateProcessInfo.lpBaseOfImage, "wine-exec"); #endif break; case EXIT_THREAD_DEBUG_EVENT: TRACE("%08lx:%08lx: exit thread (%ld)\n", - de.dwProcessId, de.dwThreadId, de.u.ExitThread.dwExitCode); - + de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode); + if (DEBUG_CurrThread == NULL) { ERR("Unknown thread\n"); break; @@ -409,8 +444,8 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) case EXIT_PROCESS_DEBUG_EVENT: TRACE("%08lx:%08lx: exit process (%ld)\n", - de.dwProcessId, de.dwThreadId, de.u.ExitProcess.dwExitCode); - + de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode); + if (DEBUG_CurrProcess == NULL) { ERR("Unknown process\n"); break; @@ -428,16 +463,18 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) } DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), DEBUG_CurrThread->process->handle, - de.u.LoadDll.lpImageName); + de->u.LoadDll.lpImageName); - /* FIXME unicode: de.u.LoadDll.fUnicode */ - TRACE("%08lx:%08lx: loads DLL %s @%p\n", de.dwProcessId, de.dwThreadId, - buffer, de.u.LoadDll.lpBaseOfDll); + /* FIXME unicode: de->u.LoadDll.fUnicode */ + TRACE("%08lx:%08lx: loads DLL %s @%p\n", de->dwProcessId, de->dwThreadId, + buffer, de->u.LoadDll.lpBaseOfDll); + CharUpperA(buffer); + DEBUG_LoadModule32( buffer, (DWORD)de->u.LoadDll.lpBaseOfDll); break; case UNLOAD_DLL_DEBUG_EVENT: - TRACE("%08lx:%08lx: unload DLL @%p\n", de.dwProcessId, de.dwThreadId, - de.u.UnloadDll.lpBaseOfDll); + TRACE("%08lx:%08lx: unload DLL @%p\n", de->dwProcessId, de->dwThreadId, + de->u.UnloadDll.lpBaseOfDll); break; case OUTPUT_DEBUG_STRING_EVENT: @@ -445,27 +482,45 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) ERR("Unknown thread\n"); break; } - + DEBUG_ProcessGetString(buffer, sizeof(buffer), DEBUG_CurrThread->process->handle, - de.u.DebugString.lpDebugStringData); + de->u.DebugString.lpDebugStringData); - /* fixme unicode de.u.DebugString.fUnicode ? */ + /* fixme unicode de->u.DebugString.fUnicode ? */ TRACE("%08lx:%08lx: output debug string (%s)\n", - de.dwProcessId, de.dwThreadId, + de->dwProcessId, de->dwThreadId, buffer); break; case RIP_EVENT: TRACE("%08lx:%08lx: rip error=%ld type=%ld\n", - de.dwProcessId, de.dwThreadId, de.u.RipInfo.dwError, - de.u.RipInfo.dwType); + de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError, + de->u.RipInfo.dwType); break; default: TRACE("%08lx:%08lx: unknown event (%ld)\n", - de.dwProcessId, de.dwThreadId, de.dwDebugEventCode); + de->dwProcessId, de->dwThreadId, de->dwDebugEventCode); } + + } __EXCEPT(wine_dbg) { + cont = 0; + } + __ENDTRY; + + return cont; +} + +static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) +{ + DEBUG_EVENT de; + DWORD cont; + + DEBUG_Init(); + + while (WaitForDebugEvent(&de, INFINITE)) { + cont = DEBUG_HandleDebugEvent(&de); ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont); } @@ -474,11 +529,6 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) return 0L; } -#include "thread.h" -#include "process.h" -#include "wingdi.h" -#include "winuser.h" - static DWORD CALLBACK DEBUG_StarterFromPID(LPVOID pid) { TRACE("WineDbg started on pid %ld\n", (DWORD)pid); -- 2.11.4.GIT