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.

2358 lines
64 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Symbol-handling routines.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #include <stddef.h>
  10. #include <cvconst.h>
  11. PCSTR g_CallConv[] =
  12. {
  13. // Ignore near/far distinctions.
  14. "cdecl", "cdecl", "pascal", "pascal", "fastcall", "fastcall",
  15. "<skipped>", "stdcall", "stdcall", "syscall", "syscall",
  16. "thiscall", "MIPS", "generic", "Alpha", "PPC", "SuperH 4",
  17. "ARM", "AM33", "TriCore", "SuperH 5", "M32R",
  18. };
  19. typedef struct _OUTPUT_SYMBOL_CALLBACK
  20. {
  21. PSTR Prefix;
  22. ULONG Verbose:1;
  23. ULONG ShowAddress:1;
  24. } OUTPUT_SYMBOL_CALLBACK, *POUTPUT_SYMBOL_CALLBACK;
  25. LPSTR g_SymbolSearchPath;
  26. LPSTR g_ExecutableImageSearchPath;
  27. // Symbol options that require symbol reloading to take effect.
  28. #define RELOAD_SYM_OPTIONS \
  29. (SYMOPT_UNDNAME | SYMOPT_NO_CPP | SYMOPT_DEFERRED_LOADS | \
  30. SYMOPT_LOAD_LINES | SYMOPT_IGNORE_CVREC | SYMOPT_LOAD_ANYTHING | \
  31. SYMOPT_EXACT_SYMBOLS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | \
  32. SYMOPT_IGNORE_NT_SYMPATH | SYMOPT_INCLUDE_32BIT_MODULES | \
  33. SYMOPT_PUBLICS_ONLY | SYMOPT_NO_PUBLICS | SYMOPT_AUTO_PUBLICS |\
  34. SYMOPT_NO_IMAGE_SEARCH)
  35. ULONG g_SymOptions = SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME |
  36. SYMOPT_OMAP_FIND_NEAREST | SYMOPT_DEFERRED_LOADS |
  37. SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH |
  38. SYMOPT_FAIL_CRITICAL_ERRORS;
  39. #define SYM_BUFFER_SIZE (sizeof(IMAGEHLP_SYMBOL64) + MAX_SYMBOL_LEN)
  40. ULONG64 g_SymBuffer[(SYM_BUFFER_SIZE + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
  41. PIMAGEHLP_SYMBOL64 g_Sym = (PIMAGEHLP_SYMBOL64) g_SymBuffer;
  42. SYMBOL_INFO_AND_NAME g_TmpSymInfo;
  43. PSTR g_DmtNameDescs[DMT_NAME_COUNT] =
  44. {
  45. "Loaded symbol image file", "Symbol file", "Mapped memory image file",
  46. "Image path",
  47. };
  48. DEBUG_SCOPE g_ScopeBuffer;
  49. void
  50. RefreshAllModules(BOOL EnsureLines)
  51. {
  52. TargetInfo* Target;
  53. ProcessInfo* Process;
  54. ForAllLayersToProcess()
  55. {
  56. ImageInfo* Image;
  57. for (Image = Process->m_ImageHead; Image; Image = Image->m_Next)
  58. {
  59. if (EnsureLines)
  60. {
  61. IMAGEHLP_MODULE64 ModInfo;
  62. ModInfo.SizeOfStruct = sizeof(ModInfo);
  63. if (SymGetModuleInfo64(g_Process->m_SymHandle,
  64. Image->m_BaseOfImage, &ModInfo) &&
  65. ModInfo.LineNumbers)
  66. {
  67. // Line number information is already loaded,
  68. // so there's no need to reload this image.
  69. continue;
  70. }
  71. }
  72. Image->ReloadSymbols();
  73. }
  74. }
  75. }
  76. HRESULT
  77. SetSymOptions(ULONG Options)
  78. {
  79. ULONG OldOptions = g_SymOptions;
  80. //
  81. // If we're enabling untrusted user mode we can't
  82. // already be in a dangerous state.
  83. //
  84. if ((Options & SYMOPT_SECURE) &&
  85. !(OldOptions & SYMOPT_SECURE))
  86. {
  87. ULONG Id;
  88. char Desc[2 * MAX_PARAM_VALUE];
  89. // If there are any active targets we
  90. // can't be sure they're safe.
  91. // If we have RPC servers there may be ways
  92. // to attack through those so disallow that.
  93. if (g_TargetHead ||
  94. DbgRpcEnumActiveServers(NULL, &Id, Desc, sizeof(Desc)))
  95. {
  96. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  97. }
  98. }
  99. SymSetOptions(Options);
  100. g_SymOptions = SymGetOptions();
  101. if (g_SymOptions != Options)
  102. {
  103. // dbghelp denied the request to set options.
  104. return E_INVALIDARG;
  105. }
  106. NotifyChangeSymbolState(DEBUG_CSS_SYMBOL_OPTIONS, g_SymOptions, NULL);
  107. if ((OldOptions ^ g_SymOptions) & RELOAD_SYM_OPTIONS)
  108. {
  109. BOOL EnsureLines = FALSE;
  110. // If the only change was to turn on line loading
  111. // there's no need to reload modules which already
  112. // have lines loaded. This is usually the case for
  113. // PDBs, so this optimization effectively avoids all
  114. // PDB reloading when turning on .lines.
  115. if ((OldOptions & ~SYMOPT_LOAD_LINES) ==
  116. (g_SymOptions & ~SYMOPT_LOAD_LINES) &&
  117. (g_SymOptions & SYMOPT_LOAD_LINES))
  118. {
  119. EnsureLines = TRUE;
  120. }
  121. RefreshAllModules(EnsureLines);
  122. }
  123. return S_OK;
  124. }
  125. /*
  126. * TranslateAddress
  127. * Flags Flags returned by dbghelp
  128. * Address IN Address returned by dbghelp
  129. * OUT Address of symbol
  130. * Value Value of the symbol if its in register
  131. *
  132. */
  133. BOOL
  134. TranslateAddress(
  135. IN ULONG64 ModBase,
  136. IN ULONG Flags,
  137. IN ULONG RegId,
  138. IN OUT PULONG64 Address,
  139. OUT PULONG64 Value
  140. )
  141. {
  142. BOOL Status;
  143. ContextSave* Push;
  144. PCROSS_PLATFORM_CONTEXT ScopeContext = GetCurrentScopeContext();
  145. if (ScopeContext)
  146. {
  147. Push = g_Machine->PushContext(ScopeContext);
  148. }
  149. if (Flags & SYMFLAG_REGREL)
  150. {
  151. ULONG64 RegContent;
  152. if (RegId || (Value && (RegId = (ULONG)*Value)))
  153. {
  154. if (g_Machine->
  155. GetScopeFrameRegister(RegId, &GetCurrentScope()->Frame,
  156. &RegContent) != S_OK)
  157. {
  158. Status = FALSE;
  159. goto Exit;
  160. }
  161. }
  162. else
  163. {
  164. DBG_ASSERT(FALSE);
  165. Status = FALSE;
  166. goto Exit;
  167. }
  168. *Address = RegContent + ((LONG64) (LONG) (ULONG) *Address);
  169. }
  170. else if (Flags & SYMFLAG_REGISTER)
  171. {
  172. if (Value)
  173. {
  174. if (RegId || (RegId = (ULONG)*Address))
  175. {
  176. if (g_Machine->
  177. GetScopeFrameRegister(RegId, &GetCurrentScope()->Frame,
  178. Value) != S_OK)
  179. {
  180. Status = FALSE;
  181. goto Exit;
  182. }
  183. }
  184. else
  185. {
  186. DBG_ASSERT(FALSE);
  187. Status = FALSE;
  188. goto Exit;
  189. }
  190. }
  191. }
  192. else if (Flags & SYMFLAG_FRAMEREL)
  193. {
  194. PDEBUG_SCOPE Scope = GetCurrentScope();
  195. if (Scope->Frame.FrameOffset)
  196. {
  197. *Address += Scope->Frame.FrameOffset;
  198. PFPO_DATA pFpoData = (PFPO_DATA)Scope->Frame.FuncTableEntry;
  199. if (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_I386 &&
  200. pFpoData &&
  201. (pFpoData->cbFrame == FRAME_FPO ||
  202. pFpoData->cbFrame == FRAME_TRAP))
  203. {
  204. // Compensate for FPO's not having ebp
  205. *Address += sizeof(DWORD);
  206. }
  207. }
  208. else
  209. {
  210. ADDR FP;
  211. g_Machine->GetFP(&FP);
  212. FP.flat = (LONG64) FP.flat + *Address;
  213. *Address = FP.flat;
  214. }
  215. }
  216. else if (Flags & SYMFLAG_TLSREL)
  217. {
  218. ULONG64 TlsAddr;
  219. ImageInfo* Image = g_Process->FindImageByOffset(ModBase, FALSE);
  220. if (!Image ||
  221. Image->GetTlsIndex() != S_OK)
  222. {
  223. Status = FALSE;
  224. goto Exit;
  225. }
  226. if (g_Process->GetImplicitThreadDataTeb(g_Thread, &TlsAddr) != S_OK ||
  227. g_Target->ReadPointer(g_Process, g_Machine,
  228. TlsAddr + 11 * (g_Machine->m_Ptr64 ? 8 : 4),
  229. &TlsAddr) != S_OK ||
  230. g_Target->ReadPointer(g_Process, g_Machine,
  231. TlsAddr + Image->m_TlsIndex *
  232. (g_Machine->m_Ptr64 ? 8 : 4),
  233. &TlsAddr) != S_OK)
  234. {
  235. return MEMORY;
  236. }
  237. (*Address) += TlsAddr;
  238. }
  239. Status = TRUE;
  240. Exit:
  241. if (ScopeContext)
  242. {
  243. g_Machine->PopContext(Push);
  244. }
  245. return Status;
  246. }
  247. void
  248. FillCorSymbolInfo(PSYMBOL_INFO SymInfo)
  249. {
  250. // XXX drewb - Not clear what to do here.
  251. // Assumes the SYM_INFO was already zero-filled,
  252. // so just leave it zeroed.
  253. }
  254. BOOL
  255. FormatSymbolName(ImageInfo* Image,
  256. ULONG64 Offset,
  257. PCSTR Name,
  258. PULONG64 Displacement,
  259. PSTR Buffer,
  260. ULONG BufferLen)
  261. {
  262. DBG_ASSERT(BufferLen > 0);
  263. if (!Image)
  264. {
  265. *Buffer = 0;
  266. *Displacement = Offset;
  267. return FALSE;
  268. }
  269. if (Name)
  270. {
  271. if (*Displacement == (ULONG64)-1)
  272. {
  273. // In some BBT cases dbghelp can tell that an offset
  274. // is associated with a particular symbol but it
  275. // doesn't have a valid offset. Present the symbol
  276. // but in a way that makes it clear that it's
  277. // this special case.
  278. PrintString(Buffer, BufferLen,
  279. "%s!%s <PERF> (%s+0x%I64x)",
  280. Image->m_ModuleName, Name,
  281. Image->m_ModuleName,
  282. (Offset - Image->m_BaseOfImage));
  283. *Displacement = 0;
  284. }
  285. else
  286. {
  287. PrintString(Buffer, BufferLen,
  288. "%s!%s", Image->m_ModuleName, Name);
  289. }
  290. }
  291. else
  292. {
  293. CopyString(Buffer, Image->m_ModuleName, BufferLen);
  294. *Displacement = Offset - Image->m_BaseOfImage;
  295. }
  296. return TRUE;
  297. }
  298. BOOL
  299. GetSymbolInfo(ULONG64 Offset,
  300. PCHAR Buffer,
  301. ULONG BufferLen,
  302. PSYMBOL_INFO SymInfo,
  303. PULONG64 Displacement)
  304. {
  305. ImageInfo* Image;
  306. PCSTR Name = NULL;
  307. PSYMBOL_INFO TmpInfo = g_TmpSymInfo.Init();
  308. if ((Image = g_Process->FindImageByOffset(Offset, TRUE)) &&
  309. !Image->m_CorImage)
  310. {
  311. if (SymFromAddr(g_Process->m_SymHandle, Offset,
  312. Displacement, TmpInfo))
  313. {
  314. Name = TmpInfo->Name;
  315. }
  316. }
  317. else if (g_Process->m_CorImage)
  318. {
  319. ULONG64 IlModBase;
  320. ULONG32 MethodToken;
  321. ULONG32 MethodOffs;
  322. // The offset is not in any known module.
  323. // The managed runtime is loaded in this process,
  324. // so possibly the offset is in some JIT code.
  325. // See if the runtime knows about it.
  326. if (g_Process->
  327. ConvertNativeToIlOffset(Offset, &IlModBase,
  328. &MethodToken, &MethodOffs) == S_OK &&
  329. (Image = g_Process->FindImageByOffset(IlModBase, TRUE)) &&
  330. g_Process->
  331. GetCorSymbol(Offset, TmpInfo->Name, TmpInfo->MaxNameLen,
  332. Displacement) == S_OK)
  333. {
  334. Name = TmpInfo->Name;
  335. FillCorSymbolInfo(TmpInfo);
  336. }
  337. }
  338. if (SymInfo)
  339. {
  340. memcpy(SymInfo, TmpInfo, FIELD_OFFSET(SYMBOL_INFO, MaxNameLen));
  341. Buffer = SymInfo->Name;
  342. BufferLen = SymInfo->MaxNameLen;
  343. }
  344. return FormatSymbolName(Image, Offset, Name, Displacement,
  345. Buffer, BufferLen);
  346. }
  347. BOOL
  348. GetNearSymbol(ULONG64 Offset,
  349. PSTR Buffer,
  350. ULONG BufferLen,
  351. PULONG64 Displacement,
  352. LONG Delta)
  353. {
  354. ImageInfo* Image;
  355. if (Delta == 0)
  356. {
  357. return GetSymbol(Offset, Buffer, BufferLen, Displacement);
  358. }
  359. if (!(Image = g_Process->FindImageByOffset(Offset, TRUE)) ||
  360. !SymGetSymFromAddr64(g_Process->m_SymHandle, Offset,
  361. Displacement, g_Sym))
  362. {
  363. return FALSE;
  364. }
  365. if (Delta < 0)
  366. {
  367. while (Delta++ < 0)
  368. {
  369. if (!SymGetSymPrev(g_Process->m_SymHandle, g_Sym))
  370. {
  371. return FALSE;
  372. }
  373. }
  374. if (Displacement != NULL)
  375. {
  376. *Displacement = Offset - g_Sym->Address;
  377. }
  378. }
  379. else if (Delta > 0)
  380. {
  381. while (Delta-- > 0)
  382. {
  383. if (!SymGetSymNext(g_Process->m_SymHandle, g_Sym))
  384. {
  385. return FALSE;
  386. }
  387. }
  388. if (Displacement != NULL)
  389. {
  390. *Displacement = g_Sym->Address - Offset;
  391. }
  392. }
  393. PrintString(Buffer, BufferLen,
  394. "%s!%s", Image->m_ModuleName, g_Sym->Name);
  395. return TRUE;
  396. }
  397. BOOL
  398. GetLineFromAddr(ProcessInfo* Process,
  399. ULONG64 Offset,
  400. PIMAGEHLP_LINE64 Line,
  401. PULONG Displacement)
  402. {
  403. ImageInfo* Image;
  404. Line->SizeOfStruct = sizeof(*Line);
  405. if (!(Image = Process->FindImageByOffset(Offset, FALSE)) ||
  406. Image->m_CorImage)
  407. {
  408. ULONG32 MethodToken;
  409. ULONG32 MethodOffs;
  410. SYMBOL_INFO SymInfo = {0};
  411. // The offset is not in any known module.
  412. // The managed runtime is loaded in this process,
  413. // so possibly the offset is in some JIT code.
  414. // See if the runtime knows about it.
  415. if (Process->
  416. ConvertNativeToIlOffset(Offset, &Offset,
  417. &MethodToken, &MethodOffs) != S_OK)
  418. {
  419. return FALSE;
  420. }
  421. // Need to look up the fake method RVA by
  422. // the method token, then add the method offset
  423. // to that and search by that offset for the line.
  424. if (!SymFromToken(Process->m_SymHandle, Offset, MethodToken, &SymInfo))
  425. {
  426. return FALSE;
  427. }
  428. Offset = SymInfo.Address + MethodOffs;
  429. }
  430. return SymGetLineFromAddr64(Process->m_SymHandle, Offset,
  431. Displacement, Line);
  432. }
  433. void
  434. OutputSymbolAndInfo(ULONG64 Addr)
  435. {
  436. SYMBOL_INFO_AND_NAME SymInfo;
  437. ULONG64 Disp;
  438. if (GetSymbolInfo(Addr, NULL, 0, SymInfo, &Disp))
  439. {
  440. dprintf("%s", SymInfo->Name);
  441. ShowSymbolInfo(SymInfo);
  442. }
  443. }
  444. #define IMAGE_IS_PATTERN ((ImageInfo*)-1)
  445. ImageInfo*
  446. ParseModuleName(PBOOL ModSpecified)
  447. {
  448. PSTR CmdSaved = g_CurCmd;
  449. CHAR Name[MAX_MODULE];
  450. PSTR Dst = Name;
  451. CHAR ch;
  452. BOOL HasWild = FALSE;
  453. // first, parse out a possible module name, either a '*' or
  454. // a string of 'A'-'Z', 'a'-'z', '0'-'9', '_', '~' (or null)
  455. ch = PeekChar();
  456. g_CurCmd++;
  457. while ((ch >= 'A' && ch <= 'Z') ||
  458. (ch >= 'a' && ch <= 'z') ||
  459. (ch >= '0' && ch <= '9') ||
  460. ch == '_' || ch == '~' || ch == '*' || ch == '?')
  461. {
  462. if (ch == '*' || ch == '?')
  463. {
  464. HasWild = TRUE;
  465. }
  466. *Dst++ = ch;
  467. ch = *g_CurCmd++;
  468. }
  469. *Dst = '\0';
  470. g_CurCmd--;
  471. // if no '!' after name and white space, then no module specified
  472. // restore text pointer and treat as null module (PC current)
  473. if (PeekChar() == '!')
  474. {
  475. g_CurCmd++;
  476. }
  477. else
  478. {
  479. g_CurCmd = CmdSaved;
  480. Name[0] = '\0';
  481. }
  482. // Name either has: '*' for all modules,
  483. // '\0' for current module,
  484. // nonnull string for module name.
  485. *ModSpecified = Name[0] != 0;
  486. if (HasWild)
  487. {
  488. return IMAGE_IS_PATTERN;
  489. }
  490. else if (Name[0])
  491. {
  492. return g_Process->FindImageByName(Name, 0, INAME_MODULE, TRUE);
  493. }
  494. else
  495. {
  496. return NULL;
  497. }
  498. }
  499. BOOL CALLBACK
  500. OutputSymbolInfoCallback(
  501. PSYMBOL_INFO SymInfo,
  502. ULONG Size,
  503. PVOID Arg
  504. )
  505. {
  506. POUTPUT_SYMBOL_CALLBACK OutSym = (POUTPUT_SYMBOL_CALLBACK)Arg;
  507. ULONG64 Address = SymInfo->Address;
  508. ULONG64 Value = 0;
  509. ImageInfo* Image;
  510. if (OutSym->Prefix)
  511. {
  512. dprintf("%s", OutSym->Prefix);
  513. }
  514. if (SymInfo->Flags & (SYMFLAG_REGISTER |
  515. SYMFLAG_REGREL |
  516. SYMFLAG_FRAMEREL |
  517. SYMFLAG_TLSREL))
  518. {
  519. TranslateAddress(SymInfo->ModBase, SymInfo->Flags,
  520. g_Machine->
  521. CvRegToMachine((CV_HREG_e)SymInfo->Register),
  522. &Address, &Value);
  523. }
  524. if (OutSym->ShowAddress)
  525. {
  526. dprintf("%s ", FormatAddr64(Address));
  527. }
  528. Image = g_Process->FindImageByOffset(SymInfo->ModBase, TRUE);
  529. if (Image && ((SymInfo->Flags & SYMFLAG_LOCAL) == 0))
  530. {
  531. dprintf("%s!%s", Image->m_ModuleName, SymInfo->Name);
  532. }
  533. else
  534. {
  535. dprintf("%s", SymInfo->Name);
  536. }
  537. if (OutSym->Verbose)
  538. {
  539. dprintf(" ");
  540. ShowSymbolInfo(SymInfo);
  541. }
  542. dprintf("\n");
  543. return !CheckUserInterrupt();
  544. }
  545. /*** ParseExamine - parse and execute examine command
  546. *
  547. * Purpose:
  548. * Parse the current command string and examine the symbol
  549. * table to display the appropriate entries. The entries
  550. * are displayed in increasing string order. This function
  551. * accepts underscores, alphabetic, and numeric characters
  552. * to match as well as the special characters '?', '*', '['-']'.
  553. *
  554. * Input:
  555. * g_CurCmd - pointer to current command string
  556. *
  557. * Output:
  558. * offset and string name of symbols displayed
  559. *
  560. *************************************************************************/
  561. void
  562. ParseExamine(void)
  563. {
  564. CHAR StringBuf[MAX_SYMBOL_LEN];
  565. UCHAR ch;
  566. PSTR String = StringBuf;
  567. PSTR Start;
  568. PSTR ModEnd;
  569. BOOL ModSpecified;
  570. ULONG64 Base = 0;
  571. ImageInfo* Image;
  572. OUTPUT_SYMBOL_CALLBACK OutSymInfo;
  573. // Get module pointer from name in command line (<string>!).
  574. PeekChar();
  575. Start = g_CurCmd;
  576. Image = ParseModuleName(&ModSpecified);
  577. ModEnd = g_CurCmd;
  578. ch = PeekChar();
  579. // Special case the command "x <pattern>!" to dump out the module table.
  580. if (Image == IMAGE_IS_PATTERN &&
  581. (ch == ';' || ch == '\0'))
  582. {
  583. *(ModEnd - 1) = 0;
  584. _strupr(Start);
  585. DumpModuleTable(DMT_STANDARD, Start);
  586. return;
  587. }
  588. if (ModSpecified)
  589. {
  590. if (Image == NULL)
  591. {
  592. // The user specified a module that doesn't exist.
  593. error(VARDEF);
  594. }
  595. else if (Image == IMAGE_IS_PATTERN)
  596. {
  597. // The user gave a pattern string for the module
  598. // so we need to pass it on for dbghelp to scan with.
  599. memcpy(String, Start, (ModEnd - Start));
  600. String += ModEnd - Start;
  601. }
  602. else
  603. {
  604. // A specific image was given and found so
  605. // confine the search to that one image.
  606. Base = Image->m_BaseOfImage;
  607. }
  608. }
  609. g_CurCmd++;
  610. // Condense leading underscores into a "_#"
  611. // that will match zero or more underscores. This causes all
  612. // underscore-prefixed symbols to match the base symbol name
  613. // when the pattern is prefixed by an underscore.
  614. if (ch == '_')
  615. {
  616. *String++ = '_';
  617. *String++ = '#';
  618. do
  619. {
  620. ch = *g_CurCmd++;
  621. } while (ch == '_');
  622. }
  623. ch = (UCHAR)toupper(ch);
  624. while (ch && ch != ';' && ch != ' ')
  625. {
  626. *String++ = ch;
  627. ch = (CHAR)toupper(*g_CurCmd);
  628. g_CurCmd++;
  629. }
  630. *String = '\0';
  631. g_CurCmd--;
  632. ZeroMemory(&OutSymInfo, sizeof(OutSymInfo));
  633. OutSymInfo.Verbose = TRUE;
  634. OutSymInfo.ShowAddress = TRUE;
  635. // We nee the scope for all cases since param values are displayed for
  636. // function in scope
  637. RequireCurrentScope();
  638. SymEnumSymbols(g_Process->m_SymHandle,
  639. Base,
  640. StringBuf,
  641. OutputSymbolInfoCallback,
  642. &OutSymInfo);
  643. }
  644. void
  645. ListNearSymbols(ULONG64 AddrStart)
  646. {
  647. ULONG64 Displacement;
  648. ImageInfo* Image;
  649. if (g_SrcOptions & SRCOPT_LIST_LINE)
  650. {
  651. OutputLineAddr(AddrStart, "%s(%d)%s\n");
  652. }
  653. if ((Image = g_Process->FindImageByOffset(AddrStart, TRUE)) &&
  654. !Image->m_CorImage)
  655. {
  656. if (!SymGetSymFromAddr64(g_Process->m_SymHandle, AddrStart,
  657. &Displacement, g_Sym))
  658. {
  659. return;
  660. }
  661. dprintf("(%s) %s!%s",
  662. FormatAddr64(g_Sym->Address),
  663. Image->m_ModuleName,
  664. g_Sym->Name);
  665. if (Displacement)
  666. {
  667. dprintf("+0x%s ", FormatDisp64(Displacement));
  668. }
  669. else
  670. {
  671. dprintf(" ");
  672. }
  673. if (SymGetSymNext64(g_Process->m_SymHandle, g_Sym))
  674. {
  675. dprintf("| (%s) %s!%s",
  676. FormatAddr64(g_Sym->Address),
  677. Image->m_ModuleName,
  678. g_Sym->Name);
  679. }
  680. dprintf("\n");
  681. if (Displacement == 0)
  682. {
  683. OUTPUT_SYMBOL_CALLBACK OutSymInfo;
  684. dprintf("Exact matches:\n");
  685. FlushCallbacks();
  686. ZeroMemory(&OutSymInfo, sizeof(OutSymInfo));
  687. OutSymInfo.Prefix = " ";
  688. OutSymInfo.Verbose = TRUE;
  689. SymEnumSymbolsForAddr(g_Process->m_SymHandle, AddrStart,
  690. OutputSymbolInfoCallback, &OutSymInfo);
  691. }
  692. }
  693. else
  694. {
  695. SYMBOL_INFO_AND_NAME SymInfo;
  696. // We couldn't find a true symbol but it may be
  697. // possible to find a managed symbol.
  698. if (GetSymbolInfo(AddrStart, NULL, 0, SymInfo, &Displacement))
  699. {
  700. dprintf("(%s) %s", FormatAddr64(AddrStart), SymInfo->Name);
  701. if (Displacement)
  702. {
  703. dprintf("+0x%s", FormatDisp64(Displacement));
  704. }
  705. dprintf("\n");
  706. }
  707. }
  708. }
  709. void
  710. DumpModuleTable(ULONG Flags, PSTR Pattern)
  711. {
  712. ImageInfo* Image;
  713. IMAGEHLP_MODULE64 ModInfo;
  714. ULONG i;
  715. if (g_Target->m_Machine->m_Ptr64)
  716. {
  717. dprintf("start end module name\n");
  718. }
  719. else
  720. {
  721. dprintf("start end module name\n");
  722. }
  723. Image = g_Process->m_ImageHead;
  724. while (Image)
  725. {
  726. ULONG PrimaryName;
  727. PSTR Names[DMT_NAME_COUNT];
  728. if (Pattern != NULL &&
  729. !MatchPattern(Image->m_ModuleName, Pattern))
  730. {
  731. Image = Image->m_Next;
  732. continue;
  733. }
  734. ModInfo.SizeOfStruct = sizeof(ModInfo);
  735. if (!SymGetModuleInfo64(g_Process->m_SymHandle,
  736. Image->m_BaseOfImage, &ModInfo))
  737. {
  738. ModInfo.SymType = SymNone;
  739. }
  740. Names[DMT_NAME_SYM_IMAGE] = ModInfo.LoadedImageName;
  741. Names[DMT_NAME_SYM_FILE] = ModInfoSymFile(&ModInfo);
  742. Names[DMT_NAME_MAPPED_IMAGE] = Image->m_MappedImagePath;
  743. Names[DMT_NAME_IMAGE_PATH] = Image->m_ImagePath;
  744. if (Flags & DMT_SYM_FILE_NAME)
  745. {
  746. PrimaryName = DMT_NAME_SYM_FILE;
  747. }
  748. else if (Flags & DMT_MAPPED_IMAGE_NAME)
  749. {
  750. PrimaryName = DMT_NAME_MAPPED_IMAGE;
  751. }
  752. else if (Flags & DMT_IMAGE_PATH_NAME)
  753. {
  754. PrimaryName = DMT_NAME_IMAGE_PATH;
  755. }
  756. else
  757. {
  758. PrimaryName = DMT_NAME_SYM_IMAGE;
  759. }
  760. //
  761. // Skip modules filtered by flags
  762. //
  763. if ((Flags & DMT_ONLY_LOADED_SYMBOLS) &&
  764. (ModInfo.SymType == SymDeferred))
  765. {
  766. Image = Image->m_Next;
  767. continue;
  768. }
  769. if (IS_KERNEL_TARGET(g_Target))
  770. {
  771. if ((Flags & DMT_ONLY_USER_SYMBOLS) &&
  772. (Image->m_BaseOfImage >= g_Target->m_SystemRangeStart))
  773. {
  774. Image = Image->m_Next;
  775. continue;
  776. }
  777. if ((Flags & DMT_ONLY_KERNEL_SYMBOLS) &&
  778. (Image->m_BaseOfImage <= g_Target->m_SystemRangeStart))
  779. {
  780. Image = Image->m_Next;
  781. continue;
  782. }
  783. }
  784. dprintf("%s %s %-8s ",
  785. FormatAddr64(Image->m_BaseOfImage),
  786. FormatAddr64(Image->m_BaseOfImage + Image->m_SizeOfImage),
  787. Image->m_ModuleName);
  788. if (Flags & DMT_NO_SYMBOL_OUTPUT)
  789. {
  790. goto SkipSymbolOutput;
  791. }
  792. if (PrimaryName == DMT_NAME_MAPPED_IMAGE ||
  793. PrimaryName == DMT_NAME_IMAGE_PATH)
  794. {
  795. dprintf(" %s\n",
  796. *Names[PrimaryName] ? Names[PrimaryName] : "<none>");
  797. goto SkipSymbolOutput;
  798. }
  799. switch(Image->m_SymState)
  800. {
  801. case ISS_MATCHED:
  802. dprintf( " " );
  803. break;
  804. case ISS_MISMATCHED_SYMBOLS:
  805. dprintf( "M " );
  806. break;
  807. case ISS_UNKNOWN_TIMESTAMP:
  808. dprintf( "T " );
  809. break;
  810. case ISS_UNKNOWN_CHECKSUM:
  811. dprintf( "C " );
  812. break;
  813. case ISS_BAD_CHECKSUM:
  814. dprintf( "# " );
  815. break;
  816. }
  817. if (ModInfo.SymType == SymDeferred)
  818. {
  819. dprintf("(deferred) ");
  820. }
  821. else if (ModInfo.SymType == SymNone)
  822. {
  823. dprintf("(no symbolic information) ");
  824. }
  825. else
  826. {
  827. switch(ModInfo.SymType)
  828. {
  829. case SymCoff:
  830. dprintf("(coff symbols) ");
  831. break;
  832. case SymCv:
  833. dprintf("(codeview symbols) ");
  834. break;
  835. case SymPdb:
  836. dprintf("(pdb symbols) ");
  837. break;
  838. case SymExport:
  839. dprintf("(export symbols) ");
  840. break;
  841. }
  842. dprintf("%s", *Names[PrimaryName] ? Names[PrimaryName] : "<none>");
  843. }
  844. dprintf("\n");
  845. SkipSymbolOutput:
  846. if (Flags & DMT_VERBOSE)
  847. {
  848. for (i = 0; i < DMT_NAME_COUNT; i++)
  849. {
  850. if (i != PrimaryName && *Names[i])
  851. {
  852. dprintf(" %s: %s\n", g_DmtNameDescs[i], Names[i]);
  853. }
  854. }
  855. }
  856. if (Flags & (DMT_VERBOSE | DMT_IMAGE_TIMESTAMP))
  857. {
  858. LPSTR TimeDateStr = TimeToStr(Image->m_TimeDateStamp);
  859. dprintf(" Checksum: %08X Timestamp: %s (%08X)\n",
  860. Image->m_CheckSum, TimeDateStr, Image->m_TimeDateStamp);
  861. }
  862. if (Flags & DMT_VERBOSE)
  863. {
  864. Image->OutputVersionInformation();
  865. }
  866. if (CheckUserInterrupt())
  867. {
  868. break;
  869. }
  870. Image = Image->m_Next;
  871. }
  872. if ((Flags & (DMT_ONLY_LOADED_SYMBOLS | DMT_ONLY_USER_SYMBOLS)) == 0)
  873. {
  874. ULONG LumFlags = LUM_OUTPUT;
  875. LumFlags |= ((Flags & DMT_VERBOSE) ? LUM_OUTPUT_VERBOSE : 0);
  876. LumFlags |= ((Flags & DMT_IMAGE_TIMESTAMP) ?
  877. LUM_OUTPUT_IMAGE_INFO : 0);
  878. dprintf("\n");
  879. ListUnloadedModules(LumFlags, Pattern);
  880. }
  881. }
  882. void
  883. ParseDumpModuleTable(void)
  884. {
  885. ULONG Flags = DMT_STANDARD;
  886. char Pattern[MAX_MODULE];
  887. PSTR Pat = NULL;
  888. if (!IS_CUR_MACHINE_ACCESSIBLE())
  889. {
  890. error(BADTHREAD);
  891. }
  892. g_CurCmd++;
  893. for (;;)
  894. {
  895. // skip white space
  896. while (isspace(*g_CurCmd))
  897. {
  898. g_CurCmd++;
  899. }
  900. if (*g_CurCmd == 'f')
  901. {
  902. Flags = (Flags & ~DMT_NAME_FLAGS) | DMT_IMAGE_PATH_NAME;
  903. g_CurCmd++;
  904. }
  905. else if (*g_CurCmd == 'i')
  906. {
  907. Flags = (Flags & ~DMT_NAME_FLAGS) | DMT_SYM_IMAGE_FILE_NAME;
  908. g_CurCmd++;
  909. }
  910. else if (*g_CurCmd == 'l')
  911. {
  912. Flags |= DMT_ONLY_LOADED_SYMBOLS;
  913. g_CurCmd++;
  914. }
  915. else if (*g_CurCmd == 'm')
  916. {
  917. g_CurCmd++;
  918. // skip white space
  919. while (isspace(*g_CurCmd))
  920. {
  921. g_CurCmd++;
  922. }
  923. Pat = Pattern;
  924. while (*g_CurCmd && !isspace(*g_CurCmd))
  925. {
  926. if ((Pat - Pattern) < sizeof(Pattern) - 1)
  927. {
  928. *Pat++ = *g_CurCmd;
  929. }
  930. g_CurCmd++;
  931. }
  932. *Pat = 0;
  933. Pat = Pattern;
  934. _strupr(Pat);
  935. }
  936. else if (*g_CurCmd == 'p')
  937. {
  938. Flags = (Flags & ~DMT_NAME_FLAGS) | DMT_MAPPED_IMAGE_NAME;
  939. g_CurCmd++;
  940. }
  941. else if (*g_CurCmd == 't')
  942. {
  943. Flags = (Flags & ~(DMT_NAME_FLAGS)) |
  944. DMT_NAME_SYM_IMAGE | DMT_IMAGE_TIMESTAMP |
  945. DMT_NO_SYMBOL_OUTPUT;
  946. g_CurCmd++;
  947. }
  948. else if (*g_CurCmd == 'v')
  949. {
  950. Flags |= DMT_VERBOSE;
  951. g_CurCmd++;
  952. }
  953. else if (IS_KERNEL_TARGET(g_Target))
  954. {
  955. if (*g_CurCmd == 'u')
  956. {
  957. Flags |= DMT_ONLY_USER_SYMBOLS;
  958. g_CurCmd++;
  959. }
  960. else if (*g_CurCmd == 'k')
  961. {
  962. Flags |= DMT_ONLY_KERNEL_SYMBOLS;
  963. g_CurCmd++;
  964. }
  965. else
  966. {
  967. break;
  968. }
  969. }
  970. else
  971. {
  972. break;
  973. }
  974. }
  975. DumpModuleTable(Flags, Pat);
  976. }
  977. void
  978. GetCurrentMemoryOffsets(PULONG64 MemoryLow,
  979. PULONG64 MemoryHigh)
  980. {
  981. // Default value for no source.
  982. *MemoryLow = (ULONG64)(LONG64)-1;
  983. }
  984. PCSTR
  985. PrependPrefixToSymbol(char PrefixedString[],
  986. PCSTR pString,
  987. PCSTR *RegString)
  988. {
  989. if ( RegString )
  990. {
  991. *RegString = NULL;
  992. }
  993. PCSTR bangPtr;
  994. int bang = '!';
  995. PCSTR Tail;
  996. bangPtr = strchr( pString, bang );
  997. if ( bangPtr )
  998. {
  999. Tail = bangPtr + 1;
  1000. }
  1001. else
  1002. {
  1003. Tail = pString;
  1004. }
  1005. if ( strncmp( Tail, g_Machine->m_SymPrefix, g_Machine->m_SymPrefixLen ) )
  1006. {
  1007. ULONG Loc = (ULONG)(Tail - pString);
  1008. if (Loc > 0)
  1009. {
  1010. memcpy( PrefixedString, pString, Loc );
  1011. }
  1012. memcpy( PrefixedString + Loc, g_Machine->m_SymPrefix,
  1013. g_Machine->m_SymPrefixLen );
  1014. if ( RegString )
  1015. {
  1016. *RegString = &PrefixedString[Loc];
  1017. }
  1018. Loc += g_Machine->m_SymPrefixLen;
  1019. strcpy( &PrefixedString[Loc], Tail );
  1020. return PrefixedString;
  1021. }
  1022. else
  1023. {
  1024. return pString;
  1025. }
  1026. }
  1027. BOOL
  1028. ForceSymbolCodeAddress(ProcessInfo* Process,
  1029. PSYMBOL_INFO Symbol, MachineInfo* Machine)
  1030. {
  1031. ULONG64 Code = Symbol->Address;
  1032. if (Symbol->Flags & SYMFLAG_FORWARDER)
  1033. {
  1034. char Fwd[2 * MAX_PATH];
  1035. ULONG Read;
  1036. PSTR Sep;
  1037. // The address of a forwarder entry points to the
  1038. // string name of the function that things are forwarded
  1039. // to. Look up that name and try to get the address
  1040. // from it.
  1041. if (g_Target->ReadVirtual(Process, Symbol->Address, Fwd, sizeof(Fwd),
  1042. &Read) != S_OK ||
  1043. Read < 2)
  1044. {
  1045. ErrOut("Unable to read forwarder string\n");
  1046. return FALSE;
  1047. }
  1048. Fwd[sizeof(Fwd) - 1] = 0;
  1049. if (!(Sep = strchr(Fwd, '.')))
  1050. {
  1051. ErrOut("Unable to read forwarder string\n");
  1052. return FALSE;
  1053. }
  1054. *Sep = '!';
  1055. if (GetOffsetFromSym(Process, Fwd, &Code, NULL) != 1)
  1056. {
  1057. ErrOut("Unable to get address of forwarder '%s'\n", Fwd);
  1058. return FALSE;
  1059. }
  1060. }
  1061. else if (Machine &&
  1062. Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_IA64 &&
  1063. (Symbol->Flags & SYMFLAG_EXPORT))
  1064. {
  1065. // On IA64 the export entries contain the address
  1066. // of the plabel. We want the actual code address
  1067. // so resolve the plabel to its code.
  1068. if (!Machine->GetPrefixedSymbolOffset(Process, Symbol->Address,
  1069. GETPREF_VERBOSE,
  1070. &Code))
  1071. {
  1072. return FALSE;
  1073. }
  1074. }
  1075. Symbol->Address = Code;
  1076. return TRUE;
  1077. }
  1078. BOOL
  1079. GetOffsetFromBreakpoint(PCSTR String, PULONG64 Offset)
  1080. {
  1081. ULONG Id;
  1082. Breakpoint* Bp;
  1083. //
  1084. // The string must be of the form "$bp[digits]".
  1085. //
  1086. if (strlen(String) < 4 || _memicmp(String, "$bp", 3) != 0)
  1087. {
  1088. return FALSE;
  1089. }
  1090. String += 3;
  1091. Id = 0;
  1092. while (*String)
  1093. {
  1094. if (*String < '0' || *String > '9')
  1095. {
  1096. return FALSE;
  1097. }
  1098. Id = Id * 10 + (int)(*String - '0');
  1099. String++;
  1100. }
  1101. Bp = GetBreakpointById(NULL, Id);
  1102. if (Bp == NULL ||
  1103. (Bp->m_Flags & DEBUG_BREAKPOINT_DEFERRED))
  1104. {
  1105. return FALSE;
  1106. }
  1107. *Offset = Flat(*Bp->GetAddr());
  1108. return TRUE;
  1109. }
  1110. BOOL
  1111. IgnoreEnumeratedSymbol(ProcessInfo* Process,
  1112. PSTR MatchString,
  1113. MachineInfo* Machine,
  1114. PSYMBOL_INFO SymInfo)
  1115. {
  1116. ULONG64 Func;
  1117. //
  1118. // The compiler and linker can generate thunks for
  1119. // a variety of reasons. For example, a "this" adjustor
  1120. // thunk can be generated to adjust a this pointer before
  1121. // calling into a method to account for differences between
  1122. // derived/container classes and the base/containee classes.
  1123. // Assume that the user doesn't care about thunks as they're
  1124. // automatically emitted.
  1125. //
  1126. if (SymInfo->Tag == SymTagThunk &&
  1127. !_stricmp(MatchString, SymInfo->Name))
  1128. {
  1129. // We hit a thunk for the function we're looking
  1130. // for, just ignore it.
  1131. return TRUE;
  1132. }
  1133. //
  1134. // IA64 plabels are publics with the same name
  1135. // as the function they refer to. This causes
  1136. // ambiguity problems as we end up with two
  1137. // hits. The plabel is rarely interesting, though,
  1138. // so just filter them out here so that expressions
  1139. // always evaluate to the function itself.
  1140. //
  1141. if ((Machine->m_ExecTypes[0] != IMAGE_FILE_MACHINE_IA64) ||
  1142. (SymInfo->Scope != SymTagPublicSymbol) ||
  1143. (SymInfo->Flags & SYMFLAG_FUNCTION) ||
  1144. !Machine->GetPrefixedSymbolOffset(Process, SymInfo->Address,
  1145. 0, &Func))
  1146. {
  1147. return FALSE;
  1148. }
  1149. if (Func == SymInfo->Address)
  1150. {
  1151. // The symbol is probably a global pointing to itself
  1152. return FALSE;
  1153. }
  1154. PSYMBOL_INFO FuncSymInfo;
  1155. PSTR FuncSym;
  1156. __try
  1157. {
  1158. FuncSymInfo = (PSYMBOL_INFO)
  1159. alloca(sizeof(*FuncSymInfo) + MAX_SYMBOL_LEN * 2);
  1160. }
  1161. __except(EXCEPTION_EXECUTE_HANDLER)
  1162. {
  1163. FuncSymInfo = NULL;
  1164. }
  1165. if (FuncSymInfo == NULL)
  1166. {
  1167. return FALSE;
  1168. }
  1169. FuncSym = FuncSymInfo->Name;
  1170. SYMBOL_INFO LocalSymInfo;
  1171. // We have to save and restore the original data as
  1172. // dbghelp always uses a single buffer to store all
  1173. // symbol information. The incoming symbol info
  1174. // is going to be wiped out when we look up another symbol.
  1175. LocalSymInfo = *SymInfo;
  1176. strcpy(FuncSym + MAX_SYMBOL_LEN, SymInfo->Name);
  1177. ULONG64 FuncSymDisp;
  1178. ZeroMemory(FuncSymInfo, sizeof(*FuncSymInfo));
  1179. FuncSymInfo->SizeOfStruct = sizeof(*FuncSymInfo);
  1180. FuncSymInfo->MaxNameLen = MAX_SYMBOL_LEN;
  1181. FuncSym[0] = 0;
  1182. if (!SymFromAddr(Process->m_SymHandle, Func, &FuncSymDisp, FuncSymInfo))
  1183. {
  1184. FuncSymDisp = 1;
  1185. }
  1186. else
  1187. {
  1188. // Incremental linking produces intermediate thunks
  1189. // that entry points refer to. The thunks call on
  1190. // to the real code. The extra layer of code prevents
  1191. // direct filtering; we have to chain through thunks
  1192. // to see if the final code is the function code.
  1193. while (FuncSymDisp == 0 &&
  1194. FuncSymInfo->Tag == SymTagThunk &&
  1195. strstr(FuncSym, FuncSym + MAX_SYMBOL_LEN) == NULL)
  1196. {
  1197. FuncSym[0] = 0;
  1198. if (!SymFromAddr(Process->m_SymHandle, FuncSymInfo->Value,
  1199. &FuncSymDisp, FuncSymInfo))
  1200. {
  1201. FuncSymDisp = 1;
  1202. break;
  1203. }
  1204. }
  1205. }
  1206. *SymInfo = LocalSymInfo;
  1207. strcpy(SymInfo->Name, FuncSym + MAX_SYMBOL_LEN);
  1208. return FuncSymDisp == 0 && strstr(FuncSym, SymInfo->Name);
  1209. }
  1210. struct COUNT_SYMBOL_MATCHES
  1211. {
  1212. PSTR MatchString;
  1213. ProcessInfo* Process;
  1214. MachineInfo* Machine;
  1215. SYMBOL_INFO ReturnSymInfo;
  1216. CHAR SymbolNameOverflowBuffer[MAX_SYMBOL_LEN];
  1217. ULONG Matches;
  1218. };
  1219. BOOL CALLBACK
  1220. CountSymbolMatches(
  1221. PSYMBOL_INFO SymInfo,
  1222. ULONG Size,
  1223. PVOID UserContext
  1224. )
  1225. {
  1226. COUNT_SYMBOL_MATCHES* Context =
  1227. (COUNT_SYMBOL_MATCHES*)UserContext;
  1228. if (IgnoreEnumeratedSymbol(Context->Process, Context->MatchString,
  1229. Context->Machine, SymInfo))
  1230. {
  1231. return TRUE;
  1232. }
  1233. if (Context->Matches == 1)
  1234. {
  1235. // We already have one match, check if we got a duplicate.
  1236. if ((SymInfo->Address == Context->ReturnSymInfo.Address) &&
  1237. !strcmp(SymInfo->Name, Context->ReturnSymInfo.Name))
  1238. {
  1239. // Looks like the same symbol, ignore it.
  1240. return TRUE;
  1241. }
  1242. }
  1243. Context->ReturnSymInfo = *SymInfo;
  1244. if (SymInfo->NameLen < MAX_SYMBOL_LEN)
  1245. {
  1246. strcpy(Context->ReturnSymInfo.Name, SymInfo->Name);
  1247. }
  1248. Context->Matches++;
  1249. return TRUE;
  1250. }
  1251. ULONG
  1252. MultiSymFromName(IN ProcessInfo* Process,
  1253. IN LPSTR Name,
  1254. IN ImageInfo* Image,
  1255. IN MachineInfo* Machine,
  1256. OUT PSYMBOL_INFO Symbol)
  1257. {
  1258. ULONG Matches;
  1259. RequireCurrentScope();
  1260. if (!Image)
  1261. {
  1262. if (!SymFromName(Process->m_SymHandle, Name, Symbol))
  1263. {
  1264. return 0;
  1265. }
  1266. Matches = 1;
  1267. }
  1268. else
  1269. {
  1270. COUNT_SYMBOL_MATCHES Context;
  1271. ULONG MaxName = Symbol->MaxNameLen;
  1272. PSTR Bang;
  1273. Bang = strchr(Name, '!');
  1274. if (Bang &&
  1275. !_strnicmp(Image->m_ModuleName, Name,
  1276. Bang - Name))
  1277. {
  1278. Context.MatchString = Bang + 1;
  1279. }
  1280. else
  1281. {
  1282. Context.MatchString = Name;
  1283. }
  1284. Context.Process = Process;
  1285. Context.Machine = Machine;
  1286. Context.ReturnSymInfo = *Symbol;
  1287. if (Symbol->NameLen < MAX_SYMBOL_LEN)
  1288. {
  1289. strcpy(Context.ReturnSymInfo.Name, Symbol->Name);
  1290. }
  1291. Context.Matches = 0;
  1292. SymEnumSymbols(Process->m_SymHandle, Image->m_BaseOfImage, Name,
  1293. CountSymbolMatches, &Context);
  1294. *Symbol = Context.ReturnSymInfo;
  1295. Symbol->MaxNameLen = MaxName;
  1296. if (Symbol->MaxNameLen > Context.ReturnSymInfo.NameLen)
  1297. {
  1298. strcpy(Symbol->Name, Context.ReturnSymInfo.Name);
  1299. }
  1300. Matches = Context.Matches;
  1301. }
  1302. if (Matches == 1 &&
  1303. !ForceSymbolCodeAddress(Process, Symbol, Machine))
  1304. {
  1305. return 0;
  1306. }
  1307. return Matches;
  1308. }
  1309. ULONG
  1310. GetOffsetFromSym(ProcessInfo* Process,
  1311. PCSTR String,
  1312. PULONG64 Offset,
  1313. ImageInfo** Image)
  1314. {
  1315. CHAR ModifiedString[MAX_SYMBOL_LEN + 64];
  1316. CHAR Suffix[2];
  1317. SYMBOL_INFO SymInfo = {0};
  1318. ULONG Count;
  1319. if (Image != NULL)
  1320. {
  1321. *Image = NULL;
  1322. }
  1323. if (strlen(String) >= MAX_SYMBOL_LEN)
  1324. {
  1325. return 0;
  1326. }
  1327. //
  1328. // We can't do anything without a current process.
  1329. //
  1330. if (Process == NULL)
  1331. {
  1332. return 0;
  1333. }
  1334. if ( strlen(String) == 0 )
  1335. {
  1336. return 0;
  1337. }
  1338. if (Process->GetOffsetFromMod(String, Offset) ||
  1339. GetOffsetFromBreakpoint(String, Offset))
  1340. {
  1341. return 1;
  1342. }
  1343. //
  1344. // If a module name was given look up the module
  1345. // and determine the processor type so that the
  1346. // appropriate machine is used for the following
  1347. // machine-specific operations.
  1348. //
  1349. ImageInfo* StrImage;
  1350. PCSTR ModSep = strchr(String, '!');
  1351. if (ModSep != NULL)
  1352. {
  1353. StrImage = Process->
  1354. FindImageByName(String, (ULONG)(ModSep - String),
  1355. INAME_MODULE, TRUE);
  1356. if (Image != NULL)
  1357. {
  1358. *Image = StrImage;
  1359. }
  1360. }
  1361. else
  1362. {
  1363. StrImage = NULL;
  1364. }
  1365. MachineInfo* Machine = Process->m_Target->m_EffMachine;
  1366. if (StrImage != NULL)
  1367. {
  1368. Machine = MachineTypeInfo(Process->m_Target,
  1369. StrImage->GetMachineType());
  1370. if (Machine == NULL)
  1371. {
  1372. Machine = Process->m_Target->m_EffMachine;
  1373. }
  1374. }
  1375. if ( g_PrefixSymbols && Machine->m_SymPrefix != NULL )
  1376. {
  1377. PCSTR PreString;
  1378. PCSTR RegString;
  1379. PreString = PrependPrefixToSymbol( ModifiedString, String,
  1380. &RegString );
  1381. if ( Count =
  1382. MultiSymFromName( Process, (PSTR)PreString,
  1383. StrImage, Machine, &SymInfo ) )
  1384. {
  1385. *Offset = SymInfo.Address;
  1386. goto GotOffsetSuccess;
  1387. }
  1388. if ( (PreString != String) &&
  1389. (Count =
  1390. MultiSymFromName( Process, (PSTR)String,
  1391. StrImage, Machine, &SymInfo ) ) )
  1392. {
  1393. // Ambiguous plabels shouldn't be further resolved,
  1394. // so just return the information for the plabel.
  1395. if (Count > 1)
  1396. {
  1397. *Offset = SymInfo.Address;
  1398. goto GotOffsetSuccess;
  1399. }
  1400. if (!Machine->GetPrefixedSymbolOffset(Process, SymInfo.Address,
  1401. GETPREF_VERBOSE,
  1402. Offset))
  1403. {
  1404. // This symbol doesn't appear to actually
  1405. // be a plabel so just use the symbol address.
  1406. *Offset = SymInfo.Address;
  1407. }
  1408. goto GotOffsetSuccess;
  1409. }
  1410. }
  1411. else if (Count =
  1412. MultiSymFromName( Process, (PSTR)String,
  1413. StrImage, Machine, &SymInfo ))
  1414. {
  1415. *Offset = SymInfo.Address;
  1416. goto GotOffsetSuccess;
  1417. }
  1418. if (g_SymbolSuffix != 'n')
  1419. {
  1420. strcpy( ModifiedString, String );
  1421. Suffix[0] = g_SymbolSuffix;
  1422. Suffix[1] = '\0';
  1423. strcat( ModifiedString, Suffix );
  1424. if (Count =
  1425. MultiSymFromName( Process, ModifiedString,
  1426. StrImage, Machine, &SymInfo ))
  1427. {
  1428. *Offset = SymInfo.Address;
  1429. goto GotOffsetSuccess;
  1430. }
  1431. }
  1432. return 0;
  1433. GotOffsetSuccess:
  1434. TranslateAddress(SymInfo.ModBase, SymInfo.Flags,
  1435. Machine->CvRegToMachine((CV_HREG_e)SymInfo.Register),
  1436. Offset, &SymInfo.Value);
  1437. if (SymInfo.Flags & SYMFLAG_REGISTER)
  1438. {
  1439. *Offset = SymInfo.Value;
  1440. }
  1441. return Count;
  1442. }
  1443. void
  1444. CreateModuleNameFromPath(LPSTR ImagePath, LPSTR ModuleName)
  1445. {
  1446. PSTR Scan;
  1447. CopyString( ModuleName, PathTail(ImagePath), MAX_MODULE );
  1448. Scan = strrchr( ModuleName, '.' );
  1449. if (Scan != NULL)
  1450. {
  1451. *Scan = '\0';
  1452. }
  1453. }
  1454. void
  1455. GetAdjacentSymOffsets(ULONG64 AddrStart,
  1456. PULONG64 PrevOffset,
  1457. PULONG64 NextOffset)
  1458. {
  1459. DWORD64 Displacement;
  1460. //
  1461. // assume failure
  1462. //
  1463. *PrevOffset = 0;
  1464. *NextOffset = (ULONG64) -1;
  1465. //
  1466. // get the symbol for the initial address
  1467. //
  1468. if (!SymGetSymFromAddr64(g_Process->m_SymHandle, AddrStart, &Displacement,
  1469. g_Sym))
  1470. {
  1471. return;
  1472. }
  1473. *PrevOffset = g_Sym->Address;
  1474. if (SymGetSymNext64(g_Process->m_SymHandle, g_Sym))
  1475. {
  1476. *NextOffset = g_Sym->Address;
  1477. }
  1478. }
  1479. BOOL
  1480. SymbolCallbackFunction(HANDLE ProcessSymHandle,
  1481. ULONG ActionCode,
  1482. ULONG64 CallbackData,
  1483. ULONG64 UserContext)
  1484. {
  1485. PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 DefLoad;
  1486. PIMAGEHLP_CBA_READ_MEMORY ReadMem;
  1487. PIMAGEHLP_CBA_EVENT Event;
  1488. ImageInfo* Image;
  1489. ULONG i;
  1490. ULONG OldSymOptions;
  1491. PVOID Mapping;
  1492. ProcessInfo* Process =
  1493. (ProcessInfo*)(ULONG_PTR)UserContext;
  1494. DefLoad = (PIMAGEHLP_DEFERRED_SYMBOL_LOAD64) CallbackData;
  1495. switch(ActionCode)
  1496. {
  1497. case CBA_DEBUG_INFO:
  1498. DBG_ASSERT(CallbackData && *(LPSTR)CallbackData);
  1499. CompletePartialLine(DEBUG_OUTPUT_SYMBOLS);
  1500. MaskOut(DEBUG_OUTPUT_SYMBOLS, "%s", (LPSTR)CallbackData);
  1501. return TRUE;
  1502. case CBA_EVENT:
  1503. Event = (PIMAGEHLP_CBA_EVENT)CallbackData;
  1504. DBG_ASSERT(Event);
  1505. if (Event->desc && *Event->desc)
  1506. {
  1507. dprintf("%s", Event->desc);
  1508. if (Event->severity >= sevProblem)
  1509. {
  1510. FlushCallbacks();
  1511. }
  1512. }
  1513. return TRUE;
  1514. case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
  1515. return PollUserInterrupt(TRUE);
  1516. case CBA_DEFERRED_SYMBOL_LOAD_START:
  1517. Image = Process->FindImageByOffset(DefLoad->BaseOfImage, FALSE);
  1518. if (Image)
  1519. {
  1520. // Try to load the image memory right away in this
  1521. // case to catch incomplete-information errors.
  1522. if (!Image->DemandLoadImageMemory(TRUE, TRUE))
  1523. {
  1524. return FALSE;
  1525. }
  1526. // Update dbghelp with the latest image file handle
  1527. // as loading image memory may have given us one.
  1528. DefLoad->hFile = Image->m_File;
  1529. VerbOut("Loading symbols for %s %16s -> ",
  1530. FormatAddr64(DefLoad->BaseOfImage),
  1531. DefLoad->FileName);
  1532. return TRUE;
  1533. }
  1534. break;
  1535. case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
  1536. //
  1537. // dbghelp wasn't able to get complete
  1538. // information about an image and so had
  1539. // to do some guessing when loading symbols.
  1540. // Returning FALSE means do the best that
  1541. // dbghelp can. Returning TRUE means try
  1542. // again with any updated data we provide here.
  1543. // We use this as an opportunity to go out
  1544. // and attempt to load image files to get
  1545. // image information that may not be present in
  1546. // the debuggee and thus we are creating information
  1547. // that's not really present. Hopefully we'll find
  1548. // the right image and not come up with incorrect information.
  1549. //
  1550. // Don't do this if the user has asked for exact
  1551. // symbols as the in-memory image may not exactly
  1552. // match what's on disk even if the headers are similar.
  1553. if (g_SymOptions & SYMOPT_EXACT_SYMBOLS)
  1554. {
  1555. return FALSE;
  1556. }
  1557. Image = Process->FindImageByOffset(DefLoad->BaseOfImage, FALSE);
  1558. if (!Image ||
  1559. Image->m_File ||
  1560. Image->m_MapAlreadyFailed ||
  1561. !(Mapping =
  1562. FindImageFile(Process, Image->m_ImagePath, Image->m_SizeOfImage,
  1563. Image->m_CheckSum, Image->m_TimeDateStamp,
  1564. &Image->m_File, Image->m_MappedImagePath)))
  1565. {
  1566. return FALSE;
  1567. }
  1568. // This file handle is only good as long as the
  1569. // image information doesn't change.
  1570. Image->m_FileIsDemandMapped = TRUE;
  1571. // We don't need the actual file mapping, just
  1572. // the file handle.
  1573. UnmapViewOfFile(Mapping);
  1574. // Update dbghelp with the latest image file handle
  1575. // as loading the image has given us one.
  1576. DefLoad->Reparse = TRUE;
  1577. DefLoad->hFile = Image->m_File;
  1578. if (g_SymOptions & SYMOPT_DEBUG)
  1579. {
  1580. CompletePartialLine(DEBUG_OUTPUT_SYMBOLS);
  1581. MaskOut(DEBUG_OUTPUT_SYMBOLS,
  1582. "DBGENG: Partial symbol load found image %s.\n",
  1583. Image->m_MappedImagePath);
  1584. }
  1585. return TRUE;
  1586. case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
  1587. if (IS_KERNEL_TARGET(Process->m_Target) &&
  1588. DefLoad->SizeOfStruct >=
  1589. FIELD_OFFSET(IMAGEHLP_DEFERRED_SYMBOL_LOAD, Reparse))
  1590. {
  1591. i = 0;
  1592. if (strncmp(DefLoad->FileName, "dump_", sizeof("dump_")-1) == 0)
  1593. {
  1594. i = sizeof("dump_")-1;
  1595. }
  1596. if (strncmp(DefLoad->FileName, "hiber_", sizeof("hiber_")-1) == 0)
  1597. {
  1598. i = sizeof("hiber_")-1;
  1599. }
  1600. if (i)
  1601. {
  1602. if (_stricmp (DefLoad->FileName+i, "scsiport.sys") == 0)
  1603. {
  1604. strcpy (DefLoad->FileName, "diskdump.sys");
  1605. }
  1606. else
  1607. {
  1608. strcpy(DefLoad->FileName, DefLoad->FileName+i);
  1609. }
  1610. DefLoad->Reparse = TRUE;
  1611. return TRUE;
  1612. }
  1613. }
  1614. if (DefLoad->FileName && *DefLoad->FileName)
  1615. {
  1616. VerbOut("*** Error: could not load symbols for %s\n",
  1617. DefLoad->FileName);
  1618. }
  1619. else
  1620. {
  1621. VerbOut("*** Error: could not load symbols [MODNAME UNKNOWN]\n");
  1622. }
  1623. break;
  1624. case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
  1625. Image = Process->FindImageByOffset(DefLoad->BaseOfImage, FALSE);
  1626. if (!Image)
  1627. {
  1628. VerbOut("\n");
  1629. break;
  1630. }
  1631. // Do not load unqualified symbols in this callback since this
  1632. // could result in stack overflow.
  1633. OldSymOptions = SymGetOptions();
  1634. SymSetOptions(OldSymOptions | SYMOPT_NO_UNQUALIFIED_LOADS);
  1635. VerbOut("%s\n", DefLoad->FileName);
  1636. Image->ValidateSymbolLoad(DefLoad);
  1637. NotifyChangeSymbolState(DEBUG_CSS_LOADS,
  1638. DefLoad->BaseOfImage, Process);
  1639. SymSetOptions(OldSymOptions);
  1640. return TRUE;
  1641. case CBA_SYMBOLS_UNLOADED:
  1642. VerbOut("Symbols unloaded for %s %s\n",
  1643. FormatAddr64(DefLoad->BaseOfImage),
  1644. DefLoad->FileName);
  1645. break;
  1646. case CBA_READ_MEMORY:
  1647. ReadMem = (PIMAGEHLP_CBA_READ_MEMORY)CallbackData;
  1648. return Process->m_Target->
  1649. ReadVirtual(Process,
  1650. ReadMem->addr,
  1651. ReadMem->buf,
  1652. ReadMem->bytes,
  1653. ReadMem->bytesread) == S_OK;
  1654. case CBA_SET_OPTIONS:
  1655. // Symbol options are set through the interface
  1656. // so the debugger generally knows about them
  1657. // already. The only flags that we want to check
  1658. // here are internal flags that can be changed through
  1659. // !sym or other dbghelp extension commands.
  1660. // There is no need to notify here for internal flag
  1661. // changes.
  1662. #define DBGHELP_CHANGE_SYMOPT \
  1663. (SYMOPT_NO_PROMPTS | \
  1664. SYMOPT_DEBUG)
  1665. g_SymOptions = (g_SymOptions & ~DBGHELP_CHANGE_SYMOPT) |
  1666. (*(PULONG)CallbackData & DBGHELP_CHANGE_SYMOPT);
  1667. break;
  1668. default:
  1669. return FALSE;
  1670. }
  1671. return FALSE;
  1672. }
  1673. BOOL
  1674. ValidatePathComponent(PCSTR Part)
  1675. {
  1676. if (strlen(Part) == 0)
  1677. {
  1678. return FALSE;
  1679. }
  1680. else if (!_strnicmp(Part, "SYMSRV*", 7) ||
  1681. !_strnicmp(Part, "SRV*", 4) ||
  1682. IsUrlPathComponent(Part))
  1683. {
  1684. // No easy way to validate symbol server or URL paths.
  1685. // They're virtually always network references,
  1686. // so just disallow all such usage when net
  1687. // access isn't allowed.
  1688. if (g_EngOptions & DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS)
  1689. {
  1690. return FALSE;
  1691. }
  1692. return TRUE;
  1693. }
  1694. else
  1695. {
  1696. DWORD Attrs;
  1697. DWORD OldMode;
  1698. char Expand[MAX_PATH];
  1699. // Otherwise make sure this is a valid directory.
  1700. if (!ExpandEnvironmentStrings(Part, Expand, sizeof(Expand)))
  1701. {
  1702. return FALSE;
  1703. }
  1704. if (g_EngOptions & DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS)
  1705. {
  1706. // Don't call GetFileAttributes when network paths
  1707. // are disabled as net operations may cause deadlocks.
  1708. if (NetworkPathCheck(Expand) != ERROR_SUCCESS)
  1709. {
  1710. return FALSE;
  1711. }
  1712. }
  1713. // We can still get to this point when debugging CSR
  1714. // if the user has explicitly allowed net paths.
  1715. // This check isn't important enough to risk a hang.
  1716. if (AnySystemProcesses(TRUE))
  1717. {
  1718. return TRUE;
  1719. }
  1720. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  1721. Attrs = GetFileAttributes(Expand);
  1722. SetErrorMode(OldMode);
  1723. return Attrs != 0xffffffff && (Attrs & FILE_ATTRIBUTE_DIRECTORY);
  1724. }
  1725. }
  1726. void
  1727. SetSymbolSearchPath(ProcessInfo* Process)
  1728. {
  1729. LPSTR lpExePathEnv;
  1730. size_t cbExePath;
  1731. LPSTR lpSymPathEnv;
  1732. LPSTR lpAltSymPathEnv;
  1733. size_t cbSymPath;
  1734. LPSTR NewMem;
  1735. //
  1736. // Load the Binary path (needed for triage dumps)
  1737. //
  1738. // No clue why this or the next is 18 ...
  1739. cbExePath = 18;
  1740. if (g_ExecutableImageSearchPath)
  1741. {
  1742. cbExePath += strlen(g_ExecutableImageSearchPath) + 1;
  1743. }
  1744. lpExePathEnv = NULL;
  1745. if ((g_SymOptions & SYMOPT_IGNORE_NT_SYMPATH) == 0 &&
  1746. (lpExePathEnv = getenv("_NT_EXECUTABLE_IMAGE_PATH")))
  1747. {
  1748. cbExePath += strlen(lpExePathEnv) + 1;
  1749. }
  1750. NewMem = (char*)realloc(g_ExecutableImageSearchPath, cbExePath);
  1751. if (!NewMem)
  1752. {
  1753. ErrOut("Not enough memory to allocate/initialize "
  1754. "ExecutableImageSearchPath");
  1755. return;
  1756. }
  1757. if (!g_ExecutableImageSearchPath)
  1758. {
  1759. *NewMem = 0;
  1760. }
  1761. g_ExecutableImageSearchPath = NewMem;
  1762. if ((g_SymOptions & SYMOPT_IGNORE_NT_SYMPATH) == 0)
  1763. {
  1764. AppendComponentsToPath(g_ExecutableImageSearchPath, lpExePathEnv,
  1765. TRUE);
  1766. }
  1767. //
  1768. // Load symbol Path
  1769. //
  1770. cbSymPath = 18;
  1771. if (g_SymbolSearchPath)
  1772. {
  1773. cbSymPath += strlen(g_SymbolSearchPath) + 1;
  1774. }
  1775. if ((g_SymOptions & SYMOPT_IGNORE_NT_SYMPATH) == 0 &&
  1776. (lpSymPathEnv = getenv("_NT_SYMBOL_PATH")))
  1777. {
  1778. cbSymPath += strlen(lpSymPathEnv) + 1;
  1779. }
  1780. if ((g_SymOptions & SYMOPT_IGNORE_NT_SYMPATH) == 0 &&
  1781. (lpAltSymPathEnv = getenv("_NT_ALT_SYMBOL_PATH")))
  1782. {
  1783. cbSymPath += strlen(lpAltSymPathEnv) + 1;
  1784. }
  1785. NewMem = (char*)realloc(g_SymbolSearchPath, cbSymPath);
  1786. if (!NewMem)
  1787. {
  1788. ErrOut("Not enough memory to allocate/initialize "
  1789. "SymbolSearchPath");
  1790. return;
  1791. }
  1792. if (!g_SymbolSearchPath)
  1793. {
  1794. *NewMem = 0;
  1795. }
  1796. g_SymbolSearchPath = NewMem;
  1797. if ((g_SymOptions & SYMOPT_IGNORE_NT_SYMPATH) == 0)
  1798. {
  1799. AppendComponentsToPath(g_SymbolSearchPath, lpAltSymPathEnv, TRUE);
  1800. AppendComponentsToPath(g_SymbolSearchPath, lpSymPathEnv, TRUE);
  1801. }
  1802. SymSetSearchPath( Process->m_SymHandle, g_SymbolSearchPath );
  1803. dprintf("Symbol search path is: %s\n",
  1804. *g_SymbolSearchPath ?
  1805. g_SymbolSearchPath :
  1806. "*** Invalid *** : Verify _NT_SYMBOL_PATH setting" );
  1807. if (g_ExecutableImageSearchPath)
  1808. {
  1809. dprintf("Executable search path is: %s\n",
  1810. g_ExecutableImageSearchPath);
  1811. }
  1812. }
  1813. BOOL
  1814. SetCurrentScope(
  1815. IN PDEBUG_STACK_FRAME ScopeFrame,
  1816. IN OPTIONAL PVOID ScopeContext,
  1817. IN ULONG ScopeContextSize
  1818. )
  1819. {
  1820. BOOL ScopeChanged;
  1821. PDEBUG_SCOPE Scope = &g_ScopeBuffer;
  1822. if (Scope->State == ScopeDefaultLazy)
  1823. {
  1824. // It's not a lazy scope now.
  1825. Scope->State = ScopeDefault;
  1826. }
  1827. if (ScopeFrame->FrameNumber != 0)
  1828. {
  1829. // Backup 1 byte to get correct scoped locals
  1830. ScopeFrame->InstructionOffset--;
  1831. }
  1832. Scope->Process = g_Process;
  1833. Scope->CheckedForThis = FALSE;
  1834. ZeroMemory(&Scope->ThisData, sizeof(Scope->ThisData));
  1835. ScopeChanged = g_Process &&
  1836. SymSetContext(g_Process->m_SymHandle,
  1837. (PIMAGEHLP_STACK_FRAME) ScopeFrame,
  1838. ScopeContext);
  1839. if (ScopeFrame->FrameNumber != 0)
  1840. {
  1841. // restore backed up byte
  1842. ScopeFrame->InstructionOffset++;
  1843. }
  1844. if (ScopeContext && (sizeof(Scope->Context) >= ScopeContextSize))
  1845. {
  1846. memcpy(&Scope->Context, ScopeContext, ScopeContextSize);
  1847. Scope->ContextState = MCTX_FULL;
  1848. Scope->State = ScopeFromContext;
  1849. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS, DEBUG_ANY_ID);
  1850. }
  1851. if (ScopeChanged ||
  1852. (ScopeFrame->FrameOffset != Scope->Frame.FrameOffset))
  1853. {
  1854. Scope->Frame = *ScopeFrame;
  1855. if (ScopeFrame->FuncTableEntry)
  1856. {
  1857. // Cache the FPO data since the pointer is only temporary
  1858. Scope->CachedFpo =
  1859. *((PFPO_DATA) ScopeFrame->FuncTableEntry);
  1860. Scope->Frame.FuncTableEntry =
  1861. (ULONG64) &Scope->CachedFpo;
  1862. }
  1863. NotifyChangeSymbolState(DEBUG_CSS_SCOPE, 0, g_Process);
  1864. }
  1865. else
  1866. {
  1867. Scope->Frame = *ScopeFrame;
  1868. if (ScopeFrame->FuncTableEntry)
  1869. {
  1870. // Cache the FPO data since the pointer is only temporary
  1871. Scope->CachedFpo =
  1872. *((PFPO_DATA) ScopeFrame->FuncTableEntry);
  1873. Scope->Frame.FuncTableEntry =
  1874. (ULONG64) &Scope->CachedFpo;
  1875. }
  1876. }
  1877. return ScopeChanged;
  1878. }
  1879. BOOL
  1880. ResetCurrentScopeLazy(void)
  1881. {
  1882. PDEBUG_SCOPE Scope = &g_ScopeBuffer;
  1883. if (Scope->State == ScopeFromContext)
  1884. {
  1885. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS, DEBUG_ANY_ID);
  1886. }
  1887. Scope->State = ScopeDefaultLazy;
  1888. return TRUE;
  1889. }
  1890. BOOL
  1891. ResetCurrentScope(void)
  1892. {
  1893. DEBUG_STACK_FRAME LocalFrame;
  1894. PDEBUG_SCOPE Scope = &g_ScopeBuffer;
  1895. if (Scope->State == ScopeFromContext)
  1896. {
  1897. NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS, DEBUG_ANY_ID);
  1898. }
  1899. Scope->State = ScopeDefault;
  1900. ZeroMemory(&LocalFrame, sizeof(LocalFrame));
  1901. // At the initial kernel load the system is only partially
  1902. // initialized and is very sensitive to bad memory reads.
  1903. // Stack traces can cause reads through unusual memory areas
  1904. // so it's best to avoid them at this time. This isn't
  1905. // much of a problem since users don't usually expect a locals
  1906. // context at this point.
  1907. if ((IS_USER_TARGET(g_Target) ||
  1908. (g_EngStatus & ENG_STATUS_AT_INITIAL_MODULE_LOAD) == 0) &&
  1909. IS_CUR_CONTEXT_ACCESSIBLE())
  1910. {
  1911. if (!StackTrace(NULL, 0, 0, 0, STACK_ALL_DEFAULT,
  1912. &LocalFrame, 1, 0, 0, TRUE))
  1913. {
  1914. ADDR Addr;
  1915. g_Machine->GetPC(&Addr);
  1916. LocalFrame.InstructionOffset = Addr.off;
  1917. }
  1918. }
  1919. return SetCurrentScope(&LocalFrame, NULL, 0);
  1920. }
  1921. ULONG
  1922. GetCurrentScopeThisData(TypedData* Data)
  1923. {
  1924. PDEBUG_SCOPE Scope = GetCurrentScope();
  1925. if (!Scope->CheckedForThis)
  1926. {
  1927. ULONG Tag;
  1928. if (Scope->ThisData.FindSymbol(Scope->Process,
  1929. "this",
  1930. TDACC_REQUIRE,
  1931. g_Machine->m_Ptr64 ? 8 : 4) ||
  1932. !Scope->ThisData.m_Image ||
  1933. !Scope->ThisData.IsPointer() ||
  1934. Scope->ThisData.GetTypeTag(Scope->ThisData.m_NextType, &Tag) ||
  1935. Tag != SymTagUDT)
  1936. {
  1937. ZeroMemory(&Scope->ThisData, sizeof(Scope->ThisData));
  1938. }
  1939. Scope->CheckedForThis = TRUE;
  1940. }
  1941. if (!Scope->ThisData.m_Image)
  1942. {
  1943. return VARDEF;
  1944. }
  1945. *Data = Scope->ThisData;
  1946. return NO_ERROR;
  1947. }
  1948. void
  1949. ListUnloadedModules(ULONG Flags, PSTR Pattern)
  1950. {
  1951. UnloadedModuleInfo* Unl;
  1952. g_Process->m_NumUnloadedModules = 0;
  1953. Unl = g_Target->GetUnloadedModuleInfo();
  1954. if (Unl == NULL || Unl->Initialize(g_Thread) != S_OK)
  1955. {
  1956. // User-mode only has an unloaded module list
  1957. // for .NET Server, so don't show any errors
  1958. // if there isn't one.
  1959. if (IS_KERNEL_TARGET(g_Target))
  1960. {
  1961. ErrOut("No unloaded module list present\n");
  1962. }
  1963. return;
  1964. }
  1965. char UnlName[MAX_INFO_UNLOADED_NAME];
  1966. DEBUG_MODULE_PARAMETERS Params;
  1967. if (Flags & LUM_OUTPUT)
  1968. {
  1969. dprintf("Unloaded modules:\n");
  1970. }
  1971. while (Unl->GetEntry(UnlName, &Params) == S_OK)
  1972. {
  1973. g_Process->m_NumUnloadedModules++;
  1974. if (Pattern != NULL &&
  1975. !MatchPattern(UnlName, Pattern))
  1976. {
  1977. continue;
  1978. }
  1979. if (Flags & LUM_OUTPUT_TERSE)
  1980. {
  1981. dprintf(".");
  1982. continue;
  1983. }
  1984. if (Flags & LUM_OUTPUT)
  1985. {
  1986. dprintf("%s %s %-8s\n",
  1987. FormatAddr64(Params.Base),
  1988. FormatAddr64(Params.Base + Params.Size),
  1989. UnlName);
  1990. }
  1991. if (Flags & ( LUM_OUTPUT_VERBOSE | LUM_OUTPUT_IMAGE_INFO))
  1992. {
  1993. PSTR TimeDateStr = TimeToStr(Params.TimeDateStamp);
  1994. dprintf(" Timestamp: %s (%08X)\n",
  1995. TimeDateStr, Params.TimeDateStamp);
  1996. dprintf(" Checksum: %08X\n", Params.Checksum);
  1997. }
  1998. }
  1999. dprintf("\n");
  2000. }
  2001. ULONG
  2002. ModuleMachineType(ProcessInfo* Process, ULONG64 Offset)
  2003. {
  2004. ImageInfo* Image = Process->FindImageByOffset(Offset, FALSE);
  2005. return Image ? Image->GetMachineType() : IMAGE_FILE_MACHINE_UNKNOWN;
  2006. }
  2007. ULONG
  2008. IsInFastSyscall(ULONG64 Addr, PULONG64 Base)
  2009. {
  2010. if (Addr >= g_Target->m_TypeInfo.UmSharedSysCallOffset &&
  2011. Addr < g_Target->m_TypeInfo.UmSharedSysCallOffset +
  2012. g_Target->m_TypeInfo.UmSharedSysCallSize)
  2013. {
  2014. *Base = g_Target->m_TypeInfo.UmSharedSysCallOffset;
  2015. return FSC_FOUND;
  2016. }
  2017. return FSC_NONE;
  2018. }
  2019. BOOL
  2020. ShowFunctionParameters(PDEBUG_STACK_FRAME StackFrame)
  2021. {
  2022. SYM_DUMP_PARAM_EX SymFunction = {0};
  2023. ULONG Status = 0;
  2024. PDEBUG_SCOPE Scope = GetCurrentScope();
  2025. DEBUG_SCOPE SavScope = *Scope;
  2026. SymFunction.size = sizeof(SYM_DUMP_PARAM_EX);
  2027. SymFunction.addr = StackFrame->InstructionOffset;
  2028. SymFunction.Options = DBG_DUMP_COMPACT_OUT | DBG_DUMP_FUNCTION_FORMAT;
  2029. // SetCurrentScope to this function
  2030. SymSetContext(g_Process->m_SymHandle,
  2031. (PIMAGEHLP_STACK_FRAME) StackFrame, NULL);
  2032. Scope->Frame = *StackFrame;
  2033. if (StackFrame->FuncTableEntry)
  2034. {
  2035. // Cache the FPO data since the pointer is only temporary
  2036. Scope->CachedFpo = *((PFPO_DATA) StackFrame->FuncTableEntry);
  2037. Scope->Frame.FuncTableEntry =
  2038. (ULONG64) &Scope->CachedFpo;
  2039. }
  2040. if (!SymbolTypeDumpNew(&SymFunction, &Status) &&
  2041. !Status)
  2042. {
  2043. Status = TRUE;
  2044. }
  2045. g_ScopeBuffer = SavScope;
  2046. SymSetContext(g_Process->m_SymHandle,
  2047. (PIMAGEHLP_STACK_FRAME) &Scope->Frame, NULL);
  2048. return !Status;
  2049. }