Commit 62bf6ecc authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- now detecting Dwarf debug information in ELF modules (but don't load

it) - separated module management (pe.c, elf.c) from debug information management (stabs.c, msc.c) - worked around new wine-pthread and wine-kthread loaders (no longer use "wine" as default loader) - better convergence of gdb-proxy and winedbg for ELF handling - fixed ELF link-map walking - now using all loaded shared libs - (with the help of Robert Shearman) - added a bit of const correctness
parent d329f1be
......@@ -11,6 +11,7 @@ C_SRCS = \
break.c \
db_disasm.c \
display.c \
elf.c \
expr.c \
ext_debugger.c \
gdbproxy.c \
......@@ -19,6 +20,7 @@ C_SRCS = \
memory.c \
module.c \
msc.c \
pe.c \
registers.c \
source.c \
stabs.c \
......
......@@ -267,20 +267,20 @@ extern HANDLE DEBUG_hParserOutput;
#define DEBUG_WRITE_MEM_VERBOSE(addr, buf, len) \
(DEBUG_WRITE_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0))
enum DbgInfoLoad {DIL_DEFERRED, DIL_LOADED, DIL_NOINFO, DIL_ERROR};
enum DbgInfoLoad {DIL_DEFERRED, DIL_LOADED, DIL_NOINFO, DIL_NOT_SUPPORTED, DIL_ERROR};
enum DbgModuleType {DMT_UNKNOWN, DMT_ELF, DMT_NE, DMT_PE};
typedef struct tagDBG_MODULE {
void* load_addr;
unsigned long size;
char* module_name;
const char* module_name;
enum DbgInfoLoad dil;
enum DbgModuleType type;
unsigned short main : 1;
short int dbg_index;
HMODULE handle;
struct tagMSC_DBG_INFO* msc_info;
struct tagELF_DBG_INFO* elf_info;
struct tagMSC_DBG_INFO* msc_dbg_info;
struct tagELF_DBG_INFO* elf_dbg_info;
} DBG_MODULE;
typedef struct {
......@@ -335,6 +335,26 @@ extern int DEBUG_DelDisplay(int displaynum);
extern int DEBUG_InfoDisplay(void);
extern int DEBUG_EnableDisplay(int displaynum, int enable);
/* debugger/elf.c */
#define ELF_INFO_PATH 0x0001
#define ELF_INFO_DEBUG_HEADER 0x0002
#define ELF_INFO_SEGMENTS 0x0004
#define ELF_INFO_MODULE 0x0008
struct elf_info
{
unsigned flags;
char* elf_path; /* path to unix elf path, if ELF_INFO_PATH is set */
size_t elf_path_len;
void* load_addr; /* 32 bit linear addr, where ELF module is loaded */
unsigned long size; /* size of elf module (guessed) */
unsigned long dbg_hdr_addr; /* address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
unsigned long segments[3]; /* addresses of .text, .data and .bss segments (not filled yet) */
};
extern enum DbgInfoLoad DEBUG_ReadWineLoaderDbgInfo(HANDLE hProcess, struct elf_info* elf_info);
extern BOOL DEBUG_SetElfSoLoadBreakpoint(const struct elf_info* elf_info);
/* debugger/expr.c */
extern void DEBUG_FreeExprMem(void);
struct expr * DEBUG_IntVarExpr(const char* name);
......@@ -432,27 +452,34 @@ extern int DEBUG_PrintStringA(const DBG_ADDR* address, int len);
extern int DEBUG_PrintStringW(const DBG_ADDR* address, int len);
/* debugger/module.c */
extern DBG_MODULE* DEBUG_AddModule(const char* name, enum DbgModuleType type,
void* mod_addr, unsigned long size, HMODULE hmodule);
extern int DEBUG_LoadEntryPoints( const char * prefix );
extern void DEBUG_LoadModule32( const char* name, HANDLE hFile, void *base );
extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, enum DbgModuleType type);
extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, enum DbgModuleType type);
extern DBG_MODULE* DEBUG_FindModuleByAddr(void* addr, enum DbgModuleType type);
extern DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process);
extern DBG_MODULE* DEBUG_RegisterELFModule(void *load_addr, unsigned 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, void *load_addr);
extern void DEBUG_InfoShare(void);
/* debugger/msc.c */
extern void DEBUG_InitCVDataTypes(void);
extern enum DbgInfoLoad DEBUG_ProcessDebugDirectory( DBG_MODULE *module, const BYTE* file_map,
PIMAGE_DEBUG_DIRECTORY dbg, int nDbg );
/* debugger/pe.c */
extern void* DEBUG_MapDebugInfoFile(const char* name, DWORD offset, DWORD size,
HANDLE* hFile, HANDLE* hMap);
extern void DEBUG_UnmapDebugInfoFile(HANDLE hFile, HANDLE hMap, const void* addr);
extern void DEBUG_LoadPEModule( const char* name, HANDLE hFile, void *base );
extern enum DbgInfoLoad DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, HANDLE hFile,
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 enum DbgInfoLoad DEBUG_RegisterPEDebugInfo(DBG_MODULE* wmod, HANDLE hFile,
void* _nth, unsigned long nth_ofs);
/* debugger/registers.c */
extern void DEBUG_InfoRegisters(const CONTEXT* ctx);
......@@ -477,8 +504,7 @@ extern int DEBUG_GetCurrentFrame(struct name_hash ** name,
unsigned int * ebp);
/* debugger/stabs.c */
extern enum DbgInfoLoad DEBUG_ReadExecutableDbgInfo(const char* exe_name);
extern enum DbgInfoLoad DEBUG_ParseStabs(char * addr, void *load_offset,
extern enum DbgInfoLoad DEBUG_ParseStabs(const char* addr, void *load_offset,
unsigned int staboff, int stablen,
unsigned int strtaboff, int strtablen);
......
......@@ -102,8 +102,6 @@ struct gdb_context
unsigned long wine_segs[3]; /* load addresses of the ELF wine exec segments (text, bss and data) */
};
extern int read_elf_info(const char* filename, unsigned long tab[]);
/* =============================================== *
* B A S I C M A N I P U L A T I O N S *
* =============================================== *
......@@ -620,29 +618,6 @@ static void handle_debug_event(struct gdb_context* gdbctx, DEBUG_EVENT* de)
de->u.CreateProcessInfo.hThread,
de->u.CreateProcessInfo.lpStartAddress,
de->u.CreateProcessInfo.lpThreadLocalBase);
#if 0
DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile,
de->u.CreateProcessInfo.lpBaseOfImage);
if (buffer[0]) /* we got a process name */
{
DWORD type;
if (!GetBinaryTypeA( buffer, &type ))
{
/* not a Windows binary, assume it's a Unix executable then */
char unixname[MAX_PATH];
/* HACK!! should fix DEBUG_ReadExecutableDbgInfo to accept DOS filenames */
if (wine_get_unix_file_name( buffer, unixname, sizeof(unixname) ))
{
DEBUG_ReadExecutableDbgInfo( unixname );
break;
}
}
}
/* if it is a Windows binary, or an invalid or missing file name,
* we use wine itself as the main executable */
DEBUG_ReadExecutableDbgInfo( "wine" );
#endif
break;
case LOAD_DLL_DEBUG_EVENT:
......@@ -1980,7 +1955,7 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
int s_len = sizeof(s_addrs);
struct pollfd pollfd;
char wine_path[MAX_PATH];
char* ptr;
struct elf_info elf_info;
/* step 1: create socket for gdb connection request */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
......@@ -1995,11 +1970,16 @@ static BOOL gdb_startup(struct gdb_context* gdbctx, DEBUG_EVENT* de, unsigned fl
return FALSE;
/* step 2: find out wine executable location (as a Unix filename) */
ptr = getenv("WINELOADER");
strcpy(wine_path, ptr ? ptr : "wine");
elf_info.flags = ELF_INFO_PATH | ELF_INFO_SEGMENTS;
elf_info.elf_path = wine_path;
elf_info.elf_path_len = sizeof(wine_path);
if (DEBUG_ReadWineLoaderDbgInfo(de->u.CreateProcessInfo.hProcess, &elf_info) == DIL_ERROR)
return FALSE;
gdbctx->wine_segs[0] = elf_info.segments[0];
gdbctx->wine_segs[1] = elf_info.segments[1];
gdbctx->wine_segs[2] = elf_info.segments[2];
fprintf(stderr, "Using wine_path: %s\n", wine_path);
read_elf_info(wine_path, gdbctx->wine_segs);
/* step 3: fire up gdb (if requested) */
if (flags & 1)
......
......@@ -704,7 +704,7 @@ const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
module = DEBUG_FindModuleByAddr((void*)DEBUG_ToLinear(addr), DMT_UNKNOWN);
if (module) {
char *p, *name = module->module_name;
const char *p, *name = module->module_name;
if ((p = strrchr(name, '/'))) name = p + 1;
if ((p = strrchr(name, '\\'))) name = p + 1;
snprintf( modbuf, sizeof(modbuf), " in %s", name);
......
......@@ -140,7 +140,7 @@ void DEBUG_GetCurrentAddress( DBG_ADDR *addr )
void DEBUG_InvalAddr( const DBG_ADDR* addr )
{
DEBUG_Printf("*** Invalid address ");
DEBUG_PrintAddress(addr, DEBUG_CurrThread->dbg_mode, FALSE);
DEBUG_PrintAddress(addr, DEBUG_CurrThread ? DEBUG_CurrThread->dbg_mode : MODE_32, FALSE);
DEBUG_Printf("\n");
if (DBG_IVAR(ExtDbgOnInvalidAddress)) DEBUG_ExternalDebugger();
}
......
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* File module.c - module handling for the wine debugger
*
......@@ -34,8 +33,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
* Creates and links a new module to the current process
*
*/
static DBG_MODULE* DEBUG_AddModule(const char* name, enum DbgModuleType type,
void* mod_addr, unsigned long size, HMODULE hmodule)
DBG_MODULE* DEBUG_AddModule(const char* name, enum DbgModuleType type,
void* mod_addr, unsigned long size, HMODULE hmodule)
{
DBG_MODULE* wmod;
......@@ -52,6 +51,7 @@ static DBG_MODULE* DEBUG_AddModule(const char* name, enum DbgModuleType type,
wmod->handle = hmodule;
wmod->dbg_index = DEBUG_CurrProcess->next_index;
wmod->module_name = DBG_strdup(name);
DEBUG_CurrProcess->next_index++;
DEBUG_CurrProcess->modules = DBG_realloc(DEBUG_CurrProcess->modules,
++DEBUG_CurrProcess->num_modules * sizeof(DBG_MODULE*));
......@@ -130,39 +130,6 @@ DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
return process->modules[0];
}
/***********************************************************************
* 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(void *load_addr, unsigned long size, const char* name)
{
DBG_MODULE* wmod = DEBUG_AddModule(name, DMT_ELF, load_addr, size, 0);
if (!wmod) return NULL;
DEBUG_CurrProcess->next_index++;
return wmod;
}
/***********************************************************************
* DEBUG_RegisterPEModule
*
*/
static DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, void *load_addr,
unsigned long size, const char *module_name)
{
DBG_MODULE* wmod = DEBUG_AddModule(module_name, DMT_PE, load_addr, size, hModule);
if (!wmod) return NULL;
DEBUG_CurrProcess->next_index++;
return wmod;
}
#if 0
/***********************************************************************
* DEBUG_RegisterNEModule
......@@ -273,152 +240,6 @@ static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleA
#endif
/***********************************************************************
* DEBUG_LoadModule32
*/
void DEBUG_LoadModule32(const char* name, HANDLE hFile, void *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( (char *)base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew),
&nth_ofs, sizeof(nth_ofs)) ||
!DEBUG_READ_MEM_VERBOSE( (char *)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( (char *)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);
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;
char buffer[512];
char bufstr[256];
unsigned int i;
IMAGE_SECTION_HEADER pe_seg;
DWORD pe_seg_ofs;
IMAGE_DATA_DIRECTORY dir;
DWORD dir_ofs;
const char* prefix;
IMAGE_NT_HEADERS* nth = (PIMAGE_NT_HEADERS)_nth;
void * base = wmod->load_addr;
value.type = NULL;
value.cookie = DV_TARGET;
value.addr.seg = 0;
value.addr.off = 0;
/* Add start of DLL */
value.addr.off = (unsigned long)base;
if ((prefix = strrchr(wmod->module_name, '\\' ))) prefix++;
else prefix = wmod->module_name;
DEBUG_AddSymbol(prefix, &value, NULL, SYM_WIN32 | SYM_FUNC);
/* Add entry point */
snprintf(buffer, sizeof(buffer), "%s.EntryPoint", prefix);
value.addr.off = (unsigned long)base + nth->OptionalHeader.AddressOfEntryPoint;
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
/* Add start of sections */
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( (char *)base + pe_seg_ofs, &pe_seg, sizeof(pe_seg)))
continue;
snprintf(buffer, sizeof(buffer), "%s.%s", prefix, pe_seg.Name);
value.addr.off = (unsigned long)base + pe_seg.VirtualAddress;
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
}
/* Add exported functions */
dir_ofs = nth_ofs +
OFFSET_OF(IMAGE_NT_HEADERS,
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
if (DEBUG_READ_MEM_VERBOSE( (char *)base + dir_ofs, &dir, sizeof(dir)) && dir.Size) {
IMAGE_EXPORT_DIRECTORY exports;
WORD* ordinals = NULL;
void** functions = NULL;
DWORD* names = NULL;
unsigned int j;
if (DEBUG_READ_MEM_VERBOSE( (char *)base + dir.VirtualAddress,
&exports, sizeof(exports)) &&
((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
DEBUG_READ_MEM_VERBOSE( (char *)base + exports.AddressOfFunctions,
functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
DEBUG_READ_MEM_VERBOSE( (char *)base + (DWORD)exports.AddressOfNameOrdinals,
ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
DEBUG_READ_MEM_VERBOSE( (char *)base + (DWORD)exports.AddressOfNames,
names, sizeof(names[0]) * exports.NumberOfNames)) {
for (i = 0; i < exports.NumberOfNames; i++) {
if (!names[i] ||
!DEBUG_READ_MEM_VERBOSE( (char *)base + names[i], bufstr, sizeof(bufstr)))
continue;
bufstr[sizeof(bufstr) - 1] = 0;
snprintf(buffer, sizeof(buffer), "%s.%s", prefix, bufstr);
value.addr.off = (unsigned long)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;
snprintf(buffer, sizeof(buffer), "%s.%ld", prefix, i + exports.Base);
value.addr.off = (unsigned long)base + (DWORD)functions[i];
DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
}
}
DBG_free(functions);
DBG_free(ordinals);
DBG_free(names);
}
/* no real debug info, only entry points */
return DIL_NOINFO;
}
/***********************************************************************
* DEBUG_LoadEntryPoints
*
* Load the entry points of all the modules into the hash table.
......@@ -484,6 +305,9 @@ void DEBUG_ReportDIL(enum DbgInfoLoad dil, const char* pfx, const char* filename
case DIL_NOINFO:
fmt = "No debug information in %s '%s' (%p)\n";
break;
case DIL_NOT_SUPPORTED:
fmt = "Unsupported debug information in %s '%s' (%p)\n";
break;
case DIL_ERROR:
fmt = "Can't find file for %s '%s' (%p)\n";
break;
......@@ -508,11 +332,12 @@ static const char* DEBUG_GetModuleType(enum DbgModuleType type)
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 "?";
case DIL_LOADED: return "loaded";
case DIL_DEFERRED: return "deferred";
case DIL_NOINFO: return "none";
case DIL_NOT_SUPPORTED: return "not supported";
case DIL_ERROR: return "error";
default: return "?";
}
}
......
......@@ -674,8 +674,8 @@ static DWORD DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOO
static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
{
char buffer[256];
DWORD cont = DBG_CONTINUE;
char buffer[256];
DWORD cont = DBG_CONTINUE;
DEBUG_CurrPid = de->dwProcessId;
DEBUG_CurrTid = de->dwThreadId;
......@@ -782,24 +782,30 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
WINE_ERR("Couldn't create thread\n");
break;
}
DEBUG_InitCurrProcess();
DEBUG_InitCurrThread();
/* module is either PE, NE or ELF module (for WineLib), but all
* are loaded with wine, so load its symbols, then the main module
*/
do
else
{
char* ptr = getenv("WINELOADER");
struct elf_info elf_info;
if (!ptr || DEBUG_ReadExecutableDbgInfo( ptr ) == DIL_ERROR)
DEBUG_ReadExecutableDbgInfo( "wine" );
} while (0);
DEBUG_InitCurrProcess();
DEBUG_InitCurrThread();
DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile,
de->u.CreateProcessInfo.lpBaseOfImage);
elf_info.flags = ELF_INFO_MODULE;
if (DEBUG_ReadWineLoaderDbgInfo(DEBUG_CurrProcess->handle, &elf_info) != DIL_ERROR &&
DEBUG_SetElfSoLoadBreakpoint(&elf_info))
{
/* then load the main module's symbols */
DEBUG_LoadPEModule(DEBUG_CurrProcess->imageName,
de->u.CreateProcessInfo.hFile,
de->u.CreateProcessInfo.lpBaseOfImage);
}
else
{
DEBUG_DelThread(DEBUG_CurrProcess->threads);
DEBUG_DelProcess(DEBUG_CurrProcess);
DEBUG_Printf("Couldn't load process\n");
}
}
break;
case EXIT_THREAD_DEBUG_EVENT:
......@@ -850,7 +856,7 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
de->u.LoadDll.dwDebugInfoFileOffset,
de->u.LoadDll.nDebugInfoSize);
_strupr(buffer);
DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, de->u.LoadDll.lpBaseOfDll);
DEBUG_LoadPEModule(buffer, de->u.LoadDll.hFile, de->u.LoadDll.lpBaseOfDll);
DEBUG_CheckDelayedBP();
if (DBG_IVAR(BreakOnDllLoad))
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment