dbgeval.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. dbgeval.c
  5. Abstract:
  6. This module implements arithmetic expression evaluation for the debugger.
  7. Author:
  8. Evan Green 11-Jul-2012
  9. Environment:
  10. Debug client.
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "dbgrtl.h"
  16. #include <minoca/debug/spproto.h>
  17. #include <minoca/lib/im.h>
  18. #include <minoca/debug/dbgext.h>
  19. #include "symbols.h"
  20. #include "dbgapi.h"
  21. #include "dbgrprof.h"
  22. #include "dbgrcomm.h"
  23. #include "dbgsym.h"
  24. #include <assert.h>
  25. #include <errno.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. //
  30. // ---------------------------------------------------------------- Definitions
  31. //
  32. //
  33. // ------------------------------------------------------ Data Type Definitions
  34. //
  35. typedef enum _EVALUATION_OPERATOR {
  36. OperatorInvalid,
  37. OperatorValue,
  38. OperatorAdd,
  39. OperatorSubtract,
  40. OperatorMultiply,
  41. OperatorDivide,
  42. OperatorOpenParentheses,
  43. OperatorCloseParentheses
  44. } EVALUATION_OPERATOR, *PEVALUATION_OPERATOR;
  45. typedef struct _STACK_ELEMENT STACK_ELEMENT, *PSTACK_ELEMENT;
  46. struct _STACK_ELEMENT {
  47. PLIST_ENTRY ListHead;
  48. PSTACK_ELEMENT NextElement;
  49. };
  50. typedef struct _EVALUATION_ELEMENT {
  51. LIST_ENTRY ListEntry;
  52. EVALUATION_OPERATOR Operator;
  53. ULONGLONG Value;
  54. } EVALUATION_ELEMENT, *PEVALUATION_ELEMENT;
  55. typedef struct _EVALUATION_DATA {
  56. PSTACK_ELEMENT StackTop;
  57. PSTR InitialString;
  58. PSTR String;
  59. } EVALUATION_DATA, *PEVALUATION_DATA;
  60. //
  61. // ----------------------------------------------- Internal Function Prototypes
  62. //
  63. INT
  64. EvalGetNextToken (
  65. PDEBUGGER_CONTEXT Context,
  66. PEVALUATION_DATA State,
  67. PEVALUATION_OPERATOR Operator,
  68. PULONGLONG Value
  69. );
  70. BOOL
  71. EvalEvaluateBasicList (
  72. PLIST_ENTRY ListHead,
  73. PULONGLONG Result
  74. );
  75. INT
  76. EvalGetAddressFromSymbol (
  77. PDEBUGGER_CONTEXT Context,
  78. PSTR SymbolName,
  79. PULONGLONG Address
  80. );
  81. //
  82. // -------------------------------------------------------------------- Globals
  83. //
  84. //
  85. // --------------------------------------------------------------------- Macros
  86. //
  87. #define MALLOC(_x) malloc(_x)
  88. #define FREE(_x) free(_x)
  89. //
  90. // ------------------------------------------------------------------ Functions
  91. //
  92. INT
  93. DbgEvaluate (
  94. PDEBUGGER_CONTEXT Context,
  95. PSTR String,
  96. PULONGLONG Result
  97. )
  98. /*++
  99. Routine Description:
  100. This routine evaluates a mathematical expression. The following operators
  101. are supported: +, -, *, /, (, ). No spaces are permitted. Module symbols
  102. are permitted and will be translated into their corresponding address.
  103. Arguments:
  104. Context - Supplies a pointer to the debugger application context.
  105. String - Supplies the string to evaluate.
  106. Result - Supplies a pointer to the 64-bit unsigned integer where the result
  107. will be stored.
  108. Return Value:
  109. 0 if the expression was successfully evaluated.
  110. Returns an error code on failure.
  111. --*/
  112. {
  113. ULONGLONG ComputationValue;
  114. PEVALUATION_ELEMENT CurrentElement;
  115. PLIST_ENTRY CurrentElementEntry;
  116. BOOL CurrentListEmpty;
  117. PLIST_ENTRY CurrentListHead;
  118. PSTACK_ELEMENT CurrentStackElement;
  119. EVALUATION_DATA Evaluation;
  120. PEVALUATION_ELEMENT NewElement;
  121. PSTACK_ELEMENT NewStackElement;
  122. PSTACK_ELEMENT NextStackElement;
  123. EVALUATION_OPERATOR Operator;
  124. PSTACK_ELEMENT PoppedStackElement;
  125. INT Status;
  126. ULONG StringLength;
  127. ULONGLONG Value;
  128. CurrentListHead = NULL;
  129. Evaluation.StackTop = NULL;
  130. Evaluation.InitialString = NULL;
  131. //
  132. // Parameter check and put a default value in the result.
  133. //
  134. if ((String == NULL) || (Result == NULL)) {
  135. Status = EINVAL;
  136. goto EvaluateEnd;
  137. }
  138. *Result = 0;
  139. //
  140. // Make a copy of the string that can be modified.
  141. //
  142. StringLength = RtlStringLength(String);
  143. Evaluation.InitialString = MALLOC(StringLength + 1);
  144. if (Evaluation.InitialString == NULL) {
  145. Status = EINVAL;
  146. goto EvaluateEnd;
  147. }
  148. RtlStringCopy(Evaluation.InitialString, String, StringLength + 1);
  149. Evaluation.String = Evaluation.InitialString;
  150. CurrentListHead = MALLOC(sizeof(LIST_ENTRY));
  151. if (CurrentListHead == NULL) {
  152. Status = EINVAL;
  153. goto EvaluateEnd;
  154. }
  155. INITIALIZE_LIST_HEAD(CurrentListHead);
  156. //
  157. // This is the main processing loop.
  158. //
  159. CurrentListEmpty = TRUE;
  160. while (TRUE) {
  161. Status = EvalGetNextToken(Context, &Evaluation, &Operator, &Value);
  162. if (Status != 0) {
  163. goto EvaluateEnd;
  164. }
  165. //
  166. // If it's the end of the string, break out of the processing loop.
  167. //
  168. if (Operator == OperatorInvalid) {
  169. break;
  170. }
  171. //
  172. // If it's an open parentheses, push the current list onto the stack,
  173. // and start a new list.
  174. //
  175. if (Operator == OperatorOpenParentheses) {
  176. NewStackElement = MALLOC(sizeof(STACK_ELEMENT));
  177. if (NewStackElement == NULL) {
  178. Status = EINVAL;
  179. goto EvaluateEnd;
  180. }
  181. NewStackElement->ListHead = CurrentListHead;
  182. NewStackElement->NextElement = Evaluation.StackTop;
  183. Evaluation.StackTop = NewStackElement;
  184. CurrentListHead = MALLOC(sizeof(LIST_ENTRY));
  185. if (CurrentListHead == NULL) {
  186. Status = ENOMEM;
  187. goto EvaluateEnd;
  188. }
  189. INITIALIZE_LIST_HEAD(CurrentListHead);
  190. CurrentListEmpty = TRUE;
  191. //
  192. // If it's a close parentheses, the idea is to evaluate the current
  193. // list, pop the last list, and append the result to that popped list.
  194. //
  195. } else if (Operator == OperatorCloseParentheses) {
  196. //
  197. // If nothing was evaluated in between the parentheses, that's an
  198. // error.
  199. //
  200. if (CurrentListEmpty != FALSE) {
  201. Status = EINVAL;
  202. goto EvaluateEnd;
  203. }
  204. //
  205. // Evaluate the current list. If successful, all elements except the
  206. // list head will be freed automatically.
  207. //
  208. Status = EvalEvaluateBasicList(CurrentListHead, &ComputationValue);
  209. if (Status == FALSE) {
  210. Status = EINVAL;
  211. goto EvaluateEnd;
  212. }
  213. //
  214. // Free the current list head, and pop the last list off the stack.
  215. //
  216. FREE(CurrentListHead);
  217. PoppedStackElement = Evaluation.StackTop;
  218. CurrentListHead = PoppedStackElement->ListHead;
  219. Evaluation.StackTop = Evaluation.StackTop->NextElement;
  220. FREE(PoppedStackElement);
  221. //
  222. // Create a new value element and insert it into the popped list.
  223. //
  224. NewElement = MALLOC(sizeof(EVALUATION_ELEMENT));
  225. if (NewElement == NULL) {
  226. Status = ENOMEM;
  227. goto EvaluateEnd;
  228. }
  229. memset(NewElement, 0, sizeof(EVALUATION_ELEMENT));
  230. NewElement->Operator = OperatorValue;
  231. NewElement->Value = ComputationValue;
  232. INSERT_BEFORE(&(NewElement->ListEntry), CurrentListHead);
  233. CurrentListEmpty = FALSE;
  234. } else {
  235. //
  236. // It must just be a normal operator or a value. Add it to the list.
  237. //
  238. NewElement = MALLOC(sizeof(EVALUATION_ELEMENT));
  239. if (NewElement == NULL) {
  240. Status = ENOMEM;
  241. goto EvaluateEnd;
  242. }
  243. memset(NewElement, 0, sizeof(EVALUATION_ELEMENT));
  244. NewElement->Operator = Operator;
  245. NewElement->Value = Value;
  246. INSERT_BEFORE(&(NewElement->ListEntry), CurrentListHead);
  247. CurrentListEmpty = FALSE;
  248. }
  249. }
  250. Status = EvalEvaluateBasicList(CurrentListHead, Result);
  251. if (Status == FALSE) {
  252. Status = EINVAL;
  253. goto EvaluateEnd;
  254. }
  255. Status = 0;
  256. EvaluateEnd:
  257. //
  258. // Clean up the current list, if one exists.
  259. //
  260. if (CurrentListHead != NULL) {
  261. CurrentElementEntry = CurrentListHead->Next;
  262. while (CurrentElementEntry != CurrentListHead) {
  263. CurrentElement = LIST_VALUE(CurrentElementEntry,
  264. EVALUATION_ELEMENT,
  265. ListEntry);
  266. CurrentElementEntry = CurrentElementEntry->Next;
  267. FREE(CurrentElement);
  268. }
  269. FREE(CurrentListHead);
  270. }
  271. //
  272. // Clean up any leftover elements on the stack.
  273. //
  274. CurrentStackElement = Evaluation.StackTop;
  275. while (CurrentStackElement != NULL) {
  276. //
  277. // Free the list associated with this stack element.
  278. //
  279. CurrentElementEntry = CurrentStackElement->ListHead->Next;
  280. while (CurrentElementEntry != CurrentStackElement->ListHead) {
  281. CurrentElement = LIST_VALUE(CurrentElementEntry,
  282. EVALUATION_ELEMENT,
  283. ListEntry);
  284. CurrentElementEntry = CurrentElementEntry->Next;
  285. FREE(CurrentElement);
  286. }
  287. FREE(CurrentStackElement->ListHead);
  288. NextStackElement = CurrentStackElement->NextElement;
  289. FREE(CurrentStackElement);
  290. CurrentStackElement = NextStackElement;
  291. }
  292. //
  293. // Free the string copy.
  294. //
  295. if (Evaluation.InitialString != NULL) {
  296. FREE(Evaluation.InitialString);
  297. }
  298. return Status;
  299. }
  300. //
  301. // --------------------------------------------------------- Internal Functions
  302. //
  303. BOOL
  304. EvalEvaluateBasicList (
  305. PLIST_ENTRY ListHead,
  306. PULONGLONG Result
  307. )
  308. /*++
  309. Routine Description:
  310. This routine evaluates a simple arithmetic expression. It supports
  311. +, -, *, and / operators, but not parentheses.
  312. Arguments:
  313. ListHead - Supplies a pointer to the beginning of a list of
  314. EVALUATION_ELEMENTs. If completely successful, this list will have no
  315. members in it upon return, the members will have been freed. Upon
  316. failure, some of the members may have been freed, and any remaining ones
  317. will still be in the list.
  318. Result - Supplies a pointer where the resulting number will be returned.
  319. Return Value:
  320. Returns TRUE if the function was successful, or NULL if there was a syntax
  321. error.
  322. --*/
  323. {
  324. PEVALUATION_ELEMENT ComputationResult;
  325. PEVALUATION_ELEMENT CurrentElement;
  326. PLIST_ENTRY CurrentEntry;
  327. EVALUATION_OPERATOR CurrentPassOperator1;
  328. EVALUATION_OPERATOR CurrentPassOperator2;
  329. PEVALUATION_ELEMENT LeftOperand;
  330. ULONG Pass;
  331. PEVALUATION_ELEMENT RightOperand;
  332. *Result = 0;
  333. //
  334. // The first pass handles * and / operators only. The second pass handles
  335. // + and -. This accomplishes order of operations. Not allowing parentheses
  336. // makes this simplification possible.
  337. //
  338. for (Pass = 0; Pass < 2; Pass += 1) {
  339. //
  340. // Set the operators being looked at for the current pass.
  341. //
  342. if (Pass == 0) {
  343. CurrentPassOperator1 = OperatorMultiply;
  344. CurrentPassOperator2 = OperatorDivide;
  345. } else {
  346. CurrentPassOperator1 = OperatorAdd;
  347. CurrentPassOperator2 = OperatorSubtract;
  348. }
  349. CurrentEntry = ListHead->Next;
  350. while (CurrentEntry != ListHead) {
  351. CurrentElement = LIST_VALUE(CurrentEntry,
  352. EVALUATION_ELEMENT,
  353. ListEntry);
  354. //
  355. // Only basic operators and values are supported.
  356. //
  357. if ((CurrentElement->Operator == OperatorInvalid) ||
  358. (CurrentElement->Operator == OperatorOpenParentheses) ||
  359. (CurrentElement->Operator == OperatorCloseParentheses)) {
  360. return FALSE;
  361. }
  362. if ((CurrentElement->Operator == CurrentPassOperator1) ||
  363. (CurrentElement->Operator == CurrentPassOperator2)) {
  364. //
  365. // This had better not be the first or the last value in the
  366. // list.
  367. //
  368. if ((CurrentElement->ListEntry.Next == ListHead) ||
  369. (CurrentElement->ListEntry.Previous == ListHead)) {
  370. return FALSE;
  371. }
  372. //
  373. // Get the operands on either side of this one. They had better
  374. // be values (not other operands).
  375. //
  376. LeftOperand = LIST_VALUE(CurrentElement->ListEntry.Previous,
  377. EVALUATION_ELEMENT,
  378. ListEntry);
  379. RightOperand = LIST_VALUE(CurrentElement->ListEntry.Next,
  380. EVALUATION_ELEMENT,
  381. ListEntry);
  382. if ((LeftOperand->Operator != OperatorValue) ||
  383. (RightOperand->Operator != OperatorValue)) {
  384. return FALSE;
  385. }
  386. //
  387. // Based on the operator, compute the result and store it into
  388. // the operator's value. This will become the result.
  389. //
  390. if (CurrentElement->Operator == OperatorMultiply) {
  391. CurrentElement->Value = LeftOperand->Value *
  392. RightOperand->Value;
  393. } else if (CurrentElement->Operator == OperatorDivide) {
  394. CurrentElement->Value = LeftOperand->Value /
  395. RightOperand->Value;
  396. } else if (CurrentElement->Operator == OperatorAdd) {
  397. CurrentElement->Value = LeftOperand->Value +
  398. RightOperand->Value;
  399. } else if (CurrentElement->Operator == OperatorSubtract) {
  400. CurrentElement->Value = LeftOperand->Value -
  401. RightOperand->Value;
  402. } else {
  403. return FALSE;
  404. }
  405. CurrentElement->Operator = OperatorValue;
  406. //
  407. // Remove the left and right operands from the list and free
  408. // their data structures.
  409. //
  410. LIST_REMOVE(&(LeftOperand->ListEntry));
  411. LIST_REMOVE(&(RightOperand->ListEntry));
  412. FREE(LeftOperand);
  413. FREE(RightOperand);
  414. }
  415. CurrentEntry = CurrentEntry->Next;
  416. }
  417. }
  418. //
  419. // Both passes have completed. In the end one lone value should remain. If
  420. // something else is there, there was a syntax error.
  421. //
  422. ComputationResult = LIST_VALUE(ListHead->Next,
  423. EVALUATION_ELEMENT,
  424. ListEntry);
  425. if (ComputationResult->ListEntry.Next != ListHead) {
  426. return FALSE;
  427. }
  428. if (ComputationResult->Operator != OperatorValue) {
  429. return FALSE;
  430. }
  431. *Result = ComputationResult->Value;
  432. LIST_REMOVE(&(ComputationResult->ListEntry));
  433. FREE(ComputationResult);
  434. return TRUE;
  435. }
  436. INT
  437. EvalGetNextToken (
  438. PDEBUGGER_CONTEXT Context,
  439. PEVALUATION_DATA State,
  440. PEVALUATION_OPERATOR Operator,
  441. PULONGLONG Value
  442. )
  443. /*++
  444. Routine Description:
  445. This routine retrieves the next token from the evaluation string.
  446. Arguments:
  447. Context - Supplies a pointer to the application context.
  448. State - Supplies a pointer to the current evaluation state.
  449. Operator - Supplies a pointer that will receive the operator of the next
  450. token. If the end of the string is reached, the operator will be set to
  451. OperatorInvalid.
  452. Value - Supplies a pointer that will receieve the value of the token if it's
  453. not an operator.
  454. Return Value:
  455. 0 on success.
  456. Returns an error code on failure.
  457. --*/
  458. {
  459. PARM_GENERAL_REGISTERS ArmRegisters;
  460. ULONG Base;
  461. PSTR CurrentPosition;
  462. UCHAR FirstCharacter;
  463. INT Result;
  464. UCHAR SecondCharacter;
  465. PSTR SymbolEnd;
  466. UCHAR TerminatorValue;
  467. PX86_GENERAL_REGISTERS X86Registers;
  468. Result = 0;
  469. *Operator = OperatorInvalid;
  470. *Value = 0;
  471. FirstCharacter = *(State->String);
  472. CurrentPosition = State->String + 1;
  473. SymbolEnd = State->String + 1;
  474. //
  475. // If it's end of the string, end now.
  476. //
  477. if (FirstCharacter == '\0') {
  478. goto GetNextTokenEnd;
  479. }
  480. //
  481. // Find the end of the symbol.
  482. //
  483. while ((*SymbolEnd != '\0') &&
  484. (*SymbolEnd != '+') &&
  485. (*SymbolEnd != '-') &&
  486. (*SymbolEnd != '*') &&
  487. (*SymbolEnd != '/') &&
  488. (*SymbolEnd != '(') &&
  489. (*SymbolEnd != ')') &&
  490. (*SymbolEnd != '@')) {
  491. SymbolEnd += 1;
  492. }
  493. //
  494. // Check the standard operators.
  495. //
  496. if (FirstCharacter == '+') {
  497. *Operator = OperatorAdd;
  498. } else if (FirstCharacter == '-') {
  499. *Operator = OperatorSubtract;
  500. } else if (FirstCharacter == '*') {
  501. *Operator = OperatorMultiply;
  502. } else if (FirstCharacter == '/') {
  503. *Operator = OperatorDivide;
  504. } else if (FirstCharacter == '(') {
  505. *Operator = OperatorOpenParentheses;
  506. } else if (FirstCharacter == ')') {
  507. *Operator = OperatorCloseParentheses;
  508. //
  509. // If it's a digit between 1 and 9, it's clearly a number. Treat it as hex.
  510. //
  511. } else if ((FirstCharacter >= '1') && (FirstCharacter <= '9')) {
  512. *Value = strtoull(State->String, (PCHAR *)&CurrentPosition, 16);
  513. if (CurrentPosition == State->String) {
  514. Result = EINVAL;
  515. goto GetNextTokenEnd;
  516. }
  517. *Operator = OperatorValue;
  518. //
  519. // If the first character is 0, it could be a hex or decimal number. Check
  520. // the second digit to determine which one. Default to hex if nothing is
  521. // specified.
  522. //
  523. } else if (FirstCharacter == '0') {
  524. SecondCharacter = *(State->String + 1);
  525. Base = 16;
  526. if (SecondCharacter == 'x') {
  527. State->String += 2;
  528. Base = 16;
  529. } else if (SecondCharacter == 'n') {
  530. State->String += 2;
  531. Base = 10;
  532. }
  533. *Value = strtoull(State->String, (PCHAR *)&CurrentPosition, Base);
  534. if (CurrentPosition == State->String) {
  535. Result = EINVAL;
  536. goto GetNextTokenEnd;
  537. }
  538. *Operator = OperatorValue;
  539. //
  540. // The first character is an @, so the value is a register.
  541. //
  542. //
  543. } else if (FirstCharacter == '@') {
  544. assert(Context->CurrentEvent.Type == DebuggerEventBreak);
  545. X86Registers = &(Context->FrameRegisters.X86);
  546. ArmRegisters = &(Context->FrameRegisters.Arm);
  547. //
  548. // Assume success and set the operator. It will be set back if the
  549. // lookup fails. terminate the symbol string and attempt to look up the
  550. // register.
  551. //
  552. *Operator = OperatorValue;
  553. TerminatorValue = *SymbolEnd;
  554. *SymbolEnd = '\0';
  555. switch (Context->MachineType) {
  556. //
  557. // Get x86 registers.
  558. //
  559. case MACHINE_TYPE_X86:
  560. //
  561. // Start with the 32 bit registers.
  562. //
  563. if (strcasecmp(CurrentPosition, "eax") == 0) {
  564. *Value = X86Registers->Eax & 0xFFFFFFFF;
  565. } else if (strcasecmp(CurrentPosition, "ebx") == 0) {
  566. *Value = X86Registers->Ebx & 0xFFFFFFFF;
  567. } else if (strcasecmp(CurrentPosition, "ecx") == 0) {
  568. *Value = X86Registers->Ecx & 0xFFFFFFFF;
  569. } else if (strcasecmp(CurrentPosition, "edx") == 0) {
  570. *Value = X86Registers->Edx & 0xFFFFFFFF;
  571. } else if (strcasecmp(CurrentPosition, "esi") == 0) {
  572. *Value = X86Registers->Esi & 0xFFFFFFFF;
  573. } else if (strcasecmp(CurrentPosition, "edi") == 0) {
  574. *Value = X86Registers->Edi & 0xFFFFFFFF;
  575. } else if (strcasecmp(CurrentPosition, "esp") == 0) {
  576. *Value = X86Registers->Esp & 0xFFFFFFFF;
  577. } else if (strcasecmp(CurrentPosition, "ebp") == 0) {
  578. *Value = X86Registers->Ebp & 0xFFFFFFFF;
  579. } else if (strcasecmp(CurrentPosition, "eip") == 0) {
  580. *Value = X86Registers->Eip & 0xFFFFFFFF;
  581. } else if (strcasecmp(CurrentPosition, "eflags") == 0) {
  582. *Value = X86Registers->Eflags & 0xFFFFFFFF;
  583. //
  584. // Check the 8 bit registers.
  585. //
  586. } else if (strcasecmp(CurrentPosition, "al") == 0) {
  587. *Value = X86Registers->Eax & 0x00FF;
  588. } else if (strcasecmp(CurrentPosition, "ah") == 0) {
  589. *Value = X86Registers->Eax & 0xFF00;
  590. } else if (strcasecmp(CurrentPosition, "bl") == 0) {
  591. *Value = X86Registers->Ebx & 0x00FF;
  592. } else if (strcasecmp(CurrentPosition, "bh") == 0) {
  593. *Value = X86Registers->Ebx & 0xFF00;
  594. } else if (strcasecmp(CurrentPosition, "cl") == 0) {
  595. *Value = X86Registers->Ecx & 0x00FF;
  596. } else if (strcasecmp(CurrentPosition, "ch") == 0) {
  597. *Value = X86Registers->Ecx & 0xFF00;
  598. } else if (strcasecmp(CurrentPosition, "dl") == 0) {
  599. *Value = X86Registers->Edx & 0x00FF;
  600. } else if (strcasecmp(CurrentPosition, "dh") == 0) {
  601. *Value = X86Registers->Edx & 0xFF00;
  602. //
  603. // Finally, check the 16 bit registers.
  604. //
  605. } else if (strcasecmp(CurrentPosition, "ax") == 0) {
  606. *Value = X86Registers->Eax & 0xFFFF;
  607. } else if (strcasecmp(CurrentPosition, "bx") == 0) {
  608. *Value = X86Registers->Ebx & 0xFFFF;
  609. } else if (strcasecmp(CurrentPosition, "cx") == 0) {
  610. *Value = X86Registers->Ecx & 0xFFFF;
  611. } else if (strcasecmp(CurrentPosition, "dx") == 0) {
  612. *Value = X86Registers->Edx & 0xFFFF;
  613. } else if (strcasecmp(CurrentPosition, "si") == 0) {
  614. *Value = X86Registers->Esi & 0xFFFF;
  615. } else if (strcasecmp(CurrentPosition, "di") == 0) {
  616. *Value = X86Registers->Edi & 0xFFFF;
  617. } else if (strcasecmp(CurrentPosition, "sp") == 0) {
  618. *Value = X86Registers->Esp & 0xFFFF;
  619. } else if (strcasecmp(CurrentPosition, "bp") == 0) {
  620. *Value = X86Registers->Ebp & 0xFFFF;
  621. } else if (strcasecmp(CurrentPosition, "ip") == 0) {
  622. *Value = X86Registers->Eip & 0xFFFF;
  623. } else if (strcasecmp(CurrentPosition, "flags") == 0) {
  624. *Value = X86Registers->Eflags & 0xFFFF;
  625. } else if (strcasecmp(CurrentPosition, "cs") == 0) {
  626. *Value = X86Registers->Cs;
  627. } else if (strcasecmp(CurrentPosition, "ds") == 0) {
  628. *Value = X86Registers->Ds;
  629. } else if (strcasecmp(CurrentPosition, "es") == 0) {
  630. *Value = X86Registers->Es;
  631. } else if (strcasecmp(CurrentPosition, "fs") == 0) {
  632. *Value = X86Registers->Fs;
  633. } else if (strcasecmp(CurrentPosition, "gs") == 0) {
  634. *Value = X86Registers->Gs;
  635. } else if (strcasecmp(CurrentPosition, "ss") == 0) {
  636. *Value = X86Registers->Ss;
  637. //
  638. // No valid register name could be found. This is a syntax error.
  639. //
  640. } else {
  641. *Operator = OperatorInvalid;
  642. Result = EINVAL;
  643. goto GetNextTokenEnd;
  644. }
  645. break;
  646. //
  647. // Get ARM regisers.
  648. //
  649. case MACHINE_TYPE_ARM:
  650. if (strcasecmp(CurrentPosition, "r0") == 0) {
  651. *Value = ArmRegisters->R0;
  652. } else if (strcasecmp(CurrentPosition, "r1") == 0) {
  653. *Value = ArmRegisters->R1;
  654. } else if (strcasecmp(CurrentPosition, "r2") == 0) {
  655. *Value = ArmRegisters->R2;
  656. } else if (strcasecmp(CurrentPosition, "r3") == 0) {
  657. *Value = ArmRegisters->R3;
  658. } else if (strcasecmp(CurrentPosition, "r4") == 0) {
  659. *Value = ArmRegisters->R4;
  660. } else if (strcasecmp(CurrentPosition, "r5") == 0) {
  661. *Value = ArmRegisters->R5;
  662. } else if (strcasecmp(CurrentPosition, "r6") == 0) {
  663. *Value = ArmRegisters->R6;
  664. } else if (strcasecmp(CurrentPosition, "r7") == 0) {
  665. *Value = ArmRegisters->R7;
  666. } else if (strcasecmp(CurrentPosition, "r8") == 0) {
  667. *Value = ArmRegisters->R8;
  668. } else if (strcasecmp(CurrentPosition, "r9") == 0) {
  669. *Value = ArmRegisters->R9;
  670. } else if ((strcasecmp(CurrentPosition, "r10") == 0) ||
  671. (strcasecmp(CurrentPosition, "sl") == 0)) {
  672. *Value = ArmRegisters->R10;
  673. } else if ((strcasecmp(CurrentPosition, "r11") == 0) ||
  674. (strcasecmp(CurrentPosition, "fp") == 0)) {
  675. *Value = ArmRegisters->R11Fp;
  676. } else if ((strcasecmp(CurrentPosition, "r12") == 0) ||
  677. (strcasecmp(CurrentPosition, "ip") == 0)) {
  678. *Value = ArmRegisters->R12Ip;
  679. } else if ((strcasecmp(CurrentPosition, "r13") == 0) ||
  680. (strcasecmp(CurrentPosition, "sp") == 0)) {
  681. *Value = ArmRegisters->R13Sp;
  682. } else if ((strcasecmp(CurrentPosition, "r14") == 0) ||
  683. (strcasecmp(CurrentPosition, "lr") == 0)) {
  684. *Value = ArmRegisters->R14Lr;
  685. } else if ((strcasecmp(CurrentPosition, "r15") == 0) ||
  686. (strcasecmp(CurrentPosition, "pc") == 0)) {
  687. *Value = ArmRegisters->R15Pc;
  688. } else if (strcasecmp(CurrentPosition, "cpsr") == 0) {
  689. *Value = ArmRegisters->Cpsr;
  690. } else {
  691. *Operator = OperatorInvalid;
  692. Result = EINVAL;
  693. goto GetNextTokenEnd;
  694. }
  695. break;
  696. //
  697. // Unknown machine type.
  698. //
  699. default:
  700. *Operator = OperatorInvalid;
  701. Result = EINVAL;
  702. goto GetNextTokenEnd;
  703. }
  704. //
  705. // Restore the original string, and update the string position.
  706. //
  707. *SymbolEnd = TerminatorValue;
  708. CurrentPosition = SymbolEnd;
  709. //
  710. // The first character is not a recognized character, so assume it's a
  711. // symbol of some sort. Attempt to look up the symbol.
  712. //
  713. } else {
  714. //
  715. // Save the character after the symbol string, terminate the symbol
  716. // string, and attempt to look up the symbol.
  717. //
  718. TerminatorValue = *SymbolEnd;
  719. *SymbolEnd = '\0';
  720. Result = EvalGetAddressFromSymbol(Context, State->String, Value);
  721. //
  722. // Restore the original character. If the result was valid, then the
  723. // output parameter was already updated.
  724. //
  725. *SymbolEnd = TerminatorValue;
  726. CurrentPosition = SymbolEnd;
  727. if (Result == 0) {
  728. *Operator = OperatorValue;
  729. }
  730. }
  731. State->String = CurrentPosition;
  732. GetNextTokenEnd:
  733. return Result;
  734. }
  735. INT
  736. EvalGetAddressFromSymbol (
  737. PDEBUGGER_CONTEXT Context,
  738. PSTR SymbolName,
  739. PULONGLONG Address
  740. )
  741. /*++
  742. Routine Description:
  743. This routine converts a symbol name into a virtual address.
  744. Arguments:
  745. Context - Supplies a pointer to the application context.
  746. SymbolName - Supplies the string containing the name of the symbol.
  747. Address - Supplies a pointer that receives the resulting address of the
  748. symbol.
  749. Return Value:
  750. 0 if a data or function symbol was found.
  751. Returns an error code if no match could be made.
  752. --*/
  753. {
  754. PDEBUGGER_MODULE CurrentModule;
  755. PLIST_ENTRY CurrentModuleEntry;
  756. PSTR ModuleEnd;
  757. ULONG ModuleLength;
  758. ULONGLONG Pc;
  759. INT Result;
  760. PSYMBOL_SEARCH_RESULT ResultValid;
  761. SYMBOL_SEARCH_RESULT SearchResult;
  762. PDEBUGGER_MODULE UserModule;
  763. Result = EINVAL;
  764. UserModule = NULL;
  765. *Address = (INTN)NULL;
  766. //
  767. // If an exclamation point exists, then the module was specified. Find that
  768. // module.
  769. //
  770. ModuleEnd = strchr(SymbolName, '!');
  771. if (ModuleEnd != NULL) {
  772. ModuleLength = (UINTN)ModuleEnd - (UINTN)SymbolName;
  773. UserModule = DbgpGetModule(Context, SymbolName, ModuleLength);
  774. if (UserModule == NULL) {
  775. DbgOut("Module %s not found.\n", SymbolName);
  776. Result = EINVAL;
  777. goto GetAddressFromSymbolEnd;
  778. }
  779. //
  780. // Move the search string and initialize the list entry.
  781. //
  782. SymbolName = ModuleEnd + 1;
  783. CurrentModuleEntry = &(UserModule->ListEntry);
  784. //
  785. // If a module was not specified, simply start with the first one.
  786. //
  787. } else {
  788. CurrentModuleEntry = Context->ModuleList.ModulesHead.Next;
  789. }
  790. //
  791. // Loop over all modules.
  792. //
  793. while (CurrentModuleEntry != &(Context->ModuleList.ModulesHead)) {
  794. CurrentModule = LIST_VALUE(CurrentModuleEntry,
  795. DEBUGGER_MODULE,
  796. ListEntry);
  797. CurrentModuleEntry = CurrentModuleEntry->Next;
  798. if (!IS_MODULE_IN_CURRENT_PROCESS(Context, CurrentModule)) {
  799. if (UserModule != NULL) {
  800. break;
  801. }
  802. continue;
  803. }
  804. //
  805. // Find the symbol. This is not a search function, so accept the first
  806. // result.
  807. //
  808. SearchResult.Variety = SymbolResultInvalid;
  809. ResultValid = DbgpFindSymbolInModule(CurrentModule->Symbols,
  810. SymbolName,
  811. &SearchResult);
  812. //
  813. // If one was found, break out of this loop.
  814. //
  815. if ((ResultValid != NULL) &&
  816. (SearchResult.Variety != SymbolResultInvalid)) {
  817. if (SearchResult.Variety == SymbolResultFunction) {
  818. *Address = SearchResult.U.FunctionResult->StartAddress +
  819. CurrentModule->BaseDifference;
  820. //
  821. // Add in the thumb bit here so things like "g myfunc" work
  822. // correctly on Thumb.
  823. //
  824. if ((Context->MachineType == MACHINE_TYPE_ARM) &&
  825. ((Context->FrameRegisters.Arm.Cpsr &
  826. PSR_FLAG_THUMB) != 0)) {
  827. *Address |= ARM_THUMB_BIT;
  828. }
  829. Result = 0;
  830. break;
  831. } else if (SearchResult.Variety == SymbolResultData) {
  832. Pc = DbgGetPc(Context, &(Context->FrameRegisters)) -
  833. CurrentModule->BaseDifference;
  834. Result = DbgGetDataSymbolAddress(Context,
  835. CurrentModule->Symbols,
  836. SearchResult.U.DataResult,
  837. Pc,
  838. Address);
  839. if (Result == 0) {
  840. *Address += CurrentModule->BaseDifference;
  841. break;
  842. }
  843. }
  844. }
  845. //
  846. // If a specific user module was specified, do not loop over more
  847. // modules.
  848. //
  849. if (UserModule != NULL) {
  850. break;
  851. }
  852. }
  853. GetAddressFromSymbolEnd:
  854. return Result;
  855. }