#include <assert.h>
#include "dbghelp_private.h"
+#ifndef DBGHELP_STATIC_LIB
#include "psapi.h"
#include "winternl.h"
#include "wine/debug.h"
+#endif
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
static const WCHAR S_DotDylibW[] = {'.','d','y','l','i','b','\0'};
static const WCHAR S_DotPdbW[] = {'.','p','d','b','\0'};
static const WCHAR S_DotDbgW[] = {'.','d','b','g','\0'};
-const WCHAR S_WineW[] = {'w','i','n','e',0};
const WCHAR S_SlashW[] = {'/','\0'};
static const WCHAR S_AcmW[] = {'.','a','c','m','\0'};
for (e = ext; *e; e++)
{
l = strlenW(*e);
- if (l >= len) return FALSE;
+ if (l >= len) return 0;
if (strncmpiW(&ptr[len - l], *e, l)) continue;
return l;
}
static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size)
{
+ const WCHAR *loader = get_wine_loader_name();
const WCHAR *ptr, *endptr;
size_t len, l;
out[len] = '\0';
if (len > 4 && (l = match_ext(out, len)))
out[len - l] = '\0';
- else if (len > 4 && !strcmpiW(out + len - 4, S_WineW))
+ else if (len > strlenW(loader) && !strcmpiW(out + len - strlenW(loader), loader))
lstrcpynW(out, S_WineLoaderW, size);
else
{
void module_set_module(struct module* module, const WCHAR* name)
{
- module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
- WideCharToMultiByte(CP_ACP, 0, module->module.ModuleName, -1,
- module->module_name, sizeof(module->module_name),
- NULL, NULL);
+ module_fill_module(name, module->module.ModuleName,
+ sizeof(module->module.ModuleName) / sizeof(module->module.ModuleName[0]));
+ module_fill_module(name, module->modulename, sizeof(module->modulename) / sizeof(module->modulename[0]));
+}
+
+const WCHAR *get_wine_loader_name(void)
+{
+ static const BOOL 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)
module->module.TimeDateStamp = stamp;
module->module.CheckSum = checksum;
- memset(module->module.LoadedPdbName, 0, sizeof(module->module.CVData));
+ memset(module->module.LoadedPdbName, 0, sizeof(module->module.LoadedPdbName));
module->module.CVSig = 0;
memset(module->module.CVData, 0, sizeof(module->module.CVData));
module->module.PdbSig = 0;
module->reloc_delta = 0;
module->type = type;
- module->is_virtual = virtual ? TRUE : FALSE;
+ module->is_virtual = virtual;
for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL;
module->sortlist_valid = FALSE;
module->sorttab_size = 0;
*/
hash_table_init(&module->pool, &module->ht_symbols, 4096);
hash_table_init(&module->pool, &module->ht_types, 4096);
+#ifdef __x86_64__
+ hash_table_init(&module->pool, &module->ht_symaddr, 4096);
+#endif
vector_init(&module->vtypes, sizeof(struct symt*), 32);
module->sources_used = 0;
module->sources_alloc = 0;
module->sources = 0;
+ wine_rb_init(&module->sources_offsets_tree, source_rb_compare);
return module;
}
/***********************************************************************
- * module_find_by_name
+ * module_find_by_nameW
*
*/
-static struct module* module_find_by_name(const struct process* pcs, const WCHAR* name)
+struct module* module_find_by_nameW(const struct process* pcs, const WCHAR* name)
{
struct module* module;
WCHAR wname[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, name, -1, wname, sizeof(wname) / sizeof(WCHAR));
- return module_find_by_name(pcs, wname);
+ return module_find_by_nameW(pcs, wname);
}
/***********************************************************************
if (pair->effective->is_virtual) ret = FALSE;
else switch (pair->effective->type)
{
+#ifndef DBGHELP_STATIC_LIB
case DMT_ELF:
- ret = elf_load_debug_info(pair->effective, NULL);
+ ret = elf_load_debug_info(pair->effective);
break;
+#endif
case DMT_PE:
idslW64.SizeOfStruct = sizeof(idslW64);
idslW64.BaseOfImage = pair->effective->module.BaseOfImage;
ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
&idslW64);
break;
+#ifndef DBGHELP_STATIC_LIB
case DMT_MACHO:
- ret = macho_load_debug_info(pair->effective, NULL);
+ ret = macho_load_debug_info(pair->effective);
break;
+#endif
default:
ret = FALSE;
break;
* either the addr where module is loaded, or any address inside the
* module
*/
-struct module* module_find_by_addr(const struct process* pcs, unsigned long addr,
+struct module* module_find_by_addr(const struct process* pcs, DWORD64 addr,
enum module_type type)
{
struct module* module;
return module;
}
}
- SetLastError(ERROR_INVALID_ADDRESS);
+ SetLastError(ERROR_MOD_NOT_FOUND);
return module;
}
*/
enum module_type module_get_type_by_name(const WCHAR* name)
{
- int len = strlenW(name);
+ int loader_len, len = strlenW(name);
+ const WCHAR *loader;
/* Skip all version extensions (.[digits]) regex: "(\.\d+)*$" */
do
{
int i = len;
- while (i && isdigit(name[i - 1])) i--;
+ while (i && name[i - 1] >= '0' && name[i - 1] <= '9') i--;
if (i && name[i - 1] == '.')
len = i - 1;
return DMT_DBG;
/* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */
- if (((len > 4 && name[len - 5] == '/') || len == 4) && !strcmpiW(name + len - 4, S_WineW))
+ 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;
/******************************************************************
* refresh_module_list
*/
+#ifndef DBGHELP_STATIC_LIB
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);
}
+#endif
/***********************************************************************
* SymLoadModule (DBGHELP.@)
if (Flags & ~(SLMFLAG_VIRTUAL))
FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
+#ifndef DBGHELP_STATIC_LIB
refresh_module_list(pcs);
+#endif
/* this is a Wine extension to the API just to redo the synchronisation */
if (!wImageName && !hFile) return 0;
wImageName)
{
/* and finally an ELF or Mach-O module */
+#ifndef DBGHELP_STATIC_LIB
switch (module_get_type_by_name(wImageName))
{
case DMT_ELF:
/* Ignored */
break;
}
+#endif
}
}
if (!module)
DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
{
- if (!validate_addr64(BaseOfDll)) return FALSE;
- return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, SizeOfDll);
+ return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll,
+ NULL, 0);
}
/******************************************************************
pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
if (!validate_addr64(BaseOfDll)) return FALSE;
- module = module_find_by_addr(pcs, (DWORD)BaseOfDll, DMT_UNKNOWN);
+ module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!module) return FALSE;
return module_remove(pcs, module);
}
if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) &&
(module->type == DMT_ELF || module->type == DMT_MACHO))
continue;
- if (!EnumModulesCallback(module->module.ModuleName,
+ if (!EnumModulesCallback(module->modulename,
module->module.BaseOfImage, UserContext))
break;
}
return TRUE;
}
+#ifndef DBGHELP_STATIC_LIB
/******************************************************************
* EnumerateLoadedModules64 (DBGHELP.@)
*
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
!GetModuleBaseNameW(hProcess, hMods[i], baseW, sizeof(baseW) / sizeof(WCHAR)))
continue;
- module_fill_module(baseW, modW, sizeof(modW) / sizeof(CHAR));
+ module_fill_module(baseW, modW, sizeof(modW) / sizeof(modW[0]));
EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage,
UserContext);
}
return sz != 0 && i == sz;
}
+#endif /* DBGHELP_STATIC_LIB */
+
+static void dbghelp_str_WtoA(const WCHAR *src, char *dst, int dst_len)
+{
+ WideCharToMultiByte(CP_ACP, 0, src, -1, dst, dst_len - 1, NULL, NULL);
+ dst[dst_len - 1] = 0;
+}
+
/******************************************************************
* SymGetModuleInfo (DBGHELP.@)
*
miw64.SizeOfStruct = sizeof(miw64);
if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
- mi.SizeOfStruct = miw64.SizeOfStruct;
+ mi.SizeOfStruct = ModuleInfo->SizeOfStruct;
mi.BaseOfImage = miw64.BaseOfImage;
mi.ImageSize = miw64.ImageSize;
mi.TimeDateStamp = miw64.TimeDateStamp;
mi.CheckSum = miw64.CheckSum;
mi.NumSyms = miw64.NumSyms;
mi.SymType = miw64.SymType;
- WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1,
- mi.ModuleName, sizeof(mi.ModuleName), NULL, NULL);
- WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1,
- mi.ImageName, sizeof(mi.ImageName), NULL, NULL);
- WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1,
- mi.LoadedImageName, sizeof(mi.LoadedImageName), NULL, NULL);
+ dbghelp_str_WtoA(miw64.ModuleName, mi.ModuleName, sizeof(mi.ModuleName));
+ dbghelp_str_WtoA(miw64.ImageName, mi.ImageName, sizeof(mi.ImageName));
+ dbghelp_str_WtoA(miw64.LoadedImageName, mi.LoadedImageName, sizeof(mi.LoadedImageName));
memcpy(ModuleInfo, &mi, ModuleInfo->SizeOfStruct);
miw64.SizeOfStruct = sizeof(miw64);
if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
- miw.SizeOfStruct = miw64.SizeOfStruct;
+ miw.SizeOfStruct = ModuleInfo->SizeOfStruct;
miw.BaseOfImage = miw64.BaseOfImage;
miw.ImageSize = miw64.ImageSize;
miw.TimeDateStamp = miw64.TimeDateStamp;
miw64.SizeOfStruct = sizeof(miw64);
if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
- mi64.SizeOfStruct = miw64.SizeOfStruct;
+ mi64.SizeOfStruct = ModuleInfo->SizeOfStruct;
mi64.BaseOfImage = miw64.BaseOfImage;
mi64.ImageSize = miw64.ImageSize;
mi64.TimeDateStamp = miw64.TimeDateStamp;
mi64.CheckSum = miw64.CheckSum;
mi64.NumSyms = miw64.NumSyms;
mi64.SymType = miw64.SymType;
- WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1,
- mi64.ModuleName, sizeof(mi64.ModuleName), NULL, NULL);
- WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1,
- mi64.ImageName, sizeof(mi64.ImageName), NULL, NULL);
- WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1,
- mi64.LoadedImageName, sizeof(mi64.LoadedImageName), NULL, NULL);
- WideCharToMultiByte(CP_ACP, 0, miw64.LoadedPdbName, -1,
- mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName), NULL, NULL);
+ dbghelp_str_WtoA(miw64.ModuleName, mi64.ModuleName, sizeof(mi64.ModuleName));
+ dbghelp_str_WtoA(miw64.ImageName, mi64.ImageName, sizeof(mi64.ImageName));
+ dbghelp_str_WtoA(miw64.LoadedImageName, mi64.LoadedImageName, sizeof(mi64.LoadedImageName));
+ dbghelp_str_WtoA(miw64.LoadedPdbName, mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName));
mi64.CVSig = miw64.CVSig;
- WideCharToMultiByte(CP_ACP, 0, miw64.CVData, -1,
- mi64.CVData, sizeof(mi64.CVData), NULL, NULL);
+ dbghelp_str_WtoA(miw64.CVData, mi64.CVData, sizeof(mi64.CVData));
mi64.PdbSig = miw64.PdbSig;
mi64.PdbSig70 = miw64.PdbSig70;
mi64.PdbAge = miw64.PdbAge;
if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
+#ifndef DBGHELP_STATIC_LIB
return refresh_module_list(pcs);
+#else
+ return TRUE;
+#endif
}
/***********************************************************************