#include "dbghelp_private.h"
#include "psapi.h"
-#include "winreg.h"
#include "winternl.h"
#include "wine/debug.h"
const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'};
const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'};
static const WCHAR S_DotSoW[] = {'.','s','o','\0'};
+static const WCHAR S_DotDylibW[] = {'.','d','y','l','i','b','\0'};
static const WCHAR S_DotPdbW[] = {'.','p','d','b','\0'};
-static const WCHAR S_WinePThreadW[] = {'w','i','n','e','-','p','t','h','r','e','a','d','\0'};
-static const WCHAR S_WineKThreadW[] = {'w','i','n','e','-','k','t','h','r','e','a','d','\0'};
+static const WCHAR S_DotDbgW[] = {'.','d','b','g','\0'};
+const WCHAR S_SlashW[] = {'/','\0'};
static const WCHAR S_AcmW[] = {'.','a','c','m','\0'};
static const WCHAR S_DllW[] = {'.','d','l','l','\0'};
return 0;
}
+static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr)
+{
+ const WCHAR* ptr;
+
+ if (!endptr) endptr = name + strlenW(name);
+ for (ptr = endptr - 1; ptr >= name; ptr--)
+ {
+ if (*ptr == '/' || *ptr == '\\') break;
+ }
+ return ++ptr;
+}
+
static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size)
{
- const WCHAR *ptr,*endptr;
+ const WCHAR *loader = get_wine_loader_name();
+ const WCHAR *ptr, *endptr;
size_t len, l;
- endptr = in + strlenW(in);
- for (ptr = endptr - 1;
- ptr >= in && *ptr != '/' && *ptr != '\\';
- ptr--);
- ptr++;
- len = min(endptr-ptr,size-1);
+ ptr = get_filename(in, endptr = in + strlenW(in));
+ len = min(endptr - ptr, size - 1);
memcpy(out, ptr, len * sizeof(WCHAR));
out[len] = '\0';
if (len > 4 && (l = match_ext(out, len)))
out[len - l] = '\0';
- else if (len > 12 &&
- (!strcmpiW(out + len - 12, S_WinePThreadW) ||
- !strcmpiW(out + len - 12, S_WineKThreadW)))
+ else if (len > strlenW(loader) && !strcmpiW(out + len - strlenW(loader), loader))
lstrcpynW(out, S_WineLoaderW, size);
else
{
NULL, NULL);
}
+const WCHAR *get_wine_loader_name(void)
+{
+ static const int is_win64 = sizeof(void *) > sizeof(int); /* FIXME: should depend on target process */
+ static const WCHAR wineW[] = {'w','i','n','e',0};
+ static const WCHAR suffixW[] = {'6','4',0};
+ static const WCHAR *loader;
+
+ if (!loader)
+ {
+ WCHAR *p, *buffer;
+ const char *ptr;
+
+ /* All binaries are loaded with WINELOADER (if run from tree) or by the
+ * main executable
+ */
+ if ((ptr = getenv("WINELOADER")))
+ {
+ DWORD len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, NULL, 0 );
+ buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+ MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, buffer, len );
+ }
+ else
+ {
+ buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(wineW) + 2 * sizeof(WCHAR) );
+ strcpyW( buffer, wineW );
+ }
+ p = buffer + strlenW( buffer ) - strlenW( suffixW );
+ if (p > buffer && !strcmpW( p, suffixW ))
+ {
+ if (!is_win64) *p = 0;
+ }
+ else if (is_win64) strcatW( buffer, suffixW );
+
+ TRACE( "returning %s\n", debugstr_w(buffer) );
+ loader = buffer;
+ }
+ return loader;
+}
+
static const char* get_module_type(enum module_type type, BOOL virtual)
{
switch (type)
{
case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
case DMT_PE: return virtual ? "Virtual PE" : "PE";
+ case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O";
default: return "---";
}
}
*/
struct module* module_new(struct process* pcs, const WCHAR* name,
enum module_type type, BOOL virtual,
- unsigned long mod_addr, unsigned long size,
+ DWORD64 mod_addr, DWORD64 size,
unsigned long stamp, unsigned long checksum)
{
struct module* module;
+ unsigned i;
- assert(type == DMT_ELF || type == DMT_PE);
- if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
+ assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO);
+ if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module))))
return NULL;
- memset(module, 0, sizeof(*module));
-
module->next = pcs->lmodules;
pcs->lmodules = module;
- TRACE("=> %s %08lx-%08lx %s\n",
- get_module_type(type, virtual), mod_addr, mod_addr + size,
+ TRACE("=> %s %s-%s %s\n",
+ get_module_type(type, virtual),
+ wine_dbgstr_longlong(mod_addr), wine_dbgstr_longlong(mod_addr + size),
debugstr_w(name));
pool_init(&module->pool, 65536);
+ module->process = pcs;
module->module.SizeOfStruct = sizeof(module->module);
module->module.BaseOfImage = mod_addr;
module->module.ImageSize = size;
module->module.SourceIndexed = FALSE;
module->module.Publics = FALSE;
+ module->reloc_delta = 0;
module->type = type;
module->is_virtual = virtual ? TRUE : FALSE;
+ for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL;
module->sortlist_valid = FALSE;
+ module->sorttab_size = 0;
module->addr_sorttab = NULL;
+ module->num_sorttab = 0;
+ module->num_symbols = 0;
+
+ vector_init(&module->vsymt, sizeof(struct symt*), 128);
/* FIXME: this seems a bit too high (on a per module basis)
* need some statistics about this
*/
module->sources_used = 0;
module->sources_alloc = 0;
module->sources = 0;
+ wine_rb_init(&module->sources_offsets_tree, &source_rb_functions);
return module;
}
* module_find_by_name
*
*/
-struct module* module_find_by_name(const struct process* pcs,
- const WCHAR* name, enum module_type type)
+static struct module* module_find_by_name(const struct process* pcs, const WCHAR* name)
{
struct module* module;
- if (type == DMT_UNKNOWN)
- {
- if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
- (module = module_find_by_name(pcs, name, DMT_ELF)))
- return module;
- }
- else
+ for (module = pcs->lmodules; module; module = module->next)
{
- WCHAR modname[MAX_PATH];
-
- for (module = pcs->lmodules; module; module = module->next)
- {
- if (type == module->type &&
- !strcmpiW(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 &&
- !strcmpiW(modname, module->module.ModuleName))
- return module;
- }
+ if (!strcmpiW(name, module->module.ModuleName)) return module;
}
SetLastError(ERROR_INVALID_NAME);
return NULL;
}
-struct module* module_find_by_nameA(const struct process* pcs,
- const char* name, enum module_type type)
+struct module* module_find_by_nameA(const struct process* pcs, const char* name)
{
WCHAR wname[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, name, -1, wname, sizeof(wname) / sizeof(WCHAR));
- return module_find_by_name(pcs, wname, type);
+ return module_find_by_name(pcs, wname);
+}
+
+/***********************************************************************
+ * module_is_already_loaded
+ *
+ */
+struct module* module_is_already_loaded(const struct process* pcs, const WCHAR* name)
+{
+ struct module* module;
+ const WCHAR* filename;
+
+ /* first compare the loaded image name... */
+ for (module = pcs->lmodules; module; module = module->next)
+ {
+ if (!strcmpiW(name, module->module.LoadedImageName))
+ return module;
+ }
+ /* then compare the standard filenames (without the path) ... */
+ filename = get_filename(name, NULL);
+ for (module = pcs->lmodules; module; module = module->next)
+ {
+ if (!strcmpiW(filename, get_filename(module->module.LoadedImageName, NULL)))
+ return module;
+ }
+ SetLastError(ERROR_INVALID_NAME);
+ return NULL;
}
/***********************************************************************
* module_get_container
*
*/
-struct module* module_get_container(const struct process* pcs,
+static struct module* module_get_container(const struct process* pcs,
const struct module* inner)
{
struct module* module;
else switch (pair->effective->type)
{
case DMT_ELF:
- ret = elf_load_debug_info(pair->effective, NULL);
+ ret = elf_load_debug_info(pair->effective);
break;
case DMT_PE:
idslW64.SizeOfStruct = sizeof(idslW64);
idslW64.CheckSum = pair->effective->module.CheckSum;
idslW64.TimeDateStamp = pair->effective->module.TimeDateStamp;
memcpy(idslW64.FileName, pair->effective->module.ImageName,
- sizeof(idslW64.FileName));
+ sizeof(pair->effective->module.ImageName));
idslW64.Reparse = FALSE;
idslW64.hFile = INVALID_HANDLE_VALUE;
ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
&idslW64);
break;
+ case DMT_MACHO:
+ ret = macho_load_debug_info(pair->effective, NULL);
+ break;
default:
ret = FALSE;
break;
if (type == DMT_UNKNOWN)
{
if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
- (module = module_find_by_addr(pcs, addr, DMT_ELF)))
+ (module = module_find_by_addr(pcs, addr, DMT_ELF)) ||
+ (module = module_find_by_addr(pcs, addr, DMT_MACHO)))
return module;
}
else
return module;
}
-static BOOL module_is_elf_container_loaded(struct process* pcs,
- const WCHAR* ImageName,
- const WCHAR* ModuleName)
+/******************************************************************
+ * module_is_container_loaded
+ *
+ * checks whether the native container, for a (supposed) PE builtin is
+ * already loaded
+ */
+static BOOL module_is_container_loaded(const struct process* pcs,
+ const WCHAR* ImageName, DWORD64 base)
{
- WCHAR buffer[MAX_PATH];
size_t len;
struct module* module;
+ PCWSTR filename, modname;
+
+ if (!base) return FALSE;
+ filename = get_filename(ImageName, NULL);
+ len = strlenW(filename);
- if (!ModuleName)
- {
- module_fill_module(ImageName, buffer, sizeof(buffer));
- ModuleName = buffer;
- }
- len = strlenW(ModuleName);
for (module = pcs->lmodules; module; module = module->next)
{
- if (!strncmpiW(module->module.ModuleName, ModuleName, len) &&
- module->type == DMT_ELF &&
- !strcmpW(module->module.ModuleName + len, S_ElfW))
- return TRUE;
+ if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
+ base >= module->module.BaseOfImage &&
+ base < module->module.BaseOfImage + module->module.ImageSize)
+ {
+ modname = get_filename(module->module.LoadedImageName, NULL);
+ if (!strncmpiW(modname, filename, len) &&
+ !memcmp(modname + len, S_DotSoW, 3 * sizeof(WCHAR)))
+ {
+ return TRUE;
+ }
+ }
}
+ /* likely a native PE module */
+ WARN("Couldn't find container for %s\n", debugstr_w(ImageName));
return FALSE;
}
*/
enum module_type module_get_type_by_name(const WCHAR* name)
{
- const WCHAR*ptr;
- int len = strlenW(name);
+ int loader_len, len = strlenW(name);
+ const WCHAR *loader;
- /* check for terminating .so or .so.[digit] */
- ptr = strrchrW(name, '.');
- if (ptr)
+ /* Skip all version extensions (.[digits]) regex: "(\.\d+)*$" */
+ do
{
- if (!strcmpW(ptr, S_DotSoW) ||
- (isdigit(ptr[1]) && !ptr[2] && ptr >= name + 3 && !memcmp(ptr - 3, S_DotSoW, 3)))
- return DMT_ELF;
- else if (!strcmpiW(ptr, S_DotPdbW))
- return DMT_PDB;
- }
- /* wine-[kp]thread is also an ELF module */
- else if (((len > 12 && name[len - 13] == '/') || len == 12) &&
- (!strcmpiW(name + len - 12, S_WinePThreadW) ||
- !strcmpiW(name + len - 12, S_WineKThreadW)))
+ int i = len;
+
+ while (i && isdigit(name[i - 1])) i--;
+
+ if (i && name[i - 1] == '.')
+ len = i - 1;
+ else
+ break;
+ } while (len);
+
+ /* check for terminating .so or .so.[digit] */
+ /* FIXME: Can't rely solely on extension; have to check magic or
+ * stop using .so on Mac OS X. For now, base on platform. */
+ if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3))
+#ifdef __APPLE__
+ return DMT_MACHO;
+#else
+ return DMT_ELF;
+#endif
+
+ if (len > 6 && !strncmpiW(name + len - 6, S_DotDylibW, 6))
+ return DMT_MACHO;
+
+ if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4))
+ return DMT_PDB;
+
+ if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4))
+ return DMT_DBG;
+
+ /* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */
+ loader = get_wine_loader_name();
+ loader_len = strlenW( loader );
+ if ((len == loader_len || (len > loader_len && name[len - loader_len - 1] == '/')) &&
+ !strcmpiW(name + len - loader_len, loader))
{
+#ifdef __APPLE__
+ return DMT_MACHO;
+#else
return DMT_ELF;
+#endif
}
return DMT_PE;
}
+/******************************************************************
+ * refresh_module_list
+ */
+static BOOL refresh_module_list(struct process* pcs)
+{
+ /* force transparent ELF and Mach-O loading / unloading */
+ return elf_synchronize_module_list(pcs) || macho_synchronize_module_list(pcs);
+}
+
/***********************************************************************
* SymLoadModule (DBGHELP.@)
*/
-DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, const char* ImageName,
- const char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
+DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
+ PCSTR ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
{
return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll,
SizeOfDll, NULL, 0);
PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize,
PMODLOAD_DATA Data, DWORD Flags)
{
- LPWSTR wImageName, wModuleName;
+ PWSTR wImageName, wModuleName;
unsigned len;
DWORD64 ret;
if (Flags & SLMFLAG_VIRTUAL)
{
+ if (!wImageName) return FALSE;
module = module_new(pcs, wImageName, module_get_type_by_name(wImageName),
- TRUE, (DWORD)BaseOfDll, SizeOfDll, 0, 0);
+ TRUE, BaseOfDll, SizeOfDll, 0, 0);
if (!module) return FALSE;
if (wModuleName) module_set_module(module, wModuleName);
module->module.SymType = SymVirtual;
if (Flags & ~(SLMFLAG_VIRTUAL))
FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
- /* force transparent ELF loading / unloading */
- elf_synchronize_module_list(pcs);
+ refresh_module_list(pcs);
/* this is a Wine extension to the API just to redo the synchronisation */
if (!wImageName && !hFile) return 0;
- if (module_is_elf_container_loaded(pcs, wImageName, wModuleName))
+ /* check if the module is already loaded, or if it's a builtin PE module with
+ * an containing ELF module
+ */
+ if (wImageName)
{
- /* force the loading of DLL as builtin */
- if ((module = pe_load_module_from_pcs(pcs, wImageName, wModuleName,
- BaseOfDll, SizeOfDll)))
- goto done;
- WARN("Couldn't locate %s\n", debugstr_w(wImageName));
- return 0;
+ module = module_is_already_loaded(pcs, wImageName);
+ if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll))
+ {
+ /* force the loading of DLL as builtin */
+ module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll);
+ }
}
- TRACE("Assuming %s as native DLL\n", debugstr_w(wImageName));
- if (!(module = pe_load_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)))
+ if (!module)
+ {
+ /* otherwise, try a regular PE module */
+ if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) &&
+ wImageName)
+ {
+ /* and finally an ELF or Mach-O module */
+ switch (module_get_type_by_name(wImageName))
+ {
+ case DMT_ELF:
+ module = elf_load_module(pcs, wImageName, BaseOfDll);
+ break;
+ case DMT_MACHO:
+ module = macho_load_module(pcs, wImageName, BaseOfDll);
+ break;
+ default:
+ /* Ignored */
+ break;
+ }
+ }
+ }
+ if (!module)
{
- if (module_get_type_by_name(wImageName) == DMT_ELF &&
- (module = elf_load_module(pcs, wImageName, BaseOfDll)))
- goto done;
- FIXME("Should have successfully loaded debug information for image %s\n",
- debugstr_w(wImageName));
- if ((module = pe_load_module_from_pcs(pcs, wImageName, wModuleName,
- BaseOfDll, SizeOfDll)))
- goto done;
WARN("Couldn't locate %s\n", debugstr_w(wImageName));
return 0;
}
module->module.NumSyms = module->ht_symbols.num_elts;
-done:
- /* by default pe_load_module fills module.ModuleName from a derivation
- * of ImageName. Overwrite it, if we have better information
+ /* by default module_new fills module.ModuleName from a derivation
+ * of LoadedImageName. Overwrite it, if we have better information
*/
if (wModuleName)
module_set_module(module, wModuleName);
- lstrcpynW(module->module.ImageName, wImageName,
- sizeof(module->module.ImageName) / sizeof(CHAR));
+ if (wImageName)
+ lstrcpynW(module->module.ImageName, wImageName,
+ sizeof(module->module.ImageName) / sizeof(WCHAR));
return module->module.BaseOfImage;
}
*/
BOOL module_remove(struct process* pcs, struct module* module)
{
+ struct module_format*modfmt;
struct module** p;
+ unsigned i;
+
+ TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module);
- TRACE("%s (%p)\n", module->module_name, module);
+ for (i = 0; i < DFI_LAST; i++)
+ {
+ if ((modfmt = module->format_info[i]) && modfmt->remove)
+ modfmt->remove(pcs, module->format_info[i]);
+ }
hash_table_destroy(&module->ht_symbols);
hash_table_destroy(&module->ht_types);
- HeapFree(GetProcessHeap(), 0, (char*)module->sources);
+ wine_rb_destroy(&module->sources_offsets_tree, NULL, NULL);
+ HeapFree(GetProcessHeap(), 0, module->sources);
HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
- HeapFree(GetProcessHeap(), 0, module->dwarf2_info);
pool_destroy(&module->pool);
/* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here
* so do we
* SymEnumerateModules (DBGHELP.@)
*
*/
+struct enum_modW64_32
+{
+ PSYM_ENUMMODULES_CALLBACK cb;
+ PVOID user;
+ char module[MAX_PATH];
+};
+
+static BOOL CALLBACK enum_modW64_32(PCWSTR name, DWORD64 base, PVOID user)
+{
+ struct enum_modW64_32* x = user;
+
+ WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
+ return x->cb(x->module, (DWORD)base, x->user);
+}
+
BOOL WINAPI SymEnumerateModules(HANDLE hProcess,
PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
PVOID UserContext)
{
- struct process* pcs = process_find_by_handle(hProcess);
- struct module* module;
+ struct enum_modW64_32 x;
- if (!pcs) return FALSE;
-
- for (module = pcs->lmodules; module; module = module->next)
- {
- if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
- continue;
- if (!EnumModulesCallback(module->module_name,
- module->module.BaseOfImage, UserContext))
- break;
- }
- return TRUE;
+ x.cb = EnumModulesCallback;
+ x.user = UserContext;
+
+ return SymEnumerateModulesW64(hProcess, enum_modW64_32, &x);
}
/******************************************************************
* SymEnumerateModules64 (DBGHELP.@)
*
*/
+struct enum_modW64_64
+{
+ PSYM_ENUMMODULES_CALLBACK64 cb;
+ PVOID user;
+ char module[MAX_PATH];
+};
+
+static BOOL CALLBACK enum_modW64_64(PCWSTR name, DWORD64 base, PVOID user)
+{
+ struct enum_modW64_64* x = user;
+
+ WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
+ return x->cb(x->module, base, x->user);
+}
+
BOOL WINAPI SymEnumerateModules64(HANDLE hProcess,
PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,
PVOID UserContext)
+{
+ struct enum_modW64_64 x;
+
+ x.cb = EnumModulesCallback;
+ x.user = UserContext;
+
+ return SymEnumerateModulesW64(hProcess, enum_modW64_64, &x);
+}
+
+/******************************************************************
+ * SymEnumerateModulesW64 (DBGHELP.@)
+ *
+ */
+BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess,
+ PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback,
+ PVOID UserContext)
{
struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
for (module = pcs->lmodules; module; module = module->next)
{
- if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
+ if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) &&
+ (module->type == DMT_ELF || module->type == DMT_MACHO))
continue;
- if (!EnumModulesCallback(module->module_name,
+ if (!EnumModulesCallback(module->module.ModuleName,
module->module.BaseOfImage, UserContext))
break;
}
char module[MAX_PATH];
};
-static BOOL CALLBACK enum_load_modW64_64(PWSTR name, DWORD64 base, ULONG size,
+static BOOL CALLBACK enum_load_modW64_64(PCWSTR name, DWORD64 base, ULONG size,
PVOID user)
{
struct enum_load_modW64_64* x = user;
char module[MAX_PATH];
};
-static BOOL CALLBACK enum_load_modW64_32(PWSTR name, DWORD64 base, ULONG size,
+static BOOL CALLBACK enum_load_modW64_32(PCWSTR name, DWORD64 base, ULONG size,
PVOID user)
{
struct enum_load_modW64_32* x = user;
IMAGEHLP_MODULE64 mi64;
IMAGEHLP_MODULEW64 miw64;
- if (sizeof(mi64) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
+ if (sizeof(mi64) < ModuleInfo->SizeOfStruct)
+ {
+ SetLastError(ERROR_MOD_NOT_FOUND); /* NOTE: native returns this error */
+ WARN("Wrong size %u\n", ModuleInfo->SizeOfStruct);
+ return FALSE;
+ }
miw64.SizeOfStruct = sizeof(miw64);
if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
*/
DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
{
- struct process* pcs = process_find_by_handle(hProcess);
- struct module* module;
+ DWORD64 ret;
- if (!pcs) return 0;
- module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
- if (!module) return 0;
- return module->module.BaseOfImage;
+ ret = SymGetModuleBase64(hProcess, dwAddr);
+ return validate_addr64(ret) ? ret : 0;
}
/***********************************************************************
*/
DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
{
- if (!validate_addr64(dwAddr)) return 0;
- return SymGetModuleBase(hProcess, (DWORD)dwAddr);
+ struct process* pcs = process_find_by_handle(hProcess);
+ struct module* module;
+
+ if (!pcs) return 0;
+ module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
+ if (!module) return 0;
+ return module->module.BaseOfImage;
}
/******************************************************************
void module_reset_debug_info(struct module* module)
{
module->sortlist_valid = TRUE;
+ module->sorttab_size = 0;
module->addr_sorttab = NULL;
+ module->num_sorttab = module->num_symbols = 0;
hash_table_destroy(&module->ht_symbols);
module->ht_symbols.num_buckets = 0;
module->ht_symbols.buckets = NULL;
module->sources_used = module->sources_alloc = 0;
module->sources = NULL;
}
+
+/******************************************************************
+ * SymRefreshModuleList (DBGHELP.@)
+ */
+BOOL WINAPI SymRefreshModuleList(HANDLE hProcess)
+{
+ struct process* pcs;
+
+ TRACE("(%p)\n", hProcess);
+
+ if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
+
+ return refresh_module_list(pcs);
+}
+
+/***********************************************************************
+ * SymFunctionTableAccess (DBGHELP.@)
+ */
+PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
+{
+ return SymFunctionTableAccess64(hProcess, AddrBase);
+}
+
+/***********************************************************************
+ * SymFunctionTableAccess64 (DBGHELP.@)
+ */
+PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
+{
+ struct process* pcs = process_find_by_handle(hProcess);
+ struct module* module;
+
+ if (!pcs || !dbghelp_current_cpu->find_runtime_function) return NULL;
+ module = module_find_by_addr(pcs, AddrBase, DMT_UNKNOWN);
+ if (!module) return NULL;
+
+ return dbghelp_current_cpu->find_runtime_function(module, AddrBase);
+}