2 * File module.c - module handling for the wine debugger
4 * Copyright (C) 1993, Eric Youngdale.
5 * 2000-2007, Eric Pouech
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "dbghelp_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
36 const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'};
37 const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'};
38 static const WCHAR S_DotSoW[] = {'.','s','o','\0'};
39 static const WCHAR S_DotPdbW[] = {'.','p','d','b','\0'};
40 const WCHAR S_WinePThreadW[] = {'w','i','n','e','-','p','t','h','r','e','a','d','\0'};
41 const WCHAR S_WineKThreadW[] = {'w','i','n','e','-','k','t','h','r','e','a','d','\0'};
42 const WCHAR S_SlashW[] = {'/','\0'};
44 static const WCHAR S_AcmW[] = {'.','a','c','m','\0'};
45 static const WCHAR S_DllW[] = {'.','d','l','l','\0'};
46 static const WCHAR S_DrvW[] = {'.','d','r','v','\0'};
47 static const WCHAR S_ExeW[] = {'.','e','x','e','\0'};
48 static const WCHAR S_OcxW[] = {'.','o','c','x','\0'};
49 static const WCHAR S_VxdW[] = {'.','v','x','d','\0'};
50 static const WCHAR * const ext[] = {S_AcmW, S_DllW, S_DrvW, S_ExeW, S_OcxW, S_VxdW, NULL};
52 static int match_ext(const WCHAR* ptr, size_t len)
54 const WCHAR* const *e;
57 for (e = ext; *e; e++)
60 if (l >= len) return FALSE;
61 if (strncmpiW(&ptr[len - l], *e, l)) continue;
67 static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size)
69 const WCHAR *ptr,*endptr;
72 endptr = in + strlenW(in);
73 for (ptr = endptr - 1;
74 ptr >= in && *ptr != '/' && *ptr != '\\';
77 len = min(endptr-ptr,size-1);
78 memcpy(out, ptr, len * sizeof(WCHAR));
80 if (len > 4 && (l = match_ext(out, len)))
83 (!strcmpiW(out + len - 12, S_WinePThreadW) ||
84 !strcmpiW(out + len - 12, S_WineKThreadW)))
85 lstrcpynW(out, S_WineLoaderW, size);
88 if (len > 3 && !strcmpiW(&out[len - 3], S_DotSoW) &&
89 (l = match_ext(out, len - 3)))
90 strcpyW(&out[len - l - 3], S_ElfW);
92 while ((*out = tolowerW(*out))) out++;
95 void module_set_module(struct module* module, const WCHAR* name)
97 module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
98 WideCharToMultiByte(CP_ACP, 0, module->module.ModuleName, -1,
99 module->module_name, sizeof(module->module_name),
103 static const char* get_module_type(enum module_type type, BOOL virtual)
107 case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
108 case DMT_PE: return virtual ? "Virtual PE" : "PE";
109 default: return "---";
113 /***********************************************************************
114 * Creates and links a new module to a process
116 struct module* module_new(struct process* pcs, const WCHAR* name,
117 enum module_type type, BOOL virtual,
118 unsigned long mod_addr, unsigned long size,
119 unsigned long stamp, unsigned long checksum)
121 struct module* module;
123 assert(type == DMT_ELF || type == DMT_PE);
124 if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
127 memset(module, 0, sizeof(*module));
129 module->next = pcs->lmodules;
130 pcs->lmodules = module;
132 TRACE("=> %s %08lx-%08lx %s\n",
133 get_module_type(type, virtual), mod_addr, mod_addr + size,
136 pool_init(&module->pool, 65536);
138 module->module.SizeOfStruct = sizeof(module->module);
139 module->module.BaseOfImage = mod_addr;
140 module->module.ImageSize = size;
141 module_set_module(module, name);
142 module->module.ImageName[0] = '\0';
143 lstrcpynW(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName) / sizeof(WCHAR));
144 module->module.SymType = SymNone;
145 module->module.NumSyms = 0;
146 module->module.TimeDateStamp = stamp;
147 module->module.CheckSum = checksum;
149 memset(module->module.LoadedPdbName, 0, sizeof(module->module.CVData));
150 module->module.CVSig = 0;
151 memset(module->module.CVData, 0, sizeof(module->module.CVData));
152 module->module.PdbSig = 0;
153 memset(&module->module.PdbSig70, 0, sizeof(module->module.PdbSig70));
154 module->module.PdbAge = 0;
155 module->module.PdbUnmatched = FALSE;
156 module->module.DbgUnmatched = FALSE;
157 module->module.LineNumbers = FALSE;
158 module->module.GlobalSymbols = FALSE;
159 module->module.TypeInfo = FALSE;
160 module->module.SourceIndexed = FALSE;
161 module->module.Publics = FALSE;
164 module->is_virtual = virtual ? TRUE : FALSE;
165 module->sortlist_valid = FALSE;
166 module->addr_sorttab = NULL;
167 /* FIXME: this seems a bit too high (on a per module basis)
168 * need some statistics about this
170 hash_table_init(&module->pool, &module->ht_symbols, 4096);
171 hash_table_init(&module->pool, &module->ht_types, 4096);
172 vector_init(&module->vtypes, sizeof(struct symt*), 32);
174 module->sources_used = 0;
175 module->sources_alloc = 0;
181 /***********************************************************************
182 * module_find_by_name
185 struct module* module_find_by_name(const struct process* pcs,
186 const WCHAR* name, enum module_type type)
188 struct module* module;
190 if (type == DMT_UNKNOWN)
192 if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
193 (module = module_find_by_name(pcs, name, DMT_ELF)))
198 WCHAR modname[MAX_PATH];
200 for (module = pcs->lmodules; module; module = module->next)
202 if (type == module->type &&
203 !strcmpiW(name, module->module.LoadedImageName))
206 module_fill_module(name, modname, sizeof(modname));
207 for (module = pcs->lmodules; module; module = module->next)
209 if (type == module->type &&
210 !strcmpiW(modname, module->module.ModuleName))
214 SetLastError(ERROR_INVALID_NAME);
218 struct module* module_find_by_nameA(const struct process* pcs,
219 const char* name, enum module_type type)
221 WCHAR wname[MAX_PATH];
223 MultiByteToWideChar(CP_ACP, 0, name, -1, wname, sizeof(wname) / sizeof(WCHAR));
224 return module_find_by_name(pcs, wname, type);
227 /***********************************************************************
228 * module_get_container
231 struct module* module_get_container(const struct process* pcs,
232 const struct module* inner)
234 struct module* module;
236 for (module = pcs->lmodules; module; module = module->next)
238 if (module != inner &&
239 module->module.BaseOfImage <= inner->module.BaseOfImage &&
240 module->module.BaseOfImage + module->module.ImageSize >=
241 inner->module.BaseOfImage + inner->module.ImageSize)
247 /***********************************************************************
248 * module_get_containee
251 struct module* module_get_containee(const struct process* pcs,
252 const struct module* outter)
254 struct module* module;
256 for (module = pcs->lmodules; module; module = module->next)
258 if (module != outter &&
259 outter->module.BaseOfImage <= module->module.BaseOfImage &&
260 outter->module.BaseOfImage + outter->module.ImageSize >=
261 module->module.BaseOfImage + module->module.ImageSize)
267 /******************************************************************
270 * get the debug information from a module:
271 * - if the module's type is deferred, then force loading of debug info (and return
273 * - if the module has no debug info and has an ELF container, then return the ELF
274 * container (and also force the ELF container's debug info loading if deferred)
275 * - otherwise return the module itself if it has some debug info
277 BOOL module_get_debug(struct module_pair* pair)
279 IMAGEHLP_DEFERRED_SYMBOL_LOADW64 idslW64;
281 if (!pair->requested) return FALSE;
282 /* for a PE builtin, always get info from container */
283 if (!(pair->effective = module_get_container(pair->pcs, pair->requested)))
284 pair->effective = pair->requested;
285 /* if deferred, force loading */
286 if (pair->effective->module.SymType == SymDeferred)
290 if (pair->effective->is_virtual) ret = FALSE;
291 else switch (pair->effective->type)
294 ret = elf_load_debug_info(pair->effective, NULL);
297 idslW64.SizeOfStruct = sizeof(idslW64);
298 idslW64.BaseOfImage = pair->effective->module.BaseOfImage;
299 idslW64.CheckSum = pair->effective->module.CheckSum;
300 idslW64.TimeDateStamp = pair->effective->module.TimeDateStamp;
301 memcpy(idslW64.FileName, pair->effective->module.ImageName,
302 sizeof(idslW64.FileName));
303 idslW64.Reparse = FALSE;
304 idslW64.hFile = INVALID_HANDLE_VALUE;
306 pcs_callback(pair->pcs, CBA_DEFERRED_SYMBOL_LOAD_START, &idslW64);
307 ret = pe_load_debug_info(pair->pcs, pair->effective);
308 pcs_callback(pair->pcs,
309 ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
316 if (!ret) pair->effective->module.SymType = SymNone;
317 assert(pair->effective->module.SymType != SymDeferred);
318 pair->effective->module.NumSyms = pair->effective->ht_symbols.num_elts;
320 return pair->effective->module.SymType != SymNone;
323 /***********************************************************************
324 * module_find_by_addr
326 * either the addr where module is loaded, or any address inside the
329 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr,
330 enum module_type type)
332 struct module* module;
334 if (type == DMT_UNKNOWN)
336 if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
337 (module = module_find_by_addr(pcs, addr, DMT_ELF)))
342 for (module = pcs->lmodules; module; module = module->next)
344 if (type == module->type && addr >= module->module.BaseOfImage &&
345 addr < module->module.BaseOfImage + module->module.ImageSize)
349 SetLastError(ERROR_INVALID_ADDRESS);
353 static BOOL module_is_elf_container_loaded(struct process* pcs,
354 const WCHAR* ImageName,
355 const WCHAR* ModuleName)
357 WCHAR buffer[MAX_PATH];
359 struct module* module;
363 module_fill_module(ImageName, buffer, sizeof(buffer));
366 len = strlenW(ModuleName);
367 for (module = pcs->lmodules; module; module = module->next)
369 if (!strncmpiW(module->module.ModuleName, ModuleName, len) &&
370 module->type == DMT_ELF &&
371 !strcmpW(module->module.ModuleName + len, S_ElfW))
377 /******************************************************************
378 * module_get_type_by_name
380 * Guesses a filename type from its extension
382 enum module_type module_get_type_by_name(const WCHAR* name)
385 int len = strlenW(name);
387 /* check for terminating .so or .so.[digit] */
388 ptr = strrchrW(name, '.');
391 if (!strcmpW(ptr, S_DotSoW) ||
392 (isdigit(ptr[1]) && !ptr[2] && ptr >= name + 3 && !memcmp(ptr - 3, S_DotSoW, 3)))
394 else if (!strcmpiW(ptr, S_DotPdbW))
397 /* wine-[kp]thread is also an ELF module */
398 else if (((len > 12 && name[len - 13] == '/') || len == 12) &&
399 (!strcmpiW(name + len - 12, S_WinePThreadW) ||
400 !strcmpiW(name + len - 12, S_WineKThreadW)))
407 /***********************************************************************
408 * SymLoadModule (DBGHELP.@)
410 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, const char* ImageName,
411 const char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
413 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll,
417 /***********************************************************************
418 * SymLoadModuleEx (DBGHELP.@)
420 DWORD64 WINAPI SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
421 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize,
422 PMODLOAD_DATA Data, DWORD Flags)
424 LPWSTR wImageName, wModuleName;
428 TRACE("(%p %p %s %s %s %08x %p %08x)\n",
429 hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName),
430 wine_dbgstr_longlong(BaseOfDll), DllSize, Data, Flags);
434 len = MultiByteToWideChar(CP_ACP, 0, ImageName, -1, NULL, 0);
435 wImageName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
436 MultiByteToWideChar(CP_ACP, 0, ImageName, -1, wImageName, len);
438 else wImageName = NULL;
441 len = MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, NULL, 0);
442 wModuleName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
443 MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, wModuleName, len);
445 else wModuleName = NULL;
447 ret = SymLoadModuleExW(hProcess, hFile, wImageName, wModuleName,
448 BaseOfDll, DllSize, Data, Flags);
449 HeapFree(GetProcessHeap(), 0, wImageName);
450 HeapFree(GetProcessHeap(), 0, wModuleName);
454 /***********************************************************************
455 * SymLoadModuleExW (DBGHELP.@)
457 DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName,
458 PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll,
459 PMODLOAD_DATA Data, DWORD Flags)
462 struct module* module = NULL;
464 TRACE("(%p %p %s %s %s %08x %p %08x)\n",
465 hProcess, hFile, debugstr_w(wImageName), debugstr_w(wModuleName),
466 wine_dbgstr_longlong(BaseOfDll), SizeOfDll, Data, Flags);
469 FIXME("Unsupported load data parameter %p for %s\n",
470 Data, debugstr_w(wImageName));
471 if (!validate_addr64(BaseOfDll)) return FALSE;
473 if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
475 if (Flags & SLMFLAG_VIRTUAL)
477 module = module_new(pcs, wImageName, module_get_type_by_name(wImageName),
478 TRUE, (DWORD)BaseOfDll, SizeOfDll, 0, 0);
479 if (!module) return FALSE;
480 if (wModuleName) module_set_module(module, wModuleName);
481 module->module.SymType = SymVirtual;
485 if (Flags & ~(SLMFLAG_VIRTUAL))
486 FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
488 /* force transparent ELF loading / unloading */
489 elf_synchronize_module_list(pcs);
491 /* this is a Wine extension to the API just to redo the synchronisation */
492 if (!wImageName && !hFile) return 0;
494 if (module_is_elf_container_loaded(pcs, wImageName, wModuleName))
496 /* force the loading of DLL as builtin */
497 if ((module = pe_load_module_from_pcs(pcs, wImageName, wModuleName,
498 BaseOfDll, SizeOfDll)))
500 WARN("Couldn't locate %s\n", debugstr_w(wImageName));
503 TRACE("Assuming %s as native DLL\n", debugstr_w(wImageName));
504 if (!(module = pe_load_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)))
506 if (module_get_type_by_name(wImageName) == DMT_ELF &&
507 (module = elf_load_module(pcs, wImageName, BaseOfDll)))
509 FIXME("Should have successfully loaded debug information for image %s\n",
510 debugstr_w(wImageName));
511 if ((module = pe_load_module_from_pcs(pcs, wImageName, wModuleName,
512 BaseOfDll, SizeOfDll)))
514 WARN("Couldn't locate %s\n", debugstr_w(wImageName));
517 module->module.NumSyms = module->ht_symbols.num_elts;
519 /* by default pe_load_module fills module.ModuleName from a derivation
520 * of ImageName. Overwrite it, if we have better information
523 module_set_module(module, wModuleName);
524 lstrcpynW(module->module.ImageName, wImageName,
525 sizeof(module->module.ImageName) / sizeof(CHAR));
527 return module->module.BaseOfImage;
530 /***********************************************************************
531 * SymLoadModule64 (DBGHELP.@)
533 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
534 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
536 if (!validate_addr64(BaseOfDll)) return FALSE;
537 return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, SizeOfDll);
540 /******************************************************************
544 BOOL module_remove(struct process* pcs, struct module* module)
548 TRACE("%s (%p)\n", module->module_name, module);
549 hash_table_destroy(&module->ht_symbols);
550 hash_table_destroy(&module->ht_types);
551 HeapFree(GetProcessHeap(), 0, (char*)module->sources);
552 HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
553 HeapFree(GetProcessHeap(), 0, module->dwarf2_info);
554 pool_destroy(&module->pool);
555 /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here
558 for (p = &pcs->lmodules; *p; p = &(*p)->next)
563 HeapFree(GetProcessHeap(), 0, module);
567 FIXME("This shouldn't happen\n");
571 /******************************************************************
572 * SymUnloadModule (DBGHELP.@)
575 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
578 struct module* module;
580 pcs = process_find_by_handle(hProcess);
581 if (!pcs) return FALSE;
582 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
583 if (!module) return FALSE;
584 return module_remove(pcs, module);
587 /******************************************************************
588 * SymUnloadModule64 (DBGHELP.@)
591 BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll)
594 struct module* module;
596 pcs = process_find_by_handle(hProcess);
597 if (!pcs) return FALSE;
598 if (!validate_addr64(BaseOfDll)) return FALSE;
599 module = module_find_by_addr(pcs, (DWORD)BaseOfDll, DMT_UNKNOWN);
600 if (!module) return FALSE;
601 return module_remove(pcs, module);
604 /******************************************************************
605 * SymEnumerateModules (DBGHELP.@)
608 BOOL WINAPI SymEnumerateModules(HANDLE hProcess,
609 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
612 struct process* pcs = process_find_by_handle(hProcess);
613 struct module* module;
615 if (!pcs) return FALSE;
617 for (module = pcs->lmodules; module; module = module->next)
619 if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
621 if (!EnumModulesCallback(module->module_name,
622 module->module.BaseOfImage, UserContext))
628 /******************************************************************
629 * SymEnumerateModules64 (DBGHELP.@)
632 BOOL WINAPI SymEnumerateModules64(HANDLE hProcess,
633 PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,
636 struct process* pcs = process_find_by_handle(hProcess);
637 struct module* module;
639 if (!pcs) return FALSE;
641 for (module = pcs->lmodules; module; module = module->next)
643 if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
645 if (!EnumModulesCallback(module->module_name,
646 module->module.BaseOfImage, UserContext))
652 /******************************************************************
653 * EnumerateLoadedModules64 (DBGHELP.@)
656 struct enum_load_modW64_64
658 PENUMLOADED_MODULES_CALLBACK64 cb;
660 char module[MAX_PATH];
663 static BOOL CALLBACK enum_load_modW64_64(PWSTR name, DWORD64 base, ULONG size,
666 struct enum_load_modW64_64* x = user;
668 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
669 return x->cb(x->module, base, size, x->user);
672 BOOL WINAPI EnumerateLoadedModules64(HANDLE hProcess,
673 PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,
676 struct enum_load_modW64_64 x;
678 x.cb = EnumLoadedModulesCallback;
679 x.user = UserContext;
681 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_64, &x);
684 /******************************************************************
685 * EnumerateLoadedModules (DBGHELP.@)
688 struct enum_load_modW64_32
690 PENUMLOADED_MODULES_CALLBACK cb;
692 char module[MAX_PATH];
695 static BOOL CALLBACK enum_load_modW64_32(PWSTR name, DWORD64 base, ULONG size,
698 struct enum_load_modW64_32* x = user;
699 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
700 return x->cb(x->module, (DWORD)base, size, x->user);
703 BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
704 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
707 struct enum_load_modW64_32 x;
709 x.cb = EnumLoadedModulesCallback;
710 x.user = UserContext;
712 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_32, &x);
715 /******************************************************************
716 * EnumerateLoadedModulesW64 (DBGHELP.@)
719 BOOL WINAPI EnumerateLoadedModulesW64(HANDLE hProcess,
720 PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback,
724 WCHAR baseW[256], modW[256];
728 hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0]));
729 if (!hMods) return FALSE;
731 if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
733 /* hProcess should also be a valid process handle !! */
734 FIXME("If this happens, bump the number in mod\n");
735 HeapFree(GetProcessHeap(), 0, hMods);
738 sz /= sizeof(HMODULE);
739 for (i = 0; i < sz; i++)
741 if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
742 !GetModuleBaseNameW(hProcess, hMods[i], baseW, sizeof(baseW) / sizeof(WCHAR)))
744 module_fill_module(baseW, modW, sizeof(modW) / sizeof(CHAR));
745 EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage,
748 HeapFree(GetProcessHeap(), 0, hMods);
750 return sz != 0 && i == sz;
753 /******************************************************************
754 * SymGetModuleInfo (DBGHELP.@)
757 BOOL WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr,
758 PIMAGEHLP_MODULE ModuleInfo)
761 IMAGEHLP_MODULEW64 miw64;
763 if (sizeof(mi) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
765 miw64.SizeOfStruct = sizeof(miw64);
766 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
768 mi.SizeOfStruct = miw64.SizeOfStruct;
769 mi.BaseOfImage = miw64.BaseOfImage;
770 mi.ImageSize = miw64.ImageSize;
771 mi.TimeDateStamp = miw64.TimeDateStamp;
772 mi.CheckSum = miw64.CheckSum;
773 mi.NumSyms = miw64.NumSyms;
774 mi.SymType = miw64.SymType;
775 WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1,
776 mi.ModuleName, sizeof(mi.ModuleName), NULL, NULL);
777 WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1,
778 mi.ImageName, sizeof(mi.ImageName), NULL, NULL);
779 WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1,
780 mi.LoadedImageName, sizeof(mi.LoadedImageName), NULL, NULL);
782 memcpy(ModuleInfo, &mi, ModuleInfo->SizeOfStruct);
787 /******************************************************************
788 * SymGetModuleInfoW (DBGHELP.@)
791 BOOL WINAPI SymGetModuleInfoW(HANDLE hProcess, DWORD dwAddr,
792 PIMAGEHLP_MODULEW ModuleInfo)
794 IMAGEHLP_MODULEW64 miw64;
795 IMAGEHLP_MODULEW miw;
797 if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
799 miw64.SizeOfStruct = sizeof(miw64);
800 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
802 miw.SizeOfStruct = miw64.SizeOfStruct;
803 miw.BaseOfImage = miw64.BaseOfImage;
804 miw.ImageSize = miw64.ImageSize;
805 miw.TimeDateStamp = miw64.TimeDateStamp;
806 miw.CheckSum = miw64.CheckSum;
807 miw.NumSyms = miw64.NumSyms;
808 miw.SymType = miw64.SymType;
809 strcpyW(miw.ModuleName, miw64.ModuleName);
810 strcpyW(miw.ImageName, miw64.ImageName);
811 strcpyW(miw.LoadedImageName, miw64.LoadedImageName);
812 memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct);
817 /******************************************************************
818 * SymGetModuleInfo64 (DBGHELP.@)
821 BOOL WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr,
822 PIMAGEHLP_MODULE64 ModuleInfo)
824 IMAGEHLP_MODULE64 mi64;
825 IMAGEHLP_MODULEW64 miw64;
827 if (sizeof(mi64) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
829 miw64.SizeOfStruct = sizeof(miw64);
830 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
832 mi64.SizeOfStruct = miw64.SizeOfStruct;
833 mi64.BaseOfImage = miw64.BaseOfImage;
834 mi64.ImageSize = miw64.ImageSize;
835 mi64.TimeDateStamp = miw64.TimeDateStamp;
836 mi64.CheckSum = miw64.CheckSum;
837 mi64.NumSyms = miw64.NumSyms;
838 mi64.SymType = miw64.SymType;
839 WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1,
840 mi64.ModuleName, sizeof(mi64.ModuleName), NULL, NULL);
841 WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1,
842 mi64.ImageName, sizeof(mi64.ImageName), NULL, NULL);
843 WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1,
844 mi64.LoadedImageName, sizeof(mi64.LoadedImageName), NULL, NULL);
845 WideCharToMultiByte(CP_ACP, 0, miw64.LoadedPdbName, -1,
846 mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName), NULL, NULL);
848 mi64.CVSig = miw64.CVSig;
849 WideCharToMultiByte(CP_ACP, 0, miw64.CVData, -1,
850 mi64.CVData, sizeof(mi64.CVData), NULL, NULL);
851 mi64.PdbSig = miw64.PdbSig;
852 mi64.PdbSig70 = miw64.PdbSig70;
853 mi64.PdbAge = miw64.PdbAge;
854 mi64.PdbUnmatched = miw64.PdbUnmatched;
855 mi64.DbgUnmatched = miw64.DbgUnmatched;
856 mi64.LineNumbers = miw64.LineNumbers;
857 mi64.GlobalSymbols = miw64.GlobalSymbols;
858 mi64.TypeInfo = miw64.TypeInfo;
859 mi64.SourceIndexed = miw64.SourceIndexed;
860 mi64.Publics = miw64.Publics;
862 memcpy(ModuleInfo, &mi64, ModuleInfo->SizeOfStruct);
867 /******************************************************************
868 * SymGetModuleInfoW64 (DBGHELP.@)
871 BOOL WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr,
872 PIMAGEHLP_MODULEW64 ModuleInfo)
874 struct process* pcs = process_find_by_handle(hProcess);
875 struct module* module;
876 IMAGEHLP_MODULEW64 miw64;
878 TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo);
880 if (!pcs) return FALSE;
881 if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE;
882 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
883 if (!module) return FALSE;
885 miw64 = module->module;
887 /* update debug information from container if any */
888 if (module->module.SymType == SymNone)
890 module = module_get_container(pcs, module);
891 if (module && module->module.SymType != SymNone)
893 miw64.SymType = module->module.SymType;
894 miw64.NumSyms = module->module.NumSyms;
897 memcpy(ModuleInfo, &miw64, ModuleInfo->SizeOfStruct);
901 /***********************************************************************
902 * SymGetModuleBase (DBGHELP.@)
904 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
906 struct process* pcs = process_find_by_handle(hProcess);
907 struct module* module;
910 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
911 if (!module) return 0;
912 return module->module.BaseOfImage;
915 /***********************************************************************
916 * SymGetModuleBase64 (DBGHELP.@)
918 DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
920 if (!validate_addr64(dwAddr)) return 0;
921 return SymGetModuleBase(hProcess, (DWORD)dwAddr);
924 /******************************************************************
925 * module_reset_debug_info
926 * Removes any debug information linked to a given module.
928 void module_reset_debug_info(struct module* module)
930 module->sortlist_valid = TRUE;
931 module->addr_sorttab = NULL;
932 hash_table_destroy(&module->ht_symbols);
933 module->ht_symbols.num_buckets = 0;
934 module->ht_symbols.buckets = NULL;
935 hash_table_destroy(&module->ht_types);
936 module->ht_types.num_buckets = 0;
937 module->ht_types.buckets = NULL;
938 module->vtypes.num_elts = 0;
939 hash_table_destroy(&module->ht_symbols);
940 module->sources_used = module->sources_alloc = 0;
941 module->sources = NULL;