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 /***********************************************************************
37 * Creates and links a new module to a process
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
)
44 struct module
* module
;
47 if (!(module
= HeapAlloc(GetProcessHeap(), 0, sizeof(*module
))))
50 memset(module
, 0, sizeof(*module
));
52 module
->next
= pcs
->lmodules
;
53 pcs
->lmodules
= module
;
55 TRACE("=> %s %08lx-%08lx %s\n",
56 type
== DMT_ELF
? "ELF" : (type
== DMT_PE
? "PE" : "---"),
57 mod_addr
, mod_addr
+ size
, name
);
59 pool_init(&module
->pool
, 65536);
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
;
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
;
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
85 hash_table_init(&module
->pool
, &module
->ht_symbols
, 4096);
86 hash_table_init(&module
->pool
, &module
->ht_types
, 4096);
88 module
->sources_used
= 0;
89 module
->sources_alloc
= 0;
95 /***********************************************************************
99 struct module
* module_find_by_name(const struct process
* pcs
,
100 const char* name
, enum DbgModuleType type
)
102 struct module
* module
;
104 if (type
== DMT_UNKNOWN
)
106 if ((module
= module_find_by_name(pcs
, name
, DMT_PE
)) ||
107 (module
= module_find_by_name(pcs
, name
, DMT_ELF
)))
112 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
114 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.LoadedImageName
))
117 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
119 if (type
== module
->type
&& !strcasecmp(name
, module
->module
.ModuleName
))
123 SetLastError(ERROR_INVALID_NAME
);
127 /***********************************************************************
128 * module_has_container
131 static struct module
* module_get_container(const struct process
* pcs
,
132 const struct module
* inner
)
134 struct module
* module
;
136 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
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
)
147 /******************************************************************
150 * get the debug information from a module:
151 * - if the module's type is deferred, then force loading of debug info (and return
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
157 struct module
* module_get_debug(const struct process
* pcs
, struct module
* module
)
159 if (!module
) return NULL
;
160 switch (module
->module
.SymType
)
164 module
= module_get_container(pcs
, module
);
165 if (!module
|| module
->module
.SymType
!= SymDeferred
) break;
168 switch (module
->type
)
171 elf_load_debug_info(module
);
174 pe_load_debug_info(pcs
, module
);
181 return (module
&& module
->module
.SymType
> SymNone
) ? module
: NULL
;
184 /***********************************************************************
185 * module_find_by_addr
187 * either the addr where module is loaded, or any address inside the
190 struct module
* module_find_by_addr(const struct process
* pcs
, unsigned long addr
,
191 enum DbgModuleType type
)
193 struct module
* module
;
195 if (type
== DMT_UNKNOWN
)
197 if ((module
= module_find_by_addr(pcs
, addr
, DMT_PE
)) ||
198 (module
= module_find_by_addr(pcs
, addr
, DMT_ELF
)))
203 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
205 if (type
== module
->type
&& addr
>= module
->module
.BaseOfImage
&&
206 addr
< module
->module
.BaseOfImage
+ module
->module
.ImageSize
)
210 SetLastError(ERROR_INVALID_ADDRESS
);
214 /***********************************************************************
215 * SymLoadModule (DBGHELP.@)
217 DWORD WINAPI
SymLoadModule(HANDLE hProcess
, HANDLE hFile
, char* ImageName
,
218 char* ModuleName
, DWORD BaseOfDll
, DWORD SizeOfDll
)
221 struct module
* module
= NULL
;
223 TRACE("(%p %p %s %s %08lx %08lx)\n",
224 hProcess
, hFile
, debugstr_a(ImageName
), debugstr_a(ModuleName
),
225 BaseOfDll
, SizeOfDll
);
227 pcs
= process_find_by_handle(hProcess
);
228 if (!pcs
) return FALSE
;
230 if (!(module
= pe_load_module(pcs
, ImageName
, hFile
, BaseOfDll
, SizeOfDll
)))
232 unsigned len
= strlen(ImageName
);
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
)))
238 WARN("Couldn't locate %s\n", ImageName
);
243 /* by default pe_load_module fills module.ModuleName from a derivation
244 * of ImageName. Overwrite it, if we have better information
248 strncpy(module
->module
.ModuleName
, ModuleName
,
249 sizeof(module
->module
.ModuleName
));
250 module
->module
.ModuleName
[sizeof(module
->module
.ModuleName
) - 1] = '\0';
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
);
257 return module
->module
.BaseOfImage
;
260 /******************************************************************
264 BOOL
module_remove(struct process
* pcs
, struct module
* module
)
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
);
275 for (p
= &pcs
->lmodules
; *p
; p
= &(*p
)->next
)
280 HeapFree(GetProcessHeap(), 0, module
);
284 FIXME("This shouldn't happen\n");
288 /******************************************************************
289 * SymUnloadModule (DBGHELP.@)
292 BOOL WINAPI
SymUnloadModule(HANDLE hProcess
, DWORD BaseOfDll
)
295 struct module
* module
;
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
);
304 /******************************************************************
305 * SymEnumerateModules (DBGHELP.@)
308 BOOL WINAPI
SymEnumerateModules(HANDLE hProcess
,
309 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback
,
312 struct process
* pcs
= process_find_by_handle(hProcess
);
313 struct module
* module
;
315 if (!pcs
) return FALSE
;
317 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
319 if (module
->type
!= DMT_PE
) continue;
320 if (!EnumModulesCallback(module
->module
.ModuleName
,
321 module
->module
.BaseOfImage
, UserContext
))
327 /******************************************************************
328 * EnumerateLoadedModules (DBGHELP.@)
331 BOOL WINAPI
EnumerateLoadedModules(HANDLE hProcess
,
332 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback
,
336 char img
[256], mod
[256];
340 hMods
= HeapAlloc(GetProcessHeap(), 0, sz
);
341 if (!hMods
) return FALSE
;
343 if (!EnumProcessModules(hProcess
, hMods
, 256 * sizeof(hMods
[0]), &sz
))
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
);
350 sz
/= sizeof(HMODULE
);
351 for (i
= 0; i
< sz
; i
++)
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
)))
357 EnumLoadedModulesCallback(mod
, (DWORD
)mi
.lpBaseOfDll
, mi
.SizeOfImage
,
360 HeapFree(GetProcessHeap(), 0, hMods
);
362 return sz
!= 0 && i
== sz
;
365 /******************************************************************
366 * SymGetModuleInfo (DBGHELP.@)
369 BOOL WINAPI
SymGetModuleInfo(HANDLE hProcess
, DWORD dwAddr
,
370 PIMAGEHLP_MODULE ModuleInfo
)
372 struct process
* pcs
= process_find_by_handle(hProcess
);
373 struct module
* module
;
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
;
380 *ModuleInfo
= module
->module
;
381 if (module
->module
.SymType
<= SymNone
)
383 module
= module_get_container(pcs
, module
);
384 if (module
&& module
->module
.SymType
> SymNone
)
385 ModuleInfo
->SymType
= module
->module
.SymType
;
391 /***********************************************************************
392 * SymGetModuleBase (IMAGEHLP.@)
394 DWORD WINAPI
SymGetModuleBase(HANDLE hProcess
, DWORD dwAddr
)
396 struct process
* pcs
= process_find_by_handle(hProcess
);
397 struct module
* module
;
400 module
= module_find_by_addr(pcs
, dwAddr
, DMT_UNKNOWN
);
401 if (!module
) return 0;
402 return module
->module
.BaseOfImage
;