0173469bd6eabea46fd2bd91c41d2a6e2320c767
[reactos.git] / dll / win32 / dbghelp / module.c
1 /*
2 * File module.c - module handling for the wine debugger
3 *
4 * Copyright (C) 1993, Eric Youngdale.
5 * 2000-2007, Eric Pouech
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "dbghelp_private.h"
29 #ifndef DBGHELP_STATIC_LIB
30 #include "psapi.h"
31 #include "winternl.h"
32 #include "wine/debug.h"
33 #endif
34
35 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
36
37 const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'};
38 const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'};
39 static const WCHAR S_DotSoW[] = {'.','s','o','\0'};
40 static const WCHAR S_DotDylibW[] = {'.','d','y','l','i','b','\0'};
41 static const WCHAR S_DotPdbW[] = {'.','p','d','b','\0'};
42 static const WCHAR S_DotDbgW[] = {'.','d','b','g','\0'};
43 const WCHAR S_SlashW[] = {'/','\0'};
44
45 static const WCHAR S_AcmW[] = {'.','a','c','m','\0'};
46 static const WCHAR S_DllW[] = {'.','d','l','l','\0'};
47 static const WCHAR S_DrvW[] = {'.','d','r','v','\0'};
48 static const WCHAR S_ExeW[] = {'.','e','x','e','\0'};
49 static const WCHAR S_OcxW[] = {'.','o','c','x','\0'};
50 static const WCHAR S_VxdW[] = {'.','v','x','d','\0'};
51 static const WCHAR * const ext[] = {S_AcmW, S_DllW, S_DrvW, S_ExeW, S_OcxW, S_VxdW, NULL};
52
53 static int match_ext(const WCHAR* ptr, size_t len)
54 {
55 const WCHAR* const *e;
56 size_t l;
57
58 for (e = ext; *e; e++)
59 {
60 l = strlenW(*e);
61 if (l >= len) return 0;
62 if (strncmpiW(&ptr[len - l], *e, l)) continue;
63 return l;
64 }
65 return 0;
66 }
67
68 static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr)
69 {
70 const WCHAR* ptr;
71
72 if (!endptr) endptr = name + strlenW(name);
73 for (ptr = endptr - 1; ptr >= name; ptr--)
74 {
75 if (*ptr == '/' || *ptr == '\\') break;
76 }
77 return ++ptr;
78 }
79
80 static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size)
81 {
82 const WCHAR *loader = get_wine_loader_name();
83 const WCHAR *ptr, *endptr;
84 size_t len, l;
85
86 ptr = get_filename(in, endptr = in + strlenW(in));
87 len = min(endptr - ptr, size - 1);
88 memcpy(out, ptr, len * sizeof(WCHAR));
89 out[len] = '\0';
90 if (len > 4 && (l = match_ext(out, len)))
91 out[len - l] = '\0';
92 else if (len > strlenW(loader) && !strcmpiW(out + len - strlenW(loader), loader))
93 lstrcpynW(out, S_WineLoaderW, size);
94 else
95 {
96 if (len > 3 && !strcmpiW(&out[len - 3], S_DotSoW) &&
97 (l = match_ext(out, len - 3)))
98 strcpyW(&out[len - l - 3], S_ElfW);
99 }
100 while ((*out = tolowerW(*out))) out++;
101 }
102
103 void module_set_module(struct module* module, const WCHAR* name)
104 {
105 module_fill_module(name, module->module.ModuleName,
106 sizeof(module->module.ModuleName) / sizeof(module->module.ModuleName[0]));
107 module_fill_module(name, module->modulename, sizeof(module->modulename) / sizeof(module->modulename[0]));
108 }
109
110 const WCHAR *get_wine_loader_name(void)
111 {
112 static const BOOL is_win64 = sizeof(void *) > sizeof(int); /* FIXME: should depend on target process */
113 static const WCHAR wineW[] = {'w','i','n','e',0};
114 static const WCHAR suffixW[] = {'6','4',0};
115 static const WCHAR *loader;
116
117 if (!loader)
118 {
119 WCHAR *p, *buffer;
120 const char *ptr;
121
122 /* All binaries are loaded with WINELOADER (if run from tree) or by the
123 * main executable
124 */
125 if ((ptr = getenv("WINELOADER")))
126 {
127 DWORD len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, NULL, 0 );
128 buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
129 MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, buffer, len );
130 }
131 else
132 {
133 buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(wineW) + 2 * sizeof(WCHAR) );
134 strcpyW( buffer, wineW );
135 }
136 p = buffer + strlenW( buffer ) - strlenW( suffixW );
137 if (p > buffer && !strcmpW( p, suffixW ))
138 {
139 if (!is_win64) *p = 0;
140 }
141 else if (is_win64) strcatW( buffer, suffixW );
142
143 TRACE( "returning %s\n", debugstr_w(buffer) );
144 loader = buffer;
145 }
146 return loader;
147 }
148
149 static const char* get_module_type(enum module_type type, BOOL virtual)
150 {
151 switch (type)
152 {
153 case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
154 case DMT_PE: return virtual ? "Virtual PE" : "PE";
155 case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O";
156 default: return "---";
157 }
158 }
159
160 /***********************************************************************
161 * Creates and links a new module to a process
162 */
163 struct module* module_new(struct process* pcs, const WCHAR* name,
164 enum module_type type, BOOL virtual,
165 DWORD64 mod_addr, DWORD64 size,
166 unsigned long stamp, unsigned long checksum)
167 {
168 struct module* module;
169 unsigned i;
170
171 assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO);
172 if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module))))
173 return NULL;
174
175 module->next = pcs->lmodules;
176 pcs->lmodules = module;
177
178 TRACE("=> %s %s-%s %s\n",
179 get_module_type(type, virtual),
180 wine_dbgstr_longlong(mod_addr), wine_dbgstr_longlong(mod_addr + size),
181 debugstr_w(name));
182
183 pool_init(&module->pool, 65536);
184
185 module->process = pcs;
186 module->module.SizeOfStruct = sizeof(module->module);
187 module->module.BaseOfImage = mod_addr;
188 module->module.ImageSize = size;
189 module_set_module(module, name);
190 module->module.ImageName[0] = '\0';
191 lstrcpynW(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName) / sizeof(WCHAR));
192 module->module.SymType = SymNone;
193 module->module.NumSyms = 0;
194 module->module.TimeDateStamp = stamp;
195 module->module.CheckSum = checksum;
196
197 memset(module->module.LoadedPdbName, 0, sizeof(module->module.LoadedPdbName));
198 module->module.CVSig = 0;
199 memset(module->module.CVData, 0, sizeof(module->module.CVData));
200 module->module.PdbSig = 0;
201 memset(&module->module.PdbSig70, 0, sizeof(module->module.PdbSig70));
202 module->module.PdbAge = 0;
203 module->module.PdbUnmatched = FALSE;
204 module->module.DbgUnmatched = FALSE;
205 module->module.LineNumbers = FALSE;
206 module->module.GlobalSymbols = FALSE;
207 module->module.TypeInfo = FALSE;
208 module->module.SourceIndexed = FALSE;
209 module->module.Publics = FALSE;
210
211 module->reloc_delta = 0;
212 module->type = type;
213 module->is_virtual = virtual;
214 for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL;
215 module->sortlist_valid = FALSE;
216 module->sorttab_size = 0;
217 module->addr_sorttab = NULL;
218 module->num_sorttab = 0;
219 module->num_symbols = 0;
220
221 vector_init(&module->vsymt, sizeof(struct symt*), 128);
222 /* FIXME: this seems a bit too high (on a per module basis)
223 * need some statistics about this
224 */
225 hash_table_init(&module->pool, &module->ht_symbols, 4096);
226 hash_table_init(&module->pool, &module->ht_types, 4096);
227 #ifdef __x86_64__
228 hash_table_init(&module->pool, &module->ht_symaddr, 4096);
229 #endif
230 vector_init(&module->vtypes, sizeof(struct symt*), 32);
231
232 module->sources_used = 0;
233 module->sources_alloc = 0;
234 module->sources = 0;
235 wine_rb_init(&module->sources_offsets_tree, source_rb_compare);
236
237 return module;
238 }
239
240 /***********************************************************************
241 * module_find_by_nameW
242 *
243 */
244 struct module* module_find_by_nameW(const struct process* pcs, const WCHAR* name)
245 {
246 struct module* module;
247
248 for (module = pcs->lmodules; module; module = module->next)
249 {
250 if (!strcmpiW(name, module->module.ModuleName)) return module;
251 }
252 SetLastError(ERROR_INVALID_NAME);
253 return NULL;
254 }
255
256 struct module* module_find_by_nameA(const struct process* pcs, const char* name)
257 {
258 WCHAR wname[MAX_PATH];
259
260 MultiByteToWideChar(CP_ACP, 0, name, -1, wname, sizeof(wname) / sizeof(WCHAR));
261 return module_find_by_nameW(pcs, wname);
262 }
263
264 /***********************************************************************
265 * module_is_already_loaded
266 *
267 */
268 struct module* module_is_already_loaded(const struct process* pcs, const WCHAR* name)
269 {
270 struct module* module;
271 const WCHAR* filename;
272
273 /* first compare the loaded image name... */
274 for (module = pcs->lmodules; module; module = module->next)
275 {
276 if (!strcmpiW(name, module->module.LoadedImageName))
277 return module;
278 }
279 /* then compare the standard filenames (without the path) ... */
280 filename = get_filename(name, NULL);
281 for (module = pcs->lmodules; module; module = module->next)
282 {
283 if (!strcmpiW(filename, get_filename(module->module.LoadedImageName, NULL)))
284 return module;
285 }
286 SetLastError(ERROR_INVALID_NAME);
287 return NULL;
288 }
289
290 /***********************************************************************
291 * module_get_container
292 *
293 */
294 static struct module* module_get_container(const struct process* pcs,
295 const struct module* inner)
296 {
297 struct module* module;
298
299 for (module = pcs->lmodules; module; module = module->next)
300 {
301 if (module != inner &&
302 module->module.BaseOfImage <= inner->module.BaseOfImage &&
303 module->module.BaseOfImage + module->module.ImageSize >=
304 inner->module.BaseOfImage + inner->module.ImageSize)
305 return module;
306 }
307 return NULL;
308 }
309
310 /***********************************************************************
311 * module_get_containee
312 *
313 */
314 struct module* module_get_containee(const struct process* pcs,
315 const struct module* outter)
316 {
317 struct module* module;
318
319 for (module = pcs->lmodules; module; module = module->next)
320 {
321 if (module != outter &&
322 outter->module.BaseOfImage <= module->module.BaseOfImage &&
323 outter->module.BaseOfImage + outter->module.ImageSize >=
324 module->module.BaseOfImage + module->module.ImageSize)
325 return module;
326 }
327 return NULL;
328 }
329
330 /******************************************************************
331 * module_get_debug
332 *
333 * get the debug information from a module:
334 * - if the module's type is deferred, then force loading of debug info (and return
335 * the module itself)
336 * - if the module has no debug info and has an ELF container, then return the ELF
337 * container (and also force the ELF container's debug info loading if deferred)
338 * - otherwise return the module itself if it has some debug info
339 */
340 BOOL module_get_debug(struct module_pair* pair)
341 {
342 IMAGEHLP_DEFERRED_SYMBOL_LOADW64 idslW64;
343
344 if (!pair->requested) return FALSE;
345 /* for a PE builtin, always get info from container */
346 if (!(pair->effective = module_get_container(pair->pcs, pair->requested)))
347 pair->effective = pair->requested;
348 /* if deferred, force loading */
349 if (pair->effective->module.SymType == SymDeferred)
350 {
351 BOOL ret;
352
353 if (pair->effective->is_virtual) ret = FALSE;
354 else switch (pair->effective->type)
355 {
356 #ifndef DBGHELP_STATIC_LIB
357 case DMT_ELF:
358 ret = elf_load_debug_info(pair->effective);
359 break;
360 #endif
361 case DMT_PE:
362 idslW64.SizeOfStruct = sizeof(idslW64);
363 idslW64.BaseOfImage = pair->effective->module.BaseOfImage;
364 idslW64.CheckSum = pair->effective->module.CheckSum;
365 idslW64.TimeDateStamp = pair->effective->module.TimeDateStamp;
366 memcpy(idslW64.FileName, pair->effective->module.ImageName,
367 sizeof(pair->effective->module.ImageName));
368 idslW64.Reparse = FALSE;
369 idslW64.hFile = INVALID_HANDLE_VALUE;
370
371 pcs_callback(pair->pcs, CBA_DEFERRED_SYMBOL_LOAD_START, &idslW64);
372 ret = pe_load_debug_info(pair->pcs, pair->effective);
373 pcs_callback(pair->pcs,
374 ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
375 &idslW64);
376 break;
377 #ifndef DBGHELP_STATIC_LIB
378 case DMT_MACHO:
379 ret = macho_load_debug_info(pair->effective);
380 break;
381 #endif
382 default:
383 ret = FALSE;
384 break;
385 }
386 if (!ret) pair->effective->module.SymType = SymNone;
387 assert(pair->effective->module.SymType != SymDeferred);
388 pair->effective->module.NumSyms = pair->effective->ht_symbols.num_elts;
389 }
390 return pair->effective->module.SymType != SymNone;
391 }
392
393 /***********************************************************************
394 * module_find_by_addr
395 *
396 * either the addr where module is loaded, or any address inside the
397 * module
398 */
399 struct module* module_find_by_addr(const struct process* pcs, DWORD64 addr,
400 enum module_type type)
401 {
402 struct module* module;
403
404 if (type == DMT_UNKNOWN)
405 {
406 if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
407 (module = module_find_by_addr(pcs, addr, DMT_ELF)) ||
408 (module = module_find_by_addr(pcs, addr, DMT_MACHO)))
409 return module;
410 }
411 else
412 {
413 for (module = pcs->lmodules; module; module = module->next)
414 {
415 if (type == module->type && addr >= module->module.BaseOfImage &&
416 addr < module->module.BaseOfImage + module->module.ImageSize)
417 return module;
418 }
419 }
420 SetLastError(ERROR_INVALID_ADDRESS);
421 return module;
422 }
423
424 /******************************************************************
425 * module_is_container_loaded
426 *
427 * checks whether the native container, for a (supposed) PE builtin is
428 * already loaded
429 */
430 static BOOL module_is_container_loaded(const struct process* pcs,
431 const WCHAR* ImageName, DWORD64 base)
432 {
433 size_t len;
434 struct module* module;
435 PCWSTR filename, modname;
436
437 if (!base) return FALSE;
438 filename = get_filename(ImageName, NULL);
439 len = strlenW(filename);
440
441 for (module = pcs->lmodules; module; module = module->next)
442 {
443 if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
444 base >= module->module.BaseOfImage &&
445 base < module->module.BaseOfImage + module->module.ImageSize)
446 {
447 modname = get_filename(module->module.LoadedImageName, NULL);
448 if (!strncmpiW(modname, filename, len) &&
449 !memcmp(modname + len, S_DotSoW, 3 * sizeof(WCHAR)))
450 {
451 return TRUE;
452 }
453 }
454 }
455 /* likely a native PE module */
456 WARN("Couldn't find container for %s\n", debugstr_w(ImageName));
457 return FALSE;
458 }
459
460 /******************************************************************
461 * module_get_type_by_name
462 *
463 * Guesses a filename type from its extension
464 */
465 enum module_type module_get_type_by_name(const WCHAR* name)
466 {
467 int loader_len, len = strlenW(name);
468 const WCHAR *loader;
469
470 /* Skip all version extensions (.[digits]) regex: "(\.\d+)*$" */
471 do
472 {
473 int i = len;
474
475 while (i && name[i - 1] >= '0' && name[i - 1] <= '9') i--;
476
477 if (i && name[i - 1] == '.')
478 len = i - 1;
479 else
480 break;
481 } while (len);
482
483 /* check for terminating .so or .so.[digit] */
484 /* FIXME: Can't rely solely on extension; have to check magic or
485 * stop using .so on Mac OS X. For now, base on platform. */
486 if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3))
487 #ifdef __APPLE__
488 return DMT_MACHO;
489 #else
490 return DMT_ELF;
491 #endif
492
493 if (len > 6 && !strncmpiW(name + len - 6, S_DotDylibW, 6))
494 return DMT_MACHO;
495
496 if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4))
497 return DMT_PDB;
498
499 if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4))
500 return DMT_DBG;
501
502 /* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */
503 loader = get_wine_loader_name();
504 loader_len = strlenW( loader );
505 if ((len == loader_len || (len > loader_len && name[len - loader_len - 1] == '/')) &&
506 !strcmpiW(name + len - loader_len, loader))
507 {
508 #ifdef __APPLE__
509 return DMT_MACHO;
510 #else
511 return DMT_ELF;
512 #endif
513 }
514 return DMT_PE;
515 }
516
517 /******************************************************************
518 * refresh_module_list
519 */
520 #ifndef DBGHELP_STATIC_LIB
521 static BOOL refresh_module_list(struct process* pcs)
522 {
523 /* force transparent ELF and Mach-O loading / unloading */
524 return elf_synchronize_module_list(pcs) || macho_synchronize_module_list(pcs);
525 }
526 #endif
527
528 /***********************************************************************
529 * SymLoadModule (DBGHELP.@)
530 */
531 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
532 PCSTR ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
533 {
534 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll,
535 SizeOfDll, NULL, 0);
536 }
537
538 /***********************************************************************
539 * SymLoadModuleEx (DBGHELP.@)
540 */
541 DWORD64 WINAPI SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
542 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize,
543 PMODLOAD_DATA Data, DWORD Flags)
544 {
545 PWSTR wImageName, wModuleName;
546 unsigned len;
547 DWORD64 ret;
548
549 TRACE("(%p %p %s %s %s %08x %p %08x)\n",
550 hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName),
551 wine_dbgstr_longlong(BaseOfDll), DllSize, Data, Flags);
552
553 if (ImageName)
554 {
555 len = MultiByteToWideChar(CP_ACP, 0, ImageName, -1, NULL, 0);
556 wImageName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
557 MultiByteToWideChar(CP_ACP, 0, ImageName, -1, wImageName, len);
558 }
559 else wImageName = NULL;
560 if (ModuleName)
561 {
562 len = MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, NULL, 0);
563 wModuleName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
564 MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, wModuleName, len);
565 }
566 else wModuleName = NULL;
567
568 ret = SymLoadModuleExW(hProcess, hFile, wImageName, wModuleName,
569 BaseOfDll, DllSize, Data, Flags);
570 HeapFree(GetProcessHeap(), 0, wImageName);
571 HeapFree(GetProcessHeap(), 0, wModuleName);
572 return ret;
573 }
574
575 /***********************************************************************
576 * SymLoadModuleExW (DBGHELP.@)
577 */
578 DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName,
579 PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll,
580 PMODLOAD_DATA Data, DWORD Flags)
581 {
582 struct process* pcs;
583 struct module* module = NULL;
584
585 TRACE("(%p %p %s %s %s %08x %p %08x)\n",
586 hProcess, hFile, debugstr_w(wImageName), debugstr_w(wModuleName),
587 wine_dbgstr_longlong(BaseOfDll), SizeOfDll, Data, Flags);
588
589 if (Data)
590 FIXME("Unsupported load data parameter %p for %s\n",
591 Data, debugstr_w(wImageName));
592 if (!validate_addr64(BaseOfDll)) return FALSE;
593
594 if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
595
596 if (Flags & SLMFLAG_VIRTUAL)
597 {
598 if (!wImageName) return FALSE;
599 module = module_new(pcs, wImageName, module_get_type_by_name(wImageName),
600 TRUE, BaseOfDll, SizeOfDll, 0, 0);
601 if (!module) return FALSE;
602 if (wModuleName) module_set_module(module, wModuleName);
603 module->module.SymType = SymVirtual;
604
605 return TRUE;
606 }
607 if (Flags & ~(SLMFLAG_VIRTUAL))
608 FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
609
610 #ifndef DBGHELP_STATIC_LIB
611 refresh_module_list(pcs);
612 #endif
613
614 /* this is a Wine extension to the API just to redo the synchronisation */
615 if (!wImageName && !hFile) return 0;
616
617 /* check if the module is already loaded, or if it's a builtin PE module with
618 * an containing ELF module
619 */
620 if (wImageName)
621 {
622 module = module_is_already_loaded(pcs, wImageName);
623 if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll))
624 {
625 /* force the loading of DLL as builtin */
626 module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll);
627 }
628 }
629 if (!module)
630 {
631 /* otherwise, try a regular PE module */
632 if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) &&
633 wImageName)
634 {
635 /* and finally an ELF or Mach-O module */
636 #ifndef DBGHELP_STATIC_LIB
637 switch (module_get_type_by_name(wImageName))
638 {
639 case DMT_ELF:
640 module = elf_load_module(pcs, wImageName, BaseOfDll);
641 break;
642 case DMT_MACHO:
643 module = macho_load_module(pcs, wImageName, BaseOfDll);
644 break;
645 default:
646 /* Ignored */
647 break;
648 }
649 #endif
650 }
651 }
652 if (!module)
653 {
654 WARN("Couldn't locate %s\n", debugstr_w(wImageName));
655 return 0;
656 }
657 module->module.NumSyms = module->ht_symbols.num_elts;
658 /* by default module_new fills module.ModuleName from a derivation
659 * of LoadedImageName. Overwrite it, if we have better information
660 */
661 if (wModuleName)
662 module_set_module(module, wModuleName);
663 if (wImageName)
664 lstrcpynW(module->module.ImageName, wImageName,
665 sizeof(module->module.ImageName) / sizeof(WCHAR));
666
667 return module->module.BaseOfImage;
668 }
669
670 /***********************************************************************
671 * SymLoadModule64 (DBGHELP.@)
672 */
673 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
674 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
675 {
676 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll,
677 NULL, 0);
678 }
679
680 /******************************************************************
681 * module_remove
682 *
683 */
684 BOOL module_remove(struct process* pcs, struct module* module)
685 {
686 struct module_format*modfmt;
687 struct module** p;
688 unsigned i;
689
690 TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module);
691
692 for (i = 0; i < DFI_LAST; i++)
693 {
694 if ((modfmt = module->format_info[i]) && modfmt->remove)
695 modfmt->remove(pcs, module->format_info[i]);
696 }
697 hash_table_destroy(&module->ht_symbols);
698 hash_table_destroy(&module->ht_types);
699 HeapFree(GetProcessHeap(), 0, module->sources);
700 HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
701 pool_destroy(&module->pool);
702 /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here
703 * so do we
704 */
705 for (p = &pcs->lmodules; *p; p = &(*p)->next)
706 {
707 if (*p == module)
708 {
709 *p = module->next;
710 HeapFree(GetProcessHeap(), 0, module);
711 return TRUE;
712 }
713 }
714 FIXME("This shouldn't happen\n");
715 return FALSE;
716 }
717
718 /******************************************************************
719 * SymUnloadModule (DBGHELP.@)
720 *
721 */
722 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
723 {
724 struct process* pcs;
725 struct module* module;
726
727 pcs = process_find_by_handle(hProcess);
728 if (!pcs) return FALSE;
729 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
730 if (!module) return FALSE;
731 return module_remove(pcs, module);
732 }
733
734 /******************************************************************
735 * SymUnloadModule64 (DBGHELP.@)
736 *
737 */
738 BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll)
739 {
740 struct process* pcs;
741 struct module* module;
742
743 pcs = process_find_by_handle(hProcess);
744 if (!pcs) return FALSE;
745 if (!validate_addr64(BaseOfDll)) return FALSE;
746 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
747 if (!module) return FALSE;
748 return module_remove(pcs, module);
749 }
750
751 /******************************************************************
752 * SymEnumerateModules (DBGHELP.@)
753 *
754 */
755 struct enum_modW64_32
756 {
757 PSYM_ENUMMODULES_CALLBACK cb;
758 PVOID user;
759 char module[MAX_PATH];
760 };
761
762 static BOOL CALLBACK enum_modW64_32(PCWSTR name, DWORD64 base, PVOID user)
763 {
764 struct enum_modW64_32* x = user;
765
766 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
767 return x->cb(x->module, (DWORD)base, x->user);
768 }
769
770 BOOL WINAPI SymEnumerateModules(HANDLE hProcess,
771 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
772 PVOID UserContext)
773 {
774 struct enum_modW64_32 x;
775
776 x.cb = EnumModulesCallback;
777 x.user = UserContext;
778
779 return SymEnumerateModulesW64(hProcess, enum_modW64_32, &x);
780 }
781
782 /******************************************************************
783 * SymEnumerateModules64 (DBGHELP.@)
784 *
785 */
786 struct enum_modW64_64
787 {
788 PSYM_ENUMMODULES_CALLBACK64 cb;
789 PVOID user;
790 char module[MAX_PATH];
791 };
792
793 static BOOL CALLBACK enum_modW64_64(PCWSTR name, DWORD64 base, PVOID user)
794 {
795 struct enum_modW64_64* x = user;
796
797 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
798 return x->cb(x->module, base, x->user);
799 }
800
801 BOOL WINAPI SymEnumerateModules64(HANDLE hProcess,
802 PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,
803 PVOID UserContext)
804 {
805 struct enum_modW64_64 x;
806
807 x.cb = EnumModulesCallback;
808 x.user = UserContext;
809
810 return SymEnumerateModulesW64(hProcess, enum_modW64_64, &x);
811 }
812
813 /******************************************************************
814 * SymEnumerateModulesW64 (DBGHELP.@)
815 *
816 */
817 BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess,
818 PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback,
819 PVOID UserContext)
820 {
821 struct process* pcs = process_find_by_handle(hProcess);
822 struct module* module;
823
824 if (!pcs) return FALSE;
825
826 for (module = pcs->lmodules; module; module = module->next)
827 {
828 if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) &&
829 (module->type == DMT_ELF || module->type == DMT_MACHO))
830 continue;
831 if (!EnumModulesCallback(module->modulename,
832 module->module.BaseOfImage, UserContext))
833 break;
834 }
835 return TRUE;
836 }
837
838 #ifndef DBGHELP_STATIC_LIB
839 /******************************************************************
840 * EnumerateLoadedModules64 (DBGHELP.@)
841 *
842 */
843 struct enum_load_modW64_64
844 {
845 PENUMLOADED_MODULES_CALLBACK64 cb;
846 PVOID user;
847 char module[MAX_PATH];
848 };
849
850 static BOOL CALLBACK enum_load_modW64_64(PCWSTR name, DWORD64 base, ULONG size,
851 PVOID user)
852 {
853 struct enum_load_modW64_64* x = user;
854
855 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
856 return x->cb(x->module, base, size, x->user);
857 }
858
859 BOOL WINAPI EnumerateLoadedModules64(HANDLE hProcess,
860 PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,
861 PVOID UserContext)
862 {
863 struct enum_load_modW64_64 x;
864
865 x.cb = EnumLoadedModulesCallback;
866 x.user = UserContext;
867
868 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_64, &x);
869 }
870
871 /******************************************************************
872 * EnumerateLoadedModules (DBGHELP.@)
873 *
874 */
875 struct enum_load_modW64_32
876 {
877 PENUMLOADED_MODULES_CALLBACK cb;
878 PVOID user;
879 char module[MAX_PATH];
880 };
881
882 static BOOL CALLBACK enum_load_modW64_32(PCWSTR name, DWORD64 base, ULONG size,
883 PVOID user)
884 {
885 struct enum_load_modW64_32* x = user;
886 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL);
887 return x->cb(x->module, (DWORD)base, size, x->user);
888 }
889
890 BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
891 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
892 PVOID UserContext)
893 {
894 struct enum_load_modW64_32 x;
895
896 x.cb = EnumLoadedModulesCallback;
897 x.user = UserContext;
898
899 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_32, &x);
900 }
901
902 /******************************************************************
903 * EnumerateLoadedModulesW64 (DBGHELP.@)
904 *
905 */
906 BOOL WINAPI EnumerateLoadedModulesW64(HANDLE hProcess,
907 PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback,
908 PVOID UserContext)
909 {
910 HMODULE* hMods;
911 WCHAR baseW[256], modW[256];
912 DWORD i, sz;
913 MODULEINFO mi;
914
915 hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0]));
916 if (!hMods) return FALSE;
917
918 if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
919 {
920 /* hProcess should also be a valid process handle !! */
921 FIXME("If this happens, bump the number in mod\n");
922 HeapFree(GetProcessHeap(), 0, hMods);
923 return FALSE;
924 }
925 sz /= sizeof(HMODULE);
926 for (i = 0; i < sz; i++)
927 {
928 if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
929 !GetModuleBaseNameW(hProcess, hMods[i], baseW, sizeof(baseW) / sizeof(WCHAR)))
930 continue;
931 module_fill_module(baseW, modW, sizeof(modW) / sizeof(modW[0]));
932 EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage,
933 UserContext);
934 }
935 HeapFree(GetProcessHeap(), 0, hMods);
936
937 return sz != 0 && i == sz;
938 }
939
940 #endif /* DBGHELP_STATIC_LIB */
941
942 static void dbghelp_str_WtoA(const WCHAR *src, char *dst, int dst_len)
943 {
944 WideCharToMultiByte(CP_ACP, 0, src, -1, dst, dst_len - 1, NULL, NULL);
945 dst[dst_len - 1] = 0;
946 }
947
948 /******************************************************************
949 * SymGetModuleInfo (DBGHELP.@)
950 *
951 */
952 BOOL WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr,
953 PIMAGEHLP_MODULE ModuleInfo)
954 {
955 IMAGEHLP_MODULE mi;
956 IMAGEHLP_MODULEW64 miw64;
957
958 if (sizeof(mi) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
959
960 miw64.SizeOfStruct = sizeof(miw64);
961 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
962
963 mi.SizeOfStruct = ModuleInfo->SizeOfStruct;
964 mi.BaseOfImage = miw64.BaseOfImage;
965 mi.ImageSize = miw64.ImageSize;
966 mi.TimeDateStamp = miw64.TimeDateStamp;
967 mi.CheckSum = miw64.CheckSum;
968 mi.NumSyms = miw64.NumSyms;
969 mi.SymType = miw64.SymType;
970 dbghelp_str_WtoA(miw64.ModuleName, mi.ModuleName, sizeof(mi.ModuleName));
971 dbghelp_str_WtoA(miw64.ImageName, mi.ImageName, sizeof(mi.ImageName));
972 dbghelp_str_WtoA(miw64.LoadedImageName, mi.LoadedImageName, sizeof(mi.LoadedImageName));
973
974 memcpy(ModuleInfo, &mi, ModuleInfo->SizeOfStruct);
975
976 return TRUE;
977 }
978
979 /******************************************************************
980 * SymGetModuleInfoW (DBGHELP.@)
981 *
982 */
983 BOOL WINAPI SymGetModuleInfoW(HANDLE hProcess, DWORD dwAddr,
984 PIMAGEHLP_MODULEW ModuleInfo)
985 {
986 IMAGEHLP_MODULEW64 miw64;
987 IMAGEHLP_MODULEW miw;
988
989 if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");
990
991 miw64.SizeOfStruct = sizeof(miw64);
992 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
993
994 miw.SizeOfStruct = ModuleInfo->SizeOfStruct;
995 miw.BaseOfImage = miw64.BaseOfImage;
996 miw.ImageSize = miw64.ImageSize;
997 miw.TimeDateStamp = miw64.TimeDateStamp;
998 miw.CheckSum = miw64.CheckSum;
999 miw.NumSyms = miw64.NumSyms;
1000 miw.SymType = miw64.SymType;
1001 strcpyW(miw.ModuleName, miw64.ModuleName);
1002 strcpyW(miw.ImageName, miw64.ImageName);
1003 strcpyW(miw.LoadedImageName, miw64.LoadedImageName);
1004 memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct);
1005
1006 return TRUE;
1007 }
1008
1009 /******************************************************************
1010 * SymGetModuleInfo64 (DBGHELP.@)
1011 *
1012 */
1013 BOOL WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr,
1014 PIMAGEHLP_MODULE64 ModuleInfo)
1015 {
1016 IMAGEHLP_MODULE64 mi64;
1017 IMAGEHLP_MODULEW64 miw64;
1018
1019 if (sizeof(mi64) < ModuleInfo->SizeOfStruct)
1020 {
1021 SetLastError(ERROR_MOD_NOT_FOUND); /* NOTE: native returns this error */
1022 WARN("Wrong size %u\n", ModuleInfo->SizeOfStruct);
1023 return FALSE;
1024 }
1025
1026 miw64.SizeOfStruct = sizeof(miw64);
1027 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE;
1028
1029 mi64.SizeOfStruct = ModuleInfo->SizeOfStruct;
1030 mi64.BaseOfImage = miw64.BaseOfImage;
1031 mi64.ImageSize = miw64.ImageSize;
1032 mi64.TimeDateStamp = miw64.TimeDateStamp;
1033 mi64.CheckSum = miw64.CheckSum;
1034 mi64.NumSyms = miw64.NumSyms;
1035 mi64.SymType = miw64.SymType;
1036 dbghelp_str_WtoA(miw64.ModuleName, mi64.ModuleName, sizeof(mi64.ModuleName));
1037 dbghelp_str_WtoA(miw64.ImageName, mi64.ImageName, sizeof(mi64.ImageName));
1038 dbghelp_str_WtoA(miw64.LoadedImageName, mi64.LoadedImageName, sizeof(mi64.LoadedImageName));
1039 dbghelp_str_WtoA(miw64.LoadedPdbName, mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName));
1040
1041 mi64.CVSig = miw64.CVSig;
1042 dbghelp_str_WtoA(miw64.CVData, mi64.CVData, sizeof(mi64.CVData));
1043 mi64.PdbSig = miw64.PdbSig;
1044 mi64.PdbSig70 = miw64.PdbSig70;
1045 mi64.PdbAge = miw64.PdbAge;
1046 mi64.PdbUnmatched = miw64.PdbUnmatched;
1047 mi64.DbgUnmatched = miw64.DbgUnmatched;
1048 mi64.LineNumbers = miw64.LineNumbers;
1049 mi64.GlobalSymbols = miw64.GlobalSymbols;
1050 mi64.TypeInfo = miw64.TypeInfo;
1051 mi64.SourceIndexed = miw64.SourceIndexed;
1052 mi64.Publics = miw64.Publics;
1053
1054 memcpy(ModuleInfo, &mi64, ModuleInfo->SizeOfStruct);
1055
1056 return TRUE;
1057 }
1058
1059 /******************************************************************
1060 * SymGetModuleInfoW64 (DBGHELP.@)
1061 *
1062 */
1063 BOOL WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr,
1064 PIMAGEHLP_MODULEW64 ModuleInfo)
1065 {
1066 struct process* pcs = process_find_by_handle(hProcess);
1067 struct module* module;
1068 IMAGEHLP_MODULEW64 miw64;
1069
1070 TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo);
1071
1072 if (!pcs) return FALSE;
1073 if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE;
1074 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
1075 if (!module) return FALSE;
1076
1077 miw64 = module->module;
1078
1079 /* update debug information from container if any */
1080 if (module->module.SymType == SymNone)
1081 {
1082 module = module_get_container(pcs, module);
1083 if (module && module->module.SymType != SymNone)
1084 {
1085 miw64.SymType = module->module.SymType;
1086 miw64.NumSyms = module->module.NumSyms;
1087 }
1088 }
1089 memcpy(ModuleInfo, &miw64, ModuleInfo->SizeOfStruct);
1090 return TRUE;
1091 }
1092
1093 /***********************************************************************
1094 * SymGetModuleBase (DBGHELP.@)
1095 */
1096 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
1097 {
1098 DWORD64 ret;
1099
1100 ret = SymGetModuleBase64(hProcess, dwAddr);
1101 return validate_addr64(ret) ? ret : 0;
1102 }
1103
1104 /***********************************************************************
1105 * SymGetModuleBase64 (DBGHELP.@)
1106 */
1107 DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
1108 {
1109 struct process* pcs = process_find_by_handle(hProcess);
1110 struct module* module;
1111
1112 if (!pcs) return 0;
1113 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
1114 if (!module) return 0;
1115 return module->module.BaseOfImage;
1116 }
1117
1118 /******************************************************************
1119 * module_reset_debug_info
1120 * Removes any debug information linked to a given module.
1121 */
1122 void module_reset_debug_info(struct module* module)
1123 {
1124 module->sortlist_valid = TRUE;
1125 module->sorttab_size = 0;
1126 module->addr_sorttab = NULL;
1127 module->num_sorttab = module->num_symbols = 0;
1128 hash_table_destroy(&module->ht_symbols);
1129 module->ht_symbols.num_buckets = 0;
1130 module->ht_symbols.buckets = NULL;
1131 hash_table_destroy(&module->ht_types);
1132 module->ht_types.num_buckets = 0;
1133 module->ht_types.buckets = NULL;
1134 module->vtypes.num_elts = 0;
1135 hash_table_destroy(&module->ht_symbols);
1136 module->sources_used = module->sources_alloc = 0;
1137 module->sources = NULL;
1138 }
1139
1140 /******************************************************************
1141 * SymRefreshModuleList (DBGHELP.@)
1142 */
1143 BOOL WINAPI SymRefreshModuleList(HANDLE hProcess)
1144 {
1145 struct process* pcs;
1146
1147 TRACE("(%p)\n", hProcess);
1148
1149 if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
1150
1151 #ifndef DBGHELP_STATIC_LIB
1152 return refresh_module_list(pcs);
1153 #else
1154 return TRUE;
1155 #endif
1156 }
1157
1158 /***********************************************************************
1159 * SymFunctionTableAccess (DBGHELP.@)
1160 */
1161 PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
1162 {
1163 return SymFunctionTableAccess64(hProcess, AddrBase);
1164 }
1165
1166 /***********************************************************************
1167 * SymFunctionTableAccess64 (DBGHELP.@)
1168 */
1169 PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
1170 {
1171 struct process* pcs = process_find_by_handle(hProcess);
1172 struct module* module;
1173
1174 if (!pcs || !dbghelp_current_cpu->find_runtime_function) return NULL;
1175 module = module_find_by_addr(pcs, AddrBase, DMT_UNKNOWN);
1176 if (!module) return NULL;
1177
1178 return dbghelp_current_cpu->find_runtime_function(module, AddrBase);
1179 }