winedbg (take 2)
Eric Pouech
pouech-eric at wanadoo.fr
Mon Feb 2 16:09:18 CST 2004
Robert Shearman did some more tests on my previous patch, which ended up
with two bugs. So, here's the new patch with the two one-liners to make
it more correct.
Alexandre, please use this one instead.
A+
-------------- next part --------------
Name: wd_load
ChangeLog:
- 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)
(stronger detection at run-time that debuggee's loader is what winedbg thinks it is)
- 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 R Shearman)
- added a bit of const correctness
License: X11
GenDate: 2004/02/02 22:06:35 UTC
ModifiedFiles: programs/winedbg/Makefile.in programs/winedbg/debugger.h programs/winedbg/gdbproxy.c programs/winedbg/hash.c programs/winedbg/memory.c programs/winedbg/module.c programs/winedbg/msc.c programs/winedbg/stabs.c programs/winedbg/winedbg.c
AddedFiles: programs/winedbg/elf.c programs/winedbg/pe.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/Makefile.in,v
retrieving revision 1.2
diff -u -u -r1.2 Makefile.in
--- programs/winedbg/Makefile.in 15 Dec 2002 01:19:53 -0000 1.2
+++ programs/winedbg/Makefile.in 25 Jan 2004 14:13:05 -0000
@@ -11,6 +11,7 @@
break.c \
db_disasm.c \
display.c \
+ elf.c \
expr.c \
ext_debugger.c \
gdbproxy.c \
@@ -19,6 +20,7 @@
memory.c \
module.c \
msc.c \
+ pe.c \
registers.c \
source.c \
stabs.c \
Index: programs/winedbg/debugger.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/debugger.h,v
retrieving revision 1.16
diff -u -u -r1.16 debugger.h
--- programs/winedbg/debugger.h 15 Dec 2003 19:53:08 -0000 1.16
+++ programs/winedbg/debugger.h 1 Feb 2004 09:47:03 -0000
@@ -267,20 +267,20 @@
#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_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_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 @@
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);
Index: programs/winedbg/gdbproxy.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/gdbproxy.c,v
retrieving revision 1.16
diff -u -u -r1.16 gdbproxy.c
--- programs/winedbg/gdbproxy.c 15 Dec 2003 19:53:08 -0000 1.16
+++ programs/winedbg/gdbproxy.c 31 Jan 2004 11:00:13 -0000
@@ -102,8 +102,6 @@
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 @@
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 @@
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 @@
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)
Index: programs/winedbg/hash.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/hash.c,v
retrieving revision 1.15
diff -u -u -r1.15 hash.c
--- programs/winedbg/hash.c 15 Dec 2003 19:53:08 -0000 1.15
+++ programs/winedbg/hash.c 1 Feb 2004 08:43:49 -0000
@@ -704,7 +704,7 @@
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);
Index: programs/winedbg/memory.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/memory.c,v
retrieving revision 1.6
diff -u -u -r1.6 memory.c
--- programs/winedbg/memory.c 15 Dec 2003 19:53:08 -0000 1.6
+++ programs/winedbg/memory.c 31 Jan 2004 08:58:04 -0000
@@ -140,7 +140,7 @@
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();
}
Index: programs/winedbg/module.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/module.c,v
retrieving revision 1.5
diff -u -u -r1.5 module.c
--- programs/winedbg/module.c 15 Dec 2003 19:53:08 -0000 1.5
+++ programs/winedbg/module.c 25 Jan 2004 14:27:56 -0000
@@ -1,4 +1,3 @@
-/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
* File module.c - module handling for the wine debugger
*
@@ -34,8 +33,8 @@
* 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 @@
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 @@
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 @@
#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 @@
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_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 "?";
}
}
Index: programs/winedbg/msc.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/msc.c,v
retrieving revision 1.6
diff -u -u -r1.6 msc.c
--- programs/winedbg/msc.c 15 Dec 2003 19:53:08 -0000 1.6
+++ programs/winedbg/msc.c 1 Feb 2004 08:56:00 -0000
@@ -79,83 +79,6 @@
return EXCEPTION_CONTINUE_SEARCH;
}
-/***********************************************************************
- * DEBUG_LocateDebugInfoFile
- *
- * NOTE: dbg_filename must be at least MAX_PATHNAME_LEN bytes in size
- */
-static void DEBUG_LocateDebugInfoFile(const char *filename, char *dbg_filename)
-{
- char *str1 = DBG_alloc(MAX_PATHNAME_LEN);
- char *str2 = DBG_alloc(MAX_PATHNAME_LEN*10);
- const char *file;
- char *name_part;
-
- file = strrchr(filename, '\\');
- if( file == NULL ) file = filename; else file++;
-
- if ((GetEnvironmentVariable("_NT_SYMBOL_PATH", str1, MAX_PATHNAME_LEN) &&
- (SearchPath(str1, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part))) ||
- (GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", str1, MAX_PATHNAME_LEN) &&
- (SearchPath(str1, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part))) ||
- (SearchPath(NULL, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part)))
- lstrcpyn(dbg_filename, str2, MAX_PATHNAME_LEN);
- else
- lstrcpyn(dbg_filename, filename, MAX_PATHNAME_LEN);
- DBG_free(str1);
- DBG_free(str2);
-}
-
-/***********************************************************************
- * DEBUG_MapDebugInfoFile
- */
-static void* DEBUG_MapDebugInfoFile(const char* name, DWORD offset, DWORD size,
- HANDLE* hFile, HANDLE* hMap)
-{
- DWORD g_offset; /* offset aligned on map granuality */
- DWORD g_size; /* size to map, with offset aligned */
- char* ret;
-
- *hMap = 0;
-
- if (name != NULL) {
- char filename[MAX_PATHNAME_LEN];
-
- DEBUG_LocateDebugInfoFile(name, filename);
- if ((*hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
- return NULL;
- }
-
- if (!size) {
- DWORD file_size = GetFileSize(*hFile, NULL);
- if (file_size == (DWORD)-1) return NULL;
- size = file_size - offset;
- }
-
- g_offset = offset & ~0xFFFF; /* FIXME: is granularity portable ? */
- g_size = offset + size - g_offset;
-
- if ((*hMap = CreateFileMapping(*hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == 0)
- return NULL;
-
- if ((ret = MapViewOfFile(*hMap, FILE_MAP_READ, 0, g_offset, g_size)) != NULL)
- ret += offset - g_offset;
-
- return ret;
-}
-
-/***********************************************************************
- * DEBUG_UnmapDebugInfoFile
- */
-static void DEBUG_UnmapDebugInfoFile(HANDLE hFile, HANDLE hMap, void* addr)
-{
- if (addr) UnmapViewOfFile(addr);
- if (hMap) CloseHandle(hMap);
- if (hFile!=INVALID_HANDLE_VALUE) CloseHandle(hFile);
-}
-
-
-
/*========================================================================
* Process COFF debug information.
*/
@@ -234,7 +157,7 @@
coff_file->entries[coff_file->neps++] = sym;
}
-static enum DbgInfoLoad DEBUG_ProcessCoff( DBG_MODULE *module, LPBYTE root )
+static enum DbgInfoLoad DEBUG_ProcessCoff( DBG_MODULE *module, const BYTE* root )
{
PIMAGE_AUX_SYMBOL aux;
PIMAGE_COFF_SYMBOLS_HEADER coff;
@@ -369,7 +292,7 @@
&& (naux == 0)
&& (coff_sym->SectionNumber == 1) )
{
- DWORD base = module->msc_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
+ DWORD base = module->msc_dbg_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
/*
* This is a normal static function when naux == 0.
* Just register it. The current file is the correct
@@ -396,7 +319,7 @@
&& (coff_sym->SectionNumber > 0) )
{
const char* this_file = NULL;
- DWORD base = module->msc_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
+ DWORD base = module->msc_dbg_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
nampnt = DEBUG_GetCoffName( coff_sym, coff_strtab );
new_value.addr.seg = 0;
@@ -405,7 +328,7 @@
WINE_TRACE_(winedbg_msc)("%d: %lx %s\n", i, new_value.addr.off, nampnt);
WINE_TRACE_(winedbg_msc)(
"\tAdding global symbol %s (sect=%s)\n",
- nampnt, module->msc_info->sectp[coff_sym->SectionNumber - 1].Name);
+ nampnt, module->msc_dbg_info->sectp[coff_sym->SectionNumber - 1].Name);
/*
* Now we need to figure out which file this guy belongs to.
@@ -432,7 +355,7 @@
if( (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
&& (coff_sym->SectionNumber > 0) )
{
- DWORD base = module->msc_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
+ DWORD base = module->msc_dbg_info->sectp[coff_sym->SectionNumber - 1].VirtualAddress;
/*
* Similar to above, but for the case of data symbols.
* These aren't treated as entrypoints.
@@ -1760,10 +1683,10 @@
union any_size
{
- char * c;
- short * s;
- int * i;
- unsigned int * ui;
+ const char* c;
+ const short* s;
+ const int* i;
+ const unsigned int* ui;
};
struct startend
@@ -1778,18 +1701,18 @@
unsigned int segno;
unsigned int start;
unsigned int end;
- char * sourcefile;
- unsigned short * linetab;
- unsigned int * offtab;
+ const char * sourcefile;
+ const unsigned short * linetab;
+ const unsigned int * offtab;
};
static struct codeview_linetab_hdr *
-DEBUG_SnarfLinetab(char * linetab,
+DEBUG_SnarfLinetab(const char * linetab,
int size)
{
int file_segcount;
char filename[PATH_MAX];
- unsigned int * filetab;
+ const unsigned int * filetab;
char * fn;
int i;
int k;
@@ -1809,7 +1732,7 @@
nfile = *pnt.s++;
nseg = *pnt.s++;
- filetab = (unsigned int *) pnt.c;
+ filetab = (const unsigned int *) pnt.c;
/*
* Now count up the number of segments in the file.
@@ -2049,8 +1972,8 @@
static unsigned int
DEBUG_MapCVOffset( DBG_MODULE *module, unsigned int offset )
{
- int nomap = module->msc_info->nomap;
- OMAP_DATA *omapp = module->msc_info->omapp;
+ int nomap = module->msc_dbg_info->nomap;
+ OMAP_DATA *omapp = module->msc_dbg_info->omapp;
int i;
if ( !nomap || !omapp )
@@ -2070,8 +1993,8 @@
int size, int cookie, int flags,
struct codeview_linetab_hdr *linetab )
{
- int nsect = module->msc_info->nsect;
- PIMAGE_SECTION_HEADER sectp = module->msc_info->sectp;
+ int nsect = module->msc_dbg_info->nsect;
+ PIMAGE_SECTION_HEADER sectp = module->msc_dbg_info->sectp;
struct name_hash *symbol;
char symname[PATH_MAX];
@@ -2162,7 +2085,7 @@
}
static int
-DEBUG_SnarfCodeView( DBG_MODULE *module, LPBYTE root, int offset, int size,
+DEBUG_SnarfCodeView( DBG_MODULE *module, const BYTE* root, int offset, int size,
struct codeview_linetab_hdr *linetab )
{
struct name_hash *curr_func = NULL;
@@ -2788,7 +2711,7 @@
#define sstSrcModule 0x127
-static enum DbgInfoLoad DEBUG_ProcessCodeView( DBG_MODULE *module, LPBYTE root )
+static enum DbgInfoLoad DEBUG_ProcessCodeView( DBG_MODULE *module, const BYTE* root )
{
PCODEVIEW_HEADER cv = (PCODEVIEW_HEADER)root;
enum DbgInfoLoad dil = DIL_ERROR;
@@ -2860,10 +2783,8 @@
/*========================================================================
* Process debug directory.
*/
-static enum DbgInfoLoad DEBUG_ProcessDebugDirectory( DBG_MODULE *module,
- LPBYTE file_map,
- PIMAGE_DEBUG_DIRECTORY dbg,
- int nDbg )
+enum DbgInfoLoad DEBUG_ProcessDebugDirectory( DBG_MODULE *module, const BYTE* file_map,
+ PIMAGE_DEBUG_DIRECTORY dbg, int nDbg )
{
enum DbgInfoLoad dil;
int i;
@@ -2874,8 +2795,8 @@
{
if ( dbg[i].Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC )
{
- module->msc_info->nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
- module->msc_info->omapp = (OMAP_DATA *)(file_map + dbg[i].PointerToRawData);
+ module->msc_dbg_info->nomap = dbg[i].SizeOfData / sizeof(OMAP_DATA);
+ module->msc_dbg_info->omapp = (OMAP_DATA *)(file_map + dbg[i].PointerToRawData);
break;
}
}
@@ -2932,214 +2853,3 @@
}
-/*========================================================================
- * Process DBG file.
- */
-static enum DbgInfoLoad DEBUG_ProcessDBGFile( DBG_MODULE *module,
- const char *filename, DWORD timestamp )
-{
- enum DbgInfoLoad dil = DIL_ERROR;
- HANDLE hFile = INVALID_HANDLE_VALUE, hMap = 0;
- LPBYTE file_map = NULL;
- PIMAGE_SEPARATE_DEBUG_HEADER hdr;
- PIMAGE_DEBUG_DIRECTORY dbg;
- int nDbg;
-
- WINE_TRACE("Processing DBG file %s\n", filename);
-
- file_map = DEBUG_MapDebugInfoFile( filename, 0, 0, &hFile, &hMap );
- if ( !file_map )
- {
- WINE_ERR("-Unable to peruse .DBG file %s\n", filename);
- goto leave;
- }
-
- hdr = (PIMAGE_SEPARATE_DEBUG_HEADER) file_map;
-
- if ( hdr->TimeDateStamp != timestamp )
- {
- WINE_ERR("Warning - %s has incorrect internal timestamp\n", filename);
- /*
- * Well, sometimes this happens to DBG files which ARE REALLY the right .DBG
- * files but nonetheless this check fails. Anyway, WINDBG (debugger for
- * Windows by Microsoft) loads debug symbols which have incorrect timestamps.
- */
- }
-
-
- dbg = (PIMAGE_DEBUG_DIRECTORY) ( file_map + sizeof(*hdr)
- + hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER)
- + hdr->ExportedNamesSize );
-
- nDbg = hdr->DebugDirectorySize / sizeof(*dbg);
-
- dil = DEBUG_ProcessDebugDirectory( module, file_map, dbg, nDbg );
-
-
- leave:
- DEBUG_UnmapDebugInfoFile( hFile, hMap, file_map );
- return dil;
-}
-
-
-/*========================================================================
- * Process MSC debug information in PE file.
- */
-enum DbgInfoLoad DEBUG_RegisterMSCDebugInfo( DBG_MODULE *module, HANDLE hFile,
- void *_nth, unsigned long nth_ofs )
-{
- enum DbgInfoLoad dil = DIL_ERROR;
- PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
- PIMAGE_DATA_DIRECTORY dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
- PIMAGE_DEBUG_DIRECTORY dbg = NULL;
- int nDbg;
- MSC_DBG_INFO extra_info = { 0, NULL, 0, NULL };
- HANDLE hMap = 0;
- LPBYTE file_map = NULL;
-
-
- /* Read in section data */
-
- module->msc_info = &extra_info;
- extra_info.nsect = nth->FileHeader.NumberOfSections;
- extra_info.sectp = DBG_alloc( extra_info.nsect * sizeof(IMAGE_SECTION_HEADER) );
- if ( !extra_info.sectp )
- goto leave;
-
- if ( !DEBUG_READ_MEM_VERBOSE( (char *)module->load_addr +
- nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
- nth->FileHeader.SizeOfOptionalHeader,
- extra_info.sectp,
- extra_info.nsect * sizeof(IMAGE_SECTION_HEADER) ) )
- goto leave;
-
- /* Read in debug directory */
-
- nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
- if ( !nDbg )
- goto leave;
-
- dbg = (PIMAGE_DEBUG_DIRECTORY) DBG_alloc( nDbg * sizeof(IMAGE_DEBUG_DIRECTORY) );
- if ( !dbg )
- goto leave;
-
- if ( !DEBUG_READ_MEM_VERBOSE( (char *)module->load_addr + dir->VirtualAddress,
- dbg, nDbg * sizeof(IMAGE_DEBUG_DIRECTORY) ) )
- goto leave;
-
-
- /* Map in PE file */
- file_map = DEBUG_MapDebugInfoFile( NULL, 0, 0, &hFile, &hMap );
- if ( !file_map )
- goto leave;
-
-
- /* Parse debug directory */
-
- if ( nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED )
- {
- /* Debug info is stripped to .DBG file */
-
- PIMAGE_DEBUG_MISC misc = (PIMAGE_DEBUG_MISC)(file_map + dbg->PointerToRawData);
-
- if ( nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC
- || misc->DataType != IMAGE_DEBUG_MISC_EXENAME )
- {
- WINE_ERR("-Debug info stripped, but no .DBG file in module %s\n",
- module->module_name );
- goto leave;
- }
-
- dil = DEBUG_ProcessDBGFile( module, misc->Data, nth->FileHeader.TimeDateStamp );
- }
- else
- {
- /* Debug info is embedded into PE module */
- /* FIXME: the nDBG information we're manipulating comes from the debuggee
- * address space. However, the following code will be made against the
- * version mapped in the debugger address space. There are cases (for example
- * when the PE sections are compressed in the file and become decompressed
- * in the debuggee address space) where the two don't match.
- * Therefore, redo the DBG information lookup with the mapped data
- */
- PIMAGE_NT_HEADERS mpd_nth = (PIMAGE_NT_HEADERS)(file_map + nth_ofs);
- PIMAGE_DATA_DIRECTORY mpd_dir;
- PIMAGE_DEBUG_DIRECTORY mpd_dbg = NULL;
-
- /* sanity checks */
- if ( mpd_nth->Signature != IMAGE_NT_SIGNATURE ||
- mpd_nth->FileHeader.NumberOfSections != nth->FileHeader.NumberOfSections ||
- (mpd_nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0)
- goto leave;
- mpd_dir = mpd_nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
-
- if ((mpd_dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY)) != nDbg)
- goto leave;
-
- mpd_dbg = (PIMAGE_DEBUG_DIRECTORY)(file_map + mpd_dir->VirtualAddress);
-
- dil = DEBUG_ProcessDebugDirectory( module, file_map, mpd_dbg, nDbg );
- }
-
-
- leave:
- module->msc_info = NULL;
-
- DEBUG_UnmapDebugInfoFile( 0, hMap, file_map );
- if ( extra_info.sectp ) DBG_free( extra_info.sectp );
- if ( dbg ) DBG_free( dbg );
- return dil;
-}
-
-
-/*========================================================================
- * look for stabs information in PE header (it's how mingw compiler provides its
- * debugging information), and also wine PE <-> ELF linking through .wsolnk sections
- */
-enum DbgInfoLoad DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, HANDLE hFile,
- void* _nth, unsigned long nth_ofs)
-{
- IMAGE_SECTION_HEADER pe_seg;
- unsigned long pe_seg_ofs;
- int i, stabsize = 0, stabstrsize = 0;
- unsigned int stabs = 0, stabstr = 0;
- PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
- enum DbgInfoLoad dil = DIL_ERROR;
-
- pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
- nth->FileHeader.SizeOfOptionalHeader;
-
- for (i = 0; i < nth->FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
- if (!DEBUG_READ_MEM_VERBOSE((void*)((char *)module->load_addr + pe_seg_ofs),
- &pe_seg, sizeof(pe_seg)))
- continue;
-
- if (!strcasecmp(pe_seg.Name, ".stab")) {
- stabs = pe_seg.VirtualAddress;
- stabsize = pe_seg.SizeOfRawData;
- } else if (!strncasecmp(pe_seg.Name, ".stabstr", 8)) {
- stabstr = pe_seg.VirtualAddress;
- stabstrsize = pe_seg.SizeOfRawData;
- }
- }
-
- if (stabstrsize && stabsize) {
- char* s1 = DBG_alloc(stabsize+stabstrsize);
-
- if (s1) {
- if (DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabs, s1, stabsize) &&
- DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabstr,
- s1 + stabsize, stabstrsize)) {
- dil = DEBUG_ParseStabs(s1, 0, 0, stabsize, stabsize, stabstrsize);
- } else {
- DEBUG_Printf("couldn't read data block\n");
- }
- DBG_free(s1);
- } else {
- DEBUG_Printf("couldn't alloc %d bytes\n", stabsize + stabstrsize);
- }
- } else {
- dil = DIL_NOINFO;
- }
- return dil;
-}
Index: programs/winedbg/stabs.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/stabs.c,v
retrieving revision 1.11
diff -u -u -r1.11 stabs.c
--- programs/winedbg/stabs.c 15 Dec 2003 19:53:08 -0000 1.11
+++ programs/winedbg/stabs.c 1 Feb 2004 09:47:44 -0000
@@ -56,22 +56,9 @@
#define __ELF__
#endif
-#ifdef __ELF__
-#ifdef HAVE_ELF_H
-# include <elf.h>
-#endif
-#ifdef HAVE_LINK_H
-# include <link.h>
-#endif
-#ifdef HAVE_SYS_LINK_H
-# include <sys/link.h>
-#endif
-#endif
-
#include "wine/debug.h"
-WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
-WINE_DECLARE_DEBUG_CHANNEL(winedbg_stabs);
+WINE_DEFAULT_DEBUG_CHANNEL(winedbg_stabs);
#ifndef N_UNDF
#define N_UNDF 0x00
@@ -100,11 +87,6 @@
#define N_EXCL 0xc2
#define N_RBRAC 0xe0
-typedef struct tagELF_DBG_INFO
-{
- void *elf_addr;
-} ELF_DBG_INFO;
-
struct stab_nlist {
union {
char *n_name;
@@ -235,7 +217,7 @@
{
struct datatype** ret;
- WINE_TRACE_(winedbg_stabs)("creating type id for (%d,%d)\n", filenr, subnr);
+ WINE_TRACE("creating type id for (%d,%d)\n", filenr, subnr);
/* FIXME: I could perhaps create a dummy include_def for each compilation
* unit which would allow not to handle those two cases separately
@@ -266,24 +248,25 @@
}
ret = &idef->vector[subnr];
}
- WINE_TRACE_(winedbg_stabs)("(%d,%d) is %p\n",filenr,subnr,ret);
+ WINE_TRACE("(%d,%d) is %p\n",filenr,subnr,ret);
return ret;
}
static
struct datatype**
-DEBUG_ReadTypeEnum(char **x) {
+DEBUG_ReadTypeEnum(LPCSTR *x)
+{
int filenr,subnr;
if (**x=='(') {
(*x)++; /* '(' */
- filenr=strtol(*x,x,10); /* <int> */
+ filenr=strtol(*x,(char**)x,10); /* <int> */
(*x)++; /* ',' */
- subnr=strtol(*x,x,10); /* <int> */
+ subnr=strtol(*x,(char**)x,10); /* <int> */
(*x)++; /* ')' */
} else {
filenr = 0;
- subnr = strtol(*x,x,10); /* <int> */
+ subnr = strtol(*x,(char**)x,10); /* <int> */
}
return DEBUG_FileSubNr2StabEnum(filenr,subnr);
}
@@ -291,7 +274,7 @@
/*#define PTS_DEBUG*/
struct ParseTypedefData
{
- char* ptr;
+ const char* ptr;
char buf[1024];
int idx;
#ifdef PTS_DEBUG
@@ -322,7 +305,7 @@
static int DEBUG_PTS_ReadID(struct ParseTypedefData* ptd)
{
- char* first = ptd->ptr;
+ const char* first = ptd->ptr;
unsigned int len;
PTS_ABORTIF(ptd, (ptd->ptr = strchr(ptd->ptr, ':')) == NULL);
@@ -611,7 +594,7 @@
if (*++ptd->ptr == 's') {
ptd->ptr++;
if (DEBUG_PTS_ReadNum(ptd, &sz) == -1) {
- WINE_ERR_(winedbg_stabs)("Not an attribute... NIY\n");
+ WINE_ERR("Not an attribute... NIY\n");
ptd->ptr -= 2;
return -1;
}
@@ -669,7 +652,7 @@
*DEBUG_FileSubNr2StabEnum(filenr1, subnr1) = new_dt;
} else {
if (DEBUG_GetType(dt1) != DT_STRUCT) {
- WINE_ERR_(winedbg_stabs)("Forward declaration is not an aggregate\n");
+ WINE_ERR("Forward declaration is not an aggregate\n");
return -1;
}
@@ -784,7 +767,7 @@
}
break;
default:
- WINE_ERR_(winedbg_stabs)("Unknown type '%c'\n", ptd->ptr[-1]);
+ WINE_ERR("Unknown type '%c'\n", ptd->ptr[-1]);
return -1;
}
}
@@ -809,7 +792,7 @@
return 0;
}
-static int DEBUG_ParseTypedefStab(char* ptr, const char* typename)
+static int DEBUG_ParseTypedefStab(const char* ptr, const char* typename)
{
struct ParseTypedefData ptd;
struct datatype* dt;
@@ -838,20 +821,20 @@
if (ret == -1 || *ptd.ptr) {
#ifdef PTS_DEBUG
int i;
- WINE_TRACE_(winedbg_stabs)("Failure on %s\n", ptr);
+ WINE_TRACE("Failure on %s\n", ptr);
if (ret == -1)
{
for (i = 0; i < ptd.err_idx; i++)
{
- WINE_TRACE_(winedbg_stabs)("[%d]: line %d => %s\n",
- i, ptd.errors[i].line, ptd.errors[i].ptr);
+ WINE_TRACE("[%d]: line %d => %s\n",
+ i, ptd.errors[i].line, ptd.errors[i].ptr);
}
}
else
- WINE_TRACE_(winedbg_stabs)("[0]: => %s\n", ptd.ptr);
+ WINE_TRACE("[0]: => %s\n", ptd.ptr);
#else
- WINE_ERR_(winedbg_stabs)("Failure on %s at %s\n", ptr, ptd.ptr);
+ WINE_ERR("Failure on %s at %s\n", ptr, ptd.ptr);
#endif
return FALSE;
}
@@ -859,8 +842,8 @@
return TRUE;
}
-static struct datatype *
-DEBUG_ParseStabType(const char * stab)
+static struct datatype*
+DEBUG_ParseStabType(const char* stab)
{
const char* c = stab - 1;
@@ -888,31 +871,31 @@
* The next is either an integer or a (integer,integer).
* The DEBUG_ReadTypeEnum takes care that stab_types is large enough.
*/
- return *DEBUG_ReadTypeEnum((char**)&c);
+ return *DEBUG_ReadTypeEnum(&c);
}
-enum DbgInfoLoad DEBUG_ParseStabs(char * addr, void *load_offset,
+enum DbgInfoLoad DEBUG_ParseStabs(const char* addr, void* load_offset,
unsigned int staboff, int stablen,
unsigned int strtaboff, int strtablen)
{
- struct name_hash * curr_func = NULL;
- struct wine_locals * curr_loc = NULL;
- struct name_hash * curr_sym = NULL;
- char currpath[PATH_MAX];
- int i;
- int in_external_file = FALSE;
- int last_nso = -1;
- unsigned int len;
- DBG_VALUE new_value;
- int nstab;
- char * ptr;
- char * stabbuff;
- unsigned int stabbufflen;
- struct stab_nlist * stab_ptr;
- char * strs;
- int strtabinc;
- char * subpath = NULL;
- char symname[4096];
+ struct name_hash* curr_func = NULL;
+ struct wine_locals* curr_loc = NULL;
+ struct name_hash* curr_sym = NULL;
+ char currpath[PATH_MAX];
+ int i;
+ int in_external_file = FALSE;
+ int last_nso = -1;
+ unsigned int len;
+ DBG_VALUE new_value;
+ int nstab;
+ const char* ptr;
+ char* stabbuff;
+ unsigned int stabbufflen;
+ const struct stab_nlist* stab_ptr;
+ const char* strs;
+ int strtabinc;
+ const char* subpath = NULL;
+ char symname[4096];
nstab = stablen / sizeof(struct stab_nlist);
stab_ptr = (struct stab_nlist *) (addr + staboff);
@@ -1200,15 +1183,15 @@
*/
break;
default:
- WINE_ERR_(winedbg_stabs)("Unknown stab type 0x%02x\n", stab_ptr->n_type);
+ WINE_ERR("Unknown stab type 0x%02x\n", stab_ptr->n_type);
break;
}
stabbuff[0] = '\0';
- WINE_TRACE_(winedbg_stabs)("0x%02x %x %s\n", stab_ptr->n_type,
- (unsigned int) stab_ptr->n_value,
- strs + (unsigned int) stab_ptr->n_un.n_name);
+ WINE_TRACE("0x%02x %x %s\n", stab_ptr->n_type,
+ (unsigned int) stab_ptr->n_value,
+ strs + (unsigned int) stab_ptr->n_un.n_name);
}
DEBUG_FreeIncludes();
@@ -1216,498 +1199,3 @@
return DIL_LOADED;
}
-#ifdef __ELF__
-
-/*
- * Walk through the entire symbol table and add any symbols we find there.
- * This can be used in cases where we have stripped ELF shared libraries,
- * or it can be used in cases where we have data symbols for which the address
- * isn't encoded in the stabs.
- *
- * This is all really quite easy, since we don't have to worry about line
- * numbers or local data variables.
- */
-static int DEBUG_ProcessElfSymtab(DBG_MODULE* module, char* addr,
- void *load_addr, Elf32_Shdr* symtab,
- Elf32_Shdr* strtab)
-{
- char * curfile = NULL;
- struct name_hash * curr_sym = NULL;
- int flags;
- int i;
- DBG_VALUE new_value;
- int nsym;
- char * strp;
- char * symname;
- Elf32_Sym * symp;
-
- symp = (Elf32_Sym *) (addr + symtab->sh_offset);
- nsym = symtab->sh_size / sizeof(*symp);
- strp = (char *) (addr + strtab->sh_offset);
-
- for (i = 0; i < nsym; i++, symp++)
- {
- /*
- * Ignore certain types of entries which really aren't of that much
- * interest.
- */
- if( ELF32_ST_TYPE(symp->st_info) == STT_SECTION ||
- symp->st_shndx == STN_UNDEF )
- {
- continue;
- }
-
- symname = strp + symp->st_name;
-
- /*
- * Save the name of the current file, so we have a way of tracking
- * static functions/data.
- */
- if( ELF32_ST_TYPE(symp->st_info) == STT_FILE )
- {
- curfile = symname;
- continue;
- }
-
- new_value.type = NULL;
- new_value.addr.seg = 0;
- new_value.addr.off = (unsigned long)load_addr + symp->st_value;
- new_value.cookie = DV_TARGET;
- flags = SYM_WINE | ((ELF32_ST_TYPE(symp->st_info) == STT_FUNC)
- ? SYM_FUNC : SYM_DATA);
- if( ELF32_ST_BIND(symp->st_info) == STB_GLOBAL )
- curr_sym = DEBUG_AddSymbol( symname, &new_value, NULL, flags );
- else
- curr_sym = DEBUG_AddSymbol( symname, &new_value, curfile, flags );
-
- /*
- * Record the size of the symbol. This can come in handy in
- * some cases. Not really used yet, however.
- */
- if( symp->st_size != 0 )
- DEBUG_SetSymbolSize(curr_sym, symp->st_size);
- }
-
- return TRUE;
-}
-
-/*
- * Loads the symbolic information from ELF module stored in 'filename'
- * the module has been loaded at 'load_offset' address, so symbols' address
- * relocation is performed
- * 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
- */
-enum DbgInfoLoad DEBUG_LoadElfStabs(DBG_MODULE* module)
-{
- enum DbgInfoLoad dil = DIL_ERROR;
- char* addr = (char*)0xffffffff;
- int fd = -1;
- struct stat statbuf;
- Elf32_Ehdr* ehptr;
- Elf32_Shdr* spnt;
- char* shstrtab;
- int i;
- int stabsect;
- int stabstrsect;
-
- if (module->type != DMT_ELF || !module->elf_info) {
- WINE_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 */
- if (stat(module->module_name, &statbuf) == -1) goto leave;
- if (S_ISDIR(statbuf.st_mode)) goto leave;
-
- /*
- * Now open the file, so that we can mmap() it.
- */
- if ((fd = open(module->module_name, O_RDONLY)) == -1) goto leave;
-
- dil = DIL_NOINFO;
- /*
- * Now mmap() the file.
- */
- addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (addr == (char*)0xffffffff) goto leave;
-
- /*
- * 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);
-
- stabsect = stabstrsect = -1;
-
- for (i = 0; i < ehptr->e_shnum; i++) {
- if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
- stabsect = i;
-
- if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
- stabstrsect = i;
- }
-
- if (stabsect == -1 || stabstrsect == -1) {
- WINE_WARN("No .stab section\n");
- goto leave;
- }
-
- /*
- * OK, now just parse all of the stabs.
- */
- 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;
- WINE_WARN("Couldn't read correctly read stabs\n");
- goto leave;
- }
-
- for (i = 0; i < ehptr->e_shnum; i++) {
- if ( (strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0)
- && (spnt[i].sh_type == SHT_SYMTAB))
- DEBUG_ProcessElfSymtab(module, addr, module->elf_info->elf_addr,
- spnt + i, spnt + spnt[i].sh_link);
-
- if ( (strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0)
- && (spnt[i].sh_type == SHT_DYNSYM))
- DEBUG_ProcessElfSymtab(module, addr, module->elf_info->elf_addr,
- spnt + i, spnt + spnt[i].sh_link);
- }
-
- leave:
- if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
- if (fd != -1) close(fd);
-
- return dil;
-}
-
-/*
- * 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,
- void *load_offset,
- unsigned int* dyn_addr)
-{
- static const unsigned char elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
- enum DbgInfoLoad dil = DIL_ERROR;
- char* addr = (char*)0xffffffff;
- 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;
-
- WINE_TRACE("Processing elf file '%s'\n", filename);
-
- /* check that the file exists, and that the module hasn't been loaded yet */
- if (stat(filename, &statbuf) == -1) goto leave;
-
- /*
- * 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*)-1) 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;
- if (memcmp( ehptr->e_ident, elf_signature, sizeof(elf_signature) )) goto leave;
-
- 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) ? (void *)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) {
- WINE_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 enum DbgInfoLoad DEBUG_ProcessElfFileFromPath(const char * filename,
- void *load_offset,
- unsigned int* dyn_addr,
- const char* path)
-{
- enum DbgInfoLoad dil = DIL_ERROR;
- char *s, *t, *fn;
- char* paths = NULL;
-
- if (!path) return -1;
-
- for (s = paths = DBG_strdup(path); s && *s; s = (t) ? (t+1) : NULL) {
- 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;
- }
-
- DBG_free(paths);
- return dil;
-}
-
-static enum DbgInfoLoad DEBUG_ProcessElfObject(const char* filename,
- void *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;
-
- if (strstr (filename, "libstdc++")) return DIL_ERROR; /* We know we can't do it */
- dil = DEBUG_ProcessElfFile(filename, load_offset, dyn_addr);
-
- /* if relative pathname, try some absolute base dirs */
- if (dil == DIL_ERROR && !strchr(filename, '/')) {
- dil = DEBUG_ProcessElfFileFromPath(filename, load_offset, dyn_addr, getenv("PATH"));
- if (dil == DIL_ERROR)
- dil = DEBUG_ProcessElfFileFromPath(filename, load_offset, dyn_addr, getenv("LD_LIBRARY_PATH"));
- if (dil == DIL_ERROR)
- dil = DEBUG_ProcessElfFileFromPath(filename, load_offset, dyn_addr, getenv("WINEDLLPATH"));
- }
-
- DEBUG_ReportDIL(dil, "ELF", filename, load_offset);
-
- return dil;
-}
-
-static BOOL DEBUG_WalkList(struct r_debug* dbg_hdr)
-{
- void *lm_addr;
- struct link_map lm;
- Elf32_Ehdr ehdr;
- char bufstr[256];
-
- /*
- * Now walk the linked list. In all known ELF implementations,
- * 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
- * does.
- */
- for (lm_addr = (void *)dbg_hdr->r_map; lm_addr; lm_addr = (void *)lm.l_next) {
- if (!DEBUG_READ_MEM_VERBOSE(lm_addr, &lm, sizeof(lm)))
- return FALSE;
-
- if (lm.l_addr != 0 &&
- DEBUG_READ_MEM_VERBOSE((void*)lm.l_addr, &ehdr, sizeof(ehdr)) &&
- ehdr.e_type == ET_DYN && /* only look at dynamic modules */
- lm.l_name != NULL &&
- DEBUG_READ_MEM_VERBOSE((void*)lm.l_name, bufstr, sizeof(bufstr))) {
- bufstr[sizeof(bufstr) - 1] = '\0';
- DEBUG_ProcessElfObject(bufstr, (void *)lm.l_addr, NULL);
- }
- }
-
- return TRUE;
-}
-
-static BOOL DEBUG_RescanElf(void)
-{
- struct r_debug dbg_hdr;
-
- if (!DEBUG_CurrProcess ||
- !DEBUG_READ_MEM_VERBOSE((void*)DEBUG_CurrProcess->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)))
- return FALSE;
-
- switch (dbg_hdr.r_state) {
- case RT_CONSISTENT:
- DEBUG_WalkList(&dbg_hdr);
- DEBUG_CheckDelayedBP();
- break;
- case RT_ADD:
- break;
- case RT_DELETE:
- /* FIXME: this is not currently handled, would need some kind of mark&sweep algo */
- break;
- }
- return FALSE;
-}
-
-enum DbgInfoLoad DEBUG_ReadExecutableDbgInfo(const char* exe_name)
-{
- Elf32_Dyn dyn;
- struct r_debug dbg_hdr;
- enum DbgInfoLoad dil = DIL_NOINFO;
- unsigned int dyn_addr;
-
- /*
- * Make sure we can stat and open this file.
- */
- if (exe_name == NULL) goto leave;
- DEBUG_ProcessElfObject(exe_name, 0, &dyn_addr);
-
- do {
- if (!DEBUG_READ_MEM_VERBOSE((void*)dyn_addr, &dyn, sizeof(dyn)))
- goto leave;
- dyn_addr += sizeof(dyn);
- } while (dyn.d_tag != DT_DEBUG && dyn.d_tag != DT_NULL);
- if (dyn.d_tag == DT_NULL) goto leave;
-
- /*
- * OK, now dig into the actual tables themselves.
- */
- if (!DEBUG_READ_MEM_VERBOSE((void*)dyn.d_un.d_ptr, &dbg_hdr, sizeof(dbg_hdr)))
- goto leave;
-
- assert(!DEBUG_CurrProcess->dbg_hdr_addr);
- DEBUG_CurrProcess->dbg_hdr_addr = (unsigned long)dyn.d_un.d_ptr;
-
- if (dbg_hdr.r_brk) {
- DBG_VALUE value;
-
- WINE_TRACE("Setting up a breakpoint on r_brk(%lx)\n", (unsigned long)dbg_hdr.r_brk);
-
- DEBUG_SetBreakpoints(FALSE);
- value.type = NULL;
- value.cookie = DV_TARGET;
- value.addr.seg = 0;
- value.addr.off = (DWORD)dbg_hdr.r_brk;
- DEBUG_AddBreakpoint(&value, DEBUG_RescanElf, TRUE);
- DEBUG_SetBreakpoints(TRUE);
- }
-
- dil = DEBUG_WalkList(&dbg_hdr);
-
- leave:
- return dil;
-}
-
-/* FIXME: merge with some of the routines above */
-int read_elf_info(const char* filename, unsigned long tab[])
-{
- static const unsigned char elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
- char* addr;
- Elf32_Ehdr* ehptr;
- Elf32_Shdr* spnt;
- char* shstrtab;
- int i;
- int ret = 0;
- HANDLE hFile;
- HANDLE hMap = 0;
-
- addr = NULL;
- hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) goto leave;
- hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
- if (hMap == 0) goto leave;
- addr = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
- if (addr == NULL) goto leave;
-
- ehptr = (Elf32_Ehdr*) addr;
- if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave;
-
- spnt = (Elf32_Shdr*) (addr + ehptr->e_shoff);
- shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
-
- tab[0] = tab[1] = tab[2] = 0;
- for (i = 0; i < ehptr->e_shnum; i++)
- {
- }
- ret = 1;
- leave:
- if (addr != NULL) UnmapViewOfFile(addr);
- if (hMap != 0) CloseHandle(hMap);
- if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
- return ret;
-}
-
-#else /* !__ELF__ */
-
-enum DbgInfoLoad DEBUG_ReadExecutableDbgInfo(const char* exe_name)
-{
- return FALSE;
-}
-
-int read_elf_info(const char* filename, unsigned long tab[])
-{
- return 0;
-}
-
-#endif /* __ELF__ */
Index: programs/winedbg/winedbg.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/winedbg.c,v
retrieving revision 1.17
diff -u -u -r1.17 winedbg.c
--- programs/winedbg/winedbg.c 15 Dec 2003 19:53:08 -0000 1.17
+++ programs/winedbg/winedbg.c 31 Jan 2004 10:51:04 -0000
@@ -674,8 +674,8 @@
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 @@
WINE_ERR("Couldn't create thread\n");
break;
}
+ else
+ {
+ struct elf_info elf_info;
- 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
- {
- char* ptr = getenv("WINELOADER");
-
- 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 @@
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))
{
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ programs/winedbg/elf.c 2004-02-02 23:03:43.000000000 +0100
@@ -0,0 +1,591 @@
+/*
+ * File elf.c - processing of ELF files
+ *
+ * Copyright (C) 1996, Eric Youngdale.
+ * 1999-2004 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+
+#include "debugger.h"
+
+#if defined(__svr4__) || defined(__sun)
+#define __ELF__
+#endif
+
+#ifdef __ELF__
+#ifdef HAVE_ELF_H
+# include <elf.h>
+#endif
+#ifdef HAVE_LINK_H
+# include <link.h>
+#endif
+#ifdef HAVE_SYS_LINK_H
+# include <sys/link.h>
+#endif
+#endif
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
+
+typedef struct tagELF_DBG_INFO
+{
+ void *elf_addr;
+} ELF_DBG_INFO;
+
+#ifdef __ELF__
+
+/*
+ * Walk through the entire symbol table and add any symbols we find there.
+ * This can be used in cases where we have stripped ELF shared libraries,
+ * or it can be used in cases where we have data symbols for which the address
+ * isn't encoded in the stabs.
+ *
+ * This is all really quite easy, since we don't have to worry about line
+ * numbers or local data variables.
+ */
+static int DEBUG_ProcessElfSymtab(DBG_MODULE* module, const char* addr,
+ void *load_addr, const Elf32_Shdr* symtab,
+ const Elf32_Shdr* strtab)
+{
+ const char* curfile = NULL;
+ struct name_hash* curr_sym = NULL;
+ int flags;
+ int i;
+ DBG_VALUE new_value;
+ int nsym;
+ const char* strp;
+ const char* symname;
+ const Elf32_Sym* symp;
+
+ symp = (Elf32_Sym *)(addr + symtab->sh_offset);
+ nsym = symtab->sh_size / sizeof(*symp);
+ strp = (char *)(addr + strtab->sh_offset);
+
+ for (i = 0; i < nsym; i++, symp++)
+ {
+ /*
+ * Ignore certain types of entries which really aren't of that much
+ * interest.
+ */
+ if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION ||
+ symp->st_shndx == STN_UNDEF)
+ {
+ continue;
+ }
+
+ symname = strp + symp->st_name;
+
+ /*
+ * Save the name of the current file, so we have a way of tracking
+ * static functions/data.
+ */
+ if (ELF32_ST_TYPE(symp->st_info) == STT_FILE)
+ {
+ curfile = symname;
+ continue;
+ }
+
+ new_value.type = NULL;
+ new_value.addr.seg = 0;
+ new_value.addr.off = (unsigned long)load_addr + symp->st_value;
+ new_value.cookie = DV_TARGET;
+ flags = SYM_WINE | ((ELF32_ST_TYPE(symp->st_info) == STT_FUNC)
+ ? SYM_FUNC : SYM_DATA);
+ if (ELF32_ST_BIND(symp->st_info) == STB_GLOBAL)
+ curr_sym = DEBUG_AddSymbol(symname, &new_value, NULL, flags);
+ else
+ curr_sym = DEBUG_AddSymbol(symname, &new_value, curfile, flags);
+
+ /*
+ * Record the size of the symbol. This can come in handy in
+ * some cases. Not really used yet, however.
+ */
+ if (symp->st_size != 0)
+ DEBUG_SetSymbolSize(curr_sym, symp->st_size);
+ }
+
+ return TRUE;
+}
+
+/*
+ * Loads the symbolic information from ELF module stored in 'filename'
+ * the module has been loaded at 'load_offset' address, so symbols' address
+ * relocation is performed
+ * 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
+ */
+enum DbgInfoLoad DEBUG_LoadElfStabs(DBG_MODULE* module)
+{
+ enum DbgInfoLoad dil = DIL_ERROR;
+ char* addr = (char*)0xffffffff;
+ int fd = -1;
+ struct stat statbuf;
+ const Elf32_Ehdr* ehptr;
+ const Elf32_Shdr* spnt;
+ const char* shstrtab;
+ int i;
+ int stabsect, stabstrsect, debugsect;
+
+ if (module->type != DMT_ELF || !module->elf_dbg_info)
+ {
+ WINE_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 */
+ if (stat(module->module_name, &statbuf) == -1) goto leave;
+ if (S_ISDIR(statbuf.st_mode)) goto leave;
+
+ /*
+ * Now open the file, so that we can mmap() it.
+ */
+ if ((fd = open(module->module_name, O_RDONLY)) == -1) goto leave;
+
+ dil = DIL_NOINFO;
+ /*
+ * Now mmap() the file.
+ */
+ addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (addr == (char*)0xffffffff) goto leave;
+
+ /*
+ * 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);
+
+ stabsect = stabstrsect = debugsect = -1;
+
+ for (i = 0; i < ehptr->e_shnum; i++)
+ {
+ if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0)
+ stabsect = i;
+ if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0)
+ stabstrsect = i;
+ if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0)
+ debugsect = i;
+ }
+
+ if (stabsect != -1 && stabstrsect != -1)
+ {
+ /*
+ * OK, now just parse all of the stabs.
+ */
+ if (DEBUG_ParseStabs(addr,
+ module->elf_dbg_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;
+ WINE_WARN("Couldn't read correctly read stabs\n");
+ goto leave;
+ }
+ }
+ else if (debugsect != -1)
+ {
+ /* Dwarf 2 debug information */
+ dil = DIL_NOT_SUPPORTED;
+ }
+ /* now load dynamic symbol info */
+ for (i = 0; i < ehptr->e_shnum; i++)
+ {
+ if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) &&
+ (spnt[i].sh_type == SHT_SYMTAB))
+ DEBUG_ProcessElfSymtab(module, addr, module->elf_dbg_info->elf_addr,
+ spnt + i, spnt + spnt[i].sh_link);
+
+ if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) &&
+ (spnt[i].sh_type == SHT_DYNSYM))
+ DEBUG_ProcessElfSymtab(module, addr, module->elf_dbg_info->elf_addr,
+ spnt + i, spnt + spnt[i].sh_link);
+ }
+
+leave:
+ if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size);
+ if (fd != -1) close(fd);
+
+ return dil;
+}
+
+/*
+ * 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(HANDLE hProcess,
+ const char* filename,
+ void *load_offset,
+ struct elf_info* elf_info)
+{
+ static const unsigned char elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
+ enum DbgInfoLoad dil = DIL_ERROR;
+ const char* addr = (char*)0xffffffff;
+ int fd = -1;
+ struct stat statbuf;
+ const Elf32_Ehdr* ehptr;
+ const Elf32_Shdr* spnt;
+ const Elf32_Phdr* ppnt;
+ const char* shstrtab;
+ int i;
+ DWORD delta;
+
+ WINE_TRACE("Processing elf file '%s' at %p\n", filename, load_offset);
+
+ /* check that the file exists, and that the module hasn't been loaded yet */
+ if (stat(filename, &statbuf) == -1) goto leave;
+
+ /*
+ * 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*)-1) 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;
+ if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave;
+
+ 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);
+ elf_info->size = 0;
+ for (i = 0; i < ehptr->e_phnum; i++)
+ {
+ if (ppnt[i].p_type != PT_LOAD) continue;
+ if (elf_info->size < ppnt[i].p_vaddr - delta + ppnt[i].p_memsz)
+ elf_info->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 (elf_info->size < spnt[i].sh_addr - delta + spnt[i].sh_size)
+ elf_info->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 (elf_info->flags & ELF_INFO_DEBUG_HEADER)
+ {
+ Elf32_Dyn dyn;
+ char* ptr = (char*)spnt[i].sh_addr;
+ unsigned long len;
+
+ do
+ {
+ if (!ReadProcessMemory(hProcess, ptr, &dyn, sizeof(dyn), &len) ||
+ len != sizeof(dyn) ||
+ !((dyn.d_tag >= 0 &&
+ dyn.d_tag < DT_NUM+DT_PROCNUM+DT_EXTRANUM) ||
+ (dyn.d_tag >= DT_LOOS && dyn.d_tag < DT_HIOS) ||
+ (dyn.d_tag >= DT_LOPROC && dyn.d_tag < DT_HIPROC))
+ )
+ dyn.d_tag = DT_NULL;
+ ptr += sizeof(dyn);
+ } while (dyn.d_tag != DT_DEBUG && dyn.d_tag != DT_NULL);
+ if (dyn.d_tag == DT_NULL)
+ {
+ dil = DIL_ERROR;
+ goto leave;
+ }
+ elf_info->dbg_hdr_addr = dyn.d_un.d_ptr;
+ }
+ }
+ }
+
+ elf_info->segments[0] = elf_info->segments[1] = elf_info->segments[2] = 0;
+ if (elf_info->flags & ELF_INFO_PATH)
+ {
+ strncpy(elf_info->elf_path, filename, elf_info->elf_path_len);
+ elf_info->elf_path[elf_info->elf_path_len - 1] = '\0';
+ }
+
+ elf_info->load_addr = (load_offset == 0) ? (void *)ehptr->e_entry : load_offset;
+
+ if (elf_info->flags & ELF_INFO_MODULE)
+ {
+ DBG_MODULE* module;
+
+ module = DEBUG_AddModule(filename, DMT_ELF, elf_info->load_addr, elf_info->size, 0);
+ if (module)
+ {
+ if ((module->elf_dbg_info = DBG_alloc(sizeof(ELF_DBG_INFO))) == NULL)
+ {
+ WINE_ERR("OOM\n");
+ exit(0);
+ }
+ module->elf_dbg_info->elf_addr = load_offset;
+ module->dil = dil = DEBUG_LoadElfStabs(module);
+ }
+ else dil = DIL_ERROR;
+ }
+
+leave:
+ if (addr != (char*)0xffffffff) munmap((void*)addr, statbuf.st_size);
+ if (fd != -1) close(fd);
+
+ return dil;
+}
+
+static enum DbgInfoLoad DEBUG_ProcessElfFileFromPath(HANDLE hProcess,
+ const char * filename,
+ void *load_offset,
+ const char* path,
+ struct elf_info* elf_info)
+{
+ enum DbgInfoLoad dil = DIL_ERROR;
+ char *s, *t, *fn;
+ char* paths = NULL;
+
+ if (!path) return dil;
+
+ for (s = paths = DBG_strdup(path); s && *s; s = (t) ? (t+1) : NULL)
+ {
+ 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(hProcess, fn, load_offset, elf_info);
+ DBG_free(fn);
+ if (dil != DIL_ERROR) break;
+ s = (t) ? (t+1) : NULL;
+ }
+
+ DBG_free(paths);
+ return dil;
+}
+
+static enum DbgInfoLoad DEBUG_ProcessElfObject(HANDLE hProcess,
+ const char* filename,
+ void *load_offset,
+ struct elf_info* elf_info)
+{
+ enum DbgInfoLoad dil = DIL_ERROR;
+
+ if (filename == NULL || !*filename) return DIL_ERROR;
+ if (DEBUG_FindModuleByName(filename, DMT_ELF))
+ {
+ assert(!(elf_info->flags & ELF_INFO_PATH));
+ return DIL_LOADED;
+ }
+
+ if (strstr(filename, "libstdc++")) return DIL_ERROR; /* We know we can't do it */
+ dil = DEBUG_ProcessElfFile(hProcess, filename, load_offset, elf_info);
+ /* if relative pathname, try some absolute base dirs */
+ if (dil == DIL_ERROR && !strchr(filename, '/'))
+ {
+ dil = DEBUG_ProcessElfFileFromPath(hProcess, filename, load_offset,
+ getenv("PATH"), elf_info);
+ if (dil == DIL_ERROR)
+ dil = DEBUG_ProcessElfFileFromPath(hProcess, filename, load_offset,
+ getenv("LD_LIBRARY_PATH"), elf_info);
+ if (dil == DIL_ERROR)
+ dil = DEBUG_ProcessElfFileFromPath(hProcess, filename, load_offset,
+ getenv("WINEDLLPATH"), elf_info);
+ }
+
+ DEBUG_ReportDIL(dil, "ELF", filename, load_offset);
+
+ return dil;
+}
+
+static BOOL DEBUG_WalkList(const struct r_debug* dbg_hdr)
+{
+ void* lm_addr;
+ struct link_map lm;
+ char bufstr[256];
+ struct elf_info elf_info;
+
+ elf_info.flags = ELF_INFO_MODULE;
+ /*
+ * Now walk the linked list. In all known ELF implementations,
+ * 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
+ * does.
+ */
+ for (lm_addr = (void *)dbg_hdr->r_map; lm_addr; lm_addr = (void *)lm.l_next)
+ {
+ if (!DEBUG_READ_MEM_VERBOSE(lm_addr, &lm, sizeof(lm)))
+ return FALSE;
+
+ if (lm.l_prev != NULL && /* skip first entry, normally debuggee itself */
+ lm.l_name != NULL &&
+ DEBUG_READ_MEM_VERBOSE((void*)lm.l_name, bufstr, sizeof(bufstr)))
+ {
+ bufstr[sizeof(bufstr) - 1] = '\0';
+ DEBUG_ProcessElfObject(DEBUG_CurrProcess->handle, bufstr,
+ (void *)lm.l_addr, &elf_info);
+ }
+ }
+
+ return TRUE;
+}
+
+static BOOL DEBUG_RescanElf(void)
+{
+ struct r_debug dbg_hdr;
+
+ if (DEBUG_CurrProcess &&
+ DEBUG_READ_MEM_VERBOSE((void*)DEBUG_CurrProcess->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)))
+ {
+ switch (dbg_hdr.r_state)
+ {
+ case RT_CONSISTENT:
+ DEBUG_WalkList(&dbg_hdr);
+ DEBUG_CheckDelayedBP();
+ break;
+ case RT_ADD:
+ break;
+ case RT_DELETE:
+ /* FIXME: this is not currently handled */
+ break;
+ }
+ }
+ return FALSE;
+}
+
+/******************************************************************
+ * DEBUG_ReadWineLoaderDbgInfo
+ *
+ * Try to find a decent wine executable which could have loader the debuggee
+ */
+enum DbgInfoLoad DEBUG_ReadWineLoaderDbgInfo(HANDLE hProcess, struct elf_info* elf_info)
+{
+ const char* ptr;
+ enum DbgInfoLoad dil;
+
+ /* All binaries are loaded with WINELOADER (if run from tree) or by the
+ * main executable (either wine-kthread or wine-pthread)
+ * Note: the heuristic use to know wether we need to load wine-pthread or
+ * wine-kthread is not 100% safe
+ */
+ elf_info->flags |= ELF_INFO_DEBUG_HEADER;
+ if ((ptr = getenv("WINELOADER")))
+ dil = DEBUG_ProcessElfObject(hProcess, ptr, 0, elf_info);
+ else
+ {
+ if ((dil = DEBUG_ProcessElfObject(hProcess, "wine-kthread", 0, elf_info)) == DIL_ERROR)
+ dil = DEBUG_ProcessElfObject(hProcess, "wine-pthread", 0, elf_info);
+ }
+ return dil;
+}
+
+/******************************************************************
+ * DEBUG_SetElfSoLoadBreakpoint
+ *
+ * Sets a breakpoint to handle .so loading events, so we can add debug info
+ * on the fly
+ */
+BOOL DEBUG_SetElfSoLoadBreakpoint(const struct elf_info* elf_info)
+{
+ struct r_debug dbg_hdr;
+
+ /*
+ * OK, now dig into the actual tables themselves.
+ */
+ if (!DEBUG_READ_MEM_VERBOSE((void*)elf_info->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr)))
+ return FALSE;
+
+ assert(!DEBUG_CurrProcess->dbg_hdr_addr);
+ DEBUG_CurrProcess->dbg_hdr_addr = elf_info->dbg_hdr_addr;
+
+ if (dbg_hdr.r_brk)
+ {
+ DBG_VALUE value;
+
+ WINE_TRACE("Setting up a breakpoint on r_brk(%lx)\n",
+ (unsigned long)dbg_hdr.r_brk);
+
+ DEBUG_SetBreakpoints(FALSE);
+ value.type = NULL;
+ value.cookie = DV_TARGET;
+ value.addr.seg = 0;
+ value.addr.off = (DWORD)dbg_hdr.r_brk;
+ DEBUG_AddBreakpoint(&value, DEBUG_RescanElf, TRUE);
+ DEBUG_SetBreakpoints(TRUE);
+ }
+
+ return DEBUG_WalkList(&dbg_hdr);
+}
+
+#else /* !__ELF__ */
+
+enum DbgInfoLoad DEBUG_ReadExecutableDbgInfo(HANDLE hProcess, struct elf_info* elf_info)
+{
+ return DIL_ERROR;
+}
+
+BOOL DEBUG_SetElfSoLoadBreakpoint(const struct elf_info* elf_info)
+{
+ return FALSE;
+}
+
+#endif /* __ELF__ */
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ programs/winedbg/pe.c 2004-02-01 10:47:09.000000000 +0100
@@ -0,0 +1,513 @@
+/*
+ * File pe.c - handle PE module information
+ *
+ * Copyright (C) 1996, Eric Youngdale.
+ * Copyright (C) 1999, 2000, Ulrich Weigand.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+#include "wine/exception.h"
+#include "wine/debug.h"
+#include "excpt.h"
+#include "debugger.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
+
+#define MAX_PATHNAME_LEN 1024
+
+typedef struct
+{
+ DWORD from;
+ DWORD to;
+
+} OMAP_DATA;
+
+typedef struct tagMSC_DBG_INFO
+{
+ int nsect;
+ PIMAGE_SECTION_HEADER sectp;
+ int nomap;
+ OMAP_DATA* omapp;
+
+} MSC_DBG_INFO;
+
+/***********************************************************************
+ * DEBUG_LocateDebugInfoFile
+ *
+ * NOTE: dbg_filename must be at least MAX_PATHNAME_LEN bytes in size
+ */
+static void DEBUG_LocateDebugInfoFile(const char* filename, char* dbg_filename)
+{
+ char* str1 = DBG_alloc(MAX_PATHNAME_LEN);
+ char* str2 = DBG_alloc(MAX_PATHNAME_LEN*10);
+ const char* file;
+ char* name_part;
+
+ file = strrchr(filename, '\\');
+ if (file == NULL) file = filename; else file++;
+
+ if ((GetEnvironmentVariable("_NT_SYMBOL_PATH", str1, MAX_PATHNAME_LEN) &&
+ (SearchPath(str1, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part))) ||
+ (GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", str1, MAX_PATHNAME_LEN) &&
+ (SearchPath(str1, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part))) ||
+ (SearchPath(NULL, file, NULL, MAX_PATHNAME_LEN*10, str2, &name_part)))
+ lstrcpyn(dbg_filename, str2, MAX_PATHNAME_LEN);
+ else
+ lstrcpyn(dbg_filename, filename, MAX_PATHNAME_LEN);
+ DBG_free(str1);
+ DBG_free(str2);
+}
+
+/***********************************************************************
+ * DEBUG_MapDebugInfoFile
+ */
+void* DEBUG_MapDebugInfoFile(const char* name, DWORD offset, DWORD size,
+ HANDLE* hFile, HANDLE* hMap)
+{
+ DWORD g_offset; /* offset aligned on map granuality */
+ DWORD g_size; /* size to map, with offset aligned */
+ char* ret;
+
+ *hMap = 0;
+
+ if (name != NULL)
+ {
+ char filename[MAX_PATHNAME_LEN];
+
+ DEBUG_LocateDebugInfoFile(name, filename);
+ if ((*hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ return NULL;
+ }
+
+ if (!size)
+ {
+ DWORD file_size = GetFileSize(*hFile, NULL);
+ if (file_size == (DWORD)-1) return NULL;
+ size = file_size - offset;
+ }
+
+ g_offset = offset & ~0xFFFF; /* FIXME: is granularity portable ? */
+ g_size = offset + size - g_offset;
+
+ if ((*hMap = CreateFileMapping(*hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == 0)
+ return NULL;
+
+ if ((ret = MapViewOfFile(*hMap, FILE_MAP_READ, 0, g_offset, g_size)) != NULL)
+ ret += offset - g_offset;
+
+ return ret;
+}
+
+/***********************************************************************
+ * DEBUG_UnmapDebugInfoFile
+ */
+void DEBUG_UnmapDebugInfoFile(HANDLE hFile, HANDLE hMap, const void* addr)
+{
+ if (addr) UnmapViewOfFile((void*)addr);
+ if (hMap) CloseHandle(hMap);
+ if (hFile!=INVALID_HANDLE_VALUE) CloseHandle(hFile);
+}
+
+/*========================================================================
+ * Process DBG file.
+ */
+static enum DbgInfoLoad DEBUG_ProcessDBGFile(DBG_MODULE* module,
+ const char* filename, DWORD timestamp)
+{
+ enum DbgInfoLoad dil = DIL_ERROR;
+ HANDLE hFile = INVALID_HANDLE_VALUE, hMap = 0;
+ const BYTE* file_map = NULL;
+ PIMAGE_SEPARATE_DEBUG_HEADER hdr;
+ PIMAGE_DEBUG_DIRECTORY dbg;
+ int nDbg;
+
+ WINE_TRACE("Processing DBG file %s\n", filename);
+
+ file_map = DEBUG_MapDebugInfoFile(filename, 0, 0, &hFile, &hMap);
+ if (!file_map)
+ {
+ WINE_ERR("-Unable to peruse .DBG file %s\n", filename);
+ goto leave;
+ }
+
+ hdr = (PIMAGE_SEPARATE_DEBUG_HEADER) file_map;
+
+ if (hdr->TimeDateStamp != timestamp)
+ {
+ WINE_ERR("Warning - %s has incorrect internal timestamp\n", filename);
+ /*
+ * Well, sometimes this happens to DBG files which ARE REALLY the right .DBG
+ * files but nonetheless this check fails. Anyway, WINDBG (debugger for
+ * Windows by Microsoft) loads debug symbols which have incorrect timestamps.
+ */
+ }
+
+
+ dbg = (PIMAGE_DEBUG_DIRECTORY)
+ (file_map + sizeof(*hdr) + hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER)
+ + hdr->ExportedNamesSize);
+
+ nDbg = hdr->DebugDirectorySize / sizeof(*dbg);
+
+ dil = DEBUG_ProcessDebugDirectory(module, file_map, dbg, nDbg);
+
+leave:
+ DEBUG_UnmapDebugInfoFile(hFile, hMap, file_map);
+ return dil;
+}
+
+
+/*========================================================================
+ * Process MSC debug information in PE file.
+ */
+enum DbgInfoLoad DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, HANDLE hFile,
+ void* _nth, unsigned long nth_ofs)
+{
+ enum DbgInfoLoad dil = DIL_ERROR;
+ PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
+ PIMAGE_DATA_DIRECTORY dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
+ PIMAGE_DEBUG_DIRECTORY dbg = NULL;
+ int nDbg;
+ MSC_DBG_INFO extra_info = { 0, NULL, 0, NULL };
+ HANDLE hMap = 0;
+ const BYTE* file_map = NULL;
+
+ /* Read in section data */
+
+ module->msc_dbg_info = &extra_info;
+ extra_info.nsect = nth->FileHeader.NumberOfSections;
+ extra_info.sectp = DBG_alloc(extra_info.nsect * sizeof(IMAGE_SECTION_HEADER));
+ if (!extra_info.sectp)
+ goto leave;
+
+ if (!DEBUG_READ_MEM_VERBOSE((char*)module->load_addr +
+ nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
+ nth->FileHeader.SizeOfOptionalHeader,
+ extra_info.sectp,
+ extra_info.nsect * sizeof(IMAGE_SECTION_HEADER)))
+ goto leave;
+
+ /* Read in debug directory */
+
+ nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
+ if (!nDbg)
+ goto leave;
+
+ dbg = (PIMAGE_DEBUG_DIRECTORY) DBG_alloc(nDbg * sizeof(IMAGE_DEBUG_DIRECTORY));
+ if (!dbg)
+ goto leave;
+
+ if (!DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + dir->VirtualAddress,
+ dbg, nDbg * sizeof(IMAGE_DEBUG_DIRECTORY)))
+ goto leave;
+
+
+ /* Map in PE file */
+ file_map = DEBUG_MapDebugInfoFile(NULL, 0, 0, &hFile, &hMap);
+ if (!file_map)
+ goto leave;
+
+
+ /* Parse debug directory */
+
+ if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
+ {
+ /* Debug info is stripped to .DBG file */
+
+ PIMAGE_DEBUG_MISC misc = (PIMAGE_DEBUG_MISC)(file_map + dbg->PointerToRawData);
+
+ if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC
+ || misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
+ {
+ WINE_ERR("-Debug info stripped, but no .DBG file in module %s\n",
+ module->module_name);
+ goto leave;
+ }
+
+ dil = DEBUG_ProcessDBGFile(module, misc->Data, nth->FileHeader.TimeDateStamp);
+ }
+ else
+ {
+ /* Debug info is embedded into PE module */
+ /* FIXME: the nDBG information we're manipulating comes from the debuggee
+ * address space. However, the following code will be made against the
+ * version mapped in the debugger address space. There are cases (for example
+ * when the PE sections are compressed in the file and become decompressed
+ * in the debuggee address space) where the two don't match.
+ * Therefore, redo the DBG information lookup with the mapped data
+ */
+ PIMAGE_NT_HEADERS mpd_nth = (PIMAGE_NT_HEADERS)(file_map + nth_ofs);
+ PIMAGE_DATA_DIRECTORY mpd_dir;
+ PIMAGE_DEBUG_DIRECTORY mpd_dbg = NULL;
+
+ /* sanity checks */
+ if (mpd_nth->Signature != IMAGE_NT_SIGNATURE ||
+ mpd_nth->FileHeader.NumberOfSections != nth->FileHeader.NumberOfSections ||
+ (mpd_nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0)
+ goto leave;
+ mpd_dir = mpd_nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
+
+ if ((mpd_dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY)) != nDbg)
+ goto leave;
+
+ mpd_dbg = (PIMAGE_DEBUG_DIRECTORY)(file_map + mpd_dir->VirtualAddress);
+
+ dil = DEBUG_ProcessDebugDirectory(module, file_map, mpd_dbg, nDbg);
+ }
+
+
+leave:
+ module->msc_dbg_info = NULL;
+
+ DEBUG_UnmapDebugInfoFile(0, hMap, file_map);
+ if (extra_info.sectp) DBG_free(extra_info.sectp);
+ if (dbg) DBG_free(dbg);
+ return dil;
+}
+
+
+/*========================================================================
+ * look for stabs information in PE header (it's how mingw compiler provides its
+ * debugging information), and also wine PE <-> ELF linking through .wsolnk sections
+ */
+enum DbgInfoLoad DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, HANDLE hFile,
+ void* _nth, unsigned long nth_ofs)
+{
+ IMAGE_SECTION_HEADER pe_seg;
+ unsigned long pe_seg_ofs;
+ int i, stabsize = 0, stabstrsize = 0;
+ unsigned int stabs = 0, stabstr = 0;
+ PIMAGE_NT_HEADERS nth = (PIMAGE_NT_HEADERS)_nth;
+ enum DbgInfoLoad dil = DIL_ERROR;
+
+ pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
+ nth->FileHeader.SizeOfOptionalHeader;
+
+ for (i = 0; i < nth->FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg))
+ {
+ if (!DEBUG_READ_MEM_VERBOSE((void*)((char*)module->load_addr + pe_seg_ofs),
+ &pe_seg, sizeof(pe_seg)))
+ continue;
+
+ if (!strcasecmp(pe_seg.Name, ".stab"))
+ {
+ stabs = pe_seg.VirtualAddress;
+ stabsize = pe_seg.SizeOfRawData;
+ }
+ else if (!strncasecmp(pe_seg.Name, ".stabstr", 8))
+ {
+ stabstr = pe_seg.VirtualAddress;
+ stabstrsize = pe_seg.SizeOfRawData;
+ }
+ }
+
+ if (stabstrsize && stabsize)
+ {
+ char* s1 = DBG_alloc(stabsize+stabstrsize);
+
+ if (s1)
+ {
+ if (DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabs, s1, stabsize) &&
+ DEBUG_READ_MEM_VERBOSE((char*)module->load_addr + stabstr,
+ s1 + stabsize, stabstrsize))
+ {
+ dil = DEBUG_ParseStabs(s1, 0, 0, stabsize, stabsize, stabstrsize);
+ }
+ else
+ {
+ DEBUG_Printf("couldn't read data block\n");
+ }
+ DBG_free(s1);
+ }
+ else
+ {
+ DEBUG_Printf("couldn't alloc %d bytes\n", stabsize + stabstrsize);
+ }
+ }
+ else
+ {
+ dil = DIL_NOINFO;
+ }
+ return dil;
+}
+
+/***********************************************************************
+ * 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_LoadPEModule
+ */
+void DEBUG_LoadPEModule(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_AddModule(name, DMT_PE, base, size, (HMODULE)base);
+
+ 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);
+}
More information about the wine-patches
mailing list