Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmodule.c
Go to the documentation of this file.
00001 /* 00002 * File module.c - module handling for the wine debugger 00003 * 00004 * Copyright (C) 1993, Eric Youngdale. 00005 * 2000-2007, Eric Pouech 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "config.h" 00023 #include <stdlib.h> 00024 #include <stdio.h> 00025 #include <string.h> 00026 #include <assert.h> 00027 00028 #include "dbghelp_private.h" 00029 #include "psapi.h" 00030 #include "winternl.h" 00031 #include "wine/debug.h" 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); 00034 00035 const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'}; 00036 const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'}; 00037 static const WCHAR S_DotSoW[] = {'.','s','o','\0'}; 00038 static const WCHAR S_DotDylibW[] = {'.','d','y','l','i','b','\0'}; 00039 static const WCHAR S_DotPdbW[] = {'.','p','d','b','\0'}; 00040 static const WCHAR S_DotDbgW[] = {'.','d','b','g','\0'}; 00041 const WCHAR S_SlashW[] = {'/','\0'}; 00042 00043 static const WCHAR S_AcmW[] = {'.','a','c','m','\0'}; 00044 static const WCHAR S_DllW[] = {'.','d','l','l','\0'}; 00045 static const WCHAR S_DrvW[] = {'.','d','r','v','\0'}; 00046 static const WCHAR S_ExeW[] = {'.','e','x','e','\0'}; 00047 static const WCHAR S_OcxW[] = {'.','o','c','x','\0'}; 00048 static const WCHAR S_VxdW[] = {'.','v','x','d','\0'}; 00049 static const WCHAR * const ext[] = {S_AcmW, S_DllW, S_DrvW, S_ExeW, S_OcxW, S_VxdW, NULL}; 00050 00051 static int match_ext(const WCHAR* ptr, size_t len) 00052 { 00053 const WCHAR* const *e; 00054 size_t l; 00055 00056 for (e = ext; *e; e++) 00057 { 00058 l = strlenW(*e); 00059 if (l >= len) return FALSE; 00060 if (strncmpiW(&ptr[len - l], *e, l)) continue; 00061 return l; 00062 } 00063 return 0; 00064 } 00065 00066 static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr) 00067 { 00068 const WCHAR* ptr; 00069 00070 if (!endptr) endptr = name + strlenW(name); 00071 for (ptr = endptr - 1; ptr >= name; ptr--) 00072 { 00073 if (*ptr == '/' || *ptr == '\\') break; 00074 } 00075 return ++ptr; 00076 } 00077 00078 static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size) 00079 { 00080 const WCHAR *loader = get_wine_loader_name(); 00081 const WCHAR *ptr, *endptr; 00082 size_t len, l; 00083 00084 ptr = get_filename(in, endptr = in + strlenW(in)); 00085 len = min(endptr - ptr, size - 1); 00086 memcpy(out, ptr, len * sizeof(WCHAR)); 00087 out[len] = '\0'; 00088 if (len > 4 && (l = match_ext(out, len))) 00089 out[len - l] = '\0'; 00090 else if (len > strlenW(loader) && !strcmpiW(out + len - strlenW(loader), loader)) 00091 lstrcpynW(out, S_WineLoaderW, size); 00092 else 00093 { 00094 if (len > 3 && !strcmpiW(&out[len - 3], S_DotSoW) && 00095 (l = match_ext(out, len - 3))) 00096 strcpyW(&out[len - l - 3], S_ElfW); 00097 } 00098 while ((*out = tolowerW(*out))) out++; 00099 } 00100 00101 void module_set_module(struct module* module, const WCHAR* name) 00102 { 00103 module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName)); 00104 WideCharToMultiByte(CP_ACP, 0, module->module.ModuleName, -1, 00105 module->module_name, sizeof(module->module_name), 00106 NULL, NULL); 00107 } 00108 00109 const WCHAR *get_wine_loader_name(void) 00110 { 00111 static const int is_win64 = sizeof(void *) > sizeof(int); /* FIXME: should depend on target process */ 00112 static const WCHAR wineW[] = {'w','i','n','e',0}; 00113 static const WCHAR suffixW[] = {'6','4',0}; 00114 static const WCHAR *loader; 00115 00116 if (!loader) 00117 { 00118 WCHAR *p, *buffer; 00119 const char *ptr; 00120 00121 /* All binaries are loaded with WINELOADER (if run from tree) or by the 00122 * main executable 00123 */ 00124 if ((ptr = getenv("WINELOADER"))) 00125 { 00126 DWORD len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, NULL, 0 ); 00127 buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); 00128 MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, buffer, len ); 00129 } 00130 else 00131 { 00132 buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(wineW) + 2 * sizeof(WCHAR) ); 00133 strcpyW( buffer, wineW ); 00134 } 00135 p = buffer + strlenW( buffer ) - strlenW( suffixW ); 00136 if (p > buffer && !strcmpW( p, suffixW )) 00137 { 00138 if (!is_win64) *p = 0; 00139 } 00140 else if (is_win64) strcatW( buffer, suffixW ); 00141 00142 TRACE( "returning %s\n", debugstr_w(buffer) ); 00143 loader = buffer; 00144 } 00145 return loader; 00146 } 00147 00148 static const char* get_module_type(enum module_type type, BOOL virtual) 00149 { 00150 switch (type) 00151 { 00152 case DMT_ELF: return virtual ? "Virtual ELF" : "ELF"; 00153 case DMT_PE: return virtual ? "Virtual PE" : "PE"; 00154 case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O"; 00155 default: return "---"; 00156 } 00157 } 00158 00159 /*********************************************************************** 00160 * Creates and links a new module to a process 00161 */ 00162 struct module* module_new(struct process* pcs, const WCHAR* name, 00163 enum module_type type, BOOL virtual, 00164 DWORD64 mod_addr, DWORD64 size, 00165 unsigned long stamp, unsigned long checksum) 00166 { 00167 struct module* module; 00168 unsigned i; 00169 00170 assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO); 00171 if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module)))) 00172 return NULL; 00173 00174 module->next = pcs->lmodules; 00175 pcs->lmodules = module; 00176 00177 TRACE("=> %s %s-%s %s\n", 00178 get_module_type(type, virtual), 00179 wine_dbgstr_longlong(mod_addr), wine_dbgstr_longlong(mod_addr + size), 00180 debugstr_w(name)); 00181 00182 pool_init(&module->pool, 65536); 00183 00184 module->process = pcs; 00185 module->module.SizeOfStruct = sizeof(module->module); 00186 module->module.BaseOfImage = mod_addr; 00187 module->module.ImageSize = size; 00188 module_set_module(module, name); 00189 module->module.ImageName[0] = '\0'; 00190 lstrcpynW(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName) / sizeof(WCHAR)); 00191 module->module.SymType = SymNone; 00192 module->module.NumSyms = 0; 00193 module->module.TimeDateStamp = stamp; 00194 module->module.CheckSum = checksum; 00195 00196 memset(module->module.LoadedPdbName, 0, sizeof(module->module.LoadedPdbName)); 00197 module->module.CVSig = 0; 00198 memset(module->module.CVData, 0, sizeof(module->module.CVData)); 00199 module->module.PdbSig = 0; 00200 memset(&module->module.PdbSig70, 0, sizeof(module->module.PdbSig70)); 00201 module->module.PdbAge = 0; 00202 module->module.PdbUnmatched = FALSE; 00203 module->module.DbgUnmatched = FALSE; 00204 module->module.LineNumbers = FALSE; 00205 module->module.GlobalSymbols = FALSE; 00206 module->module.TypeInfo = FALSE; 00207 module->module.SourceIndexed = FALSE; 00208 module->module.Publics = FALSE; 00209 00210 module->reloc_delta = 0; 00211 module->type = type; 00212 module->is_virtual = virtual ? TRUE : FALSE; 00213 for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; 00214 module->sortlist_valid = FALSE; 00215 module->sorttab_size = 0; 00216 module->addr_sorttab = NULL; 00217 module->num_sorttab = 0; 00218 module->num_symbols = 0; 00219 00220 vector_init(&module->vsymt, sizeof(struct symt*), 128); 00221 /* FIXME: this seems a bit too high (on a per module basis) 00222 * need some statistics about this 00223 */ 00224 hash_table_init(&module->pool, &module->ht_symbols, 4096); 00225 hash_table_init(&module->pool, &module->ht_types, 4096); 00226 vector_init(&module->vtypes, sizeof(struct symt*), 32); 00227 00228 module->sources_used = 0; 00229 module->sources_alloc = 0; 00230 module->sources = 0; 00231 wine_rb_init(&module->sources_offsets_tree, &source_rb_functions); 00232 00233 return module; 00234 } 00235 00236 /*********************************************************************** 00237 * module_find_by_nameW 00238 * 00239 */ 00240 struct module* module_find_by_nameW(const struct process* pcs, const WCHAR* name) 00241 { 00242 struct module* module; 00243 00244 for (module = pcs->lmodules; module; module = module->next) 00245 { 00246 if (!strcmpiW(name, module->module.ModuleName)) return module; 00247 } 00248 SetLastError(ERROR_INVALID_NAME); 00249 return NULL; 00250 } 00251 00252 struct module* module_find_by_nameA(const struct process* pcs, const char* name) 00253 { 00254 WCHAR wname[MAX_PATH]; 00255 00256 MultiByteToWideChar(CP_ACP, 0, name, -1, wname, sizeof(wname) / sizeof(WCHAR)); 00257 return module_find_by_nameW(pcs, wname); 00258 } 00259 00260 /*********************************************************************** 00261 * module_is_already_loaded 00262 * 00263 */ 00264 struct module* module_is_already_loaded(const struct process* pcs, const WCHAR* name) 00265 { 00266 struct module* module; 00267 const WCHAR* filename; 00268 00269 /* first compare the loaded image name... */ 00270 for (module = pcs->lmodules; module; module = module->next) 00271 { 00272 if (!strcmpiW(name, module->module.LoadedImageName)) 00273 return module; 00274 } 00275 /* then compare the standard filenames (without the path) ... */ 00276 filename = get_filename(name, NULL); 00277 for (module = pcs->lmodules; module; module = module->next) 00278 { 00279 if (!strcmpiW(filename, get_filename(module->module.LoadedImageName, NULL))) 00280 return module; 00281 } 00282 SetLastError(ERROR_INVALID_NAME); 00283 return NULL; 00284 } 00285 00286 /*********************************************************************** 00287 * module_get_container 00288 * 00289 */ 00290 static struct module* module_get_container(const struct process* pcs, 00291 const struct module* inner) 00292 { 00293 struct module* module; 00294 00295 for (module = pcs->lmodules; module; module = module->next) 00296 { 00297 if (module != inner && 00298 module->module.BaseOfImage <= inner->module.BaseOfImage && 00299 module->module.BaseOfImage + module->module.ImageSize >= 00300 inner->module.BaseOfImage + inner->module.ImageSize) 00301 return module; 00302 } 00303 return NULL; 00304 } 00305 00306 /*********************************************************************** 00307 * module_get_containee 00308 * 00309 */ 00310 struct module* module_get_containee(const struct process* pcs, 00311 const struct module* outter) 00312 { 00313 struct module* module; 00314 00315 for (module = pcs->lmodules; module; module = module->next) 00316 { 00317 if (module != outter && 00318 outter->module.BaseOfImage <= module->module.BaseOfImage && 00319 outter->module.BaseOfImage + outter->module.ImageSize >= 00320 module->module.BaseOfImage + module->module.ImageSize) 00321 return module; 00322 } 00323 return NULL; 00324 } 00325 00326 /****************************************************************** 00327 * module_get_debug 00328 * 00329 * get the debug information from a module: 00330 * - if the module's type is deferred, then force loading of debug info (and return 00331 * the module itself) 00332 * - if the module has no debug info and has an ELF container, then return the ELF 00333 * container (and also force the ELF container's debug info loading if deferred) 00334 * - otherwise return the module itself if it has some debug info 00335 */ 00336 BOOL module_get_debug(struct module_pair* pair) 00337 { 00338 IMAGEHLP_DEFERRED_SYMBOL_LOADW64 idslW64; 00339 00340 if (!pair->requested) return FALSE; 00341 /* for a PE builtin, always get info from container */ 00342 if (!(pair->effective = module_get_container(pair->pcs, pair->requested))) 00343 pair->effective = pair->requested; 00344 /* if deferred, force loading */ 00345 if (pair->effective->module.SymType == SymDeferred) 00346 { 00347 BOOL ret; 00348 00349 if (pair->effective->is_virtual) ret = FALSE; 00350 else switch (pair->effective->type) 00351 { 00352 case DMT_ELF: 00353 ret = elf_load_debug_info(pair->effective); 00354 break; 00355 case DMT_PE: 00356 idslW64.SizeOfStruct = sizeof(idslW64); 00357 idslW64.BaseOfImage = pair->effective->module.BaseOfImage; 00358 idslW64.CheckSum = pair->effective->module.CheckSum; 00359 idslW64.TimeDateStamp = pair->effective->module.TimeDateStamp; 00360 memcpy(idslW64.FileName, pair->effective->module.ImageName, 00361 sizeof(pair->effective->module.ImageName)); 00362 idslW64.Reparse = FALSE; 00363 idslW64.hFile = INVALID_HANDLE_VALUE; 00364 00365 pcs_callback(pair->pcs, CBA_DEFERRED_SYMBOL_LOAD_START, &idslW64); 00366 ret = pe_load_debug_info(pair->pcs, pair->effective); 00367 pcs_callback(pair->pcs, 00368 ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE, 00369 &idslW64); 00370 break; 00371 case DMT_MACHO: 00372 ret = macho_load_debug_info(pair->effective, NULL); 00373 break; 00374 default: 00375 ret = FALSE; 00376 break; 00377 } 00378 if (!ret) pair->effective->module.SymType = SymNone; 00379 assert(pair->effective->module.SymType != SymDeferred); 00380 pair->effective->module.NumSyms = pair->effective->ht_symbols.num_elts; 00381 } 00382 return pair->effective->module.SymType != SymNone; 00383 } 00384 00385 /*********************************************************************** 00386 * module_find_by_addr 00387 * 00388 * either the addr where module is loaded, or any address inside the 00389 * module 00390 */ 00391 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 00392 enum module_type type) 00393 { 00394 struct module* module; 00395 00396 if (type == DMT_UNKNOWN) 00397 { 00398 if ((module = module_find_by_addr(pcs, addr, DMT_PE)) || 00399 (module = module_find_by_addr(pcs, addr, DMT_ELF)) || 00400 (module = module_find_by_addr(pcs, addr, DMT_MACHO))) 00401 return module; 00402 } 00403 else 00404 { 00405 for (module = pcs->lmodules; module; module = module->next) 00406 { 00407 if (type == module->type && addr >= module->module.BaseOfImage && 00408 addr < module->module.BaseOfImage + module->module.ImageSize) 00409 return module; 00410 } 00411 } 00412 SetLastError(ERROR_INVALID_ADDRESS); 00413 return module; 00414 } 00415 00416 /****************************************************************** 00417 * module_is_container_loaded 00418 * 00419 * checks whether the native container, for a (supposed) PE builtin is 00420 * already loaded 00421 */ 00422 static BOOL module_is_container_loaded(const struct process* pcs, 00423 const WCHAR* ImageName, DWORD64 base) 00424 { 00425 size_t len; 00426 struct module* module; 00427 PCWSTR filename, modname; 00428 00429 if (!base) return FALSE; 00430 filename = get_filename(ImageName, NULL); 00431 len = strlenW(filename); 00432 00433 for (module = pcs->lmodules; module; module = module->next) 00434 { 00435 if ((module->type == DMT_ELF || module->type == DMT_MACHO) && 00436 base >= module->module.BaseOfImage && 00437 base < module->module.BaseOfImage + module->module.ImageSize) 00438 { 00439 modname = get_filename(module->module.LoadedImageName, NULL); 00440 if (!strncmpiW(modname, filename, len) && 00441 !memcmp(modname + len, S_DotSoW, 3 * sizeof(WCHAR))) 00442 { 00443 return TRUE; 00444 } 00445 } 00446 } 00447 /* likely a native PE module */ 00448 WARN("Couldn't find container for %s\n", debugstr_w(ImageName)); 00449 return FALSE; 00450 } 00451 00452 /****************************************************************** 00453 * module_get_type_by_name 00454 * 00455 * Guesses a filename type from its extension 00456 */ 00457 enum module_type module_get_type_by_name(const WCHAR* name) 00458 { 00459 int loader_len, len = strlenW(name); 00460 const WCHAR *loader; 00461 00462 /* Skip all version extensions (.[digits]) regex: "(\.\d+)*$" */ 00463 do 00464 { 00465 int i = len; 00466 00467 while (i && isdigit(name[i - 1])) i--; 00468 00469 if (i && name[i - 1] == '.') 00470 len = i - 1; 00471 else 00472 break; 00473 } while (len); 00474 00475 /* check for terminating .so or .so.[digit] */ 00476 /* FIXME: Can't rely solely on extension; have to check magic or 00477 * stop using .so on Mac OS X. For now, base on platform. */ 00478 if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3)) 00479 #ifdef __APPLE__ 00480 return DMT_MACHO; 00481 #else 00482 return DMT_ELF; 00483 #endif 00484 00485 if (len > 6 && !strncmpiW(name + len - 6, S_DotDylibW, 6)) 00486 return DMT_MACHO; 00487 00488 if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4)) 00489 return DMT_PDB; 00490 00491 if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4)) 00492 return DMT_DBG; 00493 00494 /* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */ 00495 loader = get_wine_loader_name(); 00496 loader_len = strlenW( loader ); 00497 if ((len == loader_len || (len > loader_len && name[len - loader_len - 1] == '/')) && 00498 !strcmpiW(name + len - loader_len, loader)) 00499 { 00500 #ifdef __APPLE__ 00501 return DMT_MACHO; 00502 #else 00503 return DMT_ELF; 00504 #endif 00505 } 00506 return DMT_PE; 00507 } 00508 00509 /****************************************************************** 00510 * refresh_module_list 00511 */ 00512 static BOOL refresh_module_list(struct process* pcs) 00513 { 00514 /* force transparent ELF and Mach-O loading / unloading */ 00515 return elf_synchronize_module_list(pcs) || macho_synchronize_module_list(pcs); 00516 } 00517 00518 /*********************************************************************** 00519 * SymLoadModule (DBGHELP.@) 00520 */ 00521 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 00522 PCSTR ModuleName, DWORD BaseOfDll, DWORD SizeOfDll) 00523 { 00524 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, 00525 SizeOfDll, NULL, 0); 00526 } 00527 00528 /*********************************************************************** 00529 * SymLoadModuleEx (DBGHELP.@) 00530 */ 00531 DWORD64 WINAPI SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 00532 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize, 00533 PMODLOAD_DATA Data, DWORD Flags) 00534 { 00535 PWSTR wImageName, wModuleName; 00536 unsigned len; 00537 DWORD64 ret; 00538 00539 TRACE("(%p %p %s %s %s %08x %p %08x)\n", 00540 hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName), 00541 wine_dbgstr_longlong(BaseOfDll), DllSize, Data, Flags); 00542 00543 if (ImageName) 00544 { 00545 len = MultiByteToWideChar(CP_ACP, 0, ImageName, -1, NULL, 0); 00546 wImageName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00547 MultiByteToWideChar(CP_ACP, 0, ImageName, -1, wImageName, len); 00548 } 00549 else wImageName = NULL; 00550 if (ModuleName) 00551 { 00552 len = MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, NULL, 0); 00553 wModuleName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00554 MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, wModuleName, len); 00555 } 00556 else wModuleName = NULL; 00557 00558 ret = SymLoadModuleExW(hProcess, hFile, wImageName, wModuleName, 00559 BaseOfDll, DllSize, Data, Flags); 00560 HeapFree(GetProcessHeap(), 0, wImageName); 00561 HeapFree(GetProcessHeap(), 0, wModuleName); 00562 return ret; 00563 } 00564 00565 /*********************************************************************** 00566 * SymLoadModuleExW (DBGHELP.@) 00567 */ 00568 DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName, 00569 PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll, 00570 PMODLOAD_DATA Data, DWORD Flags) 00571 { 00572 struct process* pcs; 00573 struct module* module = NULL; 00574 00575 TRACE("(%p %p %s %s %s %08x %p %08x)\n", 00576 hProcess, hFile, debugstr_w(wImageName), debugstr_w(wModuleName), 00577 wine_dbgstr_longlong(BaseOfDll), SizeOfDll, Data, Flags); 00578 00579 if (Data) 00580 FIXME("Unsupported load data parameter %p for %s\n", 00581 Data, debugstr_w(wImageName)); 00582 if (!validate_addr64(BaseOfDll)) return FALSE; 00583 00584 if (!(pcs = process_find_by_handle(hProcess))) return FALSE; 00585 00586 if (Flags & SLMFLAG_VIRTUAL) 00587 { 00588 if (!wImageName) return FALSE; 00589 module = module_new(pcs, wImageName, module_get_type_by_name(wImageName), 00590 TRUE, BaseOfDll, SizeOfDll, 0, 0); 00591 if (!module) return FALSE; 00592 if (wModuleName) module_set_module(module, wModuleName); 00593 module->module.SymType = SymVirtual; 00594 00595 return TRUE; 00596 } 00597 if (Flags & ~(SLMFLAG_VIRTUAL)) 00598 FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName)); 00599 00600 refresh_module_list(pcs); 00601 00602 /* this is a Wine extension to the API just to redo the synchronisation */ 00603 if (!wImageName && !hFile) return 0; 00604 00605 /* check if the module is already loaded, or if it's a builtin PE module with 00606 * an containing ELF module 00607 */ 00608 if (wImageName) 00609 { 00610 module = module_is_already_loaded(pcs, wImageName); 00611 if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll)) 00612 { 00613 /* force the loading of DLL as builtin */ 00614 module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll); 00615 } 00616 } 00617 if (!module) 00618 { 00619 /* otherwise, try a regular PE module */ 00620 if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) && 00621 wImageName) 00622 { 00623 /* and finally an ELF or Mach-O module */ 00624 switch (module_get_type_by_name(wImageName)) 00625 { 00626 case DMT_ELF: 00627 module = elf_load_module(pcs, wImageName, BaseOfDll); 00628 break; 00629 case DMT_MACHO: 00630 module = macho_load_module(pcs, wImageName, BaseOfDll); 00631 break; 00632 default: 00633 /* Ignored */ 00634 break; 00635 } 00636 } 00637 } 00638 if (!module) 00639 { 00640 WARN("Couldn't locate %s\n", debugstr_w(wImageName)); 00641 return 0; 00642 } 00643 module->module.NumSyms = module->ht_symbols.num_elts; 00644 /* by default module_new fills module.ModuleName from a derivation 00645 * of LoadedImageName. Overwrite it, if we have better information 00646 */ 00647 if (wModuleName) 00648 module_set_module(module, wModuleName); 00649 if (wImageName) 00650 lstrcpynW(module->module.ImageName, wImageName, 00651 sizeof(module->module.ImageName) / sizeof(WCHAR)); 00652 00653 return module->module.BaseOfImage; 00654 } 00655 00656 /*********************************************************************** 00657 * SymLoadModule64 (DBGHELP.@) 00658 */ 00659 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 00660 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) 00661 { 00662 if (!validate_addr64(BaseOfDll)) return FALSE; 00663 return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, SizeOfDll); 00664 } 00665 00666 /****************************************************************** 00667 * module_remove 00668 * 00669 */ 00670 BOOL module_remove(struct process* pcs, struct module* module) 00671 { 00672 struct module_format*modfmt; 00673 struct module** p; 00674 unsigned i; 00675 00676 TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module); 00677 00678 for (i = 0; i < DFI_LAST; i++) 00679 { 00680 if ((modfmt = module->format_info[i]) && modfmt->remove) 00681 modfmt->remove(pcs, module->format_info[i]); 00682 } 00683 hash_table_destroy(&module->ht_symbols); 00684 hash_table_destroy(&module->ht_types); 00685 wine_rb_destroy(&module->sources_offsets_tree, NULL, NULL); 00686 HeapFree(GetProcessHeap(), 0, module->sources); 00687 HeapFree(GetProcessHeap(), 0, module->addr_sorttab); 00688 pool_destroy(&module->pool); 00689 /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here 00690 * so do we 00691 */ 00692 for (p = &pcs->lmodules; *p; p = &(*p)->next) 00693 { 00694 if (*p == module) 00695 { 00696 *p = module->next; 00697 HeapFree(GetProcessHeap(), 0, module); 00698 return TRUE; 00699 } 00700 } 00701 FIXME("This shouldn't happen\n"); 00702 return FALSE; 00703 } 00704 00705 /****************************************************************** 00706 * SymUnloadModule (DBGHELP.@) 00707 * 00708 */ 00709 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll) 00710 { 00711 struct process* pcs; 00712 struct module* module; 00713 00714 pcs = process_find_by_handle(hProcess); 00715 if (!pcs) return FALSE; 00716 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); 00717 if (!module) return FALSE; 00718 return module_remove(pcs, module); 00719 } 00720 00721 /****************************************************************** 00722 * SymUnloadModule64 (DBGHELP.@) 00723 * 00724 */ 00725 BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll) 00726 { 00727 struct process* pcs; 00728 struct module* module; 00729 00730 pcs = process_find_by_handle(hProcess); 00731 if (!pcs) return FALSE; 00732 if (!validate_addr64(BaseOfDll)) return FALSE; 00733 module = module_find_by_addr(pcs, (DWORD)BaseOfDll, DMT_UNKNOWN); 00734 if (!module) return FALSE; 00735 return module_remove(pcs, module); 00736 } 00737 00738 /****************************************************************** 00739 * SymEnumerateModules (DBGHELP.@) 00740 * 00741 */ 00742 struct enum_modW64_32 00743 { 00744 PSYM_ENUMMODULES_CALLBACK cb; 00745 PVOID user; 00746 char module[MAX_PATH]; 00747 }; 00748 00749 static BOOL CALLBACK enum_modW64_32(PCWSTR name, DWORD64 base, PVOID user) 00750 { 00751 struct enum_modW64_32* x = user; 00752 00753 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 00754 return x->cb(x->module, (DWORD)base, x->user); 00755 } 00756 00757 BOOL WINAPI SymEnumerateModules(HANDLE hProcess, 00758 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, 00759 PVOID UserContext) 00760 { 00761 struct enum_modW64_32 x; 00762 00763 x.cb = EnumModulesCallback; 00764 x.user = UserContext; 00765 00766 return SymEnumerateModulesW64(hProcess, enum_modW64_32, &x); 00767 } 00768 00769 /****************************************************************** 00770 * SymEnumerateModules64 (DBGHELP.@) 00771 * 00772 */ 00773 struct enum_modW64_64 00774 { 00775 PSYM_ENUMMODULES_CALLBACK64 cb; 00776 PVOID user; 00777 char module[MAX_PATH]; 00778 }; 00779 00780 static BOOL CALLBACK enum_modW64_64(PCWSTR name, DWORD64 base, PVOID user) 00781 { 00782 struct enum_modW64_64* x = user; 00783 00784 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 00785 return x->cb(x->module, base, x->user); 00786 } 00787 00788 BOOL WINAPI SymEnumerateModules64(HANDLE hProcess, 00789 PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, 00790 PVOID UserContext) 00791 { 00792 struct enum_modW64_64 x; 00793 00794 x.cb = EnumModulesCallback; 00795 x.user = UserContext; 00796 00797 return SymEnumerateModulesW64(hProcess, enum_modW64_64, &x); 00798 } 00799 00800 /****************************************************************** 00801 * SymEnumerateModulesW64 (DBGHELP.@) 00802 * 00803 */ 00804 BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess, 00805 PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback, 00806 PVOID UserContext) 00807 { 00808 struct process* pcs = process_find_by_handle(hProcess); 00809 struct module* module; 00810 00811 if (!pcs) return FALSE; 00812 00813 for (module = pcs->lmodules; module; module = module->next) 00814 { 00815 if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) && 00816 (module->type == DMT_ELF || module->type == DMT_MACHO)) 00817 continue; 00818 if (!EnumModulesCallback(module->module.ModuleName, 00819 module->module.BaseOfImage, UserContext)) 00820 break; 00821 } 00822 return TRUE; 00823 } 00824 00825 /****************************************************************** 00826 * EnumerateLoadedModules64 (DBGHELP.@) 00827 * 00828 */ 00829 struct enum_load_modW64_64 00830 { 00831 PENUMLOADED_MODULES_CALLBACK64 cb; 00832 PVOID user; 00833 char module[MAX_PATH]; 00834 }; 00835 00836 static BOOL CALLBACK enum_load_modW64_64(PCWSTR name, DWORD64 base, ULONG size, 00837 PVOID user) 00838 { 00839 struct enum_load_modW64_64* x = user; 00840 00841 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 00842 return x->cb(x->module, base, size, x->user); 00843 } 00844 00845 BOOL WINAPI EnumerateLoadedModules64(HANDLE hProcess, 00846 PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, 00847 PVOID UserContext) 00848 { 00849 struct enum_load_modW64_64 x; 00850 00851 x.cb = EnumLoadedModulesCallback; 00852 x.user = UserContext; 00853 00854 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_64, &x); 00855 } 00856 00857 /****************************************************************** 00858 * EnumerateLoadedModules (DBGHELP.@) 00859 * 00860 */ 00861 struct enum_load_modW64_32 00862 { 00863 PENUMLOADED_MODULES_CALLBACK cb; 00864 PVOID user; 00865 char module[MAX_PATH]; 00866 }; 00867 00868 static BOOL CALLBACK enum_load_modW64_32(PCWSTR name, DWORD64 base, ULONG size, 00869 PVOID user) 00870 { 00871 struct enum_load_modW64_32* x = user; 00872 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 00873 return x->cb(x->module, (DWORD)base, size, x->user); 00874 } 00875 00876 BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess, 00877 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback, 00878 PVOID UserContext) 00879 { 00880 struct enum_load_modW64_32 x; 00881 00882 x.cb = EnumLoadedModulesCallback; 00883 x.user = UserContext; 00884 00885 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_32, &x); 00886 } 00887 00888 /****************************************************************** 00889 * EnumerateLoadedModulesW64 (DBGHELP.@) 00890 * 00891 */ 00892 BOOL WINAPI EnumerateLoadedModulesW64(HANDLE hProcess, 00893 PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, 00894 PVOID UserContext) 00895 { 00896 HMODULE* hMods; 00897 WCHAR baseW[256], modW[256]; 00898 DWORD i, sz; 00899 MODULEINFO mi; 00900 00901 hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0])); 00902 if (!hMods) return FALSE; 00903 00904 if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz)) 00905 { 00906 /* hProcess should also be a valid process handle !! */ 00907 FIXME("If this happens, bump the number in mod\n"); 00908 HeapFree(GetProcessHeap(), 0, hMods); 00909 return FALSE; 00910 } 00911 sz /= sizeof(HMODULE); 00912 for (i = 0; i < sz; i++) 00913 { 00914 if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) || 00915 !GetModuleBaseNameW(hProcess, hMods[i], baseW, sizeof(baseW) / sizeof(WCHAR))) 00916 continue; 00917 module_fill_module(baseW, modW, sizeof(modW) / sizeof(CHAR)); 00918 EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage, 00919 UserContext); 00920 } 00921 HeapFree(GetProcessHeap(), 0, hMods); 00922 00923 return sz != 0 && i == sz; 00924 } 00925 00926 /****************************************************************** 00927 * SymGetModuleInfo (DBGHELP.@) 00928 * 00929 */ 00930 BOOL WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 00931 PIMAGEHLP_MODULE ModuleInfo) 00932 { 00933 IMAGEHLP_MODULE mi; 00934 IMAGEHLP_MODULEW64 miw64; 00935 00936 if (sizeof(mi) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n"); 00937 00938 miw64.SizeOfStruct = sizeof(miw64); 00939 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 00940 00941 mi.SizeOfStruct = miw64.SizeOfStruct; 00942 mi.BaseOfImage = miw64.BaseOfImage; 00943 mi.ImageSize = miw64.ImageSize; 00944 mi.TimeDateStamp = miw64.TimeDateStamp; 00945 mi.CheckSum = miw64.CheckSum; 00946 mi.NumSyms = miw64.NumSyms; 00947 mi.SymType = miw64.SymType; 00948 WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1, 00949 mi.ModuleName, sizeof(mi.ModuleName), NULL, NULL); 00950 WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1, 00951 mi.ImageName, sizeof(mi.ImageName), NULL, NULL); 00952 WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1, 00953 mi.LoadedImageName, sizeof(mi.LoadedImageName), NULL, NULL); 00954 00955 memcpy(ModuleInfo, &mi, ModuleInfo->SizeOfStruct); 00956 00957 return TRUE; 00958 } 00959 00960 /****************************************************************** 00961 * SymGetModuleInfoW (DBGHELP.@) 00962 * 00963 */ 00964 BOOL WINAPI SymGetModuleInfoW(HANDLE hProcess, DWORD dwAddr, 00965 PIMAGEHLP_MODULEW ModuleInfo) 00966 { 00967 IMAGEHLP_MODULEW64 miw64; 00968 IMAGEHLP_MODULEW miw; 00969 00970 if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n"); 00971 00972 miw64.SizeOfStruct = sizeof(miw64); 00973 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 00974 00975 miw.SizeOfStruct = miw64.SizeOfStruct; 00976 miw.BaseOfImage = miw64.BaseOfImage; 00977 miw.ImageSize = miw64.ImageSize; 00978 miw.TimeDateStamp = miw64.TimeDateStamp; 00979 miw.CheckSum = miw64.CheckSum; 00980 miw.NumSyms = miw64.NumSyms; 00981 miw.SymType = miw64.SymType; 00982 strcpyW(miw.ModuleName, miw64.ModuleName); 00983 strcpyW(miw.ImageName, miw64.ImageName); 00984 strcpyW(miw.LoadedImageName, miw64.LoadedImageName); 00985 memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct); 00986 00987 return TRUE; 00988 } 00989 00990 /****************************************************************** 00991 * SymGetModuleInfo64 (DBGHELP.@) 00992 * 00993 */ 00994 BOOL WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr, 00995 PIMAGEHLP_MODULE64 ModuleInfo) 00996 { 00997 IMAGEHLP_MODULE64 mi64; 00998 IMAGEHLP_MODULEW64 miw64; 00999 01000 if (sizeof(mi64) < ModuleInfo->SizeOfStruct) 01001 { 01002 SetLastError(ERROR_MOD_NOT_FOUND); /* NOTE: native returns this error */ 01003 WARN("Wrong size %u\n", ModuleInfo->SizeOfStruct); 01004 return FALSE; 01005 } 01006 01007 miw64.SizeOfStruct = sizeof(miw64); 01008 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 01009 01010 mi64.SizeOfStruct = miw64.SizeOfStruct; 01011 mi64.BaseOfImage = miw64.BaseOfImage; 01012 mi64.ImageSize = miw64.ImageSize; 01013 mi64.TimeDateStamp = miw64.TimeDateStamp; 01014 mi64.CheckSum = miw64.CheckSum; 01015 mi64.NumSyms = miw64.NumSyms; 01016 mi64.SymType = miw64.SymType; 01017 WideCharToMultiByte(CP_ACP, 0, miw64.ModuleName, -1, 01018 mi64.ModuleName, sizeof(mi64.ModuleName), NULL, NULL); 01019 WideCharToMultiByte(CP_ACP, 0, miw64.ImageName, -1, 01020 mi64.ImageName, sizeof(mi64.ImageName), NULL, NULL); 01021 WideCharToMultiByte(CP_ACP, 0, miw64.LoadedImageName, -1, 01022 mi64.LoadedImageName, sizeof(mi64.LoadedImageName), NULL, NULL); 01023 WideCharToMultiByte(CP_ACP, 0, miw64.LoadedPdbName, -1, 01024 mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName), NULL, NULL); 01025 01026 mi64.CVSig = miw64.CVSig; 01027 WideCharToMultiByte(CP_ACP, 0, miw64.CVData, -1, 01028 mi64.CVData, sizeof(mi64.CVData), NULL, NULL); 01029 mi64.PdbSig = miw64.PdbSig; 01030 mi64.PdbSig70 = miw64.PdbSig70; 01031 mi64.PdbAge = miw64.PdbAge; 01032 mi64.PdbUnmatched = miw64.PdbUnmatched; 01033 mi64.DbgUnmatched = miw64.DbgUnmatched; 01034 mi64.LineNumbers = miw64.LineNumbers; 01035 mi64.GlobalSymbols = miw64.GlobalSymbols; 01036 mi64.TypeInfo = miw64.TypeInfo; 01037 mi64.SourceIndexed = miw64.SourceIndexed; 01038 mi64.Publics = miw64.Publics; 01039 01040 memcpy(ModuleInfo, &mi64, ModuleInfo->SizeOfStruct); 01041 01042 return TRUE; 01043 } 01044 01045 /****************************************************************** 01046 * SymGetModuleInfoW64 (DBGHELP.@) 01047 * 01048 */ 01049 BOOL WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr, 01050 PIMAGEHLP_MODULEW64 ModuleInfo) 01051 { 01052 struct process* pcs = process_find_by_handle(hProcess); 01053 struct module* module; 01054 IMAGEHLP_MODULEW64 miw64; 01055 01056 TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo); 01057 01058 if (!pcs) return FALSE; 01059 if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE; 01060 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN); 01061 if (!module) return FALSE; 01062 01063 miw64 = module->module; 01064 01065 /* update debug information from container if any */ 01066 if (module->module.SymType == SymNone) 01067 { 01068 module = module_get_container(pcs, module); 01069 if (module && module->module.SymType != SymNone) 01070 { 01071 miw64.SymType = module->module.SymType; 01072 miw64.NumSyms = module->module.NumSyms; 01073 } 01074 } 01075 memcpy(ModuleInfo, &miw64, ModuleInfo->SizeOfStruct); 01076 return TRUE; 01077 } 01078 01079 /*********************************************************************** 01080 * SymGetModuleBase (DBGHELP.@) 01081 */ 01082 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr) 01083 { 01084 DWORD64 ret; 01085 01086 ret = SymGetModuleBase64(hProcess, dwAddr); 01087 return validate_addr64(ret) ? ret : 0; 01088 } 01089 01090 /*********************************************************************** 01091 * SymGetModuleBase64 (DBGHELP.@) 01092 */ 01093 DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) 01094 { 01095 struct process* pcs = process_find_by_handle(hProcess); 01096 struct module* module; 01097 01098 if (!pcs) return 0; 01099 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN); 01100 if (!module) return 0; 01101 return module->module.BaseOfImage; 01102 } 01103 01104 /****************************************************************** 01105 * module_reset_debug_info 01106 * Removes any debug information linked to a given module. 01107 */ 01108 void module_reset_debug_info(struct module* module) 01109 { 01110 module->sortlist_valid = TRUE; 01111 module->sorttab_size = 0; 01112 module->addr_sorttab = NULL; 01113 module->num_sorttab = module->num_symbols = 0; 01114 hash_table_destroy(&module->ht_symbols); 01115 module->ht_symbols.num_buckets = 0; 01116 module->ht_symbols.buckets = NULL; 01117 hash_table_destroy(&module->ht_types); 01118 module->ht_types.num_buckets = 0; 01119 module->ht_types.buckets = NULL; 01120 module->vtypes.num_elts = 0; 01121 hash_table_destroy(&module->ht_symbols); 01122 module->sources_used = module->sources_alloc = 0; 01123 module->sources = NULL; 01124 } 01125 01126 /****************************************************************** 01127 * SymRefreshModuleList (DBGHELP.@) 01128 */ 01129 BOOL WINAPI SymRefreshModuleList(HANDLE hProcess) 01130 { 01131 struct process* pcs; 01132 01133 TRACE("(%p)\n", hProcess); 01134 01135 if (!(pcs = process_find_by_handle(hProcess))) return FALSE; 01136 01137 return refresh_module_list(pcs); 01138 } 01139 01140 /*********************************************************************** 01141 * SymFunctionTableAccess (DBGHELP.@) 01142 */ 01143 PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase) 01144 { 01145 return SymFunctionTableAccess64(hProcess, AddrBase); 01146 } 01147 01148 /*********************************************************************** 01149 * SymFunctionTableAccess64 (DBGHELP.@) 01150 */ 01151 PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) 01152 { 01153 struct process* pcs = process_find_by_handle(hProcess); 01154 struct module* module; 01155 01156 if (!pcs || !dbghelp_current_cpu->find_runtime_function) return NULL; 01157 module = module_find_by_addr(pcs, AddrBase, DMT_UNKNOWN); 01158 if (!module) return NULL; 01159 01160 return dbghelp_current_cpu->find_runtime_function(module, AddrBase); 01161 } Generated on Fri May 25 2012 04:21:22 for ReactOS by
1.7.6.1
|