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.

2178 lines
57 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // MASM-syntax expression evaluation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1990-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. // token classes (< 100) and types (>= 100)
  10. #define EOL_CLASS 0
  11. #define ADDOP_CLASS 1
  12. #define ADDOP_PLUS 100
  13. #define ADDOP_MINUS 101
  14. #define MULOP_CLASS 2
  15. #define MULOP_MULT 200
  16. #define MULOP_DIVIDE 201
  17. #define MULOP_MOD 202
  18. #define MULOP_SEG 203
  19. //#define MULOP_64 204
  20. #define LOGOP_CLASS 3
  21. #define LOGOP_AND 300
  22. #define LOGOP_OR 301
  23. #define LOGOP_XOR 302
  24. #define LRELOP_CLASS 4
  25. #define LRELOP_EQ 400
  26. #define LRELOP_NE 401
  27. #define LRELOP_LT 402
  28. #define LRELOP_GT 403
  29. #define UNOP_CLASS 5
  30. #define UNOP_NOT 500
  31. #define UNOP_BY 501
  32. #define UNOP_WO 502
  33. #define UNOP_DWO 503
  34. #define UNOP_POI 504
  35. #define UNOP_LOW 505
  36. #define UNOP_HI 506
  37. #define UNOP_QWO 507
  38. #define UNOP_VAL 508
  39. #define LPAREN_CLASS 6
  40. #define RPAREN_CLASS 7
  41. #define LBRACK_CLASS 8
  42. #define RBRACK_CLASS 9
  43. #define REG_CLASS 10
  44. #define NUMBER_CLASS 11
  45. #define SYMBOL_CLASS 12
  46. #define LINE_CLASS 13
  47. #define SHIFT_CLASS 14
  48. #define SHIFT_LEFT 1400
  49. #define SHIFT_RIGHT_LOGICAL 1401
  50. #define SHIFT_RIGHT_ARITHMETIC 1402
  51. #define ERROR_CLASS 99 //only used for PeekToken()
  52. #define INVALID_CLASS -1
  53. struct Res
  54. {
  55. char chRes[3];
  56. ULONG classRes;
  57. ULONG valueRes;
  58. };
  59. Res g_Reserved[] =
  60. {
  61. { 'o', 'r', '\0', LOGOP_CLASS, LOGOP_OR },
  62. { 'b', 'y', '\0', UNOP_CLASS, UNOP_BY },
  63. { 'w', 'o', '\0', UNOP_CLASS, UNOP_WO },
  64. { 'd', 'w', 'o', UNOP_CLASS, UNOP_DWO },
  65. { 'q', 'w', 'o', UNOP_CLASS, UNOP_QWO },
  66. { 'h', 'i', '\0', UNOP_CLASS, UNOP_HI },
  67. { 'm', 'o', 'd', MULOP_CLASS, MULOP_MOD },
  68. { 'x', 'o', 'r', LOGOP_CLASS, LOGOP_XOR },
  69. { 'a', 'n', 'd', LOGOP_CLASS, LOGOP_AND },
  70. { 'p', 'o', 'i', UNOP_CLASS, UNOP_POI },
  71. { 'n', 'o', 't', UNOP_CLASS, UNOP_NOT },
  72. { 'l', 'o', 'w', UNOP_CLASS, UNOP_LOW },
  73. { 'v', 'a', 'l', UNOP_CLASS, UNOP_VAL }
  74. };
  75. Res g_X86Reserved[] =
  76. {
  77. { 'e', 'a', 'x', REG_CLASS, X86_EAX },
  78. { 'e', 'b', 'x', REG_CLASS, X86_EBX },
  79. { 'e', 'c', 'x', REG_CLASS, X86_ECX },
  80. { 'e', 'd', 'x', REG_CLASS, X86_EDX },
  81. { 'e', 'b', 'p', REG_CLASS, X86_EBP },
  82. { 'e', 's', 'p', REG_CLASS, X86_ESP },
  83. { 'e', 'i', 'p', REG_CLASS, X86_EIP },
  84. { 'e', 's', 'i', REG_CLASS, X86_ESI },
  85. { 'e', 'd', 'i', REG_CLASS, X86_EDI },
  86. { 'e', 'f', 'l', REG_CLASS, X86_EFL }
  87. };
  88. #define RESERVESIZE (sizeof(g_Reserved) / sizeof(Res))
  89. #define X86_RESERVESIZE (sizeof(g_X86Reserved) / sizeof(Res))
  90. char * g_X86SegRegs[] =
  91. {
  92. "cs", "ds", "es", "fs", "gs", "ss"
  93. };
  94. #define X86_SEGREGSIZE (sizeof(g_X86SegRegs) / sizeof(char *))
  95. //----------------------------------------------------------------------------
  96. //
  97. // MasmEvalExpression.
  98. //
  99. //----------------------------------------------------------------------------
  100. MasmEvalExpression::MasmEvalExpression(void)
  101. : EvalExpression(DEBUG_EXPR_MASM,
  102. "Microsoft Assembler expressions",
  103. "MASM")
  104. {
  105. m_SavedClass = INVALID_CLASS;
  106. m_ForcePositiveNumber = FALSE;
  107. m_AddrExprType = 0;
  108. m_TypedExpr = FALSE;
  109. }
  110. MasmEvalExpression::~MasmEvalExpression(void)
  111. {
  112. }
  113. PCSTR
  114. MasmEvalExpression::Evaluate(PCSTR Expr, PCSTR Desc, ULONG Flags,
  115. TypedData* Result)
  116. {
  117. ULONG64 Value;
  118. Start(Expr, Desc, Flags);
  119. if (m_Flags & EXPRF_SINGLE_TERM)
  120. {
  121. m_SavedClass = INVALID_CLASS;
  122. Value = GetTerm();
  123. }
  124. else
  125. {
  126. Value = GetCommonExpression();
  127. }
  128. ZeroMemory(Result, sizeof(*Result));
  129. Result->SetToNativeType(DNTYPE_UINT64);
  130. Result->m_U64 = Value;
  131. Expr = m_Lex;
  132. End(Result);
  133. return Expr;
  134. }
  135. PCSTR
  136. MasmEvalExpression::EvaluateAddr(PCSTR Expr, PCSTR Desc,
  137. ULONG SegReg, PADDR Addr)
  138. {
  139. TypedData Result;
  140. Start(Expr, Desc, EXPRF_DEFAULT);
  141. Result.SetU64(GetCommonExpression());
  142. Expr = m_Lex;
  143. End(&Result);
  144. ForceAddrExpression(SegReg, Addr, Result.m_U64);
  145. return Expr;
  146. }
  147. void
  148. MasmEvalExpression::ForceAddrExpression(ULONG SegReg, PADDR Address,
  149. ULONG64 Value)
  150. {
  151. DESCRIPTOR64 DescBuf, *Desc = NULL;
  152. *Address = m_TempAddr;
  153. // Rewriting the offset may change flat address so
  154. // be sure to recompute it later.
  155. Off(*Address) = Value;
  156. // If it wasn't an explicit address expression
  157. // force it to be an address
  158. if (!(m_AddrExprType & ~INSTR_POINTER))
  159. {
  160. // Default to a flat address.
  161. m_AddrExprType = ADDR_FLAT;
  162. // Apply various overrides.
  163. if (g_X86InVm86)
  164. {
  165. m_AddrExprType = ADDR_V86;
  166. }
  167. else if (g_X86InCode16)
  168. {
  169. m_AddrExprType = ADDR_16;
  170. }
  171. else if (g_Machine &&
  172. g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64 &&
  173. !g_Amd64InCode64)
  174. {
  175. m_AddrExprType = ADDR_1632;
  176. }
  177. Address->type = m_AddrExprType;
  178. if (m_AddrExprType != ADDR_FLAT &&
  179. SegReg < SEGREG_COUNT &&
  180. g_Machine &&
  181. g_Machine->GetSegRegDescriptor(SegReg, &DescBuf) == S_OK)
  182. {
  183. ContextSave* Push;
  184. PCROSS_PLATFORM_CONTEXT ScopeContext =
  185. GetCurrentScopeContext();
  186. if (ScopeContext)
  187. {
  188. Push = g_Machine->PushContext(ScopeContext);
  189. }
  190. Address->seg = (USHORT)
  191. g_Machine->FullGetVal32(g_Machine->GetSegRegNum(SegReg));
  192. Desc = &DescBuf;
  193. if (ScopeContext)
  194. {
  195. g_Machine->PopContext(Push);
  196. }
  197. }
  198. else
  199. {
  200. Address->seg = 0;
  201. }
  202. }
  203. else if fnotFlat(*Address)
  204. {
  205. // This case (i.e., m_AddrExprType && !flat) results from
  206. // an override (i.e., %,,&, or #) being used but no segment
  207. // being specified to force a flat address computation.
  208. Type(*Address) = m_AddrExprType;
  209. Address->seg = 0;
  210. if (SegReg < SEGREG_COUNT)
  211. {
  212. // test flag for IP or EIP as register argument
  213. // if so, use CS as default register
  214. if (fInstrPtr(*Address))
  215. {
  216. SegReg = SEGREG_CODE;
  217. }
  218. if (g_Machine &&
  219. g_Machine->GetSegRegDescriptor(SegReg, &DescBuf) == S_OK)
  220. {
  221. ContextSave* Push;
  222. PCROSS_PLATFORM_CONTEXT ScopeContext =
  223. GetCurrentScopeContext();
  224. if (ScopeContext)
  225. {
  226. Push = g_Machine->PushContext(ScopeContext);
  227. }
  228. Address->seg = (USHORT)
  229. g_Machine->FullGetVal32(g_Machine->GetSegRegNum(SegReg));
  230. Desc = &DescBuf;
  231. if (ScopeContext)
  232. {
  233. g_Machine->PopContext(Push);
  234. }
  235. }
  236. }
  237. }
  238. // Force sign-extension of 32-bit flat addresses.
  239. if (Address->type == ADDR_FLAT &&
  240. g_Machine &&
  241. !g_Machine->m_Ptr64)
  242. {
  243. Off(*Address) = EXTEND64(Off(*Address));
  244. }
  245. // Force an updated flat address to be computed.
  246. NotFlat(*Address);
  247. ComputeFlatAddress(Address, Desc);
  248. }
  249. /*
  250. Inputs
  251. Must be ([*|&] Sym[(.->)Field])
  252. Outputs
  253. Evaluates typed expression and returns value
  254. */
  255. LONG64
  256. MasmEvalExpression::GetTypedExpression(void)
  257. {
  258. ULONG64 Value=0;
  259. BOOL AddrOf=FALSE, ValueAt=FALSE;
  260. CHAR c;
  261. static CHAR Name[MAX_NAME], Field[MAX_NAME];
  262. c = Peek();
  263. switch (c)
  264. {
  265. case '(':
  266. m_Lex++;
  267. Value = GetTypedExpression();
  268. c = Peek();
  269. if (c != ')')
  270. {
  271. EvalError(SYNTAX);
  272. return 0;
  273. }
  274. ++m_Lex;
  275. return Value;
  276. case '&':
  277. // Get Offset/Address
  278. // AddrOf = TRUE;
  279. // m_Lex++;
  280. // Peek();
  281. break;
  282. case '*':
  283. default:
  284. break;
  285. }
  286. #if 0
  287. ULONG i=0;
  288. ValueAt = TRUE;
  289. m_Lex++;
  290. Peek();
  291. break;
  292. c = Peek();
  293. while ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
  294. (c >= '0' && c <= '9') || (c == '_') || (c == '$') ||
  295. (c == '!'))
  296. {
  297. // Sym Name
  298. Name[i++] = c;
  299. c = *++m_Lex;
  300. }
  301. Name[i]=0;
  302. if (c=='.')
  303. {
  304. ++m_Lex;
  305. }
  306. else if (c=='-' && *++m_Lex == '>')
  307. {
  308. ++m_Lex;
  309. }
  310. i=0;
  311. c = Peek();
  312. while ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
  313. (c >= '0' && c <= '9') || (c == '_') || (c == '$') ||
  314. (c == '.') || (c == '-') || (c == '>'))
  315. {
  316. Field[i++]= c;
  317. c = *++m_Lex;
  318. }
  319. Field[i] = 0;
  320. SYM_DUMP_PARAM Sym = {0};
  321. FIELD_INFO FieldInfo ={0};
  322. Sym.size = sizeof(SYM_DUMP_PARAM);
  323. Sym.sName = (PUCHAR) Name;
  324. Sym.Options = DBG_DUMP_NO_PRINT;
  325. if (Field[0])
  326. {
  327. Sym.nFields = 1;
  328. Sym.Fields = &FieldInfo;
  329. FieldInfo.fName = (PUCHAR) Field;
  330. if (AddrOf)
  331. {
  332. FieldInfo.fOptions |= DBG_DUMP_FIELD_RETURN_ADDRESS;
  333. }
  334. }
  335. else if (AddrOf)
  336. {
  337. PUCHAR pch = m_Lex;
  338. m_Lex = &Name[0];
  339. Value = GetMterm();
  340. m_Lex = pch;
  341. return Value;
  342. }
  343. else
  344. {
  345. Sym.Options |= DBG_DUMP_GET_SIZE_ONLY;
  346. }
  347. ULONG Status=0;
  348. ULONG Size = SymbolTypeDump(0, NULL, &Sym, &Status);
  349. if (!Status)
  350. {
  351. if (!Field[0] && (Size <= sizeof (Value)))
  352. {
  353. // Call routine again to read value
  354. Sym.Options |= DBG_DUMP_COPY_TYPE_DATA;
  355. Sym.Context = (PVOID) &Value;
  356. if ((SymbolTypeDump(0, NULL, &Sym, &Status) == 8) && (Size == 4))
  357. {
  358. Value = (ULONG) Value;
  359. }
  360. }
  361. else if (Field[0] && (FieldInfo.size <= sizeof(ULONG64)))
  362. {
  363. Value = FieldInfo.address;
  364. }
  365. else // too big
  366. {
  367. Value = 0;
  368. }
  369. }
  370. #endif
  371. ULONG PreferVal = m_Flags & EXPRF_PREFER_SYMBOL_VALUES;
  372. m_Flags |= EXPRF_PREFER_SYMBOL_VALUES;
  373. Value = GetMterm();
  374. m_Flags = (m_Flags & ~EXPRF_PREFER_SYMBOL_VALUES) | PreferVal;
  375. return Value;
  376. }
  377. /*
  378. Evaluate the value in symbol expression Symbol
  379. */
  380. BOOL
  381. MasmEvalExpression::GetSymValue(PSTR Symbol, PULONG64 RetValue)
  382. {
  383. TYPES_INFO_ALL Typ;
  384. if (GetExpressionTypeInfo(Symbol, &Typ))
  385. {
  386. if (Typ.Flags)
  387. {
  388. if (Typ.Flags & SYMFLAG_VALUEPRESENT)
  389. {
  390. *RetValue = Typ.Value;
  391. return TRUE;
  392. }
  393. TranslateAddress(Typ.Module, Typ.Flags, Typ.Register,
  394. &Typ.Address, &Typ.Value);
  395. if (Typ.Value && (Typ.Flags & SYMFLAG_REGISTER))
  396. {
  397. *RetValue = Typ.Value;
  398. return TRUE;
  399. }
  400. }
  401. if (Symbol[0] == '&')
  402. {
  403. *RetValue = Typ.Address;
  404. return TRUE;
  405. }
  406. else if (Typ.Size <= sizeof(*RetValue))
  407. {
  408. ULONG64 Val = 0;
  409. if (CurReadAllVirtual(Typ.Address, &Val, Typ.Size) == S_OK)
  410. {
  411. *RetValue = Val;
  412. return TRUE;
  413. }
  414. }
  415. }
  416. *RetValue = 0;
  417. return FALSE;
  418. }
  419. char
  420. MasmEvalExpression::Peek(void)
  421. {
  422. char Ch;
  423. do
  424. {
  425. Ch = *m_Lex++;
  426. } while (Ch == ' ' || Ch == '\t' || Ch == '\r' || Ch == '\n');
  427. m_Lex--;
  428. return Ch;
  429. }
  430. ULONG64
  431. MasmEvalExpression::GetCommonExpression(void)
  432. {
  433. CHAR ch;
  434. m_SavedClass = INVALID_CLASS;
  435. ch = Peek();
  436. switch(ch)
  437. {
  438. case '&':
  439. m_Lex++;
  440. m_AddrExprType = ADDR_V86;
  441. break;
  442. case '#':
  443. m_Lex++;
  444. m_AddrExprType = ADDR_16;
  445. break;
  446. case '%':
  447. m_Lex++;
  448. m_AddrExprType = ADDR_FLAT;
  449. break;
  450. default:
  451. m_AddrExprType = ADDR_NONE;
  452. break;
  453. }
  454. Peek();
  455. return (ULONG64)StartExpr();
  456. }
  457. /*** StartExpr - Get expression
  458. *
  459. * Purpose:
  460. * Parse logical-terms separated by logical operators into
  461. * expression value.
  462. *
  463. * Input:
  464. * m_Lex - present command line position
  465. *
  466. * Returns:
  467. * long value of logical result.
  468. *
  469. * Exceptions:
  470. * error exit: SYNTAX - bad expression or premature end-of-line
  471. *
  472. * Notes:
  473. * may be called recursively.
  474. * <expr> = <lterm> [<logic-op> <lterm>]*
  475. * <logic-op> = AND (&), OR (|), XOR (^)
  476. *
  477. *************************************************************************/
  478. LONG64
  479. MasmEvalExpression::StartExpr(void)
  480. {
  481. LONG64 value1;
  482. LONG64 value2;
  483. ULONG opclass;
  484. LONG64 oRetValue;
  485. //dprintf("LONG64 StartExpr ()\n");
  486. value1 = GetLRterm();
  487. while ((opclass = PeekToken(&oRetValue)) == LOGOP_CLASS)
  488. {
  489. AcceptToken();
  490. value2 = GetLRterm();
  491. switch (oRetValue)
  492. {
  493. case LOGOP_AND:
  494. value1 &= value2;
  495. break;
  496. case LOGOP_OR:
  497. value1 |= value2;
  498. break;
  499. case LOGOP_XOR:
  500. value1 ^= value2;
  501. break;
  502. default:
  503. EvalError(SYNTAX);
  504. }
  505. }
  506. return value1;
  507. }
  508. /*** GetLRterm - get logical relational term
  509. *
  510. * Purpose:
  511. * Parse logical-terms separated by logical relational
  512. * operators into the expression value.
  513. *
  514. * Input:
  515. * m_Lex - present command line position
  516. *
  517. * Returns:
  518. * long value of logical result.
  519. *
  520. * Exceptions:
  521. * error exit: SYNTAX - bad expression or premature end-of-line
  522. *
  523. * Notes:
  524. * may be called recursively.
  525. * <expr> = <lterm> [<rel-logic-op> <lterm>]*
  526. * <logic-op> = '==' or '=', '!=', '>', '<'
  527. *
  528. *************************************************************************/
  529. LONG64
  530. MasmEvalExpression::GetLRterm(void)
  531. {
  532. LONG64 value1;
  533. LONG64 value2;
  534. ULONG opclass;
  535. LONG64 oRetValue;
  536. //dprintf("LONG64 GetLRterm ()\n");
  537. value1 = GetLterm();
  538. while ((opclass = PeekToken(&oRetValue)) == LRELOP_CLASS)
  539. {
  540. AcceptToken();
  541. value2 = GetLterm();
  542. switch (oRetValue)
  543. {
  544. case LRELOP_EQ:
  545. value1 = (value1 == value2);
  546. break;
  547. case LRELOP_NE:
  548. value1 = (value1 != value2);
  549. break;
  550. case LRELOP_LT:
  551. value1 = (value1 < value2);
  552. break;
  553. case LRELOP_GT:
  554. value1 = (value1 > value2);
  555. break;
  556. default:
  557. EvalError(SYNTAX);
  558. }
  559. }
  560. return value1;
  561. }
  562. /*** GetLterm - get logical term
  563. *
  564. * Purpose:
  565. * Parse shift-terms separated by shift operators into
  566. * logical term value.
  567. *
  568. * Input:
  569. * m_Lex - present command line position
  570. *
  571. * Returns:
  572. * long value of sum.
  573. *
  574. * Exceptions:
  575. * error exit: SYNTAX - bad logical term or premature end-of-line
  576. *
  577. * Notes:
  578. * may be called recursively.
  579. * <lterm> = <sterm> [<shift-op> <sterm>]*
  580. * <shift-op> = <<, >>, >>>
  581. *
  582. *************************************************************************/
  583. LONG64
  584. MasmEvalExpression::GetLterm(void)
  585. {
  586. LONG64 value1 = GetShiftTerm();
  587. LONG64 value2;
  588. ULONG opclass;
  589. LONG64 oRetValue;
  590. //dprintf("LONG64 GetLterm ()\n");
  591. while ((opclass = PeekToken(&oRetValue)) == SHIFT_CLASS)
  592. {
  593. AcceptToken();
  594. value2 = GetShiftTerm();
  595. switch (oRetValue)
  596. {
  597. case SHIFT_LEFT:
  598. value1 <<= value2;
  599. break;
  600. case SHIFT_RIGHT_LOGICAL:
  601. value1 = (LONG64)((ULONG64)value1 >> value2);
  602. break;
  603. case SHIFT_RIGHT_ARITHMETIC:
  604. value1 >>= value2;
  605. break;
  606. default:
  607. EvalError(SYNTAX);
  608. }
  609. }
  610. return value1;
  611. }
  612. /*** GetShiftTerm - get logical term
  613. *
  614. * Purpose:
  615. * Parse additive-terms separated by additive operators into
  616. * shift term value.
  617. *
  618. * Input:
  619. * m_Lex - present command line position
  620. *
  621. * Returns:
  622. * long value of sum.
  623. *
  624. * Exceptions:
  625. * error exit: SYNTAX - bad shift term or premature end-of-line
  626. *
  627. * Notes:
  628. * may be called recursively.
  629. * <sterm> = <aterm> [<add-op> <aterm>]*
  630. * <add-op> = +, -
  631. *
  632. *************************************************************************/
  633. LONG64
  634. MasmEvalExpression::GetShiftTerm(void)
  635. {
  636. LONG64 value1 = GetAterm();
  637. LONG64 value2;
  638. ULONG opclass;
  639. LONG64 oRetValue;
  640. USHORT AddrType1 = m_AddrExprType;
  641. //dprintf("LONG64 GetShifTerm ()\n");
  642. while ((opclass = PeekToken(&oRetValue)) == ADDOP_CLASS)
  643. {
  644. AcceptToken();
  645. value2 = GetAterm();
  646. // If either item is an address we want
  647. // to use the special address arithmetic functions.
  648. // They only handle address+-value, so we may need
  649. // to swap things around to allow their use.
  650. // We can't swap the order of subtraction, plus the
  651. // result of a subtraction should be a constant.
  652. if (AddrType1 == ADDR_NONE && m_AddrExprType != ADDR_NONE &&
  653. oRetValue == ADDOP_PLUS)
  654. {
  655. LONG64 Tmp = value1;
  656. value1 = value2;
  657. value2 = Tmp;
  658. AddrType1 = m_AddrExprType;
  659. }
  660. if (AddrType1 & ~INSTR_POINTER)
  661. {
  662. switch (oRetValue)
  663. {
  664. case ADDOP_PLUS:
  665. AddrAdd(&m_TempAddr, value2);
  666. value1 += value2;
  667. break;
  668. case ADDOP_MINUS:
  669. AddrSub(&m_TempAddr, value2);
  670. value1 -= value2;
  671. break;
  672. default:
  673. EvalError(SYNTAX);
  674. }
  675. }
  676. else
  677. {
  678. switch (oRetValue)
  679. {
  680. case ADDOP_PLUS:
  681. value1 += value2;
  682. break;
  683. case ADDOP_MINUS:
  684. value1 -= value2;
  685. break;
  686. default:
  687. EvalError(SYNTAX);
  688. }
  689. }
  690. }
  691. return value1;
  692. }
  693. /*** GetAterm - get additive term
  694. *
  695. * Purpose:
  696. * Parse multiplicative-terms separated by multipicative operators
  697. * into additive term value.
  698. *
  699. * Input:
  700. * m_Lex - present command line position
  701. *
  702. * Returns:
  703. * long value of product.
  704. *
  705. * Exceptions:
  706. * error exit: SYNTAX - bad additive term or premature end-of-line
  707. *
  708. * Notes:
  709. * may be called recursively.
  710. * <aterm> = <mterm> [<mult-op> <mterm>]*
  711. * <mult-op> = *, /, MOD (%)
  712. *
  713. *************************************************************************/
  714. LONG64
  715. MasmEvalExpression::GetAterm(void)
  716. {
  717. LONG64 value1;
  718. LONG64 value2;
  719. ULONG opclass;
  720. LONG64 oRetValue;
  721. //dprintf("LONG64 GetAterm ()\n");
  722. value1 = GetMterm();
  723. while ((opclass = PeekToken(&oRetValue)) == MULOP_CLASS)
  724. {
  725. AcceptToken();
  726. value2 = GetMterm();
  727. switch (oRetValue)
  728. {
  729. case MULOP_MULT:
  730. value1 *= value2;
  731. break;
  732. case MULOP_DIVIDE:
  733. if (value2 == 0)
  734. {
  735. EvalError(OPERAND);
  736. }
  737. value1 /= value2;
  738. break;
  739. case MULOP_MOD:
  740. if (value2 == 0)
  741. {
  742. EvalError(OPERAND);
  743. }
  744. value1 %= value2;
  745. break;
  746. case MULOP_SEG:
  747. PDESCRIPTOR64 pdesc;
  748. DESCRIPTOR64 desc;
  749. pdesc = NULL;
  750. if (m_AddrExprType != ADDR_NONE)
  751. {
  752. Type(m_TempAddr) = m_AddrExprType;
  753. }
  754. else
  755. {
  756. // We don't know what kind of address this is
  757. // Let's try to figure it out.
  758. if (g_X86InVm86)
  759. {
  760. m_AddrExprType = Type(m_TempAddr) = ADDR_V86;
  761. }
  762. else if (g_Target->GetSelDescriptor
  763. (g_Thread, g_Machine,
  764. (ULONG)value1, &desc) != S_OK)
  765. {
  766. EvalError(BADSEG);
  767. }
  768. else
  769. {
  770. m_AddrExprType = Type(m_TempAddr) =
  771. (desc.Flags & X86_DESC_DEFAULT_BIG) ?
  772. ADDR_1632 : ADDR_16;
  773. pdesc = &desc;
  774. }
  775. }
  776. m_TempAddr.seg = (USHORT)value1;
  777. m_TempAddr.off = value2;
  778. ComputeFlatAddress(&m_TempAddr, pdesc);
  779. value1 = value2;
  780. break;
  781. default:
  782. EvalError(SYNTAX);
  783. }
  784. }
  785. return value1;
  786. }
  787. /*** GetMterm - get multiplicative term
  788. *
  789. * Purpose:
  790. * Parse basic-terms optionally prefaced by one or more
  791. * unary operators into a multiplicative term.
  792. *
  793. * Input:
  794. * m_Lex - present command line position
  795. *
  796. * Returns:
  797. * long value of multiplicative term.
  798. *
  799. * Exceptions:
  800. * error exit: SYNTAX - bad multiplicative term or premature end-of-line
  801. *
  802. * Notes:
  803. * may be called recursively.
  804. * <mterm> = [<unary-op>] <term> | <unary-op> <mterm>
  805. * <unary-op> = <add-op>, ~ (NOT), BY, WO, DW, HI, LOW
  806. *
  807. *************************************************************************/
  808. LONG64
  809. MasmEvalExpression::GetMterm(void)
  810. {
  811. LONG64 value;
  812. ULONG opclass;
  813. LONG64 oRetValue;
  814. ULONG size = 0;
  815. //dprintf("LONG64 GetMterm ()\n");
  816. if ((opclass = PeekToken(&oRetValue)) == UNOP_CLASS ||
  817. opclass == ADDOP_CLASS)
  818. {
  819. AcceptToken();
  820. if (oRetValue == UNOP_VAL)
  821. {
  822. // Do not use default expression handler for type expressions.
  823. value = GetTypedExpression();
  824. }
  825. else
  826. {
  827. value = GetMterm();
  828. }
  829. switch (oRetValue)
  830. {
  831. case UNOP_NOT:
  832. value = !value;
  833. break;
  834. case UNOP_BY:
  835. size = 1;
  836. break;
  837. case UNOP_WO:
  838. size = 2;
  839. break;
  840. case UNOP_DWO:
  841. size = 4;
  842. break;
  843. case UNOP_POI:
  844. size = 0xFFFF;
  845. break;
  846. case UNOP_QWO:
  847. size = 8;
  848. break;
  849. case UNOP_LOW:
  850. value &= 0xffff;
  851. break;
  852. case UNOP_HI:
  853. value = (ULONG)value >> 16;
  854. break;
  855. case ADDOP_PLUS:
  856. break;
  857. case ADDOP_MINUS:
  858. value = -value;
  859. break;
  860. case UNOP_VAL:
  861. break;
  862. default:
  863. EvalError(SYNTAX);
  864. }
  865. if (size)
  866. {
  867. ADDR CurAddr;
  868. NotFlat(CurAddr);
  869. ForceAddrExpression(SEGREG_COUNT, &CurAddr, value);
  870. value = 0;
  871. //
  872. // For pointers, call read pointer so we read the correct size
  873. // and sign extend.
  874. //
  875. if (size == 0xFFFF)
  876. {
  877. if (g_Target->ReadPointer(g_Process, g_Machine,
  878. Flat(CurAddr),
  879. (PULONG64)&value) != S_OK)
  880. {
  881. EvalError(MEMORY);
  882. }
  883. }
  884. else
  885. {
  886. if (g_Target->ReadAllVirtual(g_Process, Flat(CurAddr),
  887. &value, size) != S_OK)
  888. {
  889. EvalError(MEMORY);
  890. }
  891. }
  892. // We've looked up an arbitrary value so we can
  893. // no longer consider this an address expression.
  894. m_AddrExprType = ADDR_NONE;
  895. }
  896. }
  897. else
  898. {
  899. value = GetTerm();
  900. }
  901. return value;
  902. }
  903. /*** GetTerm - get basic term
  904. *
  905. * Purpose:
  906. * Parse numeric, variable, or register name into a basic
  907. * term value.
  908. *
  909. * Input:
  910. * m_Lex - present command line position
  911. *
  912. * Returns:
  913. * long value of basic term.
  914. *
  915. * Exceptions:
  916. * error exit: SYNTAX - empty basic term or premature end-of-line
  917. *
  918. * Notes:
  919. * may be called recursively.
  920. * <term> = ( <expr> ) | <register-value> | <number> | <variable>
  921. * <register-value> = @<register-name>
  922. *
  923. *************************************************************************/
  924. LONG64
  925. MasmEvalExpression::GetTerm(void)
  926. {
  927. LONG64 value;
  928. ULONG opclass;
  929. LONG64 oRetValue;
  930. //dprintf("LONG64 GetTerm ()\n");
  931. opclass = GetTokenSym(&oRetValue);
  932. if (opclass == LPAREN_CLASS)
  933. {
  934. value = StartExpr();
  935. if (GetTokenSym(&oRetValue) != RPAREN_CLASS)
  936. {
  937. EvalError(SYNTAX);
  938. }
  939. }
  940. else if (opclass == LBRACK_CLASS)
  941. {
  942. value = StartExpr();
  943. if (GetTokenSym(&oRetValue) != RBRACK_CLASS)
  944. {
  945. EvalError(SYNTAX);
  946. }
  947. }
  948. else if (opclass == REG_CLASS)
  949. {
  950. REGVAL Val;
  951. if (g_Machine &&
  952. ((g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_I386 &&
  953. (oRetValue == X86_EIP || oRetValue == X86_IP)) ||
  954. (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64 &&
  955. (oRetValue == AMD64_RIP || oRetValue == AMD64_EIP ||
  956. oRetValue == AMD64_IP))))
  957. {
  958. m_AddrExprType |= INSTR_POINTER;
  959. }
  960. GetPseudoOrRegVal(TRUE, (ULONG)oRetValue, &Val);
  961. value = Val.I64;
  962. }
  963. else if (opclass == NUMBER_CLASS ||
  964. opclass == SYMBOL_CLASS ||
  965. opclass == LINE_CLASS)
  966. {
  967. value = oRetValue;
  968. }
  969. else
  970. {
  971. EvalErrorDesc(SYNTAX, m_ExprDesc);
  972. }
  973. return value;
  974. }
  975. ULONG
  976. MasmEvalExpression::GetRegToken(char *str, PULONG64 value)
  977. {
  978. if ((*value = RegIndexFromName(str)) != REG_ERROR)
  979. {
  980. return REG_CLASS;
  981. }
  982. else
  983. {
  984. *value = BADREG;
  985. return ERROR_CLASS;
  986. }
  987. }
  988. /*** PeekToken - peek the next command line token
  989. *
  990. * Purpose:
  991. * Return the next command line token, but do not advance
  992. * the m_Lex pointer.
  993. *
  994. * Input:
  995. * m_Lex - present command line position.
  996. *
  997. * Output:
  998. * *RetValue - optional value of token
  999. * Returns:
  1000. * class of token
  1001. *
  1002. * Notes:
  1003. * m_SavedClass, m_SavedValue, and m_SavedCommand saves the token getting
  1004. * state for future peeks. To get the next token, a GetToken or
  1005. * AcceptToken call must first be made.
  1006. *
  1007. *************************************************************************/
  1008. ULONG
  1009. MasmEvalExpression::PeekToken(PLONG64 RetValue)
  1010. {
  1011. PCSTR Temp;
  1012. //dprintf("ULONG PeekToken (PLONG64 RetValue)\n");
  1013. // Get next class and value, but do not
  1014. // move m_Lex, but save it in m_SavedCommand.
  1015. // Do not report any error condition.
  1016. if (m_SavedClass == INVALID_CLASS)
  1017. {
  1018. Temp = m_Lex;
  1019. m_SavedClass = NextToken(&m_SavedValue);
  1020. m_SavedCommand = m_Lex;
  1021. m_Lex = Temp;
  1022. if (m_SavedClass == ADDOP_CLASS && m_SavedValue == ADDOP_PLUS)
  1023. {
  1024. m_ForcePositiveNumber = TRUE;
  1025. }
  1026. else
  1027. {
  1028. m_ForcePositiveNumber = FALSE;
  1029. }
  1030. }
  1031. *RetValue = m_SavedValue;
  1032. return m_SavedClass;
  1033. }
  1034. /*** AcceptToken - accept any peeked token
  1035. *
  1036. * Purpose:
  1037. * To reset the PeekToken saved variables so the next PeekToken
  1038. * will get the next token in the command line.
  1039. *
  1040. * Input:
  1041. * None.
  1042. *
  1043. * Output:
  1044. * None.
  1045. *
  1046. *************************************************************************/
  1047. void
  1048. MasmEvalExpression::AcceptToken(void)
  1049. {
  1050. //dprintf("void AcceptToken (void)\n");
  1051. m_SavedClass = INVALID_CLASS;
  1052. m_Lex = m_SavedCommand;
  1053. }
  1054. /*** GetTokenSym - peek and accept the next token
  1055. *
  1056. * Purpose:
  1057. * Combines the functionality of PeekToken and AcceptToken
  1058. * to return the class and optional value of the next token
  1059. * as well as updating the command pointer m_Lex.
  1060. *
  1061. * Input:
  1062. * m_Lex - present command string pointer
  1063. *
  1064. * Output:
  1065. * *RetValue - pointer to the token value optionally set.
  1066. * Returns:
  1067. * class of the token read.
  1068. *
  1069. * Notes:
  1070. * An illegal token returns the value of ERROR_CLASS with *RetValue
  1071. * being the error number, but produces no actual error.
  1072. *
  1073. *************************************************************************/
  1074. ULONG
  1075. MasmEvalExpression::GetTokenSym(PLONG64 RetValue)
  1076. {
  1077. ULONG opclass;
  1078. //dprintf("ULONG GetTokenSym (PLONG RetValue)\n");
  1079. if (m_SavedClass != INVALID_CLASS)
  1080. {
  1081. opclass = m_SavedClass;
  1082. m_SavedClass = INVALID_CLASS;
  1083. *RetValue = m_SavedValue;
  1084. m_Lex = m_SavedCommand;
  1085. }
  1086. else
  1087. {
  1088. opclass = NextToken(RetValue);
  1089. }
  1090. if (opclass == ERROR_CLASS)
  1091. {
  1092. EvalError((ULONG)*RetValue);
  1093. }
  1094. return opclass;
  1095. }
  1096. struct DISPLAY_AMBIGUOUS_SYMBOLS
  1097. {
  1098. PSTR MatchString;
  1099. PSTR Module;
  1100. MachineInfo* Machine;
  1101. };
  1102. BOOL CALLBACK
  1103. DisplayAmbiguousSymbols(
  1104. PSYMBOL_INFO SymInfo,
  1105. ULONG Size,
  1106. PVOID UserContext
  1107. )
  1108. {
  1109. DISPLAY_AMBIGUOUS_SYMBOLS* Context =
  1110. (DISPLAY_AMBIGUOUS_SYMBOLS*)UserContext;
  1111. if (IgnoreEnumeratedSymbol(g_Process, Context->MatchString,
  1112. Context->Machine, SymInfo))
  1113. {
  1114. return TRUE;
  1115. }
  1116. dprintf("Matched: %s %s!%s",
  1117. FormatAddr64(SymInfo->Address), Context->Module, SymInfo->Name);
  1118. ShowSymbolInfo(SymInfo);
  1119. dprintf("\n");
  1120. return TRUE;
  1121. }
  1122. ULONG
  1123. MasmEvalExpression::EvalSymbol(PSTR Name, PULONG64 Value)
  1124. {
  1125. if (m_Process == NULL)
  1126. {
  1127. return INVALID_CLASS;
  1128. }
  1129. if (m_Flags & EXPRF_PREFER_SYMBOL_VALUES)
  1130. {
  1131. if (GetSymValue(Name, Value))
  1132. {
  1133. return SYMBOL_CLASS;
  1134. }
  1135. else
  1136. {
  1137. return INVALID_CLASS;
  1138. }
  1139. }
  1140. ULONG Count;
  1141. ImageInfo* Image;
  1142. if (!(Count = GetOffsetFromSym(g_Process, Name, Value, &Image)))
  1143. {
  1144. // If a valid module name was given we can assume
  1145. // the user really intended this as a symbol reference
  1146. // and return a not-found error rather than letting
  1147. // the text be checked for other kinds of matches.
  1148. if (Image != NULL)
  1149. {
  1150. *Value = VARDEF;
  1151. return ERROR_CLASS;
  1152. }
  1153. else
  1154. {
  1155. return INVALID_CLASS;
  1156. }
  1157. }
  1158. if (Count == 1)
  1159. {
  1160. // Found an unambiguous match.
  1161. Type(m_TempAddr) = ADDR_FLAT | FLAT_COMPUTED;
  1162. Flat(m_TempAddr) = Off(m_TempAddr) = *Value;
  1163. m_AddrExprType = Type(m_TempAddr);
  1164. return SYMBOL_CLASS;
  1165. }
  1166. //
  1167. // Multiple matches were found so the name is ambiguous.
  1168. // Enumerate the instances and display them.
  1169. //
  1170. Image = m_Process->FindImageByOffset(*Value, FALSE);
  1171. if (Image != NULL)
  1172. {
  1173. DISPLAY_AMBIGUOUS_SYMBOLS Context;
  1174. char FoundSymbol[MAX_SYMBOL_LEN];
  1175. ULONG64 Disp;
  1176. PSTR Bang;
  1177. // The symbol found may not have exactly the name
  1178. // passed in due to prefixing or other modifications.
  1179. // Look up the actual name found.
  1180. GetSymbol(*Value, FoundSymbol, sizeof(FoundSymbol), &Disp);
  1181. Bang = strchr(FoundSymbol, '!');
  1182. if (Bang &&
  1183. !_strnicmp(Image->m_ModuleName, FoundSymbol,
  1184. Bang - FoundSymbol))
  1185. {
  1186. Context.MatchString = Bang + 1;
  1187. }
  1188. else
  1189. {
  1190. Context.MatchString = FoundSymbol;
  1191. }
  1192. Context.Module = Image->m_ModuleName;
  1193. Context.Machine = MachineTypeInfo(g_Target, Image->GetMachineType());
  1194. if (Context.Machine == NULL)
  1195. {
  1196. Context.Machine = g_Machine;
  1197. }
  1198. SymEnumSymbols(m_Process->m_SymHandle, Image->m_BaseOfImage,
  1199. FoundSymbol, DisplayAmbiguousSymbols, &Context);
  1200. }
  1201. *Value = AMBIGUOUS;
  1202. return ERROR_CLASS;
  1203. }
  1204. /*** NextToken - process the next token
  1205. *
  1206. * Purpose:
  1207. * Parse the next token from the present command string.
  1208. * After skipping any leading white space, first check for
  1209. * any single character tokens or register variables. If
  1210. * no match, then parse for a number or variable. If a
  1211. * possible variable, check the reserved word list for operators.
  1212. *
  1213. * Input:
  1214. * m_Lex - pointer to present command string
  1215. *
  1216. * Output:
  1217. * *RetValue - optional value of token returned
  1218. * m_Lex - updated to point past processed token
  1219. * Returns:
  1220. * class of token returned
  1221. *
  1222. * Notes:
  1223. * An illegal token returns the value of ERROR_CLASS with *RetValue
  1224. * being the error number, but produces no actual error.
  1225. *
  1226. *************************************************************************/
  1227. ULONG
  1228. MasmEvalExpression::NextToken(PLONG64 RetValue)
  1229. {
  1230. ULONG Base = g_DefaultRadix;
  1231. BOOL AllowSignExtension;
  1232. CHAR Symbol[MAX_SYMBOL_LEN];
  1233. CHAR SymbolString[MAX_SYMBOL_LEN];
  1234. CHAR PreSym[9];
  1235. ULONG SymbolLen = 0;
  1236. BOOL IsNumber = TRUE;
  1237. BOOL IsSymbol = TRUE;
  1238. BOOL ForceReg = FALSE;
  1239. BOOL ForceSym = FALSE;
  1240. ULONG ErrNumber = 0;
  1241. CHAR Ch;
  1242. CHAR ChLow;
  1243. CHAR ChTemp;
  1244. CHAR Limit1 = '9';
  1245. CHAR Limit2 = '9';
  1246. BOOL IsDigit = FALSE;
  1247. ULONG64 Value = 0;
  1248. ULONG64 TmpValue;
  1249. ULONG Index;
  1250. PCSTR CmdSave;
  1251. BOOL WasDigit;
  1252. ULONG SymClass;
  1253. ULONG Len;
  1254. // Do sign extension for kernel only.
  1255. AllowSignExtension = IS_KERNEL_TARGET(g_Target);
  1256. Peek();
  1257. m_LexemeSourceStart = m_Lex;
  1258. Ch = *m_Lex++;
  1259. ChLow = (CHAR)tolower(Ch);
  1260. // Check to see if we're at a symbol prefix followed by
  1261. // a symbol character. Symbol prefixes often contain
  1262. // characters meaningful in other ways in expressions so
  1263. // this check must be performed before the specific expression
  1264. // character checks below.
  1265. if (g_Machine != NULL &&
  1266. g_Machine->m_SymPrefix != NULL &&
  1267. ChLow == g_Machine->m_SymPrefix[0] &&
  1268. (g_Machine->m_SymPrefixLen == 1 ||
  1269. !strncmp(m_Lex, g_Machine->m_SymPrefix + 1,
  1270. g_Machine->m_SymPrefixLen - 1)))
  1271. {
  1272. CHAR ChNext = *(m_Lex + g_Machine->m_SymPrefixLen - 1);
  1273. CHAR ChNextLow = (CHAR)tolower(ChNext);
  1274. if (ChNextLow == '_' ||
  1275. (ChNextLow >= 'a' && ChNextLow <= 'z'))
  1276. {
  1277. // A symbol character followed the prefix so assume it's
  1278. // a symbol.
  1279. SymbolLen = g_Machine->m_SymPrefixLen;
  1280. DBG_ASSERT(SymbolLen <= sizeof(PreSym));
  1281. m_Lex--;
  1282. memcpy(PreSym, m_Lex, g_Machine->m_SymPrefixLen);
  1283. memcpy(Symbol, m_Lex, g_Machine->m_SymPrefixLen);
  1284. m_Lex += g_Machine->m_SymPrefixLen + 1;
  1285. Ch = ChNext;
  1286. ChLow = ChNextLow;
  1287. ForceSym = TRUE;
  1288. ForceReg = FALSE;
  1289. IsNumber = FALSE;
  1290. goto ProbableSymbol;
  1291. }
  1292. }
  1293. // Test for special character operators and register variable.
  1294. switch(ChLow)
  1295. {
  1296. case '\0':
  1297. case ';':
  1298. m_Lex--;
  1299. return EOL_CLASS;
  1300. case '+':
  1301. *RetValue = ADDOP_PLUS;
  1302. return ADDOP_CLASS;
  1303. case '-':
  1304. *RetValue = ADDOP_MINUS;
  1305. return ADDOP_CLASS;
  1306. case '*':
  1307. *RetValue = MULOP_MULT;
  1308. return MULOP_CLASS;
  1309. case '/':
  1310. *RetValue = MULOP_DIVIDE;
  1311. return MULOP_CLASS;
  1312. case '%':
  1313. *RetValue = MULOP_MOD;
  1314. return MULOP_CLASS;
  1315. case '&':
  1316. *RetValue = LOGOP_AND;
  1317. return LOGOP_CLASS;
  1318. case '|':
  1319. *RetValue = LOGOP_OR;
  1320. return LOGOP_CLASS;
  1321. case '^':
  1322. *RetValue = LOGOP_XOR;
  1323. return LOGOP_CLASS;
  1324. case '=':
  1325. if (*m_Lex == '=')
  1326. {
  1327. m_Lex++;
  1328. }
  1329. *RetValue = LRELOP_EQ;
  1330. return LRELOP_CLASS;
  1331. case '>':
  1332. if (*m_Lex == '>')
  1333. {
  1334. m_Lex++;
  1335. if (*m_Lex == '>')
  1336. {
  1337. m_Lex++;
  1338. *RetValue = SHIFT_RIGHT_ARITHMETIC;
  1339. }
  1340. else
  1341. {
  1342. *RetValue = SHIFT_RIGHT_LOGICAL;
  1343. }
  1344. return SHIFT_CLASS;
  1345. }
  1346. *RetValue = LRELOP_GT;
  1347. return LRELOP_CLASS;
  1348. case '<':
  1349. if (*m_Lex == '<')
  1350. {
  1351. m_Lex++;
  1352. *RetValue = SHIFT_LEFT;
  1353. return SHIFT_CLASS;
  1354. }
  1355. *RetValue = LRELOP_LT;
  1356. return LRELOP_CLASS;
  1357. case '!':
  1358. if (*m_Lex != '=')
  1359. {
  1360. break;
  1361. }
  1362. m_Lex++;
  1363. *RetValue = LRELOP_NE;
  1364. return LRELOP_CLASS;
  1365. case '~':
  1366. *RetValue = UNOP_NOT;
  1367. return UNOP_CLASS;
  1368. case '(':
  1369. return LPAREN_CLASS;
  1370. case ')':
  1371. return RPAREN_CLASS;
  1372. case '[':
  1373. return LBRACK_CLASS;
  1374. case ']':
  1375. return RBRACK_CLASS;
  1376. case '.':
  1377. ContextSave* Push;
  1378. PCROSS_PLATFORM_CONTEXT ScopeContext;
  1379. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1380. {
  1381. *RetValue = BADTHREAD;
  1382. return ERROR_CLASS;
  1383. }
  1384. ScopeContext = GetCurrentScopeContext();
  1385. if (ScopeContext)
  1386. {
  1387. Push = g_Machine->PushContext(ScopeContext);
  1388. }
  1389. g_Machine->GetPC(&m_TempAddr);
  1390. *RetValue = Flat(m_TempAddr);
  1391. m_AddrExprType = Type(m_TempAddr);
  1392. if (ScopeContext)
  1393. {
  1394. g_Machine->PopContext(Push);
  1395. }
  1396. return NUMBER_CLASS;
  1397. case ':':
  1398. *RetValue = MULOP_SEG;
  1399. return MULOP_CLASS;
  1400. }
  1401. //
  1402. // Look for source line expressions. Because source file names
  1403. // can contain a lot of expression characters which are meaningful
  1404. // to the lexer the whole expression is enclosed in ` characters.
  1405. // This makes them easy to identify and scan.
  1406. //
  1407. if (ChLow == '`')
  1408. {
  1409. ULONG FoundLine;
  1410. // Scan forward for closing `
  1411. CmdSave = m_Lex;
  1412. while (*m_Lex != '`' && *m_Lex != ';' && *m_Lex != 0)
  1413. {
  1414. m_Lex++;
  1415. }
  1416. if (*m_Lex == ';' || *m_Lex == 0)
  1417. {
  1418. *RetValue = SYNTAX;
  1419. return ERROR_CLASS;
  1420. }
  1421. Len = (ULONG)(m_Lex - CmdSave);
  1422. if (Len >= sizeof(m_LexemeBuffer))
  1423. {
  1424. EvalError(OVERFLOW);
  1425. }
  1426. memcpy(m_LexemeBuffer, CmdSave, Len);
  1427. m_LexemeBuffer[Len] = 0;
  1428. m_Lex++;
  1429. FoundLine = GetOffsetFromLine(m_LexemeBuffer, &Value);
  1430. if (FoundLine == LINE_NOT_FOUND && m_AllowUnresolvedSymbols)
  1431. {
  1432. m_NumUnresolvedSymbols++;
  1433. FoundLine = LINE_FOUND;
  1434. Value = 0;
  1435. }
  1436. if (FoundLine == LINE_FOUND)
  1437. {
  1438. *RetValue = Value;
  1439. Type(m_TempAddr) = ADDR_FLAT | FLAT_COMPUTED;
  1440. Flat(m_TempAddr) = Off(m_TempAddr) = Value;
  1441. m_AddrExprType = Type(m_TempAddr);
  1442. return LINE_CLASS;
  1443. }
  1444. else
  1445. {
  1446. *RetValue = NOTFOUND;
  1447. return ERROR_CLASS;
  1448. }
  1449. }
  1450. //
  1451. // Check for an alternate evaluator expression. As with line
  1452. // expressions alteval expressions have different
  1453. // lexical rules and therefore represent a text
  1454. // blob that is parsed with different rules.
  1455. //
  1456. if (ChLow == '@' && *m_Lex == '@')
  1457. {
  1458. TypedData Result;
  1459. //
  1460. // Scan to '(', picking up the optional evaluator name.
  1461. //
  1462. CmdSave = ++m_Lex;
  1463. while (*m_Lex != '(' && *m_Lex != ';' && *m_Lex != 0)
  1464. {
  1465. m_Lex++;
  1466. }
  1467. if (*m_Lex == ';' || *m_Lex == 0)
  1468. {
  1469. *RetValue = SYNTAX;
  1470. return ERROR_CLASS;
  1471. }
  1472. Len = (ULONG)(m_Lex - CmdSave);
  1473. if (Len >= sizeof(m_LexemeBuffer))
  1474. {
  1475. EvalError(OVERFLOW);
  1476. }
  1477. memcpy(m_LexemeBuffer, CmdSave, Len);
  1478. m_LexemeBuffer[Len] = 0;
  1479. m_Lex++;
  1480. EvalExpression* Eval;
  1481. if (Len > 0)
  1482. {
  1483. GetEvaluatorByName(m_LexemeBuffer, FALSE, &Eval);
  1484. }
  1485. else
  1486. {
  1487. Eval = GetEvaluator(DEBUG_EXPR_CPLUSPLUS, FALSE);
  1488. }
  1489. Eval->InheritStart(this);
  1490. // Allow all nested evaluators to get cleaned up.
  1491. Eval->m_ChainTop = FALSE;
  1492. m_Lex = (PSTR)Eval->
  1493. Evaluate(m_Lex, NULL, EXPRF_DEFAULT, &Result);
  1494. Eval->InheritEnd(this);
  1495. ReleaseEvaluator(Eval);
  1496. if (*m_Lex != ')')
  1497. {
  1498. *RetValue = SYNTAX;
  1499. return ERROR_CLASS;
  1500. }
  1501. m_Lex++;
  1502. if (ErrNumber = Result.ConvertToU64())
  1503. {
  1504. EvalError(ErrNumber);
  1505. }
  1506. *RetValue = Result.m_U64;
  1507. return NUMBER_CLASS;
  1508. }
  1509. // Special prefixes - '@' for register - '!' for symbol.
  1510. if (ChLow == '@' || ChLow == '!')
  1511. {
  1512. ForceReg = (BOOL)(ChLow == '@');
  1513. ForceSym = (BOOL)!ForceReg;
  1514. IsNumber = FALSE;
  1515. Ch = *m_Lex++;
  1516. ChLow = (CHAR)tolower(Ch);
  1517. }
  1518. // If string is followed by '!', but not '!=',
  1519. // then it is a module name and treat as text.
  1520. CmdSave = m_Lex;
  1521. WasDigit = FALSE;
  1522. while ((ChLow >= 'a' && ChLow <= 'z') ||
  1523. (ChLow >= '0' && ChLow <= '9') ||
  1524. ((WasDigit || ForceSym) && ChLow == '`') ||
  1525. (ForceSym && ChLow == '\'') ||
  1526. (ChLow == '_') || (ChLow == '$') || (ChLow == '~') ||
  1527. (!ForceReg && ChLow == ':' && *m_Lex == ':'))
  1528. {
  1529. WasDigit = (ChLow >= '0' && ChLow <= '9') ||
  1530. (ChLow >= 'a' && ChLow <= 'f');
  1531. if (ChLow == ':')
  1532. {
  1533. // Colons must come in pairs so skip the second colon
  1534. // right away.
  1535. m_Lex++;
  1536. IsNumber = FALSE;
  1537. }
  1538. ChLow = (CHAR)tolower(*m_Lex);
  1539. m_Lex++;
  1540. }
  1541. // Treat as symbol if a nonnull string is followed by '!',
  1542. // but not '!='.
  1543. if (ChLow == '!' && *m_Lex != '=' && CmdSave != m_Lex)
  1544. {
  1545. IsNumber = FALSE;
  1546. }
  1547. m_Lex = CmdSave;
  1548. ChLow = (CHAR)tolower(Ch); // ch was NOT modified
  1549. if (IsNumber)
  1550. {
  1551. if (ChLow == '\'')
  1552. {
  1553. *RetValue = 0;
  1554. while (TRUE)
  1555. {
  1556. Ch = *m_Lex++;
  1557. if (!Ch)
  1558. {
  1559. *RetValue = SYNTAX;
  1560. return ERROR_CLASS;
  1561. }
  1562. if (Ch == '\'')
  1563. {
  1564. if (*m_Lex != '\'')
  1565. {
  1566. break;
  1567. }
  1568. Ch = *m_Lex++;
  1569. }
  1570. else if (Ch == '\\')
  1571. {
  1572. Ch = *m_Lex++;
  1573. }
  1574. *RetValue = (*RetValue << 8) | Ch;
  1575. }
  1576. return NUMBER_CLASS;
  1577. }
  1578. // If first character is a decimal digit, it cannot
  1579. // be a symbol. leading '0' implies octal, except
  1580. // a leading '0x' implies hexadecimal.
  1581. if (ChLow >= '0' && ChLow <= '9')
  1582. {
  1583. if (ForceReg)
  1584. {
  1585. *RetValue = SYNTAX;
  1586. return ERROR_CLASS;
  1587. }
  1588. IsSymbol = FALSE;
  1589. if (ChLow == '0')
  1590. {
  1591. //
  1592. // too many people type in leading 0x so we can't use it to
  1593. // deal with sign extension.
  1594. //
  1595. Ch = *m_Lex++;
  1596. ChLow = (CHAR)tolower(Ch);
  1597. if (ChLow == 'n')
  1598. {
  1599. Base = 10;
  1600. Ch = *m_Lex++;
  1601. ChLow = (CHAR)tolower(Ch);
  1602. IsDigit = TRUE;
  1603. }
  1604. else if (ChLow == 't')
  1605. {
  1606. Base = 8;
  1607. Ch = *m_Lex++;
  1608. ChLow = (CHAR)tolower(Ch);
  1609. IsDigit = TRUE;
  1610. }
  1611. else if (ChLow == 'x')
  1612. {
  1613. Base = 16;
  1614. Ch = *m_Lex++;
  1615. ChLow = (CHAR)tolower(Ch);
  1616. IsDigit = TRUE;
  1617. }
  1618. else if (ChLow == 'y')
  1619. {
  1620. Base = 2;
  1621. Ch = *m_Lex++;
  1622. ChLow = (CHAR)tolower(Ch);
  1623. IsDigit = TRUE;
  1624. }
  1625. else
  1626. {
  1627. // Leading zero is used only to imply a positive value
  1628. // that shouldn't get sign extended.
  1629. IsDigit = TRUE;
  1630. }
  1631. }
  1632. }
  1633. // A number can start with a letter only if base is
  1634. // hexadecimal and it is a hexadecimal digit 'a'-'f'.
  1635. else if ((ChLow < 'a' || ChLow > 'f') || Base != 16)
  1636. {
  1637. IsNumber = FALSE;
  1638. }
  1639. // Set limit characters for the appropriate base.
  1640. if (Base == 2)
  1641. {
  1642. Limit1 = '1';
  1643. }
  1644. else if (Base == 8)
  1645. {
  1646. Limit1 = '7';
  1647. }
  1648. else if (Base == 16)
  1649. {
  1650. Limit2 = 'f';
  1651. }
  1652. }
  1653. ProbableSymbol:
  1654. // Perform processing while character is a letter,
  1655. // digit, underscore, tilde or dollar-sign.
  1656. while ((ChLow >= 'a' && ChLow <= 'z') ||
  1657. (ChLow >= '0' && ChLow <= '9') ||
  1658. ((ForceSym || (IsDigit && Base == 16)) && ChLow == '`') ||
  1659. (ForceSym && ChLow == '\'') ||
  1660. (ChLow == '_') || (ChLow == '$') || (ChLow == '~') ||
  1661. (!ForceReg && ChLow == ':' && *m_Lex == ':'))
  1662. {
  1663. if (ChLow == ':')
  1664. {
  1665. IsNumber = FALSE;
  1666. }
  1667. // If possible number, test if within proper range,
  1668. // and if so, accumulate sum.
  1669. if (IsNumber)
  1670. {
  1671. if ((ChLow >= '0' && ChLow <= Limit1) ||
  1672. (ChLow >= 'a' && ChLow <= Limit2))
  1673. {
  1674. IsDigit = TRUE;
  1675. TmpValue = Value * Base;
  1676. if (TmpValue < Value)
  1677. {
  1678. ErrNumber = OVERFLOW;
  1679. }
  1680. ChTemp = (CHAR)(ChLow - '0');
  1681. if (ChTemp > 9)
  1682. {
  1683. ChTemp -= 'a' - '0' - 10;
  1684. }
  1685. Value = TmpValue + (ULONG64)ChTemp;
  1686. if (Value < TmpValue)
  1687. {
  1688. ErrNumber = OVERFLOW;
  1689. }
  1690. }
  1691. else if (IsDigit && ChLow == '`')
  1692. {
  1693. // If ` character is seen, disallow sign extension.
  1694. AllowSignExtension = FALSE;
  1695. }
  1696. else
  1697. {
  1698. IsNumber = FALSE;
  1699. ErrNumber = SYNTAX;
  1700. }
  1701. }
  1702. if (IsSymbol)
  1703. {
  1704. if (SymbolLen < sizeof(PreSym))
  1705. {
  1706. PreSym[SymbolLen] = ChLow;
  1707. }
  1708. if (SymbolLen < MAX_SYMBOL_LEN - 1)
  1709. {
  1710. Symbol[SymbolLen++] = Ch;
  1711. }
  1712. // Colons must come in pairs so process the second colon.
  1713. if (ChLow == ':')
  1714. {
  1715. if (SymbolLen < sizeof(PreSym))
  1716. {
  1717. PreSym[SymbolLen] = ChLow;
  1718. }
  1719. if (SymbolLen < MAX_SYMBOL_LEN - 1)
  1720. {
  1721. Symbol[SymbolLen++] = Ch;
  1722. }
  1723. m_Lex++;
  1724. }
  1725. }
  1726. Ch = *m_Lex++;
  1727. if (m_Flags & EXPRF_PREFER_SYMBOL_VALUES)
  1728. {
  1729. if (Ch == '.')
  1730. {
  1731. Symbol[SymbolLen++] = Ch;
  1732. Ch = *m_Lex++;
  1733. }
  1734. else if (Ch == '-' && *m_Lex == '>')
  1735. {
  1736. Symbol[SymbolLen++] = Ch;
  1737. Ch = *m_Lex++;
  1738. Symbol[SymbolLen++] = Ch;
  1739. Ch = *m_Lex++;
  1740. }
  1741. }
  1742. ChLow = (CHAR)tolower(Ch);
  1743. }
  1744. // Back up pointer to first character after token.
  1745. m_Lex--;
  1746. if (SymbolLen < sizeof(PreSym))
  1747. {
  1748. PreSym[SymbolLen] = '\0';
  1749. }
  1750. if (g_Machine &&
  1751. (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_I386 ||
  1752. g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64))
  1753. {
  1754. // Catch segment overrides.
  1755. if (!ForceReg && Ch == ':')
  1756. {
  1757. for (Index = 0; Index < X86_SEGREGSIZE; Index++)
  1758. {
  1759. if (!strncmp(PreSym, g_X86SegRegs[Index], 2))
  1760. {
  1761. ForceReg = TRUE;
  1762. IsSymbol = FALSE;
  1763. break;
  1764. }
  1765. }
  1766. }
  1767. }
  1768. // If ForceReg, check for register name and return
  1769. // success or failure.
  1770. if (ForceReg)
  1771. {
  1772. return GetRegToken(PreSym, (PULONG64)RetValue);
  1773. }
  1774. // Test if number.
  1775. if (IsNumber && !ErrNumber && IsDigit)
  1776. {
  1777. if (AllowSignExtension && !m_ForcePositiveNumber &&
  1778. ((Value >> 32) == 0))
  1779. {
  1780. *RetValue = (LONG)Value;
  1781. }
  1782. else
  1783. {
  1784. *RetValue = Value;
  1785. }
  1786. return NUMBER_CLASS;
  1787. }
  1788. // Next test for reserved word and symbol string.
  1789. if (IsSymbol && !ForceReg)
  1790. {
  1791. // check lowercase string in PreSym for text operator
  1792. // or register name.
  1793. // otherwise, return symbol value from name in Symbol.
  1794. if (!ForceSym && (SymbolLen == 2 || SymbolLen == 3))
  1795. {
  1796. for (Index = 0; Index < RESERVESIZE; Index++)
  1797. {
  1798. if (!strncmp(PreSym, g_Reserved[Index].chRes, 3))
  1799. {
  1800. *RetValue = g_Reserved[Index].valueRes;
  1801. return g_Reserved[Index].classRes;
  1802. }
  1803. }
  1804. if (g_Machine &&
  1805. (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_I386 ||
  1806. g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64))
  1807. {
  1808. for (Index = 0; Index < X86_RESERVESIZE; Index++)
  1809. {
  1810. if (!strncmp(PreSym,
  1811. g_X86Reserved[Index].chRes, 3))
  1812. {
  1813. *RetValue = g_X86Reserved[Index].valueRes;
  1814. return g_X86Reserved[Index].classRes;
  1815. }
  1816. }
  1817. }
  1818. }
  1819. // Start processing string as symbol.
  1820. Symbol[SymbolLen] = '\0';
  1821. // Test if symbol is a module name (followed by '!')
  1822. // if so, get next token and treat as symbol.
  1823. if (Peek() == '!')
  1824. {
  1825. // SymbolString holds the name of the symbol to be searched.
  1826. // Symbol holds the symbol image file name.
  1827. m_Lex++;
  1828. Ch = Peek();
  1829. m_Lex++;
  1830. // Scan prefix if one is present.
  1831. if (g_Machine != NULL &&
  1832. g_Machine->m_SymPrefix != NULL &&
  1833. Ch == g_Machine->m_SymPrefix[0] &&
  1834. (g_Machine->m_SymPrefixLen == 1 ||
  1835. !strncmp(m_Lex, g_Machine->m_SymPrefix + 1,
  1836. g_Machine->m_SymPrefixLen - 1)))
  1837. {
  1838. SymbolLen = g_Machine->m_SymPrefixLen;
  1839. memcpy(SymbolString, m_Lex - 1,
  1840. g_Machine->m_SymPrefixLen);
  1841. m_Lex += g_Machine->m_SymPrefixLen - 1;
  1842. Ch = *m_Lex++;
  1843. }
  1844. else
  1845. {
  1846. SymbolLen = 0;
  1847. }
  1848. while ((Ch >= 'A' && Ch <= 'Z') || (Ch >= 'a' && Ch <= 'z') ||
  1849. (Ch >= '0' && Ch <= '9') || (Ch == '_') || (Ch == '$') ||
  1850. (Ch == '`') || (Ch == '\'') ||
  1851. (Ch == ':' && *m_Lex == ':'))
  1852. {
  1853. SymbolString[SymbolLen++] = Ch;
  1854. // Handle :: and ::~.
  1855. if (Ch == ':')
  1856. {
  1857. SymbolString[SymbolLen++] = Ch;
  1858. m_Lex++;
  1859. if (*m_Lex == '~')
  1860. {
  1861. SymbolString[SymbolLen++] = '~';
  1862. m_Lex++;
  1863. }
  1864. }
  1865. Ch = *m_Lex++;
  1866. if (m_Flags & EXPRF_PREFER_SYMBOL_VALUES)
  1867. {
  1868. if (Ch == '.')
  1869. {
  1870. SymbolString[SymbolLen++] = Ch;
  1871. Ch = *m_Lex++;
  1872. }
  1873. else if (Ch == '-' && *m_Lex == '>')
  1874. {
  1875. SymbolString[SymbolLen++] = Ch;
  1876. Ch = *m_Lex++;
  1877. SymbolString[SymbolLen++] = Ch;
  1878. Ch = *m_Lex++;
  1879. }
  1880. }
  1881. }
  1882. SymbolString[SymbolLen] = '\0';
  1883. m_Lex--;
  1884. if (SymbolLen == 0)
  1885. {
  1886. *RetValue = SYNTAX;
  1887. return ERROR_CLASS;
  1888. }
  1889. CatString(Symbol, "!", DIMA(Symbol));
  1890. CatString(Symbol, SymbolString, DIMA(Symbol));
  1891. SymClass = EvalSymbol(Symbol, &Value);
  1892. if (SymClass != INVALID_CLASS)
  1893. {
  1894. *RetValue = Value;
  1895. return SymClass;
  1896. }
  1897. }
  1898. else
  1899. {
  1900. if (SymbolLen == 0)
  1901. {
  1902. *RetValue = SYNTAX;
  1903. return ERROR_CLASS;
  1904. }
  1905. SymClass = EvalSymbol(Symbol, &Value);
  1906. if (SymClass != INVALID_CLASS)
  1907. {
  1908. *RetValue = Value;
  1909. return SymClass;
  1910. }
  1911. // Quick test for register names too
  1912. if (!ForceSym &&
  1913. (TmpValue = GetRegToken(PreSym,
  1914. (PULONG64)RetValue)) != ERROR_CLASS)
  1915. {
  1916. return (ULONG)TmpValue;
  1917. }
  1918. }
  1919. //
  1920. // Symbol is undefined.
  1921. // If a possible hex number, do not set the error type.
  1922. //
  1923. if (!IsNumber)
  1924. {
  1925. ErrNumber = VARDEF;
  1926. }
  1927. }
  1928. //
  1929. // Last chance, undefined symbol and illegal number,
  1930. // so test for register, will handle old format.
  1931. //
  1932. if (!ForceSym &&
  1933. (TmpValue = GetRegToken(PreSym,
  1934. (PULONG64)RetValue)) != ERROR_CLASS)
  1935. {
  1936. return (ULONG)TmpValue;
  1937. }
  1938. if (m_AllowUnresolvedSymbols)
  1939. {
  1940. m_NumUnresolvedSymbols++;
  1941. *RetValue = 0;
  1942. Type(m_TempAddr) = ADDR_FLAT | FLAT_COMPUTED;
  1943. Flat(m_TempAddr) = Off(m_TempAddr) = *RetValue;
  1944. m_AddrExprType = Type(m_TempAddr);
  1945. return SYMBOL_CLASS;
  1946. }
  1947. //
  1948. // No success, so set error message and return.
  1949. //
  1950. *RetValue = (ULONG64)ErrNumber;
  1951. return ERROR_CLASS;
  1952. }