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 "imagehlp.h" 29 30 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); 31 32 static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount); 33 34 /*********************************************************************** 35 * BindImage (IMAGEHLP.@) 36 * 37 * NOTES 38 * See BindImageEx 39 */ 40 BOOL WINAPI BindImage( 41 PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath) 42 { 43 return BindImageEx(0, ImageName, DllPath, SymbolPath, NULL); 44 } 45 46 /*********************************************************************** 47 * BindImageEx (IMAGEHLP.@) 48 * 49 * Compute the virtual address of each function imported by a PE image 50 * 51 * PARAMS 52 * 53 * Flags [in] Bind options 54 * ImageName [in] File name of the image to be bound 55 * DllPath [in] Root of the fallback search path in case the ImageName file cannot be opened 56 * SymbolPath [in] Symbol file root search path 57 * StatusRoutine [in] Pointer to a status routine which will be called during the binding process 58 * 59 * RETURNS 60 * Success: TRUE 61 * Failure: FALSE 62 * 63 * NOTES 64 * Binding is not implemented yet, so far this function only enumerates 65 * all imported dlls/functions and returns TRUE. 66 */ 67 BOOL WINAPI BindImageEx( 68 DWORD Flags, PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath, 69 PIMAGEHLP_STATUS_ROUTINE StatusRoutine) 70 { 71 LOADED_IMAGE loaded_image; 72 const IMAGE_IMPORT_DESCRIPTOR *import_desc; 73 ULONG size; 74 75 FIXME("(%d, %s, %s, %s, %p): semi-stub\n", 76 Flags, debugstr_a(ImageName), debugstr_a(DllPath), 77 debugstr_a(SymbolPath), StatusRoutine 78 ); 79 80 if (!(MapAndLoad(ImageName, DllPath, &loaded_image, TRUE, TRUE))) return FALSE; 81 82 if (!(import_desc = RtlImageDirectoryEntryToData((HMODULE)loaded_image.MappedAddress, FALSE, 83 IMAGE_DIRECTORY_ENTRY_IMPORT, &size))) 84 { 85 UnMapAndLoad(&loaded_image); 86 return TRUE; /* No imported modules means nothing to bind, so we're done. */ 87 } 88 89 /* FIXME: Does native imagehlp support both 32-bit and 64-bit PE executables? */ 90 #ifdef _WIN64 91 if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) 92 #else 93 if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) 94 #endif 95 { 96 FIXME("Wrong architecture in PE header, unable to enumerate imports\n"); 97 UnMapAndLoad(&loaded_image); 98 return TRUE; 99 } 100 101 for (; import_desc->Name && import_desc->FirstThunk; ++import_desc) 102 { 103 IMAGE_THUNK_DATA *thunk; 104 char dll_fullname[MAX_PATH]; 105 const char *dll_name; 106 107 if (!(dll_name = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, 108 import_desc->Name, 0))) 109 { 110 UnMapAndLoad(&loaded_image); 111 SetLastError(ERROR_INVALID_ACCESS); /* FIXME */ 112 return FALSE; 113 } 114 115 if (StatusRoutine) 116 StatusRoutine(BindImportModule, ImageName, dll_name, 0, 0); 117 118 if (!SearchPathA(DllPath, dll_name, 0, sizeof(dll_fullname), dll_fullname, 0)) 119 { 120 UnMapAndLoad(&loaded_image); 121 SetLastError(ERROR_FILE_NOT_FOUND); 122 return FALSE; 123 } 124 125 if (!(thunk = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, 126 import_desc->OriginalFirstThunk ? import_desc->OriginalFirstThunk : 127 import_desc->FirstThunk, 0))) 128 { 129 ERR("Can't grab thunk data of %s, going to next imported DLL\n", dll_name); 130 continue; 131 } 132 133 for (; thunk->u1.Ordinal; ++thunk) 134 { 135 /* Ignoring ordinal imports for now */ 136 if(!IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal)) 137 { 138 IMAGE_IMPORT_BY_NAME *iibn; 139 140 if (!(iibn = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress, 141 thunk->u1.AddressOfData, 0))) 142 { 143 ERR("Can't grab import by name info, skipping to next ordinal\n"); 144 continue; 145 } 146 147 if (StatusRoutine) 148 StatusRoutine(BindImportProcedure, ImageName, dll_fullname, 0, (ULONG_PTR)iibn->Name); 149 } 150 } 151 } 152 153 UnMapAndLoad(&loaded_image); 154 return TRUE; 155 } 156 157 158 /*********************************************************************** 159 * CheckSum (internal) 160 */ 161 static WORD CalcCheckSum( 162 DWORD StartValue, LPVOID BaseAddress, DWORD WordCount) 163 { 164 LPWORD Ptr; 165 DWORD Sum; 166 DWORD i; 167 168 Sum = StartValue; 169 Ptr = (LPWORD)BaseAddress; 170 for (i = 0; i < WordCount; i++) 171 { 172 Sum += *Ptr; 173 if (HIWORD(Sum) != 0) 174 { 175 Sum = LOWORD(Sum) + HIWORD(Sum); 176 } 177 Ptr++; 178 } 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 PIMAGE_NT_HEADERS header; 192 DWORD CalcSum; 193 DWORD HdrSum; 194 195 TRACE("(%p, %d, %p, %p)\n", BaseAddress, FileLength, HeaderSum, CheckSum); 196 197 CalcSum = CalcCheckSum(0, BaseAddress, (FileLength + 1) / sizeof(WORD)); 198 header = RtlImageNtHeader(BaseAddress); 199 200 if (!header) 201 return NULL; 202 203 *HeaderSum = HdrSum = header->OptionalHeader.CheckSum; 204 205 /* Subtract image checksum from calculated checksum. */ 206 /* fix low word of checksum */ 207 if (LOWORD(CalcSum) >= LOWORD(HdrSum)) 208 { 209 CalcSum -= LOWORD(HdrSum); 210 } 211 else 212 { 213 CalcSum = ((LOWORD(CalcSum) - LOWORD(HdrSum)) & 0xFFFF) - 1; 214 } 215 216 /* fix high word of checksum */ 217 if (LOWORD(CalcSum) >= HIWORD(HdrSum)) 218 { 219 CalcSum -= HIWORD(HdrSum); 220 } 221 else 222 { 223 CalcSum = ((LOWORD(CalcSum) - HIWORD(HdrSum)) & 0xFFFF) - 1; 224 } 225 226 /* add file length */ 227 CalcSum += FileLength; 228 229 *CheckSum = CalcSum; 230 231 return header; 232 } 233 234 /*********************************************************************** 235 * MapFileAndCheckSumA (IMAGEHLP.@) 236 */ 237 DWORD WINAPI MapFileAndCheckSumA( 238 PCSTR Filename, PDWORD HeaderSum, PDWORD CheckSum) 239 { 240 HANDLE hFile; 241 HANDLE hMapping; 242 LPVOID BaseAddress; 243 DWORD FileLength; 244 245 TRACE("(%s, %p, %p): stub\n", 246 debugstr_a(Filename), HeaderSum, CheckSum 247 ); 248 249 hFile = CreateFileA(Filename, 250 GENERIC_READ, 251 FILE_SHARE_READ | FILE_SHARE_WRITE, 252 NULL, 253 OPEN_EXISTING, 254 FILE_ATTRIBUTE_NORMAL, 255 0); 256 if (hFile == INVALID_HANDLE_VALUE) 257 { 258 return CHECKSUM_OPEN_FAILURE; 259 } 260 261 hMapping = CreateFileMappingW(hFile, 262 NULL, 263 PAGE_READONLY, 264 0, 265 0, 266 NULL); 267 if (hMapping == 0) 268 { 269 CloseHandle(hFile); 270 return CHECKSUM_MAP_FAILURE; 271 } 272 273 BaseAddress = MapViewOfFile(hMapping, 274 FILE_MAP_READ, 275 0, 276 0, 277 0); 278 if (BaseAddress == 0) 279 { 280 CloseHandle(hMapping); 281 CloseHandle(hFile); 282 return CHECKSUM_MAPVIEW_FAILURE; 283 } 284 285 FileLength = GetFileSize(hFile, 286 NULL); 287 288 CheckSumMappedFile(BaseAddress, 289 FileLength, 290 HeaderSum, 291 CheckSum); 292 293 UnmapViewOfFile(BaseAddress); 294 CloseHandle(hMapping); 295 CloseHandle(hFile); 296 297 return 0; 298 } 299 300 /*********************************************************************** 301 * MapFileAndCheckSumW (IMAGEHLP.@) 302 */ 303 DWORD WINAPI MapFileAndCheckSumW( 304 PCWSTR Filename, PDWORD HeaderSum, PDWORD CheckSum) 305 { 306 HANDLE hFile; 307 HANDLE hMapping; 308 LPVOID BaseAddress; 309 DWORD FileLength; 310 311 TRACE("(%s, %p, %p): stub\n", 312 debugstr_w(Filename), HeaderSum, CheckSum 313 ); 314 315 hFile = CreateFileW(Filename, 316 GENERIC_READ, 317 FILE_SHARE_READ | FILE_SHARE_WRITE, 318 NULL, 319 OPEN_EXISTING, 320 FILE_ATTRIBUTE_NORMAL, 321 0); 322 if (hFile == INVALID_HANDLE_VALUE) 323 { 324 return CHECKSUM_OPEN_FAILURE; 325 } 326 327 hMapping = CreateFileMappingW(hFile, 328 NULL, 329 PAGE_READONLY, 330 0, 331 0, 332 NULL); 333 if (hMapping == 0) 334 { 335 CloseHandle(hFile); 336 return CHECKSUM_MAP_FAILURE; 337 } 338 339 BaseAddress = MapViewOfFile(hMapping, 340 FILE_MAP_READ, 341 0, 342 0, 343 0); 344 if (BaseAddress == 0) 345 { 346 CloseHandle(hMapping); 347 CloseHandle(hFile); 348 return CHECKSUM_MAPVIEW_FAILURE; 349 } 350 351 FileLength = GetFileSize(hFile, 352 NULL); 353 354 CheckSumMappedFile(BaseAddress, 355 FileLength, 356 HeaderSum, 357 CheckSum); 358 359 UnmapViewOfFile(BaseAddress); 360 CloseHandle(hMapping); 361 CloseHandle(hFile); 362 363 return 0; 364 } 365 366 /*********************************************************************** 367 * ReBaseImage (IMAGEHLP.@) 368 */ 369 BOOL WINAPI ReBaseImage( 370 PCSTR CurrentImageName, PCSTR SymbolPath, BOOL fReBase, 371 BOOL fRebaseSysfileOk, BOOL fGoingDown, ULONG CheckImageSize, 372 ULONG *OldImageSize, ULONG_PTR *OldImageBase, ULONG *NewImageSize, 373 ULONG_PTR *NewImageBase, ULONG TimeStamp) 374 { 375 FIXME( 376 "(%s, %s, %d, %d, %d, %d, %p, %p, %p, %p, %d): stub\n", 377 debugstr_a(CurrentImageName),debugstr_a(SymbolPath), fReBase, 378 fRebaseSysfileOk, fGoingDown, CheckImageSize, OldImageSize, 379 OldImageBase, NewImageSize, NewImageBase, TimeStamp 380 ); 381 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 382 return FALSE; 383 } 384 385 /*********************************************************************** 386 * RemovePrivateCvSymbolic (IMAGEHLP.@) 387 */ 388 BOOL WINAPI RemovePrivateCvSymbolic( 389 PCHAR DebugData, PCHAR *NewDebugData, ULONG *NewDebugSize) 390 { 391 FIXME("(%p, %p, %p): stub\n", 392 DebugData, NewDebugData, NewDebugSize 393 ); 394 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 395 return FALSE; 396 } 397 398 /*********************************************************************** 399 * RemoveRelocations (IMAGEHLP.@) 400 */ 401 VOID WINAPI RemoveRelocations(PCHAR ImageName) 402 { 403 FIXME("(%p): stub\n", ImageName); 404 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 405 } 406 407 /*********************************************************************** 408 * SplitSymbols (IMAGEHLP.@) 409 */ 410 BOOL WINAPI SplitSymbols( 411 PSTR ImageName, PCSTR SymbolsPath, 412 PSTR SymbolFilePath, ULONG Flags) 413 { 414 FIXME("(%s, %s, %s, %d): stub\n", 415 debugstr_a(ImageName), debugstr_a(SymbolsPath), 416 debugstr_a(SymbolFilePath), Flags 417 ); 418 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 419 return FALSE; 420 } 421 422 /*********************************************************************** 423 * UpdateDebugInfoFile (IMAGEHLP.@) 424 */ 425 BOOL WINAPI UpdateDebugInfoFile( 426 PCSTR ImageFileName, PCSTR SymbolPath, 427 PSTR DebugFilePath, PIMAGE_NT_HEADERS32 NtHeaders) 428 { 429 FIXME("(%s, %s, %s, %p): stub\n", 430 debugstr_a(ImageFileName), debugstr_a(SymbolPath), 431 debugstr_a(DebugFilePath), NtHeaders 432 ); 433 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 434 return FALSE; 435 } 436 437 /*********************************************************************** 438 * UpdateDebugInfoFileEx (IMAGEHLP.@) 439 */ 440 BOOL WINAPI UpdateDebugInfoFileEx( 441 PCSTR ImageFileName, PCSTR SymbolPath, PSTR DebugFilePath, 442 PIMAGE_NT_HEADERS32 NtHeaders, DWORD OldChecksum) 443 { 444 FIXME("(%s, %s, %s, %p, %d): stub\n", 445 debugstr_a(ImageFileName), debugstr_a(SymbolPath), 446 debugstr_a(DebugFilePath), NtHeaders, OldChecksum 447 ); 448 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 449 return FALSE; 450 } 451