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
This commit is contained in:
parent
323af8dbba
commit
ac11a68f3e
|
@ -15,7 +15,8 @@ C_SRCS = \
|
|||
hash.c \
|
||||
info.c \
|
||||
memory.c \
|
||||
msc.c \
|
||||
module.c \
|
||||
msc.c \
|
||||
registers.c \
|
||||
source.c \
|
||||
stabs.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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 @@ 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;
|
||||
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 @@ 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);
|
||||
|
|
257
debugger/hash.c
257
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 @@ 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 )
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
465
debugger/msc.c
465
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
|
||||
{
|
||||
|
@ -689,30 +692,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);
|
||||
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 @@ 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);
|
||||
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 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ 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 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 @@ 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);
|
||||
|
|
Loading…
Reference in New Issue