Eric Pouech a écrit :
minidumps now contain more accurate information about modules,
especially information that will allow when reloading a minidump in a
debugger to check whether we're using the right modules (ELF & PE)
implemented also check for this information in SymFindFileInPath
A+
Please use this version instead (the previous had an un-wanted statement)
A+
--
Eric Pouech
Name: dbghelp18
ChangeLog:
- various improvements for minidump module information
. added timestamp & checksum in PE module
. added size & checksum in ELF module
. wine loader now appears with its pathname
- Implemented PE & ELF timestamp & checksum validation in SymFindFileInPath
License: X11
GenDate: 2005/03/28 16:36:41 UTC
ModifiedFiles: dlls/dbghelp/dbghelp_private.h dlls/dbghelp/elf_module.c dlls/dbghelp/minidump.c dlls/dbghelp/module.c
dlls/dbghelp/path.c dlls/dbghelp/pe_module.c include/dbghelp.h
AddedFiles:
RemovedFiles:
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/dbghelp/dbghelp_private.h,v
retrieving revision 1.14
diff -u -u -r1.14 dbghelp_private.h
--- dlls/dbghelp/dbghelp_private.h 1 Mar 2005 10:39:49 -0000 1.14
+++ dlls/dbghelp/dbghelp_private.h 28 Mar 2005 11:28:25 -0000
@@ -249,6 +249,7 @@
DMT_UNKNOWN, /* for lookup, not actually used for a module */
DMT_ELF, /* a real ELF shared module */
DMT_PE, /* a native or builtin PE module */
+ DMT_PDB, /* PDB file */
};
struct module
@@ -295,6 +296,7 @@
/* elf_module.c */
typedef BOOL (*elf_enum_modules_cb)(const char*, unsigned long addr, void* user);
extern BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb, void*);
+extern BOOL elf_fetch_file_info(const char* name, DWORD* base, DWORD* size, DWORD* checksum);
struct elf_file_map;
extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap);
extern struct module*
@@ -324,6 +326,8 @@
extern struct module*
module_get_containee(const struct process* pcs,
const struct module* inner);
+extern enum module_type
+ module_get_type_by_name(const char* name);
extern void module_reset_debug_info(struct module* module);
extern BOOL module_remove(struct process* pcs,
struct module* module);
@@ -334,6 +338,7 @@
const IMAGE_SECTION_HEADER* sectp, DWORD nsect,
const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
/* pe_module.c */
+extern BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth);
extern struct module*
pe_load_module(struct process* pcs, char* name,
HANDLE hFile, DWORD base, DWORD size);
Index: dlls/dbghelp/elf_module.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/dbghelp/elf_module.c,v
retrieving revision 1.17
diff -u -u -r1.17 elf_module.c
--- dlls/dbghelp/elf_module.c 23 Mar 2005 13:15:20 -0000 1.17
+++ dlls/dbghelp/elf_module.c 28 Mar 2005 12:00:09 -0000
@@ -81,12 +81,14 @@
#define ELF_INFO_DEBUG_HEADER 0x0001
#define ELF_INFO_MODULE 0x0002
+#define ELF_INFO_NAME 0x0004
struct elf_info
{
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
+ const char* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */
};
#define NO_MAP ((const void*)0xffffffff)
@@ -139,7 +141,8 @@
return NO_MAP;
/* align required information on page size (we assume pagesize is a power of 2) */
ofst = fmap->sect[sidx].shdr.sh_offset & ~(pgsz - 1);
- size = (fmap->sect[sidx].shdr.sh_offset + fmap->sect[sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1);
+ size = (fmap->sect[sidx].shdr.sh_offset +
+ fmap->sect[sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1);
fmap->sect[sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fmap->fd, ofst);
if (fmap->sect[sidx].mapped == NO_MAP) return NO_MAP;
return fmap->sect[sidx].mapped + (fmap->sect[sidx].shdr.sh_offset & (pgsz - 1));
@@ -188,7 +191,8 @@
if (memcmp(fmap->elfhdr.e_ident,
elf_signature, sizeof(elf_signature))) return FALSE;
- fmap->sect = HeapAlloc(GetProcessHeap(), 0, fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
+ fmap->sect = HeapAlloc(GetProcessHeap(), 0,
+ fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
if (!fmap->sect) return FALSE;
lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET);
@@ -800,7 +804,8 @@
shstrtab = elf_map_section(fmap, fmap->elfhdr.e_shstrndx);
if (shstrtab == NO_MAP) return FALSE;
- symtab_sect = dynsym_sect = stab_sect = stabstr_sect = debug_sect = debuglink_sect = -1;
+ symtab_sect = dynsym_sect = stab_sect = stabstr_sect =
+ debug_sect = debuglink_sect = -1;
for (i = 0; i < fmap->elfhdr.e_shnum; i++)
{
@@ -867,7 +872,8 @@
else if (debug_sect != -1)
{
/* Dwarf 2 debug information */
- FIXME("Unsupported Dwarf2 information for %s\n", module->module.ModuleName);
+ FIXME("Unsupported Dwarf2 information for %s\n",
+ module->module.ModuleName);
}
else if (debuglink_sect != -1)
{
@@ -876,7 +882,8 @@
dbg_link = elf_map_section(fmap, debuglink_sect);
/* The content of a debug link section is:
- * 1/ a NULL terminated string, containing the file name for the debug info
+ * 1/ a NULL terminated string, containing the file name for the
+ * debug info
* 2/ padding on 4 byte boundary
* 3/ CRC of the linked ELF file
*/
@@ -884,11 +891,14 @@
{
fmap_link.crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3));
fmap_link.with_crc = 1;
- ret = elf_load_debug_info_from_map(module, &fmap_link, pool, ht_symtab);
+ ret = elf_load_debug_info_from_map(module, &fmap_link, pool,
+ ht_symtab);
if (!ret)
WARN("Couldn't load debug information from %s\n", dbg_link);
}
- else WARN("Couldn't load linked debug file for %s\n", module->module.ModuleName);
+ else
+ WARN("Couldn't load linked debug file for %s\n",
+ module->module.ModuleName);
elf_unmap_file(&fmap_link);
}
}
@@ -940,6 +950,22 @@
return ret;
}
+/******************************************************************
+ * elf_fetch_file_info
+ *
+ * Gathers some more information for an ELF module from a given file
+ */
+BOOL elf_fetch_file_info(const char* name, DWORD* base,
+ DWORD* size, DWORD* checksum)
+{
+ struct elf_file_map fmap;
+ if (!elf_map_file(name, &fmap)) return FALSE;
+ if (base) *base = fmap.elf_start;
+ *size = fmap.elf_size;
+ *checksum = calc_crc32(&fmap);
+ elf_unmap_file(&fmap);
+ return TRUE;
+}
/******************************************************************
* is_dt_flag_valid
@@ -1033,7 +1059,7 @@
if (!elf_module_info) goto leave;
elf_info->module = module_new(pcs, filename, DMT_ELF,
(load_offset) ? load_offset : fmap.elf_start,
- fmap.elf_size, 0, 0);
+ fmap.elf_size, 0, calc_crc32(&fmap));
if (!elf_info->module)
{
HeapFree(GetProcessHeap(), 0, elf_module_info);
@@ -1053,6 +1079,11 @@
elf_info->module->elf_info->elf_loader = 0;
} else ret = TRUE;
+ if (elf_info->flags & ELF_INFO_NAME)
+ {
+ elf_info->module_name = strcpy(HeapAlloc(GetProcessHeap(), 0,
+ strlen(filename) + 1), filename);
+ }
leave:
elf_unmap_file(&fmap);
@@ -1137,6 +1168,7 @@
* Enumerate ELF modules from a running process
*/
static BOOL elf_enum_modules_internal(const struct process* pcs,
+ const char* main_name,
elf_enum_modules_cb cb, void* user)
{
struct r_debug dbg_hdr;
@@ -1164,7 +1196,8 @@
ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL))
{
bufstr[sizeof(bufstr) - 1] = '\0';
- if (!cb(bufstr, lm.l_addr, user)) break;
+ if (main_name && !bufstr[0]) strcpy(bufstr, main_name);
+ if (!cb(bufstr, (unsigned long)lm.l_addr, user)) break;
}
}
return TRUE;
@@ -1204,7 +1237,7 @@
es.pcs = pcs;
es.elf_info.flags = ELF_INFO_MODULE;
- if (!elf_enum_modules_internal(pcs, elf_enum_sync_cb, &es))
+ if (!elf_enum_modules_internal(pcs, NULL, elf_enum_sync_cb, &es))
return FALSE;
module = pcs->lmodules;
@@ -1277,13 +1310,16 @@
{
struct process pcs;
struct elf_info elf_info;
+ BOOL ret;
memset(&pcs, 0, sizeof(pcs));
pcs.handle = hProc;
- elf_info.flags = ELF_INFO_DEBUG_HEADER;
+ elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_NAME;
if (!elf_search_loader(&pcs, &elf_info)) return FALSE;
pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr;
- return elf_enum_modules_internal(&pcs, cb, user);
+ ret = elf_enum_modules_internal(&pcs, elf_info.module_name, cb, user);
+ HeapFree(GetProcessHeap(), 0, (char*)elf_info.module_name);
+ return ret;
}
struct elf_load
@@ -1329,7 +1365,7 @@
{
struct elf_load el;
- TRACE("(%p %s)\n", pcs, name);
+ TRACE("(%p %s %08lx)\n", pcs, name, addr);
el.elf_info.flags = ELF_INFO_MODULE;
el.ret = FALSE;
@@ -1337,14 +1373,14 @@
if (pcs->dbg_hdr_addr) /* we're debugging a life target */
{
el.pcs = pcs;
- /* do only the lookup from the filename, not the path (as we lookup module name
- * in the process' loaded module list)
+ /* do only the lookup from the filename, not the path (as we lookup module
+ * name in the process' loaded module list)
*/
el.name = strrchr(name, '/');
if (!el.name++) el.name = name;
el.ret = FALSE;
- if (!elf_enum_modules_internal(pcs, elf_load_cb, &el))
+ if (!elf_enum_modules_internal(pcs, NULL, elf_load_cb, &el))
return NULL;
}
else if (addr)
Index: dlls/dbghelp/minidump.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/dbghelp/minidump.c,v
retrieving revision 1.3
diff -u -u -r1.3 minidump.c
--- dlls/dbghelp/minidump.c 23 Mar 2005 13:15:20 -0000 1.3
+++ dlls/dbghelp/minidump.c 28 Mar 2005 16:35:49 -0000
@@ -1,7 +1,7 @@
/*
* File minidump.c - management of dumps (read & write)
*
- * Copyright (C) 2004, Eric Pouech
+ * Copyright (C) 2004-2005, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -45,6 +45,8 @@
unsigned is_elf;
ULONG base;
ULONG size;
+ DWORD timestamp;
+ DWORD checksum;
char name[MAX_PATH];
};
@@ -182,12 +184,15 @@
* Add a module to a dump context
*/
static BOOL add_module(struct dump_context* dc, const char* name,
- DWORD base, DWORD size, BOOL is_elf)
+ DWORD base, DWORD size, DWORD timestamp, DWORD checksum,
+ BOOL is_elf)
{
if (!dc->module)
- dc->module = HeapAlloc(GetProcessHeap(), 0, ++dc->num_module * sizeof(*dc->module));
+ dc->module = HeapAlloc(GetProcessHeap(), 0,
+ ++dc->num_module * sizeof(*dc->module));
else
- dc->module = HeapReAlloc(GetProcessHeap(), 0, dc->module, ++dc->num_module * sizeof(*dc->module));
+ dc->module = HeapReAlloc(GetProcessHeap(), 0, dc->module,
+ ++dc->num_module * sizeof(*dc->module));
if (!dc->module) return FALSE;
if (is_elf ||
!GetModuleFileNameExA(dc->hProcess, (HMODULE)base,
@@ -197,6 +202,8 @@
sizeof(dc->module[dc->num_module - 1].name));
dc->module[dc->num_module - 1].base = base;
dc->module[dc->num_module - 1].size = size;
+ dc->module[dc->num_module - 1].timestamp = timestamp;
+ dc->module[dc->num_module - 1].checksum = checksum;
dc->module[dc->num_module - 1].is_elf = is_elf;
return TRUE;
@@ -210,7 +217,14 @@
static BOOL WINAPI fetch_pe_module_info_cb(char* name, DWORD base, DWORD size,
void* user)
{
- return add_module((struct dump_context*)user, name, base, size, FALSE);
+ struct dump_context* dc = (struct dump_context*)user;
+ IMAGE_NT_HEADERS nth;
+
+ if (pe_load_nt_header(dc->hProcess, base, &nth))
+ add_module((struct dump_context*)user, name, base, size,
+ nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum,
+ FALSE);
+ return TRUE;
}
/******************************************************************
@@ -221,13 +235,22 @@
static BOOL fetch_elf_module_info_cb(const char* name, unsigned long base,
void* user)
{
- return add_module((struct dump_context*)user, name,
- base, 0 /* FIXME */, TRUE);
+ struct dump_context* dc = (struct dump_context*)user;
+ DWORD size, checksum;
+
+ /* FIXME: there's no relevant timestamp on ELF modules */
+ /* NB: if we have a non-null base from the live-target use it (whenever
+ * the ELF module is relocatable or not). If we have a null base (ELF
+ * module isn't relocatable) then grab its base address from ELF file
+ */
+ if (!elf_fetch_file_info(name, base ? NULL : &base, &size, &checksum))
+ size = checksum = 0;
+ add_module(dc, name, base, size, 0 /* FIXME */, checksum, TRUE);
+ return TRUE;
}
static void fetch_module_info(struct dump_context* dc)
{
- WINE_FIXME("--> %p\n", dc->hProcess);
EnumerateLoadedModules(dc->hProcess, fetch_pe_module_info_cb, dc);
/* Since we include ELF modules in a separate stream from the regular PE ones,
* we can always include those ELF modules (they don't eat lots of space)
@@ -352,7 +375,8 @@
for (i = nmod = 0; i < dc->num_module; i++)
{
- if ((dc->module[i].is_elf && dump_elf) || (!dc->module[i].is_elf && !dump_elf))
+ if ((dc->module[i].is_elf && dump_elf) ||
+ (!dc->module[i].is_elf && !dump_elf))
nmod++;
}
@@ -366,7 +390,8 @@
dc->rva += sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod;
for (i = 0; i < dc->num_module; i++)
{
- if ((dc->module[i].is_elf && !dump_elf) || (!dc->module[i].is_elf && dump_elf))
+ if ((dc->module[i].is_elf && !dump_elf) ||
+ (!dc->module[i].is_elf && dump_elf))
continue;
flags_out = ModuleWriteModule | ModuleWriteMiscRecord | ModuleWriteCvRecord;
@@ -396,8 +421,8 @@
cbin.u.Module.FullPath = ms->Buffer;
cbin.u.Module.BaseOfImage = dc->module[i].base;
cbin.u.Module.SizeOfImage = dc->module[i].size;
- cbin.u.Module.CheckSum = 0; /* FIXME */
- cbin.u.Module.TimeDateStamp = 0; /* FIXME */
+ cbin.u.Module.CheckSum = dc->module[i].checksum;
+ cbin.u.Module.TimeDateStamp = dc->module[i].timestamp;
memset(&cbin.u.Module.VersionInfo, 0, sizeof(cbin.u.Module.VersionInfo));
cbin.u.Module.CvRecord = NULL;
cbin.u.Module.SizeOfCvRecord = 0;
@@ -413,8 +438,8 @@
{
mdModule.BaseOfImage = dc->module[i].base;
mdModule.SizeOfImage = dc->module[i].size;
- mdModule.CheckSum = 0; /* FIXME */
- mdModule.TimeDateStamp = 0; /* FIXME */
+ mdModule.CheckSum = dc->module[i].checksum;
+ mdModule.TimeDateStamp = dc->module[i].timestamp;
mdModule.ModuleNameRva = dc->rva;
ms->Length -= sizeof(WCHAR);
append(dc, ms, sizeof(ULONG) + ms->Length);
@@ -619,7 +644,6 @@
/******************************************************************
* MiniDumpWriteDump (DEBUGHLP.@)
*
- *
*/
BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile,
MINIDUMP_TYPE DumpType,
Index: dlls/dbghelp/module.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/dbghelp/module.c,v
retrieving revision 1.10
diff -u -u -r1.10 module.c
--- dlls/dbghelp/module.c 28 Mar 2005 14:17:52 -0000 1.10
+++ dlls/dbghelp/module.c 28 Mar 2005 14:36:40 -0000
@@ -76,6 +76,7 @@
{
struct module* module;
+ assert(type == DMT_ELF || type == DMT_PE);
if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
return NULL;
@@ -93,7 +94,8 @@
module->module.SizeOfStruct = sizeof(module->module);
module->module.BaseOfImage = mod_addr;
module->module.ImageSize = size;
- module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
+ module_fill_module(name, module->module.ModuleName,
+ sizeof(module->module.ModuleName));
module->module.ImageName[0] = '\0';
lstrcpynA(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName));
module->module.SymType = SymNone;
@@ -139,13 +141,15 @@
for (module = pcs->lmodules; module; module = module->next)
{
- if (type == module->type && !strcasecmp(name, module->module.LoadedImageName))
+ if (type == module->type &&
+ !strcasecmp(name, module->module.LoadedImageName))
return module;
}
module_fill_module(name, modname, sizeof(modname));
for (module = pcs->lmodules; module; module = module->next)
{
- if (type == module->type && !strcasecmp(modname, module->module.ModuleName))
+ if (type == module->type &&
+ !strcasecmp(modname, module->module.ModuleName))
return module;
}
}
@@ -258,7 +262,7 @@
return module;
}
-static BOOL module_is_elf_container_loaded(struct process* pcs, const char* ImageName,
+static BOOL module_is_elf_container_loaded(struct process* pcs, const char* ImageName,
const char* ModuleName)
{
char buffer[MAX_PATH];
@@ -281,31 +285,34 @@
return FALSE;
}
-static BOOL elf_is_shared_by_name(const char* name)
+/******************************************************************
+ * module_get_type_by_name
+ *
+ * Guesses a filename type from its extension
+ */
+enum module_type module_get_type_by_name(const char* name)
{
const char* ptr;
int len = strlen(name);
- /* check for terminating .so or .so.[digit]+ */
- while (len)
- {
- for (ptr = name + len - 1; ptr >= name; ptr--) if (*ptr == '.') break;
- if (ptr < name) break;
- if (ptr == name + len - 2 && isdigit(ptr[1]))
- {
- len -= 2;
- continue;
- }
- if (ptr == name + len - 3 && ptr[1] == 's' && ptr[2] == 'o')
- return TRUE;
- break;
+ /* check for terminating .so or .so.[digit] */
+ ptr = strrchr(name, '.');
+ if (ptr)
+ {
+ if (!strcmp(ptr, ".so") ||
+ (isdigit(ptr[1]) && !ptr[2] && ptr >= name + 3 && !memcmp(ptr - 3, ".so", 3)))
+ return DMT_ELF;
+ else if (!strcasecmp(ptr, ".pdb"))
+ return DMT_PDB;
}
- /* wine-[kp]thread is valid too */
- if (((len > 12 && name[len - 13] == '/') || len == 12) &&
+ /* wine-[kp]thread is also an ELF module */
+ else if (((len > 12 && name[len - 13] == '/') || len == 12) &&
(!strcasecmp(name + len - 12, "wine-pthread") ||
!strcasecmp(name + len - 12, "wine-kthread")))
- return TRUE;
- return FALSE;
+ {
+ return DMT_ELF;
+ }
+ return DMT_PE;
}
/***********************************************************************
@@ -333,7 +340,8 @@
if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
{
/* force the loading of DLL as builtin */
- if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
+ if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
+ BaseOfDll, SizeOfDll)))
goto done;
WARN("Couldn't locate %s\n", ImageName);
return 0;
@@ -341,12 +349,13 @@
TRACE("Assuming %s as native DLL\n", ImageName);
if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
{
- if (elf_is_shared_by_name(ImageName) &&
+ if (module_get_type_by_name(ImageName) == DMT_ELF &&
(module = elf_load_module(pcs, ImageName, BaseOfDll)))
goto done;
FIXME("Should have successfully loaded debug information for image %s\n",
ImageName);
- if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
+ if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
+ BaseOfDll, SizeOfDll)))
goto done;
WARN("Couldn't locate %s\n", ImageName);
return 0;
@@ -461,7 +470,6 @@
!GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
continue;
module_fill_module(base, mod, sizeof(mod));
-
EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
UserContext);
}
Index: dlls/dbghelp/path.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/dbghelp/path.c,v
retrieving revision 1.4
diff -u -u -r1.4 path.c
--- dlls/dbghelp/path.c 21 Oct 2004 19:57:56 -0000 1.4
+++ dlls/dbghelp/path.c 28 Mar 2005 16:21:25 -0000
@@ -24,6 +24,10 @@
#include <string.h>
#include "dbghelp_private.h"
+#include "ntstatus.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
@@ -140,7 +144,7 @@
return mptr == match - 1;
}
-static BOOL do_search(const char* file, char* buffer,
+static BOOL do_search(const char* file, char* buffer, BOOL recurse,
PENUMDIRTREE_CALLBACK cb, void* user)
{
HANDLE h;
@@ -161,8 +165,8 @@
if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
strcpy(buffer + pos, fd.cFileName);
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- found = do_search(file, buffer, cb, user);
+ if (recurse && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ found = do_search(file, buffer, TRUE, cb, user);
else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
{
if (!cb || cb(buffer, user)) found = TRUE;
@@ -182,7 +186,7 @@
TRACE("(%s, %s, %p)\n",
debugstr_a(root), debugstr_a(file), buffer);
strcpy(buffer, root);
- return do_search(file, buffer, NULL, NULL);
+ return do_search(file, buffer, TRUE, NULL, NULL);
}
/******************************************************************
@@ -196,11 +200,19 @@
TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
strcpy(buffer, root);
- return do_search(file, buffer, cb, user);
+ return do_search(file, buffer, TRUE, cb, user);
}
struct sffip
{
+ enum module_type kind;
+ /* pe: id -> DWORD:timestamp
+ * two -> size of image (from PE header)
+ * pdb: id -> PDB signature
+ * I think either DWORD:timestamp or GUID:guid depending on PDB version
+ * two -> PDB age ???
+ * elf: id -> DWORD:CRC 32 of ELF image (Wine only)
+ */
PVOID id;
DWORD two;
DWORD three;
@@ -212,11 +224,66 @@
static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
{
struct sffip* s = (struct sffip*)user;
-
+ DWORD size, checksum;
+ DWORD_PTR timestamp;
/* FIXME: should check that id/two/three match the file pointed
* by buffer
*/
- /* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
+ switch (s->kind)
+ {
+ case DMT_PE:
+ {
+ HANDLE hFile, hMap;
+ void* mapping;
+
+ timestamp = ~(DWORD_PTR)s->id;
+ size = ~s->two;
+ hFile = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) return TRUE;
+ if ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
+ {
+ if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
+ {
+ IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping);
+ timestamp = nth->FileHeader.TimeDateStamp;
+ size = nth->OptionalHeader.SizeOfImage;
+ UnmapViewOfFile(mapping);
+ }
+ CloseHandle(hMap);
+ }
+ CloseHandle(hFile);
+ if (timestamp != (DWORD_PTR)s->id || size != s->two)
+ {
+ WARN("Found %s, but wrong size or timestamp\n", buffer);
+ return TRUE;
+ }
+ }
+ break;
+ case DMT_ELF:
+ if (elf_fetch_file_info(buffer, 0, &size, &checksum))
+ {
+ if (checksum != (DWORD_PTR)s->id)
+ {
+ WARN("Found %s, but wrong checksums: %08lx %08lx\n",
+ buffer, checksum, (DWORD_PTR)s->id);
+ return TRUE;
+ }
+ }
+ else
+ {
+ WARN("Couldn't read %s\n", buffer);
+ return TRUE;
+ }
+ break;
+ case DMT_PDB:
+ FIXME("NIY on '%s'\n", buffer);
+ break;
+ default:
+ FIXME("What the heck??\n");
+ return TRUE;
+ }
+ /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite
* convention to stop/continue enumeration. sigh.
*/
return !(s->cb)((char*)buffer, s->user);
@@ -226,7 +293,7 @@
* SymFindFileInPath (DBGHELP.@)
*
*/
-BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
+BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR full_path,
PVOID id, DWORD two, DWORD three, DWORD flags,
LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
PVOID user)
@@ -235,9 +302,10 @@
struct process* pcs = process_find_by_handle(hProcess);
char tmp[MAX_PATH];
char* ptr;
+ char* filename;
TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
- hProcess, searchPath, file, id, two, three, flags,
+ hProcess, searchPath, full_path, id, two, three, flags,
buffer, cb, user);
if (!pcs) return FALSE;
@@ -250,7 +318,15 @@
s.cb = cb;
s.user = user;
- file = file_name(file);
+ filename = file_name(full_path);
+ s.kind = module_get_type_by_name(filename);
+
+ /* first check full path to file */
+ if (sffip_cb(full_path, &s))
+ {
+ strcpy(buffer, full_path);
+ return TRUE;
+ }
while (searchPath)
{
@@ -266,7 +342,8 @@
strcpy(tmp, searchPath);
searchPath = NULL;
}
- if (EnumDirTree(hProcess, tmp, file, buffer, sffip_cb, &s)) return TRUE;
+ if (do_search(filename, tmp, FALSE, sffip_cb, &s)) return TRUE;
}
return FALSE;
}
+
Index: dlls/dbghelp/pe_module.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/dbghelp/pe_module.c,v
retrieving revision 1.10
diff -u -u -r1.10 pe_module.c
--- dlls/dbghelp/pe_module.c 1 Mar 2005 10:39:49 -0000 1.10
+++ dlls/dbghelp/pe_module.c 28 Mar 2005 08:39:50 -0000
@@ -341,7 +341,7 @@
/* FIXME SetLastError */
return NULL;
}
- if ((hFile = FindExecutableImage(name, NULL, loaded_name)) == NULL)
+ if ((hFile = FindExecutableImage(name, pcs->search_path, loaded_name)) == NULL)
return NULL;
opened = TRUE;
}
@@ -381,6 +381,21 @@
}
/******************************************************************
+ * pe_load_nt_header
+ *
+ */
+BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth)
+{
+ IMAGE_DOS_HEADER dos;
+
+ return ReadProcessMemory(hProc, (char*)base, &dos, sizeof(dos), NULL) &&
+ dos.e_magic == IMAGE_DOS_SIGNATURE &&
+ ReadProcessMemory(hProc, (char*)(base + dos.e_lfanew),
+ nth, sizeof(*nth), NULL) &&
+ nth->Signature == IMAGE_NT_SIGNATURE;
+}
+
+/******************************************************************
* pe_load_module_from_pcs
*
*/
@@ -408,14 +423,9 @@
{
if (pcs->dbg_hdr_addr)
{
- IMAGE_DOS_HEADER dos;
IMAGE_NT_HEADERS nth;
- if (ReadProcessMemory(pcs->handle, (char*)base, &dos, sizeof(dos), NULL) &&
- dos.e_magic == IMAGE_DOS_SIGNATURE &&
- ReadProcessMemory(pcs->handle, (char*)(base + dos.e_lfanew),
- &nth, sizeof(nth), NULL) &&
- nth.Signature == IMAGE_NT_SIGNATURE)
+ if (pe_load_nt_header(pcs->handle, base, &nth))
{
if (!size) size = nth.OptionalHeader.SizeOfImage;
module = module_new(pcs, name, DMT_PE, base, size,
Index: include/dbghelp.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/include/dbghelp.h,v
retrieving revision 1.10
diff -u -u -r1.10 dbghelp.h
--- include/dbghelp.h 7 Mar 2005 11:03:21 -0000 1.10
+++ include/dbghelp.h 28 Mar 2005 08:11:08 -0000
@@ -887,6 +887,35 @@
DWORD WINAPI SymGetOptions(void);
DWORD WINAPI SymSetOptions(DWORD);
+/* Symbol server bits */
+typedef BOOL (WINAPI* PSYMBOLSERVERPROC)(LPCSTR, LPCSTR, PVOID, DWORD, DWORD, LPSTR);
+typedef BOOL (WINAPI* PSYMBOLSERVEROPENPROC)(void);
+typedef BOOL (WINAPI* PSYMBOLSERVERCLOSEPROC)(void);
+typedef BOOL (WINAPI* PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR, ULONG64);
+typedef BOOL (CALLBACK* PSYMBOLSERVERCALLBACKPROC)(UINT_PTR, ULONG64, ULONG64);
+typedef UINT_PTR (WINAPI* PSYMBOLSERVERGETOPTIONSPROC)();
+typedef BOOL (WINAPI* PSYMBOLSERVERPINGPROC)(LPCSTR);
+
+#define SSRVOPT_CALLBACK 0x0001
+#define SSRVOPT_DWORD 0x0002
+#define SSRVOPT_DWORDPTR 0x0004
+#define SSRVOPT_GUIDPTR 0x0008
+#define SSRVOPT_OLDGUIDPTR 0x0010
+#define SSRVOPT_UNATTENDED 0x0020
+#define SSRVOPT_NOCOPY 0x0040
+#define SSRVOPT_PARENTWIN 0x0080
+#define SSRVOPT_PARAMTYPE 0x0100
+#define SSRVOPT_SECURE 0x0200
+#define SSRVOPT_TRACE 0x0400
+#define SSRVOPT_SETCONTEXT 0x0800
+#define SSRVOPT_PROXY 0x1000
+#define SSRVOPT_DOWNSTREAM_STORE 0x2000
+#define SSRVOPT_RESET ((ULONG_PTR)-1)
+
+#define SSRVACTION_TRACE 1
+#define SSRVACTION_QUERYCANCEL 2
+#define SSRVACTION_EVENT 3
+
#ifdef __cplusplus
} /* extern "C" */
#endif /* defined(__cplusplus) */