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
diff --git a/debugger/Makefile.in b/debugger/Makefile.in
index a5524d7..54328b4 100644
--- a/debugger/Makefile.in
+++ b/debugger/Makefile.in
@@ -15,7 +15,8 @@
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 2199505..f38cb2f 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -208,7 +208,6 @@
}
*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 @@
break;
}
}
- fprintf(stderr, "Setting DR7 %08lx\n", DEBUG_context.Dr7);
}
/***********************************************************************
diff --git a/debugger/dbg.y b/debugger/dbg.y
index f4c3899..1ed882b 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -398,8 +398,9 @@
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 @@
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 104bfde..d95ce57 100644
--- a/debugger/debugger.h
+++ b/debugger/debugger.h
@@ -11,6 +11,7 @@
#include <assert.h>
#include "windef.h"
#include "winbase.h"
+#include "wine/exception.h"
#ifdef __i386__
#define STEP_FLAG 0x00000100 /* single step flag */
@@ -135,8 +136,8 @@
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 @@
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;
+ 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 WINE_DBG_PROCESS* DEBUG_CurrProcess;
-extern WINE_DBG_THREAD* DEBUG_CurrThread;
-extern CONTEXT DEBUG_context;
+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 @@
#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 @@
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 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_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_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 cd6cd19..1eaf5ce 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -11,11 +11,7 @@
#include <string.h>
#include <limits.h>
#include <sys/types.h>
-#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 @@
}
-/***********************************************************************
- * 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 7f1f64f..19ca90c 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -344,16 +344,6 @@
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 0000000..f73dfb2
--- /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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#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 8842f34..24bc680 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 @@
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 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 @@
* 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 @@
* 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 @@
* 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);
+ if (!(module->extra_info = DBG_alloc(sizeof(MSC_DBG_INFO))))
+ break;
- deefer->sectp = PE_SECTIONS(hModule);
- deefer->nsect = PE_HEADER(hModule)->FileHeader.NumberOfSections;
-
- dbglist = deefer;
+ 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;i<nth->FileHeader.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 @@
/* 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);
+ return TRUE;
}
/*
- * 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);
-}
-
-
-
-/*
* 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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
{
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_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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
*/
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 @@
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 @@
*/
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 @@
DBG_free(linetab);
}
+ DBG_free(sectp);
return TRUE;
}
@@ -2593,7 +2547,7 @@
}
}
-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 @@
*/
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 @@
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 @@
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 @@
/*
* 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 @@
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 @@
* 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 @@
/*
* 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 @@
}
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 b240a01..f7b8dd6 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -1237,9 +1237,9 @@
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 f98a80c..be37c11 100644
--- a/debugger/winedbg.c
+++ b/debugger/winedbg.c
@@ -9,7 +9,12 @@
#include <stdio.h>
#include <sys/stat.h>
#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 @@
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 WINE_DBG_PROCESS* DEBUG_GetProcess(DWORD pid)
+static BOOL DEBUG_Init(void)
{
- WINE_DBG_PROCESS* p;
+ 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 DBG_PROCESS* DEBUG_GetProcess(DWORD pid)
+{
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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);