Source code of Windows XP (NT5)
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.

3101 lines
83 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Symbol-handling routines.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #include <stddef.h>
  10. #include <cvconst.h>
  11. #include <common.ver>
  12. typedef struct _EXAMINE_INFO
  13. {
  14. BOOL Verbose;
  15. } EXAMINE_INFO, *PEXAMINE_INFO;
  16. LPSTR g_SymbolSearchPath;
  17. LPSTR g_ExecutableImageSearchPath;
  18. // Symbol options that require symbol reloading to take effect.
  19. #define RELOAD_SYM_OPTIONS \
  20. (SYMOPT_UNDNAME | SYMOPT_NO_CPP | SYMOPT_DEFERRED_LOADS | \
  21. SYMOPT_LOAD_LINES | SYMOPT_IGNORE_CVREC | SYMOPT_LOAD_ANYTHING | \
  22. SYMOPT_EXACT_SYMBOLS)
  23. ULONG g_SymOptions = SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME |
  24. SYMOPT_NO_CPP | SYMOPT_OMAP_FIND_NEAREST |
  25. SYMOPT_DEFERRED_LOADS;
  26. CHAR g_SymBuffer[SYM_BUFFER_SIZE];
  27. CHAR g_SymStartBuffer[SYM_BUFFER_SIZE];
  28. PIMAGEHLP_SYMBOL64 g_Sym = (PIMAGEHLP_SYMBOL64) g_SymBuffer;
  29. PIMAGEHLP_SYMBOL64 g_SymStart = (PIMAGEHLP_SYMBOL64) g_SymStartBuffer;
  30. ULONG g_NumUnloadedModules;
  31. PSTR g_DmtNameDescs[DMT_NAME_COUNT] =
  32. {
  33. "Loaded symbol image file", "Symbol file", "Mapped memory image file",
  34. "Image path",
  35. };
  36. DEBUG_SCOPE g_ScopeBuffer;
  37. void
  38. RefreshAllModules(void)
  39. {
  40. PPROCESS_INFO Process;
  41. // Force all loaded symbols to be unloaded so that symbols will
  42. // be reloaded with any updated settings.
  43. for (Process = g_ProcessHead;
  44. Process != NULL;
  45. Process = Process->Next)
  46. {
  47. PDEBUG_IMAGE_INFO Image;
  48. for (Image = Process->ImageHead;
  49. Image != NULL;
  50. Image = Image->Next)
  51. {
  52. SymUnloadModule64(Process->Handle, Image->BaseOfImage);
  53. ClearStoredTypes(Image->BaseOfImage);
  54. if (!SymLoadModule64(Process->Handle,
  55. Image->File,
  56. PrepareImagePath(Image->ImagePath),
  57. Image->ModuleName,
  58. Image->BaseOfImage,
  59. Image->SizeOfImage))
  60. {
  61. ErrOut("Unable to reload %s\n", Image->ModuleName);
  62. }
  63. }
  64. }
  65. }
  66. void
  67. SetSymOptions(ULONG Options)
  68. {
  69. ULONG OldOptions = g_SymOptions;
  70. g_SymOptions = Options;
  71. SymSetOptions(g_SymOptions);
  72. NotifyChangeSymbolState(DEBUG_CSS_SYMBOL_OPTIONS, g_SymOptions, NULL);
  73. if ((OldOptions ^ g_SymOptions) & RELOAD_SYM_OPTIONS)
  74. {
  75. RefreshAllModules();
  76. }
  77. }
  78. BOOL
  79. IsImageMachineType64(DWORD MachineType)
  80. {
  81. switch (MachineType)
  82. {
  83. case IMAGE_FILE_MACHINE_AXP64:
  84. case IMAGE_FILE_MACHINE_IA64:
  85. case IMAGE_FILE_MACHINE_AMD64:
  86. return TRUE;
  87. default:
  88. return FALSE;
  89. }
  90. }
  91. ULONG64
  92. GetRegValIA64(
  93. PCROSS_PLATFORM_CONTEXT Context,
  94. PDEBUG_STACK_FRAME Frame,
  95. ULONG RegID
  96. )
  97. {
  98. ULONGLONG Registers[96+2];
  99. ULONGLONG RegisterHome = Frame->FrameOffset;
  100. ULONG RegisterCount;
  101. ULONG RegisterNumber;
  102. ULONG ReadLength;
  103. ULONG i;
  104. if (Frame->FrameNumber = 0)
  105. {
  106. RegisterCount = (ULONG) Context->IA64Context.StIFS & 0x7f;
  107. }
  108. else
  109. {
  110. RegisterCount = 96;
  111. }
  112. // Sanity.
  113. if (RegisterCount > 96)
  114. {
  115. return g_Machine->GetReg64(RegID);
  116. }
  117. if (RegisterHome & 3)
  118. {
  119. return g_Machine->GetReg64(RegID);
  120. }
  121. if ((RegID >= INTR32) && (RegID < INTR32 + RegisterCount))
  122. {
  123. //
  124. // Read only what we have to
  125. //
  126. RegisterCount = RegID - INTR32 + 1;
  127. //
  128. // Calculate the number of registers to read from the
  129. // RSE stack. For every 63 registers there will be at
  130. // at least one NaT collection register, depending on
  131. // where we start, there may be another one.
  132. //
  133. // First, starting at the current BSP, if we cross a 64 (0x40)
  134. // boundry, then we have an extra.
  135. //
  136. ReadLength = (((((ULONG)Frame->FrameOffset) >> 3) & 0x1f) +
  137. RegisterCount) >> 6;
  138. //
  139. // Add 1 for every 63 registers.
  140. //
  141. ReadLength = (RegisterCount / 63) + RegisterCount;
  142. ReadLength *= sizeof(ULONGLONG);
  143. //
  144. // Read the registers for this frame.
  145. //
  146. if (!SwReadMemory(g_CurrentProcess->Handle,
  147. RegisterHome,
  148. Registers,
  149. ReadLength,
  150. &i))
  151. {
  152. //
  153. // This shouldn't have happened.
  154. //
  155. return g_Machine->GetReg64(RegID);
  156. }
  157. return Registers[RegID - INTR32];
  158. }
  159. else
  160. {
  161. return g_Machine->GetReg64(RegID);
  162. }
  163. if (RegisterCount == 0)
  164. {
  165. //
  166. // Not much point doing anything in this case.
  167. //
  168. return g_Machine->GetReg64(RegID);
  169. }
  170. //
  171. // Note: the following code should be altered to understand
  172. // NaTs as they come from the register stack (currently
  173. // it ignores them).
  174. //
  175. RegisterNumber = 32;
  176. }
  177. ULONG64
  178. GetScopeRegVal(ULONG RegId)
  179. {
  180. PDEBUG_SCOPE Scope = GetCurrentScope();
  181. if (g_EffMachine == IMAGE_FILE_MACHINE_IA64)
  182. {
  183. switch (RegId)
  184. {
  185. case INTSP:
  186. return Scope->Frame.StackOffset;
  187. case RSBSP:
  188. return Scope->Frame.FrameOffset;
  189. default:
  190. // continue
  191. ;
  192. }
  193. CROSS_PLATFORM_CONTEXT Context;
  194. Context = g_Machine->m_Context;
  195. return GetRegValIA64(&Context, &Scope->Frame, RegId);
  196. }
  197. else if (g_EffMachine == IMAGE_FILE_MACHINE_I386)
  198. {
  199. switch (RegId)
  200. {
  201. case X86_EBP:
  202. if (Scope->Frame.FuncTableEntry)
  203. {
  204. PFPO_DATA FpoData = (PFPO_DATA)Scope->Frame.FuncTableEntry;
  205. if (FpoData->cbFrame == FRAME_FPO)
  206. {
  207. //
  208. // Get EBP from FPO data, if available
  209. //
  210. if (SAVE_EBP(&Scope->Frame))
  211. {
  212. return SAVE_EBP(&Scope->Frame);
  213. }
  214. else
  215. {
  216. //
  217. // Guess the ebp value, in most cases for FPO frames its
  218. // a DWORD off frameoffset
  219. //
  220. return Scope->Frame.FrameOffset + sizeof(DWORD);
  221. }
  222. }
  223. }
  224. return Scope->Frame.FrameOffset;
  225. case X86_ESP:
  226. return Scope->Frame.StackOffset;
  227. default:
  228. // continue
  229. ;
  230. }
  231. }
  232. return g_Machine->GetReg64(RegId);
  233. }
  234. /*
  235. * TranslateAddress
  236. * Flags Flags returned by dbghelp
  237. * Address IN Address returned by dbghelp
  238. * OUT Address of symbol
  239. * Value Value of the symbol if its in register
  240. *
  241. */
  242. BOOL
  243. TranslateAddress(
  244. IN ULONG Flags,
  245. IN ULONG RegId,
  246. IN OUT PULONG64 Address,
  247. OUT PULONG64 Value
  248. )
  249. {
  250. PCROSS_PLATFORM_CONTEXT ScopeContext = GetCurrentScopeContext();
  251. if (ScopeContext)
  252. {
  253. g_Machine->PushContext(ScopeContext);
  254. }
  255. if (Flags & SYMF_REGREL)
  256. {
  257. ULONG64 RegContent;
  258. if (RegId)
  259. {
  260. RegContent = GetScopeRegVal(RegId);
  261. }
  262. else if (Value)
  263. {
  264. //
  265. // *Value has RegID and *Address has Offset
  266. //
  267. RegContent = GetScopeRegVal(RegId = (ULONG) *Value);
  268. }
  269. else
  270. {
  271. DBG_ASSERT(FALSE);
  272. if (ScopeContext)
  273. {
  274. g_Machine->PopContext();
  275. }
  276. return FALSE;
  277. }
  278. *Address = RegContent + ((LONG64) (LONG) (ULONG) *Address);
  279. #if 0
  280. // This is now adjusted in GetScopeRegVal
  281. if (g_EffMachine == IMAGE_FILE_MACHINE_I386 &&
  282. RegId == X86_EBP)
  283. {
  284. PDEBUG_SCOPE Scope = GetCurrentScope();
  285. PFPO_DATA pFpoData = (PFPO_DATA)Scope->Frame.FuncTableEntry;
  286. if (pFpoData &&
  287. (pFpoData->cbFrame == FRAME_FPO ||
  288. pFpoData->cbFrame == FRAME_TRAP))
  289. {
  290. // Compensate for FPO's not having ebp
  291. *Address += sizeof(DWORD);
  292. }
  293. }
  294. #endif
  295. }
  296. else if (Flags & SYMF_REGISTER)
  297. {
  298. if (Value)
  299. {
  300. if (RegId)
  301. {
  302. *Value = GetScopeRegVal(RegId);
  303. }
  304. else
  305. {
  306. *Value = GetScopeRegVal((ULONG) *Address);
  307. }
  308. }
  309. }
  310. else if (Flags & SYMF_FRAMEREL)
  311. {
  312. PDEBUG_SCOPE Scope = GetCurrentScope();
  313. if (Scope->Frame.FrameOffset)
  314. {
  315. *Address += Scope->Frame.FrameOffset;
  316. PFPO_DATA pFpoData = (PFPO_DATA)Scope->Frame.FuncTableEntry;
  317. if (g_EffMachine == IMAGE_FILE_MACHINE_I386 &&
  318. pFpoData &&
  319. (pFpoData->cbFrame == FRAME_FPO ||
  320. pFpoData->cbFrame == FRAME_TRAP))
  321. {
  322. // Compensate for FPO's not having ebp
  323. *Address += sizeof(DWORD);
  324. }
  325. }
  326. else
  327. {
  328. ADDR FP;
  329. g_Machine->GetFP(&FP);
  330. FP.flat = (LONG64) FP.flat + *Address;
  331. *Address = FP.flat;
  332. }
  333. }
  334. if (ScopeContext)
  335. {
  336. g_Machine->PopContext();
  337. }
  338. return TRUE;
  339. }
  340. void
  341. GetSymbolStdCall(ULONG64 Offset,
  342. PCHAR Buffer,
  343. ULONG BufferLen,
  344. PULONG64 Displacement,
  345. PUSHORT StdCallParams
  346. )
  347. {
  348. IMAGEHLP_MODULE64 Mod;
  349. // Assert that we have at least a minimum amount of space.
  350. DBG_ASSERT(BufferLen >= sizeof(Mod.ModuleName));
  351. Buffer[BufferLen - 1] = 0;
  352. // In the past symbolic information would report the
  353. // size of stdcall arguments, thus the StdCallParams argument
  354. // could be filled out. Nowadays we do not have access
  355. // to this information so just set it to 0xffff, which
  356. // means unknown. In the future perhaps this can be
  357. // turned back on.
  358. if (StdCallParams != NULL)
  359. {
  360. *StdCallParams = 0xffff;
  361. }
  362. Mod.SizeOfStruct = sizeof(Mod);
  363. // SymGetModuleInfo does special things with a -1 offset,
  364. // so just assume there's never a symbol there and skip the call.
  365. if (Offset != -1 &&
  366. SymGetModuleInfo64(g_CurrentProcess->Handle, Offset, &Mod))
  367. {
  368. if (SymGetSymFromAddr64(g_CurrentProcess->Handle, Offset,
  369. Displacement, g_Sym))
  370. {
  371. if (*Displacement == (ULONG64)-1)
  372. {
  373. // In some BBT cases dbghelp can tell that an offset
  374. // is associated with a particular symbol but it
  375. // doesn't have a valid offset. Present the symbol
  376. // but in a way that makes it clear that it's
  377. // this special case.
  378. _snprintf(Buffer, BufferLen - 1,
  379. "%s!%s <PERF> (%s+0x%I64x)",
  380. Mod.ModuleName, g_Sym->Name,
  381. Mod.ModuleName, (Offset - Mod.BaseOfImage));
  382. *Displacement = 0;
  383. }
  384. else
  385. {
  386. _snprintf(Buffer, BufferLen - 1,
  387. "%s!%s", Mod.ModuleName, g_Sym->Name);
  388. }
  389. return;
  390. }
  391. else
  392. {
  393. if (Offset >= Mod.BaseOfImage &&
  394. Offset <= Mod.BaseOfImage + Mod.ImageSize)
  395. {
  396. strcpy(Buffer, Mod.ModuleName);
  397. *Displacement = Offset - Mod.BaseOfImage;
  398. return;
  399. }
  400. }
  401. }
  402. ULONG64 FscBase;
  403. // XXX drewb - Temporary hack so that stack traces
  404. // show meaningful symbols for the fast system call
  405. // code stuck in the shared user data area.
  406. switch(IsInFastSyscall(Offset, &FscBase))
  407. {
  408. case FSC_FOUND:
  409. strcpy(Buffer, "*SharedUserSystemCall");
  410. *Displacement = Offset - FscBase;
  411. return;
  412. }
  413. *Buffer = 0;
  414. *Displacement = Offset;
  415. }
  416. BOOL
  417. GetNearSymbol(
  418. ULONG64 Offset,
  419. PSTR Buffer,
  420. ULONG BufferLen,
  421. PULONG64 Disp,
  422. LONG Delta
  423. )
  424. {
  425. IMAGEHLP_MODULE64 Mod;
  426. // Assert that we have at least a minimum amount of space.
  427. DBG_ASSERT(BufferLen >= sizeof(Mod.ModuleName));
  428. Buffer[BufferLen - 1] = 0;
  429. Mod.SizeOfStruct = sizeof(Mod);
  430. // SymGetModuleInfo does special things with a -1 offset,
  431. // so just assume there's never a symbol there and skip the call.
  432. if (Offset != -1 &&
  433. SymGetModuleInfo64(g_CurrentProcess->Handle, Offset, &Mod))
  434. {
  435. if (SymGetSymFromAddr64(g_CurrentProcess->Handle, Offset, Disp, g_Sym))
  436. {
  437. if (Delta < 0)
  438. {
  439. while (Delta++ < 0)
  440. {
  441. if (!SymGetSymPrev(g_CurrentProcess->Handle, g_Sym))
  442. {
  443. return FALSE;
  444. }
  445. }
  446. if (Disp != NULL)
  447. {
  448. *Disp = Offset - g_Sym->Address;
  449. }
  450. }
  451. else if (Delta > 0)
  452. {
  453. while (Delta-- > 0)
  454. {
  455. if (!SymGetSymNext(g_CurrentProcess->Handle, g_Sym))
  456. {
  457. return FALSE;
  458. }
  459. }
  460. if (Disp != NULL)
  461. {
  462. *Disp = g_Sym->Address - Offset;
  463. }
  464. }
  465. _snprintf(Buffer, BufferLen - 1,
  466. "%s!%s", Mod.ModuleName, g_Sym->Name);
  467. return TRUE;
  468. }
  469. else if (Delta == 0 &&
  470. Offset >= Mod.BaseOfImage &&
  471. Offset <= Mod.BaseOfImage + Mod.ImageSize)
  472. {
  473. strcpy(Buffer, Mod.ModuleName);
  474. if (Disp != NULL)
  475. {
  476. *Disp = Offset - Mod.BaseOfImage;
  477. }
  478. return TRUE;
  479. }
  480. }
  481. return FALSE;
  482. }
  483. PDEBUG_IMAGE_INFO
  484. GetImageByIndex(PPROCESS_INFO Process, ULONG Index)
  485. {
  486. PDEBUG_IMAGE_INFO Image = Process->ImageHead;
  487. while (Index > 0 && Image != NULL)
  488. {
  489. Index--;
  490. Image = Image->Next;
  491. }
  492. return Image;
  493. }
  494. PDEBUG_IMAGE_INFO
  495. GetImageByOffset(PPROCESS_INFO Process, ULONG64 Offset)
  496. {
  497. PDEBUG_IMAGE_INFO Image = Process->ImageHead;
  498. while (Image != NULL &&
  499. (Offset < Image->BaseOfImage ||
  500. Offset >= Image->BaseOfImage + Image->SizeOfImage))
  501. {
  502. Image = Image->Next;
  503. }
  504. return Image;
  505. }
  506. PDEBUG_IMAGE_INFO
  507. GetImageByName(PPROCESS_INFO Process, PCSTR Name, INAME Which)
  508. {
  509. PDEBUG_IMAGE_INFO Image = Process->ImageHead;
  510. while (Image != NULL)
  511. {
  512. PCSTR WhichStr;
  513. switch(Which)
  514. {
  515. case INAME_IMAGE_PATH:
  516. WhichStr = Image->ImagePath;
  517. break;
  518. case INAME_IMAGE_PATH_TAIL:
  519. WhichStr = PathTail(Image->ImagePath);
  520. break;
  521. case INAME_MODULE:
  522. if (Image->OriginalModuleName[0] &&
  523. !_stricmp(Image->OriginalModuleName, Name))
  524. {
  525. return Image;
  526. }
  527. WhichStr = Image->ModuleName;
  528. break;
  529. }
  530. if (_stricmp(WhichStr, Name) == 0)
  531. {
  532. break;
  533. }
  534. Image = Image->Next;
  535. }
  536. return Image;
  537. }
  538. #define IMAGE_IS_PATTERN ((PDEBUG_IMAGE_INFO)-1)
  539. PDEBUG_IMAGE_INFO
  540. ParseModuleName(PBOOL ModSpecified)
  541. {
  542. PSTR CmdSaved = g_CurCmd;
  543. CHAR Name[MAX_MODULE];
  544. PSTR Dst = Name;
  545. CHAR ch;
  546. BOOL HasWild = FALSE;
  547. // first, parse out a possible module name, either a '*' or
  548. // a string of 'A'-'Z', 'a'-'z', '0'-'9', '_', '~' (or null)
  549. ch = PeekChar();
  550. g_CurCmd++;
  551. while ((ch >= 'A' && ch <= 'Z') ||
  552. (ch >= 'a' && ch <= 'z') ||
  553. (ch >= '0' && ch <= '9') ||
  554. ch == '_' || ch == '~' || ch == '*' || ch == '?')
  555. {
  556. if (ch == '*' || ch == '?')
  557. {
  558. HasWild = TRUE;
  559. }
  560. *Dst++ = ch;
  561. ch = *g_CurCmd++;
  562. }
  563. *Dst = '\0';
  564. g_CurCmd--;
  565. // if no '!' after name and white space, then no module specified
  566. // restore text pointer and treat as null module (PC current)
  567. if (PeekChar() == '!')
  568. {
  569. g_CurCmd++;
  570. }
  571. else
  572. {
  573. g_CurCmd = CmdSaved;
  574. Name[0] = '\0';
  575. }
  576. // Name either has: '*' for all modules,
  577. // '\0' for current module,
  578. // nonnull string for module name.
  579. *ModSpecified = Name[0] != 0;
  580. if (HasWild)
  581. {
  582. return IMAGE_IS_PATTERN;
  583. }
  584. else if (Name[0])
  585. {
  586. return GetImageByName(g_CurrentProcess, Name, INAME_MODULE);
  587. }
  588. else
  589. {
  590. return NULL;
  591. }
  592. }
  593. BOOL CALLBACK
  594. ParseExamineSymbolInfo(
  595. PSYMBOL_INFO SymInfo,
  596. ULONG Size,
  597. PVOID ExamineInfoArg
  598. )
  599. {
  600. PEXAMINE_INFO ExamineInfo = (PEXAMINE_INFO)ExamineInfoArg;
  601. ULONG64 Address = SymInfo->Address;
  602. PDEBUG_IMAGE_INFO Image;
  603. Image = GetImageByOffset(g_CurrentProcess, SymInfo->ModBase);
  604. if (Image && ((SymInfo->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) == 0))
  605. {
  606. dprintf( "%s %s!%s",
  607. FormatAddr64(Address),
  608. Image->ModuleName,
  609. SymInfo->Name);
  610. }
  611. else
  612. {
  613. ULONG64 Value = 0;
  614. TranslateAddress(SymInfo->Flags, SymInfo->Register,
  615. &Address, &Value);
  616. dprintf( "%s %s",
  617. FormatAddr64(Address),
  618. SymInfo->Name);
  619. }
  620. if (ExamineInfo->Verbose)
  621. {
  622. dprintf(" ");
  623. ShowSymbolInfo(SymInfo);
  624. }
  625. dprintf("\n");
  626. return !CheckUserInterrupt();
  627. }
  628. /*** ParseExamine - parse and execute examine command
  629. *
  630. * Purpose:
  631. * Parse the current command string and examine the symbol
  632. * table to display the appropriate entries. The entries
  633. * are displayed in increasing string order. This function
  634. * accepts underscores, alphabetic, and numeric characters
  635. * to match as well as the special characters '?', '*', '['-']'.
  636. *
  637. * Input:
  638. * g_CurCmd - pointer to current command string
  639. *
  640. * Output:
  641. * offset and string name of symbols displayed
  642. *
  643. *************************************************************************/
  644. void
  645. ParseExamine(void)
  646. {
  647. CHAR StringBuf[MAX_SYMBOL_LEN];
  648. UCHAR ch;
  649. PSTR String = StringBuf;
  650. PSTR Start;
  651. PSTR ModEnd;
  652. BOOL ModSpecified;
  653. ULONG64 Base = 0;
  654. ULONG Count;
  655. PDEBUG_IMAGE_INFO Image;
  656. EXAMINE_INFO ExamineInfo;
  657. // Get module pointer from name in command line (<string>!).
  658. PeekChar();
  659. Start = g_CurCmd;
  660. Image = ParseModuleName(&ModSpecified);
  661. ModEnd = g_CurCmd;
  662. ch = PeekChar();
  663. // Special case the command "x <pattern>!" to dump out the module table.
  664. if (Image == IMAGE_IS_PATTERN &&
  665. (ch == ';' || ch == '\0'))
  666. {
  667. *(ModEnd - 1) = 0;
  668. _strupr(Start);
  669. DumpModuleTable(DMT_STANDARD, Start);
  670. return;
  671. }
  672. if (ModSpecified)
  673. {
  674. if (Image == NULL)
  675. {
  676. // The user specified a module that doesn't exist.
  677. error(VARDEF);
  678. }
  679. else if (Image == IMAGE_IS_PATTERN)
  680. {
  681. // The user gave a pattern string for the module
  682. // so we need to pass it on for dbghelp to scan with.
  683. memcpy(String, Start, (ModEnd - Start));
  684. String += ModEnd - Start;
  685. }
  686. else
  687. {
  688. // A specific image was given and found so
  689. // confine the search to that one image.
  690. Base = Image->BaseOfImage;
  691. }
  692. }
  693. g_CurCmd++;
  694. // Condense leading underscores into a "_#"
  695. // that will match zero or more underscores. This causes all
  696. // underscore-prefixed symbols to match the base symbol name
  697. // when the pattern is prefixed by an underscore.
  698. if (ch == '_')
  699. {
  700. *String++ = '_';
  701. *String++ = '#';
  702. do
  703. {
  704. ch = *g_CurCmd++;
  705. } while (ch == '_');
  706. }
  707. ch = (UCHAR)toupper(ch);
  708. while (ch && ch != ';' && ch != ' ')
  709. {
  710. *String++ = ch;
  711. ch = (CHAR)toupper(*g_CurCmd);
  712. g_CurCmd++;
  713. }
  714. *String = '\0';
  715. g_CurCmd--;
  716. ExamineInfo.Verbose = TRUE;
  717. // We nee the scope for all cases since param values are displayed for
  718. // function in scope
  719. RequireCurrentScope();
  720. SymEnumSymbols(g_CurrentProcess->Handle,
  721. Base,
  722. StringBuf,
  723. ParseExamineSymbolInfo,
  724. &ExamineInfo);
  725. }
  726. /*** fnListNear - function to list symbols near an address
  727. *
  728. * Purpose:
  729. * from the address specified, access the symbol table to
  730. * find the closest symbolic addresses both before and after
  731. * it. output these on one line (if spaces permits).
  732. *
  733. * Input:
  734. * addrstart - address to base listing
  735. *
  736. * Output:
  737. * symbolic and absolute addresses of variable on or before
  738. * and after the specified address
  739. *
  740. *************************************************************************/
  741. void
  742. fnListNear(ULONG64 AddrStart)
  743. {
  744. ULONG64 Displacement;
  745. IMAGEHLP_MODULE64 Mod;
  746. if (g_SrcOptions & SRCOPT_LIST_LINE)
  747. {
  748. OutputLineAddr(AddrStart);
  749. }
  750. if (SymGetSymFromAddr64(g_CurrentProcess->Handle, AddrStart,
  751. &Displacement, g_Sym))
  752. {
  753. Mod.SizeOfStruct = sizeof(Mod);
  754. if (!SymGetModuleInfo64(g_CurrentProcess->Handle, AddrStart, &Mod))
  755. {
  756. return;
  757. }
  758. dprintf("(%s) %s!%s",
  759. FormatAddr64(g_Sym->Address),
  760. Mod.ModuleName,
  761. g_Sym->Name);
  762. if (Displacement)
  763. {
  764. dprintf("+0x%s ", FormatDisp64(Displacement));
  765. }
  766. else
  767. {
  768. dprintf(" ");
  769. }
  770. if (SymGetSymNext64(g_CurrentProcess->Handle, g_Sym))
  771. {
  772. dprintf("| (%s) %s!%s",
  773. FormatAddr64(g_Sym->Address),
  774. Mod.ModuleName,
  775. g_Sym->Name);
  776. }
  777. dprintf("\n");
  778. }
  779. }
  780. void
  781. DumpModuleTable(ULONG Flags, PSTR Pattern)
  782. {
  783. PDEBUG_IMAGE_INFO Image;
  784. IMAGEHLP_MODULE64 mi;
  785. DBH_MODSYMINFO SymFile;
  786. ULONG i;
  787. if (g_TargetMachine->m_Ptr64)
  788. {
  789. dprintf("start end module name\n");
  790. }
  791. else
  792. {
  793. dprintf("start end module name\n");
  794. }
  795. Image = g_CurrentProcess->ImageHead;
  796. while (Image)
  797. {
  798. ULONG PrimaryName;
  799. PSTR Names[DMT_NAME_COUNT];
  800. if (Pattern != NULL &&
  801. !MatchPattern(Image->ModuleName, Pattern))
  802. {
  803. Image = Image->Next;
  804. continue;
  805. }
  806. mi.SizeOfStruct = sizeof(mi);
  807. if (!SymGetModuleInfo64( g_CurrentProcess->Handle,
  808. Image->BaseOfImage, &mi ))
  809. {
  810. mi.SymType = SymNone;
  811. }
  812. if (Flags & (DMT_SYM_FILE_NAME | DMT_VERBOSE))
  813. {
  814. SymFile.function = dbhModSymInfo;
  815. SymFile.sizeofstruct = sizeof(SymFile);
  816. SymFile.addr = Image->BaseOfImage;
  817. if (!dbghelp(g_CurrentProcess->Handle, &SymFile))
  818. {
  819. sprintf(SymFile.file, "<Error: %s>",
  820. FormatStatusCode(WIN32_LAST_STATUS()));
  821. }
  822. }
  823. else
  824. {
  825. SymFile.file[0] = 0;
  826. }
  827. Names[DMT_NAME_SYM_IMAGE] = mi.LoadedImageName;
  828. Names[DMT_NAME_SYM_FILE] = SymFile.file;
  829. Names[DMT_NAME_MAPPED_IMAGE] = Image->MappedImagePath;
  830. Names[DMT_NAME_IMAGE_PATH] = Image->ImagePath;
  831. if (Flags & DMT_SYM_FILE_NAME)
  832. {
  833. PrimaryName = DMT_NAME_SYM_FILE;
  834. }
  835. else if (Flags & DMT_MAPPED_IMAGE_NAME)
  836. {
  837. PrimaryName = DMT_NAME_MAPPED_IMAGE;
  838. }
  839. else if (Flags & DMT_IMAGE_PATH_NAME)
  840. {
  841. PrimaryName = DMT_NAME_IMAGE_PATH;
  842. }
  843. else
  844. {
  845. PrimaryName = DMT_NAME_SYM_IMAGE;
  846. }
  847. //
  848. // Skip modules filtered by flags
  849. //
  850. if ((Flags & DMT_ONLY_LOADED_SYMBOLS) &&
  851. (mi.SymType == SymDeferred))
  852. {
  853. Image = Image->Next;
  854. continue;
  855. }
  856. if (IS_KERNEL_TARGET())
  857. {
  858. if ((Flags & DMT_ONLY_USER_SYMBOLS) &&
  859. (Image->BaseOfImage >= g_SystemRangeStart))
  860. {
  861. Image = Image->Next;
  862. continue;
  863. }
  864. if ((Flags & DMT_ONLY_KERNEL_SYMBOLS) &&
  865. (Image->BaseOfImage <= g_SystemRangeStart))
  866. {
  867. Image = Image->Next;
  868. continue;
  869. }
  870. }
  871. _strlwr( Image->ModuleName );
  872. dprintf( "%s %s %-8s ",
  873. FormatAddr64(Image->BaseOfImage),
  874. FormatAddr64(Image->BaseOfImage + Image->SizeOfImage),
  875. Image->ModuleName
  876. );
  877. if (Flags & DMT_NO_SYMBOL_OUTPUT)
  878. {
  879. goto SkipSymbolOutput;
  880. }
  881. if (PrimaryName == DMT_NAME_MAPPED_IMAGE ||
  882. PrimaryName == DMT_NAME_IMAGE_PATH)
  883. {
  884. dprintf(" %s\n",
  885. *Names[PrimaryName] ? Names[PrimaryName] : "<none>");
  886. goto SkipSymbolOutput;
  887. }
  888. switch (Image->GoodCheckSum)
  889. {
  890. case DII_GOOD_CHECKSUM:
  891. dprintf( " " );
  892. break;
  893. case DII_UNKNOWN_TIMESTAMP:
  894. dprintf( "T " );
  895. break;
  896. case DII_UNKNOWN_CHECKSUM:
  897. dprintf( "C " );
  898. break;
  899. case DII_BAD_CHECKSUM:
  900. dprintf( "# " );
  901. break;
  902. }
  903. if (mi.SymType == SymDeferred)
  904. {
  905. dprintf( "(deferred) " );
  906. }
  907. else if (mi.SymType == SymNone)
  908. {
  909. dprintf( "(no symbolic information) " );
  910. }
  911. else
  912. {
  913. switch ( mi.SymType )
  914. {
  915. case SymCoff:
  916. dprintf( "(coff symbols) " );
  917. break;
  918. case SymCv:
  919. dprintf( "(codeview symbols) " );
  920. break;
  921. case SymPdb:
  922. dprintf( "(pdb symbols) " );
  923. break;
  924. case SymExport:
  925. dprintf( "(export symbols) " );
  926. break;
  927. }
  928. dprintf("%s", *Names[PrimaryName] ? Names[PrimaryName] : "<none>");
  929. }
  930. dprintf("\n");
  931. SkipSymbolOutput:
  932. if (Flags & DMT_VERBOSE)
  933. {
  934. for (i = 0; i < DMT_NAME_COUNT; i++)
  935. {
  936. if (i != PrimaryName && *Names[i])
  937. {
  938. dprintf(" %s: %s\n", g_DmtNameDescs[i], Names[i]);
  939. }
  940. }
  941. }
  942. if (Flags & (DMT_VERBOSE | DMT_IMAGE_TIMESTAMP))
  943. {
  944. LPSTR TimeDateStr = TimeToStr(Image->TimeDateStamp);
  945. dprintf(" Checksum: %08X Timestamp: %s (%08X)\n",
  946. Image->CheckSum, TimeDateStr, Image->TimeDateStamp);
  947. }
  948. if (Flags & DMT_VERBOSE)
  949. {
  950. VS_FIXEDFILEINFO FixedVer;
  951. if (g_Target->GetImageVersionInformation
  952. (Image->ImagePath, Image->BaseOfImage, "\\",
  953. &FixedVer, sizeof(FixedVer), NULL) == S_OK)
  954. {
  955. char Item[64];
  956. char VerString[128];
  957. dprintf(" File version: %d.%d.%d.%d"
  958. " Product version: %d.%d.%d.%d\n",
  959. FixedVer.dwFileVersionMS >> 16,
  960. FixedVer.dwFileVersionMS & 0xFFFF,
  961. FixedVer.dwFileVersionLS >> 16,
  962. FixedVer.dwFileVersionLS & 0xFFFF,
  963. FixedVer.dwProductVersionMS >> 16,
  964. FixedVer.dwProductVersionMS & 0xFFFF,
  965. FixedVer.dwProductVersionLS >> 16,
  966. FixedVer.dwProductVersionLS & 0xFFFF);
  967. dprintf(" File flags: %X (Mask %X) File OS: %X "
  968. "File type: %X.%X\n",
  969. FixedVer.dwFileFlags & FixedVer.dwFileFlagsMask,
  970. FixedVer.dwFileFlagsMask, FixedVer.dwFileOS,
  971. FixedVer.dwFileType, FixedVer.dwFileSubtype);
  972. dprintf(" File date: %08X.%08X\n",
  973. FixedVer.dwFileDateMS, FixedVer.dwFileDateLS);
  974. sprintf(Item, "\\StringFileInfo\\%04x%04x\\FileVersion",
  975. VER_VERSION_TRANSLATION);
  976. if (SUCCEEDED(g_Target->GetImageVersionInformation
  977. (Image->ImagePath, Image->BaseOfImage, Item,
  978. VerString, sizeof(VerString), NULL)))
  979. {
  980. dprintf(" Version string: %s\n", VerString);
  981. }
  982. }
  983. }
  984. if (CheckUserInterrupt())
  985. {
  986. break;
  987. }
  988. Image = Image->Next;
  989. }
  990. UnloadedModuleInfo* Unl;
  991. if ((Flags & (DMT_ONLY_LOADED_SYMBOLS | DMT_ONLY_USER_SYMBOLS)) == 0)
  992. {
  993. ULONG LumFlags = LUM_OUTPUT;
  994. LumFlags |= ((Flags & DMT_VERBOSE) ? LUM_OUTPUT_VERBOSE : 0);
  995. LumFlags |= ((Flags & DMT_IMAGE_TIMESTAMP) ? LUM_OUTPUT_TIMESTAMP : 0);
  996. dprintf("\n");
  997. ListUnloadedModules(LumFlags, Pattern);
  998. }
  999. }
  1000. void
  1001. ParseDumpModuleTable(void)
  1002. {
  1003. ULONG Flags = DMT_STANDARD;
  1004. char Pattern[MAX_MODULE];
  1005. PSTR Pat = NULL;
  1006. g_CurCmd++;
  1007. for (;;)
  1008. {
  1009. // skip white space
  1010. while (isspace(*g_CurCmd))
  1011. {
  1012. g_CurCmd++;
  1013. }
  1014. if (*g_CurCmd == 'f')
  1015. {
  1016. Flags = (Flags & ~DMT_NAME_FLAGS) | DMT_IMAGE_PATH_NAME;
  1017. g_CurCmd++;
  1018. }
  1019. else if (*g_CurCmd == 'i')
  1020. {
  1021. Flags = (Flags & ~DMT_NAME_FLAGS) | DMT_SYM_IMAGE_FILE_NAME;
  1022. g_CurCmd++;
  1023. }
  1024. else if (*g_CurCmd == 'l')
  1025. {
  1026. Flags |= DMT_ONLY_LOADED_SYMBOLS;
  1027. g_CurCmd++;
  1028. }
  1029. else if (*g_CurCmd == 'm')
  1030. {
  1031. g_CurCmd++;
  1032. // skip white space
  1033. while (isspace(*g_CurCmd))
  1034. {
  1035. g_CurCmd++;
  1036. }
  1037. Pat = Pattern;
  1038. while (*g_CurCmd && !isspace(*g_CurCmd))
  1039. {
  1040. if ((Pat - Pattern) < sizeof(Pattern) - 1)
  1041. {
  1042. *Pat++ = *g_CurCmd;
  1043. }
  1044. g_CurCmd++;
  1045. }
  1046. *Pat = 0;
  1047. Pat = Pattern;
  1048. _strupr(Pat);
  1049. }
  1050. else if (*g_CurCmd == 'p')
  1051. {
  1052. Flags = (Flags & ~DMT_NAME_FLAGS) | DMT_MAPPED_IMAGE_NAME;
  1053. g_CurCmd++;
  1054. }
  1055. else if (*g_CurCmd == 't')
  1056. {
  1057. Flags = (Flags & ~(DMT_NAME_FLAGS)) | DMT_NAME_SYM_IMAGE | DMT_IMAGE_TIMESTAMP
  1058. | DMT_NO_SYMBOL_OUTPUT;
  1059. g_CurCmd++;
  1060. }
  1061. else if (*g_CurCmd == 'v')
  1062. {
  1063. Flags |= DMT_VERBOSE;
  1064. g_CurCmd++;
  1065. }
  1066. else if (IS_KERNEL_TARGET())
  1067. {
  1068. if (*g_CurCmd == 'u')
  1069. {
  1070. Flags |= DMT_ONLY_USER_SYMBOLS;
  1071. g_CurCmd++;
  1072. }
  1073. else if (*g_CurCmd == 'k')
  1074. {
  1075. Flags |= DMT_ONLY_KERNEL_SYMBOLS;
  1076. g_CurCmd++;
  1077. }
  1078. else
  1079. {
  1080. break;
  1081. }
  1082. }
  1083. else
  1084. {
  1085. break;
  1086. }
  1087. }
  1088. DumpModuleTable(Flags, Pat);
  1089. }
  1090. void
  1091. GetCurrentMemoryOffsets (
  1092. PULONG64 pMemoryLow,
  1093. PULONG64 pMemoryHigh
  1094. )
  1095. {
  1096. *pMemoryLow = (ULONG64)(LONG64)-1; // default value for no source
  1097. }
  1098. ULONG
  1099. ReadImageData(
  1100. ULONG64 Address,
  1101. HANDLE hFile,
  1102. LPVOID Buffer,
  1103. ULONG Size
  1104. )
  1105. {
  1106. if (hFile)
  1107. {
  1108. ULONG Result;
  1109. if (!SetFilePointer( hFile, (ULONG)Address, NULL, FILE_BEGIN ))
  1110. {
  1111. return 0;
  1112. }
  1113. if (!ReadFile( hFile, Buffer, Size, &Result, NULL))
  1114. {
  1115. return 0;
  1116. }
  1117. }
  1118. else
  1119. {
  1120. ULONG Result;
  1121. if (g_Target->ReadVirtual(Address, Buffer, Size, &Result) != S_OK ||
  1122. Result < Size)
  1123. {
  1124. return 0;
  1125. }
  1126. }
  1127. return Size;
  1128. }
  1129. BOOL
  1130. GetModnameFromImageInternal(ULONG64 BaseOfDll,
  1131. HANDLE hFile,
  1132. LPSTR lpName,
  1133. ULONG NameSize
  1134. )
  1135. {
  1136. IMAGE_DEBUG_DIRECTORY DebugDir;
  1137. PIMAGE_DEBUG_MISC pMisc;
  1138. PIMAGE_DEBUG_MISC pT;
  1139. DWORD rva;
  1140. int nDebugDirs;
  1141. int i;
  1142. int j;
  1143. int l;
  1144. BOOL rVal = FALSE;
  1145. PVOID pExeName;
  1146. IMAGE_DOS_HEADER dh;
  1147. USHORT NumberOfSections;
  1148. USHORT Characteristics;
  1149. ULONG64 address;
  1150. DWORD sig;
  1151. PIMAGE_SECTION_HEADER pSH = NULL;
  1152. DWORD cb;
  1153. NTSTATUS Status;
  1154. ULONG Result;
  1155. IMAGE_NT_HEADERS64 nh64;
  1156. PIMAGE_NT_HEADERS32 pnh32 = (PIMAGE_NT_HEADERS32) &nh64;
  1157. BOOL fCheckDllExtensionInExportTable = FALSE;
  1158. lpName[0] = 0;
  1159. if (hFile)
  1160. {
  1161. BaseOfDll = 0;
  1162. }
  1163. address = BaseOfDll;
  1164. ReadImageData( address, hFile, &dh, sizeof(dh) );
  1165. if (dh.e_magic == IMAGE_DOS_SIGNATURE)
  1166. {
  1167. address += dh.e_lfanew;
  1168. }
  1169. ReadImageData( address, hFile, &sig, sizeof(sig) );
  1170. if (sig != IMAGE_NT_SIGNATURE)
  1171. {
  1172. IMAGE_FILE_HEADER fh;
  1173. IMAGE_ROM_OPTIONAL_HEADER rom;
  1174. ReadImageData( address, hFile, &fh, sizeof(IMAGE_FILE_HEADER) );
  1175. address += sizeof(IMAGE_FILE_HEADER);
  1176. ReadImageData( address, hFile, &rom, sizeof(rom) );
  1177. address += sizeof(rom);
  1178. if (rom.Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC)
  1179. {
  1180. NumberOfSections = fh.NumberOfSections;
  1181. Characteristics = fh.Characteristics;
  1182. nDebugDirs = rva = 0;
  1183. }
  1184. else
  1185. {
  1186. goto Finish;
  1187. }
  1188. }
  1189. else
  1190. {
  1191. //
  1192. // read the head as a 64 bit header and cast it appropriately.
  1193. //
  1194. ReadImageData( address, hFile, &nh64, sizeof(nh64) );
  1195. if (IsImageMachineType64(pnh32->FileHeader.Machine))
  1196. {
  1197. address += sizeof(IMAGE_NT_HEADERS64);
  1198. NumberOfSections = nh64.FileHeader.NumberOfSections;
  1199. Characteristics = nh64.FileHeader.Characteristics;
  1200. nDebugDirs = nh64.OptionalHeader.
  1201. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
  1202. sizeof(IMAGE_DEBUG_DIRECTORY);
  1203. rva = nh64.OptionalHeader.
  1204. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  1205. }
  1206. else
  1207. {
  1208. address += sizeof(IMAGE_NT_HEADERS32);
  1209. NumberOfSections = pnh32->FileHeader.NumberOfSections;
  1210. Characteristics = pnh32->FileHeader.Characteristics;
  1211. nDebugDirs = pnh32->OptionalHeader.
  1212. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
  1213. sizeof(IMAGE_DEBUG_DIRECTORY);
  1214. rva = pnh32->OptionalHeader.
  1215. DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  1216. }
  1217. }
  1218. // After this point, none of the image datastructures have changed between
  1219. // 32bit NT and 64bit NT.
  1220. cb = NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER;
  1221. pSH = (PIMAGE_SECTION_HEADER)malloc( cb );
  1222. if (!pSH)
  1223. {
  1224. goto Finish;
  1225. }
  1226. if (!ReadImageData( address, hFile, pSH, cb ))
  1227. {
  1228. goto Finish;
  1229. }
  1230. if (!nDebugDirs)
  1231. {
  1232. goto CheckExportTable;
  1233. }
  1234. for (i = 0; i < NumberOfSections; i++)
  1235. {
  1236. if (rva >= pSH[i].VirtualAddress &&
  1237. rva < pSH[i].VirtualAddress + pSH[i].SizeOfRawData)
  1238. {
  1239. break;
  1240. }
  1241. }
  1242. if (i >= NumberOfSections)
  1243. {
  1244. goto CheckExportTable;
  1245. }
  1246. rva = rva - pSH[i].VirtualAddress;
  1247. if (hFile)
  1248. {
  1249. rva += pSH[i].PointerToRawData;
  1250. }
  1251. else
  1252. {
  1253. rva += pSH[i].VirtualAddress;
  1254. }
  1255. for (j = 0; j < nDebugDirs; j++)
  1256. {
  1257. ReadImageData( rva + (sizeof(DebugDir) * j) + BaseOfDll,
  1258. hFile, &DebugDir, sizeof(DebugDir) );
  1259. if (DebugDir.Type == IMAGE_DEBUG_TYPE_MISC)
  1260. {
  1261. l = DebugDir.SizeOfData;
  1262. pMisc = pT = (PIMAGE_DEBUG_MISC)malloc(l);
  1263. if (!pMisc)
  1264. {
  1265. break;
  1266. }
  1267. if (!hFile &&
  1268. ((ULONG)DebugDir.AddressOfRawData < pSH[i].VirtualAddress ||
  1269. (ULONG)DebugDir.AddressOfRawData >=
  1270. pSH[i].VirtualAddress + pSH[i].SizeOfRawData))
  1271. {
  1272. //
  1273. // the misc debug data MUST be in the .rdata section
  1274. // otherwise the debugger cannot access it as it is not
  1275. // mapped in.
  1276. //
  1277. break;
  1278. }
  1279. if (hFile)
  1280. {
  1281. address = DebugDir.PointerToRawData;
  1282. }
  1283. else
  1284. {
  1285. address = DebugDir.AddressOfRawData + BaseOfDll;
  1286. }
  1287. ReadImageData( address, hFile, pMisc, l );
  1288. while (l > 0)
  1289. {
  1290. if (pMisc->DataType != IMAGE_DEBUG_MISC_EXENAME)
  1291. {
  1292. //
  1293. // beware corrupt images:
  1294. //
  1295. if (pMisc->Length == 0 ||
  1296. pMisc->Length > (ULONG)l)
  1297. {
  1298. break;
  1299. }
  1300. l -= pMisc->Length;
  1301. pMisc = (PIMAGE_DEBUG_MISC)
  1302. (((LPSTR)pMisc) + pMisc->Length);
  1303. }
  1304. else
  1305. {
  1306. pExeName = (PVOID)&pMisc->Data[ 0 ];
  1307. if (!pMisc->Unicode)
  1308. {
  1309. strncat(lpName, (LPSTR)pExeName, NameSize - 1);
  1310. rVal = TRUE;
  1311. }
  1312. else
  1313. {
  1314. WideCharToMultiByte(CP_ACP,
  1315. 0,
  1316. (LPWSTR)pExeName,
  1317. -1,
  1318. lpName,
  1319. NameSize,
  1320. NULL,
  1321. NULL);
  1322. rVal = TRUE;
  1323. }
  1324. //
  1325. // Undo stevewo's error
  1326. //
  1327. if (_stricmp(&lpName[strlen(lpName) - 4], ".DBG") == 0)
  1328. {
  1329. char rgchPath[MAX_IMAGE_PATH];
  1330. char rgchBase[_MAX_FNAME];
  1331. _splitpath(lpName, NULL, rgchPath, rgchBase, NULL);
  1332. if (strlen(rgchPath) == 4)
  1333. {
  1334. rgchPath[strlen(rgchPath) - 1] = 0;
  1335. strcpy(lpName, rgchBase);
  1336. strcat(lpName, ".");
  1337. strcat(lpName, rgchPath);
  1338. }
  1339. else if (Characteristics & IMAGE_FILE_DLL)
  1340. {
  1341. strcpy(lpName, rgchBase);
  1342. strcat(lpName, ".dll");
  1343. }
  1344. else
  1345. {
  1346. strcpy(lpName, rgchBase);
  1347. strcat(lpName, ".exe");
  1348. }
  1349. }
  1350. break;
  1351. }
  1352. }
  1353. free(pT);
  1354. break;
  1355. }
  1356. else if ((DebugDir.Type == IMAGE_DEBUG_TYPE_CODEVIEW) &&
  1357. ((!hFile && DebugDir.AddressOfRawData) ||
  1358. (hFile && DebugDir.PointerToRawData)) &&
  1359. (DebugDir.SizeOfData > sizeof(NB10IH)))
  1360. {
  1361. DWORD Signature;
  1362. char rgchPath[MAX_IMAGE_PATH];
  1363. char rgchBase[_MAX_FNAME];
  1364. // Mapped CV info. Read the data and see what the content is.
  1365. if (hFile)
  1366. {
  1367. address = DebugDir.PointerToRawData;
  1368. }
  1369. else
  1370. {
  1371. address = DebugDir.AddressOfRawData + BaseOfDll;
  1372. }
  1373. if (!ReadImageData( address, hFile, &Signature,
  1374. sizeof(Signature) ))
  1375. {
  1376. break;
  1377. }
  1378. // NB10 or PDB7 signature?
  1379. if (Signature == NB10_SIG ||
  1380. Signature == RSDS_SIG)
  1381. {
  1382. ULONG HdrSize = Signature == NB10_SIG ?
  1383. sizeof(NB10IH) : sizeof(RSDSIH);
  1384. address += HdrSize;
  1385. if ((DebugDir.SizeOfData - sizeof(HdrSize)) > MAX_PATH)
  1386. {
  1387. // Something's wrong here. The record should only contain
  1388. // a MAX_PATH path name.
  1389. break;
  1390. }
  1391. if (DebugDir.SizeOfData - HdrSize > NameSize)
  1392. {
  1393. break;
  1394. }
  1395. if (!ReadImageData(address, hFile, lpName,
  1396. DebugDir.SizeOfData - HdrSize))
  1397. {
  1398. break;
  1399. }
  1400. _splitpath(lpName, NULL, rgchPath, rgchBase, NULL);
  1401. // Files are sometimes generated with .pdb appended
  1402. // to the image name rather than replacing the extension
  1403. // of the image name, such as foo.exe.pdb.
  1404. // splitpath only takes off the outermost extension,
  1405. // so check and see if the base already has an extension
  1406. // we recognize.
  1407. PSTR Ext = strrchr(rgchBase, '.');
  1408. if (Ext != NULL &&
  1409. (!strcmp(Ext, ".exe") || !strcmp(Ext, ".dll") ||
  1410. !strcmp(Ext, ".sys")))
  1411. {
  1412. // The base already has an extension so use
  1413. // it as-is.
  1414. strcpy(lpName, rgchBase);
  1415. fCheckDllExtensionInExportTable = !strcmp(Ext, ".dll");
  1416. }
  1417. else if (Characteristics & IMAGE_FILE_DLL)
  1418. {
  1419. strcpy(lpName, rgchBase);
  1420. strcat(lpName, ".dll");
  1421. fCheckDllExtensionInExportTable = TRUE;
  1422. }
  1423. else
  1424. {
  1425. strcpy(lpName, rgchBase);
  1426. strcat(lpName, ".exe");
  1427. }
  1428. rVal = TRUE;
  1429. }
  1430. }
  1431. }
  1432. if (!rVal || fCheckDllExtensionInExportTable)
  1433. {
  1434. CHAR Char;
  1435. ULONG64 ExportNameRva;
  1436. char FileName[MAX_IMAGE_PATH];
  1437. int x;
  1438. ExportNameRva = 0;
  1439. CheckExportTable:
  1440. // No luck wandering the debug info. Try the export table.
  1441. if (IsImageMachineType64(pnh32->FileHeader.Machine))
  1442. {
  1443. rva = nh64.OptionalHeader.
  1444. DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  1445. }
  1446. else
  1447. {
  1448. rva = pnh32->OptionalHeader.
  1449. DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  1450. }
  1451. if (!rva)
  1452. {
  1453. goto Finish;
  1454. }
  1455. for (i = 0; i < NumberOfSections; i++)
  1456. {
  1457. if (rva >= pSH[i].VirtualAddress &&
  1458. rva < pSH[i].VirtualAddress + pSH[i].SizeOfRawData)
  1459. {
  1460. break;
  1461. }
  1462. }
  1463. if (i >= NumberOfSections)
  1464. {
  1465. goto Finish;
  1466. }
  1467. if (hFile)
  1468. {
  1469. rva = rva - pSH[i].VirtualAddress + pSH[i].PointerToRawData;
  1470. }
  1471. if (!ReadImageData( rva + offsetof(IMAGE_EXPORT_DIRECTORY, Name) +
  1472. BaseOfDll, hFile, &ExportNameRva, sizeof(DWORD)))
  1473. {
  1474. goto Finish;
  1475. }
  1476. if (hFile)
  1477. {
  1478. ExportNameRva = ExportNameRva - pSH[i].VirtualAddress +
  1479. pSH[i].PointerToRawData;
  1480. }
  1481. ExportNameRva += BaseOfDll;
  1482. rVal = TRUE;
  1483. x = 0;
  1484. do
  1485. {
  1486. if (!ReadImageData( ExportNameRva,
  1487. hFile, &Char, sizeof(Char)))
  1488. {
  1489. rVal = FALSE;
  1490. break;
  1491. }
  1492. ExportNameRva++;
  1493. FileName[x] = Char;
  1494. x++;
  1495. } while (Char && (x < sizeof(FileName)));
  1496. if (fCheckDllExtensionInExportTable)
  1497. {
  1498. char rgchExtFromExportTable[_MAX_EXT];
  1499. _splitpath(FileName, NULL, NULL, NULL, rgchExtFromExportTable);
  1500. if (_stricmp(rgchExtFromExportTable, ".dll"))
  1501. {
  1502. // Export table has something different.
  1503. // Use it with our base name.
  1504. strcpy(lpName + strlen(lpName) - 4,
  1505. rgchExtFromExportTable);
  1506. }
  1507. }
  1508. else
  1509. {
  1510. lpName[0] = 0;
  1511. strncat(lpName, FileName, NameSize - 1);
  1512. }
  1513. }
  1514. Finish:
  1515. if (pSH)
  1516. {
  1517. free(pSH);
  1518. }
  1519. return rVal;
  1520. }
  1521. BOOL
  1522. GetModnameFromImage(ULONG64 BaseOfDll,
  1523. HANDLE hFile,
  1524. LPSTR lpName,
  1525. ULONG NameSize)
  1526. {
  1527. BOOL Status = GetModnameFromImageInternal( BaseOfDll, NULL,
  1528. lpName, NameSize );
  1529. if (!Status && hFile != NULL)
  1530. {
  1531. Status = GetModnameFromImageInternal( BaseOfDll, hFile,
  1532. lpName, NameSize );
  1533. }
  1534. return Status;
  1535. }
  1536. BOOL
  1537. GetHeaderInfo(
  1538. IN ULONG64 BaseOfDll,
  1539. OUT LPDWORD CheckSum,
  1540. OUT LPDWORD TimeDateStamp,
  1541. OUT LPDWORD SizeOfImage
  1542. )
  1543. {
  1544. IMAGE_NT_HEADERS32 nh32;
  1545. IMAGE_DOS_HEADER dh;
  1546. ULONG64 address;
  1547. DWORD sig;
  1548. address = BaseOfDll;
  1549. ReadImageData( address, NULL, &dh, sizeof(dh) );
  1550. if (dh.e_magic == IMAGE_DOS_SIGNATURE) {
  1551. address += dh.e_lfanew;
  1552. }
  1553. ReadImageData( address, NULL, &sig, sizeof(sig) );
  1554. if (sig != IMAGE_NT_SIGNATURE) {
  1555. IMAGE_FILE_HEADER fh;
  1556. ReadImageData( address, NULL, &fh, sizeof(IMAGE_FILE_HEADER) );
  1557. *CheckSum = 0;
  1558. *TimeDateStamp = fh.TimeDateStamp;
  1559. *SizeOfImage = 0;
  1560. return TRUE;
  1561. }
  1562. // Attempt to read as a 32bit header, then reread if the image type is 64bit.
  1563. // This works because IMAGE_FILE_HEADER, which is at the start of the IMAGE_NT_HEADERS,
  1564. // is the same on 32bit NT and 64bit NT and IMAGE_NT_HEADER32 <= IMAGE_NT_HEADER64.
  1565. ReadImageData( address, NULL, &nh32, sizeof(nh32) );
  1566. if (IsImageMachineType64(nh32.FileHeader.Machine)) {
  1567. // Image is 64bit. Reread as a 64bit structure.
  1568. IMAGE_NT_HEADERS64 nh64;
  1569. ReadImageData( address, NULL, &nh64, sizeof(nh64) );
  1570. *CheckSum = nh64.OptionalHeader.CheckSum;
  1571. *TimeDateStamp = nh64.FileHeader.TimeDateStamp;
  1572. *SizeOfImage = nh64.OptionalHeader.SizeOfImage;
  1573. }
  1574. else {
  1575. *CheckSum = nh32.OptionalHeader.CheckSum;
  1576. *TimeDateStamp = nh32.FileHeader.TimeDateStamp;
  1577. *SizeOfImage = nh32.OptionalHeader.SizeOfImage;
  1578. }
  1579. return TRUE;
  1580. }
  1581. PCSTR
  1582. PrependPrefixToSymbol( char PrefixedString[],
  1583. PCSTR pString,
  1584. PCSTR *RegString
  1585. )
  1586. {
  1587. if ( RegString )
  1588. {
  1589. *RegString = NULL;
  1590. }
  1591. PCSTR bangPtr;
  1592. int bang = '!';
  1593. PCSTR Tail;
  1594. bangPtr = strchr( pString, bang );
  1595. if ( bangPtr )
  1596. {
  1597. Tail = bangPtr + 1;
  1598. }
  1599. else
  1600. {
  1601. Tail = pString;
  1602. }
  1603. if ( strncmp( Tail, g_Machine->m_SymPrefix, g_Machine->m_SymPrefixLen ) )
  1604. {
  1605. ULONG Loc = (ULONG)(Tail - pString);
  1606. if (Loc > 0)
  1607. {
  1608. memcpy( PrefixedString, pString, Loc );
  1609. }
  1610. memcpy( PrefixedString + Loc, g_Machine->m_SymPrefix,
  1611. g_Machine->m_SymPrefixLen );
  1612. if ( RegString )
  1613. {
  1614. *RegString = &PrefixedString[Loc];
  1615. }
  1616. Loc += g_Machine->m_SymPrefixLen;
  1617. strcpy( &PrefixedString[Loc], Tail );
  1618. return PrefixedString;
  1619. }
  1620. else
  1621. {
  1622. return pString;
  1623. }
  1624. }
  1625. BOOL
  1626. ForceSymbolCodeAddress(PSYMBOL_INFO Symbol, MachineInfo* Machine)
  1627. {
  1628. ULONG64 Code = Symbol->Address;
  1629. if (Symbol->Flags & SYMF_FORWARDER)
  1630. {
  1631. char Fwd[2 * MAX_PATH];
  1632. ULONG Read;
  1633. PSTR Sep;
  1634. // The address of a forwarder entry points to the
  1635. // string name of the function that things are forwarded
  1636. // to. Look up that name and try to get the address
  1637. // from it.
  1638. if (g_Target->ReadVirtual(Symbol->Address, Fwd, sizeof(Fwd),
  1639. &Read) != S_OK ||
  1640. Read < 2)
  1641. {
  1642. ErrOut("Unable to read forwarder string\n");
  1643. return FALSE;
  1644. }
  1645. Fwd[sizeof(Fwd) - 1] = 0;
  1646. if (!(Sep = strchr(Fwd, '.')))
  1647. {
  1648. ErrOut("Unable to read forwarder string\n");
  1649. return FALSE;
  1650. }
  1651. *Sep = '!';
  1652. if (GetOffsetFromSym(Fwd, &Code, NULL) != 1)
  1653. {
  1654. ErrOut("Unable to get address of forwarder '%s'\n", Fwd);
  1655. return FALSE;
  1656. }
  1657. }
  1658. else if (Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_IA64 &&
  1659. (Symbol->Flags & SYMF_EXPORT))
  1660. {
  1661. // On IA64 the export entries contain the address
  1662. // of the plabel. We want the actual code address
  1663. // so resolve the plabel to its code.
  1664. if (!Machine->GetPrefixedSymbolOffset(Symbol->Address,
  1665. GETPREF_VERBOSE,
  1666. &Code))
  1667. {
  1668. return FALSE;
  1669. }
  1670. }
  1671. Symbol->Address = Code;
  1672. return TRUE;
  1673. }
  1674. /*** GetOffsetFromSym - return offset from symbol specified
  1675. *
  1676. * Purpose:
  1677. * external routine.
  1678. * With the specified symbol, set the pointer to
  1679. * its offset. The variable chSymbolSuffix may
  1680. * be used to append a character to repeat the search
  1681. * if it first fails.
  1682. *
  1683. * Input:
  1684. * pString - pointer to input symbol
  1685. *
  1686. * Output:
  1687. * pOffset - pointer to offset to be set
  1688. *
  1689. * Returns:
  1690. * BOOL value of success
  1691. *
  1692. *************************************************************************/
  1693. #ifndef _DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1694. extern "C" {
  1695. BOOL
  1696. IMAGEAPI
  1697. SymSetSymWithAddr64(
  1698. IN HANDLE hProcess,
  1699. IN DWORD64 qwAddr,
  1700. IN LPSTR SymString,
  1701. OUT PIMAGEHLP_SYMBOL64 Symbol
  1702. );
  1703. }
  1704. #endif // ! _DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1705. BOOL
  1706. GetOffsetFromMod(
  1707. PCSTR pString,
  1708. PULONG64 pOffset
  1709. )
  1710. {
  1711. if (!strchr(pString, '!'))
  1712. {
  1713. // Could be a module name
  1714. PDEBUG_IMAGE_INFO pImage = g_CurrentProcess->ImageHead;
  1715. while (pImage)
  1716. {
  1717. if (!_stricmp(pString, &pImage->ModuleName[0]) ||
  1718. (pImage->OriginalModuleName[0] &&
  1719. !_stricmp(pString, &pImage->OriginalModuleName[0])))
  1720. {
  1721. *pOffset = pImage->BaseOfImage;
  1722. return TRUE;
  1723. }
  1724. pImage = pImage->Next;
  1725. }
  1726. }
  1727. return FALSE;
  1728. }
  1729. BOOL
  1730. IgnoreEnumeratedSymbol(class MachineInfo* Machine,
  1731. PSYMBOL_INFO SymInfo)
  1732. {
  1733. ULONG64 Func;
  1734. //
  1735. // IA64 plabels are publics with the same name
  1736. // as the function they refer to. This causes
  1737. // ambiguity problems as we end up with two
  1738. // hits. The plabel is rarely interesting, though,
  1739. // so just filter them out here so that expressions
  1740. // always evaluate to the function itself.
  1741. //
  1742. if (Machine->m_ExecTypes[0] != IMAGE_FILE_MACHINE_IA64 ||
  1743. SymInfo->Scope != SymTagPublicSymbol ||
  1744. SymInfo->Flags & SYMF_FUNCTION ||
  1745. !Machine->GetPrefixedSymbolOffset(SymInfo->Address, 0, &Func))
  1746. {
  1747. return FALSE;
  1748. }
  1749. PSTR FuncSym;
  1750. __try
  1751. {
  1752. FuncSym = (PSTR)alloca(MAX_SYMBOL_LEN * 2);
  1753. }
  1754. __except(EXCEPTION_EXECUTE_HANDLER)
  1755. {
  1756. FuncSym = NULL;
  1757. }
  1758. if (FuncSym == NULL)
  1759. {
  1760. return FALSE;
  1761. }
  1762. SYMBOL_INFO LocalSymInfo;
  1763. // We have to save and restore the original data as
  1764. // dbghelp always uses a single buffer to store all
  1765. // symbol information. The incoming symbol info
  1766. // is going to be wiped out when we
  1767. // call GetSymbolStdCall.
  1768. LocalSymInfo = *SymInfo;
  1769. strcpy(FuncSym + MAX_SYMBOL_LEN, SymInfo->Name);
  1770. ULONG64 FuncSymDisp;
  1771. GetSymbolStdCall(Func, FuncSym, MAX_SYMBOL_LEN,
  1772. &FuncSymDisp, NULL);
  1773. *SymInfo = LocalSymInfo;
  1774. strcpy(SymInfo->Name, FuncSym + MAX_SYMBOL_LEN);
  1775. return FuncSymDisp == 0 && strstr(FuncSym, SymInfo->Name);
  1776. }
  1777. struct COUNT_SYMBOL_MATCHES
  1778. {
  1779. MachineInfo* Machine;
  1780. SYMBOL_INFO ReturnSymInfo;
  1781. CHAR SymbolNameOverflowBuffer[MAX_SYMBOL_LEN];
  1782. ULONG Matches;
  1783. };
  1784. BOOL CALLBACK
  1785. CountSymbolMatches(
  1786. PSYMBOL_INFO SymInfo,
  1787. ULONG Size,
  1788. PVOID UserContext
  1789. )
  1790. {
  1791. COUNT_SYMBOL_MATCHES* Context =
  1792. (COUNT_SYMBOL_MATCHES*)UserContext;
  1793. if (IgnoreEnumeratedSymbol(Context->Machine, SymInfo))
  1794. {
  1795. return TRUE;
  1796. }
  1797. if (Context->Matches == 1)
  1798. {
  1799. // We already have one match, check if we got a duplicate.
  1800. if ((SymInfo->Address == Context->ReturnSymInfo.Address) &&
  1801. !strcmp(SymInfo->Name, Context->ReturnSymInfo.Name))
  1802. {
  1803. // Looks like the same symbol, ignore it.
  1804. return TRUE;
  1805. }
  1806. }
  1807. Context->ReturnSymInfo = *SymInfo;
  1808. if (SymInfo->NameLen < MAX_SYMBOL_LEN)
  1809. {
  1810. strcpy(Context->ReturnSymInfo.Name, SymInfo->Name);
  1811. }
  1812. Context->Matches++;
  1813. return TRUE;
  1814. }
  1815. ULONG
  1816. MultiSymFromName(IN HANDLE Process,
  1817. IN LPSTR Name,
  1818. IN ULONG64 ImageBase,
  1819. IN MachineInfo* Machine,
  1820. OUT PSYMBOL_INFO Symbol)
  1821. {
  1822. ULONG Matches;
  1823. RequireCurrentScope();
  1824. if (ImageBase == 0)
  1825. {
  1826. if (!SymFromName(Process, Name, Symbol))
  1827. {
  1828. return 0;
  1829. }
  1830. Matches = 1;
  1831. }
  1832. else
  1833. {
  1834. COUNT_SYMBOL_MATCHES Context;
  1835. ULONG MaxName = Symbol->MaxNameLen;
  1836. Context.Machine = Machine;
  1837. Context.ReturnSymInfo = *Symbol;
  1838. if (Symbol->NameLen < MAX_SYMBOL_LEN)
  1839. {
  1840. strcpy(Context.ReturnSymInfo.Name, Symbol->Name);
  1841. }
  1842. Context.Matches = 0;
  1843. SymEnumSymbols(Process, ImageBase, Name,
  1844. CountSymbolMatches, &Context);
  1845. *Symbol = Context.ReturnSymInfo;
  1846. Symbol->MaxNameLen = MaxName;
  1847. if (Symbol->MaxNameLen > Context.ReturnSymInfo.NameLen)
  1848. {
  1849. strcpy(Symbol->Name, Context.ReturnSymInfo.Name);
  1850. }
  1851. Matches = Context.Matches;
  1852. }
  1853. if (Matches == 1 &&
  1854. !ForceSymbolCodeAddress(Symbol, Machine))
  1855. {
  1856. return 0;
  1857. }
  1858. return Matches;
  1859. }
  1860. ULONG
  1861. GetOffsetFromSym(PCSTR String,
  1862. PULONG64 Offset,
  1863. PDEBUG_IMAGE_INFO* Image)
  1864. {
  1865. CHAR ModifiedString[MAX_SYMBOL_LEN + 64];
  1866. CHAR Suffix[2];
  1867. SYMBOL_INFO SymInfo = {0};
  1868. ULONG Count;
  1869. if (Image != NULL)
  1870. {
  1871. *Image = NULL;
  1872. }
  1873. //
  1874. // We can't do anything without a current process.
  1875. //
  1876. if (g_CurrentProcess == NULL)
  1877. {
  1878. return 0;
  1879. }
  1880. if ( strlen(String) == 0 )
  1881. {
  1882. return 0;
  1883. }
  1884. if (GetOffsetFromMod(String, Offset))
  1885. {
  1886. return 1;
  1887. }
  1888. //
  1889. // If a module name was given look up the module
  1890. // and determine the processor type so that the
  1891. // appropriate machine is used for the following
  1892. // machine-specific operations.
  1893. //
  1894. PDEBUG_IMAGE_INFO StrImage;
  1895. ULONG64 ImageBase;
  1896. PCSTR ModSep = strchr(String, '!');
  1897. if (ModSep != NULL)
  1898. {
  1899. ULONG Len = (ULONG)(ModSep - String);
  1900. memcpy(ModifiedString, String, Len);
  1901. ModifiedString[Len] = 0;
  1902. StrImage = GetImageByName(g_CurrentProcess, ModifiedString,
  1903. INAME_MODULE);
  1904. if (Image != NULL)
  1905. {
  1906. *Image = StrImage;
  1907. }
  1908. ImageBase = StrImage ? StrImage->BaseOfImage : 0;
  1909. }
  1910. else
  1911. {
  1912. StrImage = NULL;
  1913. ImageBase = 0;
  1914. }
  1915. MachineInfo* Machine = g_Machine;
  1916. if (StrImage != NULL)
  1917. {
  1918. Machine = MachineTypeInfo(ModuleMachineType(g_CurrentProcess,
  1919. StrImage->BaseOfImage));
  1920. if (Machine == NULL)
  1921. {
  1922. Machine = g_Machine;
  1923. }
  1924. }
  1925. if ( g_PrefixSymbols && Machine->m_SymPrefix != NULL )
  1926. {
  1927. PCSTR PreString;
  1928. PCSTR RegString;
  1929. PreString = PrependPrefixToSymbol( ModifiedString, String,
  1930. &RegString );
  1931. if ( Count =
  1932. MultiSymFromName( g_CurrentProcess->Handle, (PSTR)PreString,
  1933. ImageBase, Machine, &SymInfo ) )
  1934. {
  1935. *Offset = SymInfo.Address;
  1936. goto GotOffsetSuccess;
  1937. }
  1938. if ( (PreString != String) &&
  1939. (Count =
  1940. MultiSymFromName( g_CurrentProcess->Handle, (PSTR)String,
  1941. ImageBase, Machine, &SymInfo ) ) )
  1942. {
  1943. // Ambiguous plabels shouldn't be further resolved,
  1944. // so just return the information for the plabel.
  1945. if (Count > 1)
  1946. {
  1947. *Offset = SymInfo.Address;
  1948. goto GotOffsetSuccess;
  1949. }
  1950. if (Machine->GetPrefixedSymbolOffset(SymInfo.Address,
  1951. GETPREF_VERBOSE,
  1952. Offset))
  1953. {
  1954. #ifndef _DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1955. if ( ! SymSetSymWithAddr64( g_CurrentProcess->Handle,
  1956. *Offset, (PSTR)RegString,
  1957. g_Sym ) )
  1958. {
  1959. DWORD LastError = GetLastError();
  1960. if ( LastError != ERROR_ALREADY_EXISTS )
  1961. {
  1962. ErrOut("GetOffsetFromSym: "
  1963. "%s registration in dbghelp: "
  1964. "FAILED!!!, lerr:0x%lx\n",
  1965. RegString, LastError );
  1966. }
  1967. #endif // !_DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1968. }
  1969. else
  1970. {
  1971. // This symbol doesn't appear to actually
  1972. // be a plabel so just use the symbol address.
  1973. *Offset = SymInfo.Address;
  1974. }
  1975. }
  1976. else
  1977. {
  1978. *Offset = SymInfo.Address;
  1979. }
  1980. goto GotOffsetSuccess;
  1981. }
  1982. }
  1983. else if (Count =
  1984. MultiSymFromName( g_CurrentProcess->Handle, (PSTR)String,
  1985. ImageBase, Machine, &SymInfo ))
  1986. {
  1987. *Offset = SymInfo.Address;
  1988. goto GotOffsetSuccess;
  1989. }
  1990. if (g_SymbolSuffix != 'n')
  1991. {
  1992. strcpy( ModifiedString, String );
  1993. Suffix[0] = g_SymbolSuffix;
  1994. Suffix[1] = '\0';
  1995. strcat( ModifiedString, Suffix );
  1996. if (Count =
  1997. MultiSymFromName( g_CurrentProcess->Handle, ModifiedString,
  1998. ImageBase, Machine, &SymInfo ))
  1999. {
  2000. *Offset = SymInfo.Address;
  2001. goto GotOffsetSuccess;
  2002. }
  2003. }
  2004. return 0;
  2005. GotOffsetSuccess:
  2006. TranslateAddress(SymInfo.Flags, SymInfo.Register, Offset, &SymInfo.Value);
  2007. if (SymInfo.Flags & SYMF_REGISTER)
  2008. {
  2009. *Offset = SymInfo.Value;
  2010. }
  2011. return Count;
  2012. }
  2013. void
  2014. CreateModuleNameFromPath(LPSTR ImagePath, LPSTR ModuleName)
  2015. {
  2016. PSTR Scan;
  2017. ModuleName[0] = 0;
  2018. strncat( ModuleName, PathTail(ImagePath), MAX_MODULE - 1 );
  2019. Scan = strchr( ModuleName, '.' );
  2020. if (Scan != NULL)
  2021. {
  2022. *Scan = '\0';
  2023. }
  2024. }
  2025. void
  2026. GetAdjacentSymOffsets(
  2027. ULONG64 addrStart,
  2028. PULONG64 prevOffset,
  2029. PULONG64 nextOffset
  2030. )
  2031. {
  2032. DWORD64 Displacement;
  2033. //
  2034. // assume failure
  2035. //
  2036. *prevOffset = 0;
  2037. *nextOffset = (ULONG64) -1;
  2038. //
  2039. // get the symbol for the initial address
  2040. //
  2041. if (!SymGetSymFromAddr64( g_CurrentProcess->Handle, addrStart, &Displacement, g_SymStart )) {
  2042. return;
  2043. }
  2044. *prevOffset = g_SymStart->Address;
  2045. if (SymGetSymNext64( g_CurrentProcess->Handle, g_SymStart )) {
  2046. *nextOffset = g_SymStart->Address;
  2047. }
  2048. return;
  2049. }
  2050. BOOL
  2051. SymbolCallbackFunction(
  2052. HANDLE hProcess,
  2053. ULONG ActionCode,
  2054. ULONG64 CallbackData,
  2055. ULONG64 UserContext
  2056. )
  2057. {
  2058. PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl;
  2059. PIMAGEHLP_CBA_READ_MEMORY prm;
  2060. PIMAGEHLP_CBA_EVENT evt;
  2061. PDEBUG_IMAGE_INFO pImage;
  2062. IMAGEHLP_MODULE64 mi;
  2063. PUCHAR p;
  2064. ULONG i;
  2065. ULONG OldSymOptions;
  2066. idsl = (PIMAGEHLP_DEFERRED_SYMBOL_LOAD64) CallbackData;
  2067. switch ( ActionCode )
  2068. {
  2069. case CBA_DEBUG_INFO:
  2070. assert(CallbackData && *(LPSTR)CallbackData);
  2071. dprintf("%s", (LPSTR)CallbackData);
  2072. break;
  2073. case CBA_EVENT:
  2074. evt = (PIMAGEHLP_CBA_EVENT)CallbackData;
  2075. assert(evt);
  2076. if (evt->desc && *evt->desc)
  2077. dprintf("%s", evt->desc);
  2078. break;
  2079. case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
  2080. if (g_EngStatus & (ENG_STATUS_USER_INTERRUPT |
  2081. ENG_STATUS_PENDING_BREAK_IN))
  2082. {
  2083. return TRUE;
  2084. }
  2085. break;
  2086. case CBA_DEFERRED_SYMBOL_LOAD_START:
  2087. pImage = g_CurrentProcess->ImageHead;
  2088. while (pImage)
  2089. {
  2090. if (idsl->BaseOfImage == pImage->BaseOfImage)
  2091. {
  2092. _strlwr( idsl->FileName );
  2093. VerbOut( "Loading symbols for %s %16s -> ",
  2094. FormatAddr64(idsl->BaseOfImage),
  2095. idsl->FileName
  2096. );
  2097. return TRUE;
  2098. }
  2099. pImage = pImage->Next;
  2100. }
  2101. break;
  2102. case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
  2103. if (IS_KERNEL_TARGET() &&
  2104. idsl->SizeOfStruct >= FIELD_OFFSET(IMAGEHLP_DEFERRED_SYMBOL_LOAD,
  2105. Reparse))
  2106. {
  2107. i = 0;
  2108. if (strncmp(idsl->FileName, "dump_", sizeof("dump_")-1) == 0)
  2109. {
  2110. i = sizeof("dump_")-1;
  2111. }
  2112. if (strncmp(idsl->FileName, "hiber_", sizeof("hiber_")-1) == 0)
  2113. {
  2114. i = sizeof("hiber_")-1;
  2115. }
  2116. if (i)
  2117. {
  2118. if (_stricmp (idsl->FileName+i, "scsiport.sys") == 0)
  2119. {
  2120. strcpy (idsl->FileName, "diskdump.sys");
  2121. }
  2122. else
  2123. {
  2124. strcpy(idsl->FileName, idsl->FileName+i);
  2125. }
  2126. idsl->Reparse = TRUE;
  2127. return TRUE;
  2128. }
  2129. }
  2130. if (idsl->FileName && *idsl->FileName)
  2131. {
  2132. VerbOut( "*** Error: could not load symbols for %s\n",
  2133. idsl->FileName );
  2134. }
  2135. else
  2136. {
  2137. VerbOut( "*** Error: could not load symbols [MODNAME UNKNOWN]\n");
  2138. }
  2139. break;
  2140. case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
  2141. pImage = g_CurrentProcess->ImageHead;
  2142. // Do not load unqualified symbols in this callback sine this
  2143. // could result in stack owerflow
  2144. OldSymOptions = SymGetOptions();
  2145. SymSetOptions(OldSymOptions | SYMOPT_NO_UNQUALIFIED_LOADS);
  2146. while (pImage)
  2147. {
  2148. if ((idsl->BaseOfImage == pImage->BaseOfImage) ||
  2149. (pImage->BaseOfImage == 0))
  2150. {
  2151. VerbOut( "%s\n", idsl->FileName );
  2152. pImage->GoodCheckSum = DII_GOOD_CHECKSUM;
  2153. //
  2154. // If we had a 0 timestamp for the image, try to update it
  2155. // from the image since for NT4 - XP, the kernel
  2156. // does not report timestamps in the initial symbol load
  2157. // module
  2158. //
  2159. if (pImage->BaseOfImage &&
  2160. (pImage->TimeDateStamp == 0))
  2161. {
  2162. DWORD CheckSum;
  2163. DWORD TimeDateStamp;
  2164. DWORD SizeOfImage;
  2165. if (GetHeaderInfo(pImage->BaseOfImage,
  2166. &CheckSum,
  2167. &TimeDateStamp,
  2168. &SizeOfImage))
  2169. {
  2170. pImage->TimeDateStamp = TimeDateStamp;
  2171. }
  2172. }
  2173. if ((idsl->TimeDateStamp == 0) ||
  2174. (pImage->TimeDateStamp == 0) ||
  2175. (pImage->TimeDateStamp == UNKNOWN_TIMESTAMP))
  2176. {
  2177. dprintf( "*** WARNING: Unable to verify "
  2178. "timestamp for %s\n", idsl->FileName );
  2179. pImage->GoodCheckSum = DII_UNKNOWN_TIMESTAMP;
  2180. }
  2181. else
  2182. {
  2183. if ((idsl->CheckSum == 0) ||
  2184. (pImage->CheckSum == 0) ||
  2185. (pImage->CheckSum == UNKNOWN_CHECKSUM))
  2186. {
  2187. dprintf( "*** WARNING: Unable to verify "
  2188. "checksum for %s\n", idsl->FileName );
  2189. pImage->GoodCheckSum = DII_UNKNOWN_CHECKSUM;
  2190. }
  2191. else if (idsl->CheckSum != pImage->CheckSum)
  2192. {
  2193. pImage->GoodCheckSum = DII_BAD_CHECKSUM;
  2194. if (g_TargetMachineType == IMAGE_FILE_MACHINE_I386)
  2195. {
  2196. if (IS_USER_TARGET() ||
  2197. g_TargetNumberProcessors == 1)
  2198. {
  2199. //
  2200. // See if this is an MP image with the
  2201. // lock table removed by setup. If
  2202. // it is and the timestamps match, don't
  2203. // print the invalid checksum warning.
  2204. //
  2205. char szFileName[_MAX_FNAME];
  2206. _splitpath(idsl->FileName, NULL, NULL,
  2207. szFileName, NULL);
  2208. if ((!_stricmp(szFileName, "kernel32") ||
  2209. (IS_KERNEL_TARGET() &&
  2210. !_stricmp(szFileName, "win32k")) ||
  2211. !_stricmp(szFileName, "wow32") ||
  2212. !_stricmp(szFileName, "ntvdm") ||
  2213. !_stricmp(szFileName, "ntdll")) &&
  2214. (pImage->TimeDateStamp ==
  2215. idsl->TimeDateStamp))
  2216. {
  2217. pImage->GoodCheckSum = DII_GOOD_CHECKSUM;
  2218. }
  2219. }
  2220. }
  2221. if (pImage->GoodCheckSum == DII_BAD_CHECKSUM)
  2222. {
  2223. //
  2224. // Only print the message if the timestamps
  2225. // are wrong.
  2226. //
  2227. if (pImage->TimeDateStamp != idsl->TimeDateStamp)
  2228. {
  2229. dprintf("*** WARNING: symbols timestamp "
  2230. "is wrong 0x%08x 0x%08x for %s\n",
  2231. pImage->TimeDateStamp,
  2232. idsl->TimeDateStamp,
  2233. idsl->FileName);
  2234. }
  2235. }
  2236. }
  2237. }
  2238. mi.SizeOfStruct = sizeof(mi);
  2239. if (SymGetModuleInfo64( g_CurrentProcess->Handle,
  2240. idsl->BaseOfImage, &mi ))
  2241. {
  2242. if (mi.SymType == SymExport)
  2243. {
  2244. WarnOut("*** ERROR: Symbol file could not be found."
  2245. " Defaulted to export symbols for %s - \n",
  2246. idsl->FileName);
  2247. }
  2248. if (mi.SymType == SymNone)
  2249. {
  2250. WarnOut("*** ERROR: Module load completed but "
  2251. "symbols could not be loaded for %s\n",
  2252. idsl->FileName);
  2253. }
  2254. }
  2255. NotifyChangeSymbolState(DEBUG_CSS_LOADS,
  2256. idsl->BaseOfImage, g_CurrentProcess);
  2257. SymSetOptions(OldSymOptions);
  2258. return TRUE;
  2259. }
  2260. pImage = pImage->Next;
  2261. }
  2262. VerbOut( "\n" );
  2263. NotifyChangeSymbolState(DEBUG_CSS_LOADS,
  2264. idsl->BaseOfImage,
  2265. g_CurrentProcess);
  2266. SymSetOptions(OldSymOptions);
  2267. break;
  2268. case CBA_SYMBOLS_UNLOADED:
  2269. VerbOut( "Symbols unloaded for %s %s\n",
  2270. FormatAddr64(idsl->BaseOfImage),
  2271. idsl->FileName
  2272. );
  2273. break;
  2274. case CBA_READ_MEMORY:
  2275. prm = (PIMAGEHLP_CBA_READ_MEMORY)CallbackData;
  2276. return g_Target->ReadVirtual(prm->addr,
  2277. prm->buf,
  2278. prm->bytes,
  2279. prm->bytesread) == S_OK;
  2280. case CBA_SET_OPTIONS:
  2281. // Symbol options are set through the interface
  2282. // so the debugger generally knows about them
  2283. // already. The only flag that we want to check
  2284. // here is the debug flag since it can be changed
  2285. // through !sym. There is no need to notify
  2286. // about this as it's only an internal flag.
  2287. g_SymOptions = (g_SymOptions & ~SYMOPT_DEBUG) |
  2288. (*(PULONG)CallbackData & SYMOPT_DEBUG);
  2289. break;
  2290. default:
  2291. return FALSE;
  2292. }
  2293. return FALSE;
  2294. }
  2295. BOOL
  2296. ValidatePathComponent(PCSTR Part)
  2297. {
  2298. if (strlen(Part) == 0)
  2299. {
  2300. return FALSE;
  2301. }
  2302. else if (!_strnicmp(Part, "SYMSRV*", 7) ||
  2303. IsUrlPathComponent(Part))
  2304. {
  2305. // No easy way to validate symbol server or URL paths.
  2306. // They're virtually always network references,
  2307. // so just disallow all such usage when net
  2308. // access isn't allowed.
  2309. if (g_EngOptions & DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS)
  2310. {
  2311. return FALSE;
  2312. }
  2313. return TRUE;
  2314. }
  2315. else
  2316. {
  2317. DWORD Attrs;
  2318. DWORD OldMode;
  2319. char Expand[MAX_PATH];
  2320. // Otherwise make sure this is a valid directory.
  2321. if (!ExpandEnvironmentStrings(Part, Expand, sizeof(Expand)))
  2322. {
  2323. return FALSE;
  2324. }
  2325. if (g_EngOptions & DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS)
  2326. {
  2327. // Don't call GetFileAttributes when network paths
  2328. // are disabled as net operations may cause deadlocks.
  2329. if (NetworkPathCheck(Expand) != ERROR_SUCCESS)
  2330. {
  2331. return FALSE;
  2332. }
  2333. }
  2334. // We can still get to this point when debugging CSR
  2335. // if the user has explicitly allowed net paths.
  2336. // This check isn't important enough to risk a hang.
  2337. if (SYSTEM_PROCESSES())
  2338. {
  2339. return TRUE;
  2340. }
  2341. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  2342. Attrs = GetFileAttributes(Expand);
  2343. SetErrorMode(OldMode);
  2344. return Attrs != 0xffffffff && (Attrs & FILE_ATTRIBUTE_DIRECTORY);
  2345. }
  2346. }
  2347. VOID
  2348. FeedSymPath(
  2349. LPSTR pSymbolSearchPath,
  2350. LPSTR raw
  2351. )
  2352. {
  2353. DWORD dw;
  2354. LPSTR rawbuf;
  2355. LPSTR p;
  2356. BOOL bAppend;
  2357. if (!raw)
  2358. {
  2359. return;
  2360. }
  2361. p = strtok(raw, ";");
  2362. while (p)
  2363. {
  2364. bAppend = FALSE;
  2365. // Check and see if this string is already in the path.
  2366. // If it is, don't add it again.
  2367. PSTR Dup = strstr(pSymbolSearchPath, p);
  2368. if (Dup != NULL)
  2369. {
  2370. PSTR DupEnd = Dup + strlen(p);
  2371. if ((Dup == pSymbolSearchPath || Dup[-1] == ';') &&
  2372. (*DupEnd == 0 || *DupEnd == ';'))
  2373. {
  2374. p = strtok(NULL, ";");
  2375. continue;
  2376. }
  2377. }
  2378. bAppend = ValidatePathComponent(p);
  2379. if (bAppend)
  2380. {
  2381. if (*pSymbolSearchPath)
  2382. {
  2383. strcat(pSymbolSearchPath, ";");
  2384. }
  2385. strcat(pSymbolSearchPath, p);
  2386. }
  2387. else
  2388. {
  2389. WarnOut("WARNING: %s is not accessible, ignoring\n", p);
  2390. }
  2391. p = strtok(NULL, ";");
  2392. }
  2393. }
  2394. void
  2395. SetSymbolSearchPath(PPROCESS_INFO Process)
  2396. {
  2397. LPSTR lpExePathEnv;
  2398. size_t cbExePath;
  2399. LPSTR lpSymPathEnv;
  2400. LPSTR lpAltSymPathEnv;
  2401. LPSTR lpSymPath;
  2402. size_t cbSymPath;
  2403. LPSTR NewMem;
  2404. //
  2405. // Load the Binary path (needed for triage dumps)
  2406. //
  2407. // No clue why this or the next is 18 ...
  2408. cbExePath = 18;
  2409. if (g_ExecutableImageSearchPath)
  2410. {
  2411. cbExePath += strlen(g_ExecutableImageSearchPath) + 1;
  2412. }
  2413. if (lpExePathEnv = getenv("_NT_EXECUTABLE_IMAGE_PATH"))
  2414. {
  2415. cbExePath += strlen(lpExePathEnv) + 1;
  2416. }
  2417. NewMem = (char*)realloc(g_ExecutableImageSearchPath, cbExePath);
  2418. if (!NewMem)
  2419. {
  2420. ErrOut("Not enough memory to allocate/initialize "
  2421. "ExecutableImageSearchPath");
  2422. return;
  2423. }
  2424. if (!g_ExecutableImageSearchPath)
  2425. {
  2426. *NewMem = 0;
  2427. }
  2428. g_ExecutableImageSearchPath = NewMem;
  2429. FeedSymPath(g_ExecutableImageSearchPath, lpExePathEnv);
  2430. //
  2431. // Load symbol Path
  2432. //
  2433. cbSymPath = 18;
  2434. if (g_SymbolSearchPath)
  2435. {
  2436. cbSymPath += strlen(g_SymbolSearchPath) + 1;
  2437. }
  2438. if (lpSymPathEnv = getenv("_NT_SYMBOL_PATH"))
  2439. {
  2440. cbSymPath += strlen(lpSymPathEnv) + 1;
  2441. }
  2442. if (lpAltSymPathEnv = getenv("_NT_ALT_SYMBOL_PATH"))
  2443. {
  2444. cbSymPath += strlen(lpAltSymPathEnv) + 1;
  2445. }
  2446. NewMem = (char*)realloc(g_SymbolSearchPath, cbSymPath);
  2447. if (!NewMem)
  2448. {
  2449. ErrOut("Not enough memory to allocate/initialize "
  2450. "SymbolSearchPath");
  2451. return;
  2452. }
  2453. if (!g_SymbolSearchPath)
  2454. {
  2455. *NewMem = 0;
  2456. }
  2457. g_SymbolSearchPath = NewMem;
  2458. FeedSymPath(g_SymbolSearchPath, lpAltSymPathEnv);
  2459. FeedSymPath(g_SymbolSearchPath, lpSymPathEnv);
  2460. SymSetSearchPath( Process->Handle, g_SymbolSearchPath );
  2461. dprintf("Symbol search path is: %s\n",
  2462. *g_SymbolSearchPath ?
  2463. g_SymbolSearchPath :
  2464. "*** Invalid *** : Verify _NT_SYMBOL_PATH setting" );
  2465. if (g_ExecutableImageSearchPath)
  2466. {
  2467. dprintf("Executable search path is: %s\n",
  2468. g_ExecutableImageSearchPath);
  2469. }
  2470. }
  2471. BOOL
  2472. SetCurrentScope(
  2473. IN PDEBUG_STACK_FRAME ScopeFrame,
  2474. IN OPTIONAL PVOID ScopeContext,
  2475. IN ULONG ScopeContextSize
  2476. )
  2477. {
  2478. BOOL ScopeChanged;
  2479. PDEBUG_SCOPE Scope = &g_ScopeBuffer;
  2480. if (Scope->State == ScopeDefaultLazy)
  2481. {
  2482. // Its not a lazy scope now
  2483. Scope->State = ScopeDefault;
  2484. }
  2485. ScopeChanged = SymSetContext(g_CurrentProcess->Handle,
  2486. (PIMAGEHLP_STACK_FRAME) ScopeFrame,
  2487. ScopeContext);
  2488. if (ScopeContext && (sizeof(Scope->Context) >= ScopeContextSize))
  2489. {
  2490. memcpy(&Scope->Context, ScopeContext, ScopeContextSize);
  2491. Scope->ContextState = MCTX_FULL;
  2492. Scope->State = ScopeFromContext;
  2493. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS, DEBUG_ANY_ID);
  2494. }
  2495. Scope->LocalsChanged = ScopeChanged;
  2496. if (ScopeChanged ||
  2497. (ScopeFrame->FrameOffset != Scope->Frame.FrameOffset))
  2498. {
  2499. Scope->Frame = *ScopeFrame;
  2500. Scope->LocalsChanged = TRUE;
  2501. if (ScopeFrame->FuncTableEntry)
  2502. {
  2503. // Cache the FPO data since the pointer is only temporary
  2504. Scope->CachedFpo =
  2505. *((PFPO_DATA) ScopeFrame->FuncTableEntry);
  2506. Scope->Frame.FuncTableEntry =
  2507. (ULONG64) &Scope->CachedFpo;
  2508. }
  2509. NotifyChangeSymbolState(DEBUG_CSS_SCOPE, 0, g_CurrentProcess);
  2510. }
  2511. else
  2512. {
  2513. Scope->Frame = *ScopeFrame;
  2514. if (ScopeFrame->FuncTableEntry)
  2515. {
  2516. // Cache the FPO data since the pointer is only temporary
  2517. Scope->CachedFpo =
  2518. *((PFPO_DATA) ScopeFrame->FuncTableEntry);
  2519. Scope->Frame.FuncTableEntry =
  2520. (ULONG64) &Scope->CachedFpo;
  2521. }
  2522. }
  2523. return ScopeChanged;
  2524. }
  2525. BOOL
  2526. ResetCurrentScopeLazy(void)
  2527. {
  2528. PDEBUG_SCOPE Scope = &g_ScopeBuffer;
  2529. if (Scope->State == ScopeFromContext)
  2530. {
  2531. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS, DEBUG_ANY_ID);
  2532. }
  2533. Scope->State = ScopeDefaultLazy;
  2534. return TRUE;
  2535. }
  2536. BOOL
  2537. ResetCurrentScope(void)
  2538. {
  2539. DEBUG_STACK_FRAME LocalFrame;
  2540. PDEBUG_SCOPE Scope = &g_ScopeBuffer;
  2541. if (Scope->State == ScopeFromContext)
  2542. {
  2543. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS, DEBUG_ANY_ID);
  2544. }
  2545. Scope->State = ScopeDefault;
  2546. ZeroMemory(&LocalFrame, sizeof(LocalFrame));
  2547. // At the initial kernel load the system is only partially
  2548. // initialized and is very sensitive to bad memory reads.
  2549. // Stack traces can cause reads through unusual memory areas
  2550. // so it's best to avoid them at this time. This isn't
  2551. // much of a problem since users don't usually expect a locals
  2552. // context at this point.
  2553. if ((IS_USER_TARGET() ||
  2554. (g_EngStatus & ENG_STATUS_AT_INITIAL_MODULE_LOAD) == 0) &&
  2555. IS_CONTEXT_ACCESSIBLE())
  2556. {
  2557. if (!StackTrace(0, 0, 0, &LocalFrame, 1, 0, 0, TRUE))
  2558. {
  2559. ADDR Addr;
  2560. g_Machine->GetPC(&Addr);
  2561. LocalFrame.InstructionOffset = Addr.off;
  2562. }
  2563. }
  2564. return SetCurrentScope(&LocalFrame, NULL, 0);
  2565. }
  2566. void
  2567. ListUnloadedModules(ULONG Flags, PSTR Pattern)
  2568. {
  2569. UnloadedModuleInfo* Unl;
  2570. g_NumUnloadedModules = 0;
  2571. if (!IS_KERNEL_TARGET())
  2572. {
  2573. return;
  2574. }
  2575. Unl = g_Target->GetUnloadedModuleInfo();
  2576. if (Unl == NULL || Unl->Initialize() != S_OK)
  2577. {
  2578. ErrOut("Unable to examine unloaded module list\n");
  2579. return;
  2580. }
  2581. char UnlName[MAX_UNLOADED_NAME_LENGTH / sizeof(WCHAR) + 1];
  2582. DEBUG_MODULE_PARAMETERS Params;
  2583. if (Flags & LUM_OUTPUT)
  2584. {
  2585. dprintf("Unloaded modules:\n");
  2586. }
  2587. while (Unl->GetEntry(UnlName, &Params) == S_OK)
  2588. {
  2589. g_NumUnloadedModules++;
  2590. if (Pattern != NULL &&
  2591. !MatchPattern(UnlName, Pattern))
  2592. {
  2593. continue;
  2594. }
  2595. if (Flags & LUM_OUTPUT_TERSE)
  2596. {
  2597. dprintf(".");
  2598. continue;
  2599. }
  2600. if (Flags & LUM_OUTPUT)
  2601. {
  2602. dprintf("%s %s %-8s",
  2603. FormatAddr64(Params.Base),
  2604. FormatAddr64(Params.Base + Params.Size),
  2605. UnlName);
  2606. }
  2607. if (Flags & ( LUM_OUTPUT_VERBOSE | LUM_OUTPUT_TIMESTAMP))
  2608. {
  2609. PSTR TimeDateStr = TimeToStr(Params.TimeDateStamp);
  2610. dprintf(" Timestamp: %s (%08X)",
  2611. TimeDateStr, Params.TimeDateStamp);
  2612. }
  2613. dprintf("\n");
  2614. }
  2615. dprintf("\n");
  2616. }
  2617. ULONG
  2618. ModuleMachineType(PPROCESS_INFO Process, ULONG64 Offset)
  2619. {
  2620. ULONG64 Base = SymGetModuleBase64(Process->Handle, Offset);
  2621. if (Base == 0)
  2622. {
  2623. return IMAGE_FILE_MACHINE_UNKNOWN;
  2624. }
  2625. PPROCESS_INFO OldCur = g_CurrentProcess;
  2626. g_CurrentProcess = Process;
  2627. ULONG Machine = IMAGE_FILE_MACHINE_UNKNOWN;
  2628. IMAGE_DOS_HEADER DosHdr;
  2629. IMAGE_NT_HEADERS64 NtHdr;
  2630. ULONG Done;
  2631. if (g_Target->ReadVirtual(Base, &DosHdr, sizeof(DosHdr), &Done) == S_OK &&
  2632. Done == sizeof(DosHdr) &&
  2633. DosHdr.e_magic == IMAGE_DOS_SIGNATURE &&
  2634. g_Target->ReadVirtual(Base + DosHdr.e_lfanew, &NtHdr,
  2635. FIELD_OFFSET(IMAGE_NT_HEADERS64,
  2636. FileHeader.NumberOfSections),
  2637. &Done) == S_OK &&
  2638. Done == FIELD_OFFSET(IMAGE_NT_HEADERS64,
  2639. FileHeader.NumberOfSections) &&
  2640. NtHdr.Signature == IMAGE_NT_SIGNATURE &&
  2641. MachineTypeIndex(NtHdr.FileHeader.Machine) != MACHIDX_COUNT)
  2642. {
  2643. Machine = NtHdr.FileHeader.Machine;
  2644. }
  2645. g_CurrentProcess = OldCur;
  2646. return Machine;
  2647. }
  2648. ULONG
  2649. IsInFastSyscall(ULONG64 Addr, PULONG64 Base)
  2650. {
  2651. if (g_TargetMachineType != IMAGE_FILE_MACHINE_I386 ||
  2652. g_TargetPlatformId != VER_PLATFORM_WIN32_NT ||
  2653. g_SystemVersion < NT_SVER_W2K_WHISTLER)
  2654. {
  2655. return FSC_NONE;
  2656. }
  2657. ULONG64 FastBase = g_TargetBuildNumber >= 2412 ?
  2658. X86_SHARED_SYSCALL_BASE_GTE2412 :
  2659. X86_SHARED_SYSCALL_BASE_LT2412;
  2660. if (Addr >= FastBase &&
  2661. Addr < (FastBase + X86_SHARED_SYSCALL_SIZE))
  2662. {
  2663. *Base = FastBase;
  2664. return FSC_FOUND;
  2665. }
  2666. return FSC_NONE;
  2667. }
  2668. BOOL
  2669. ShowFunctionParameters(PDEBUG_STACK_FRAME StackFrame,
  2670. PSTR SymBuf, ULONG64 Displacement)
  2671. {
  2672. SYM_DUMP_PARAM_EX SymFunction = {0};
  2673. ULONG Status = 0;
  2674. PDEBUG_SCOPE Scope = GetCurrentScope();
  2675. DEBUG_SCOPE SavScope = *Scope;
  2676. SymFunction.size = sizeof(SYM_DUMP_PARAM_EX);
  2677. // SymFunction.sName = (PUCHAR) SymBuf;
  2678. SymFunction.addr = StackFrame->InstructionOffset;
  2679. SymFunction.Options = DBG_DUMP_COMPACT_OUT | DBG_DUMP_FUNCTION_FORMAT;
  2680. // SetCurrentScope to this function
  2681. SymSetContext(g_CurrentProcess->Handle,
  2682. (PIMAGEHLP_STACK_FRAME) StackFrame, NULL);
  2683. Scope->Frame = *StackFrame;
  2684. if (StackFrame->FuncTableEntry)
  2685. {
  2686. // Cache the FPO data since the pointer is only temporary
  2687. Scope->CachedFpo = *((PFPO_DATA) StackFrame->FuncTableEntry);
  2688. Scope->Frame.FuncTableEntry =
  2689. (ULONG64) &Scope->CachedFpo;
  2690. }
  2691. if (!SymbolTypeDumpNew(&SymFunction, &Status) &&
  2692. !Status)
  2693. {
  2694. Status = TRUE;
  2695. }
  2696. g_ScopeBuffer = SavScope;
  2697. SymSetContext(g_CurrentProcess->Handle,
  2698. (PIMAGEHLP_STACK_FRAME) &Scope->Frame, NULL);
  2699. return !Status;
  2700. }