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
)
38 const char *ptr
,*endptr
;
41 endptr
= in
+ strlen(in
);
42 for (ptr
= endptr
- 1;
43 ptr
>= in
&& *ptr
!= '/' && *ptr
!= '\\';
46 len
= min(endptr
-ptr
,size
-1);
47 memcpy(out
, ptr
, len
);
50 (!strcasecmp(&out
[len
- 4], ".dll") || !strcasecmp(&out
[len
- 4], ".exe")))
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
);
59 (!strcasecmp(&out
[len
- 7], ".dll.so") || !strcasecmp(&out
[len
- 7], ".exe.so")))
60 strcpy(&out
[len
- 7], "<elf>");
62 out
[len
- 7] == '.' && !strcasecmp(&out
[len
- 3], ".so"))
64 if (len
+ 3 < size
) strcpy(&out
[len
- 3], "<elf>");
65 else WARN("Buffer too short: %s\n", out
);
68 while ((*out
= tolower(*out
))) out
++;
71 /***********************************************************************
72 * Creates and links a new module to a process
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
)
79 struct module
* module
;
81 assert(type
== DMT_ELF
|| type
== DMT_PE
);
82 if (!(module
= HeapAlloc(GetProcessHeap(), 0, sizeof(*module
))))
85 memset(module
, 0, sizeof(*module
));
87 module
->next
= pcs
->lmodules
;
88 pcs
->lmodules
= module
;
90 TRACE("=> %s %08lx-%08lx %s\n",
91 type
== DMT_ELF
? "ELF" : (type
== DMT_PE
? "PE" : "---"),
92 mod_addr
, mod_addr
+ size
, name
);
94 pool_init(&module
->pool
, 65536);
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
;
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
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);
118 module
->sources_used
= 0;
119 module
->sources_alloc
= 0;
125 /***********************************************************************
126 * module_find_by_name
129 struct module
* module_find_by_name(const struct process
* pcs
,
130 const char* name
, enum module_type type
)
132 struct module
* module
;
134 if (type
== DMT_UNKNOWN
)
136 if ((module
= module_find_by_name(pcs
, name
, DMT_PE
)) ||
137 (module
= module_find_by_name(pcs
, name
, DMT_ELF
)))
142 char modname
[MAX_PATH
];
144 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
146 if (type
== module
->type
&&
147 !strcasecmp(name
, module
->module
.LoadedImageName
))
150 module_fill_module(name
, modname
, sizeof(modname
));
151 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
153 if (type
== module
->type
&&
154 !strcasecmp(modname
, module
->module
.ModuleName
))
158 SetLastError(ERROR_INVALID_NAME
);
162 /***********************************************************************
163 * module_get_container
166 struct module
* module_get_container(const struct process
* pcs
,
167 const struct module
* inner
)
169 struct module
* module
;
171 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
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
)
182 /***********************************************************************
183 * module_get_containee
186 struct module
* module_get_containee(const struct process
* pcs
,
187 const struct module
* outter
)
189 struct module
* module
;
191 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
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
)
202 /******************************************************************
205 * get the debug information from a module:
206 * - if the module's type is deferred, then force loading of debug info (and return
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
212 struct module
* module_get_debug(const struct process
* pcs
, struct module
* module
)
214 struct module
* parent
;
216 if (!module
) return NULL
;
217 /* for a PE builtin, always get info from parent */
218 if ((parent
= module_get_container(pcs
, module
)))
220 /* if deferred, force loading */
221 if (module
->module
.SymType
== SymDeferred
)
225 switch (module
->type
)
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;
231 if (!ret
) module
->module
.SymType
= SymNone
;
232 assert(module
->module
.SymType
!= SymDeferred
);
234 return (module
&& module
->module
.SymType
!= SymNone
) ? module
: NULL
;
237 /***********************************************************************
238 * module_find_by_addr
240 * either the addr where module is loaded, or any address inside the
243 struct module
* module_find_by_addr(const struct process
* pcs
, unsigned long addr
,
244 enum module_type type
)
246 struct module
* module
;
248 if (type
== DMT_UNKNOWN
)
250 if ((module
= module_find_by_addr(pcs
, addr
, DMT_PE
)) ||
251 (module
= module_find_by_addr(pcs
, addr
, DMT_ELF
)))
256 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
258 if (type
== module
->type
&& addr
>= module
->module
.BaseOfImage
&&
259 addr
< module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
263 SetLastError(ERROR_INVALID_ADDRESS
);
267 static BOOL
module_is_elf_container_loaded(struct process
* pcs
, const char* ImageName
,
268 const char* ModuleName
)
270 char buffer
[MAX_PATH
];
272 struct module
* module
;
276 module_fill_module(ImageName
, buffer
, sizeof(buffer
));
279 len
= strlen(ModuleName
);
280 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
282 if (!strncasecmp(module
->module
.ModuleName
, ModuleName
, len
) &&
283 module
->type
== DMT_ELF
&&
284 !strcmp(module
->module
.ModuleName
+ len
, "<elf>"))
290 /******************************************************************
291 * module_get_type_by_name
293 * Guesses a filename type from its extension
295 enum module_type
module_get_type_by_name(const char* name
)
298 int len
= strlen(name
);
300 /* check for terminating .so or .so.[digit] */
301 ptr
= strrchr(name
, '.');
304 if (!strcmp(ptr
, ".so") ||
305 (isdigit(ptr
[1]) && !ptr
[2] && ptr
>= name
+ 3 && !memcmp(ptr
- 3, ".so", 3)))
307 else if (!strcasecmp(ptr
, ".pdb"))
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")))
320 /***********************************************************************
321 * SymLoadModule (DBGHELP.@)
323 DWORD WINAPI
SymLoadModule(HANDLE hProcess
, HANDLE hFile
, char* ImageName
,
324 char* ModuleName
, DWORD BaseOfDll
, DWORD SizeOfDll
)
327 struct module
* module
= NULL
;
329 TRACE("(%p %p %s %s %08lx %08lx)\n",
330 hProcess
, hFile
, debugstr_a(ImageName
), debugstr_a(ModuleName
),
331 BaseOfDll
, SizeOfDll
);
333 pcs
= process_find_by_handle(hProcess
);
334 if (!pcs
) return FALSE
;
336 /* force transparent ELF loading / unloading */
337 elf_synchronize_module_list(pcs
);
339 /* this is a Wine extension to the API just to redo the synchronisation */
340 if (!ImageName
&& !hFile
) return 0;
342 if (module_is_elf_container_loaded(pcs
, ImageName
, ModuleName
))
344 /* force the loading of DLL as builtin */
345 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
,
346 BaseOfDll
, SizeOfDll
)))
348 WARN("Couldn't locate %s\n", ImageName
);
351 TRACE("Assuming %s as native DLL\n", ImageName
);
352 if (!(module
= pe_load_module(pcs
, ImageName
, hFile
, BaseOfDll
, SizeOfDll
)))
354 if (module_get_type_by_name(ImageName
) == DMT_ELF
&&
355 (module
= elf_load_module(pcs
, ImageName
, BaseOfDll
)))
357 FIXME("Should have successfully loaded debug information for image %s\n",
359 if ((module
= pe_load_module_from_pcs(pcs
, ImageName
, ModuleName
,
360 BaseOfDll
, SizeOfDll
)))
362 WARN("Couldn't locate %s\n", ImageName
);
367 /* by default pe_load_module fills module.ModuleName from a derivation
368 * of ImageName. Overwrite it, if we have better information
371 lstrcpynA(module
->module
.ModuleName
, ModuleName
, sizeof(module
->module
.ModuleName
));
372 lstrcpynA(module
->module
.ImageName
, ImageName
, sizeof(module
->module
.ImageName
));
374 return module
->module
.BaseOfImage
;
377 /******************************************************************
381 BOOL
module_remove(struct process
* pcs
, struct module
* module
)
385 TRACE("%s (%p)\n", module
->module
.ModuleName
, module
);
386 hash_table_destroy(&module
->ht_symbols
);
387 hash_table_destroy(&module
->ht_types
);
388 HeapFree(GetProcessHeap(), 0, (char*)module
->sources
);
389 HeapFree(GetProcessHeap(), 0, module
->addr_sorttab
);
390 pool_destroy(&module
->pool
);
392 for (p
= &pcs
->lmodules
; *p
; p
= &(*p
)->next
)
397 HeapFree(GetProcessHeap(), 0, module
);
401 FIXME("This shouldn't happen\n");
405 /******************************************************************
406 * SymUnloadModule (DBGHELP.@)
409 BOOL WINAPI
SymUnloadModule(HANDLE hProcess
, DWORD BaseOfDll
)
412 struct module
* module
;
414 pcs
= process_find_by_handle(hProcess
);
415 if (!pcs
) return FALSE
;
416 module
= module_find_by_addr(pcs
, BaseOfDll
, DMT_UNKNOWN
);
417 if (!module
) return FALSE
;
418 return module_remove(pcs
, module
);
421 /******************************************************************
422 * SymEnumerateModules (DBGHELP.@)
425 BOOL WINAPI
SymEnumerateModules(HANDLE hProcess
,
426 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback
,
429 struct process
* pcs
= process_find_by_handle(hProcess
);
430 struct module
* module
;
432 if (!pcs
) return FALSE
;
434 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
436 if (!(dbghelp_options
& SYMOPT_WINE_WITH_ELF_MODULES
) && module
->type
!= DMT_PE
)
438 if (!EnumModulesCallback(module
->module
.ModuleName
,
439 module
->module
.BaseOfImage
, UserContext
))
445 /******************************************************************
446 * EnumerateLoadedModules (DBGHELP.@)
449 BOOL WINAPI
EnumerateLoadedModules(HANDLE hProcess
,
450 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback
,
454 char base
[256], mod
[256];
458 hMods
= HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods
[0]));
459 if (!hMods
) return FALSE
;
461 if (!EnumProcessModules(hProcess
, hMods
, 256 * sizeof(hMods
[0]), &sz
))
463 /* hProcess should also be a valid process handle !! */
464 FIXME("If this happens, bump the number in mod\n");
465 HeapFree(GetProcessHeap(), 0, hMods
);
468 sz
/= sizeof(HMODULE
);
469 for (i
= 0; i
< sz
; i
++)
471 if (!GetModuleInformation(hProcess
, hMods
[i
], &mi
, sizeof(mi
)) ||
472 !GetModuleBaseNameA(hProcess
, hMods
[i
], base
, sizeof(base
)))
474 module_fill_module(base
, mod
, sizeof(mod
));
475 EnumLoadedModulesCallback(mod
, (DWORD
)mi
.lpBaseOfDll
, mi
.SizeOfImage
,
478 HeapFree(GetProcessHeap(), 0, hMods
);
480 return sz
!= 0 && i
== sz
;
483 /******************************************************************
484 * SymGetModuleInfo (DBGHELP.@)
487 BOOL WINAPI
SymGetModuleInfo(HANDLE hProcess
, DWORD dwAddr
,
488 PIMAGEHLP_MODULE ModuleInfo
)
490 struct process
* pcs
= process_find_by_handle(hProcess
);
491 struct module
* module
;
493 if (!pcs
) return FALSE
;
494 if (ModuleInfo
->SizeOfStruct
< sizeof(*ModuleInfo
)) return FALSE
;
495 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
496 if (!module
) return FALSE
;
498 *ModuleInfo
= module
->module
;
499 if (module
->module
.SymType
== SymNone
)
501 module
= module_get_container(pcs
, module
);
502 if (module
&& module
->module
.SymType
!= SymNone
)
503 ModuleInfo
->SymType
= module
->module
.SymType
;
509 /***********************************************************************
510 * SymGetModuleBase (IMAGEHLP.@)
512 DWORD WINAPI
SymGetModuleBase(HANDLE hProcess
, DWORD dwAddr
)
514 struct process
* pcs
= process_find_by_handle(hProcess
);
515 struct module
* module
;
518 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
519 if (!module
) return 0;
520 return module
->module
.BaseOfImage
;
523 /******************************************************************
524 * module_reset_debug_info
525 * Removes any debug information linked to a given module.
527 void module_reset_debug_info(struct module
* module
)
529 module
->sortlist_valid
= TRUE
;
530 module
->addr_sorttab
= NULL
;
531 hash_table_destroy(&module
->ht_symbols
);
532 module
->ht_symbols
.num_buckets
= 0;
533 module
->ht_symbols
.buckets
= NULL
;
534 hash_table_destroy(&module
->ht_types
);
535 module
->ht_types
.num_buckets
= 0;
536 module
->ht_types
.buckets
= NULL
;
537 module
->vtypes
.num_elts
= 0;
538 hash_table_destroy(&module
->ht_symbols
);
539 module
->sources_used
= module
->sources_alloc
= 0;
540 module
->sources
= NULL
;