Assorted spelling 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 /***********************************************************************
37  * Creates and links a new module to a process 
38  */
39 struct module* module_new(struct process* pcs, const char* name, 
40                           enum DbgModuleType type, 
41                           unsigned long mod_addr, unsigned long size,
42                           unsigned long stamp, unsigned long checksum) 
43 {
44     struct module*      module;
45     const char*         ptr;
46
47     if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
48         return NULL;
49
50     memset(module, 0, sizeof(*module));
51
52     module->next = pcs->lmodules;
53     pcs->lmodules = module;
54
55     TRACE("=> %s %08lx-%08lx %s\n", 
56           type == DMT_ELF ? "ELF" : (type == DMT_PE ? "PE" : "---"),
57           mod_addr, mod_addr + size, name);
58
59     pool_init(&module->pool, 65536);
60     
61     module->module.SizeOfStruct = sizeof(module->module);
62     module->module.BaseOfImage = mod_addr;
63     module->module.ImageSize = size;
64     for (ptr = name + strlen(name) - 1; 
65          *ptr != '/' && *ptr != '\\' && ptr >= name; 
66          ptr--);
67     if (ptr < name || *ptr == '/' || *ptr == '\\') ptr++;
68     strncpy(module->module.ModuleName, ptr, sizeof(module->module.ModuleName));
69     module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
70     module->module.ImageName[0] = '\0';
71     strncpy(module->module.LoadedImageName, name, 
72             sizeof(module->module.LoadedImageName));
73     module->module.LoadedImageName[sizeof(module->module.LoadedImageName) - 1] = '\0';
74     module->module.SymType = SymNone;
75     module->module.NumSyms = 0;
76     module->module.TimeDateStamp = stamp;
77     module->module.CheckSum = checksum;
78
79     module->type              = type;
80     module->sortlist_valid    = FALSE;
81     module->addr_sorttab      = NULL;
82     /* FIXME: this seems a bit too high (on a per module basis)
83      * need some statistics about this
84      */
85     hash_table_init(&module->pool, &module->ht_symbols, 4096);
86     hash_table_init(&module->pool, &module->ht_types,   4096);
87
88     module->sources_used      = 0;
89     module->sources_alloc     = 0;
90     module->sources           = 0;
91
92     return module;
93 }
94
95 /***********************************************************************
96  *      module_find_by_name
97  *
98  */
99 struct module* module_find_by_name(const struct process* pcs, 
100                                    const char* name, enum DbgModuleType type)
101 {
102     struct module*      module;
103
104     if (type == DMT_UNKNOWN)
105     {
106         if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
107             (module = module_find_by_name(pcs, name, DMT_ELF)))
108             return module;
109     }
110     else
111     {
112         for (module = pcs->lmodules; module; module = module->next)
113         {
114             if (type == module->type && !strcasecmp(name, module->module.LoadedImageName)) 
115                 return module;
116         }
117         for (module = pcs->lmodules; module; module = module->next)
118         {
119             if (type == module->type && !strcasecmp(name, module->module.ModuleName)) 
120                 return module;
121         }
122     }
123     SetLastError(ERROR_INVALID_NAME);
124     return NULL;
125 }
126
127 /***********************************************************************
128  *           module_has_container
129  *
130  */
131 static struct module* module_get_container(const struct process* pcs, 
132                                            const struct module* inner)
133 {
134     struct module*      module;
135      
136     for (module = pcs->lmodules; module; module = module->next)
137     {
138         if (module != inner &&
139             module->module.BaseOfImage <= inner->module.BaseOfImage &&
140             module->module.BaseOfImage + module->module.ImageSize >=
141             inner->module.BaseOfImage + inner->module.ImageSize)
142             return module;
143     }
144     return NULL;
145 }
146
147 /******************************************************************
148  *              module_get_debug
149  *
150  * get the debug information from a module:
151  * - if the module's type is deferred, then force loading of debug info (and return
152  *   the module itself)
153  * - if the module has no debug info and has an ELF container, then return the ELF
154  *   container (and also force the ELF container's debug info loading if deferred)
155  * - otherwise return the module itself if it has some debug info
156  */
157 struct module* module_get_debug(const struct process* pcs, struct module* module)
158 {
159     if (!module) return NULL;
160     switch (module->module.SymType)
161     {
162     case -1: break;
163     case SymNone:
164         module = module_get_container(pcs, module);
165         if (!module || module->module.SymType != SymDeferred) break;
166         /* fall through */
167     case SymDeferred:
168         switch (module->type)
169         {
170         case DMT_ELF:
171             elf_load_debug_info(module);
172             break;
173         case DMT_PE:
174             pe_load_debug_info(pcs, module);
175             break;
176         default: break;
177         }
178         break;
179     default: break;
180     }
181     return (module && module->module.SymType > SymNone) ? module : NULL;
182 }
183
184 /***********************************************************************
185  *      module_find_by_addr
186  *
187  * either the addr where module is loaded, or any address inside the 
188  * module
189  */
190 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 
191                                    enum DbgModuleType type)
192 {
193     struct module*      module;
194     
195     if (type == DMT_UNKNOWN)
196     {
197         if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
198             (module = module_find_by_addr(pcs, addr, DMT_ELF)))
199             return module;
200     }
201     else
202     {
203         for (module = pcs->lmodules; module; module = module->next)
204         {
205             if (type == module->type && addr >= module->module.BaseOfImage &&
206                 addr < module->module.BaseOfImage + module->module.ImageSize) 
207                 return module;
208         }
209     }
210     SetLastError(ERROR_INVALID_ADDRESS);
211     return module;
212 }
213
214 /***********************************************************************
215  *                      SymLoadModule (DBGHELP.@)
216  */
217 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
218                            char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
219 {
220     struct process*     pcs;
221     struct module*      module = NULL;
222
223     TRACE("(%p %p %s %s %08lx %08lx)\n", 
224           hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName), 
225           BaseOfDll, SizeOfDll);
226
227     pcs = process_find_by_handle(hProcess);
228     if (!pcs) return FALSE;
229
230     if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
231     {
232         unsigned        len = strlen(ImageName);
233
234         if (!strcmp(ImageName + len - 3, ".so") &&
235             (module = elf_load_module(pcs, ImageName))) goto done;
236         if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
237             goto done;
238         WARN("Couldn't locate %s\n", ImageName);
239         return 0;
240     }
241
242 done:
243     /* by default pe_load_module fills module.ModuleName from a derivation 
244      * of ImageName. Overwrite it, if we have better information
245      */
246     if (ModuleName)
247     {
248         strncpy(module->module.ModuleName, ModuleName, 
249                 sizeof(module->module.ModuleName));
250         module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
251     }
252     strncpy(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
253     module->module.ImageName[sizeof(module->module.ImageName) - 1] = '\0';
254     /* force transparent ELF loading / unloading */
255     if (module->type != DMT_ELF) elf_synchronize_module_list(pcs);
256
257     return module->module.BaseOfImage;
258 }
259
260 /******************************************************************
261  *              module_remove
262  *
263  */
264 BOOL module_remove(struct process* pcs, struct module* module)
265 {
266     struct module**     p;
267
268     TRACE("%s (%p)\n", module->module.ModuleName, module);
269     hash_table_destroy(&module->ht_symbols);
270     hash_table_destroy(&module->ht_types);
271     HeapFree(GetProcessHeap(), 0, (char*)module->sources);
272     HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
273     pool_destroy(&module->pool);
274
275     for (p = &pcs->lmodules; *p; p = &(*p)->next)
276     {
277         if (*p == module)
278         {
279             *p = module->next;
280             HeapFree(GetProcessHeap(), 0, module);
281             return TRUE;
282         }
283     }
284     FIXME("This shouldn't happen\n");
285     return FALSE;
286 }
287
288 /******************************************************************
289  *              SymUnloadModule (DBGHELP.@)
290  *
291  */
292 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
293 {
294     struct process*     pcs;
295     struct module*      module;
296
297     pcs = process_find_by_handle(hProcess);
298     if (!pcs) return FALSE;
299     module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
300     if (!module) return FALSE;
301     return module_remove(pcs, module);
302 }
303
304 /******************************************************************
305  *              SymEnumerateModules (DBGHELP.@)
306  *
307  */
308 BOOL  WINAPI SymEnumerateModules(HANDLE hProcess,
309                                  PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,  
310                                  PVOID UserContext)
311 {
312     struct process*     pcs = process_find_by_handle(hProcess);
313     struct module*      module;
314
315     if (!pcs) return FALSE;
316     
317     for (module = pcs->lmodules; module; module = module->next)
318     {
319         if (module->type != DMT_PE) continue;
320         if (!EnumModulesCallback(module->module.ModuleName, 
321                                  module->module.BaseOfImage, UserContext))
322             break;
323     }
324     return TRUE;
325 }
326
327 /******************************************************************
328  *              EnumerateLoadedModules (DBGHELP.@)
329  *
330  */
331 BOOL  WINAPI EnumerateLoadedModules(HANDLE hProcess,
332                                     PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
333                                     PVOID UserContext)
334 {
335     HMODULE*    hMods;
336     char        img[256], mod[256];
337     DWORD       i, sz;
338     MODULEINFO  mi;
339
340     hMods = HeapAlloc(GetProcessHeap(), 0, sz);
341     if (!hMods) return FALSE;
342
343     if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
344     {
345         /* hProcess should also be a valid process handle !! */
346         FIXME("If this happens, bump the number in mod\n");
347         HeapFree(GetProcessHeap(), 0, hMods);
348         return FALSE;
349     }
350     sz /= sizeof(HMODULE);
351     for (i = 0; i < sz; i++)
352     {
353         if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
354             !GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
355             !GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)))
356             break;
357         EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage, 
358                                   UserContext);
359     }
360     HeapFree(GetProcessHeap(), 0, hMods);
361
362     return sz != 0 && i == sz;
363 }
364
365 /******************************************************************
366  *              SymGetModuleInfo (DBGHELP.@)
367  *
368  */
369 BOOL  WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 
370                               PIMAGEHLP_MODULE ModuleInfo)
371 {
372     struct process*     pcs = process_find_by_handle(hProcess);
373     struct module*      module;
374
375     if (!pcs) return FALSE;
376     if (ModuleInfo->SizeOfStruct < sizeof(*ModuleInfo)) return FALSE;
377     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
378     if (!module) return FALSE;
379
380     *ModuleInfo = module->module;
381     if (module->module.SymType <= SymNone)
382     {
383         module = module_get_container(pcs, module);
384         if (module && module->module.SymType > SymNone)
385             ModuleInfo->SymType = module->module.SymType;
386     }
387
388     return TRUE;
389 }
390
391 /***********************************************************************
392  *              SymGetModuleBase (IMAGEHLP.@)
393  */
394 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
395 {
396     struct process*     pcs = process_find_by_handle(hProcess);
397     struct module*      module;
398
399     if (!pcs) return 0;
400     module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
401     if (!module) return 0;
402     return module->module.BaseOfImage;
403 }