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);
112 module
->sources_used
= 0;
113 module
->sources_alloc
= 0;
119 /***********************************************************************
120 * module_find_by_name
123 struct module
* module_find_by_name(const struct process
* pcs
,
124 const char* name
, enum module_type type
)
126 struct module
* module
;
128 if (type
== DMT_UNKNOWN
)
130 if ((module
= module_find_by_name(pcs
, name
, DMT_PE
)) ||
131 (module
= module_find_by_name(pcs
, name
, DMT_ELF
)))
136 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
138 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.LoadedImageName
))
141 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
143 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.ModuleName
))
147 SetLastError(ERROR_INVALID_NAME
);
151 /***********************************************************************
152 * module_get_container
155 struct module
* module_get_container(const struct process
* pcs
,
156 const struct module
* inner
)
158 struct module
* module
;
160 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
162 if (module
!= inner
&&
163 module
->module
.BaseOfImage
<= inner
->module
.BaseOfImage
&&
164 module
->module
.BaseOfImage
+ module
->module
.ImageSize
>=
165 inner
->module
.BaseOfImage
+ inner
->module
.ImageSize
)
171 /***********************************************************************
172 * module_get_containee
175 struct module
* module_get_containee(const struct process
* pcs
,
176 const struct module
* outter
)
178 struct module
* module
;
180 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
182 if (module
!= outter
&&
183 outter
->module
.BaseOfImage
<= module
->module
.BaseOfImage
&&
184 outter
->module
.BaseOfImage
+ outter
->module
.ImageSize
>=
185 module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
191 /******************************************************************
194 * get the debug information from a module:
195 * - if the module's type is deferred, then force loading of debug info (and return
197 * - if the module has no debug info and has an ELF container, then return the ELF
198 * container (and also force the ELF container's debug info loading if deferred)
199 * - otherwise return the module itself if it has some debug info
201 struct module
* module_get_debug(const struct process
* pcs
, struct module
* module
)
205 if (!module
) return NULL
;
206 switch (module
->module
.SymType
)
209 module
= module_get_container(pcs
, module
);
210 if (!module
|| module
->module
.SymType
!= SymDeferred
) break;
213 switch (module
->type
)
215 case DMT_ELF
: ret
= elf_load_debug_info(module
); break;
216 case DMT_PE
: ret
= pe_load_debug_info(pcs
, module
); break;
217 default: ret
= FALSE
; break;
219 if (!ret
) module
->module
.SymType
= SymNone
;
223 return (module
&& module
->module
.SymType
!= SymNone
) ? module
: NULL
;
226 /***********************************************************************
227 * module_find_by_addr
229 * either the addr where module is loaded, or any address inside the
232 struct module
* module_find_by_addr(const struct process
* pcs
, unsigned long addr
,
233 enum module_type type
)
235 struct module
* module
;
237 if (type
== DMT_UNKNOWN
)
239 if ((module
= module_find_by_addr(pcs
, addr
, DMT_PE
)) ||
240 (module
= module_find_by_addr(pcs
, addr
, DMT_ELF
)))
245 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
247 if (type
== module
->type
&& addr
>= module
->module
.BaseOfImage
&&
248 addr
< module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
252 SetLastError(ERROR_INVALID_ADDRESS
);
256 static BOOL
module_is_elf_container_loaded(struct process
* pcs
, const char* ImageName
,
257 const char* ModuleName
)
259 char buffer
[MAX_PATH
];
261 struct module
* module
;
265 module_fill_module(ImageName
, buffer
, sizeof(buffer
));
268 len
= strlen(ModuleName
);
269 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
271 if (!strncasecmp(module
->module
.ModuleName
, ModuleName
, len
) &&
272 module
->type
== DMT_ELF
&&
273 !strcmp(module
->module
.ModuleName
+ len
, "<elf>"))
279 /***********************************************************************
280 * SymLoadModule (DBGHELP.@)
282 DWORD WINAPI
SymLoadModule(HANDLE hProcess
, HANDLE hFile
, char* ImageName
,
283 char* ModuleName
, DWORD BaseOfDll
, DWORD SizeOfDll
)
286 struct module
* module
= NULL
;
288 TRACE("(%p %p %s %s %08lx %08lx)\n",
289 hProcess
, hFile
, debugstr_a(ImageName
), debugstr_a(ModuleName
),
290 BaseOfDll
, SizeOfDll
);
292 pcs
= process_find_by_handle(hProcess
);
293 if (!pcs
) return FALSE
;
295 /* force transparent ELF loading / unloading */
296 elf_synchronize_module_list(pcs
);
298 /* this is a Wine extension to the API just to redo the synchronisation */
299 if (!ImageName
&& !hFile
) return 0;
301 if (module_is_elf_container_loaded(pcs
, ImageName
, ModuleName
))
303 /* force the loading of DLL as builtin */
304 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
, BaseOfDll
, SizeOfDll
)))
306 WARN("Couldn't locate %s\n", ImageName
);
309 TRACE("Assuming %s as native DLL\n", ImageName
);
310 if (!(module
= pe_load_module(pcs
, ImageName
, hFile
, BaseOfDll
, SizeOfDll
)))
312 unsigned len
= strlen(ImageName
);
314 if (!strcmp(ImageName
+ len
- 3, ".so") &&
315 (module
= elf_load_module(pcs
, ImageName
))) goto done
;
316 FIXME("should no longer happen\n");
317 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
, BaseOfDll
, SizeOfDll
)))
319 WARN("Couldn't locate %s\n", ImageName
);
324 /* by default pe_load_module fills module.ModuleName from a derivation
325 * of ImageName. Overwrite it, if we have better information
329 strncpy(module
->module
.ModuleName
, ModuleName
,
330 sizeof(module
->module
.ModuleName
));
331 module
->module
.ModuleName
[sizeof(module
->module
.ModuleName
) - 1] = '\0';
333 strncpy(module
->module
.ImageName
, ImageName
, sizeof(module
->module
.ImageName
));
334 module
->module
.ImageName
[sizeof(module
->module
.ImageName
) - 1] = '\0';
336 return module
->module
.BaseOfImage
;
339 /******************************************************************
343 BOOL
module_remove(struct process
* pcs
, struct module
* module
)
347 TRACE("%s (%p)\n", module
->module
.ModuleName
, module
);
348 hash_table_destroy(&module
->ht_symbols
);
349 hash_table_destroy(&module
->ht_types
);
350 HeapFree(GetProcessHeap(), 0, (char*)module
->sources
);
351 HeapFree(GetProcessHeap(), 0, module
->addr_sorttab
);
352 pool_destroy(&module
->pool
);
354 for (p
= &pcs
->lmodules
; *p
; p
= &(*p
)->next
)
359 HeapFree(GetProcessHeap(), 0, module
);
363 FIXME("This shouldn't happen\n");
367 /******************************************************************
368 * SymUnloadModule (DBGHELP.@)
371 BOOL WINAPI
SymUnloadModule(HANDLE hProcess
, DWORD BaseOfDll
)
374 struct module
* module
;
376 pcs
= process_find_by_handle(hProcess
);
377 if (!pcs
) return FALSE
;
378 module
= module_find_by_addr(pcs
, BaseOfDll
, DMT_UNKNOWN
);
379 if (!module
) return FALSE
;
380 return module_remove(pcs
, module
);
383 /******************************************************************
384 * SymEnumerateModules (DBGHELP.@)
387 BOOL WINAPI
SymEnumerateModules(HANDLE hProcess
,
388 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback
,
391 struct process
* pcs
= process_find_by_handle(hProcess
);
392 struct module
* module
;
394 if (!pcs
) return FALSE
;
396 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
398 if (!(dbghelp_options
& SYMOPT_WINE_WITH_ELF_MODULES
) && module
->type
!= DMT_PE
)
400 if (!EnumModulesCallback(module
->module
.ModuleName
,
401 module
->module
.BaseOfImage
, UserContext
))
407 /******************************************************************
408 * EnumerateLoadedModules (DBGHELP.@)
411 BOOL WINAPI
EnumerateLoadedModules(HANDLE hProcess
,
412 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback
,
416 char base
[256], mod
[256];
420 hMods
= HeapAlloc(GetProcessHeap(), 0, sz
);
421 if (!hMods
) return FALSE
;
423 if (!EnumProcessModules(hProcess
, hMods
, 256 * sizeof(hMods
[0]), &sz
))
425 /* hProcess should also be a valid process handle !! */
426 FIXME("If this happens, bump the number in mod\n");
427 HeapFree(GetProcessHeap(), 0, hMods
);
430 sz
/= sizeof(HMODULE
);
431 for (i
= 0; i
< sz
; i
++)
433 if (!GetModuleInformation(hProcess
, hMods
[i
], &mi
, sizeof(mi
)) ||
434 !GetModuleBaseNameA(hProcess
, hMods
[i
], base
, sizeof(base
)))
436 module_fill_module(base
, mod
, sizeof(mod
));
438 EnumLoadedModulesCallback(mod
, (DWORD
)mi
.lpBaseOfDll
, mi
.SizeOfImage
,
441 HeapFree(GetProcessHeap(), 0, hMods
);
443 return sz
!= 0 && i
== sz
;
446 /******************************************************************
447 * SymGetModuleInfo (DBGHELP.@)
450 BOOL WINAPI
SymGetModuleInfo(HANDLE hProcess
, DWORD dwAddr
,
451 PIMAGEHLP_MODULE ModuleInfo
)
453 struct process
* pcs
= process_find_by_handle(hProcess
);
454 struct module
* module
;
456 if (!pcs
) return FALSE
;
457 if (ModuleInfo
->SizeOfStruct
< sizeof(*ModuleInfo
)) return FALSE
;
458 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
459 if (!module
) return FALSE
;
461 *ModuleInfo
= module
->module
;
462 if (module
->module
.SymType
== SymNone
)
464 module
= module_get_container(pcs
, module
);
465 if (module
&& module
->module
.SymType
!= SymNone
)
466 ModuleInfo
->SymType
= module
->module
.SymType
;
472 /***********************************************************************
473 * SymGetModuleBase (IMAGEHLP.@)
475 DWORD WINAPI
SymGetModuleBase(HANDLE hProcess
, DWORD dwAddr
)
477 struct process
* pcs
= process_find_by_handle(hProcess
);
478 struct module
* module
;
481 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
482 if (!module
) return 0;
483 return module
->module
.BaseOfImage
;
486 /******************************************************************
487 * module_reset_debug_info
488 * Removes any debug information linked to a given module.
490 void module_reset_debug_info(struct module
* module
)
492 module
->sortlist_valid
= TRUE
;
493 module
->addr_sorttab
= NULL
;
494 hash_table_destroy(&module
->ht_symbols
);
495 module
->ht_symbols
.num_buckets
= 0;
496 module
->ht_symbols
.buckets
= NULL
;
497 hash_table_destroy(&module
->ht_types
);
498 module
->ht_types
.num_buckets
= 0;
499 module
->ht_types
.buckets
= NULL
;
500 hash_table_destroy(&module
->ht_symbols
);
501 module
->sources_used
= module
->sources_alloc
= 0;
502 module
->sources
= NULL
;