dbgeval.c 33 KB

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