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.

608 lines
14 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // General expression evaluation support.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1990-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. ULONG g_EvalSyntax;
  10. TypedData g_LastEvalResult;
  11. EvalExpression* g_EvalReleaseChain;
  12. EvalExpression* g_EvalCache[EVAL_COUNT];
  13. EvalExpression*
  14. GetEvaluator(ULONG Syntax, BOOL RetFail)
  15. {
  16. EvalExpression* Eval;
  17. //
  18. // Evaluators contain state and so a single
  19. // global evaluator instance cannot be used
  20. // if there's any possibility of nested
  21. // evaluation. Instead we dynamically provide
  22. // an evaluator any time there's a need for
  23. // evaluation so that each nesting of a nested
  24. // evaluation will have its own state.
  25. //
  26. Eval = g_EvalCache[Syntax];
  27. if (Eval)
  28. {
  29. g_EvalCache[Syntax] = NULL;
  30. }
  31. else
  32. {
  33. switch(Syntax)
  34. {
  35. case DEBUG_EXPR_MASM:
  36. Eval = new MasmEvalExpression;
  37. break;
  38. case DEBUG_EXPR_CPLUSPLUS:
  39. Eval = new CppEvalExpression;
  40. break;
  41. default:
  42. if (RetFail)
  43. {
  44. return NULL;
  45. }
  46. else
  47. {
  48. error(IMPLERR);
  49. }
  50. }
  51. if (!Eval)
  52. {
  53. if (RetFail)
  54. {
  55. return NULL;
  56. }
  57. else
  58. {
  59. error(NOMEMORY);
  60. }
  61. }
  62. }
  63. Eval->m_ReleaseChain = g_EvalReleaseChain;
  64. g_EvalReleaseChain = Eval;
  65. return Eval;
  66. }
  67. void
  68. ReleaseEvaluator(EvalExpression* Eval)
  69. {
  70. if (g_EvalReleaseChain == Eval)
  71. {
  72. g_EvalReleaseChain = Eval->m_ReleaseChain;
  73. }
  74. if (!g_EvalCache[Eval->m_Syntax])
  75. {
  76. Eval->Reset();
  77. g_EvalCache[Eval->m_Syntax] = Eval;
  78. }
  79. else
  80. {
  81. delete Eval;
  82. }
  83. }
  84. void
  85. ReleaseEvaluators(void)
  86. {
  87. BOOL ChainTop = FALSE;
  88. while (g_EvalReleaseChain && !ChainTop)
  89. {
  90. ChainTop = g_EvalReleaseChain->m_ChainTop;
  91. ReleaseEvaluator(g_EvalReleaseChain);
  92. }
  93. }
  94. HRESULT
  95. GetEvaluatorByName(PCSTR AbbrevName, BOOL RetFail,
  96. EvalExpression** EvalRet)
  97. {
  98. for (ULONG i = 0; i < EVAL_COUNT; i++)
  99. {
  100. EvalExpression* Eval = GetEvaluator(i, RetFail);
  101. if (!Eval)
  102. {
  103. return E_OUTOFMEMORY;
  104. }
  105. if (!_stricmp(AbbrevName, Eval->m_AbbrevName))
  106. {
  107. *EvalRet = Eval;
  108. return S_OK;
  109. }
  110. ReleaseEvaluator(Eval);
  111. }
  112. if (!RetFail)
  113. {
  114. error(SYNTAX);
  115. }
  116. return E_NOINTERFACE;
  117. }
  118. CHAR
  119. PeekChar(void)
  120. {
  121. CHAR Ch;
  122. do
  123. {
  124. Ch = *g_CurCmd++;
  125. } while (Ch == ' ' || Ch == '\t' || Ch == '\r' || Ch == '\n');
  126. g_CurCmd--;
  127. return Ch;
  128. }
  129. /*** GetRange - parse address range specification
  130. *
  131. * Purpose:
  132. * With the current command line position, parse an
  133. * address range specification. Forms accepted are:
  134. * <start-addr> - starting address with default length
  135. * <start-addr> <end-addr> - inclusive address range
  136. * <start-addr> l<count> - starting address with item count
  137. *
  138. * Input:
  139. * g_CurCmd - present command line location
  140. * size - nonzero - (for data) size in bytes of items to list
  141. * specification will be "length" type with
  142. * *fLength forced to TRUE.
  143. * zero - (for instructions) specification either "length"
  144. * or "range" type, no size assumption made.
  145. *
  146. * Output:
  147. * *addr - starting address of range
  148. * *value - if *fLength = TRUE, count of items (forced if size != 0)
  149. * FALSE, ending address of range
  150. * (*addr and *value unchanged if no second argument in command)
  151. *
  152. * Returns:
  153. * A value of TRUE is returned if no length is specified, or a length
  154. * or an ending address is specified and size is not zero. Otherwise,
  155. * a value of FALSE is returned.
  156. *
  157. * Exceptions:
  158. * error exit:
  159. * SYNTAX - expression error
  160. * BADRANGE - if ending address before starting address
  161. *
  162. *************************************************************************/
  163. BOOL
  164. GetRange(PADDR Addr,
  165. PULONG64 Value,
  166. ULONG Size,
  167. ULONG SegReg,
  168. ULONG SizeLimit)
  169. {
  170. CHAR Ch;
  171. PSTR Scan;
  172. ADDR EndRange;
  173. BOOL HasL = FALSE;
  174. BOOL HasLength;
  175. BOOL WasSpace = FALSE;
  176. // skip leading whitespace first
  177. PeekChar();
  178. // Pre-parse the line, look for a " L"
  179. for (Scan = g_CurCmd; *Scan; Scan++)
  180. {
  181. if ((*Scan == 'L' || *Scan == 'l') && WasSpace)
  182. {
  183. HasL = TRUE;
  184. *Scan = '\0';
  185. break;
  186. }
  187. else if (*Scan == ';')
  188. {
  189. break;
  190. }
  191. WasSpace = *Scan == ' ';
  192. }
  193. HasLength = TRUE;
  194. if ((Ch = PeekChar()) != '\0' && Ch != ';')
  195. {
  196. GetAddrExpression(SegReg, Addr);
  197. if (((Ch = PeekChar()) != '\0' && Ch != ';') || HasL)
  198. {
  199. if (!HasL)
  200. {
  201. GetAddrExpression(SegReg, &EndRange);
  202. if (AddrGt(*Addr, EndRange))
  203. {
  204. error(BADRANGE);
  205. }
  206. if (Size)
  207. {
  208. *Value = AddrDiff(EndRange, *Addr) / Size + 1;
  209. }
  210. else
  211. {
  212. *Value = Flat(EndRange);
  213. HasLength = FALSE;
  214. }
  215. }
  216. else
  217. {
  218. BOOL Invert;
  219. g_CurCmd = Scan + 1;
  220. if (*g_CurCmd == '-')
  221. {
  222. Invert = TRUE;
  223. g_CurCmd++;
  224. }
  225. else
  226. {
  227. Invert = FALSE;
  228. }
  229. if (*g_CurCmd == '?')
  230. {
  231. // Turn off range length checking.
  232. SizeLimit = 0;
  233. g_CurCmd++;
  234. }
  235. *Value = GetExpressionDesc("Length of range missing from");
  236. *Scan = 'l';
  237. if (Invert)
  238. {
  239. // The user has given an l- range which indicates
  240. // a length before the first address instead of
  241. // a length after the first address.
  242. if (Size)
  243. {
  244. AddrSub(Addr, *Value * Size);
  245. }
  246. else
  247. {
  248. ULONG64 Back = *Value;
  249. *Value = Flat(*Addr);
  250. AddrSub(Addr, Back);
  251. HasLength = FALSE;
  252. }
  253. }
  254. }
  255. // If the length is huge assume the user made
  256. // some kind of mistake.
  257. if (SizeLimit && Size && *Value * Size > SizeLimit)
  258. {
  259. error(BADRANGE);
  260. }
  261. }
  262. }
  263. return HasLength;
  264. }
  265. ULONG64
  266. EvalStringNumAndCatch(PCSTR String)
  267. {
  268. ULONG64 Result;
  269. EvalExpression* RelChain = g_EvalReleaseChain;
  270. g_EvalReleaseChain = NULL;
  271. __try
  272. {
  273. EvalExpression* Eval = GetCurEvaluator();
  274. Result = Eval->EvalStringNum(String);
  275. ReleaseEvaluator(Eval);
  276. }
  277. __except(EXCEPTION_EXECUTE_HANDLER)
  278. {
  279. Result = 0;
  280. }
  281. g_EvalReleaseChain = RelChain;
  282. return Result;
  283. }
  284. ULONG64
  285. GetExpression(void)
  286. {
  287. EvalExpression* Eval = GetCurEvaluator();
  288. ULONG64 Result = Eval->EvalCurNum();
  289. ReleaseEvaluator(Eval);
  290. return Result;
  291. }
  292. ULONG64
  293. GetExpressionDesc(PCSTR Desc)
  294. {
  295. EvalExpression* Eval = GetCurEvaluator();
  296. ULONG64 Result = Eval->EvalCurNumDesc(Desc);
  297. ReleaseEvaluator(Eval);
  298. return Result;
  299. }
  300. ULONG64
  301. GetTermExpression(PCSTR Desc)
  302. {
  303. EvalExpression* Eval = GetCurEvaluator();
  304. ULONG64 Result = Eval->EvalCurTermNumDesc(Desc);
  305. ReleaseEvaluator(Eval);
  306. return Result;
  307. }
  308. void
  309. GetAddrExpression(ULONG SegReg, PADDR Addr)
  310. {
  311. EvalExpression* Eval = GetCurEvaluator();
  312. Eval->EvalCurAddr(SegReg, Addr);
  313. ReleaseEvaluator(Eval);
  314. }
  315. //----------------------------------------------------------------------------
  316. //
  317. // TypedDataStackAllocator.
  318. //
  319. //----------------------------------------------------------------------------
  320. void*
  321. TypedDataStackAllocator::RawAlloc(ULONG Bytes)
  322. {
  323. void* Mem = malloc(Bytes);
  324. if (!Mem)
  325. {
  326. m_Eval->EvalError(NOMEMORY);
  327. }
  328. return Mem;
  329. }
  330. //----------------------------------------------------------------------------
  331. //
  332. // EvalExpression.
  333. //
  334. //----------------------------------------------------------------------------
  335. // 'this' used in initializer list.
  336. #pragma warning(disable:4355)
  337. EvalExpression::EvalExpression(ULONG Syntax, PCSTR FullName, PCSTR AbbrevName)
  338. : m_ResultAlloc(this)
  339. {
  340. m_Syntax = Syntax;
  341. m_FullName = FullName;
  342. m_AbbrevName = AbbrevName;
  343. m_ParseOnly = 0;
  344. m_AllowUnresolvedSymbols = 0;
  345. m_NumUnresolvedSymbols = 0;
  346. m_ReleaseChain = NULL;
  347. m_ChainTop = TRUE;
  348. m_Lex = NULL;
  349. }
  350. #pragma warning(default:4355)
  351. EvalExpression::~EvalExpression(void)
  352. {
  353. }
  354. void
  355. EvalExpression::EvalCurrent(TypedData* Result)
  356. {
  357. g_CurCmd = (PSTR)
  358. Evaluate(g_CurCmd, NULL, EXPRF_DEFAULT, Result);
  359. }
  360. void
  361. EvalExpression::EvalCurAddrDesc(ULONG SegReg, PCSTR Desc, PADDR Addr)
  362. {
  363. //
  364. // Evaluate a normal expression and then
  365. // force the result to be an address.
  366. //
  367. if (Desc == NULL)
  368. {
  369. Desc = "Address expression missing from";
  370. }
  371. NotFlat(*Addr);
  372. g_CurCmd = (PSTR)
  373. EvaluateAddr(g_CurCmd, Desc, SegReg, Addr);
  374. }
  375. ULONG64
  376. EvalExpression::EvalStringNum(PCSTR String)
  377. {
  378. ULONG Err;
  379. TypedData Result;
  380. Evaluate(String, "Numeric expression missing from",
  381. EXPRF_DEFAULT, &Result);
  382. if (Err = Result.ConvertToU64())
  383. {
  384. error(Err);
  385. }
  386. return Result.m_U64;
  387. }
  388. ULONG64
  389. EvalExpression::EvalCurNumDesc(PCSTR Desc)
  390. {
  391. ULONG Err;
  392. TypedData Result;
  393. if (Desc == NULL)
  394. {
  395. Desc = "Numeric expression missing from";
  396. }
  397. g_CurCmd = (PSTR)
  398. Evaluate(g_CurCmd, Desc, EXPRF_DEFAULT, &Result);
  399. if (Err = Result.ConvertToU64())
  400. {
  401. error(Err);
  402. }
  403. return Result.m_U64;
  404. }
  405. ULONG64
  406. EvalExpression::EvalCurTermNumDesc(PCSTR Desc)
  407. {
  408. ULONG Err;
  409. TypedData Result;
  410. if (Desc == NULL)
  411. {
  412. Desc = "Numeric term missing from";
  413. }
  414. g_CurCmd = (PSTR)
  415. Evaluate(g_CurCmd, Desc, EXPRF_SINGLE_TERM, &Result);
  416. if (Err = Result.ConvertToU64())
  417. {
  418. error(Err);
  419. }
  420. return Result.m_U64;
  421. }
  422. void DECLSPEC_NORETURN
  423. EvalExpression::EvalErrorDesc(ULONG Error, PCSTR Desc)
  424. {
  425. if (!g_DisableErrorPrint)
  426. {
  427. PCSTR Text =
  428. !m_LexemeSourceStart || !*m_LexemeSourceStart ?
  429. "<EOL>" : m_LexemeSourceStart;
  430. if (Desc != NULL)
  431. {
  432. ErrOut("%s '%s'\n", Desc, Text);
  433. }
  434. else
  435. {
  436. ErrOut("%s error at '%s'\n", ErrorString(Error), Text);
  437. }
  438. }
  439. ReleaseEvaluators();
  440. RaiseException(COMMAND_EXCEPTION_BASE + Error, 0, 0, NULL);
  441. }
  442. void
  443. EvalExpression::Reset(void)
  444. {
  445. // Clear out any temporary memory that may have been allocated.
  446. m_ResultAlloc.FreeAll();
  447. m_NumUnresolvedSymbols = 0;
  448. m_Lex = NULL;
  449. m_ParseOnly = 0;
  450. m_ReleaseChain = NULL;
  451. }
  452. void
  453. EvalExpression::StartLexer(PCSTR Expr)
  454. {
  455. m_Lex = Expr;
  456. m_LexemeRestart = m_LexemeBuffer;
  457. m_LexemeSourceStart = NULL;
  458. m_AllowUnaryOp = TRUE;
  459. }
  460. void
  461. EvalExpression::Start(PCSTR Expr, PCSTR Desc, ULONG Flags)
  462. {
  463. // This class can't be used recursively.
  464. if (m_Lex || m_ResultAlloc.NumAllocatedChunks())
  465. {
  466. error(IMPLERR);
  467. }
  468. RequireCurrentScope();
  469. m_ExprDesc = Desc;
  470. m_Flags = Flags;
  471. m_Process = g_Process;
  472. if (IS_CUR_MACHINE_ACCESSIBLE())
  473. {
  474. m_Machine = g_Machine;
  475. }
  476. else
  477. {
  478. m_Machine = NULL;
  479. }
  480. m_PtrSize = (m_Machine && m_Machine->m_Ptr64) ? 8 : 4;
  481. StartLexer(Expr);
  482. }
  483. void
  484. EvalExpression::End(TypedData* Result)
  485. {
  486. g_LastEvalResult = *Result;
  487. // Allocator should have been left clean.
  488. DBG_ASSERT(m_ResultAlloc.NumAllocatedChunks() == 0);
  489. }
  490. void
  491. EvalExpression::AddLexeme(char Ch)
  492. {
  493. if (m_LexemeChar - m_LexemeBuffer >= sizeof(m_LexemeBuffer) - 1)
  494. {
  495. EvalErrorDesc(STRINGSIZE, "Lexeme too long in");
  496. }
  497. *m_LexemeChar++ = Ch;
  498. }
  499. void
  500. EvalExpression::InheritStart(EvalExpression* Parent)
  501. {
  502. //
  503. // Pick up heritable state from the parent.
  504. //
  505. if (Parent->m_ParseOnly)
  506. {
  507. m_ParseOnly++;
  508. }
  509. if (Parent->m_AllowUnresolvedSymbols)
  510. {
  511. m_AllowUnresolvedSymbols++;
  512. }
  513. }
  514. void
  515. EvalExpression::InheritEnd(EvalExpression* Parent)
  516. {
  517. //
  518. // Pass heritable state back to the parent.
  519. //
  520. if (Parent->m_ParseOnly)
  521. {
  522. m_ParseOnly--;
  523. }
  524. if (Parent->m_AllowUnresolvedSymbols)
  525. {
  526. Parent->m_NumUnresolvedSymbols += m_NumUnresolvedSymbols;
  527. m_AllowUnresolvedSymbols--;
  528. }
  529. }