dwexpr.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. dwexpr.c
  5. Abstract:
  6. This module implements support for DWARF expressions and location lists.
  7. Author:
  8. Evan Green 7-Dec-2015
  9. Environment:
  10. Debug
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/lib/types.h>
  16. #include <minoca/lib/status.h>
  17. #include <minoca/lib/im.h>
  18. #include "dwarfp.h"
  19. #include <assert.h>
  20. #include <errno.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. //
  25. // --------------------------------------------------------------------- Macros
  26. //
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. //
  31. // ------------------------------------------------------ Data Type Definitions
  32. //
  33. //
  34. // ----------------------------------------------- Internal Function Prototypes
  35. //
  36. INT
  37. DwarfpEvaluateExpression (
  38. PDWARF_CONTEXT Context,
  39. PDWARF_LOCATION_CONTEXT LocationContext,
  40. PUCHAR Expression,
  41. UINTN Size
  42. );
  43. PSTR
  44. DwarfpGetOpName (
  45. DWARF_OP Op,
  46. PSTR Buffer,
  47. UINTN Size
  48. );
  49. VOID
  50. DwarfpExpressionPush (
  51. PDWARF_LOCATION_CONTEXT LocationContext,
  52. ULONGLONG Value
  53. );
  54. ULONGLONG
  55. DwarfpExpressionPop (
  56. PDWARF_LOCATION_CONTEXT LocationContext
  57. );
  58. INT
  59. DwarfpGetFrameBase (
  60. PDWARF_CONTEXT Context,
  61. PFUNCTION_SYMBOL Function,
  62. ULONGLONG Pc,
  63. PULONGLONG FrameBaseValue
  64. );
  65. //
  66. // -------------------------------------------------------------------- Globals
  67. //
  68. PSTR DwarfOpNames[] = {
  69. "DwarfOpNull",
  70. NULL,
  71. NULL,
  72. "DwarfOpAddress",
  73. NULL,
  74. NULL,
  75. "DwarfOpDereference",
  76. NULL,
  77. "DwarfOpConst1U",
  78. "DwarfOpConst1S",
  79. "DwarfOpConst2U",
  80. "DwarfOpConst2S",
  81. "DwarfOpConst4U",
  82. "DwarfOpConst4S",
  83. "DwarfOpConst8U",
  84. "DwarfOpConst8S",
  85. "DwarfOpConstU",
  86. "DwarfOpConstS",
  87. "DwarfOpDup",
  88. "DwarfOpDrop",
  89. "DwarfOpOver",
  90. "DwarfOpPick",
  91. "DwarfOpSwap",
  92. "DwarfOpRot",
  93. "DwarfOpXDeref",
  94. "DwarfOpAbs",
  95. "DwarfOpAnd",
  96. "DwarfOpDiv",
  97. "DwarfOpMinus",
  98. "DwarfOpMod",
  99. "DwarfOpMul",
  100. "DwarfOpNeg",
  101. "DwarfOpNot",
  102. "DwarfOpOr",
  103. "DwarfOpPlus",
  104. "DwarfOpPlusUConst",
  105. "DwarfOpShl",
  106. "DwarfOpShr",
  107. "DwarfOpShra",
  108. "DwarfOpXor",
  109. "DwarfOpBra",
  110. "DwarfOpEq",
  111. "DwarfOpGe",
  112. "DwarfOpGt",
  113. "DwarfOpLe",
  114. "DwarfOpLt",
  115. "DwarfOpNe",
  116. "DwarfOpSkip",
  117. "DwarfOpLit0"
  118. };
  119. PSTR DwarfOp90Names[] = {
  120. "DwarfOpRegX",
  121. "DwarfOpFbreg",
  122. "DwarfOpBregX",
  123. "DwarfOpPiece",
  124. "DwarfOpDerefSize",
  125. "DwarfOpXDerefSize",
  126. "DwarfOpNop",
  127. "DwarfOpPushObjectAddress",
  128. "DwarfOpCall2",
  129. "DwarfOpCall4",
  130. "DwarfOpCallRef",
  131. "DwarfOpFormTlsAddress",
  132. "DwarfOpCallFrameCfa",
  133. "DwarfOpBitPiece",
  134. "DwarfOpImplicitValue",
  135. "DwarfOpStackValue",
  136. };
  137. //
  138. // ------------------------------------------------------------------ Functions
  139. //
  140. INT
  141. DwarfpGetLocation (
  142. PDWARF_CONTEXT Context,
  143. PDWARF_LOCATION_CONTEXT LocationContext,
  144. PDWARF_ATTRIBUTE_VALUE AttributeValue
  145. )
  146. /*++
  147. Routine Description:
  148. This routine evaluates a DWARF location or location list. The caller is
  149. responsible for calling the destroy location context routine after this
  150. routine runs.
  151. Arguments:
  152. Context - Supplies a pointer to the context.
  153. LocationContext - Supplies a pointer to the location context, which is
  154. assumed to have been zeroed and properly filled in.
  155. AttributeValue - Supplies a pointer to the attribute value that contains
  156. the location expression.
  157. Return Value:
  158. 0 on success, and the final location will be returned in the location
  159. context.
  160. ENOENT if the attribute is a location list and none of the current PC is
  161. not in any of the locations.
  162. Returns an error number on failure.
  163. --*/
  164. {
  165. ULONGLONG Constant;
  166. PUCHAR Expression;
  167. UINTN ExpressionSize;
  168. INT Status;
  169. PDWARF_COMPILATION_UNIT Unit;
  170. Unit = LocationContext->Unit;
  171. assert(Unit != NULL);
  172. LocationContext->AddressSize = Unit->AddressSize;
  173. //
  174. // An expression location is the primary form to be dealt with.
  175. //
  176. if ((DWARF_SECTION_OFFSET_FORM(AttributeValue->Form, Unit)) ||
  177. (AttributeValue->Form == DwarfFormExprLoc) ||
  178. (DWARF_BLOCK_FORM(AttributeValue->Form))) {
  179. //
  180. // If it's a location list, find the expression that currently matches.
  181. //
  182. if (DWARF_SECTION_OFFSET_FORM(AttributeValue->Form, Unit)) {
  183. Status = DwarfpSearchLocationList(Context,
  184. Unit,
  185. AttributeValue->Value.Offset,
  186. LocationContext->Pc,
  187. &Expression,
  188. &ExpressionSize);
  189. if (Status != 0) {
  190. return Status;
  191. }
  192. //
  193. // Otherwise, use the expression built into the block.
  194. //
  195. } else {
  196. Expression = AttributeValue->Value.Block.Data;
  197. ExpressionSize = AttributeValue->Value.Block.Size;
  198. }
  199. LocationContext->Constant = TRUE;
  200. Status = DwarfpEvaluateExpression(Context,
  201. LocationContext,
  202. Expression,
  203. ExpressionSize);
  204. //
  205. // Try to just get a constant out of it.
  206. //
  207. } else {
  208. Status = 0;
  209. switch (AttributeValue->Form) {
  210. case DwarfFormData1:
  211. case DwarfFormData2:
  212. case DwarfFormData4:
  213. case DwarfFormData8:
  214. case DwarfFormSData:
  215. case DwarfFormUData:
  216. Constant = AttributeValue->Value.UnsignedConstant;
  217. break;
  218. case DwarfFormFlag:
  219. case DwarfFormFlagPresent:
  220. Constant = AttributeValue->Value.Flag;
  221. break;
  222. default:
  223. Status = ENOENT;
  224. break;
  225. }
  226. if (Status == 0) {
  227. LocationContext->Location.Form = DwarfLocationKnownValue;
  228. LocationContext->Location.Value.Value = Constant;
  229. }
  230. }
  231. return Status;
  232. }
  233. VOID
  234. DwarfpDestroyLocationContext (
  235. PDWARF_CONTEXT Context,
  236. PDWARF_LOCATION_CONTEXT LocationContext
  237. )
  238. /*++
  239. Routine Description:
  240. This routine destroys a DWARF location context.
  241. Arguments:
  242. Context - Supplies a pointer to the context.
  243. LocationContext - Supplies a pointer to the location context to clean up.
  244. Return Value:
  245. None.
  246. --*/
  247. {
  248. PDWARF_LOCATION Next;
  249. PDWARF_LOCATION Piece;
  250. Piece = LocationContext->Location.NextPiece;
  251. LocationContext->Location.NextPiece = NULL;
  252. while (Piece != NULL) {
  253. Next = Piece->NextPiece;
  254. free(Piece);
  255. Piece = Next;
  256. }
  257. return;
  258. }
  259. INT
  260. DwarfpEvaluateSimpleExpression (
  261. PDWARF_CONTEXT Context,
  262. UCHAR AddressSize,
  263. PDWARF_COMPILATION_UNIT Unit,
  264. ULONGLONG InitialPush,
  265. PUCHAR Expression,
  266. UINTN Size,
  267. PDWARF_LOCATION Location
  268. )
  269. /*++
  270. Routine Description:
  271. This routine evaluates a simple DWARF expression. A simple expression is
  272. one that is not possibly a location list, and will ultimately contain only
  273. a single piece.
  274. Arguments:
  275. Context - Supplies a pointer to the DWARF context.
  276. AddressSize - Supplies the size of an address on the target.
  277. Unit - Supplies an optional pointer to the compilation unit.
  278. InitialPush - Supplies a value to push onto the stack initially. Supply
  279. -1ULL to not push anything onto the stack initially.
  280. Expression - Supplies a pointer to the expression bytes to evaluate.
  281. Size - Supplies the size of the expression in bytes.
  282. Location - Supplies a pointer where the location information will be
  283. returned on success.
  284. Return Value:
  285. 0 on success.
  286. Returns an error code on failure.
  287. --*/
  288. {
  289. DWARF_LOCATION_CONTEXT LocationContext;
  290. INT Status;
  291. memset(&LocationContext, 0, sizeof(DWARF_LOCATION_CONTEXT));
  292. LocationContext.Unit = Unit;
  293. LocationContext.AddressSize = AddressSize;
  294. if (Unit != NULL) {
  295. LocationContext.AddressSize = Unit->AddressSize;
  296. }
  297. if (InitialPush != -1ULL) {
  298. LocationContext.Stack[0] = InitialPush;
  299. LocationContext.StackSize = 1;
  300. }
  301. Status = DwarfpEvaluateExpression(Context,
  302. &LocationContext,
  303. Expression,
  304. Size);
  305. if (Status == 0) {
  306. memcpy(Location, &(LocationContext.Location), sizeof(DWARF_LOCATION));
  307. if (Location->NextPiece != NULL) {
  308. DWARF_ERROR("DWARF: Simple expression had multiple pieces!\n");
  309. Location->NextPiece = NULL;
  310. }
  311. }
  312. DwarfpDestroyLocationContext(Context, &LocationContext);
  313. return Status;
  314. }
  315. VOID
  316. DwarfpPrintExpression (
  317. PDWARF_CONTEXT Context,
  318. UCHAR AddressSize,
  319. PDWARF_COMPILATION_UNIT Unit,
  320. PUCHAR Expression,
  321. UINTN Size
  322. )
  323. /*++
  324. Routine Description:
  325. This routine prints out a DWARF expression.
  326. Arguments:
  327. Context - Supplies a pointer to the context.
  328. AddressSize - Supplies the size of an address on the target.
  329. Unit - Supplies an optional pointer to the compilation unit.
  330. Expression - Supplies a pointer to the expression bytes.
  331. ExpressionEnd - Supplies the first byte beyond the expression bytes.
  332. Size - Supplies the size of the expression in bytes.
  333. Return Value:
  334. None.
  335. --*/
  336. {
  337. PUCHAR Bytes;
  338. PUCHAR End;
  339. DWARF_OP Op;
  340. CHAR OpBuffer[30];
  341. ULONGLONG Operand1;
  342. BOOL Operand1Signed;
  343. ULONGLONG Operand2;
  344. BOOL Operand2Signed;
  345. ULONG OperandCount;
  346. PSTR OpName;
  347. Bytes = Expression;
  348. End = Expression + Size;
  349. while (Bytes < End) {
  350. Op = DwarfpRead1(&Bytes);
  351. OpName = DwarfpGetOpName(Op, OpBuffer, sizeof(OpBuffer));
  352. DWARF_PRINT("%s ", OpName);
  353. OperandCount = 1;
  354. Operand1Signed = FALSE;
  355. Operand2Signed = FALSE;
  356. if ((Op >= DwarfOpBreg0) && (Op <= DwarfOpBreg31)) {
  357. Operand1 = DwarfpReadSleb128(&Bytes);
  358. Operand1Signed = TRUE;
  359. } else {
  360. switch (Op) {
  361. case DwarfOpAddress:
  362. if (AddressSize == 4) {
  363. Operand1 = DwarfpRead4(&Bytes);
  364. } else {
  365. assert(AddressSize == 8);
  366. Operand1 = DwarfpRead8(&Bytes);
  367. }
  368. break;
  369. case DwarfOpConst1U:
  370. case DwarfOpPick:
  371. case DwarfOpDerefSize:
  372. case DwarfOpXDerefSize:
  373. Operand1 = DwarfpRead1(&Bytes);
  374. break;
  375. case DwarfOpConst1S:
  376. Operand1 = (signed char)(DwarfpRead1(&Bytes));
  377. Operand1Signed = TRUE;
  378. break;
  379. case DwarfOpConst2U:
  380. case DwarfOpCall2:
  381. Operand1 = DwarfpRead2(&Bytes);
  382. break;
  383. case DwarfOpConst2S:
  384. case DwarfOpSkip:
  385. case DwarfOpBra:
  386. Operand1 = (SHORT)(DwarfpRead2(&Bytes));
  387. Operand1Signed = TRUE;
  388. break;
  389. case DwarfOpConst4U:
  390. case DwarfOpCall4:
  391. Operand1 = DwarfpRead4(&Bytes);
  392. break;
  393. case DwarfOpConst4S:
  394. Operand1 = (LONG)(DwarfpRead4(&Bytes));
  395. Operand1Signed = TRUE;
  396. break;
  397. case DwarfOpConst8U:
  398. Operand1 = DwarfpRead8(&Bytes);
  399. break;
  400. case DwarfOpConst8S:
  401. Operand1 = (LONGLONG)(DwarfpRead8(&Bytes));
  402. Operand1Signed = TRUE;
  403. break;
  404. case DwarfOpConstU:
  405. case DwarfOpPlusUConst:
  406. case DwarfOpRegX:
  407. case DwarfOpPiece:
  408. Operand1 = DwarfpReadLeb128(&Bytes);
  409. break;
  410. case DwarfOpConstS:
  411. case DwarfOpFbreg:
  412. Operand1 = DwarfpReadSleb128(&Bytes);
  413. Operand1Signed = TRUE;
  414. break;
  415. case DwarfOpBregX:
  416. Operand1 = DwarfpReadLeb128(&Bytes);
  417. Operand2 = DwarfpReadSleb128(&Bytes);
  418. Operand2Signed = TRUE;
  419. OperandCount = 2;
  420. break;
  421. case DwarfOpCallRef:
  422. Operand1 = 0;
  423. if (Unit != NULL) {
  424. Operand1 = DWARF_READN(&Bytes, Unit->Is64Bit);
  425. }
  426. break;
  427. case DwarfOpBitPiece:
  428. Operand1 = DwarfpReadLeb128(&Bytes);
  429. Operand2 = DwarfpReadLeb128(&Bytes);
  430. OperandCount = 2;
  431. break;
  432. case DwarfOpImplicitValue:
  433. Operand1 = DwarfpReadLeb128(&Bytes);
  434. Bytes += Operand1;
  435. break;
  436. case DwarfOpGnuEntryValue:
  437. Operand1 = DwarfpReadLeb128(&Bytes);
  438. break;
  439. case DwarfOpGnuImplicitPointer:
  440. if (AddressSize == 8) {
  441. Operand1 = DwarfpRead8(&Bytes);
  442. } else {
  443. Operand1 = DwarfpRead4(&Bytes);
  444. }
  445. Operand2 = DwarfpReadSleb128(&Bytes);
  446. Operand2Signed = TRUE;
  447. OperandCount = 2;
  448. break;
  449. case DwarfOpGnuConstType:
  450. Operand1 = DwarfpReadLeb128(&Bytes);
  451. Operand2 = DwarfpRead1(&Bytes);
  452. Bytes += Operand2;
  453. break;
  454. case DwarfOpGnuConvert:
  455. case DwarfOpGnuReinterpret:
  456. Operand1 = DwarfpReadLeb128(&Bytes);
  457. break;
  458. //
  459. // Parameter references point to a DIE that contains an
  460. // optimized-away parameter.
  461. //
  462. case DwarfOpGnuParameterRef:
  463. Operand1 = DwarfpRead4(&Bytes);
  464. break;
  465. default:
  466. OperandCount = 0;
  467. break;
  468. }
  469. }
  470. if (OperandCount != 0) {
  471. if (Operand1Signed != FALSE) {
  472. DWARF_PRINT("%I64d ", Operand1);
  473. } else {
  474. DWARF_PRINT("%I64u ", Operand1);
  475. }
  476. if (OperandCount == 2) {
  477. if (Operand2Signed != FALSE) {
  478. DWARF_PRINT("%I64d ", Operand2);
  479. } else {
  480. DWARF_PRINT("%I64u ", Operand2);
  481. }
  482. }
  483. }
  484. }
  485. return;
  486. }
  487. //
  488. // --------------------------------------------------------- Internal Functions
  489. //
  490. INT
  491. DwarfpEvaluateExpression (
  492. PDWARF_CONTEXT Context,
  493. PDWARF_LOCATION_CONTEXT LocationContext,
  494. PUCHAR Expression,
  495. UINTN Size
  496. )
  497. /*++
  498. Routine Description:
  499. This routine executes a DWARF expression.
  500. Arguments:
  501. Context - Supplies a pointer to the context.
  502. LocationContext - Supplies a pointer to the location context to clean up.
  503. Expression - Supplies a pointer to the expression bytes.
  504. Size - Supplies the size of the expression in bytes.
  505. Return Value:
  506. 0 on success.
  507. Returns a status code on failure.
  508. --*/
  509. {
  510. UCHAR AddressSize;
  511. PUCHAR End;
  512. STACK_FRAME Frame;
  513. ULONG Index;
  514. PDWARF_LOCATION Location;
  515. DWARF_OP Op;
  516. PDWARF_LOCATION PreviousLocation;
  517. ULONG SizeOperand;
  518. ULONG StackSize;
  519. INT Status;
  520. ULONGLONG Value;
  521. ULONGLONG Value2;
  522. ULONGLONG Value3;
  523. AddressSize = LocationContext->AddressSize;
  524. assert((AddressSize == 8) || (AddressSize == 4));
  525. End = Expression + Size;
  526. PreviousLocation = NULL;
  527. Location = &(LocationContext->Location);
  528. Status = 0;
  529. while (Expression < End) {
  530. Op = DwarfpRead1(&Expression);
  531. switch (Op) {
  532. //
  533. // Push the one operand, which is the size of a target address.
  534. //
  535. case DwarfOpAddress:
  536. if (AddressSize == 8) {
  537. Value = DwarfpRead8(&Expression);
  538. } else {
  539. Value = DwarfpRead4(&Expression);
  540. }
  541. DwarfpExpressionPush(LocationContext, Value);
  542. break;
  543. //
  544. // Dereference pops an address, reads up to an address size's worth of
  545. // data from the target memory at that location, and pushes that back
  546. // on the stack. The X variants also pop an address space ID. The size
  547. // variants specify the size to read explicitly.
  548. //
  549. case DwarfOpXDerefSize:
  550. case DwarfOpXDeref:
  551. case DwarfOpDereference:
  552. case DwarfOpDerefSize:
  553. case DwarfOpGnuDerefType:
  554. Value = DwarfpExpressionPop(LocationContext);
  555. SizeOperand = AddressSize;
  556. if ((Op == DwarfOpXDerefSize) || (Op == DwarfOpDerefSize) ||
  557. (Op == DwarfOpGnuDerefType)) {
  558. SizeOperand = DwarfpRead1(&Expression);
  559. if (SizeOperand > AddressSize) {
  560. SizeOperand = AddressSize;
  561. }
  562. }
  563. //
  564. // Scan past the DIE offset of a type to interpret this as.
  565. //
  566. if (Op == DwarfOpGnuDerefType) {
  567. DwarfpReadLeb128(&Expression);
  568. }
  569. //
  570. // Pop the address space ID if this is an X operation.
  571. //
  572. Value2 = 0;
  573. if ((Op == DwarfOpXDerefSize) || (Op == DwarfOpXDeref)) {
  574. Value2 = DwarfpExpressionPop(LocationContext);
  575. }
  576. Value3 = 0;
  577. LocationContext->Constant = FALSE;
  578. Status = DwarfTargetRead(Context,
  579. Value,
  580. SizeOperand,
  581. Value2,
  582. &Value3);
  583. if (Status != 0) {
  584. DWARF_ERROR("DWARF: Target read failure from address "
  585. "0x%I64x (address space %d).\n",
  586. Value,
  587. (ULONG)Value2);
  588. goto EvaluateExpressionEnd;
  589. }
  590. DwarfpExpressionPush(LocationContext, Value3);
  591. break;
  592. case DwarfOpConst1U:
  593. Value = DwarfpRead1(&Expression);
  594. DwarfpExpressionPush(LocationContext, Value);
  595. break;
  596. case DwarfOpConst1S:
  597. Value = (LONGLONG)(signed char)(DwarfpRead1(&Expression));
  598. DwarfpExpressionPush(LocationContext, Value);
  599. break;
  600. case DwarfOpConst2U:
  601. Value = DwarfpRead2(&Expression);
  602. DwarfpExpressionPush(LocationContext, Value);
  603. break;
  604. case DwarfOpConst2S:
  605. Value = (LONGLONG)(SHORT)(DwarfpRead2(&Expression));
  606. DwarfpExpressionPush(LocationContext, Value);
  607. break;
  608. case DwarfOpConst4U:
  609. Value = DwarfpRead4(&Expression);
  610. DwarfpExpressionPush(LocationContext, Value);
  611. break;
  612. case DwarfOpConst4S:
  613. Value = (LONGLONG)(LONG)(DwarfpRead4(&Expression));
  614. DwarfpExpressionPush(LocationContext, Value);
  615. break;
  616. case DwarfOpConst8U:
  617. Value = DwarfpRead8(&Expression);
  618. DwarfpExpressionPush(LocationContext, Value);
  619. break;
  620. case DwarfOpConst8S:
  621. Value = (LONGLONG)(DwarfpRead8(&Expression));
  622. DwarfpExpressionPush(LocationContext, Value);
  623. break;
  624. case DwarfOpConstU:
  625. Value = DwarfpReadLeb128(&Expression);
  626. DwarfpExpressionPush(LocationContext, Value);
  627. break;
  628. case DwarfOpConstS:
  629. Value = DwarfpReadSleb128(&Expression);
  630. DwarfpExpressionPush(LocationContext, Value);
  631. break;
  632. //
  633. // Duplicate the value at the top of the stack.
  634. //
  635. case DwarfOpDup:
  636. Value = DwarfpExpressionPop(LocationContext);
  637. DwarfpExpressionPush(LocationContext, Value);
  638. DwarfpExpressionPush(LocationContext, Value);
  639. break;
  640. //
  641. // Pop and ignore the value at the top of the stack.
  642. //
  643. case DwarfOpDrop:
  644. DwarfpExpressionPop(LocationContext);
  645. break;
  646. //
  647. // Over is equivalent to pick(1).
  648. //
  649. case DwarfOpOver:
  650. Index = 1;
  651. //
  652. // Fall through.
  653. //
  654. //
  655. // Copy and push the stack entry at the specified index.
  656. //
  657. case DwarfOpPick:
  658. if (Op == DwarfOpPick) {
  659. Index = DwarfpRead1(&Expression);
  660. } else {
  661. Index = 0;
  662. }
  663. StackSize = LocationContext->StackSize;
  664. if (Index < StackSize) {
  665. Value = LocationContext->Stack[StackSize - 1 - Index];
  666. DwarfpExpressionPush(LocationContext, Value);
  667. } else {
  668. assert(FALSE);
  669. }
  670. break;
  671. //
  672. // Swap the top two entries of the stack.
  673. //
  674. case DwarfOpSwap:
  675. Value = DwarfpExpressionPop(LocationContext);
  676. Value2 = DwarfpExpressionPop(LocationContext);
  677. DwarfpExpressionPush(LocationContext, Value);
  678. DwarfpExpressionPush(LocationContext, Value2);
  679. break;
  680. //
  681. // Rotate the first three stack entries.
  682. //
  683. case DwarfOpRot:
  684. Value = DwarfpExpressionPop(LocationContext);
  685. Value2 = DwarfpExpressionPop(LocationContext);
  686. Value3 = DwarfpExpressionPop(LocationContext);
  687. DwarfpExpressionPush(LocationContext, Value);
  688. DwarfpExpressionPush(LocationContext, Value3);
  689. DwarfpExpressionPush(LocationContext, Value2);
  690. break;
  691. //
  692. // Handle unary arithmetic operators.
  693. //
  694. case DwarfOpAbs:
  695. case DwarfOpNot:
  696. case DwarfOpNeg:
  697. Value = DwarfpExpressionPop(LocationContext);
  698. switch (Op) {
  699. case DwarfOpAbs:
  700. if ((LONGLONG)Value < 0) {
  701. Value = -Value;
  702. }
  703. break;
  704. case DwarfOpNot:
  705. Value = ~Value;
  706. break;
  707. case DwarfOpNeg:
  708. Value = -(LONGLONG)Value;
  709. break;
  710. default:
  711. assert(FALSE);
  712. Value = 0;
  713. break;
  714. }
  715. DwarfpExpressionPush(LocationContext, Value);
  716. break;
  717. //
  718. // Handle arithmetic operators, that pop two values, compute something,
  719. // and then push the value back. The second value on the stack is
  720. // the "thing to operate on", and the first value is the operand.
  721. //
  722. case DwarfOpAnd:
  723. case DwarfOpDiv:
  724. case DwarfOpMinus:
  725. case DwarfOpMod:
  726. case DwarfOpMul:
  727. case DwarfOpOr:
  728. case DwarfOpPlus:
  729. case DwarfOpShl:
  730. case DwarfOpShr:
  731. case DwarfOpShra:
  732. case DwarfOpXor:
  733. case DwarfOpEq:
  734. case DwarfOpGe:
  735. case DwarfOpGt:
  736. case DwarfOpLe:
  737. case DwarfOpLt:
  738. case DwarfOpNe:
  739. Value = DwarfpExpressionPop(LocationContext);
  740. Value2 = DwarfpExpressionPop(LocationContext);
  741. switch (Op) {
  742. case DwarfOpAnd:
  743. Value3 = Value & Value2;
  744. break;
  745. case DwarfOpDiv:
  746. Value3 = 0;
  747. if (Value != 0) {
  748. Value3 = (LONGLONG)Value2 / (LONGLONG)Value;
  749. }
  750. break;
  751. case DwarfOpMinus:
  752. Value3 = Value2 - Value;
  753. break;
  754. case DwarfOpMod:
  755. Value3 = 0;
  756. if (Value3 != 0) {
  757. Value3 = (LONGLONG)Value2 % (LONGLONG)Value;
  758. }
  759. break;
  760. case DwarfOpMul:
  761. Value3 = Value * Value2;
  762. break;
  763. case DwarfOpOr:
  764. Value3 = Value | Value2;
  765. break;
  766. case DwarfOpPlus:
  767. Value3 = Value + Value2;
  768. break;
  769. case DwarfOpShl:
  770. Value3 = Value2 << Value;
  771. break;
  772. case DwarfOpShr:
  773. Value3 = Value2 >> Value;
  774. break;
  775. case DwarfOpShra:
  776. Value3 = ((LONGLONG)Value2) >> Value;
  777. break;
  778. case DwarfOpXor:
  779. Value3 = Value ^ Value2;
  780. break;
  781. case DwarfOpEq:
  782. Value3 = Value == Value2;
  783. break;
  784. case DwarfOpGe:
  785. Value3 = Value2 >= Value;
  786. break;
  787. case DwarfOpGt:
  788. Value3 = Value2 > Value;
  789. break;
  790. case DwarfOpLe:
  791. Value3 = Value2 <= Value;
  792. break;
  793. case DwarfOpLt:
  794. Value3 = Value2 < Value;
  795. break;
  796. case DwarfOpNe:
  797. Value3 = Value2 != Value;
  798. break;
  799. default:
  800. assert(FALSE);
  801. Value3 = 0;
  802. break;
  803. }
  804. DwarfpExpressionPush(LocationContext, Value3);
  805. break;
  806. //
  807. // Pop the top value, add it to the LEB128 operand, and push the
  808. // result.
  809. //
  810. case DwarfOpPlusUConst:
  811. Value = DwarfpExpressionPop(LocationContext);
  812. Value2 = DwarfpReadLeb128(&Expression);
  813. Value += Value2;
  814. DwarfpExpressionPush(LocationContext, Value);
  815. break;
  816. //
  817. // Conditional branch. If the top value of the stack is non-zero,
  818. // branch to the 2-byte signed operand away.
  819. // TODO: Is the branch (and skip) from the next instruction or this one?
  820. //
  821. case DwarfOpBra:
  822. Value = DwarfpExpressionPop(LocationContext);
  823. Value2 = (SHORT)DwarfpRead2(&Expression);
  824. if (Value != 0) {
  825. Expression += Value2;
  826. }
  827. break;
  828. case DwarfOpSkip:
  829. Value2 = (SHORT)DwarfpRead2(&Expression);
  830. Expression += Value2;
  831. break;
  832. case DwarfOpCall2:
  833. case DwarfOpCall4:
  834. case DwarfOpCallRef:
  835. if ((Op == DwarfOpCall2) || (Op == DwarfOpCall4)) {
  836. if (Op == DwarfOpCall2) {
  837. Value = DwarfpRead2(&Expression);
  838. } else {
  839. Value = DwarfpRead4(&Expression);
  840. }
  841. } else {
  842. if (LocationContext->Unit == NULL) {
  843. Status = EINVAL;
  844. goto EvaluateExpressionEnd;
  845. }
  846. if (LocationContext->Unit->Is64Bit != FALSE) {
  847. Value = DwarfpRead8(&Expression);
  848. } else {
  849. Value = DwarfpRead4(&Expression);
  850. }
  851. }
  852. //
  853. // Calls are not currently implemented. Call2 and Call4 are not
  854. // so bad as they involve finding the DIE in question (a little
  855. // trouble, but not too bad), then getting and executing the
  856. // attribute. The trouble with the ref call is that it points to a
  857. // DIE in some other module, but with no way to find the
  858. // abbreviation tables or compilation unit for that DIE. No one
  859. // seems to implement or use it, so for now just ignore all this.
  860. //
  861. assert(FALSE);
  862. break;
  863. case DwarfOpFbreg:
  864. LocationContext->Constant = FALSE;
  865. Status = DwarfpGetFrameBase(Context,
  866. LocationContext->CurrentFunction,
  867. LocationContext->Pc,
  868. &Value);
  869. if (Status != 0) {
  870. DWARF_ERROR("DWARF: Failed to get frame base.\n");
  871. goto EvaluateExpressionEnd;
  872. }
  873. Value2 = DwarfpReadSleb128(&Expression);
  874. Value += Value2;
  875. DwarfpExpressionPush(LocationContext, Value);
  876. break;
  877. case DwarfOpCallFrameCfa:
  878. LocationContext->Constant = FALSE;
  879. Status = DwarfpStackUnwind(Context,
  880. LocationContext->Pc,
  881. TRUE,
  882. &Frame);
  883. if (Status != 0) {
  884. DWARF_ERROR("DWARF: Failed to get CFA.\n");
  885. goto EvaluateExpressionEnd;
  886. }
  887. Value = Frame.FramePointer;
  888. DwarfpExpressionPush(LocationContext, Value);
  889. break;
  890. //
  891. // Piece defines that a portion of the location resides here. Bit piece
  892. // takes the size and offset in bits.
  893. //
  894. case DwarfOpPiece:
  895. case DwarfOpBitPiece:
  896. if (Op == DwarfOpPiece) {
  897. Value = DwarfpReadLeb128(&Expression) * BITS_PER_BYTE;
  898. Value2 = 0;
  899. } else {
  900. Value = DwarfpReadLeb128(&Expression);
  901. Value2 = DwarfpReadLeb128(&Expression);
  902. }
  903. //
  904. // If the location is not yet formed, grab its value off the stack.
  905. //
  906. if (Location->Form == DwarfLocationInvalid) {
  907. StackSize = LocationContext->StackSize;
  908. if (StackSize != 0) {
  909. Location->Form = DwarfLocationMemory;
  910. Location->Value.Address =
  911. LocationContext->Stack[StackSize - 1];
  912. } else {
  913. Location->Form = DwarfLocationUndefined;
  914. }
  915. }
  916. Location->BitSize = Value;
  917. Location->BitOffset = Value2;
  918. if (PreviousLocation != NULL) {
  919. PreviousLocation->NextPiece = Location;
  920. }
  921. PreviousLocation = Location;
  922. //
  923. // Create a new location piece if there is more stuff.
  924. //
  925. Location = NULL;
  926. if (Expression < End) {
  927. Location = malloc(sizeof(DWARF_LOCATION));
  928. if (Location == NULL) {
  929. Status = ENOMEM;
  930. goto EvaluateExpressionEnd;
  931. }
  932. memset(Location, 0, sizeof(DWARF_LOCATION));
  933. }
  934. //
  935. // Clear the stack. It's not obvious from the spec whether or not
  936. // this is the right thing to do, so change this if things aren't
  937. // working.
  938. //
  939. LocationContext->StackSize = 0;
  940. break;
  941. case DwarfOpNop:
  942. break;
  943. case DwarfOpPushObjectAddress:
  944. Value = LocationContext->ObjectAddress;
  945. DwarfpExpressionPush(LocationContext, Value);
  946. break;
  947. //
  948. // Pop the value, add it to the current thread and module's TLS base,
  949. // and push it back.
  950. //
  951. case DwarfOpFormTlsAddress:
  952. case DwarfOpGnuPushTlsAddress:
  953. LocationContext->Constant = FALSE;
  954. Value = DwarfpExpressionPop(LocationContext);
  955. Value += LocationContext->TlsBase;
  956. DwarfpExpressionPush(LocationContext, Value);
  957. break;
  958. //
  959. // Implicit value specifies that there is no location, but the value
  960. // is known.
  961. //
  962. case DwarfOpImplicitValue:
  963. Value = DwarfpReadLeb128(&Expression);
  964. Location->Form = DwarfLocationKnownData;
  965. Location->Value.Buffer.Data = Expression;
  966. Location->Value.Buffer.Size = Value;
  967. Expression += Value;
  968. break;
  969. //
  970. // Stack value specifies that there is no location, but the value
  971. // itself is at the top of the stack. This also terminates the
  972. // expression.
  973. //
  974. case DwarfOpStackValue:
  975. Value = DwarfpExpressionPop(LocationContext);
  976. Location->Form = DwarfLocationKnownValue;
  977. Location->Value.Value = Value;
  978. Status = 0;
  979. Expression = End;
  980. break;
  981. //
  982. // The variable is uninitialized.
  983. //
  984. case DwarfOpGnuUninit:
  985. break;
  986. //
  987. // The entry value contains a LEB128 length, followed by a block of
  988. // DWARF expression. The expression is either a DWARF register op,
  989. // or a generic expression. The expression should be evaluated as if
  990. // the machine was at the beginning of the current function. That is,
  991. // "unwind this function and then run the inner expression". For now
  992. // just push 0 and skip the whole thing.
  993. //
  994. case DwarfOpGnuEntryValue:
  995. Value = DwarfpReadLeb128(&Expression);
  996. Expression += Value;
  997. DwarfpExpressionPush(LocationContext, 0);
  998. break;
  999. //
  1000. // The implicit pointer informs the user that while the location of
  1001. // an object is unavailable, the actual value of that object can be
  1002. // known. It has two operands, an address-sized offset to a DIE
  1003. // describing the value of the variable (in it's location attribute),
  1004. // and a SLEB128 byte offset into that value. Currently this is just
  1005. // returned as undefined.
  1006. //
  1007. case DwarfOpGnuImplicitPointer:
  1008. if (AddressSize == 8) {
  1009. Value = DwarfpRead8(&Expression);
  1010. } else {
  1011. Value = DwarfpRead4(&Expression);
  1012. }
  1013. DwarfpReadSleb128(&Expression);
  1014. Location->Form = DwarfLocationUndefined;
  1015. break;
  1016. case DwarfOpGnuAddrIndex:
  1017. case DwarfOpGnuConstIndex:
  1018. //
  1019. // Consider implementing (or at least ignoring) these extensions.
  1020. //
  1021. assert(FALSE);
  1022. break;
  1023. //
  1024. // Constant data, preceded by a type DIE offset.
  1025. //
  1026. case DwarfOpGnuConstType:
  1027. DwarfpReadLeb128(&Expression);
  1028. Size = DwarfpRead1(&Expression);
  1029. Value = 0;
  1030. if (Size <= sizeof(ULONGLONG)) {
  1031. memcpy(&Value, Expression, Size);
  1032. }
  1033. DwarfpExpressionPush(LocationContext, Value);
  1034. Expression += Size;
  1035. break;
  1036. //
  1037. // Convert and reinterpret pop a value off the stack, cast it to
  1038. // the given type (specified by a DIE offset to a type), and push the
  1039. // value back. Just ignore this for now.
  1040. //
  1041. case DwarfOpGnuConvert:
  1042. case DwarfOpGnuReinterpret:
  1043. DwarfpReadLeb128(&Expression);
  1044. break;
  1045. //
  1046. // Parameter references point to a DIE that contains an optimized-away
  1047. // parameter.
  1048. //
  1049. case DwarfOpGnuParameterRef:
  1050. DwarfpRead4(&Expression);
  1051. DwarfpExpressionPush(LocationContext, 0);
  1052. break;
  1053. //
  1054. // Handle unknown or ranges of values.
  1055. //
  1056. default:
  1057. //
  1058. // Handle the literal encodings.
  1059. //
  1060. if ((Op >= DwarfOpLit0) && (Op <= DwarfOpLit31)) {
  1061. Value = Op - DwarfOpLit0;
  1062. DwarfpExpressionPush(LocationContext, Value);
  1063. break;
  1064. //
  1065. // Return register locations themselves.
  1066. //
  1067. } else if (((Op >= DwarfOpReg0) && (Op <= DwarfOpReg31)) ||
  1068. (Op == DwarfOpRegX)) {
  1069. if (Op == DwarfOpRegX) {
  1070. Value = DwarfpReadLeb128(&Expression);
  1071. } else {
  1072. Value = Op - DwarfOpReg0;
  1073. }
  1074. Location->Form = DwarfLocationRegister;
  1075. Location->Value.Register = Value;
  1076. break;
  1077. //
  1078. // Handle the register encodings.
  1079. //
  1080. } else if (((Op >= DwarfOpBreg0) && (Op <= DwarfOpBreg31)) ||
  1081. (Op == DwarfOpBregX) || (Op == DwarfOpGnuRegvalType)) {
  1082. LocationContext->Constant = FALSE;
  1083. Value2 = 0;
  1084. if (Op == DwarfOpBregX) {
  1085. Value = DwarfpReadLeb128(&Expression);
  1086. Value2 = DwarfpReadSleb128(&Expression);
  1087. //
  1088. // This regval type extension reads a register and interprets
  1089. // it as a given type (specified by a DIE offset).
  1090. //
  1091. } else if (Op == DwarfOpGnuRegvalType) {
  1092. Value = DwarfpReadLeb128(&Expression);
  1093. DwarfpReadLeb128(&Expression);
  1094. Value2 = 0;
  1095. } else {
  1096. Value = Op - DwarfOpBreg0;
  1097. Value2 = DwarfpReadSleb128(&Expression);
  1098. }
  1099. Status = DwarfTargetReadRegister(Context, Value, &Value);
  1100. if (Status != 0) {
  1101. DWARF_ERROR("DWARF: Failed to read register %I64d\n",
  1102. Value);
  1103. goto EvaluateExpressionEnd;
  1104. }
  1105. Value += Value2;
  1106. DwarfpExpressionPush(LocationContext, Value);
  1107. break;
  1108. }
  1109. DWARF_ERROR("DWARF: Unhandled expression op 0x%x", Op);
  1110. assert(FALSE);
  1111. Status = ENOSYS;
  1112. goto EvaluateExpressionEnd;
  1113. }
  1114. }
  1115. //
  1116. // If this is the end and the current location has not yet been filled in,
  1117. // assume it's a memory location at the top of the stack.
  1118. //
  1119. assert(Expression == End);
  1120. if ((Location != NULL) && (Location->Form == DwarfLocationInvalid)) {
  1121. StackSize = LocationContext->StackSize;
  1122. if (StackSize != 0) {
  1123. Location->Form = DwarfLocationMemory;
  1124. Location->Value.Address = LocationContext->Stack[StackSize - 1];
  1125. } else {
  1126. Location->Form = DwarfLocationUndefined;
  1127. }
  1128. if (PreviousLocation != NULL) {
  1129. PreviousLocation->NextPiece = Location;
  1130. }
  1131. Location = NULL;
  1132. }
  1133. EvaluateExpressionEnd:
  1134. //
  1135. // Free a leftover location.
  1136. //
  1137. if ((Location != NULL) && (Location != &(LocationContext->Location))) {
  1138. assert((PreviousLocation != NULL) &&
  1139. (PreviousLocation->NextPiece == NULL));
  1140. free(Location);
  1141. }
  1142. return Status;
  1143. }
  1144. PSTR
  1145. DwarfpGetOpName (
  1146. DWARF_OP Op,
  1147. PSTR Buffer,
  1148. UINTN Size
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. This routine returns the string describing a dwarf op.
  1153. Arguments:
  1154. Op - Supplies the op to decode.
  1155. Buffer - Supplies a pointer to a buffer used for dynamically generated ops.
  1156. Size - Supplies the size of the buffer in bytes.
  1157. Return Value:
  1158. Returns a pointer to a string containing the name of the op. This may
  1159. either be a pointer to a static memory location, or a pointer to the
  1160. buffer passed in.
  1161. --*/
  1162. {
  1163. if (Op <= DwarfOpLit0) {
  1164. return DwarfOpNames[Op];
  1165. } else if (Op <= DwarfOpLit31) {
  1166. snprintf(Buffer, Size, "DwarfOpLit%d", Op - DwarfOpLit0);
  1167. return Buffer;
  1168. } else if (Op <= DwarfOpReg31) {
  1169. snprintf(Buffer, Size, "DwarfReg%d", Op - DwarfOpReg0);
  1170. return Buffer;
  1171. } else if (Op <= DwarfOpBreg31) {
  1172. snprintf(Buffer, Size, "DwarfBreg%d", Op - DwarfOpBreg0);
  1173. return Buffer;
  1174. } else if (Op <= DwarfOpStackValue) {
  1175. assert(Op >= 0x90);
  1176. return DwarfOp90Names[Op - 0x90];
  1177. }
  1178. return "DwarfOpUNKNOWN";
  1179. }
  1180. VOID
  1181. DwarfpExpressionPush (
  1182. PDWARF_LOCATION_CONTEXT LocationContext,
  1183. ULONGLONG Value
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This routine pushes a value onto the DWARF expression stack.
  1188. Arguments:
  1189. LocationContext - Supplies a pointer to the execution context.
  1190. Value - Supplies the value to push.
  1191. Return Value:
  1192. None.
  1193. --*/
  1194. {
  1195. ULONG StackSize;
  1196. StackSize = LocationContext->StackSize;
  1197. if (StackSize < DWARF_EXPRESSION_STACK_SIZE) {
  1198. LocationContext->Stack[StackSize] = Value;
  1199. LocationContext->StackSize += 1;
  1200. } else {
  1201. assert(FALSE);
  1202. }
  1203. return;
  1204. }
  1205. ULONGLONG
  1206. DwarfpExpressionPop (
  1207. PDWARF_LOCATION_CONTEXT LocationContext
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. This routine pops a value off of the DWARF expression stack.
  1212. Arguments:
  1213. LocationContext - Supplies a pointer to the execution context.
  1214. Return Value:
  1215. Returns the popped value, or 0 if there were not values on the stack.
  1216. --*/
  1217. {
  1218. ULONG StackSize;
  1219. ULONGLONG Value;
  1220. StackSize = LocationContext->StackSize;
  1221. if (StackSize == 0) {
  1222. assert(FALSE);
  1223. return 0;
  1224. }
  1225. Value = LocationContext->Stack[StackSize - 1];
  1226. LocationContext->StackSize -= 1;
  1227. return Value;
  1228. }
  1229. INT
  1230. DwarfpGetFrameBase (
  1231. PDWARF_CONTEXT Context,
  1232. PFUNCTION_SYMBOL Function,
  1233. ULONGLONG Pc,
  1234. PULONGLONG FrameBaseValue
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. This routine returns the current frame base register value. This usually
  1239. resolves to something like "esp+x".
  1240. Arguments:
  1241. Context - Supplies a pointer to the DWARF context.
  1242. Function - Supplies an optional pointer to the current function containing
  1243. the location to evaluate.
  1244. Pc - Supplies the current value of the instruction pointer.
  1245. FrameBaseValue - Supplies a pointer where the frame base register value
  1246. will be returned on success.
  1247. Return Value:
  1248. 0 on success.
  1249. Returns an error number on failure.
  1250. --*/
  1251. {
  1252. PDWARF_FUNCTION_SYMBOL DwarfFunction;
  1253. DWARF_LOCATION_CONTEXT LocationContext;
  1254. INT Status;
  1255. //
  1256. // Just return a zero frame register if there's no current function or no
  1257. // frame base attribute within that function.
  1258. //
  1259. if (Function == NULL) {
  1260. *FrameBaseValue = 0;
  1261. return 0;
  1262. }
  1263. DwarfFunction = Function->SymbolContext;
  1264. if ((DwarfFunction == NULL) ||
  1265. (DwarfFunction->FrameBase.Name != DwarfAtFrameBase)) {
  1266. *FrameBaseValue = 0;
  1267. return 0;
  1268. }
  1269. //
  1270. // Evaluate the frame base location.
  1271. //
  1272. memset(&LocationContext, 0, sizeof(DWARF_LOCATION_CONTEXT));
  1273. LocationContext.Unit = DwarfFunction->Unit;
  1274. LocationContext.Pc = Pc;
  1275. Status = DwarfpGetLocation(Context,
  1276. &LocationContext,
  1277. &(DwarfFunction->FrameBase));
  1278. if (Status == 0) {
  1279. if ((LocationContext.Location.Form != DwarfLocationMemory) ||
  1280. (LocationContext.Location.NextPiece != NULL)) {
  1281. assert(FALSE);
  1282. return EINVAL;
  1283. }
  1284. *FrameBaseValue = LocationContext.Location.Value.Address;
  1285. }
  1286. DwarfpDestroyLocationContext(Context, &LocationContext);
  1287. return Status;
  1288. }