Owner drawn menu item size calculation fixes:
[wine] / dlls / dbghelp / module.c
1 /*
2  * File module.c - module handling for the wine debugger
3  *
4  * Copyright (C) 1993,      Eric Youngdale.
5  *               2000-2004, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 #include "psapi.h"
30 #include "winreg.h"
31 #include "winternl.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
35
36 static void module_fill_module(const char* in, char* out, unsigned size)
37 {
38     const char          *ptr,*endptr;
39     unsigned            len;
40
41     endptr = in + strlen(in);
42     for (ptr = endptr - 1;
43          ptr >= in && *ptr != '/' && *ptr != '\\';
44          ptr--);
45     ptr++;
46     len = min(endptr-ptr,size-1);
47     memcpy(out, ptr, len);
48     out[len] = '\0';
49     if (len > 4 && 
50         (!strcasecmp(&out[len - 4], ".dll") || !strcasecmp(&out[len - 4], ".exe")))
51         out[len - 4] = '\0';
52     else if (((len > 12 && out[len - 13] == '/') || len == 12) && 
53              (!strcasecmp(out + len - 12, "wine-pthread") || 
54               !strcasecmp(out + len - 12, "wine-kthread")))
55         lstrcpynA(out, "<wine-loader>",size);
56     else
57     {
58         if (len > 7 && 
59             (!strcasecmp(&out[len - 7], ".dll.so") || !strcasecmp(&out[len - 7], ".exe.so")))
60             strcpy(&out[len - 7], "<elf>");
61         else if (len > 7 &&
62                  out[len - 7] == '.' && !strcasecmp(&out[len - 3], ".so"))
63         {
64             if (len + 3 < size) strcpy(&out[len - 3], "<elf>");
65             else WARN("Buffer too short: %s\n", out);
66         }
67     }
68     while ((*out = tolower(*out))) out++;
69 }
70
71 /***********************************************************************
72  * Creates and links a new module to a process 
73  */
74 struct module* module_new(struct process* pcs, const char* name, 
75                           enum module_type type, 
76                           unsigned long mod_addr, unsigned long size,
77                           unsigned long stamp, unsigned long checksum) 
78 {
79     struct module*      module;
80
81     assert(type == DMT_ELF || type == DMT_PE);
82     if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
83         return NULL;
84
85     memset(module, 0, sizeof(*module));
86
87     module->next = pcs->lmodules;
88     pcs->lmodules = module;
89
90     TRACE("=> %s %08lx-%08lx %s\n", 
91           type == DMT_ELF ? "ELF" : (type == DMT_PE ? "PE" : "---"),
92           mod_addr, mod_addr + size, name);
93
94     pool_init(&module->pool, 65536);
95     
96     module->module.SizeOfStruct = sizeof(module->module);
97     module->module.BaseOfImage = mod_addr;
98     module->module.ImageSize = size;
99     module_fill_module(name, module->module.ModuleName,
100                        sizeof(module->module.ModuleName));
101     module->module.ImageName[0] = '\0';
102     lstrcpynA(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName));
103     module->module.SymType = SymNone;
104     module->module.NumSyms = 0;
105     module->module.TimeDateStamp = stamp;
106     module->module.CheckSum = checksum;
107
108     module->type              = type;
109     module->sortlist_valid    = FALSE;
110     module->addr_sorttab      = NULL;
111     /* FIXME: this seems a bit too high (on a per module basis)
112      * need some statistics about this
113      */
114     hash_table_init(&module->pool, &module->ht_symbols, 4096);
115     hash_table_init(&module->pool, &module->ht_types,   4096);
116     vector_init(&module->vtypes, sizeof(struct symt*),  32);
117
118     module->sources_used      = 0;
119     module->sources_alloc     = 0;
120     module->sources           = 0;
121
122     return module;
123 }
124
125 /***********************************************************************
126  *      module_find_by_name
127  *
128  */
129 struct module* module_find_by_name(const struct process* pcs, 
130                                    const char* name, enum module_type type)
131 {
132     struct module*      module;
133
134     if (type == DMT_UNKNOWN)
135     {
136         if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
137             (module = module_find_by_name(pcs, name, DMT_ELF)))
138             return module;
139     }
140     else
141     {
142         char                modname[MAX_PATH];
143
144         for (module = pcs->lmodules; module; module = module->next)
145         {
146             if (type == module->type &&
147                 !strcasecmp(name, module->module.LoadedImageName)) 
148                 return module;
149         }
150         module_fill_module(name, modname, sizeof(modname));
151         for (module = pcs->lmodules; module; module = module->next)
152         {
153             if (type == module->type &&
154                 !strcasecmp(modname, module->module.ModuleName)) 
155                 return module;
156         }
157     }
158     SetLastError(ERROR_INVALID_NAME);
159     return NULL;
160 }
161
162 /***********************************************************************
163  *           module_get_container
164  *
165  */
166 struct module* module_get_container(const struct process* pcs, 
167                                     const struct module* inner)
168 {
169     struct module*      module;
170      
171     for (module = pcs->lmodules; module; module = module->next)
172     {
173         if (module != inner &&
174             module->module.BaseOfImage <= inner->module.BaseOfImage &&
175             module->module.BaseOfImage + module->module.ImageSize >=
176             inner->module.BaseOfImage + inner->module.ImageSize)
177             return module;
178     }
179     return NULL;
180 }
181
182 /***********************************************************************
183  *           module_get_containee
184  *
185  */
186 struct module* module_get_containee(const struct process* pcs, 
187                                     const struct module* outter)
188 {
189     struct module*      module;
190      
191     for (module = pcs->lmodules; module; module = module->next)
192     {
193         if (module != outter &&
194             outter->module.BaseOfImage <= module->module.BaseOfImage &&
195             outter->module.BaseOfImage + outter->module.ImageSize >=
196             module->module.BaseOfImage + module->module.ImageSize)
197             return module;
198     }
199     return NULL;
200 }
201
202 /******************************************************************
203  *              module_get_debug
204  *
205  * get the debug information from a module:
206  * - if the module's type is deferred, then force loading of debug info (and return
207  *   the module itself)
208  * - if the module has no debug info and has an ELF container, then return the ELF
209  *   container (and also force the ELF container's debug info loading if deferred)
210  * - otherwise return the module itself if it has some debug info
211  */
212 struct module* module_get_debug(const struct process* pcs, struct module* module)
213 {
214     struct module*      parent;
215
216     if (!module) return NULL;
217     /* for a PE builtin, always get info from parent */
218     if ((parent = module_get_container(pcs, module)))
219         module = parent;
220     /* if deferred, force loading */
221     if (module->module.SymType == SymDeferred)
222     {
223         BOOL ret;
224
225         switch (module->type)
226         {
227         case DMT_ELF: ret = elf_load_debug_info(module, NULL);  break;
228         case DMT_PE:  ret = pe_load_debug_info(pcs, module);    break;
229         default:      ret = FALSE;                              break;
230         }
231         if (!ret) module->module.SymType = SymNone;
232         assert(module->module.SymType != SymDeferred);
233     }
234     return (module && module->module.SymType != SymNone) ? module : NULL;
235 }
236
237 /***********************************************************************
238  *      module_find_by_addr
239  *
240  * either the addr where module is loaded, or any address inside the 
241  * module
242  */
243 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 
244                                    enum module_type type)
245 {
246     struct module*      module;
247     
248     if (type == DMT_UNKNOWN)
249     {
250         if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
251             (module = module_find_by_addr(pcs, addr, DMT_ELF)))
252             return module;
253     }
254     else
255     {
256         for (module = pcs->lmodules; module; module = module->next)
257         {
258             if (type == module->type && addr >= module->module.BaseOfImage &&
259                 addr < module->module.BaseOfImage + module->module.ImageSize) 
260                 return module;
261         }
262     }
263     SetLastError(ERROR_INVALID_ADDRESS);
264     return module;
265 }
266
267 static BOOL module_is_elf_container_loaded(struct process* pcs, const char* ImageName,
268                                            const char* ModuleName)
269 {
270     char                buffer[MAX_PATH];
271     size_t              len;
272     struct module*      module;
273
274     if (!ModuleName)
275     {
276         module_fill_module(ImageName, buffer, sizeof(buffer));
277         ModuleName = buffer;
278     }
279     len = strlen(ModuleName);
280     for (module = pcs->lmodules; module; module = module->next)
281     {
282         if (!strncasecmp(module->module.ModuleName, ModuleName, len) &&
283             module->type == DMT_ELF &&
284             !strcmp(module->module.ModuleName + len, "<elf>"))
285             return TRUE;
286     }
287     return FALSE;
288 }
289
290 /******************************************************************
291  *              module_get_type_by_name
292  *
293  * Guesses a filename type from its extension
294  */
295 enum module_type module_get_type_by_name(const char* name)
296 {
297     const char* ptr;
298     int         len = strlen(name);
299
300     /* check for terminating .so or .so.[digit] */
301     ptr = strrchr(name, '.');
302     if (ptr)
303     {
304         if (!strcmp(ptr, ".so") ||
305             (isdigit(ptr[1]) && !ptr[2] && ptr >= name + 3 && !memcmp(ptr - 3, ".so", 3)))
306             return DMT_ELF;
307         else if (!strcasecmp(ptr, ".pdb"))
308             return DMT_PDB;
309     }
310     /* wine-[kp]thread is also an ELF module */
311     else if (((len > 12 && name[len - 13] == '/') || len == 12) && 
312              (!strcasecmp(name + len - 12, "wine-pthread") || 
313               !strcasecmp(name + len - 12, "wine-kthread")))
314     {
315         return DMT_ELF;
316     }
317     return DMT_PE;
318 }
319
320 /***********************************************************************
321  *                      SymLoadModule (DBGHELP.@)
322  */
323 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
324                            char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
325 {
326     struct process*     pcs;
327     struct module*      module = NULL;
328
329     TRACE("(%p %p %s %s %08lx %08lx)\n", 
330           hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName), 
331           BaseOfDll, SizeOfDll);
332
333     pcs = process_find_by_handle(hProcess);
334     if (!pcs) return FALSE;
335
336     /* force transparent ELF loading / unloading */
337     elf_synchronize_module_list(pcs);
338
339     /* this is a Wine extension to the API just to redo the synchronisation */
340     if (!ImageName && !hFile) return 0;
341
342     if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
343     {
344         /* force the loading of DLL as builtin */
345         if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
346                                               BaseOfDll, SizeOfDll)))
347             goto done;
348         WARN("Couldn't locate %s\n", ImageName);
349         return 0;
350     }
351     TRACE("Assuming %s as native DLL\n", ImageName);
352     if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
353     {
354         if (module_get_type_by_name(ImageName) == DMT_ELF &&
355             (module = elf_load_module(pcs, ImageName, BaseOfDll)))
356             goto done;
357         FIXME("Should have successfully loaded debug information for image %s\n",
358               ImageName);
359         if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
360                                               BaseOfDll, SizeOfDll)))
361             goto done;
362         WARN("Couldn't locate %s\n", ImageName);
363         return 0;
364     }
365
366 done:
367     /* by default pe_load_module fills module.ModuleName from a derivation 
368      * of ImageName. Overwrite it, if we have better information
369      */
370     if (ModuleName)
371         lstrcpynA(module->module.ModuleName, ModuleName, sizeof(module->module.ModuleName));
372     lstrcpynA(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
373
374     return module->module.BaseOfImage;
375 }
376
377 /***********************************************************************
378  *                     SymLoadModule64 (DBGHELP.@)
379  */
380 DWORD WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, char* ImageName,
381                              char* ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
382 {
383     FIXME("SymLoadModule should probably reference SymLoadModule64 instead of this way\n");
384
385     return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, SizeOfDll);
386 }
387
388 /******************************************************************
389  *              module_remove
390  *
391  */
392 BOOL module_remove(struct process* pcs, struct module* module)
393 {
394     struct module**     p;
395
396     TRACE("%s (%p)\n", module->module.ModuleName, module);
397     hash_table_destroy(&module->ht_symbols);
398     hash_table_destroy(&module->ht_types);
399     HeapFree(GetProcessHeap(), 0, (char*)module->sources);
400     HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
401     pool_destroy(&module->pool);
402
403     for (p = &pcs->lmodules; *p; p = &(*p)->next)
404     {
405         if (*p == module)
406         {
407             *p = module->next;
408             HeapFree(GetProcessHeap(), 0, module);
409             return TRUE;
410         }
411     }
412     FIXME("This shouldn't happen\n");
413     return FALSE;
414 }
415
416 /******************************************************************
417  *              SymUnloadModule (DBGHELP.@)
418  *
419  */
420 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
421 {
422     struct process*     pcs;
423     struct module*      module;
424
425     pcs = process_find_by_handle(hProcess);
426     if (!pcs) return FALSE;
427     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
428     if (!module) return FALSE;
429     return module_remove(pcs, module);
430 }
431
432 /******************************************************************
433  *              SymEnumerateModules (DBGHELP.@)
434  *
435  */
436 BOOL  WINAPI SymEnumerateModules(HANDLE hProcess,
437                                  PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,  
438                                  PVOID UserContext)
439 {
440     struct process*     pcs = process_find_by_handle(hProcess);
441     struct module*      module;
442
443     if (!pcs) return FALSE;
444     
445     for (module = pcs->lmodules; module; module = module->next)
446     {
447         if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type != DMT_PE)
448             continue;
449         if (!EnumModulesCallback(module->module.ModuleName, 
450                                  module->module.BaseOfImage, UserContext))
451             break;
452     }
453     return TRUE;
454 }
455
456 /******************************************************************
457  *              EnumerateLoadedModules (DBGHELP.@)
458  *
459  */
460 BOOL  WINAPI EnumerateLoadedModules(HANDLE hProcess,
461                                     PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
462                                     PVOID UserContext)
463 {
464     HMODULE*    hMods;
465     char        base[256], mod[256];
466     DWORD       i, sz;
467     MODULEINFO  mi;
468
469     hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0]));
470     if (!hMods) return FALSE;
471
472     if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
473     {
474         /* hProcess should also be a valid process handle !! */
475         FIXME("If this happens, bump the number in mod\n");
476         HeapFree(GetProcessHeap(), 0, hMods);
477         return FALSE;
478     }
479     sz /= sizeof(HMODULE);
480     for (i = 0; i < sz; i++)
481     {
482         if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
483             !GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
484             continue;
485         module_fill_module(base, mod, sizeof(mod));
486         EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage, 
487                                   UserContext);
488     }
489     HeapFree(GetProcessHeap(), 0, hMods);
490
491     return sz != 0 && i == sz;
492 }
493
494 /******************************************************************
495  *              SymGetModuleInfo (DBGHELP.@)
496  *
497  */
498 BOOL  WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 
499                               PIMAGEHLP_MODULE ModuleInfo)
500 {
501     struct process*     pcs = process_find_by_handle(hProcess);
502     struct module*      module;
503
504     if (!pcs) return FALSE;
505     if (ModuleInfo->SizeOfStruct < sizeof(*ModuleInfo)) return FALSE;
506     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
507     if (!module) return FALSE;
508
509     *ModuleInfo = module->module;
510     if (module->module.SymType == SymNone)
511     {
512         module = module_get_container(pcs, module);
513         if (module && module->module.SymType != SymNone)
514             ModuleInfo->SymType = module->module.SymType;
515     }
516
517     return TRUE;
518 }
519
520 /***********************************************************************
521  *              SymGetModuleBase (IMAGEHLP.@)
522  */
523 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
524 {
525     struct process*     pcs = process_find_by_handle(hProcess);
526     struct module*      module;
527
528     if (!pcs) return 0;
529     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
530     if (!module) return 0;
531     return module->module.BaseOfImage;
532 }
533
534 /******************************************************************
535  *              module_reset_debug_info
536  * Removes any debug information linked to a given module.
537  */
538 void module_reset_debug_info(struct module* module)
539 {
540     module->sortlist_valid = TRUE;
541     module->addr_sorttab = NULL;
542     hash_table_destroy(&module->ht_symbols);
543     module->ht_symbols.num_buckets = 0;
544     module->ht_symbols.buckets = NULL;
545     hash_table_destroy(&module->ht_types);
546     module->ht_types.num_buckets = 0;
547     module->ht_types.buckets = NULL;
548     module->vtypes.num_elts = 0;
549     hash_table_destroy(&module->ht_symbols);
550     module->sources_used = module->sources_alloc = 0;
551     module->sources = NULL;
552 }