2 * File module.c - module handling for the wine debugger
4 * Copyright (C) 1993, Eric Youngdale.
5 * 2000-2004, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "dbghelp_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp
);
36 static void module_fill_module(const char* in
, char* out
, unsigned size
)
41 for (ptr
= in
+ strlen(in
) - 1;
42 *ptr
!= '/' && *ptr
!= '\\' && ptr
>= in
;
44 if (ptr
< in
|| *ptr
== '/' || *ptr
== '\\') ptr
++;
45 strncpy(out
, ptr
, size
);
49 (!strcasecmp(&out
[len
- 4], ".dll") || !strcasecmp(&out
[len
- 4], ".exe")))
54 (!strcasecmp(&out
[len
- 7], ".dll.so") || !strcasecmp(&out
[len
- 7], ".exe.so")))
55 strcpy(&out
[len
- 7], "<elf>");
57 out
[len
- 7] == '.' && !strcasecmp(&out
[len
- 3], ".so"))
59 if (len
+ 3 < size
) strcpy(&out
[len
- 3], "<elf>");
60 else WARN("Buffer too short: %s\n", out
);
63 while ((*out
= tolower(*out
))) out
++;
66 /***********************************************************************
67 * Creates and links a new module to a process
69 struct module
* module_new(struct process
* pcs
, const char* name
,
70 enum module_type type
,
71 unsigned long mod_addr
, unsigned long size
,
72 unsigned long stamp
, unsigned long checksum
)
74 struct module
* module
;
76 if (!(module
= HeapAlloc(GetProcessHeap(), 0, sizeof(*module
))))
79 memset(module
, 0, sizeof(*module
));
81 module
->next
= pcs
->lmodules
;
82 pcs
->lmodules
= module
;
84 TRACE("=> %s %08lx-%08lx %s\n",
85 type
== DMT_ELF
? "ELF" : (type
== DMT_PE
? "PE" : "---"),
86 mod_addr
, mod_addr
+ size
, name
);
88 pool_init(&module
->pool
, 65536);
90 module
->module
.SizeOfStruct
= sizeof(module
->module
);
91 module
->module
.BaseOfImage
= mod_addr
;
92 module
->module
.ImageSize
= size
;
93 module_fill_module(name
, module
->module
.ModuleName
, sizeof(module
->module
.ModuleName
));
94 module
->module
.ImageName
[0] = '\0';
95 strncpy(module
->module
.LoadedImageName
, name
,
96 sizeof(module
->module
.LoadedImageName
));
97 module
->module
.LoadedImageName
[sizeof(module
->module
.LoadedImageName
) - 1] = '\0';
98 module
->module
.SymType
= SymNone
;
99 module
->module
.NumSyms
= 0;
100 module
->module
.TimeDateStamp
= stamp
;
101 module
->module
.CheckSum
= checksum
;
104 module
->sortlist_valid
= FALSE
;
105 module
->addr_sorttab
= NULL
;
106 /* FIXME: this seems a bit too high (on a per module basis)
107 * need some statistics about this
109 hash_table_init(&module
->pool
, &module
->ht_symbols
, 4096);
110 hash_table_init(&module
->pool
, &module
->ht_types
, 4096);
111 vector_init(&module
->vtypes
, sizeof(struct symt
*), 32);
113 module
->sources_used
= 0;
114 module
->sources_alloc
= 0;
120 /***********************************************************************
121 * module_find_by_name
124 struct module
* module_find_by_name(const struct process
* pcs
,
125 const char* name
, enum module_type type
)
127 struct module
* module
;
129 if (type
== DMT_UNKNOWN
)
131 if ((module
= module_find_by_name(pcs
, name
, DMT_PE
)) ||
132 (module
= module_find_by_name(pcs
, name
, DMT_ELF
)))
137 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
139 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.LoadedImageName
))
142 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
144 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.ModuleName
))
148 SetLastError(ERROR_INVALID_NAME
);
152 /***********************************************************************
153 * module_get_container
156 struct module
* module_get_container(const struct process
* pcs
,
157 const struct module
* inner
)
159 struct module
* module
;
161 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
163 if (module
!= inner
&&
164 module
->module
.BaseOfImage
<= inner
->module
.BaseOfImage
&&
165 module
->module
.BaseOfImage
+ module
->module
.ImageSize
>=
166 inner
->module
.BaseOfImage
+ inner
->module
.ImageSize
)
172 /***********************************************************************
173 * module_get_containee
176 struct module
* module_get_containee(const struct process
* pcs
,
177 const struct module
* outter
)
179 struct module
* module
;
181 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
183 if (module
!= outter
&&
184 outter
->module
.BaseOfImage
<= module
->module
.BaseOfImage
&&
185 outter
->module
.BaseOfImage
+ outter
->module
.ImageSize
>=
186 module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
192 /******************************************************************
195 * get the debug information from a module:
196 * - if the module's type is deferred, then force loading of debug info (and return
198 * - if the module has no debug info and has an ELF container, then return the ELF
199 * container (and also force the ELF container's debug info loading if deferred)
200 * - otherwise return the module itself if it has some debug info
202 struct module
* module_get_debug(const struct process
* pcs
, struct module
* module
)
206 if (!module
) return NULL
;
207 switch (module
->module
.SymType
)
210 module
= module_get_container(pcs
, module
);
211 if (!module
|| module
->module
.SymType
!= SymDeferred
) break;
214 switch (module
->type
)
216 case DMT_ELF
: ret
= elf_load_debug_info(module
); break;
217 case DMT_PE
: ret
= pe_load_debug_info(pcs
, module
); break;
218 default: ret
= FALSE
; break;
220 if (!ret
) module
->module
.SymType
= SymNone
;
224 return (module
&& module
->module
.SymType
!= SymNone
) ? module
: NULL
;
227 /***********************************************************************
228 * module_find_by_addr
230 * either the addr where module is loaded, or any address inside the
233 struct module
* module_find_by_addr(const struct process
* pcs
, unsigned long addr
,
234 enum module_type type
)
236 struct module
* module
;
238 if (type
== DMT_UNKNOWN
)
240 if ((module
= module_find_by_addr(pcs
, addr
, DMT_PE
)) ||
241 (module
= module_find_by_addr(pcs
, addr
, DMT_ELF
)))
246 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
248 if (type
== module
->type
&& addr
>= module
->module
.BaseOfImage
&&
249 addr
< module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
253 SetLastError(ERROR_INVALID_ADDRESS
);
257 static BOOL
module_is_elf_container_loaded(struct process
* pcs
, const char* ImageName
,
258 const char* ModuleName
)
260 char buffer
[MAX_PATH
];
262 struct module
* module
;
266 module_fill_module(ImageName
, buffer
, sizeof(buffer
));
269 len
= strlen(ModuleName
);
270 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
272 if (!strncasecmp(module
->module
.ModuleName
, ModuleName
, len
) &&
273 module
->type
== DMT_ELF
&&
274 !strcmp(module
->module
.ModuleName
+ len
, "<elf>"))
280 /***********************************************************************
281 * SymLoadModule (DBGHELP.@)
283 DWORD WINAPI
SymLoadModule(HANDLE hProcess
, HANDLE hFile
, char* ImageName
,
284 char* ModuleName
, DWORD BaseOfDll
, DWORD SizeOfDll
)
287 struct module
* module
= NULL
;
289 TRACE("(%p %p %s %s %08lx %08lx)\n",
290 hProcess
, hFile
, debugstr_a(ImageName
), debugstr_a(ModuleName
),
291 BaseOfDll
, SizeOfDll
);
293 pcs
= process_find_by_handle(hProcess
);
294 if (!pcs
) return FALSE
;
296 /* force transparent ELF loading / unloading */
297 elf_synchronize_module_list(pcs
);
299 /* this is a Wine extension to the API just to redo the synchronisation */
300 if (!ImageName
&& !hFile
) return 0;
302 if (module_is_elf_container_loaded(pcs
, ImageName
, ModuleName
))
304 /* force the loading of DLL as builtin */
305 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
, BaseOfDll
, SizeOfDll
)))
307 WARN("Couldn't locate %s\n", ImageName
);
310 TRACE("Assuming %s as native DLL\n", ImageName
);
311 if (!(module
= pe_load_module(pcs
, ImageName
, hFile
, BaseOfDll
, SizeOfDll
)))
313 unsigned len
= strlen(ImageName
);
315 if (!strcmp(ImageName
+ len
- 3, ".so") &&
316 (module
= elf_load_module(pcs
, ImageName
))) goto done
;
317 FIXME("should have successfully loaded some debug information for image %s\n", ImageName
);
318 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
, BaseOfDll
, SizeOfDll
)))
320 WARN("Couldn't locate %s\n", ImageName
);
325 /* by default pe_load_module fills module.ModuleName from a derivation
326 * of ImageName. Overwrite it, if we have better information
330 strncpy(module
->module
.ModuleName
, ModuleName
,
331 sizeof(module
->module
.ModuleName
));
332 module
->module
.ModuleName
[sizeof(module
->module
.ModuleName
) - 1] = '\0';
334 strncpy(module
->module
.ImageName
, ImageName
, sizeof(module
->module
.ImageName
));
335 module
->module
.ImageName
[sizeof(module
->module
.ImageName
) - 1] = '\0';
337 return module
->module
.BaseOfImage
;
340 /******************************************************************
344 BOOL
module_remove(struct process
* pcs
, struct module
* module
)
348 TRACE("%s (%p)\n", module
->module
.ModuleName
, module
);
349 hash_table_destroy(&module
->ht_symbols
);
350 hash_table_destroy(&module
->ht_types
);
351 HeapFree(GetProcessHeap(), 0, (char*)module
->sources
);
352 HeapFree(GetProcessHeap(), 0, module
->addr_sorttab
);
353 pool_destroy(&module
->pool
);
355 for (p
= &pcs
->lmodules
; *p
; p
= &(*p
)->next
)
360 HeapFree(GetProcessHeap(), 0, module
);
364 FIXME("This shouldn't happen\n");
368 /******************************************************************
369 * SymUnloadModule (DBGHELP.@)
372 BOOL WINAPI
SymUnloadModule(HANDLE hProcess
, DWORD BaseOfDll
)
375 struct module
* module
;
377 pcs
= process_find_by_handle(hProcess
);
378 if (!pcs
) return FALSE
;
379 module
= module_find_by_addr(pcs
, BaseOfDll
, DMT_UNKNOWN
);
380 if (!module
) return FALSE
;
381 return module_remove(pcs
, module
);
384 /******************************************************************
385 * SymEnumerateModules (DBGHELP.@)
388 BOOL WINAPI
SymEnumerateModules(HANDLE hProcess
,
389 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback
,
392 struct process
* pcs
= process_find_by_handle(hProcess
);
393 struct module
* module
;
395 if (!pcs
) return FALSE
;
397 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
399 if (!(dbghelp_options
& SYMOPT_WINE_WITH_ELF_MODULES
) && module
->type
!= DMT_PE
)
401 if (!EnumModulesCallback(module
->module
.ModuleName
,
402 module
->module
.BaseOfImage
, UserContext
))
408 /******************************************************************
409 * EnumerateLoadedModules (DBGHELP.@)
412 BOOL WINAPI
EnumerateLoadedModules(HANDLE hProcess
,
413 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback
,
417 char base
[256], mod
[256];
421 hMods
= HeapAlloc(GetProcessHeap(), 0, sz
);
422 if (!hMods
) return FALSE
;
424 if (!EnumProcessModules(hProcess
, hMods
, 256 * sizeof(hMods
[0]), &sz
))
426 /* hProcess should also be a valid process handle !! */
427 FIXME("If this happens, bump the number in mod\n");
428 HeapFree(GetProcessHeap(), 0, hMods
);
431 sz
/= sizeof(HMODULE
);
432 for (i
= 0; i
< sz
; i
++)
434 if (!GetModuleInformation(hProcess
, hMods
[i
], &mi
, sizeof(mi
)) ||
435 !GetModuleBaseNameA(hProcess
, hMods
[i
], base
, sizeof(base
)))
437 module_fill_module(base
, mod
, sizeof(mod
));
439 EnumLoadedModulesCallback(mod
, (DWORD
)mi
.lpBaseOfDll
, mi
.SizeOfImage
,
442 HeapFree(GetProcessHeap(), 0, hMods
);
444 return sz
!= 0 && i
== sz
;
447 /******************************************************************
448 * SymGetModuleInfo (DBGHELP.@)
451 BOOL WINAPI
SymGetModuleInfo(HANDLE hProcess
, DWORD dwAddr
,
452 PIMAGEHLP_MODULE ModuleInfo
)
454 struct process
* pcs
= process_find_by_handle(hProcess
);
455 struct module
* module
;
457 if (!pcs
) return FALSE
;
458 if (ModuleInfo
->SizeOfStruct
< sizeof(*ModuleInfo
)) return FALSE
;
459 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
460 if (!module
) return FALSE
;
462 *ModuleInfo
= module
->module
;
463 if (module
->module
.SymType
== SymNone
)
465 module
= module_get_container(pcs
, module
);
466 if (module
&& module
->module
.SymType
!= SymNone
)
467 ModuleInfo
->SymType
= module
->module
.SymType
;
473 /***********************************************************************
474 * SymGetModuleBase (IMAGEHLP.@)
476 DWORD WINAPI
SymGetModuleBase(HANDLE hProcess
, DWORD dwAddr
)
478 struct process
* pcs
= process_find_by_handle(hProcess
);
479 struct module
* module
;
482 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
483 if (!module
) return 0;
484 return module
->module
.BaseOfImage
;
487 /******************************************************************
488 * module_reset_debug_info
489 * Removes any debug information linked to a given module.
491 void module_reset_debug_info(struct module
* module
)
493 module
->sortlist_valid
= TRUE
;
494 module
->addr_sorttab
= NULL
;
495 hash_table_destroy(&module
->ht_symbols
);
496 module
->ht_symbols
.num_buckets
= 0;
497 module
->ht_symbols
.buckets
= NULL
;
498 hash_table_destroy(&module
->ht_types
);
499 module
->ht_types
.num_buckets
= 0;
500 module
->ht_types
.buckets
= NULL
;
501 module
->vtypes
.num_elts
= 0;
502 hash_table_destroy(&module
->ht_symbols
);
503 module
->sources_used
= module
->sources_alloc
= 0;
504 module
->sources
= NULL
;