Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2225 lines
64 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Image information.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #include <common.ver>
  10. #define DBG_MOD_LIST 0
  11. #define DBG_IMAGE_MAP 0
  12. #define HAL_MODULE_NAME "hal"
  13. #define KDHWEXT_MODULE_NAME "kdcom"
  14. // User-mode minidump can be created with data segments
  15. // embedded in the dump. If that's the case, don't map
  16. // such sections.
  17. #define IS_MINI_DATA_SECTION(SecHeader) \
  18. (IS_USER_MINI_DUMP(m_Process->m_Target) && \
  19. ((SecHeader)->Characteristics & IMAGE_SCN_MEM_WRITE) && \
  20. ((SecHeader)->Characteristics & IMAGE_SCN_MEM_READ) && \
  21. (((SecHeader)->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) || \
  22. ((SecHeader)->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)))
  23. static char s_Blanks16[] = " ";
  24. PCSTR g_VerStrings[] =
  25. {
  26. "CompanyName",
  27. "ProductName",
  28. "InternalName",
  29. "OriginalFilename",
  30. "ProductVersion",
  31. "FileVersion",
  32. "PrivateBuild",
  33. "SpecialBuild",
  34. "FileDescription",
  35. "LegalCopyright",
  36. "LegalTrademarks",
  37. "Comments",
  38. };
  39. PCSTR g_KernelAliasList[] =
  40. {
  41. "ntoskrnl.exe",
  42. "ntkrnlpa.exe",
  43. "ntkrnlmp.exe",
  44. "ntkrpamp.exe"
  45. };
  46. PCSTR g_HalAliasList[] =
  47. {
  48. "halaacpi.dll",
  49. "halacpi.dll",
  50. "halapic.dll",
  51. "halmacpi.dll",
  52. "halmps.dll",
  53. "hal.dll",
  54. "hal486c.dll",
  55. "halborg.dll",
  56. "halsp.dll"
  57. };
  58. PCSTR g_KdAliasList[] =
  59. {
  60. "kdcom.dll",
  61. "kd1394.dll"
  62. };
  63. MODULE_ALIAS_LIST g_AliasLists[] =
  64. {
  65. DIMA(g_KernelAliasList), g_KernelAliasList, KERNEL_MODULE_NAME,
  66. DIMA(g_HalAliasList), g_HalAliasList, HAL_MODULE_NAME,
  67. DIMA(g_KdAliasList), g_KdAliasList, KDHWEXT_MODULE_NAME,
  68. };
  69. #define MAX_ALIAS_COUNT DIMA(g_HalAliasList)
  70. MODULE_ALIAS_LIST*
  71. FindModuleAliasList(PCSTR ImageName,
  72. PBOOL NameInList)
  73. {
  74. MODULE_ALIAS_LIST* List = g_AliasLists;
  75. ULONG ListIdx, AliasIdx;
  76. // Currently alias lists are always looked up by
  77. // scanning the list for the given name. If a hit
  78. // is found, it's always in the list. In the future
  79. // we may allow list searches by artificial names.
  80. if (NameInList)
  81. {
  82. *NameInList = TRUE;
  83. }
  84. for (ListIdx = 0; ListIdx < MODALIAS_COUNT; ListIdx++)
  85. {
  86. DBG_ASSERT(List->Length <= MAX_ALIAS_COUNT);
  87. for (AliasIdx = 0; AliasIdx < List->Length; AliasIdx++)
  88. {
  89. if (!_strcmpi(ImageName, List->Aliases[AliasIdx]))
  90. {
  91. return List;
  92. }
  93. }
  94. List++;
  95. }
  96. return NULL;
  97. }
  98. //----------------------------------------------------------------------------
  99. //
  100. // ImageInfo.
  101. //
  102. //----------------------------------------------------------------------------
  103. ImageInfo::ImageInfo(ProcessInfo* Process,
  104. PSTR ImagePath, ULONG64 Base, BOOL Link)
  105. {
  106. m_Process = Process;
  107. // We need some information for the image immediately
  108. // as it's used when inserting the image into the process' list.
  109. m_BaseOfImage = Base;
  110. if (ImagePath)
  111. {
  112. CopyString(m_ImagePath, ImagePath, DIMA(m_ImagePath));
  113. }
  114. else
  115. {
  116. m_ImagePath[0] = 0;
  117. }
  118. m_Next = NULL;
  119. m_Linked = FALSE;
  120. m_Unloaded = FALSE;
  121. m_FileIsDemandMapped = FALSE;
  122. m_MapAlreadyFailed = FALSE;
  123. m_CorImage = FALSE;
  124. m_UserMode = IS_USER_TARGET(m_Process->m_Target) ? TRUE : FALSE;
  125. m_File = NULL;
  126. m_SizeOfImage = 0;
  127. m_CheckSum = 0;
  128. m_TimeDateStamp = 0;
  129. m_SymState = ISS_UNKNOWN;
  130. m_ModuleName[0] = 0;
  131. m_OriginalModuleName[0] = 0;
  132. m_MappedImagePath[0] = 0;
  133. m_MappedImageBase = NULL;
  134. m_MemMap = NULL;
  135. m_TlsIndex = 0xffffffff;
  136. m_MachineType = IMAGE_FILE_MACHINE_UNKNOWN;
  137. if (m_Process && Link)
  138. {
  139. m_Process->InsertImage(this);
  140. }
  141. }
  142. ImageInfo::~ImageInfo(void)
  143. {
  144. #if DBG_MOD_LIST
  145. dprintf("DelImage:\n"
  146. " ImagePath %s\n"
  147. " BaseOfImage %I64x\n"
  148. " SizeOfImage %x\n",
  149. m_ImagePath,
  150. m_BaseOfImage,
  151. m_SizeOfImage);
  152. #endif
  153. DeleteResources(TRUE);
  154. if (m_Process && m_Linked)
  155. {
  156. // Save the process that was linked with for later use.
  157. ProcessInfo* Linked = m_Process;
  158. // Unlink so that the process's module list no longer
  159. // refers to this image.
  160. m_Process->RemoveImage(this);
  161. // Notify with the saved process in order to mark any resulting
  162. // defered breakpoints due to this mod unload
  163. NotifyChangeSymbolState(DEBUG_CSS_UNLOADS, m_BaseOfImage, Linked);
  164. }
  165. }
  166. void
  167. ImageInfo::DeleteResources(BOOL FullDelete)
  168. {
  169. if (m_Process)
  170. {
  171. SymUnloadModule64(m_Process->m_SymHandle, m_BaseOfImage);
  172. }
  173. // Unmap the memory for this image.
  174. UnloadExecutableImageMemory();
  175. // The mapped image path can be set by demand-mapping
  176. // of images from partial symbol loads so force it
  177. // to be zeroed always.
  178. m_MappedImagePath[0] = 0;
  179. ClearStoredTypes(m_BaseOfImage);
  180. g_GenTypes.DeleteByImage(m_BaseOfImage);
  181. if (m_File && (m_FileIsDemandMapped || FullDelete))
  182. {
  183. CloseHandle(m_File);
  184. m_File = NULL;
  185. m_FileIsDemandMapped = FALSE;
  186. }
  187. g_LastDump.AvoidUsingImage(this);
  188. g_LastEvalResult.AvoidUsingImage(this);
  189. if (g_ScopeBuffer.CheckedForThis &&
  190. g_ScopeBuffer.ThisData.m_Image == this)
  191. {
  192. g_ScopeBuffer.CheckedForThis = FALSE;
  193. ZeroMemory(&g_ScopeBuffer.ThisData,
  194. sizeof(g_ScopeBuffer.ThisData));
  195. }
  196. }
  197. BOOL
  198. ImageInfo::MapImageRegion(MappedMemoryMap* MemMap,
  199. PVOID FileMapping,
  200. ULONG Rva, ULONG Size, ULONG RawDataOffset,
  201. BOOL AllowOverlap)
  202. {
  203. HRESULT Status;
  204. // Mark the region with the image structure to identify the
  205. // region as an image area.
  206. if ((Status = MemMap->AddRegion(m_BaseOfImage + Rva, Size,
  207. (PUCHAR)FileMapping + RawDataOffset,
  208. this, AllowOverlap)) != S_OK)
  209. {
  210. ErrOut("Unable to map %s section at %s, %s\n",
  211. m_ImagePath,
  212. FormatAddr64(m_BaseOfImage + Rva),
  213. FormatStatusCode(Status));
  214. // Conflicting region data is not a critical failure
  215. // unless the incomplete information flag is set.
  216. if (Status != HR_REGION_CONFLICT ||
  217. (g_EngOptions & DEBUG_ENGOPT_FAIL_INCOMPLETE_INFORMATION))
  218. {
  219. UnloadExecutableImageMemory();
  220. return FALSE;
  221. }
  222. }
  223. #if DBG_IMAGE_MAP_REGIONS
  224. dprintf("Map %s: %s to %s\n",
  225. m_ImagePath,
  226. FormatAddr64(m_BaseOfImage + Rva),
  227. FormatAddr64(m_BaseOfImage + Rva + Size - 1));
  228. #endif
  229. return TRUE;
  230. }
  231. BOOL
  232. ImageInfo::LoadExecutableImageMemory(MappedMemoryMap* MemMap,
  233. BOOL Verbose)
  234. {
  235. PVOID FileMapping;
  236. if (m_MappedImageBase)
  237. {
  238. // Memory is already mapped.
  239. return TRUE;
  240. }
  241. if (m_MapAlreadyFailed)
  242. {
  243. // We've already tried to map this image and
  244. // failed, so just quit right away. This prevents
  245. // tons of duplicate failure messages and wasted time.
  246. // A reload will discard this ImageInfo and allow
  247. // a new attempt, so it doesn't prevent the user
  248. // from retrying with different parameters later.
  249. return FALSE;
  250. }
  251. if (m_FileIsDemandMapped)
  252. {
  253. // This image has already been partially mapped
  254. // so we can't do a full mapping. We could actually
  255. // make this work if necessary but there are no
  256. // cases where this is interesting right now.
  257. ErrOut("Can't fully map a partially mapped image\n");
  258. return FALSE;
  259. }
  260. DBG_ASSERT(m_File == NULL);
  261. FileMapping = FindImageFile(m_Process,
  262. m_ImagePath,
  263. m_SizeOfImage,
  264. m_CheckSum,
  265. m_TimeDateStamp,
  266. &m_File,
  267. m_MappedImagePath);
  268. if (FileMapping == NULL)
  269. {
  270. if (Verbose)
  271. {
  272. ErrOut("Unable to load image %s\n", m_ImagePath);
  273. }
  274. m_MapAlreadyFailed = TRUE;
  275. return FALSE;
  276. }
  277. PIMAGE_NT_HEADERS Header = ImageNtHeader(FileMapping);
  278. // Header was already validated in MapImageFile.
  279. DBG_ASSERT(Header != NULL);
  280. // Map the header so we have it later.
  281. // Mark it with the image structure that this mapping is for.
  282. if (MemMap->AddRegion(m_BaseOfImage,
  283. Header->OptionalHeader.SizeOfHeaders,
  284. FileMapping, this, FALSE) != S_OK)
  285. {
  286. UnmapViewOfFile(FileMapping);
  287. if (m_File != NULL)
  288. {
  289. CloseHandle(m_File);
  290. m_File = NULL;
  291. }
  292. m_MappedImagePath[0] = 0;
  293. m_MapAlreadyFailed = TRUE;
  294. ErrOut("Unable to map image header memory for %s\n",
  295. m_ImagePath);
  296. return FALSE;
  297. }
  298. // Mark the image as having some mapped memory.
  299. m_MappedImageBase = FileMapping;
  300. m_MemMap = MemMap;
  301. PIMAGE_DATA_DIRECTORY DebugDataDir;
  302. IMAGE_DEBUG_DIRECTORY UNALIGNED * DebugDir = NULL;
  303. // Due to a linker bug, some images have debug data that is not
  304. // included as part of a section. Scan the debug data directory
  305. // and map anything that isn't already mapped.
  306. switch(Header->OptionalHeader.Magic)
  307. {
  308. case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
  309. DebugDataDir = &((PIMAGE_NT_HEADERS32)Header)->OptionalHeader.
  310. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  311. break;
  312. case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
  313. DebugDataDir = &((PIMAGE_NT_HEADERS64)Header)->OptionalHeader.
  314. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
  315. break;
  316. default:
  317. DebugDataDir = NULL;
  318. break;
  319. }
  320. //
  321. // Map all the sections in the image at their
  322. // appropriate offsets from the base address.
  323. //
  324. ULONG i;
  325. #if DBG_IMAGE_MAP
  326. dprintf("Map %s: base %s, size %x, %d sections, mapping %p\n",
  327. m_ImagePath, FormatAddr64(m_BaseOfImage),
  328. m_SizeOfImage, Header->FileHeader.NumberOfSections,
  329. FileMapping);
  330. #endif
  331. PIMAGE_SECTION_HEADER SecHeader = IMAGE_FIRST_SECTION(Header);
  332. for (i = 0; i < Header->FileHeader.NumberOfSections; i++)
  333. {
  334. BOOL AllowOverlap = FALSE;
  335. #if DBG_IMAGE_MAP
  336. dprintf(" %2d: %8.8s v %08x s %08x p %08x char %X\n", i,
  337. SecHeader->Name, SecHeader->VirtualAddress,
  338. SecHeader->SizeOfRawData, SecHeader->PointerToRawData,
  339. SecHeader->Characteristics);
  340. #endif
  341. if (SecHeader->SizeOfRawData == 0)
  342. {
  343. // Probably a BSS section that describes
  344. // a zero-filled data region and so is not
  345. // present in the executable. This should really
  346. // map to the appropriate page full of zeroes but
  347. // for now just ignore it.
  348. SecHeader++;
  349. continue;
  350. }
  351. if (IS_MINI_DATA_SECTION(SecHeader))
  352. {
  353. // Don't map any data sections as their content
  354. // may or may not be correct. Rather than presenting
  355. // data which may be wrong just leave it out.
  356. SecHeader++;
  357. continue;
  358. }
  359. if (DebugDataDir != NULL &&
  360. DebugDataDir->VirtualAddress >= SecHeader->VirtualAddress &&
  361. DebugDataDir->VirtualAddress < SecHeader->VirtualAddress +
  362. SecHeader->SizeOfRawData)
  363. {
  364. #if DBG_IMAGE_MAP
  365. dprintf(" DebugDataDir found in sec %d at %X (%X)\n",
  366. i, DebugDataDir->VirtualAddress,
  367. DebugDataDir->VirtualAddress - SecHeader->VirtualAddress);
  368. #endif
  369. DebugDir = (PIMAGE_DEBUG_DIRECTORY)
  370. ((PUCHAR)FileMapping + (DebugDataDir->VirtualAddress -
  371. SecHeader->VirtualAddress +
  372. SecHeader->PointerToRawData));
  373. }
  374. // As a sanity check make sure that the mapped region will
  375. // fall within the overall image bounds.
  376. if (SecHeader->VirtualAddress >= m_SizeOfImage ||
  377. SecHeader->VirtualAddress + SecHeader->SizeOfRawData >
  378. m_SizeOfImage)
  379. {
  380. WarnOut("WARNING: Image %s section %d extends "
  381. "outside of image bounds\n",
  382. m_ImagePath, i);
  383. }
  384. if (!MapImageRegion(MemMap, FileMapping,
  385. SecHeader->VirtualAddress,
  386. SecHeader->SizeOfRawData,
  387. SecHeader->PointerToRawData,
  388. AllowOverlap))
  389. {
  390. m_MapAlreadyFailed = TRUE;
  391. return FALSE;
  392. }
  393. SecHeader++;
  394. }
  395. if (DebugDir != NULL)
  396. {
  397. i = DebugDataDir->Size / sizeof(*DebugDir);
  398. #if DBG_IMAGE_MAP
  399. dprintf(" %d debug dirs\n", i);
  400. #endif
  401. while (i-- > 0)
  402. {
  403. #if DBG_IMAGE_MAP
  404. dprintf(" Dir %d at %p\n", i, DebugDir);
  405. #endif
  406. // If this debug directory's data is past the size
  407. // of the image it's a good indicator of the problem.
  408. if (DebugDir->AddressOfRawData != 0 &&
  409. DebugDir->PointerToRawData >= m_SizeOfImage &&
  410. !MemMap->GetRegionInfo(m_BaseOfImage +
  411. DebugDir->AddressOfRawData,
  412. NULL, NULL, NULL, NULL))
  413. {
  414. #if DBG_IMAGE_MAP
  415. dprintf(" Mapped hidden debug data at RVA %08x, "
  416. "size %x, ptr %08x\n",
  417. DebugDir->AddressOfRawData, DebugDir->SizeOfData,
  418. DebugDir->PointerToRawData);
  419. #endif
  420. if (MemMap->AddRegion(m_BaseOfImage +
  421. DebugDir->AddressOfRawData,
  422. DebugDir->SizeOfData,
  423. (PUCHAR)FileMapping +
  424. DebugDir->PointerToRawData,
  425. this, FALSE) != S_OK)
  426. {
  427. ErrOut("Unable to map extended debug data at %s\n",
  428. FormatAddr64(m_BaseOfImage +
  429. DebugDir->AddressOfRawData));
  430. }
  431. }
  432. DebugDir++;
  433. }
  434. }
  435. if (g_SymOptions & SYMOPT_DEBUG)
  436. {
  437. CompletePartialLine(DEBUG_OUTPUT_SYMBOLS);
  438. MaskOut(DEBUG_OUTPUT_SYMBOLS, "DBGENG: %s - Mapped image memory\n",
  439. m_MappedImagePath);
  440. }
  441. return TRUE;
  442. }
  443. void
  444. ImageInfo::UnloadExecutableImageMemory(void)
  445. {
  446. ULONG64 RegBase;
  447. ULONG RegSize;
  448. if (!m_MappedImageBase)
  449. {
  450. // Nothing mapped.
  451. return;
  452. }
  453. DBG_ASSERT(m_MemMap && m_File);
  454. //
  455. // This routine is called in various shutdown and deletion
  456. // paths so it can't really fail. Fortunately,
  457. // all of this image's memory regions are tagged with
  458. // the image pointer, so we can avoid all the work of
  459. // walking the image sections and so forth. We simply
  460. // scan the map for any sections marked with this image
  461. // and remove them. This guarantees
  462. // that no mapped memory from this image will remain.
  463. //
  464. for (;;)
  465. {
  466. if (!m_MemMap->GetRegionByUserData(this, &RegBase, &RegSize))
  467. {
  468. break;
  469. }
  470. m_MemMap->RemoveRegion(RegBase, RegSize);
  471. }
  472. UnmapViewOfFile(m_MappedImageBase);
  473. CloseHandle(m_File);
  474. m_MappedImageBase = NULL;
  475. m_File = NULL;
  476. m_MappedImagePath[0] = 0;
  477. m_MemMap = NULL;
  478. }
  479. BOOL
  480. ImageInfo::DemandLoadImageMemory(BOOL CheckIncomplete, BOOL Verbose)
  481. {
  482. if (!IS_DUMP_WITH_MAPPED_IMAGES(m_Process->m_Target))
  483. {
  484. return TRUE;
  485. }
  486. if (!LoadExecutableImageMemory(&((DumpTargetInfo*)m_Process->m_Target)->
  487. m_ImageMemMap, Verbose))
  488. {
  489. // If the caller has requested that we fail on
  490. // incomplete information fail the module load.
  491. // We don't do this if we're reusing an existing
  492. // module under the assumption that it's better
  493. // to continue and try to complete the reused
  494. // image rather than deleting it.
  495. if (CheckIncomplete &&
  496. (g_EngOptions & DEBUG_ENGOPT_FAIL_INCOMPLETE_INFORMATION))
  497. {
  498. return FALSE;
  499. }
  500. }
  501. return TRUE;
  502. }
  503. HRESULT
  504. ImageInfo::GetTlsIndex(void)
  505. {
  506. HRESULT Status;
  507. IMAGE_NT_HEADERS64 Hdrs;
  508. ULONG64 Addr;
  509. // Check to see if it's already set.
  510. if (m_TlsIndex != 0xffffffff)
  511. {
  512. return S_OK;
  513. }
  514. if ((Status = m_Process->m_Target->
  515. ReadImageNtHeaders(m_Process, m_BaseOfImage, &Hdrs)) != S_OK)
  516. {
  517. return Status;
  518. }
  519. if (Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size == 0)
  520. {
  521. // No TLS usage.
  522. m_TlsIndex = 0;
  523. return S_OK;
  524. }
  525. Addr = m_BaseOfImage + Hdrs.OptionalHeader.
  526. DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;
  527. if (Hdrs.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
  528. {
  529. IMAGE_TLS_DIRECTORY64 Tls;
  530. if ((Status = m_Process->m_Target->
  531. ReadAllVirtual(m_Process, Addr, &Tls, sizeof(Tls))) != S_OK)
  532. {
  533. return Status;
  534. }
  535. Addr = Tls.AddressOfIndex;
  536. }
  537. else
  538. {
  539. IMAGE_TLS_DIRECTORY32 Tls;
  540. if ((Status = m_Process->m_Target->
  541. ReadAllVirtual(m_Process, Addr, &Tls, sizeof(Tls))) != S_OK)
  542. {
  543. return Status;
  544. }
  545. Addr = EXTEND64(Tls.AddressOfIndex);
  546. }
  547. if ((Status = m_Process->m_Target->
  548. ReadAllVirtual(m_Process, Addr, &m_TlsIndex,
  549. sizeof(m_TlsIndex))) != S_OK)
  550. {
  551. m_TlsIndex = 0xffffffff;
  552. }
  553. return Status;
  554. }
  555. ULONG
  556. ImageInfo::GetMachineTypeFromHeader(void)
  557. {
  558. ULONG Machine = IMAGE_FILE_MACHINE_UNKNOWN;
  559. IMAGE_DOS_HEADER DosHdr;
  560. IMAGE_NT_HEADERS64 NtHdr;
  561. ULONG Done;
  562. //
  563. // Try to read the memory headers.
  564. //
  565. if (m_Process->m_Target->
  566. ReadAllVirtual(m_Process, m_BaseOfImage,
  567. &DosHdr, sizeof(DosHdr)) == S_OK &&
  568. DosHdr.e_magic == IMAGE_DOS_SIGNATURE &&
  569. m_Process->m_Target->
  570. ReadAllVirtual(m_Process, m_BaseOfImage + DosHdr.e_lfanew,
  571. &NtHdr,
  572. FIELD_OFFSET(IMAGE_NT_HEADERS64,
  573. FileHeader.NumberOfSections)) == S_OK &&
  574. NtHdr.Signature == IMAGE_NT_SIGNATURE &&
  575. MachineTypeIndex(NtHdr.FileHeader.Machine) != MACHIDX_COUNT)
  576. {
  577. Machine = NtHdr.FileHeader.Machine;
  578. }
  579. //
  580. // Try to read the file headers.
  581. //
  582. if (Machine == IMAGE_FILE_MACHINE_UNKNOWN &&
  583. m_File &&
  584. SetFilePointer(m_File, 0, NULL, FILE_BEGIN) !=
  585. INVALID_SET_FILE_POINTER &&
  586. ReadFile(m_File, &DosHdr, sizeof(DosHdr), &Done, NULL) &&
  587. Done == sizeof(DosHdr) &&
  588. DosHdr.e_magic == IMAGE_DOS_SIGNATURE &&
  589. SetFilePointer(m_File, DosHdr.e_lfanew, NULL, FILE_BEGIN) !=
  590. INVALID_SET_FILE_POINTER &&
  591. ReadFile(m_File, &NtHdr,
  592. FIELD_OFFSET(IMAGE_NT_HEADERS64,
  593. FileHeader.NumberOfSections), &Done, NULL) &&
  594. Done == FIELD_OFFSET(IMAGE_NT_HEADERS64,
  595. FileHeader.NumberOfSections) &&
  596. NtHdr.Signature == IMAGE_NT_SIGNATURE &&
  597. MachineTypeIndex(NtHdr.FileHeader.Machine) != MACHIDX_COUNT)
  598. {
  599. Machine = NtHdr.FileHeader.Machine;
  600. }
  601. m_MachineType = Machine;
  602. return Machine;
  603. }
  604. ULONG
  605. ImageInfo::CvRegToMachine(CV_HREG_e CvReg)
  606. {
  607. ULONG MachType;
  608. // Assume that a zero means no register. This
  609. // is true enough for CV mappings other than the 68K.
  610. if (CvReg == 0)
  611. {
  612. return CvReg;
  613. }
  614. if ((MachType = GetMachineType()) == IMAGE_FILE_MACHINE_UNKNOWN)
  615. {
  616. // Default to the native machine type if we can't
  617. // determine a specific machine type.
  618. MachType = m_Process->m_Target->m_MachineType;
  619. }
  620. return MachineTypeInfo(m_Process->m_Target, MachType)->
  621. CvRegToMachine(CvReg);
  622. }
  623. void
  624. ImageInfo::OutputVersionInformation(void)
  625. {
  626. TargetInfo* Target = m_Process->m_Target;
  627. VS_FIXEDFILEINFO FixedVer;
  628. ULONG i;
  629. char Item[128];
  630. char VerString[128];
  631. if (Target->
  632. GetImageVersionInformation(m_Process, m_ImagePath, m_BaseOfImage, "\\",
  633. &FixedVer, sizeof(FixedVer), NULL) == S_OK)
  634. {
  635. dprintf(" File version: %d.%d.%d.%d\n",
  636. FixedVer.dwFileVersionMS >> 16,
  637. FixedVer.dwFileVersionMS & 0xFFFF,
  638. FixedVer.dwFileVersionLS >> 16,
  639. FixedVer.dwFileVersionLS & 0xFFFF);
  640. dprintf(" Product version: %d.%d.%d.%d\n",
  641. FixedVer.dwProductVersionMS >> 16,
  642. FixedVer.dwProductVersionMS & 0xFFFF,
  643. FixedVer.dwProductVersionLS >> 16,
  644. FixedVer.dwProductVersionLS & 0xFFFF);
  645. FixedVer.dwFileFlags &= FixedVer.dwFileFlagsMask;
  646. dprintf(" File flags: %X (Mask %X)",
  647. FixedVer.dwFileFlags, FixedVer.dwFileFlagsMask);
  648. if (FixedVer.dwFileFlags & VS_FF_DEBUG)
  649. {
  650. dprintf(" Debug");
  651. }
  652. if (FixedVer.dwFileFlags & VS_FF_PRERELEASE)
  653. {
  654. dprintf(" Pre-release");
  655. }
  656. if (FixedVer.dwFileFlags & VS_FF_PATCHED)
  657. {
  658. dprintf(" Patched");
  659. }
  660. if (FixedVer.dwFileFlags & VS_FF_PRIVATEBUILD)
  661. {
  662. dprintf(" Private");
  663. }
  664. if (FixedVer.dwFileFlags & VS_FF_SPECIALBUILD)
  665. {
  666. dprintf(" Special");
  667. }
  668. dprintf("\n");
  669. dprintf(" File OS: %X", FixedVer.dwFileOS);
  670. switch(FixedVer.dwFileOS & 0xffff0000)
  671. {
  672. case VOS_DOS:
  673. dprintf(" DOS");
  674. break;
  675. case VOS_OS216:
  676. dprintf(" OS/2 16-bit");
  677. break;
  678. case VOS_OS232:
  679. dprintf(" OS/2 32-bit");
  680. break;
  681. case VOS_NT:
  682. dprintf(" NT");
  683. break;
  684. case VOS_WINCE:
  685. dprintf(" CE");
  686. break;
  687. default:
  688. dprintf(" Unknown");
  689. break;
  690. }
  691. switch(FixedVer.dwFileOS & 0xffff)
  692. {
  693. case VOS__WINDOWS16:
  694. dprintf(" Win16");
  695. break;
  696. case VOS__PM16:
  697. dprintf(" Presentation Manager 16-bit");
  698. break;
  699. case VOS__PM32:
  700. dprintf(" Presentation Manager 16-bit");
  701. break;
  702. case VOS__WINDOWS32:
  703. dprintf(" Win32");
  704. break;
  705. default:
  706. dprintf(" Base");
  707. break;
  708. }
  709. dprintf("\n");
  710. dprintf(" File type: %X.%X",
  711. FixedVer.dwFileType, FixedVer.dwFileSubtype);
  712. switch(FixedVer.dwFileType)
  713. {
  714. case VFT_APP:
  715. dprintf(" App");
  716. break;
  717. case VFT_DLL:
  718. dprintf(" Dll");
  719. break;
  720. case VFT_DRV:
  721. dprintf(" Driver");
  722. break;
  723. case VFT_FONT:
  724. dprintf(" Font");
  725. break;
  726. case VFT_VXD:
  727. dprintf(" VXD");
  728. break;
  729. case VFT_STATIC_LIB:
  730. dprintf(" Static library");
  731. break;
  732. default:
  733. dprintf(" Unknown");
  734. break;
  735. }
  736. dprintf("\n");
  737. dprintf(" File date: %08X.%08X\n",
  738. FixedVer.dwFileDateMS, FixedVer.dwFileDateLS);
  739. }
  740. for (i = 0; i < DIMA(g_VerStrings); i++)
  741. {
  742. sprintf(Item, "\\StringFileInfo\\%04x%04x\\%s",
  743. VER_VERSION_TRANSLATION, g_VerStrings[i]);
  744. if (SUCCEEDED(Target->GetImageVersionInformation
  745. (m_Process, m_ImagePath, m_BaseOfImage, Item,
  746. VerString, sizeof(VerString), NULL)))
  747. {
  748. PCSTR Blanks;
  749. int Len = strlen(g_VerStrings[i]);
  750. if (Len > 16)
  751. {
  752. Len = 16;
  753. }
  754. Blanks = s_Blanks16 + Len;
  755. dprintf(" %.16s:%s %s\n", g_VerStrings[i], Blanks, VerString);
  756. }
  757. }
  758. }
  759. void
  760. ImageInfo::ValidateSymbolLoad(PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 DefLoad)
  761. {
  762. //
  763. // If we had a 0 timestamp for the image, try to update it
  764. // from the image since for NT4 - XP, the kernel
  765. // does not report timestamps in the initial symbol load
  766. // module
  767. //
  768. if (m_BaseOfImage && !m_TimeDateStamp)
  769. {
  770. DWORD CheckSum;
  771. DWORD TimeDateStamp;
  772. DWORD SizeOfImage;
  773. if (GetHeaderInfo(m_Process,
  774. m_BaseOfImage,
  775. &CheckSum,
  776. &TimeDateStamp,
  777. &SizeOfImage))
  778. {
  779. m_TimeDateStamp = TimeDateStamp;
  780. }
  781. }
  782. m_SymState = ISS_MATCHED;
  783. if (DefLoad->TimeDateStamp == 0 ||
  784. m_TimeDateStamp == 0 ||
  785. m_TimeDateStamp == UNKNOWN_TIMESTAMP)
  786. {
  787. dprintf("*** WARNING: Unable to verify timestamp for %s\n",
  788. DefLoad->FileName);
  789. m_SymState = ISS_UNKNOWN_TIMESTAMP;
  790. }
  791. else if (DefLoad->CheckSum == 0 ||
  792. m_CheckSum == 0 ||
  793. m_CheckSum == UNKNOWN_CHECKSUM)
  794. {
  795. dprintf("*** WARNING: Unable to verify checksum for %s\n",
  796. DefLoad->FileName);
  797. m_SymState = ISS_UNKNOWN_CHECKSUM;
  798. }
  799. else if (DefLoad->CheckSum != m_CheckSum)
  800. {
  801. m_SymState = ISS_BAD_CHECKSUM;
  802. if (m_Process->m_Target->m_MachineType == IMAGE_FILE_MACHINE_I386)
  803. {
  804. if (IS_USER_TARGET(m_Process->m_Target) ||
  805. m_Process->m_Target->m_NumProcessors == 1)
  806. {
  807. char FileName[_MAX_FNAME];
  808. //
  809. // See if this is an MP image with the
  810. // lock table removed by setup. If
  811. // it is and the timestamps match, don't
  812. // print the invalid checksum warning.
  813. //
  814. _splitpath(DefLoad->FileName, NULL, NULL, FileName, NULL);
  815. if ((!_stricmp(FileName, "kernel32") ||
  816. (IS_KERNEL_TARGET(m_Process->m_Target) &&
  817. !_stricmp(FileName, "win32k")) ||
  818. !_stricmp(FileName, "wow32") ||
  819. !_stricmp(FileName, "ntvdm") ||
  820. !_stricmp(FileName, "ntdll")) &&
  821. m_TimeDateStamp == DefLoad->TimeDateStamp)
  822. {
  823. m_SymState = ISS_MATCHED;
  824. }
  825. }
  826. }
  827. if (m_SymState == ISS_BAD_CHECKSUM)
  828. {
  829. //
  830. // Only print the message if the timestamps
  831. // are wrong.
  832. //
  833. if (m_TimeDateStamp != DefLoad->TimeDateStamp)
  834. {
  835. dprintf("*** WARNING: symbols timestamp "
  836. "is wrong 0x%08x 0x%08x for %s\n",
  837. m_TimeDateStamp,
  838. DefLoad->TimeDateStamp,
  839. DefLoad->FileName);
  840. }
  841. }
  842. }
  843. IMAGEHLP_MODULE64 SymModInfo;
  844. SymModInfo.SizeOfStruct = sizeof(SymModInfo);
  845. if (SymGetModuleInfo64(m_Process->m_SymHandle, m_BaseOfImage, &SymModInfo))
  846. {
  847. if (SymModInfo.SymType == SymExport)
  848. {
  849. WarnOut("*** ERROR: Symbol file could not be found."
  850. " Defaulted to export symbols for %s - \n",
  851. DefLoad->FileName);
  852. }
  853. if (SymModInfo.SymType == SymNone)
  854. {
  855. WarnOut("*** ERROR: Module load completed but "
  856. "symbols could not be loaded for %s\n",
  857. DefLoad->FileName);
  858. }
  859. // If the load reports a mismatched PDB or DBG file
  860. // that overrides the other symbol states.
  861. if (SymModInfo.PdbUnmatched ||
  862. SymModInfo.DbgUnmatched)
  863. {
  864. m_SymState = ISS_MISMATCHED_SYMBOLS;
  865. if ((g_SymOptions & SYMOPT_DEBUG) &&
  866. SymModInfo.SymType != SymNone &&
  867. SymModInfo.SymType != SymExport)
  868. {
  869. // We loaded some symbols but they don't match.
  870. // Give a !sym noisy message referring to the
  871. // debugger documentation.
  872. CompletePartialLine(DEBUG_OUTPUT_SYMBOLS);
  873. MaskOut(DEBUG_OUTPUT_SYMBOLS,
  874. "DBGENG: %s has mismatched symbols - "
  875. "type \".hh dbgerr003\" for details\n",
  876. DefLoad->FileName);
  877. }
  878. }
  879. }
  880. }
  881. HRESULT
  882. ImageInfo::FindSysAssert(ULONG64 Offset,
  883. PSTR FileName,
  884. ULONG FileNameChars,
  885. PULONG Line,
  886. PSTR AssertText,
  887. ULONG AssertTextChars)
  888. {
  889. #if 0
  890. HRESULT Status;
  891. IMAGEHLP_LINE64 SymLine;
  892. ULONG Disp32;
  893. ULONG64 Disp64;
  894. SYMBOL_INFO_AND_NAME SymInfo;
  895. PSTR Text;
  896. // Look for DbgAssertBreak annotation for the given offset.
  897. if (!SymFromAddrByTag(m_Process->m_SymHandle, Offset, SymTagAnnotation,
  898. &Disp64, SymInfo) ||
  899. Disp64 != 0)
  900. {
  901. return E_NOINTERFACE;
  902. }
  903. Text = SymInfo->Name;
  904. if (strcmp(Text, "DbgAssertBreak"))
  905. {
  906. return E_NOINTERFACE;
  907. }
  908. Text += strlen(Text) + 1;
  909. // Get the file and line for reference.
  910. if (!GetLineFromAddr(m_Process, Offset, &SymLine, &Disp32))
  911. {
  912. return E_NOINTERFACE;
  913. }
  914. //
  915. // Found a match, return the information.
  916. //
  917. Status = FillStringBuffer(SymLine.FileName, 0,
  918. FileName, FileNameChars, NULL);
  919. *Line = SymLine.LineNumber;
  920. if (FillStringBuffer(Text, 0,
  921. AssertText, AssertTextChars, NULL) == S_FALSE)
  922. {
  923. Status = S_FALSE;
  924. }
  925. return Status;
  926. #else
  927. // Removing this to keep the API out of the .Net server release.
  928. return E_NOINTERFACE;
  929. #endif
  930. }
  931. void
  932. ImageInfo::ReloadSymbols(void)
  933. {
  934. // Force all symbols to be unloaded so that symbols will
  935. // be reloaded with any updated settings.
  936. SymUnloadModule64(m_Process->m_SymHandle, m_BaseOfImage);
  937. ClearStoredTypes(m_BaseOfImage);
  938. if (!SymLoadModule64(m_Process->m_SymHandle,
  939. m_File,
  940. PrepareImagePath(m_ImagePath),
  941. m_ModuleName,
  942. m_BaseOfImage,
  943. m_SizeOfImage))
  944. {
  945. ErrOut("Unable to reload %s\n", m_ModuleName);
  946. }
  947. }
  948. void
  949. ImageInfo::FillModuleParameters(PDEBUG_MODULE_PARAMETERS Params)
  950. {
  951. Params->Base = m_BaseOfImage;
  952. Params->Size = m_SizeOfImage;
  953. Params->TimeDateStamp = m_TimeDateStamp;
  954. Params->Checksum = m_CheckSum;
  955. Params->Flags = 0;
  956. if (m_SymState == ISS_BAD_CHECKSUM)
  957. {
  958. Params->Flags |= DEBUG_MODULE_SYM_BAD_CHECKSUM;
  959. }
  960. if (m_UserMode)
  961. {
  962. Params->Flags |= DEBUG_MODULE_USER_MODE;
  963. }
  964. Params->SymbolType = DEBUG_SYMTYPE_DEFERRED;
  965. Params->ImageNameSize = strlen(m_ImagePath) + 1;
  966. Params->ModuleNameSize = strlen(m_ModuleName) + 1;
  967. Params->LoadedImageNameSize = 0;
  968. Params->SymbolFileNameSize = 0;
  969. ZeroMemory(Params->Reserved, sizeof(Params->Reserved));
  970. IMAGEHLP_MODULE64 ModInfo;
  971. ModInfo.SizeOfStruct = sizeof(ModInfo);
  972. if (SymGetModuleInfo64(m_Process->m_SymHandle,
  973. m_BaseOfImage, &ModInfo))
  974. {
  975. // DEBUG_SYMTYPE_* values match imagehlp's SYM_TYPE.
  976. // Assert some key equivalences.
  977. C_ASSERT(DEBUG_SYMTYPE_PDB == SymPdb &&
  978. DEBUG_SYMTYPE_EXPORT == SymExport &&
  979. DEBUG_SYMTYPE_DEFERRED == SymDeferred &&
  980. DEBUG_SYMTYPE_DIA == SymDia);
  981. Params->SymbolType = (ULONG)ModInfo.SymType;
  982. Params->LoadedImageNameSize = strlen(ModInfo.LoadedImageName) + 1;
  983. Params->SymbolFileNameSize = strlen(ModInfoSymFile(&ModInfo)) + 1;
  984. }
  985. Params->MappedImageNameSize = strlen(m_MappedImagePath) + 1;
  986. }
  987. //----------------------------------------------------------------------------
  988. //
  989. // Functions.
  990. //
  991. //----------------------------------------------------------------------------
  992. PSTR
  993. UnknownImageName(ULONG64 ImageBase, PSTR Buffer, ULONG BufferChars)
  994. {
  995. PrintString(Buffer, BufferChars,
  996. UNKNOWN_IMAGE_NAME "_%s", FormatAddr64(ImageBase));
  997. return Buffer;
  998. }
  999. PSTR
  1000. ValidateImagePath(PSTR ImagePath, ULONG ImagePathChars,
  1001. ULONG64 ImageBase,
  1002. PSTR AnsiBuffer, ULONG AnsiBufferChars)
  1003. {
  1004. if (!ImagePath || !ImagePathChars)
  1005. {
  1006. WarnOut("Missing image name, possible corrupt data.\n");
  1007. goto Invalid;
  1008. }
  1009. if (ImagePathChars >= MAX_IMAGE_PATH)
  1010. {
  1011. WarnOut("Image path too long, possible corrupt data.\n");
  1012. goto Invalid;
  1013. }
  1014. // Incoming path may not be terminated, so force it
  1015. // in the copy buffer.
  1016. CopyNString(AnsiBuffer, ImagePath, ImagePathChars, AnsiBufferChars);
  1017. if (IsValidName(AnsiBuffer))
  1018. {
  1019. return AnsiBuffer;
  1020. }
  1021. // Converted name doesn't look valid, fall into
  1022. // replacement case.
  1023. Invalid:
  1024. return UnknownImageName(ImageBase, AnsiBuffer, AnsiBufferChars);
  1025. }
  1026. PSTR
  1027. ConvertAndValidateImagePathW(PWSTR ImagePath, ULONG ImagePathChars,
  1028. ULONG64 ImageBase,
  1029. PSTR AnsiBuffer, ULONG AnsiBufferChars)
  1030. {
  1031. if (!ImagePath || !ImagePathChars)
  1032. {
  1033. WarnOut("Missing image name, possible corrupt data.\n");
  1034. goto Invalid;
  1035. }
  1036. if (ImagePathChars >= MAX_IMAGE_PATH)
  1037. {
  1038. WarnOut("Image path too long, possible corrupt data.\n");
  1039. goto Invalid;
  1040. }
  1041. //
  1042. // Dumps, particularly kernel minidumps, can sometimes
  1043. // have bad module name string entries. There's no guaranteed
  1044. // way of detecting such bad strings so we use a simple
  1045. // two-point heuristic:
  1046. // 1. If we can't convert the Unicode to ANSI, consider it bad.
  1047. // The WCTMB call will fail if the name is too long also,
  1048. // but this isn't a bad thing.
  1049. // 2. If the resulting name doesn't contain an any alphanumeric
  1050. // characters, consider it bad.
  1051. //
  1052. ULONG Used =
  1053. WideCharToMultiByte(CP_ACP, 0, ImagePath, ImagePathChars,
  1054. AnsiBuffer, AnsiBufferChars,
  1055. NULL, NULL);
  1056. if (!Used)
  1057. {
  1058. goto Invalid;
  1059. }
  1060. if (Used < AnsiBufferChars)
  1061. {
  1062. AnsiBuffer[Used] = 0;
  1063. }
  1064. else
  1065. {
  1066. AnsiBuffer[AnsiBufferChars - 1] = 0;
  1067. }
  1068. if (IsValidName(AnsiBuffer))
  1069. {
  1070. return AnsiBuffer;
  1071. }
  1072. // Converted name doesn't look valid, fall into
  1073. // replacement case.
  1074. Invalid:
  1075. return UnknownImageName(ImageBase, AnsiBuffer, AnsiBufferChars);
  1076. }
  1077. PSTR
  1078. PrepareImagePath(PSTR ImagePath)
  1079. {
  1080. // dbghelp will sometimes scan the path given to
  1081. // SymLoadModule for the image itself. There
  1082. // can be cases where the scan uses fuzzy matching,
  1083. // so we want to be careful to only pass in a path
  1084. // for dbghelp to use when the path can safely be
  1085. // used.
  1086. if ((IS_LIVE_USER_TARGET(g_Target) &&
  1087. ((LiveUserTargetInfo*)g_Target)->m_Local) ||
  1088. IS_LOCAL_KERNEL_TARGET(g_Target))
  1089. {
  1090. return ImagePath;
  1091. }
  1092. else
  1093. {
  1094. return (PSTR)PathTail(ImagePath);
  1095. }
  1096. }
  1097. typedef struct _FIND_MODULE_DATA
  1098. {
  1099. ULONG SizeOfImage;
  1100. ULONG CheckSum;
  1101. ULONG TimeDateStamp;
  1102. BOOL Silent;
  1103. PVOID FileMapping;
  1104. HANDLE FileHandle;
  1105. } FIND_MODULE_DATA, *PFIND_MODULE_DATA;
  1106. PVOID
  1107. OpenMapping(
  1108. IN PCSTR FilePath,
  1109. OUT HANDLE* FileHandle
  1110. )
  1111. {
  1112. HANDLE File;
  1113. HANDLE Mapping;
  1114. PVOID View;
  1115. ULONG OldMode;
  1116. *FileHandle = NULL;
  1117. if (g_SymOptions & SYMOPT_FAIL_CRITICAL_ERRORS)
  1118. {
  1119. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  1120. }
  1121. File = CreateFile(
  1122. FilePath,
  1123. GENERIC_READ,
  1124. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1125. NULL,
  1126. OPEN_EXISTING,
  1127. 0,
  1128. NULL
  1129. );
  1130. if (g_SymOptions & SYMOPT_FAIL_CRITICAL_ERRORS)
  1131. {
  1132. SetErrorMode(OldMode);
  1133. }
  1134. if ( File == INVALID_HANDLE_VALUE )
  1135. {
  1136. return NULL;
  1137. }
  1138. Mapping = CreateFileMapping (
  1139. File,
  1140. NULL,
  1141. PAGE_READONLY,
  1142. 0,
  1143. 0,
  1144. NULL
  1145. );
  1146. if ( !Mapping )
  1147. {
  1148. CloseHandle ( File );
  1149. return FALSE;
  1150. }
  1151. View = MapViewOfFile (
  1152. Mapping,
  1153. FILE_MAP_READ,
  1154. 0,
  1155. 0,
  1156. 0
  1157. );
  1158. CloseHandle (Mapping);
  1159. *FileHandle = File;
  1160. return View;
  1161. }
  1162. PVOID
  1163. MapImageFile(
  1164. PCSTR FilePath,
  1165. ULONG SizeOfImage,
  1166. ULONG CheckSum,
  1167. ULONG TimeDateStamp,
  1168. BOOL Silent,
  1169. HANDLE* FileHandle
  1170. )
  1171. {
  1172. PVOID FileMapping;
  1173. PIMAGE_NT_HEADERS NtHeader;
  1174. FileMapping = OpenMapping(FilePath, FileHandle);
  1175. if (!FileMapping)
  1176. {
  1177. return NULL;
  1178. }
  1179. NtHeader = ImageNtHeader(FileMapping);
  1180. if ((NtHeader == NULL) ||
  1181. (CheckSum && NtHeader->OptionalHeader.CheckSum &&
  1182. (NtHeader->OptionalHeader.CheckSum != CheckSum)) ||
  1183. (SizeOfImage != 0 &&
  1184. NtHeader->OptionalHeader.SizeOfImage != SizeOfImage) ||
  1185. (TimeDateStamp != 0 &&
  1186. NtHeader->FileHeader.TimeDateStamp != TimeDateStamp))
  1187. {
  1188. //
  1189. // The image data does not match the request.
  1190. //
  1191. if (!Silent && (g_SymOptions & SYMOPT_DEBUG))
  1192. {
  1193. CompletePartialLine(DEBUG_OUTPUT_SYMBOLS);
  1194. MaskOut(DEBUG_OUTPUT_SYMBOLS,
  1195. (NtHeader) ? "DBGENG: %s image header does not "
  1196. "match memory image header.\n" :
  1197. "DBGENG: %s - image not mapped.\n",
  1198. FilePath);
  1199. }
  1200. UnmapViewOfFile(FileMapping);
  1201. CloseHandle(*FileHandle);
  1202. *FileHandle = NULL;
  1203. return NULL;
  1204. }
  1205. return FileMapping;
  1206. }
  1207. BOOL CALLBACK
  1208. FindFileInPathCallback(PSTR FileName, PVOID CallerData)
  1209. {
  1210. PFIND_MODULE_DATA FindModuleData = (PFIND_MODULE_DATA)CallerData;
  1211. FindModuleData->FileMapping =
  1212. MapImageFile(FileName, FindModuleData->SizeOfImage,
  1213. (g_SymOptions & SYMOPT_EXACT_SYMBOLS) ?
  1214. FindModuleData->CheckSum : 0,
  1215. FindModuleData->TimeDateStamp,
  1216. FindModuleData->Silent,
  1217. &FindModuleData->FileHandle);
  1218. // The search stops when FALSE is returned, so
  1219. // return FALSE when we've found a match.
  1220. return FindModuleData->FileMapping == NULL;
  1221. }
  1222. BOOL
  1223. FindExecutableCallback(
  1224. HANDLE File,
  1225. PSTR FileName,
  1226. PVOID CallerData
  1227. )
  1228. {
  1229. PFIND_MODULE_DATA FindModuleData;
  1230. DBG_ASSERT ( CallerData );
  1231. FindModuleData = (PFIND_MODULE_DATA) CallerData;
  1232. FindModuleData->FileMapping =
  1233. MapImageFile(FileName, FindModuleData->SizeOfImage,
  1234. (g_SymOptions & SYMOPT_EXACT_SYMBOLS) ?
  1235. FindModuleData->CheckSum : 0,
  1236. FindModuleData->TimeDateStamp,
  1237. FindModuleData->Silent,
  1238. &FindModuleData->FileHandle);
  1239. return FindModuleData->FileMapping != NULL;
  1240. }
  1241. PVOID
  1242. FindImageFile(
  1243. IN ProcessInfo* Process,
  1244. IN PCSTR ImagePath,
  1245. IN ULONG SizeOfImage,
  1246. IN ULONG CheckSum,
  1247. IN ULONG TimeDateStamp,
  1248. OUT HANDLE* FileHandle,
  1249. OUT PSTR MappedImagePath
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. Find the executable image on the SymbolPath that matches ModuleName,
  1254. CheckSum. This function takes care of things like renamed kernels and
  1255. hals, and multiple images with the same name on the path.
  1256. Return Values:
  1257. File mapping or NULL.
  1258. --*/
  1259. {
  1260. ULONG i;
  1261. HANDLE File;
  1262. ULONG AliasCount = 0;
  1263. PCSTR AliasList[MAX_ALIAS_COUNT + 3];
  1264. FIND_MODULE_DATA FindModuleData;
  1265. MODULE_ALIAS_LIST* ModAlias;
  1266. PSTR SearchPaths[2];
  1267. ULONG WhichPath;
  1268. BOOL ModInAliasList;
  1269. DBG_ASSERT ( ImagePath != NULL && ImagePath[0] != 0 );
  1270. PCSTR ModuleName = PathTail(ImagePath);
  1271. //
  1272. // Build an alias list. For normal modules, modules that are not the
  1273. // kernel, the hal or a dump driver, this list will contain exactly one
  1274. // entry with the module name. For kernel, hal and dump drivers, the
  1275. // list will contain any number of known aliases for the specific file.
  1276. //
  1277. ModAlias = FindModuleAliasList(ModuleName, &ModInAliasList);
  1278. if (ModAlias)
  1279. {
  1280. // If the given module is in the alias list already
  1281. // don't put in a duplicate.
  1282. if (!ModInAliasList)
  1283. {
  1284. AliasList[AliasCount++] = ModuleName;
  1285. }
  1286. for (i = 0; i < ModAlias->Length; i++)
  1287. {
  1288. AliasList[AliasCount++] = ModAlias->Aliases[i];
  1289. }
  1290. }
  1291. else
  1292. {
  1293. if (_strnicmp(ModuleName, "dump_scsiport", 11) == 0)
  1294. {
  1295. AliasList[0] = "diskdump.sys";
  1296. AliasCount = 1;
  1297. }
  1298. else if (_strnicmp(ModuleName, "dump_", 5) == 0)
  1299. {
  1300. //
  1301. // Setup dump driver alias list
  1302. //
  1303. AliasList[0] = &ModuleName[5];
  1304. AliasList[1] = ModuleName;
  1305. AliasCount = 2;
  1306. }
  1307. else
  1308. {
  1309. AliasList[0] = ModuleName;
  1310. AliasCount = 1;
  1311. }
  1312. }
  1313. //
  1314. // Search on the image path first, then on the symbol path.
  1315. //
  1316. SearchPaths[0] = g_ExecutableImageSearchPath;
  1317. SearchPaths[1] = g_SymbolSearchPath;
  1318. for (WhichPath = 0; WhichPath < DIMA(SearchPaths); WhichPath++)
  1319. {
  1320. if (!SearchPaths[WhichPath] || !SearchPaths[WhichPath][0])
  1321. {
  1322. continue;
  1323. }
  1324. //
  1325. // First try to find it in a symbol server or
  1326. // directly on the search path.
  1327. //
  1328. for (i = 0; i < AliasCount; i++)
  1329. {
  1330. FindModuleData.SizeOfImage = SizeOfImage;
  1331. FindModuleData.CheckSum = CheckSum;
  1332. FindModuleData.TimeDateStamp = TimeDateStamp;
  1333. FindModuleData.Silent = FALSE;
  1334. FindModuleData.FileMapping = NULL;
  1335. FindModuleData.FileHandle = NULL;
  1336. if (SymFindFileInPath(Process->m_SymHandle,
  1337. SearchPaths[WhichPath],
  1338. (PSTR)AliasList[i],
  1339. UlongToPtr(TimeDateStamp),
  1340. SizeOfImage, 0, SSRVOPT_DWORD,
  1341. MappedImagePath,
  1342. FindFileInPathCallback, &FindModuleData))
  1343. {
  1344. if (FileHandle)
  1345. {
  1346. *FileHandle = FindModuleData.FileHandle;
  1347. }
  1348. return FindModuleData.FileMapping;
  1349. }
  1350. }
  1351. //
  1352. // Initial search didn't work so do a full tree search.
  1353. //
  1354. for (i = 0; i < AliasCount; i++)
  1355. {
  1356. FindModuleData.SizeOfImage = SizeOfImage;
  1357. FindModuleData.CheckSum = CheckSum;
  1358. FindModuleData.TimeDateStamp = TimeDateStamp;
  1359. // FindExecutableImageEx displays its own
  1360. // debug output so don't display any in
  1361. // the callback.
  1362. FindModuleData.Silent = TRUE;
  1363. FindModuleData.FileMapping = NULL;
  1364. FindModuleData.FileHandle = NULL;
  1365. File = FindExecutableImageEx((PSTR)AliasList[i],
  1366. SearchPaths[WhichPath],
  1367. MappedImagePath,
  1368. FindExecutableCallback,
  1369. &FindModuleData);
  1370. if ( File != NULL && File != INVALID_HANDLE_VALUE )
  1371. {
  1372. CloseHandle (File);
  1373. }
  1374. if ( FindModuleData.FileMapping != NULL )
  1375. {
  1376. if (FileHandle)
  1377. {
  1378. *FileHandle = FindModuleData.FileHandle;
  1379. }
  1380. return FindModuleData.FileMapping;
  1381. }
  1382. }
  1383. }
  1384. //
  1385. // No path searches found the image so just try
  1386. // the given path as a last-ditch check.
  1387. //
  1388. strcpy(MappedImagePath, ImagePath);
  1389. FindModuleData.FileMapping =
  1390. MapImageFile(ImagePath, SizeOfImage, CheckSum, TimeDateStamp,
  1391. FALSE, FileHandle);
  1392. if (FindModuleData.FileMapping == NULL)
  1393. {
  1394. MappedImagePath[0] = 0;
  1395. if (FileHandle)
  1396. {
  1397. *FileHandle = NULL;
  1398. }
  1399. if (g_SymOptions & SYMOPT_DEBUG)
  1400. {
  1401. CompletePartialLine(DEBUG_OUTPUT_SYMBOLS);
  1402. MaskOut(DEBUG_OUTPUT_SYMBOLS,
  1403. "DBGENG: %s - Couldn't map image from disk.\n",
  1404. ImagePath);
  1405. }
  1406. }
  1407. return FindModuleData.FileMapping;
  1408. }
  1409. BOOL
  1410. DemandLoadReferencedImageMemory(ProcessInfo* Process,
  1411. ULONG64 Addr, ULONG Size)
  1412. {
  1413. ImageInfo* Image;
  1414. BOOL Hit = FALSE;
  1415. //
  1416. // If we are handling a mini dump, we may need to
  1417. // map image memory to respond to a memory read.
  1418. // If the given address falls within a module's range
  1419. // map its image memory.
  1420. //
  1421. // Some versions of the linker produced images
  1422. // where important debug records were outside of
  1423. // the image range, so add a fudge factor to the
  1424. // image size to include potential extra data.
  1425. //
  1426. if (Process)
  1427. {
  1428. for (Image = Process->m_ImageHead; Image; Image = Image->m_Next)
  1429. {
  1430. if (Addr + Size > Image->m_BaseOfImage &&
  1431. Addr < Image->m_BaseOfImage + Image->m_SizeOfImage + 8192)
  1432. {
  1433. if (!Image->DemandLoadImageMemory(TRUE, FALSE))
  1434. {
  1435. return FALSE;
  1436. }
  1437. Hit = TRUE;
  1438. }
  1439. }
  1440. }
  1441. return Hit;
  1442. }
  1443. ULONG
  1444. ReadImageData(ProcessInfo* Process,
  1445. ULONG64 Address,
  1446. HANDLE File,
  1447. LPVOID Buffer,
  1448. ULONG Size)
  1449. {
  1450. ULONG Result;
  1451. if (File)
  1452. {
  1453. if (SetFilePointer(File, (ULONG)Address, NULL,
  1454. FILE_BEGIN) == INVALID_SET_FILE_POINTER)
  1455. {
  1456. return 0;
  1457. }
  1458. if (!ReadFile(File, Buffer, Size, &Result, NULL) ||
  1459. Result < Size)
  1460. {
  1461. return 0;
  1462. }
  1463. }
  1464. else
  1465. {
  1466. if (Process->m_Target->
  1467. ReadVirtual(Process, Address, Buffer, Size, &Result) != S_OK ||
  1468. Result < Size)
  1469. {
  1470. return 0;
  1471. }
  1472. }
  1473. return Size;
  1474. }
  1475. BOOL
  1476. GetModnameFromImageInternal(ProcessInfo* Process,
  1477. ULONG64 BaseOfDll,
  1478. HANDLE File,
  1479. LPSTR Name,
  1480. ULONG NameSize,
  1481. BOOL SearchExportFirst)
  1482. {
  1483. IMAGE_DEBUG_DIRECTORY DebugDir;
  1484. PIMAGE_DEBUG_MISC Misc;
  1485. PIMAGE_DEBUG_MISC MiscTmp;
  1486. PIMAGE_SECTION_HEADER SecHdr = NULL;
  1487. IMAGE_NT_HEADERS64 Hdrs64;
  1488. PIMAGE_NT_HEADERS32 Hdrs32 = (PIMAGE_NT_HEADERS32)&Hdrs64;
  1489. IMAGE_DOS_HEADER DosHdr;
  1490. DWORD Rva;
  1491. DWORD RvaExport = 0;
  1492. int NumDebugDirs;
  1493. int i;
  1494. int j;
  1495. int Len;
  1496. BOOL Succ = FALSE;
  1497. USHORT NumberOfSections;
  1498. USHORT Characteristics;
  1499. ULONG64 Address;
  1500. DWORD Sig;
  1501. DWORD Bytes;
  1502. CHAR ExportName[MAX_IMAGE_PATH];
  1503. CHAR DebugName[MAX_IMAGE_PATH];
  1504. ExportName[0] = 0;
  1505. DebugName[0] = 0;
  1506. Name[0] = 0;
  1507. if (File)
  1508. {
  1509. BaseOfDll = 0;
  1510. }
  1511. Address = BaseOfDll;
  1512. if (!ReadImageData( Process, Address, File, &DosHdr, sizeof(DosHdr) ))
  1513. {
  1514. return FALSE;
  1515. }
  1516. if (DosHdr.e_magic == IMAGE_DOS_SIGNATURE)
  1517. {
  1518. Address += DosHdr.e_lfanew;
  1519. }
  1520. if (!ReadImageData( Process, Address, File, &Sig, sizeof(Sig) ))
  1521. {
  1522. return FALSE;
  1523. }
  1524. if (Sig != IMAGE_NT_SIGNATURE)
  1525. {
  1526. IMAGE_FILE_HEADER FileHdr;
  1527. IMAGE_ROM_OPTIONAL_HEADER RomHdr;
  1528. if (!ReadImageData( Process, Address, File,
  1529. &FileHdr, sizeof(FileHdr) ))
  1530. {
  1531. return FALSE;
  1532. }
  1533. Address += sizeof(FileHdr);
  1534. if (!ReadImageData( Process, Address, File, &RomHdr, sizeof(RomHdr) ))
  1535. {
  1536. return FALSE;
  1537. }
  1538. Address += sizeof(RomHdr);
  1539. if (RomHdr.Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC)
  1540. {
  1541. NumberOfSections = FileHdr.NumberOfSections;
  1542. Characteristics = FileHdr.Characteristics;
  1543. NumDebugDirs = Rva = 0;
  1544. }
  1545. else
  1546. {
  1547. return FALSE;
  1548. }
  1549. }
  1550. else
  1551. {
  1552. //
  1553. // Read the head as a 64 bit header and cast it appropriately.
  1554. //
  1555. if (!ReadImageData( Process, Address, File, &Hdrs64, sizeof(Hdrs64) ))
  1556. {
  1557. return FALSE;
  1558. }
  1559. if (IsImageMachineType64(Hdrs32->FileHeader.Machine))
  1560. {
  1561. Address += sizeof(IMAGE_NT_HEADERS64);
  1562. NumberOfSections = Hdrs64.FileHeader.NumberOfSections;
  1563. Characteristics = Hdrs64.FileHeader.Characteristics;
  1564. NumDebugDirs = Hdrs64.OptionalHeader.
  1565. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
  1566. sizeof(IMAGE_DEBUG_DIRECTORY);
  1567. Rva = Hdrs64.OptionalHeader.
  1568. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  1569. RvaExport = Hdrs64.OptionalHeader.
  1570. DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  1571. }
  1572. else
  1573. {
  1574. Address += sizeof(IMAGE_NT_HEADERS32);
  1575. NumberOfSections = Hdrs32->FileHeader.NumberOfSections;
  1576. Characteristics = Hdrs32->FileHeader.Characteristics;
  1577. NumDebugDirs = Hdrs32->OptionalHeader.
  1578. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
  1579. sizeof(IMAGE_DEBUG_DIRECTORY);
  1580. Rva = Hdrs32->OptionalHeader.
  1581. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  1582. RvaExport = Hdrs32->OptionalHeader.
  1583. DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  1584. }
  1585. }
  1586. Bytes = NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER;
  1587. SecHdr = (PIMAGE_SECTION_HEADER)malloc( Bytes );
  1588. if (!SecHdr)
  1589. {
  1590. return FALSE;
  1591. }
  1592. if (!ReadImageData( Process, Address, File, SecHdr, Bytes ))
  1593. {
  1594. goto Finish;
  1595. }
  1596. //
  1597. // Let try looking at the export table to see if we can find the image
  1598. // name.
  1599. //
  1600. if (RvaExport)
  1601. {
  1602. for (i = 0; i < NumberOfSections; i++)
  1603. {
  1604. if (RvaExport >= SecHdr[i].VirtualAddress &&
  1605. RvaExport < SecHdr[i].VirtualAddress + SecHdr[i].SizeOfRawData)
  1606. {
  1607. break;
  1608. }
  1609. }
  1610. if (i < NumberOfSections)
  1611. {
  1612. DWORD TmpRva = RvaExport;
  1613. ULONG64 ExportNameRva = 0;
  1614. CHAR Char;
  1615. if (File)
  1616. {
  1617. TmpRva = TmpRva -
  1618. SecHdr[i].VirtualAddress + SecHdr[i].PointerToRawData;
  1619. }
  1620. if (ReadImageData(Process,
  1621. TmpRva + FIELD_OFFSET(IMAGE_EXPORT_DIRECTORY,
  1622. Name) +
  1623. BaseOfDll, File, &ExportNameRva, sizeof(DWORD)))
  1624. {
  1625. if (File)
  1626. {
  1627. ExportNameRva = ExportNameRva - SecHdr[i].VirtualAddress +
  1628. SecHdr[i].PointerToRawData;
  1629. }
  1630. ExportNameRva += BaseOfDll;
  1631. Succ = TRUE;
  1632. Len = 0;
  1633. do
  1634. {
  1635. if (!ReadImageData( Process, ExportNameRva,
  1636. File, &Char, sizeof(Char)))
  1637. {
  1638. Succ = FALSE;
  1639. break;
  1640. }
  1641. ExportNameRva++;
  1642. ExportName[Len] = Char;
  1643. Len++;
  1644. } while (Char && (Len < sizeof(ExportName)));
  1645. }
  1646. }
  1647. }
  1648. //
  1649. // Now get the name from the debug directory eixsts, get that.
  1650. //
  1651. if (!Rva || !NumDebugDirs)
  1652. {
  1653. goto Finish;
  1654. }
  1655. for (i = 0; i < NumberOfSections; i++)
  1656. {
  1657. if (Rva >= SecHdr[i].VirtualAddress &&
  1658. Rva < SecHdr[i].VirtualAddress + SecHdr[i].SizeOfRawData)
  1659. {
  1660. break;
  1661. }
  1662. }
  1663. if (i >= NumberOfSections)
  1664. {
  1665. goto Finish;
  1666. }
  1667. Rva = Rva - SecHdr[i].VirtualAddress;
  1668. if (File)
  1669. {
  1670. Rva += SecHdr[i].PointerToRawData;
  1671. }
  1672. else
  1673. {
  1674. Rva += SecHdr[i].VirtualAddress;
  1675. }
  1676. for (j = 0; j < NumDebugDirs; j++)
  1677. {
  1678. if (!ReadImageData(Process, Rva + (sizeof(DebugDir) * j) + BaseOfDll,
  1679. File, &DebugDir, sizeof(DebugDir)))
  1680. {
  1681. break;
  1682. }
  1683. if (DebugDir.Type == IMAGE_DEBUG_TYPE_MISC &&
  1684. ((!File && DebugDir.AddressOfRawData) ||
  1685. (File && DebugDir.PointerToRawData)))
  1686. {
  1687. Len = DebugDir.SizeOfData;
  1688. Misc = MiscTmp = (PIMAGE_DEBUG_MISC)malloc(Len);
  1689. if (!Misc)
  1690. {
  1691. break;
  1692. }
  1693. if (File)
  1694. {
  1695. Address = DebugDir.PointerToRawData;
  1696. }
  1697. else
  1698. {
  1699. Address = DebugDir.AddressOfRawData + BaseOfDll;
  1700. }
  1701. Len = ReadImageData( Process, Address, File, Misc, Len);
  1702. while (Len >= sizeof(*Misc) &&
  1703. Misc->Length &&
  1704. (ULONG)Len >= Misc->Length)
  1705. {
  1706. if (Misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
  1707. {
  1708. Len -= Misc->Length;
  1709. Misc = (PIMAGE_DEBUG_MISC)
  1710. (((LPSTR)Misc) + Misc->Length);
  1711. }
  1712. else
  1713. {
  1714. PVOID ExeName = (PVOID)&Misc->Data[ 0 ];
  1715. if (!Misc->Unicode)
  1716. {
  1717. CatString(DebugName, (LPSTR)ExeName, DIMA(DebugName));
  1718. Succ = TRUE;
  1719. }
  1720. else
  1721. {
  1722. Succ = WideCharToMultiByte(CP_ACP,
  1723. 0,
  1724. (LPWSTR)ExeName,
  1725. -1,
  1726. DebugName,
  1727. sizeof(DebugName),
  1728. NULL,
  1729. NULL) != 0;
  1730. }
  1731. //
  1732. // Undo stevewo's error
  1733. //
  1734. if (_stricmp(&DebugName[strlen(DebugName) - 4],
  1735. ".DBG") == 0)
  1736. {
  1737. char Path[MAX_IMAGE_PATH];
  1738. char Base[_MAX_FNAME];
  1739. _splitpath(DebugName, NULL, Path, Base, NULL);
  1740. if (strlen(Path) == 4)
  1741. {
  1742. Path[strlen(Path) - 1] = 0;
  1743. CopyString(DebugName, Base, DIMA(DebugName));
  1744. CatString(DebugName, ".", DIMA(DebugName));
  1745. CatString(DebugName, Path, DIMA(DebugName));
  1746. }
  1747. else if (Characteristics & IMAGE_FILE_DLL)
  1748. {
  1749. CopyString(DebugName, Base, DIMA(DebugName));
  1750. CatString(DebugName, ".dll", DIMA(DebugName));
  1751. }
  1752. else
  1753. {
  1754. CopyString(DebugName, Base, DIMA(DebugName));
  1755. CatString(DebugName, ".exe", DIMA(DebugName));
  1756. }
  1757. }
  1758. break;
  1759. }
  1760. }
  1761. free(MiscTmp);
  1762. if (Succ)
  1763. {
  1764. break;
  1765. }
  1766. }
  1767. else if ((DebugDir.Type == IMAGE_DEBUG_TYPE_CODEVIEW) &&
  1768. ((!File && DebugDir.AddressOfRawData) ||
  1769. (File && DebugDir.PointerToRawData)) &&
  1770. (DebugDir.SizeOfData > sizeof(NB10IH)))
  1771. {
  1772. DWORD Signature;
  1773. char Path[MAX_IMAGE_PATH];
  1774. char Base[_MAX_FNAME];
  1775. // Mapped CV info. Read the data and see what the content is.
  1776. if (File)
  1777. {
  1778. Address = DebugDir.PointerToRawData;
  1779. }
  1780. else
  1781. {
  1782. Address = DebugDir.AddressOfRawData + BaseOfDll;
  1783. }
  1784. if (!ReadImageData( Process, Address, File, &Signature,
  1785. sizeof(Signature) ))
  1786. {
  1787. break;
  1788. }
  1789. // NB10 or PDB7 signature?
  1790. if (Signature == NB10_SIG ||
  1791. Signature == RSDS_SIG)
  1792. {
  1793. ULONG HdrSize = Signature == NB10_SIG ?
  1794. sizeof(NB10IH) : sizeof(RSDSIH);
  1795. Address += HdrSize;
  1796. if ((DebugDir.SizeOfData - sizeof(HdrSize)) > MAX_PATH)
  1797. {
  1798. // Something's wrong here. The record should only contain
  1799. // a MAX_PATH path name.
  1800. break;
  1801. }
  1802. if (DebugDir.SizeOfData - HdrSize > NameSize)
  1803. {
  1804. break;
  1805. }
  1806. if (!ReadImageData(Process, Address, File, DebugName,
  1807. DebugDir.SizeOfData - HdrSize))
  1808. {
  1809. break;
  1810. }
  1811. _splitpath(DebugName, NULL, Path, Base, NULL);
  1812. // Files are sometimes generated with .pdb appended
  1813. // to the image name rather than replacing the extension
  1814. // of the image name, such as foo.exe.pdb.
  1815. // splitpath only takes off the outermost extension,
  1816. // so check and see if the base already has an extension
  1817. // we recognize.
  1818. PSTR Ext = strrchr(Base, '.');
  1819. if (Ext != NULL &&
  1820. (!strcmp(Ext, ".exe") || !strcmp(Ext, ".dll") ||
  1821. !strcmp(Ext, ".sys")))
  1822. {
  1823. // The base already has an extension so use
  1824. // it as-is.
  1825. CopyString(DebugName, Base, DIMA(DebugName));
  1826. }
  1827. else if (Characteristics & IMAGE_FILE_DLL)
  1828. {
  1829. CopyString(DebugName, Base, DIMA(DebugName));
  1830. CatString(DebugName, ".dll", DIMA(DebugName));
  1831. }
  1832. else
  1833. {
  1834. CopyString(DebugName, Base, DIMA(DebugName));
  1835. CatString(DebugName, ".exe", DIMA(DebugName));
  1836. }
  1837. Succ = TRUE;
  1838. }
  1839. }
  1840. }
  1841. Finish:
  1842. //
  1843. // Now lets pick the name we want :
  1844. //
  1845. PCHAR RetName;
  1846. if (SearchExportFirst)
  1847. {
  1848. RetName = ExportName[0] ? ExportName : DebugName;
  1849. }
  1850. else
  1851. {
  1852. RetName = DebugName[0] ? DebugName : ExportName;
  1853. }
  1854. CatString(Name, RetName, NameSize);
  1855. free(SecHdr);
  1856. return Succ;
  1857. }
  1858. BOOL
  1859. GetModnameFromImage(ProcessInfo* Process,
  1860. ULONG64 BaseOfDll,
  1861. HANDLE File,
  1862. LPSTR Name,
  1863. ULONG NameSize,
  1864. BOOL SearchExportFirst)
  1865. {
  1866. BOOL Status = GetModnameFromImageInternal(Process, BaseOfDll, NULL, Name,
  1867. NameSize, SearchExportFirst);
  1868. if (!Status && File != NULL)
  1869. {
  1870. Status = GetModnameFromImageInternal(Process, BaseOfDll, File, Name,
  1871. NameSize, SearchExportFirst);
  1872. }
  1873. return Status;
  1874. }
  1875. BOOL
  1876. GetHeaderInfo(IN ProcessInfo* Process,
  1877. IN ULONG64 BaseOfDll,
  1878. OUT LPDWORD CheckSum,
  1879. OUT LPDWORD TimeDateStamp,
  1880. OUT LPDWORD SizeOfImage)
  1881. {
  1882. IMAGE_NT_HEADERS32 Hdrs32;
  1883. IMAGE_DOS_HEADER DosHdr;
  1884. ULONG64 Address;
  1885. DWORD Sig;
  1886. *CheckSum = UNKNOWN_CHECKSUM;
  1887. *TimeDateStamp = UNKNOWN_TIMESTAMP;
  1888. *SizeOfImage = 0;
  1889. if (!Process)
  1890. {
  1891. return FALSE;
  1892. }
  1893. Address = BaseOfDll;
  1894. if (!ReadImageData( Process, Address, NULL, &DosHdr, sizeof(DosHdr) ))
  1895. {
  1896. return FALSE;
  1897. }
  1898. if (DosHdr.e_magic == IMAGE_DOS_SIGNATURE)
  1899. {
  1900. Address += DosHdr.e_lfanew;
  1901. }
  1902. if (!ReadImageData( Process, Address, NULL, &Sig, sizeof(Sig) ))
  1903. {
  1904. return FALSE;
  1905. }
  1906. if (Sig != IMAGE_NT_SIGNATURE)
  1907. {
  1908. IMAGE_FILE_HEADER FileHdr;
  1909. if (!ReadImageData( Process, Address, NULL,
  1910. &FileHdr, sizeof(FileHdr) ))
  1911. {
  1912. return FALSE;
  1913. }
  1914. *CheckSum = 0;
  1915. *TimeDateStamp = FileHdr.TimeDateStamp;
  1916. *SizeOfImage = 0;
  1917. return TRUE;
  1918. }
  1919. // Attempt to read as a 32bit header, then reread if the image
  1920. // type is 64bit. This works because IMAGE_FILE_HEADER, which is
  1921. // at the start of the IMAGE_NT_HEADERS, is the same on 32bit NT
  1922. // and 64bit NT and IMAGE_NT_HEADER32 <= IMAGE_NT_HEADER64.
  1923. if (!ReadImageData( Process, Address, NULL, &Hdrs32, sizeof(Hdrs32) ))
  1924. {
  1925. return FALSE;
  1926. }
  1927. if (IsImageMachineType64(Hdrs32.FileHeader.Machine))
  1928. {
  1929. // Image is 64bit. Reread as a 64bit structure.
  1930. IMAGE_NT_HEADERS64 Hdrs64;
  1931. if (!ReadImageData( Process, Address, NULL, &Hdrs64, sizeof(Hdrs64) ))
  1932. {
  1933. return FALSE;
  1934. }
  1935. *CheckSum = Hdrs64.OptionalHeader.CheckSum;
  1936. *TimeDateStamp = Hdrs64.FileHeader.TimeDateStamp;
  1937. *SizeOfImage = Hdrs64.OptionalHeader.SizeOfImage;
  1938. }
  1939. else
  1940. {
  1941. *CheckSum = Hdrs32.OptionalHeader.CheckSum;
  1942. *TimeDateStamp = Hdrs32.FileHeader.TimeDateStamp;
  1943. *SizeOfImage = Hdrs32.OptionalHeader.SizeOfImage;
  1944. }
  1945. return TRUE;
  1946. }