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
29 #include "dbghelp_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp
);
37 static void module_fill_module(const char* in
, char* out
, unsigned size
)
42 for (ptr
= in
+ strlen(in
) - 1;
43 *ptr
!= '/' && *ptr
!= '\\' && ptr
>= in
;
45 if (ptr
< in
|| *ptr
== '/' || *ptr
== '\\') ptr
++;
46 strncpy(out
, ptr
, size
);
50 (!strcasecmp(&out
[len
- 4], ".dll") || !strcasecmp(&out
[len
- 4], ".exe")))
55 (!strcasecmp(&out
[len
- 7], ".dll.so") || !strcasecmp(&out
[len
- 7], ".exe.so")))
56 strcpy(&out
[len
- 7], "<elf>");
58 out
[len
- 7] == '.' && !strcasecmp(&out
[len
- 3], ".so"))
60 if (len
+ 3 < size
) strcpy(&out
[len
- 3], "<elf>");
61 else WARN("Buffer too short: %s\n", out
);
64 while ((*out
= tolower(*out
))) out
++;
67 /***********************************************************************
68 * Creates and links a new module to a process
70 struct module
* module_new(struct process
* pcs
, const char* name
,
71 enum module_type type
,
72 unsigned long mod_addr
, unsigned long size
,
73 unsigned long stamp
, unsigned long checksum
)
75 struct module
* module
;
77 if (!(module
= HeapAlloc(GetProcessHeap(), 0, sizeof(*module
))))
80 memset(module
, 0, sizeof(*module
));
82 module
->next
= pcs
->lmodules
;
83 pcs
->lmodules
= module
;
85 TRACE("=> %s %08lx-%08lx %s\n",
86 type
== DMT_ELF
? "ELF" : (type
== DMT_PE
? "PE" : "---"),
87 mod_addr
, mod_addr
+ size
, name
);
89 pool_init(&module
->pool
, 65536);
91 module
->module
.SizeOfStruct
= sizeof(module
->module
);
92 module
->module
.BaseOfImage
= mod_addr
;
93 module
->module
.ImageSize
= size
;
94 module_fill_module(name
, module
->module
.ModuleName
, sizeof(module
->module
.ModuleName
));
95 module
->module
.ImageName
[0] = '\0';
96 strncpy(module
->module
.LoadedImageName
, name
,
97 sizeof(module
->module
.LoadedImageName
));
98 module
->module
.LoadedImageName
[sizeof(module
->module
.LoadedImageName
) - 1] = '\0';
99 module
->module
.SymType
= SymNone
;
100 module
->module
.NumSyms
= 0;
101 module
->module
.TimeDateStamp
= stamp
;
102 module
->module
.CheckSum
= checksum
;
105 module
->sortlist_valid
= FALSE
;
106 module
->addr_sorttab
= NULL
;
107 /* FIXME: this seems a bit too high (on a per module basis)
108 * need some statistics about this
110 hash_table_init(&module
->pool
, &module
->ht_symbols
, 4096);
111 hash_table_init(&module
->pool
, &module
->ht_types
, 4096);
112 vector_init(&module
->vtypes
, sizeof(struct symt
*), 32);
114 module
->sources_used
= 0;
115 module
->sources_alloc
= 0;
121 /***********************************************************************
122 * module_find_by_name
125 struct module
* module_find_by_name(const struct process
* pcs
,
126 const char* name
, enum module_type type
)
128 struct module
* module
;
130 if (type
== DMT_UNKNOWN
)
132 if ((module
= module_find_by_name(pcs
, name
, DMT_PE
)) ||
133 (module
= module_find_by_name(pcs
, name
, DMT_ELF
)))
138 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
140 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.LoadedImageName
))
143 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
145 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.ModuleName
))
149 SetLastError(ERROR_INVALID_NAME
);
153 /***********************************************************************
154 * module_get_container
157 struct module
* module_get_container(const struct process
* pcs
,
158 const struct module
* inner
)
160 struct module
* module
;
162 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
164 if (module
!= inner
&&
165 module
->module
.BaseOfImage
<= inner
->module
.BaseOfImage
&&
166 module
->module
.BaseOfImage
+ module
->module
.ImageSize
>=
167 inner
->module
.BaseOfImage
+ inner
->module
.ImageSize
)
173 /***********************************************************************
174 * module_get_containee
177 struct module
* module_get_containee(const struct process
* pcs
,
178 const struct module
* outter
)
180 struct module
* module
;
182 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
184 if (module
!= outter
&&
185 outter
->module
.BaseOfImage
<= module
->module
.BaseOfImage
&&
186 outter
->module
.BaseOfImage
+ outter
->module
.ImageSize
>=
187 module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
193 /******************************************************************
196 * get the debug information from a module:
197 * - if the module's type is deferred, then force loading of debug info (and return
199 * - if the module has no debug info and has an ELF container, then return the ELF
200 * container (and also force the ELF container's debug info loading if deferred)
201 * - otherwise return the module itself if it has some debug info
203 struct module
* module_get_debug(const struct process
* pcs
, struct module
* module
)
205 struct module
* parent
;
207 if (!module
) return NULL
;
208 /* for a PE builtin, always get info from parent */
209 if ((parent
= module_get_container(pcs
, module
)))
211 /* if deferred, force loading */
212 if (module
->module
.SymType
== SymDeferred
)
216 switch (module
->type
)
218 case DMT_ELF
: ret
= elf_load_debug_info(module
); break;
219 case DMT_PE
: ret
= pe_load_debug_info(pcs
, module
); break;
220 default: ret
= FALSE
; break;
222 if (!ret
) module
->module
.SymType
= SymNone
;
223 assert(module
->module
.SymType
!= SymDeferred
);
225 return (module
&& module
->module
.SymType
!= SymNone
) ? module
: NULL
;
228 /***********************************************************************
229 * module_find_by_addr
231 * either the addr where module is loaded, or any address inside the
234 struct module
* module_find_by_addr(const struct process
* pcs
, unsigned long addr
,
235 enum module_type type
)
237 struct module
* module
;
239 if (type
== DMT_UNKNOWN
)
241 if ((module
= module_find_by_addr(pcs
, addr
, DMT_PE
)) ||
242 (module
= module_find_by_addr(pcs
, addr
, DMT_ELF
)))
247 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
249 if (type
== module
->type
&& addr
>= module
->module
.BaseOfImage
&&
250 addr
< module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
254 SetLastError(ERROR_INVALID_ADDRESS
);
258 static BOOL
module_is_elf_container_loaded(struct process
* pcs
, const char* ImageName
,
259 const char* ModuleName
)
261 char buffer
[MAX_PATH
];
263 struct module
* module
;
267 module_fill_module(ImageName
, buffer
, sizeof(buffer
));
270 len
= strlen(ModuleName
);
271 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
273 if (!strncasecmp(module
->module
.ModuleName
, ModuleName
, len
) &&
274 module
->type
== DMT_ELF
&&
275 !strcmp(module
->module
.ModuleName
+ len
, "<elf>"))
281 /***********************************************************************
282 * SymLoadModule (DBGHELP.@)
284 DWORD WINAPI
SymLoadModule(HANDLE hProcess
, HANDLE hFile
, char* ImageName
,
285 char* ModuleName
, DWORD BaseOfDll
, DWORD SizeOfDll
)
288 struct module
* module
= NULL
;
290 TRACE("(%p %p %s %s %08lx %08lx)\n",
291 hProcess
, hFile
, debugstr_a(ImageName
), debugstr_a(ModuleName
),
292 BaseOfDll
, SizeOfDll
);
294 pcs
= process_find_by_handle(hProcess
);
295 if (!pcs
) return FALSE
;
297 /* force transparent ELF loading / unloading */
298 elf_synchronize_module_list(pcs
);
300 /* this is a Wine extension to the API just to redo the synchronisation */
301 if (!ImageName
&& !hFile
) return 0;
303 if (module_is_elf_container_loaded(pcs
, ImageName
, ModuleName
))
305 /* force the loading of DLL as builtin */
306 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
, BaseOfDll
, SizeOfDll
)))
308 WARN("Couldn't locate %s\n", ImageName
);
311 TRACE("Assuming %s as native DLL\n", ImageName
);
312 if (!(module
= pe_load_module(pcs
, ImageName
, hFile
, BaseOfDll
, SizeOfDll
)))
314 unsigned len
= strlen(ImageName
);
316 if (!strcmp(ImageName
+ len
- 3, ".so") &&
317 (module
= elf_load_module(pcs
, ImageName
))) goto done
;
318 FIXME("should have successfully loaded some debug information for image %s\n", ImageName
);
319 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
, BaseOfDll
, SizeOfDll
)))
321 WARN("Couldn't locate %s\n", ImageName
);
326 /* by default pe_load_module fills module.ModuleName from a derivation
327 * of ImageName. Overwrite it, if we have better information
331 strncpy(module
->module
.ModuleName
, ModuleName
,
332 sizeof(module
->module
.ModuleName
));
333 module
->module
.ModuleName
[sizeof(module
->module
.ModuleName
) - 1] = '\0';
335 strncpy(module
->module
.ImageName
, ImageName
, sizeof(module
->module
.ImageName
));
336 module
->module
.ImageName
[sizeof(module
->module
.ImageName
) - 1] = '\0';
338 return module
->module
.BaseOfImage
;
341 /******************************************************************
345 BOOL
module_remove(struct process
* pcs
, struct module
* module
)
349 TRACE("%s (%p)\n", module
->module
.ModuleName
, module
);
350 hash_table_destroy(&module
->ht_symbols
);
351 hash_table_destroy(&module
->ht_types
);
352 HeapFree(GetProcessHeap(), 0, (char*)module
->sources
);
353 HeapFree(GetProcessHeap(), 0, module
->addr_sorttab
);
354 pool_destroy(&module
->pool
);
356 for (p
= &pcs
->lmodules
; *p
; p
= &(*p
)->next
)
361 HeapFree(GetProcessHeap(), 0, module
);
365 FIXME("This shouldn't happen\n");
369 /******************************************************************
370 * SymUnloadModule (DBGHELP.@)
373 BOOL WINAPI
SymUnloadModule(HANDLE hProcess
, DWORD BaseOfDll
)
376 struct module
* module
;
378 pcs
= process_find_by_handle(hProcess
);
379 if (!pcs
) return FALSE
;
380 module
= module_find_by_addr(pcs
, BaseOfDll
, DMT_UNKNOWN
);
381 if (!module
) return FALSE
;
382 return module_remove(pcs
, module
);
385 /******************************************************************
386 * SymEnumerateModules (DBGHELP.@)
389 BOOL WINAPI
SymEnumerateModules(HANDLE hProcess
,
390 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback
,
393 struct process
* pcs
= process_find_by_handle(hProcess
);
394 struct module
* module
;
396 if (!pcs
) return FALSE
;
398 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
400 if (!(dbghelp_options
& SYMOPT_WINE_WITH_ELF_MODULES
) && module
->type
!= DMT_PE
)
402 if (!EnumModulesCallback(module
->module
.ModuleName
,
403 module
->module
.BaseOfImage
, UserContext
))
409 /******************************************************************
410 * EnumerateLoadedModules (DBGHELP.@)
413 BOOL WINAPI
EnumerateLoadedModules(HANDLE hProcess
,
414 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback
,
418 char base
[256], mod
[256];
422 hMods
= HeapAlloc(GetProcessHeap(), 0, sz
);
423 if (!hMods
) return FALSE
;
425 if (!EnumProcessModules(hProcess
, hMods
, 256 * sizeof(hMods
[0]), &sz
))
427 /* hProcess should also be a valid process handle !! */
428 FIXME("If this happens, bump the number in mod\n");
429 HeapFree(GetProcessHeap(), 0, hMods
);
432 sz
/= sizeof(HMODULE
);
433 for (i
= 0; i
< sz
; i
++)
435 if (!GetModuleInformation(hProcess
, hMods
[i
], &mi
, sizeof(mi
)) ||
436 !GetModuleBaseNameA(hProcess
, hMods
[i
], base
, sizeof(base
)))
438 module_fill_module(base
, mod
, sizeof(mod
));
440 EnumLoadedModulesCallback(mod
, (DWORD
)mi
.lpBaseOfDll
, mi
.SizeOfImage
,
443 HeapFree(GetProcessHeap(), 0, hMods
);
445 return sz
!= 0 && i
== sz
;
448 /******************************************************************
449 * SymGetModuleInfo (DBGHELP.@)
452 BOOL WINAPI
SymGetModuleInfo(HANDLE hProcess
, DWORD dwAddr
,
453 PIMAGEHLP_MODULE ModuleInfo
)
455 struct process
* pcs
= process_find_by_handle(hProcess
);
456 struct module
* module
;
458 if (!pcs
) return FALSE
;
459 if (ModuleInfo
->SizeOfStruct
< sizeof(*ModuleInfo
)) return FALSE
;
460 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
461 if (!module
) return FALSE
;
463 *ModuleInfo
= module
->module
;
464 if (module
->module
.SymType
== SymNone
)
466 module
= module_get_container(pcs
, module
);
467 if (module
&& module
->module
.SymType
!= SymNone
)
468 ModuleInfo
->SymType
= module
->module
.SymType
;
474 /***********************************************************************
475 * SymGetModuleBase (IMAGEHLP.@)
477 DWORD WINAPI
SymGetModuleBase(HANDLE hProcess
, DWORD dwAddr
)
479 struct process
* pcs
= process_find_by_handle(hProcess
);
480 struct module
* module
;
483 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
484 if (!module
) return 0;
485 return module
->module
.BaseOfImage
;
488 /******************************************************************
489 * module_reset_debug_info
490 * Removes any debug information linked to a given module.
492 void module_reset_debug_info(struct module
* module
)
494 module
->sortlist_valid
= TRUE
;
495 module
->addr_sorttab
= NULL
;
496 hash_table_destroy(&module
->ht_symbols
);
497 module
->ht_symbols
.num_buckets
= 0;
498 module
->ht_symbols
.buckets
= NULL
;
499 hash_table_destroy(&module
->ht_types
);
500 module
->ht_types
.num_buckets
= 0;
501 module
->ht_types
.buckets
= NULL
;
502 module
->vtypes
.num_elts
= 0;
503 hash_table_destroy(&module
->ht_symbols
);
504 module
->sources_used
= module
->sources_alloc
= 0;
505 module
->sources
= NULL
;