Improved internal module handling (module now have a size, map of
loaded module is clearer, better error reporting, seperated module loading code from symbol extraction).
This commit is contained in:
parent
77b2185e1c
commit
e939206f90
|
@ -26,7 +26,8 @@
|
||||||
#define SYM_TRAMPOLINE 0x10
|
#define SYM_TRAMPOLINE 0x10
|
||||||
#define SYM_STEP_THROUGH 0x20
|
#define SYM_STEP_THROUGH 0x20
|
||||||
|
|
||||||
enum debug_type {DT_BASIC, DT_CONST, DT_POINTER, DT_ARRAY, DT_STRUCT, DT_ENUM, DT_TYPEDEF, DT_FUNC, DT_BITFIELD};
|
enum debug_type {DT_BASIC, DT_CONST, DT_POINTER, DT_ARRAY, DT_STRUCT, DT_ENUM,
|
||||||
|
DT_TYPEDEF, DT_FUNC, DT_BITFIELD};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -170,7 +171,8 @@ typedef struct tagDBG_PROCESS {
|
||||||
DBG_THREAD* threads;
|
DBG_THREAD* threads;
|
||||||
int num_threads;
|
int num_threads;
|
||||||
unsigned continue_on_first_exception;
|
unsigned continue_on_first_exception;
|
||||||
struct tagDBG_MODULE* modules;
|
struct tagDBG_MODULE** modules;
|
||||||
|
int num_modules;
|
||||||
unsigned long dbg_hdr_addr;
|
unsigned long dbg_hdr_addr;
|
||||||
/*
|
/*
|
||||||
* This is an index we use to keep track of the debug information
|
* This is an index we use to keep track of the debug information
|
||||||
|
@ -201,28 +203,22 @@ extern CONTEXT DEBUG_context;
|
||||||
#define DEBUG_WRITE_MEM_VERBOSE(addr, buf, len) \
|
#define DEBUG_WRITE_MEM_VERBOSE(addr, buf, len) \
|
||||||
(DEBUG_WRITE_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0))
|
(DEBUG_WRITE_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0))
|
||||||
|
|
||||||
|
enum DbgInfoLoad {DIL_DEFERRED, DIL_LOADED, DIL_NOINFO, DIL_ERROR};
|
||||||
|
enum DbgModuleType {DMT_UNKNOWN, DMT_ELF, DMT_NE, DMT_PE};
|
||||||
|
|
||||||
typedef struct tagDBG_MODULE {
|
typedef struct tagDBG_MODULE {
|
||||||
struct tagDBG_MODULE* next;
|
|
||||||
void* load_addr;
|
void* load_addr;
|
||||||
|
unsigned long size;
|
||||||
char* module_name;
|
char* module_name;
|
||||||
char status;
|
enum DbgInfoLoad dil;
|
||||||
char type;
|
enum DbgModuleType type;
|
||||||
|
unsigned char main;
|
||||||
short int dbg_index;
|
short int dbg_index;
|
||||||
HMODULE handle;
|
HMODULE handle;
|
||||||
void* extra_info;
|
struct tagMSC_DBG_INFO* msc_info;
|
||||||
|
struct tagELF_DBG_INFO* elf_info;
|
||||||
} DBG_MODULE;
|
} 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
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DWORD val;
|
DWORD val;
|
||||||
const char* name;
|
const char* name;
|
||||||
|
@ -246,7 +242,8 @@ extern void DEBUG_DelBreakpoint( int num );
|
||||||
extern void DEBUG_EnableBreakpoint( int num, BOOL enable );
|
extern void DEBUG_EnableBreakpoint( int num, BOOL enable );
|
||||||
extern void DEBUG_InfoBreakpoints(void);
|
extern void DEBUG_InfoBreakpoints(void);
|
||||||
extern BOOL DEBUG_HandleTrap(void);
|
extern BOOL DEBUG_HandleTrap(void);
|
||||||
extern BOOL DEBUG_ShouldContinue( DBG_ADDR *addr, DWORD code, enum exec_mode mode, int * count );
|
extern BOOL DEBUG_ShouldContinue( DBG_ADDR *addr, DWORD code, enum exec_mode mode,
|
||||||
|
int * count );
|
||||||
extern void DEBUG_SuspendExecution( void );
|
extern void DEBUG_SuspendExecution( void );
|
||||||
extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count );
|
extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count );
|
||||||
extern BOOL DEBUG_IsFctReturn(void);
|
extern BOOL DEBUG_IsFctReturn(void);
|
||||||
|
@ -322,7 +319,7 @@ extern int DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len);
|
||||||
extern int DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int len);
|
extern int DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int len);
|
||||||
extern int DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr);
|
extern int DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr);
|
||||||
extern int DEBUG_cmp_sym(const void * p1, const void * p2);
|
extern int DEBUG_cmp_sym(const void * p1, const void * p2);
|
||||||
extern BOOL DEBUG_GetLineNumberAddr( struct name_hash *, const int lineno,
|
extern BOOL DEBUG_GetLineNumberAddr( const struct name_hash *, const int lineno,
|
||||||
DBG_ADDR *addr, int bp_flag );
|
DBG_ADDR *addr, int bp_flag );
|
||||||
|
|
||||||
extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym,
|
extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym,
|
||||||
|
@ -331,7 +328,8 @@ extern BOOL DEBUG_Normalize(struct name_hash * nh );
|
||||||
|
|
||||||
/* debugger/info.c */
|
/* debugger/info.c */
|
||||||
extern void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format );
|
extern void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format );
|
||||||
extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr, enum dbg_mode mode, int flag );
|
extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr,
|
||||||
|
enum dbg_mode mode, int flag );
|
||||||
extern void DEBUG_Help(void);
|
extern void DEBUG_Help(void);
|
||||||
extern void DEBUG_HelpInfo(void);
|
extern void DEBUG_HelpInfo(void);
|
||||||
extern struct symbol_info DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr,
|
extern struct symbol_info DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr,
|
||||||
|
@ -370,18 +368,27 @@ extern int DEBUG_IsSelectorSystem( WORD sel );
|
||||||
/* debugger/module.c */
|
/* debugger/module.c */
|
||||||
extern int DEBUG_LoadEntryPoints( const char * prefix );
|
extern int DEBUG_LoadEntryPoints( const char * prefix );
|
||||||
extern void DEBUG_LoadModule32( const char* name, HANDLE hFile, DWORD base );
|
extern void DEBUG_LoadModule32( const char* name, HANDLE hFile, DWORD base );
|
||||||
extern DBG_MODULE* DEBUG_AddModule(const char* name, int type,
|
extern DBG_MODULE* DEBUG_AddModule(const char* name, enum DbgModuleType type,
|
||||||
void* mod_addr, HMODULE hmod);
|
void* mod_addr, u_long size, HMODULE hmod);
|
||||||
extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type);
|
extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, enum DbgModuleType type);
|
||||||
extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type);
|
extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, enum DbgModuleType type);
|
||||||
extern DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process);
|
extern DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process);
|
||||||
extern DBG_MODULE* DEBUG_RegisterPEModule(HMODULE, u_long load_addr, const char* name);
|
extern DBG_MODULE* DEBUG_RegisterPEModule(HMODULE, u_long load_addr, u_long size,
|
||||||
extern DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name);
|
const char* name);
|
||||||
|
extern DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, u_long size,
|
||||||
|
const char* name);
|
||||||
|
extern enum DbgInfoLoad DEBUG_RegisterPEDebugInfo(DBG_MODULE* wmod, HANDLE hFile,
|
||||||
|
void* _nth, unsigned long nth_ofs);
|
||||||
|
extern void DEBUG_ReportDIL(enum DbgInfoLoad dil, const char* pfx,
|
||||||
|
const char* filename, DWORD load_addr);
|
||||||
extern void DEBUG_InfoShare(void);
|
extern void DEBUG_InfoShare(void);
|
||||||
|
|
||||||
/* debugger/msc.c */
|
/* debugger/msc.c */
|
||||||
extern int DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, HANDLE hFile, void* nth, unsigned long nth_ofs);
|
extern enum DbgInfoLoad DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, HANDLE hFile,
|
||||||
extern int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, HANDLE hFile, void* nth, unsigned long nth_ofs);
|
void* nth, unsigned long nth_ofs);
|
||||||
|
extern enum DbgInfoLoad DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module,
|
||||||
|
HANDLE hFile, void* nth,
|
||||||
|
unsigned long nth_ofs);
|
||||||
extern void DEBUG_InitCVDataTypes(void);
|
extern void DEBUG_InitCVDataTypes(void);
|
||||||
|
|
||||||
/* debugger/registers.c */
|
/* debugger/registers.c */
|
||||||
|
@ -407,16 +414,18 @@ extern int DEBUG_GetCurrentFrame(struct name_hash ** name,
|
||||||
unsigned int * ebp);
|
unsigned int * ebp);
|
||||||
|
|
||||||
/* debugger/stabs.c */
|
/* debugger/stabs.c */
|
||||||
extern int DEBUG_ReadExecutableDbgInfo(const char* exe_name);
|
extern enum DbgInfoLoad DEBUG_ReadExecutableDbgInfo(const char* exe_name);
|
||||||
extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff,
|
extern enum DbgInfoLoad DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
||||||
int stablen, unsigned int strtaboff, int strtablen);
|
unsigned int staboff, int stablen,
|
||||||
|
unsigned int strtaboff, int strtablen);
|
||||||
|
|
||||||
/* debugger/types.c */
|
/* debugger/types.c */
|
||||||
extern int DEBUG_nchar;
|
extern int DEBUG_nchar;
|
||||||
extern void DEBUG_InitTypes(void);
|
extern void DEBUG_InitTypes(void);
|
||||||
extern struct datatype * DEBUG_NewDataType(enum debug_type xtype,
|
extern struct datatype * DEBUG_NewDataType(enum debug_type xtype,
|
||||||
const char * typename);
|
const char * typename);
|
||||||
extern unsigned int DEBUG_TypeDerefPointer(const DBG_VALUE *value, struct datatype ** newtype);
|
extern unsigned int DEBUG_TypeDerefPointer(const DBG_VALUE *value,
|
||||||
|
struct datatype ** newtype);
|
||||||
extern int DEBUG_AddStructElement(struct datatype * dt,
|
extern int DEBUG_AddStructElement(struct datatype * dt,
|
||||||
char * name, struct datatype * type,
|
char * name, struct datatype * type,
|
||||||
int offset, int size);
|
int offset, int size);
|
||||||
|
@ -429,7 +438,8 @@ extern unsigned int DEBUG_FindStructElement(DBG_VALUE * addr,
|
||||||
const char * ele_name, int * tmpbuf);
|
const char * ele_name, int * tmpbuf);
|
||||||
extern struct datatype * DEBUG_GetPointerType(struct datatype * dt);
|
extern struct datatype * DEBUG_GetPointerType(struct datatype * dt);
|
||||||
extern int DEBUG_GetObjectSize(struct datatype * dt);
|
extern int DEBUG_GetObjectSize(struct datatype * dt);
|
||||||
extern unsigned int DEBUG_ArrayIndex(const DBG_VALUE * addr, DBG_VALUE * result, int index);
|
extern unsigned int DEBUG_ArrayIndex(const DBG_VALUE * addr, DBG_VALUE * result,
|
||||||
|
int index);
|
||||||
extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype);
|
extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype);
|
||||||
extern long long int DEBUG_GetExprValue(const DBG_VALUE * addr, char ** format);
|
extern long long int DEBUG_GetExprValue(const DBG_VALUE * addr, char ** format);
|
||||||
extern int DEBUG_SetBitfieldParams(struct datatype * dt, int offset,
|
extern int DEBUG_SetBitfieldParams(struct datatype * dt, int offset,
|
||||||
|
|
|
@ -203,7 +203,6 @@ DEBUG_AddSymbol( const char * name, const DBG_VALUE *value, const char * source,
|
||||||
name, nh->value.addr.seg, nh->value.addr.off, value->addr.seg, value->addr.off);
|
name, nh->value.addr.seg, nh->value.addr.off, value->addr.seg, value->addr.off);
|
||||||
#endif
|
#endif
|
||||||
nh->value.addr = value->addr;
|
nh->value.addr = value->addr;
|
||||||
|
|
||||||
if( nh->value.type == NULL && value->type != NULL )
|
if( nh->value.type == NULL && value->type != NULL )
|
||||||
{
|
{
|
||||||
nh->value.type = value->type;
|
nh->value.type = value->type;
|
||||||
|
@ -345,7 +344,6 @@ BOOL DEBUG_Normalize(struct name_hash * nh )
|
||||||
BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
|
BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
|
||||||
DBG_VALUE *value, int bp_flag )
|
DBG_VALUE *value, int bp_flag )
|
||||||
{
|
{
|
||||||
char buffer[256];
|
|
||||||
struct name_hash *nh;
|
struct name_hash *nh;
|
||||||
|
|
||||||
for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
|
for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
|
||||||
|
@ -360,6 +358,9 @@ BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
|
||||||
|
|
||||||
if (!nh && (name[0] != '_'))
|
if (!nh && (name[0] != '_'))
|
||||||
{
|
{
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
assert(strlen(name) < sizeof(buffer) - 2); /* one for '_', one for '\0' */
|
||||||
buffer[0] = '_';
|
buffer[0] = '_';
|
||||||
strcpy(buffer+1, name);
|
strcpy(buffer+1, name);
|
||||||
for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
|
for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
|
||||||
|
@ -393,7 +394,7 @@ BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
|
||||||
*
|
*
|
||||||
* Get the address of a named symbol.
|
* Get the address of a named symbol.
|
||||||
*/
|
*/
|
||||||
BOOL DEBUG_GetLineNumberAddr( struct name_hash * nh, const int lineno,
|
BOOL DEBUG_GetLineNumberAddr( const struct name_hash * nh, const int lineno,
|
||||||
DBG_ADDR *addr, int bp_flag )
|
DBG_ADDR *addr, int bp_flag )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "neexe.h"
|
|
||||||
#include "file.h"
|
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
#include "toolhelp.h"
|
#include "toolhelp.h"
|
||||||
#include "wingdi.h"
|
#include "wingdi.h"
|
||||||
|
@ -20,8 +18,8 @@
|
||||||
* Creates and links a new module to the current process
|
* Creates and links a new module to the current process
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_AddModule(const char* name, int type,
|
DBG_MODULE* DEBUG_AddModule(const char* name, enum DbgModuleType type,
|
||||||
void* mod_addr, HMODULE hmodule)
|
void* mod_addr, u_long size, HMODULE hmodule)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
DBG_MODULE* wmod;
|
||||||
|
|
||||||
|
@ -30,14 +28,18 @@ DBG_MODULE* DEBUG_AddModule(const char* name, int type,
|
||||||
|
|
||||||
memset(wmod, 0, sizeof(*wmod));
|
memset(wmod, 0, sizeof(*wmod));
|
||||||
|
|
||||||
wmod->next = DEBUG_CurrProcess->modules;
|
wmod->dil = DIL_DEFERRED;
|
||||||
wmod->status = DM_STATUS_NEW;
|
wmod->main = (DEBUG_CurrProcess->num_modules == 0);
|
||||||
wmod->type = type;
|
wmod->type = type;
|
||||||
wmod->load_addr = mod_addr;
|
wmod->load_addr = mod_addr;
|
||||||
|
wmod->size = size;
|
||||||
wmod->handle = hmodule;
|
wmod->handle = hmodule;
|
||||||
wmod->dbg_index = DEBUG_CurrProcess->next_index;
|
wmod->dbg_index = DEBUG_CurrProcess->next_index;
|
||||||
wmod->module_name = DBG_strdup(name);
|
wmod->module_name = DBG_strdup(name);
|
||||||
DEBUG_CurrProcess->modules = wmod;
|
|
||||||
|
DEBUG_CurrProcess->modules = DBG_realloc(DEBUG_CurrProcess->modules,
|
||||||
|
++DEBUG_CurrProcess->num_modules * sizeof(DBG_MODULE*));
|
||||||
|
DEBUG_CurrProcess->modules[DEBUG_CurrProcess->num_modules - 1] = wmod;
|
||||||
|
|
||||||
return wmod;
|
return wmod;
|
||||||
}
|
}
|
||||||
|
@ -46,15 +48,17 @@ DBG_MODULE* DEBUG_AddModule(const char* name, int type,
|
||||||
* DEBUG_FindModuleByName
|
* DEBUG_FindModuleByName
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type)
|
DBG_MODULE* DEBUG_FindModuleByName(const char* name, enum DbgModuleType type)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
int i;
|
||||||
|
DBG_MODULE** amod = DEBUG_CurrProcess->modules;
|
||||||
|
|
||||||
for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
|
for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
|
||||||
if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
|
if ((type == DMT_UNKNOWN || type == amod[i]->type) &&
|
||||||
!strcasecmp(name, wmod->module_name)) break;
|
!strcasecmp(name, amod[i]->module_name))
|
||||||
}
|
return amod[i];
|
||||||
return wmod;
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -63,31 +67,35 @@ DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type)
|
||||||
* either the addr where module is loaded, or any address inside the
|
* either the addr where module is loaded, or any address inside the
|
||||||
* module
|
* module
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, int type)
|
DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, enum DbgModuleType type)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
int i;
|
||||||
DBG_MODULE* res = NULL;
|
DBG_MODULE** amod = DEBUG_CurrProcess->modules;
|
||||||
|
DBG_MODULE* res = NULL;
|
||||||
|
|
||||||
for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
|
for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
|
||||||
if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
|
if ((type == DMT_UNKNOWN || type == amod[i]->type) &&
|
||||||
(u_long)addr >= (u_long)wmod->load_addr &&
|
(u_long)addr >= (u_long)amod[i]->load_addr &&
|
||||||
(!res || res->load_addr < wmod->load_addr))
|
(!res || res->load_addr < amod[i]->load_addr))
|
||||||
res = wmod;
|
res = amod[i];
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DEBUG_FindModuleByHandle
|
* DEBUG_FindModuleByHandle
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type)
|
DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, enum DbgModuleType type)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
int i;
|
||||||
|
DBG_MODULE** amod = DEBUG_CurrProcess->modules;
|
||||||
|
|
||||||
for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
|
for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
|
||||||
if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
|
if ((type == DMT_UNKNOWN || type == amod[i]->type) &&
|
||||||
}
|
handle == amod[i]->handle)
|
||||||
return wmod;
|
return amod[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -95,14 +103,12 @@ DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type)
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
|
DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
if (!process || !process->num_modules) return NULL;
|
||||||
|
|
||||||
if (!process) return NULL;
|
/* main module is the first to be loaded on a given process, so it's the first
|
||||||
|
* in the array */
|
||||||
/* main module is the first to be loaded on a given process, so it's the last on
|
assert(process->modules[0]->main);
|
||||||
* the list */
|
return process->modules[0];
|
||||||
for (wmod = process->modules; wmod && wmod->next; wmod = wmod->next);
|
|
||||||
return wmod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -111,13 +117,12 @@ DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
|
||||||
* ELF modules are also entered into the list - this is so that we
|
* ELF modules are also entered into the list - this is so that we
|
||||||
* can make 'info shared' types of displays possible.
|
* can make 'info shared' types of displays possible.
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
|
DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, u_long size, const char* name)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
|
DBG_MODULE* wmod = DEBUG_AddModule(name, DMT_ELF, (void*)load_addr, size, 0);
|
||||||
|
|
||||||
if (!wmod) return NULL;
|
if (!wmod) return NULL;
|
||||||
|
|
||||||
wmod->status = DM_STATUS_LOADED;
|
|
||||||
DEBUG_CurrProcess->next_index++;
|
DEBUG_CurrProcess->next_index++;
|
||||||
|
|
||||||
return wmod;
|
return wmod;
|
||||||
|
@ -127,9 +132,9 @@ DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
|
||||||
* DEBUG_RegisterPEModule
|
* DEBUG_RegisterPEModule
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
|
DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, u_long size, const char *module_name)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
|
DBG_MODULE* wmod = DEBUG_AddModule(module_name, DMT_PE, (void*)load_addr, size, hModule);
|
||||||
|
|
||||||
if (!wmod) return NULL;
|
if (!wmod) return NULL;
|
||||||
|
|
||||||
|
@ -142,13 +147,12 @@ DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char
|
||||||
* DEBUG_RegisterNEModule
|
* DEBUG_RegisterNEModule
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
|
DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, u_long size, const char *module_name)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
|
DBG_MODULE* wmod = DEBUG_AddModule(module_name, DMT_NE, load_addr, size, hModule);
|
||||||
|
|
||||||
if (!wmod) return NULL;
|
if (!wmod) return NULL;
|
||||||
|
|
||||||
wmod->status = DM_STATUS_LOADED;
|
|
||||||
DEBUG_CurrProcess->next_index++;
|
DEBUG_CurrProcess->next_index++;
|
||||||
return wmod;
|
return wmod;
|
||||||
}
|
}
|
||||||
|
@ -251,59 +255,86 @@ static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleA
|
||||||
* DEBUG_LoadModule32
|
* DEBUG_LoadModule32
|
||||||
*/
|
*/
|
||||||
void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
||||||
|
{
|
||||||
|
IMAGE_NT_HEADERS pe_header;
|
||||||
|
DWORD nth_ofs;
|
||||||
|
DBG_MODULE* wmod = NULL;
|
||||||
|
int i;
|
||||||
|
IMAGE_SECTION_HEADER pe_seg;
|
||||||
|
DWORD pe_seg_ofs;
|
||||||
|
DWORD size = 0;
|
||||||
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
|
|
||||||
|
/* grab PE Header */
|
||||||
|
if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)),
|
||||||
|
&nth_ofs, sizeof(nth_ofs)) ||
|
||||||
|
!DEBUG_READ_MEM_VERBOSE((void*)(base + nth_ofs), &pe_header, sizeof(pe_header)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pe_seg_ofs = nth_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)))
|
||||||
|
continue;
|
||||||
|
if (size < pe_seg.VirtualAddress + pe_seg.SizeOfRawData)
|
||||||
|
size = pe_seg.VirtualAddress + pe_seg.SizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: we make the assumption that hModule == base */
|
||||||
|
wmod = DEBUG_RegisterPEModule((HMODULE)base, base, size, name);
|
||||||
|
if (wmod) {
|
||||||
|
dil = DEBUG_RegisterStabsDebugInfo(wmod, hFile, &pe_header, nth_ofs);
|
||||||
|
if (dil != DIL_LOADED)
|
||||||
|
dil = DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, nth_ofs);
|
||||||
|
if (dil != DIL_LOADED)
|
||||||
|
dil = DEBUG_RegisterPEDebugInfo(wmod, hFile, &pe_header, nth_ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wmod) wmod->dil = dil;
|
||||||
|
DEBUG_ReportDIL(dil, "32bit DLL", name, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DEBUG_RegisterPEDebugInfo
|
||||||
|
*/
|
||||||
|
enum DbgInfoLoad DEBUG_RegisterPEDebugInfo(DBG_MODULE* wmod, HANDLE hFile,
|
||||||
|
void* _nth, unsigned long nth_ofs)
|
||||||
{
|
{
|
||||||
DBG_VALUE value;
|
DBG_VALUE value;
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
char bufstr[256];
|
char bufstr[256];
|
||||||
int i;
|
int i;
|
||||||
IMAGE_NT_HEADERS pe_header;
|
|
||||||
DWORD pe_header_ofs;
|
|
||||||
IMAGE_SECTION_HEADER pe_seg;
|
IMAGE_SECTION_HEADER pe_seg;
|
||||||
DWORD pe_seg_ofs;
|
DWORD pe_seg_ofs;
|
||||||
IMAGE_DATA_DIRECTORY dir;
|
IMAGE_DATA_DIRECTORY dir;
|
||||||
DWORD dir_ofs;
|
DWORD dir_ofs;
|
||||||
DBG_MODULE* wmod;
|
const char* prefix;
|
||||||
const char *prefix;
|
IMAGE_NT_HEADERS* nth = (PIMAGE_NT_HEADERS)_nth;
|
||||||
|
DWORD base = (u_long)wmod->load_addr;
|
||||||
/* FIXME: we make the assumption that hModule == base */
|
|
||||||
wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
|
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_TRACE, "Registring 32bit DLL '%s' at %08lx\n", name, base);
|
|
||||||
|
|
||||||
value.type = NULL;
|
value.type = NULL;
|
||||||
value.cookie = DV_TARGET;
|
value.cookie = DV_TARGET;
|
||||||
value.addr.seg = 0;
|
value.addr.seg = 0;
|
||||||
value.addr.off = 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_RegisterStabsDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
|
|
||||||
DEBUG_RegisterMSCDebugInfo(wmod, hFile, &pe_header, pe_header_ofs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add start of DLL */
|
/* Add start of DLL */
|
||||||
value.addr.off = base;
|
value.addr.off = base;
|
||||||
if ((prefix = strrchr( name, '\\' ))) prefix++;
|
if ((prefix = strrchr(wmod->module_name, '\\' ))) prefix++;
|
||||||
else prefix = name;
|
else prefix = wmod->module_name;
|
||||||
|
|
||||||
DEBUG_AddSymbol(prefix, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
DEBUG_AddSymbol(prefix, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
||||||
|
|
||||||
/* Add entry point */
|
/* Add entry point */
|
||||||
wsnprintf(buffer, sizeof(buffer), "%s.EntryPoint", prefix);
|
wsnprintf(buffer, sizeof(buffer), "%s.EntryPoint", prefix);
|
||||||
value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
|
value.addr.off = base + nth->OptionalHeader.AddressOfEntryPoint;
|
||||||
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
|
||||||
|
|
||||||
/* Add start of sections */
|
/* Add start of sections */
|
||||||
pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
|
pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
|
||||||
pe_header.FileHeader.SizeOfOptionalHeader;
|
nth->FileHeader.SizeOfOptionalHeader;
|
||||||
|
|
||||||
for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
|
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
|
||||||
if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
|
if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)))
|
||||||
continue;
|
continue;
|
||||||
wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, pe_seg.Name);
|
wsnprintf(buffer, sizeof(buffer), "%s.%s", prefix, pe_seg.Name);
|
||||||
|
@ -312,7 +343,7 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add exported functions */
|
/* Add exported functions */
|
||||||
dir_ofs = pe_header_ofs +
|
dir_ofs = nth_ofs +
|
||||||
OFFSET_OF(IMAGE_NT_HEADERS,
|
OFFSET_OF(IMAGE_NT_HEADERS,
|
||||||
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
|
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
|
||||||
if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
|
if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
|
||||||
|
@ -362,6 +393,8 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
|
||||||
DBG_free(ordinals);
|
DBG_free(ordinals);
|
||||||
DBG_free(names);
|
DBG_free(names);
|
||||||
}
|
}
|
||||||
|
/* no real debug info, only entry points */
|
||||||
|
return DIL_NOINFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -416,6 +449,86 @@ int DEBUG_LoadEntryPoints(const char* pfx)
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DEBUG_ReportDIL(enum DbgInfoLoad dil, const char* pfx, const char* filename, DWORD load_addr)
|
||||||
|
{
|
||||||
|
const char* fmt;
|
||||||
|
|
||||||
|
switch (dil) {
|
||||||
|
case DIL_DEFERRED:
|
||||||
|
fmt = "Deferring debug information loading for %s '%s' (0x%08x)\n";
|
||||||
|
break;
|
||||||
|
case DIL_LOADED:
|
||||||
|
fmt = "Loaded debug information from %s '%s' (0x%08x)\n";
|
||||||
|
break;
|
||||||
|
case DIL_NOINFO:
|
||||||
|
fmt = "No debug information in %s '%s' (0x%08x)\n";
|
||||||
|
break;
|
||||||
|
case DIL_ERROR:
|
||||||
|
fmt = "Can't find file for %s '%s' (0x%08x)\n";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG_Printf(DBG_CHN_ERR, "Oooocch (%d)\n", dil);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_Printf(DBG_CHN_MESG, fmt, pfx, filename, load_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* DEBUG_GetModuleType(enum DbgModuleType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case DMT_NE: return "NE";
|
||||||
|
case DMT_PE: return "PE";
|
||||||
|
case DMT_ELF: return "ELF";
|
||||||
|
default: return "???";;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* DEBUG_GetDbgInfo(enum DbgInfoLoad dil)
|
||||||
|
{
|
||||||
|
switch (dil) {
|
||||||
|
case DIL_LOADED: return "loaded";
|
||||||
|
case DIL_DEFERRED: return "deferred";
|
||||||
|
case DIL_NOINFO: return "none";
|
||||||
|
case DIL_ERROR: return "error";
|
||||||
|
default: return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DEBUG_ModuleCompare
|
||||||
|
*
|
||||||
|
* returns -1 is p1 < p2, 0 is p1 == p2, +1 if p1 > p2
|
||||||
|
* order used is order on load_addr of a module
|
||||||
|
*/
|
||||||
|
static int DEBUG_ModuleCompare(const void* p1, const void* p2)
|
||||||
|
{
|
||||||
|
return (*((const DBG_MODULE**)p1))->load_addr -
|
||||||
|
(*((const DBG_MODULE**)p2))->load_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DEBUG_IsContainer
|
||||||
|
*
|
||||||
|
* returns TRUE is wmod_child is contained (inside bounds) of wmod_cntnr
|
||||||
|
*/
|
||||||
|
static BOOL inline DEBUG_IsContainer(const DBG_MODULE* wmod_cntnr,
|
||||||
|
const DBG_MODULE* wmod_child)
|
||||||
|
{
|
||||||
|
return wmod_cntnr->load_addr < wmod_child->load_addr &&
|
||||||
|
(DWORD)wmod_cntnr->load_addr + wmod_cntnr->size >
|
||||||
|
(DWORD)wmod_child->load_addr + wmod_child->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DEBUG_InfoShareModule(const DBG_MODULE* module, int ident)
|
||||||
|
{
|
||||||
|
if (ident) DEBUG_Printf(DBG_CHN_MESG, " \\-");
|
||||||
|
DEBUG_Printf(DBG_CHN_MESG, "%s\t0x%08lx-%08lx\t%s\n",
|
||||||
|
DEBUG_GetModuleType(module->type),
|
||||||
|
(DWORD)module->load_addr, (DWORD)module->load_addr + module->size,
|
||||||
|
module->module_name);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DEBUG_InfoShare
|
* DEBUG_InfoShare
|
||||||
*
|
*
|
||||||
|
@ -423,60 +536,64 @@ int DEBUG_LoadEntryPoints(const char* pfx)
|
||||||
*/
|
*/
|
||||||
void DEBUG_InfoShare(void)
|
void DEBUG_InfoShare(void)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
DBG_MODULE** ref;
|
||||||
const char* xtype;
|
int i, j;
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
|
ref = DBG_alloc(sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
|
||||||
|
if (!ref) return;
|
||||||
|
|
||||||
for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
|
DEBUG_Printf(DBG_CHN_MESG, "Module\tAddress\t\t\tName\t%d modules\n",
|
||||||
switch (wmod->type) {
|
DEBUG_CurrProcess->num_modules);
|
||||||
case DM_TYPE_NE: xtype = "NE"; break;
|
|
||||||
case DM_TYPE_PE: xtype = "PE"; break;
|
memcpy(ref, DEBUG_CurrProcess->modules,
|
||||||
case DM_TYPE_ELF: xtype = "ELF"; break;
|
sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
|
||||||
default: xtype = "???"; break;
|
qsort(ref, DEBUG_CurrProcess->num_modules, sizeof(DBG_MODULE*),
|
||||||
|
DEBUG_ModuleCompare);
|
||||||
|
for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
|
||||||
|
switch (ref[i]->type) {
|
||||||
|
case DMT_ELF:
|
||||||
|
DEBUG_InfoShareModule(ref[i], 0);
|
||||||
|
for (j = 0; j < DEBUG_CurrProcess->num_modules; j++) {
|
||||||
|
if (ref[j]->type != DMT_ELF && DEBUG_IsContainer(ref[i], ref[j]))
|
||||||
|
DEBUG_InfoShareModule(ref[j], 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DMT_NE:
|
||||||
|
case DMT_PE:
|
||||||
|
/* check module is not in ELF */
|
||||||
|
for (j = 0; j < DEBUG_CurrProcess->num_modules; j++) {
|
||||||
|
if (ref[j]->type == DMT_ELF &&
|
||||||
|
DEBUG_IsContainer(ref[j], ref[i]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j >= DEBUG_CurrProcess->num_modules)
|
||||||
|
DEBUG_InfoShareModule(ref[i], 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG_Printf(DBG_CHN_ERR, "Unknown type (%d)\n", ref[i]->type);
|
||||||
}
|
}
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "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 "???";
|
|
||||||
}
|
}
|
||||||
|
DBG_free(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DEBUG_
|
* DEBUG_DumpModule
|
||||||
* Display information about a given module (DLL or EXE)
|
* Display information about a given module (DLL or EXE)
|
||||||
*/
|
*/
|
||||||
void DEBUG_DumpModule(DWORD mod)
|
void DEBUG_DumpModule(DWORD mod)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
DBG_MODULE* wmod;
|
||||||
|
|
||||||
if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) &&
|
if (!(wmod = DEBUG_FindModuleByHandle(mod, DMT_UNKNOWN)) &&
|
||||||
!(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) {
|
!(wmod = DEBUG_FindModuleByAddr((void*)mod, DMT_UNKNOWN))) {
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "'0x%08lx' is not a valid module handle or address\n", mod);
|
DEBUG_Printf(DBG_CHN_MESG, "'0x%08lx' is not a valid module handle or address\n", mod);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n",
|
DEBUG_Printf(DBG_CHN_MESG, "Module '%s' (handle=0x%08x) 0x%08lx-0x%08lx (%s, debug info %s)\n",
|
||||||
wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr,
|
wmod->module_name, wmod->handle, (DWORD)wmod->load_addr,
|
||||||
DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status));
|
(DWORD)wmod->load_addr + wmod->size,
|
||||||
|
DEBUG_GetModuleType(wmod->type), DEBUG_GetDbgInfo(wmod->dil));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -486,22 +603,26 @@ void DEBUG_DumpModule(DWORD mod)
|
||||||
*/
|
*/
|
||||||
void DEBUG_WalkModules(void)
|
void DEBUG_WalkModules(void)
|
||||||
{
|
{
|
||||||
DBG_MODULE* wmod;
|
DBG_MODULE** amod;
|
||||||
const char* xtype;
|
int i;
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "Address\t\tModule\tName\n");
|
DEBUG_Printf(DBG_CHN_MESG, "Address\t\t\tModule\tName\n");
|
||||||
|
|
||||||
for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
|
amod = DBG_alloc(sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
|
||||||
switch (wmod->type) {
|
if (!amod) return;
|
||||||
case DM_TYPE_NE: xtype = "NE"; break;
|
|
||||||
case DM_TYPE_PE: xtype = "PE"; break;
|
|
||||||
case DM_TYPE_ELF: continue;
|
|
||||||
default: xtype = "???"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "0x%8.8x\t(%s)\t%s\n",
|
memcpy(amod, DEBUG_CurrProcess->modules,
|
||||||
(unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type),
|
sizeof(DBG_MODULE*) * DEBUG_CurrProcess->num_modules);
|
||||||
wmod->module_name);
|
qsort(amod, DEBUG_CurrProcess->num_modules, sizeof(DBG_MODULE*),
|
||||||
|
DEBUG_ModuleCompare);
|
||||||
|
for (i = 0; i < DEBUG_CurrProcess->num_modules; i++) {
|
||||||
|
if (amod[i]->type == DMT_ELF) continue;
|
||||||
|
|
||||||
|
DEBUG_Printf(DBG_CHN_MESG, "0x%08lx-%08lx\t(%s)\t%s\n",
|
||||||
|
(DWORD)amod[i]->load_addr,
|
||||||
|
(DWORD)amod[i]->load_addr + amod[i]->size,
|
||||||
|
DEBUG_GetModuleType(amod[i]->type), amod[i]->module_name);
|
||||||
}
|
}
|
||||||
|
DBG_free(amod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
132
debugger/msc.c
132
debugger/msc.c
|
@ -27,7 +27,6 @@
|
||||||
#include "neexe.h"
|
#include "neexe.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
DWORD from;
|
DWORD from;
|
||||||
|
@ -35,7 +34,7 @@ typedef struct
|
||||||
|
|
||||||
} OMAP_DATA;
|
} OMAP_DATA;
|
||||||
|
|
||||||
typedef struct
|
typedef struct tagMSC_DBG_INFO
|
||||||
{
|
{
|
||||||
int nsect;
|
int nsect;
|
||||||
PIMAGE_SECTION_HEADER sectp;
|
PIMAGE_SECTION_HEADER sectp;
|
||||||
|
@ -45,10 +44,6 @@ typedef struct
|
||||||
|
|
||||||
} MSC_DBG_INFO;
|
} MSC_DBG_INFO;
|
||||||
|
|
||||||
#define MSC_INFO(module) ((MSC_DBG_INFO*)((module)->extra_info))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*========================================================================
|
/*========================================================================
|
||||||
* Debug file access helper routines
|
* Debug file access helper routines
|
||||||
*/
|
*/
|
||||||
|
@ -209,7 +204,7 @@ static void DEBUG_AddCoffSymbol( struct CoffFile* coff_file, struct name_hash* s
|
||||||
coff_file->entries[coff_file->neps++] = sym;
|
coff_file->entries[coff_file->neps++] = sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
static enum DbgInfoLoad DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
||||||
{
|
{
|
||||||
PIMAGE_AUX_SYMBOL aux;
|
PIMAGE_AUX_SYMBOL aux;
|
||||||
PIMAGE_COFF_SYMBOLS_HEADER coff;
|
PIMAGE_COFF_SYMBOLS_HEADER coff;
|
||||||
|
@ -227,7 +222,7 @@ static BOOL DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
||||||
const char * nampnt;
|
const char * nampnt;
|
||||||
int naux;
|
int naux;
|
||||||
DBG_VALUE new_value;
|
DBG_VALUE new_value;
|
||||||
int rtn = FALSE;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_TRACE, "Processing COFF symbols...\n");
|
DEBUG_Printf(DBG_CHN_TRACE, "Processing COFF symbols...\n");
|
||||||
|
|
||||||
|
@ -344,7 +339,7 @@ static BOOL DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
||||||
&& (naux == 0)
|
&& (naux == 0)
|
||||||
&& (coff_sym->SectionNumber == 1) )
|
&& (coff_sym->SectionNumber == 1) )
|
||||||
{
|
{
|
||||||
DWORD base = MSC_INFO(module)->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
|
DWORD base = module->msc_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
|
||||||
/*
|
/*
|
||||||
* This is a normal static function when naux == 0.
|
* This is a normal static function when naux == 0.
|
||||||
* Just register it. The current file is the correct
|
* Just register it. The current file is the correct
|
||||||
|
@ -373,7 +368,7 @@ static BOOL DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
||||||
&& (coff_sym->SectionNumber > 0) )
|
&& (coff_sym->SectionNumber > 0) )
|
||||||
{
|
{
|
||||||
const char* this_file = NULL;
|
const char* this_file = NULL;
|
||||||
DWORD base = MSC_INFO(module)->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
|
DWORD base = module->msc_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
|
||||||
nampnt = DEBUG_GetCoffName( coff_sym, coff_strtab );
|
nampnt = DEBUG_GetCoffName( coff_sym, coff_strtab );
|
||||||
|
|
||||||
new_value.addr.seg = 0;
|
new_value.addr.seg = 0;
|
||||||
|
@ -411,7 +406,7 @@ static BOOL DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
||||||
if( (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
|
if( (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
|
||||||
&& (coff_sym->SectionNumber > 0) )
|
&& (coff_sym->SectionNumber > 0) )
|
||||||
{
|
{
|
||||||
DWORD base = MSC_INFO(module)->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
|
DWORD base = module->msc_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
|
||||||
/*
|
/*
|
||||||
* Similar to above, but for the case of data symbols.
|
* Similar to above, but for the case of data symbols.
|
||||||
* These aren't treated as entrypoints.
|
* These aren't treated as entrypoints.
|
||||||
|
@ -517,7 +512,7 @@ static BOOL DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rtn = TRUE;
|
dil = DIL_LOADED;
|
||||||
|
|
||||||
if( coff_files.files != NULL )
|
if( coff_files.files != NULL )
|
||||||
{
|
{
|
||||||
|
@ -531,7 +526,7 @@ static BOOL DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
|
||||||
DBG_free(coff_files.files);
|
DBG_free(coff_files.files);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rtn);
|
return dil;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2030,8 +2025,8 @@ union codeview_symbol
|
||||||
static unsigned int
|
static unsigned int
|
||||||
DEBUG_MapCVOffset( DBG_MODULE *module, unsigned int offset )
|
DEBUG_MapCVOffset( DBG_MODULE *module, unsigned int offset )
|
||||||
{
|
{
|
||||||
int nomap = MSC_INFO(module)->nomap;
|
int nomap = module->msc_info->nomap;
|
||||||
OMAP_DATA *omapp = MSC_INFO(module)->omapp;
|
OMAP_DATA *omapp = module->msc_info->omapp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ( !nomap || !omapp )
|
if ( !nomap || !omapp )
|
||||||
|
@ -2050,8 +2045,8 @@ DEBUG_AddCVSymbol( DBG_MODULE *module, char *name, int namelen,
|
||||||
int type, int seg, int offset, int size, int cookie, int flags,
|
int type, int seg, int offset, int size, int cookie, int flags,
|
||||||
struct codeview_linetab_hdr *linetab )
|
struct codeview_linetab_hdr *linetab )
|
||||||
{
|
{
|
||||||
int nsect = MSC_INFO(module)->nsect;
|
int nsect = module->msc_info->nsect;
|
||||||
PIMAGE_SECTION_HEADER sectp = MSC_INFO(module)->sectp;
|
PIMAGE_SECTION_HEADER sectp = module->msc_info->sectp;
|
||||||
|
|
||||||
struct name_hash *symbol;
|
struct name_hash *symbol;
|
||||||
char symname[PATH_MAX];
|
char symname[PATH_MAX];
|
||||||
|
@ -2529,8 +2524,10 @@ static void pdb_convert_symbols_header( PDB_SYMBOLS *symbols,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DEBUG_ProcessPDBFile( DBG_MODULE *module, const char *filename, DWORD timestamp )
|
static enum DbgInfoLoad DEBUG_ProcessPDBFile( DBG_MODULE *module,
|
||||||
|
const char *filename, DWORD timestamp )
|
||||||
{
|
{
|
||||||
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
HANDLE hFile, hMap;
|
HANDLE hFile, hMap;
|
||||||
char *image = NULL;
|
char *image = NULL;
|
||||||
PDB_HEADER *pdb = NULL;
|
PDB_HEADER *pdb = NULL;
|
||||||
|
@ -2690,6 +2687,7 @@ static int DEBUG_ProcessPDBFile( DBG_MODULE *module, const char *filename, DWORD
|
||||||
file = (char *)( (DWORD)(file_name + strlen(file_name) + 1 + 3) & ~3 );
|
file = (char *)( (DWORD)(file_name + strlen(file_name) + 1 + 3) & ~3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dil = DIL_LOADED;
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
|
||||||
|
@ -2706,7 +2704,7 @@ static int DEBUG_ProcessPDBFile( DBG_MODULE *module, const char *filename, DWORD
|
||||||
|
|
||||||
DEBUG_UnmapDebugInfoFile(hFile, hMap, image);
|
DEBUG_UnmapDebugInfoFile(hFile, hMap, image);
|
||||||
|
|
||||||
return TRUE;
|
return dil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2759,10 +2757,10 @@ typedef struct _CV_DIRECTORY_ENTRY
|
||||||
#define sstSrcModule 0x127
|
#define sstSrcModule 0x127
|
||||||
|
|
||||||
|
|
||||||
static BOOL DEBUG_ProcessCodeView( DBG_MODULE *module, LPBYTE root )
|
static enum DbgInfoLoad DEBUG_ProcessCodeView( DBG_MODULE *module, LPBYTE root )
|
||||||
{
|
{
|
||||||
PCODEVIEW_HEADER cv = (PCODEVIEW_HEADER)root;
|
PCODEVIEW_HEADER cv = (PCODEVIEW_HEADER)root;
|
||||||
BOOL retv = FALSE;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
|
|
||||||
switch ( cv->dwSignature )
|
switch ( cv->dwSignature )
|
||||||
{
|
{
|
||||||
|
@ -2806,7 +2804,7 @@ static BOOL DEBUG_ProcessCodeView( DBG_MODULE *module, LPBYTE root )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retv = TRUE;
|
dil = DIL_LOADED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2814,7 +2812,7 @@ static BOOL DEBUG_ProcessCodeView( DBG_MODULE *module, LPBYTE root )
|
||||||
{
|
{
|
||||||
PCODEVIEW_PDB_DATA pdb = (PCODEVIEW_PDB_DATA)(cv + 1);
|
PCODEVIEW_PDB_DATA pdb = (PCODEVIEW_PDB_DATA)(cv + 1);
|
||||||
|
|
||||||
retv = DEBUG_ProcessPDBFile( module, pdb->name, pdb->timestamp );
|
dil = DEBUG_ProcessPDBFile( module, pdb->name, pdb->timestamp );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2824,51 +2822,81 @@ static BOOL DEBUG_ProcessCodeView( DBG_MODULE *module, LPBYTE root )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return retv;
|
return dil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*========================================================================
|
/*========================================================================
|
||||||
* Process debug directory.
|
* Process debug directory.
|
||||||
*/
|
*/
|
||||||
static BOOL DEBUG_ProcessDebugDirectory( DBG_MODULE *module, LPBYTE file_map,
|
static enum DbgInfoLoad DEBUG_ProcessDebugDirectory( DBG_MODULE *module,
|
||||||
PIMAGE_DEBUG_DIRECTORY dbg, int nDbg )
|
LPBYTE file_map,
|
||||||
|
PIMAGE_DEBUG_DIRECTORY dbg,
|
||||||
|
int nDbg )
|
||||||
{
|
{
|
||||||
BOOL retv = FALSE;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* First, watch out for OMAP data */
|
/* First, watch out for OMAP data */
|
||||||
for ( i = 0; i < nDbg; i++ )
|
for ( i = 0; i < nDbg; i++ )
|
||||||
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC )
|
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC )
|
||||||
{
|
{
|
||||||
MSC_INFO(module)->nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
|
module->msc_info->nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
|
||||||
MSC_INFO(module)->omapp = (OMAP_DATA *)(file_map + dbg[i].PointerToRawData);
|
module->msc_info->omapp = (OMAP_DATA *)(file_map + dbg[i].PointerToRawData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Now, try to parse CodeView debug info */
|
/* Now, try to parse CodeView debug info */
|
||||||
for ( i = 0; !retv && i < nDbg; i++ )
|
for ( i = 0; dil != DIL_LOADED && i < nDbg; i++ )
|
||||||
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW )
|
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_CODEVIEW )
|
||||||
retv = DEBUG_ProcessCodeView( module, file_map + dbg[i].PointerToRawData );
|
dil = DEBUG_ProcessCodeView( module, file_map + dbg[i].PointerToRawData );
|
||||||
|
|
||||||
|
|
||||||
/* If not found, try to parse COFF debug info */
|
/* If not found, try to parse COFF debug info */
|
||||||
for ( i = 0; !retv && i < nDbg; i++ )
|
for ( i = 0; dil != DIL_LOADED && i < nDbg; i++ )
|
||||||
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_COFF )
|
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_COFF )
|
||||||
retv = DEBUG_ProcessCoff( module, file_map + dbg[i].PointerToRawData );
|
dil = DEBUG_ProcessCoff( module, file_map + dbg[i].PointerToRawData );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* FIXME: this should be supported... this is the debug information for
|
||||||
|
* functions compiled without a frame pointer (FPO = frame pointer omission)
|
||||||
|
* the associated data helps finding out the relevant information
|
||||||
|
*/
|
||||||
|
for ( i = 0; i < nDbg; i++ )
|
||||||
|
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_FPO )
|
||||||
|
DEBUG_Printf(DBG_CHN_MESG, "This guy has FPO information\n");
|
||||||
|
|
||||||
return retv;
|
#define FRAME_FPO 0
|
||||||
|
#define FRAME_TRAP 1
|
||||||
|
#define FRAME_TSS 2
|
||||||
|
|
||||||
|
typedef struct _FPO_DATA {
|
||||||
|
DWORD ulOffStart; /* offset 1st byte of function code */
|
||||||
|
DWORD cbProcSize; /* # bytes in function */
|
||||||
|
DWORD cdwLocals; /* # bytes in locals/4 */
|
||||||
|
WORD cdwParams; /* # bytes in params/4 */
|
||||||
|
|
||||||
|
WORD cbProlog : 8; /* # bytes in prolog */
|
||||||
|
WORD cbRegs : 3; /* # regs saved */
|
||||||
|
WORD fHasSEH : 1; /* TRUE if SEH in func */
|
||||||
|
WORD fUseBP : 1; /* TRUE if EBP has been allocated */
|
||||||
|
WORD reserved : 1; /* reserved for future use */
|
||||||
|
WORD cbFrame : 2; /* frame type */
|
||||||
|
} FPO_DATA;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return dil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*========================================================================
|
/*========================================================================
|
||||||
* Process DBG file.
|
* Process DBG file.
|
||||||
*/
|
*/
|
||||||
static BOOL DEBUG_ProcessDBGFile( DBG_MODULE *module, const char *filename, DWORD timestamp )
|
static enum DbgInfoLoad DEBUG_ProcessDBGFile( DBG_MODULE *module,
|
||||||
|
const char *filename, DWORD timestamp )
|
||||||
{
|
{
|
||||||
BOOL retv = FALSE;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
HANDLE hFile = 0, hMap = 0;
|
HANDLE hFile = 0, hMap = 0;
|
||||||
LPBYTE file_map = NULL;
|
LPBYTE file_map = NULL;
|
||||||
PIMAGE_SEPARATE_DEBUG_HEADER hdr;
|
PIMAGE_SEPARATE_DEBUG_HEADER hdr;
|
||||||
|
@ -2905,22 +2933,22 @@ static BOOL DEBUG_ProcessDBGFile( DBG_MODULE *module, const char *filename, DWOR
|
||||||
|
|
||||||
nDbg = hdr->DebugDirectorySize / sizeof(*dbg);
|
nDbg = hdr->DebugDirectorySize / sizeof(*dbg);
|
||||||
|
|
||||||
retv = DEBUG_ProcessDebugDirectory( module, file_map, dbg, nDbg );
|
dil = DEBUG_ProcessDebugDirectory( module, file_map, dbg, nDbg );
|
||||||
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
DEBUG_UnmapDebugInfoFile( hFile, hMap, file_map );
|
DEBUG_UnmapDebugInfoFile( hFile, hMap, file_map );
|
||||||
return retv;
|
return dil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*========================================================================
|
/*========================================================================
|
||||||
* Process MSC debug information in PE file.
|
* Process MSC debug information in PE file.
|
||||||
*/
|
*/
|
||||||
int DEBUG_RegisterMSCDebugInfo( DBG_MODULE *module, HANDLE hFile,
|
enum DbgInfoLoad DEBUG_RegisterMSCDebugInfo( DBG_MODULE *module, HANDLE hFile,
|
||||||
void *_nth, unsigned long nth_ofs )
|
void *_nth, unsigned long nth_ofs )
|
||||||
{
|
{
|
||||||
BOOL retv = FALSE;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
|
PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
|
||||||
PIMAGE_DATA_DIRECTORY dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
|
PIMAGE_DATA_DIRECTORY dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
|
||||||
PIMAGE_DEBUG_DIRECTORY dbg = NULL;
|
PIMAGE_DEBUG_DIRECTORY dbg = NULL;
|
||||||
|
@ -2932,7 +2960,7 @@ int DEBUG_RegisterMSCDebugInfo( DBG_MODULE *module, HANDLE hFile,
|
||||||
|
|
||||||
/* Read in section data */
|
/* Read in section data */
|
||||||
|
|
||||||
MSC_INFO(module) = &extra_info;
|
module->msc_info = &extra_info;
|
||||||
extra_info.nsect = nth->FileHeader.NumberOfSections;
|
extra_info.nsect = nth->FileHeader.NumberOfSections;
|
||||||
extra_info.sectp = DBG_alloc( extra_info.nsect * sizeof(IMAGE_SECTION_HEADER) );
|
extra_info.sectp = DBG_alloc( extra_info.nsect * sizeof(IMAGE_SECTION_HEADER) );
|
||||||
if ( !extra_info.sectp )
|
if ( !extra_info.sectp )
|
||||||
|
@ -2982,24 +3010,23 @@ int DEBUG_RegisterMSCDebugInfo( DBG_MODULE *module, HANDLE hFile,
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
retv = DEBUG_ProcessDBGFile( module, misc->Data, nth->FileHeader.TimeDateStamp );
|
dil = DEBUG_ProcessDBGFile( module, misc->Data, nth->FileHeader.TimeDateStamp );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Debug info is embedded into PE module */
|
/* Debug info is embedded into PE module */
|
||||||
|
|
||||||
retv = DEBUG_ProcessDebugDirectory( module, file_map, dbg, nDbg );
|
dil = DEBUG_ProcessDebugDirectory( module, file_map, dbg, nDbg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
module->status = retv ? DM_STATUS_LOADED : DM_STATUS_ERROR;
|
module->msc_info = NULL;
|
||||||
MSC_INFO(module) = NULL;
|
|
||||||
|
|
||||||
DEBUG_UnmapDebugInfoFile( 0, hMap, file_map );
|
DEBUG_UnmapDebugInfoFile( 0, hMap, file_map );
|
||||||
if ( extra_info.sectp ) DBG_free( extra_info.sectp );
|
if ( extra_info.sectp ) DBG_free( extra_info.sectp );
|
||||||
if ( dbg ) DBG_free( dbg );
|
if ( dbg ) DBG_free( dbg );
|
||||||
return retv;
|
return dil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3007,14 +3034,15 @@ int DEBUG_RegisterMSCDebugInfo( DBG_MODULE *module, HANDLE hFile,
|
||||||
* look for stabs information in PE header (it's how mingw compiler provides its
|
* look for stabs information in PE header (it's how mingw compiler provides its
|
||||||
* debugging information), and also wine PE <-> ELF linking thru .wsolnk sections
|
* debugging information), and also wine PE <-> ELF linking thru .wsolnk sections
|
||||||
*/
|
*/
|
||||||
int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, HANDLE hFile, void* _nth,
|
enum DbgInfoLoad DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, HANDLE hFile,
|
||||||
unsigned long nth_ofs)
|
void* _nth, unsigned long nth_ofs)
|
||||||
{
|
{
|
||||||
IMAGE_SECTION_HEADER pe_seg;
|
IMAGE_SECTION_HEADER pe_seg;
|
||||||
unsigned long pe_seg_ofs;
|
unsigned long pe_seg_ofs;
|
||||||
int i, stabsize = 0, stabstrsize = 0;
|
int i, stabsize = 0, stabstrsize = 0;
|
||||||
unsigned int stabs = 0, stabstr = 0;
|
unsigned int stabs = 0, stabstr = 0;
|
||||||
PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
|
PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
|
||||||
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
|
|
||||||
pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
|
pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
|
||||||
nth->FileHeader.SizeOfOptionalHeader;
|
nth->FileHeader.SizeOfOptionalHeader;
|
||||||
|
@ -3040,7 +3068,7 @@ int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, HANDLE hFile, void* _nth,
|
||||||
if (DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabs, s1, stabsize) &&
|
if (DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabs, s1, stabsize) &&
|
||||||
DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabstr,
|
DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabstr,
|
||||||
s1 + stabsize, stabstrsize)) {
|
s1 + stabsize, stabstrsize)) {
|
||||||
DEBUG_ParseStabs(s1, 0, 0, stabsize, stabsize, stabstrsize);
|
dil = DEBUG_ParseStabs(s1, 0, 0, stabsize, stabsize, stabstrsize);
|
||||||
} else {
|
} else {
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "couldn't read data block\n");
|
DEBUG_Printf(DBG_CHN_MESG, "couldn't read data block\n");
|
||||||
}
|
}
|
||||||
|
@ -3049,7 +3077,9 @@ int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, HANDLE hFile, void* _nth,
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "couldn't alloc %d bytes\n",
|
DEBUG_Printf(DBG_CHN_MESG, "couldn't alloc %d bytes\n",
|
||||||
stabsize + stabstrsize);
|
stabsize + stabstrsize);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dil = DIL_NOINFO;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return dil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
493
debugger/stabs.c
493
debugger/stabs.c
|
@ -1,4 +1,4 @@
|
||||||
/* -*- tab-width: 8; c-basic-offset: 2 -*- */
|
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File stabs.c - read stabs information from the wine executable itself.
|
* File stabs.c - read stabs information from the wine executable itself.
|
||||||
|
@ -73,6 +73,9 @@
|
||||||
#define N_EXCL 0xc2
|
#define N_EXCL 0xc2
|
||||||
#define N_RBRAC 0xe0
|
#define N_RBRAC 0xe0
|
||||||
|
|
||||||
|
typedef struct tagELF_DBG_INFO {
|
||||||
|
unsigned long elf_addr;
|
||||||
|
} ELF_DBG_INFO;
|
||||||
|
|
||||||
struct stab_nlist {
|
struct stab_nlist {
|
||||||
union {
|
union {
|
||||||
|
@ -767,10 +770,9 @@ DEBUG_ParseStabType(const char * stab)
|
||||||
return *DEBUG_ReadTypeEnum(&c);
|
return *DEBUG_ReadTypeEnum(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
enum DbgInfoLoad DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
||||||
DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
unsigned int staboff, int stablen,
|
||||||
unsigned int staboff, int stablen,
|
unsigned int strtaboff, int strtablen)
|
||||||
unsigned int strtaboff, int strtablen)
|
|
||||||
{
|
{
|
||||||
struct name_hash * curr_func = NULL;
|
struct name_hash * curr_func = NULL;
|
||||||
struct wine_locals * curr_loc = NULL;
|
struct wine_locals * curr_loc = NULL;
|
||||||
|
@ -979,8 +981,13 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
||||||
* all of the pages related to the stabs, and that
|
* all of the pages related to the stabs, and that
|
||||||
* sucks up swap space like crazy.
|
* sucks up swap space like crazy.
|
||||||
*/
|
*/
|
||||||
|
#ifdef __ELF__
|
||||||
curr_func = DEBUG_AddSymbol( symname, &new_value, currpath,
|
curr_func = DEBUG_AddSymbol( symname, &new_value, currpath,
|
||||||
SYM_WINE | SYM_FUNC | SYM_INVALID);
|
SYM_WINE | SYM_FUNC | SYM_INVALID );
|
||||||
|
#else
|
||||||
|
curr_func = DEBUG_AddSymbol( symname, &new_value, currpath,
|
||||||
|
SYM_WINE | SYM_FUNC );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1069,7 +1076,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_Printf(DBG_CHN_MESG, "Unkown stab type 0x%02x\n", stab_ptr->n_type);
|
DEBUG_Printf(DBG_CHN_MESG, "Unknown stab type 0x%02x\n", stab_ptr->n_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,7 +1095,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
||||||
curr_types = NULL;
|
curr_types = NULL;
|
||||||
allocated_types = 0;
|
allocated_types = 0;
|
||||||
|
|
||||||
return TRUE;
|
return DIL_LOADED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __ELF__
|
#ifdef __ELF__
|
||||||
|
@ -1102,10 +1109,9 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
||||||
* This is all really quite easy, since we don't have to worry about line
|
* This is all really quite easy, since we don't have to worry about line
|
||||||
* numbers or local data variables.
|
* numbers or local data variables.
|
||||||
*/
|
*/
|
||||||
static
|
static int DEBUG_ProcessElfSymtab(DBG_MODULE* module, char* addr,
|
||||||
int
|
u_long load_addr, Elf32_Shdr* symtab,
|
||||||
DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
|
Elf32_Shdr* strtab)
|
||||||
Elf32_Shdr * symtab, Elf32_Shdr * strtab)
|
|
||||||
{
|
{
|
||||||
char * curfile = NULL;
|
char * curfile = NULL;
|
||||||
struct name_hash * curr_sym = NULL;
|
struct name_hash * curr_sym = NULL;
|
||||||
|
@ -1117,7 +1123,6 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
|
||||||
char * symname;
|
char * symname;
|
||||||
Elf32_Sym * symp;
|
Elf32_Sym * symp;
|
||||||
|
|
||||||
|
|
||||||
symp = (Elf32_Sym *) (addr + symtab->sh_offset);
|
symp = (Elf32_Sym *) (addr + symtab->sh_offset);
|
||||||
nsym = symtab->sh_size / sizeof(*symp);
|
nsym = symtab->sh_size / sizeof(*symp);
|
||||||
strp = (char *) (addr + strtab->sh_offset);
|
strp = (char *) (addr + strtab->sh_offset);
|
||||||
|
@ -1154,12 +1159,12 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
|
||||||
* multiple local symbols by the same name.
|
* multiple local symbols by the same name.
|
||||||
*/
|
*/
|
||||||
if( (DEBUG_GetSymbolValue(symname, -1, &new_value, FALSE ) == TRUE)
|
if( (DEBUG_GetSymbolValue(symname, -1, &new_value, FALSE ) == TRUE)
|
||||||
&& (new_value.addr.off == (load_offset + symp->st_value)) )
|
&& (new_value.addr.off == (load_addr + symp->st_value)) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
new_value.addr.seg = 0;
|
new_value.addr.seg = 0;
|
||||||
new_value.type = NULL;
|
new_value.type = NULL;
|
||||||
new_value.addr.off = load_offset + symp->st_value;
|
new_value.addr.off = load_addr + symp->st_value;
|
||||||
new_value.cookie = DV_TARGET;
|
new_value.cookie = DV_TARGET;
|
||||||
flags = SYM_WINE | ((ELF32_ST_TYPE(symp->st_info) == STT_FUNC)
|
flags = SYM_WINE | ((ELF32_ST_TYPE(symp->st_info) == STT_FUNC)
|
||||||
? SYM_FUNC : SYM_DATA);
|
? SYM_FUNC : SYM_DATA);
|
||||||
|
@ -1189,179 +1194,279 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
|
||||||
* read or parsed)
|
* read or parsed)
|
||||||
* 1 on success
|
* 1 on success
|
||||||
*/
|
*/
|
||||||
static int DEBUG_ProcessElfFile(const char * filename, unsigned int load_offset)
|
enum DbgInfoLoad DEBUG_LoadElfStabs(DBG_MODULE* module)
|
||||||
{
|
{
|
||||||
int rtn = -1;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
char * addr = (char*)0xffffffff;
|
char* addr = (char*)0xffffffff;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
Elf32_Ehdr * ehptr;
|
Elf32_Ehdr* ehptr;
|
||||||
Elf32_Shdr * spnt;
|
Elf32_Shdr* spnt;
|
||||||
char * shstrtab;
|
char* shstrtab;
|
||||||
int nsect;
|
int i;
|
||||||
int i;
|
int stabsect;
|
||||||
int stabsect;
|
int stabstrsect;
|
||||||
int stabstrsect;
|
|
||||||
|
|
||||||
/* check that the file exists, and that the module hasn't been loaded yet */
|
if (module->type != DMT_ELF || ! module->elf_info) {
|
||||||
if (stat(filename, &statbuf) == -1) goto leave;
|
DEBUG_Printf(DBG_CHN_ERR, "Bad elf module '%s'\n", module->module_name);
|
||||||
|
return DIL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* check that the file exists, and that the module hasn't been loaded yet */
|
||||||
* Now open the file, so that we can mmap() it.
|
if (stat(module->module_name, &statbuf) == -1) goto leave;
|
||||||
*/
|
|
||||||
if ((fd = open(filename, O_RDONLY)) == -1) goto leave;
|
|
||||||
|
|
||||||
rtn = 0;
|
/*
|
||||||
/*
|
* Now open the file, so that we can mmap() it.
|
||||||
* Now mmap() the file.
|
*/
|
||||||
*/
|
if ((fd = open(module->module_name, O_RDONLY)) == -1) goto leave;
|
||||||
addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
||||||
if (addr == (char*)0xffffffff) goto leave;
|
|
||||||
|
|
||||||
/*
|
dil = DIL_NOINFO;
|
||||||
* Next, we need to find a few of the internal ELF headers within
|
/*
|
||||||
* this thing. We need the main executable header, and the section
|
* Now mmap() the file.
|
||||||
* table.
|
*/
|
||||||
*/
|
addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
ehptr = (Elf32_Ehdr *) addr;
|
if (addr == (char*)0xffffffff) goto leave;
|
||||||
|
|
||||||
DEBUG_RegisterELFModule((load_offset == 0) ? ehptr->e_entry : load_offset, filename);
|
/*
|
||||||
|
* Next, we need to find a few of the internal ELF headers within
|
||||||
|
* this thing. We need the main executable header, and the section
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
ehptr = (Elf32_Ehdr*) addr;
|
||||||
|
spnt = (Elf32_Shdr*) (addr + ehptr->e_shoff);
|
||||||
|
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
|
||||||
|
|
||||||
spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff);
|
stabsect = stabstrsect = -1;
|
||||||
nsect = ehptr->e_shnum;
|
|
||||||
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
|
|
||||||
|
|
||||||
stabsect = stabstrsect = -1;
|
for (i = 0; i < ehptr->e_shnum; i++) {
|
||||||
|
if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
|
||||||
|
stabsect = i;
|
||||||
|
|
||||||
for (i = 0; i < nsect; i++) {
|
if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
|
||||||
if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
|
stabstrsect = i;
|
||||||
stabsect = i;
|
}
|
||||||
|
|
||||||
if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
|
if (stabsect == -1 || stabstrsect == -1) {
|
||||||
stabstrsect = i;
|
DEBUG_Printf(DBG_CHN_WARN, "no .stab section\n");
|
||||||
}
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
if (stabsect == -1 || stabstrsect == -1) {
|
/*
|
||||||
DEBUG_Printf(DBG_CHN_WARN, "no .stab section\n");
|
* OK, now just parse all of the stabs.
|
||||||
goto leave;
|
*/
|
||||||
}
|
if (DEBUG_ParseStabs(addr,
|
||||||
|
module->elf_info->elf_addr,
|
||||||
|
spnt[stabsect].sh_offset,
|
||||||
|
spnt[stabsect].sh_size,
|
||||||
|
spnt[stabstrsect].sh_offset,
|
||||||
|
spnt[stabstrsect].sh_size)) {
|
||||||
|
dil = DIL_LOADED;
|
||||||
|
} else {
|
||||||
|
dil = DIL_ERROR;
|
||||||
|
DEBUG_Printf(DBG_CHN_WARN, "bad stabs\n");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
for (i = 0; i < ehptr->e_shnum; i++) {
|
||||||
* OK, now just parse all of the stabs.
|
if ( (strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0)
|
||||||
*/
|
&& (spnt[i].sh_type == SHT_SYMTAB))
|
||||||
if (!(rtn = DEBUG_ParseStabs(addr, load_offset,
|
DEBUG_ProcessElfSymtab(module, addr, module->elf_info->elf_addr,
|
||||||
spnt[stabsect].sh_offset,
|
spnt + i, spnt + spnt[i].sh_link);
|
||||||
spnt[stabsect].sh_size,
|
|
||||||
spnt[stabstrsect].sh_offset,
|
|
||||||
spnt[stabstrsect].sh_size))) {
|
|
||||||
DEBUG_Printf(DBG_CHN_WARN, "bad stabs\n");
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nsect; i++) {
|
if ( (strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0)
|
||||||
if ( (strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0)
|
&& (spnt[i].sh_type == SHT_DYNSYM))
|
||||||
&& (spnt[i].sh_type == SHT_SYMTAB))
|
DEBUG_ProcessElfSymtab(module, addr, module->elf_info->elf_addr,
|
||||||
DEBUG_ProcessElfSymtab(addr, load_offset,
|
spnt + i, spnt + spnt[i].sh_link);
|
||||||
spnt + i, spnt + spnt[i].sh_link);
|
}
|
||||||
|
|
||||||
if ( (strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0)
|
leave:
|
||||||
&& (spnt[i].sh_type == SHT_DYNSYM))
|
if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
|
||||||
DEBUG_ProcessElfSymtab(addr, load_offset,
|
if (fd != -1) close(fd);
|
||||||
spnt + i, spnt + spnt[i].sh_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
leave:
|
return dil;
|
||||||
if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
|
|
||||||
if (fd != -1) close(fd);
|
|
||||||
|
|
||||||
return rtn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DEBUG_ProcessElfFileFromPath(const char * filename,
|
/*
|
||||||
unsigned int load_offset, const char* path)
|
* Loads the information for ELF module stored in 'filename'
|
||||||
|
* the module has been loaded at 'load_offset' address
|
||||||
|
* returns
|
||||||
|
* -1 if the file cannot be found/opened
|
||||||
|
* 0 if the file doesn't contain symbolic info (or this info cannot be
|
||||||
|
* read or parsed)
|
||||||
|
* 1 on success
|
||||||
|
*/
|
||||||
|
static enum DbgInfoLoad DEBUG_ProcessElfFile(const char* filename,
|
||||||
|
unsigned int load_offset,
|
||||||
|
unsigned int* dyn_addr)
|
||||||
{
|
{
|
||||||
int rtn = -1;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
char *s, *t, *fn;
|
char* addr = (char*)0xffffffff;
|
||||||
char* paths = NULL;
|
int fd = -1;
|
||||||
|
struct stat statbuf;
|
||||||
|
Elf32_Ehdr* ehptr;
|
||||||
|
Elf32_Shdr* spnt;
|
||||||
|
Elf32_Phdr* ppnt;
|
||||||
|
char * shstrtab;
|
||||||
|
int i;
|
||||||
|
DBG_MODULE* module = NULL;
|
||||||
|
DWORD size;
|
||||||
|
DWORD delta;
|
||||||
|
|
||||||
if (!path) return -1;
|
DEBUG_Printf(DBG_CHN_TRACE, "Processing elf file '%s'\n", filename);
|
||||||
|
|
||||||
for (s = paths = DBG_strdup(path); s && *s; s = (t) ? (t+1) : NULL) {
|
/* check that the file exists, and that the module hasn't been loaded yet */
|
||||||
t = strchr(s, ':');
|
if (stat(filename, &statbuf) == -1) goto leave;
|
||||||
if (t) *t = '\0';
|
|
||||||
fn = (char*)DBG_alloc(strlen(filename) + 1 + strlen(s) + 1);
|
|
||||||
if (!fn) break;
|
|
||||||
strcpy(fn, s );
|
|
||||||
strcat(fn, "/");
|
|
||||||
strcat(fn, filename);
|
|
||||||
rtn = DEBUG_ProcessElfFile(fn, load_offset);
|
|
||||||
DBG_free(fn);
|
|
||||||
if (rtn >= 0) break;
|
|
||||||
s = (t) ? (t+1) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_free(paths);
|
/*
|
||||||
return rtn;
|
* Now open the file, so that we can mmap() it.
|
||||||
|
*/
|
||||||
|
if ((fd = open(filename, O_RDONLY)) == -1) goto leave;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now mmap() the file.
|
||||||
|
*/
|
||||||
|
addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (addr == (char*)0xffffffff) goto leave;
|
||||||
|
|
||||||
|
dil = DIL_NOINFO;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Next, we need to find a few of the internal ELF headers within
|
||||||
|
* this thing. We need the main executable header, and the section
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
ehptr = (Elf32_Ehdr*) addr;
|
||||||
|
spnt = (Elf32_Shdr*) (addr + ehptr->e_shoff);
|
||||||
|
shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
|
||||||
|
|
||||||
|
/* if non relocatable ELF, then remove fixed address from computation
|
||||||
|
* otherwise, all addresses are zero based
|
||||||
|
*/
|
||||||
|
delta = (load_offset == 0) ? ehptr->e_entry : 0;
|
||||||
|
|
||||||
|
/* grab size of module once loaded in memory */
|
||||||
|
ppnt = (Elf32_Phdr*) (addr + ehptr->e_phoff);
|
||||||
|
size = 0;
|
||||||
|
for (i = 0; i < ehptr->e_phnum; i++) {
|
||||||
|
if (ppnt[i].p_type != PT_LOAD) continue;
|
||||||
|
if (size < ppnt[i].p_vaddr - delta + ppnt[i].p_memsz)
|
||||||
|
size = ppnt[i].p_vaddr - delta + ppnt[i].p_memsz;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ehptr->e_shnum; i++) {
|
||||||
|
if (strcmp(shstrtab + spnt[i].sh_name, ".bss") == 0 &&
|
||||||
|
spnt[i].sh_type == SHT_NOBITS) {
|
||||||
|
if (size < spnt[i].sh_addr - delta + spnt[i].sh_size)
|
||||||
|
size = spnt[i].sh_addr - delta + spnt[i].sh_size;
|
||||||
|
}
|
||||||
|
if (strcmp(shstrtab + spnt[i].sh_name, ".dynamic") == 0 &&
|
||||||
|
spnt[i].sh_type == SHT_DYNAMIC) {
|
||||||
|
if (dyn_addr) *dyn_addr = spnt[i].sh_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module = DEBUG_RegisterELFModule((load_offset == 0) ? ehptr->e_entry : load_offset,
|
||||||
|
size, filename);
|
||||||
|
if (!module) {
|
||||||
|
dil = DIL_ERROR;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((module->elf_info = DBG_alloc(sizeof(ELF_DBG_INFO))) == NULL) {
|
||||||
|
DEBUG_Printf(DBG_CHN_ERR, "OOM\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
module->elf_info->elf_addr = load_offset;
|
||||||
|
dil = DEBUG_LoadElfStabs(module);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
|
||||||
|
if (fd != -1) close(fd);
|
||||||
|
if (module) module->dil = dil;
|
||||||
|
|
||||||
|
return dil;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DEBUG_ProcessElfObject(const char * filename, unsigned int load_offset)
|
static enum DbgInfoLoad DEBUG_ProcessElfFileFromPath(const char * filename,
|
||||||
|
unsigned int load_offset,
|
||||||
|
unsigned int* dyn_addr,
|
||||||
|
const char* path)
|
||||||
{
|
{
|
||||||
int rtn = -1;
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
const char* fmt;
|
char *s, *t, *fn;
|
||||||
|
char* paths = NULL;
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_TRACE, "Processing elf file '%s'\n", filename);
|
if (!path) return -1;
|
||||||
|
|
||||||
if (filename == NULL) return FALSE;
|
for (s = paths = DBG_strdup(path); s && *s; s = (t) ? (t+1) : NULL) {
|
||||||
if (DEBUG_FindModuleByName(filename, DM_TYPE_ELF)) return TRUE;
|
t = strchr(s, ':');
|
||||||
|
if (t) *t = '\0';
|
||||||
|
fn = (char*)DBG_alloc(strlen(filename) + 1 + strlen(s) + 1);
|
||||||
|
if (!fn) break;
|
||||||
|
strcpy(fn, s );
|
||||||
|
strcat(fn, "/");
|
||||||
|
strcat(fn, filename);
|
||||||
|
dil = DEBUG_ProcessElfFile(fn, load_offset, dyn_addr);
|
||||||
|
DBG_free(fn);
|
||||||
|
if (dil != DIL_ERROR) break;
|
||||||
|
s = (t) ? (t+1) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
rtn = DEBUG_ProcessElfFile(filename, load_offset);
|
DBG_free(paths);
|
||||||
|
return dil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum DbgInfoLoad DEBUG_ProcessElfObject(const char* filename,
|
||||||
|
unsigned int load_offset,
|
||||||
|
unsigned int* dyn_addr)
|
||||||
|
{
|
||||||
|
enum DbgInfoLoad dil = DIL_ERROR;
|
||||||
|
|
||||||
|
if (filename == NULL) return DIL_ERROR;
|
||||||
|
if (DEBUG_FindModuleByName(filename, DMT_ELF)) return DIL_LOADED;
|
||||||
|
|
||||||
|
dil = DEBUG_ProcessElfFile(filename, load_offset, dyn_addr);
|
||||||
|
|
||||||
/* if relative pathname, try some absolute base dirs */
|
/* if relative pathname, try some absolute base dirs */
|
||||||
if (rtn < 0 && !strchr(filename, '/')) {
|
if (dil == DIL_ERROR && !strchr(filename, '/')) {
|
||||||
rtn = DEBUG_ProcessElfFileFromPath(filename, load_offset, getenv("PATH"));
|
dil = DEBUG_ProcessElfFileFromPath(filename, load_offset, dyn_addr, getenv("PATH"));
|
||||||
if (rtn < 0)
|
if (dil == DIL_ERROR)
|
||||||
rtn = DEBUG_ProcessElfFileFromPath(filename, load_offset, getenv("LD_LIBRARY_PATH"));
|
dil = DEBUG_ProcessElfFileFromPath(filename, load_offset, dyn_addr, getenv("LD_LIBRARY_PATH"));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (rtn) {
|
DEBUG_ReportDIL(dil, "ELF", filename, load_offset);
|
||||||
case 1: fmt = "Loaded stabs debug symbols from ELF '%s' (0x%08x)\n"; break;
|
|
||||||
case 0: fmt = "No stabs debug symbols in ELF '%s' (0x%08x)\n"; break;
|
|
||||||
case -1:fmt = "Can't find file for ELF '%s' (0x%08x)\n"; break;
|
|
||||||
default: DEBUG_Printf(DBG_CHN_ERR, "Oooocch (%d)\n", rtn); return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_MESG, fmt, filename, load_offset);
|
return dil;
|
||||||
|
|
||||||
return rtn >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL DEBUG_WalkList(struct r_debug* dbg_hdr)
|
static BOOL DEBUG_WalkList(struct r_debug* dbg_hdr)
|
||||||
{
|
{
|
||||||
u_long lm_addr;
|
u_long lm_addr;
|
||||||
struct link_map lm;
|
struct link_map lm;
|
||||||
Elf32_Ehdr ehdr;
|
Elf32_Ehdr ehdr;
|
||||||
char bufstr[256];
|
char bufstr[256];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now walk the linked list. In all known ELF implementations,
|
* Now walk the linked list. In all known ELF implementations,
|
||||||
* the dynamic loader maintains this linked list for us. In some
|
* the dynamic loader maintains this linked list for us. In some
|
||||||
* cases the first entry doesn't appear with a name, in other cases it
|
* cases the first entry doesn't appear with a name, in other cases it
|
||||||
* does.
|
* does.
|
||||||
*/
|
*/
|
||||||
for (lm_addr = (u_long)dbg_hdr->r_map; lm_addr; lm_addr = (u_long)lm.l_next) {
|
for (lm_addr = (u_long)dbg_hdr->r_map; lm_addr; lm_addr = (u_long)lm.l_next) {
|
||||||
if (!DEBUG_READ_MEM_VERBOSE((void*)lm_addr, &lm, sizeof(lm)))
|
if (!DEBUG_READ_MEM_VERBOSE((void*)lm_addr, &lm, sizeof(lm)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (lm.l_addr != 0 &&
|
if (lm.l_addr != 0 &&
|
||||||
DEBUG_READ_MEM_VERBOSE((void*)lm.l_addr, &ehdr, sizeof(ehdr)) &&
|
DEBUG_READ_MEM_VERBOSE((void*)lm.l_addr, &ehdr, sizeof(ehdr)) &&
|
||||||
ehdr.e_type == ET_DYN && /* only look at dynamic modules */
|
ehdr.e_type == ET_DYN && /* only look at dynamic modules */
|
||||||
lm.l_name != NULL &&
|
lm.l_name != NULL &&
|
||||||
DEBUG_READ_MEM_VERBOSE((void*)lm.l_name, bufstr, sizeof(bufstr))) {
|
DEBUG_READ_MEM_VERBOSE((void*)lm.l_name, bufstr, sizeof(bufstr))) {
|
||||||
bufstr[sizeof(bufstr) - 1] = '\0';
|
bufstr[sizeof(bufstr) - 1] = '\0';
|
||||||
DEBUG_ProcessElfObject(bufstr, (unsigned)lm.l_addr);
|
DEBUG_ProcessElfObject(bufstr, (unsigned)lm.l_addr, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL DEBUG_RescanElf(void)
|
static BOOL DEBUG_RescanElf(void)
|
||||||
|
@ -1379,75 +1484,65 @@ static BOOL DEBUG_RescanElf(void)
|
||||||
case RT_ADD:
|
case RT_ADD:
|
||||||
break;
|
break;
|
||||||
case RT_DELETE:
|
case RT_DELETE:
|
||||||
/*FIXME: this is not currently handled, would need some kind of mark&sweep algo */
|
/* FIXME: this is not currently handled, would need some kind of mark&sweep algo */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
enum DbgInfoLoad DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
||||||
DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
|
||||||
{
|
{
|
||||||
Elf32_Dyn dyn;
|
Elf32_Dyn dyn;
|
||||||
struct r_debug dbg_hdr;
|
struct r_debug dbg_hdr;
|
||||||
int rtn = FALSE;
|
enum DbgInfoLoad dil = DIL_NOINFO;
|
||||||
DBG_VALUE val;
|
unsigned int dyn_addr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure we can stat and open this file.
|
* Make sure we can stat and open this file.
|
||||||
*/
|
*/
|
||||||
if (exe_name == NULL) goto leave;
|
if (exe_name == NULL) goto leave;
|
||||||
DEBUG_ProcessElfObject(exe_name, 0);
|
DEBUG_ProcessElfObject(exe_name, 0, &dyn_addr);
|
||||||
|
|
||||||
/* previous step should have loaded symbol _DYNAMIC if it exists inside
|
do {
|
||||||
* the main executable
|
if (!DEBUG_READ_MEM_VERBOSE((void*)dyn_addr, &dyn, sizeof(dyn)))
|
||||||
*/
|
goto leave;
|
||||||
if (!DEBUG_GetSymbolValue("_DYNAMIC", -1, &val, FALSE)) {
|
dyn_addr += sizeof(dyn);
|
||||||
DEBUG_Printf(DBG_CHN_WARN, "Can't find symbol _DYNAMIC\n");
|
} while (dyn.d_tag != DT_DEBUG && dyn.d_tag != DT_NULL);
|
||||||
goto leave;
|
if (dyn.d_tag == DT_NULL) goto leave;
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
/*
|
||||||
if (!DEBUG_READ_MEM_VERBOSE((void*)val.addr.off, &dyn, sizeof(dyn)))
|
* OK, now dig into the actual tables themselves.
|
||||||
goto leave;
|
*/
|
||||||
val.addr.off += sizeof(dyn);
|
if (!DEBUG_READ_MEM_VERBOSE((void*)dyn.d_un.d_ptr, &dbg_hdr, sizeof(dbg_hdr)))
|
||||||
} while (dyn.d_tag != DT_DEBUG && dyn.d_tag != DT_NULL);
|
goto leave;
|
||||||
if (dyn.d_tag == DT_NULL) goto leave;
|
|
||||||
|
|
||||||
/*
|
assert(!DEBUG_CurrProcess->dbg_hdr_addr);
|
||||||
* OK, now dig into the actual tables themselves.
|
DEBUG_CurrProcess->dbg_hdr_addr = (u_long)dyn.d_un.d_ptr;
|
||||||
*/
|
|
||||||
if (!DEBUG_READ_MEM_VERBOSE((void*)dyn.d_un.d_ptr, &dbg_hdr, sizeof(dbg_hdr)))
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
assert(!DEBUG_CurrProcess->dbg_hdr_addr);
|
if (dbg_hdr.r_brk) {
|
||||||
DEBUG_CurrProcess->dbg_hdr_addr = (u_long)dyn.d_un.d_ptr;
|
DBG_VALUE value;
|
||||||
|
|
||||||
if (dbg_hdr.r_brk) {
|
DEBUG_Printf(DBG_CHN_TRACE, "Setting up a breakpoint on r_brk(%lx)\n",
|
||||||
DBG_VALUE value;
|
(unsigned long)dbg_hdr.r_brk);
|
||||||
|
|
||||||
DEBUG_Printf(DBG_CHN_TRACE, "Setting up a breakpoint on r_brk(%lx)\n",
|
DEBUG_SetBreakpoints(FALSE);
|
||||||
(unsigned long)dbg_hdr.r_brk);
|
value.type = NULL;
|
||||||
|
value.cookie = DV_TARGET;
|
||||||
|
value.addr.seg = 0;
|
||||||
|
value.addr.off = (DWORD)dbg_hdr.r_brk;
|
||||||
|
DEBUG_AddBreakpoint(&value, DEBUG_RescanElf);
|
||||||
|
DEBUG_SetBreakpoints(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_SetBreakpoints(FALSE);
|
dil = DEBUG_WalkList(&dbg_hdr);
|
||||||
value.type = NULL;
|
|
||||||
value.cookie = DV_TARGET;
|
|
||||||
value.addr.seg = 0;
|
|
||||||
value.addr.off = (DWORD)dbg_hdr.r_brk;
|
|
||||||
DEBUG_AddBreakpoint(&value, DEBUG_RescanElf);
|
|
||||||
DEBUG_SetBreakpoints(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
rtn = DEBUG_WalkList(&dbg_hdr);
|
leave:
|
||||||
|
return dil;
|
||||||
leave:
|
|
||||||
return rtn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !__ELF__ */
|
#else /* !__ELF__ */
|
||||||
|
|
||||||
int
|
int DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
||||||
DEBUG_ReadExecutableDbgInfo(const char* exe_name)
|
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,7 @@ static DBG_PROCESS* DEBUG_AddProcess(DWORD pid, HANDLE h)
|
||||||
p->num_threads = 0;
|
p->num_threads = 0;
|
||||||
p->continue_on_first_exception = FALSE;
|
p->continue_on_first_exception = FALSE;
|
||||||
p->modules = NULL;
|
p->modules = NULL;
|
||||||
|
p->num_modules = 0;
|
||||||
p->next_index = 0;
|
p->next_index = 0;
|
||||||
p->dbg_hdr_addr = 0;
|
p->dbg_hdr_addr = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue