1 /* 2 * IMAGEHLP library 3 * 4 * Copyright 1998 Patrik Stridvall 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 23 #include "windef.h" 24 #include "winbase.h" 25 #include "winternl.h" 26 #include "winerror.h" 27 #include "wine/debug.h" 28 #include "wine/exception.h" 29 #include "imagehlp.h" 30 31 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); 32 33 static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount); 34 35 /*********************************************************************** 36 * BindImage (IMAGEHLP.@) 37 * 38 * NOTES 39 * See BindImageEx 40 */ 41 BOOL WINAPI BindImage( 42 PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath) 43 { 44 return BindImageEx(0, ImageName, DllPath, SymbolPath, NULL); 45 } 46 47 /*********************************************************************** 48 * BindImageEx (IMAGEHLP.@) 49 * 50 * Compute the virtual address of each function imported by a PE image 51 * 52 * PARAMS 53 * 54 * Flags [in] Bind options 55 * ImageName [in] File name of the image to be bound 56 * DllPath [in] Root of the fallback search path in case the ImageName file cannot be opened 57 * SymbolPath [in] Symbol file root search path 58 * StatusRoutine [in] Pointer to a status routine which will be called during the binding process 59 * 60 * RETURNS 61 * Success: TRUE 62 * Failure: FALSE 63 * 64 * NOTES 65 * Binding is not implemented yet, so far this function only enumerates 66 * all imported dlls/functions and returns TRUE. 67 */ 68 BOOL WINAPI BindImageEx( 69 DWORD Flags, PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath, 70 PIMAGEHLP_STATUS_ROUTINE StatusRoutine) 71 { 72 LOADED_IMAGE loaded_image; 73 const IMAGE_IMPORT_DESCRIPTOR *import_desc; 74 ULONG size; 75 76 FIXME("(%d, %s, %s, %s, %p): semi-stub\n", 77 Flags, debugstr_a(ImageName), debugstr_a(DllPath), 78 debugstr_a(SymbolPath), StatusRoutine 79 ); 80 81 if (!(MapAndLoad(ImageName, DllPath, &loaded_image, TRUE, TRUE))) return FALSE; 82 83 if (!(import_desc = RtlImageDirectoryEntryToData((HMODULE)loaded_image.MappedAddress, FALSE, 84 IMAGE_DIRECTORY_ENTRY_IMPORT, &size))) 85 { 86 UnMapAndLoad(&loaded_image); 87 return TRUE; /* No imported modules means nothing to bind, so we're done. */ 88 } 89 90 /* FIXME: Does native imagehlp support both 32-bit and 64-bit PE executables? */ 91 #ifdef _WIN64 92 if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) 93 #else 94 if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) 95 #endif 96 { 97 FIXME("Wrong architecture in PE header, unable to enumerate imports\n"); 98 UnMapAndLoad(&loaded_image); 99 return TRUE; 100 } 101 102 for (; import_desc->Name && import_desc->FirstThunk; ++import_desc) 103 { 104 IMAGE_THUNK_DATA *thunk; 105 char dll_fullname[MAX_PATH]; 106 const char *dll_name; 107 108 if (!(dll_name = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, 109 import_desc->Name, 0))) 110 { 111 UnMapAndLoad(&loaded_image); 112 SetLastError(ERROR_INVALID_ACCESS); /* FIXME */ 113 return FALSE; 114 } 115 116 if (StatusRoutine) 117 StatusRoutine(BindImportModule, ImageName, dll_name, 0, 0); 118 119 if (!SearchPathA(DllPath, dll_name, 0, sizeof(dll_fullname), dll_fullname, 0)) 120 { 121 UnMapAndLoad(&loaded_image); 122 SetLastError(ERROR_FILE_NOT_FOUND); 123 return FALSE; 124 } 125 126 if (!(thunk = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, 127 import_desc->OriginalFirstThunk ? import_desc->OriginalFirstThunk : 128 import_desc->FirstThunk, 0))) 129 { 130 ERR("Can't grab thunk data of %s, going to next imported DLL\n", dll_name); 131 continue; 132 } 133 134 for (; thunk->u1.Ordinal; ++thunk) 135 { 136 /* Ignoring ordinal imports for now */ 137 if(!IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal)) 138 { 139 IMAGE_IMPORT_BY_NAME *iibn; 140 141 if (!(iibn = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, 142 thunk->u1.AddressOfData, 0))) 143 { 144 ERR("Can't grab import by name info, skipping to next ordinal\n"); 145 continue; 146 } 147 148 if (StatusRoutine) 149 StatusRoutine(BindImportProcedure, ImageName, dll_fullname, 0, (ULONG_PTR)iibn->Name); 150 } 151 } 152 } 153 154 UnMapAndLoad(&loaded_image); 155 return TRUE; 156 } 157 158 159 /*********************************************************************** 160 * CheckSum (internal) 161 */ 162 static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD ByteCount) 163 { 164 LPWORD Ptr; 165 DWORD Sum, i; 166 167 Sum = StartValue; 168 Ptr = (LPWORD)BaseAddress; 169 for (i = ByteCount; i > 1; i -= 2) 170 { 171 Sum += *Ptr; 172 if (HIWORD(Sum) != 0) 173 Sum = LOWORD(Sum) + HIWORD(Sum); 174 Ptr++; 175 } 176 177 if (i == 1) 178 Sum += *(BYTE *)Ptr; 179 180 return (WORD)(LOWORD(Sum) + HIWORD(Sum)); 181 } 182 183 184 /*********************************************************************** 185 * CheckSumMappedFile (IMAGEHLP.@) 186 */ 187 PIMAGE_NT_HEADERS WINAPI CheckSumMappedFile( 188 LPVOID BaseAddress, DWORD FileLength, 189 LPDWORD HeaderSum, LPDWORD CheckSum) 190 { 191 IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *) BaseAddress; 192 PIMAGE_NT_HEADERS32 Header32; 193 PIMAGE_NT_HEADERS64 Header64; 194 PIMAGE_NT_HEADERS ret = NULL; 195 DWORD *ChecksumFile; 196 DWORD CalcSum; 197 DWORD HdrSum = 0; 198 199 TRACE("(%p, %d, %p, %p)\n", 200 BaseAddress, FileLength, HeaderSum, CheckSum 201 ); 202 203 CalcSum = (DWORD)CalcCheckSum(0, BaseAddress, FileLength); 204 205 __TRY 206 { 207 if (dos->e_magic != IMAGE_DOS_SIGNATURE) 208 #ifdef __REACTOS__ 209 _SEH2_LEAVE; 210 #else 211 break; 212 #endif 213 214 Header32 = (IMAGE_NT_HEADERS32 *)((char *)dos + dos->e_lfanew); 215 if (Header32->Signature != IMAGE_NT_SIGNATURE) 216 #ifdef __REACTOS__ 217 _SEH2_LEAVE; 218 #else 219 break; 220 #endif 221 222 ret = (PIMAGE_NT_HEADERS)Header32; 223 224 if (Header32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) 225 ChecksumFile = &Header32->OptionalHeader.CheckSum; 226 else if (Header32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) 227 { 228 Header64 = (IMAGE_NT_HEADERS64 *)Header32; 229 ChecksumFile = &Header64->OptionalHeader.CheckSum; 230 } 231 else 232 #ifdef __REACTOS__ 233 _SEH2_LEAVE; 234 #else 235 break; 236 #endif 237 238 HdrSum = *ChecksumFile; 239 } 240 __EXCEPT_PAGE_FAULT 241 { 242 /* nothing */ 243 } 244 __ENDTRY 245 246 /* Subtract image checksum from calculated checksum. */ 247 /* fix low word of checksum */ 248 if (LOWORD(CalcSum) >= LOWORD(HdrSum)) 249 { 250 CalcSum -= LOWORD(HdrSum); 251 } 252 else 253 { 254 CalcSum = ((LOWORD(CalcSum) - LOWORD(HdrSum)) & 0xFFFF) - 1; 255 } 256 257 /* fix high word of checksum */ 258 if (LOWORD(CalcSum) >= HIWORD(HdrSum)) 259 { 260 CalcSum -= HIWORD(HdrSum); 261 } 262 else 263 { 264 CalcSum = ((LOWORD(CalcSum) - HIWORD(HdrSum)) & 0xFFFF) - 1; 265 } 266 267 /* add file length */ 268 CalcSum += FileLength; 269 270 *CheckSum = CalcSum; 271 *HeaderSum = HdrSum; 272 273 return ret; 274 } 275 276 /*********************************************************************** 277 * MapFileAndCheckSumA (IMAGEHLP.@) 278 */ 279 DWORD WINAPI MapFileAndCheckSumA( 280 PCSTR Filename, PDWORD HeaderSum, PDWORD CheckSum) 281 { 282 HANDLE hFile; 283 HANDLE hMapping; 284 LPVOID BaseAddress; 285 DWORD FileLength; 286 287 TRACE("(%s, %p, %p): stub\n", 288 debugstr_a(Filename), HeaderSum, CheckSum 289 ); 290 291 hFile = CreateFileA(Filename, 292 GENERIC_READ, 293 FILE_SHARE_READ | FILE_SHARE_WRITE, 294 NULL, 295 OPEN_EXISTING, 296 FILE_ATTRIBUTE_NORMAL, 297 0); 298 if (hFile == INVALID_HANDLE_VALUE) 299 { 300 return CHECKSUM_OPEN_FAILURE; 301 } 302 303 hMapping = CreateFileMappingW(hFile, 304 NULL, 305 PAGE_READONLY, 306 0, 307 0, 308 NULL); 309 if (hMapping == 0) 310 { 311 CloseHandle(hFile); 312 return CHECKSUM_MAP_FAILURE; 313 } 314 315 BaseAddress = MapViewOfFile(hMapping, 316 FILE_MAP_READ, 317 0, 318 0, 319 0); 320 if (BaseAddress == 0) 321 { 322 CloseHandle(hMapping); 323 CloseHandle(hFile); 324 return CHECKSUM_MAPVIEW_FAILURE; 325 } 326 327 FileLength = GetFileSize(hFile, 328 NULL); 329 330 CheckSumMappedFile(BaseAddress, 331 FileLength, 332 HeaderSum, 333 CheckSum); 334 335 UnmapViewOfFile(BaseAddress); 336 CloseHandle(hMapping); 337 CloseHandle(hFile); 338 339 return 0; 340 } 341 342 /*********************************************************************** 343 * MapFileAndCheckSumW (IMAGEHLP.@) 344 */ 345 DWORD WINAPI MapFileAndCheckSumW( 346 PCWSTR Filename, PDWORD HeaderSum, PDWORD CheckSum) 347 { 348 HANDLE hFile; 349 HANDLE hMapping; 350 LPVOID BaseAddress; 351 DWORD FileLength; 352 353 TRACE("(%s, %p, %p): stub\n", 354 debugstr_w(Filename), HeaderSum, CheckSum 355 ); 356 357 hFile = CreateFileW(Filename, 358 GENERIC_READ, 359 FILE_SHARE_READ | FILE_SHARE_WRITE, 360 NULL, 361 OPEN_EXISTING, 362 FILE_ATTRIBUTE_NORMAL, 363 0); 364 if (hFile == INVALID_HANDLE_VALUE) 365 { 366 return CHECKSUM_OPEN_FAILURE; 367 } 368 369 hMapping = CreateFileMappingW(hFile, 370 NULL, 371 PAGE_READONLY, 372 0, 373 0, 374 NULL); 375 if (hMapping == 0) 376 { 377 CloseHandle(hFile); 378 return CHECKSUM_MAP_FAILURE; 379 } 380 381 BaseAddress = MapViewOfFile(hMapping, 382 FILE_MAP_READ, 383 0, 384 0, 385 0); 386 if (BaseAddress == 0) 387 { 388 CloseHandle(hMapping); 389 CloseHandle(hFile); 390 return CHECKSUM_MAPVIEW_FAILURE; 391 } 392 393 FileLength = GetFileSize(hFile, 394 NULL); 395 396 CheckSumMappedFile(BaseAddress, 397 FileLength, 398 HeaderSum, 399 CheckSum); 400 401 UnmapViewOfFile(BaseAddress); 402 CloseHandle(hMapping); 403 CloseHandle(hFile); 404 405 return 0; 406 } 407 408 /*********************************************************************** 409 * ReBaseImage (IMAGEHLP.@) 410 */ 411 BOOL WINAPI ReBaseImage( 412 PCSTR CurrentImageName, PCSTR SymbolPath, BOOL fReBase, 413 BOOL fRebaseSysfileOk, BOOL fGoingDown, ULONG CheckImageSize, 414 ULONG *OldImageSize, ULONG_PTR *OldImageBase, ULONG *NewImageSize, 415 ULONG_PTR *NewImageBase, ULONG TimeStamp) 416 { 417 FIXME( 418 "(%s, %s, %d, %d, %d, %d, %p, %p, %p, %p, %d): stub\n", 419 debugstr_a(CurrentImageName),debugstr_a(SymbolPath), fReBase, 420 fRebaseSysfileOk, fGoingDown, CheckImageSize, OldImageSize, 421 OldImageBase, NewImageSize, NewImageBase, TimeStamp 422 ); 423 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 424 return FALSE; 425 } 426 427 /*********************************************************************** 428 * RemovePrivateCvSymbolic (IMAGEHLP.@) 429 */ 430 BOOL WINAPI RemovePrivateCvSymbolic( 431 PCHAR DebugData, PCHAR *NewDebugData, ULONG *NewDebugSize) 432 { 433 FIXME("(%p, %p, %p): stub\n", 434 DebugData, NewDebugData, NewDebugSize 435 ); 436 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 437 return FALSE; 438 } 439 440 /*********************************************************************** 441 * RemoveRelocations (IMAGEHLP.@) 442 */ 443 VOID WINAPI RemoveRelocations(PCHAR ImageName) 444 { 445 FIXME("(%p): stub\n", ImageName); 446 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 447 } 448 449 /*********************************************************************** 450 * SplitSymbols (IMAGEHLP.@) 451 */ 452 BOOL WINAPI SplitSymbols( 453 PSTR ImageName, PCSTR SymbolsPath, 454 PSTR SymbolFilePath, ULONG Flags) 455 { 456 FIXME("(%s, %s, %s, %d): stub\n", 457 debugstr_a(ImageName), debugstr_a(SymbolsPath), 458 debugstr_a(SymbolFilePath), Flags 459 ); 460 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 461 return FALSE; 462 } 463 464 /*********************************************************************** 465 * UpdateDebugInfoFile (IMAGEHLP.@) 466 */ 467 BOOL WINAPI UpdateDebugInfoFile( 468 PCSTR ImageFileName, PCSTR SymbolPath, 469 PSTR DebugFilePath, PIMAGE_NT_HEADERS32 NtHeaders) 470 { 471 FIXME("(%s, %s, %s, %p): stub\n", 472 debugstr_a(ImageFileName), debugstr_a(SymbolPath), 473 debugstr_a(DebugFilePath), NtHeaders 474 ); 475 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 476 return FALSE; 477 } 478 479 /*********************************************************************** 480 * UpdateDebugInfoFileEx (IMAGEHLP.@) 481 */ 482 BOOL WINAPI UpdateDebugInfoFileEx( 483 PCSTR ImageFileName, PCSTR SymbolPath, PSTR DebugFilePath, 484 PIMAGE_NT_HEADERS32 NtHeaders, DWORD OldChecksum) 485 { 486 FIXME("(%s, %s, %s, %p, %d): stub\n", 487 debugstr_a(ImageFileName), debugstr_a(SymbolPath), 488 debugstr_a(DebugFilePath), NtHeaders, OldChecksum 489 ); 490 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 491 return FALSE; 492 } 493