123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701 |
- /*++
- Copyright (c) 2015 Minoca Corp. All Rights Reserved
- Module Name:
- dwexpr.c
- Abstract:
- This module implements support for DWARF expressions and location lists.
- Author:
- Evan Green 7-Dec-2015
- Environment:
- Debug
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/lib/types.h>
- #include <minoca/lib/status.h>
- #include <minoca/lib/im.h>
- #include "dwarfp.h"
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- INT
- DwarfpEvaluateExpression (
- PDWARF_CONTEXT Context,
- PDWARF_LOCATION_CONTEXT LocationContext,
- PUCHAR Expression,
- UINTN Size
- );
- PSTR
- DwarfpGetOpName (
- DWARF_OP Op,
- PSTR Buffer,
- UINTN Size
- );
- VOID
- DwarfpExpressionPush (
- PDWARF_LOCATION_CONTEXT LocationContext,
- ULONGLONG Value
- );
- ULONGLONG
- DwarfpExpressionPop (
- PDWARF_LOCATION_CONTEXT LocationContext
- );
- INT
- DwarfpGetFrameBase (
- PDWARF_CONTEXT Context,
- PFUNCTION_SYMBOL Function,
- ULONGLONG Pc,
- PULONGLONG FrameBaseValue
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- PSTR DwarfOpNames[] = {
- "DwarfOpNull",
- NULL,
- NULL,
- "DwarfOpAddress",
- NULL,
- NULL,
- "DwarfOpDereference",
- NULL,
- "DwarfOpConst1U",
- "DwarfOpConst1S",
- "DwarfOpConst2U",
- "DwarfOpConst2S",
- "DwarfOpConst4U",
- "DwarfOpConst4S",
- "DwarfOpConst8U",
- "DwarfOpConst8S",
- "DwarfOpConstU",
- "DwarfOpConstS",
- "DwarfOpDup",
- "DwarfOpDrop",
- "DwarfOpOver",
- "DwarfOpPick",
- "DwarfOpSwap",
- "DwarfOpRot",
- "DwarfOpXDeref",
- "DwarfOpAbs",
- "DwarfOpAnd",
- "DwarfOpDiv",
- "DwarfOpMinus",
- "DwarfOpMod",
- "DwarfOpMul",
- "DwarfOpNeg",
- "DwarfOpNot",
- "DwarfOpOr",
- "DwarfOpPlus",
- "DwarfOpPlusUConst",
- "DwarfOpShl",
- "DwarfOpShr",
- "DwarfOpShra",
- "DwarfOpXor",
- "DwarfOpBra",
- "DwarfOpEq",
- "DwarfOpGe",
- "DwarfOpGt",
- "DwarfOpLe",
- "DwarfOpLt",
- "DwarfOpNe",
- "DwarfOpSkip",
- "DwarfOpLit0"
- };
- PSTR DwarfOp90Names[] = {
- "DwarfOpRegX",
- "DwarfOpFbreg",
- "DwarfOpBregX",
- "DwarfOpPiece",
- "DwarfOpDerefSize",
- "DwarfOpXDerefSize",
- "DwarfOpNop",
- "DwarfOpPushObjectAddress",
- "DwarfOpCall2",
- "DwarfOpCall4",
- "DwarfOpCallRef",
- "DwarfOpFormTlsAddress",
- "DwarfOpCallFrameCfa",
- "DwarfOpBitPiece",
- "DwarfOpImplicitValue",
- "DwarfOpStackValue",
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- INT
- DwarfpGetLocation (
- PDWARF_CONTEXT Context,
- PDWARF_LOCATION_CONTEXT LocationContext,
- PDWARF_ATTRIBUTE_VALUE AttributeValue
- )
- /*++
- Routine Description:
- This routine evaluates a DWARF location or location list. The caller is
- responsible for calling the destroy location context routine after this
- routine runs.
- Arguments:
- Context - Supplies a pointer to the context.
- LocationContext - Supplies a pointer to the location context, which is
- assumed to have been zeroed and properly filled in.
- AttributeValue - Supplies a pointer to the attribute value that contains
- the location expression.
- Return Value:
- 0 on success, and the final location will be returned in the location
- context.
- ENOENT if the attribute is a location list and none of the current PC is
- not in any of the locations.
- Returns an error number on failure.
- --*/
- {
- ULONGLONG Constant;
- PUCHAR Expression;
- UINTN ExpressionSize;
- INT Status;
- PDWARF_COMPILATION_UNIT Unit;
- Unit = LocationContext->Unit;
- assert(Unit != NULL);
- LocationContext->AddressSize = Unit->AddressSize;
- //
- // An expression location is the primary form to be dealt with.
- //
- if ((DWARF_SECTION_OFFSET_FORM(AttributeValue->Form, Unit)) ||
- (AttributeValue->Form == DwarfFormExprLoc) ||
- (DWARF_BLOCK_FORM(AttributeValue->Form))) {
- //
- // If it's a location list, find the expression that currently matches.
- //
- if (DWARF_SECTION_OFFSET_FORM(AttributeValue->Form, Unit)) {
- Status = DwarfpSearchLocationList(Context,
- Unit,
- AttributeValue->Value.Offset,
- LocationContext->Pc,
- &Expression,
- &ExpressionSize);
- if (Status != 0) {
- return Status;
- }
- //
- // Otherwise, use the expression built into the block.
- //
- } else {
- Expression = AttributeValue->Value.Block.Data;
- ExpressionSize = AttributeValue->Value.Block.Size;
- }
- LocationContext->Constant = TRUE;
- Status = DwarfpEvaluateExpression(Context,
- LocationContext,
- Expression,
- ExpressionSize);
- //
- // Try to just get a constant out of it.
- //
- } else {
- Status = 0;
- switch (AttributeValue->Form) {
- case DwarfFormData1:
- case DwarfFormData2:
- case DwarfFormData4:
- case DwarfFormData8:
- case DwarfFormSData:
- case DwarfFormUData:
- Constant = AttributeValue->Value.UnsignedConstant;
- break;
- case DwarfFormFlag:
- case DwarfFormFlagPresent:
- Constant = AttributeValue->Value.Flag;
- break;
- default:
- Status = ENOENT;
- break;
- }
- if (Status == 0) {
- LocationContext->Location.Form = DwarfLocationKnownValue;
- LocationContext->Location.Value.Value = Constant;
- }
- }
- return Status;
- }
- VOID
- DwarfpDestroyLocationContext (
- PDWARF_CONTEXT Context,
- PDWARF_LOCATION_CONTEXT LocationContext
- )
- /*++
- Routine Description:
- This routine destroys a DWARF location context.
- Arguments:
- Context - Supplies a pointer to the context.
- LocationContext - Supplies a pointer to the location context to clean up.
- Return Value:
- None.
- --*/
- {
- PDWARF_LOCATION Next;
- PDWARF_LOCATION Piece;
- Piece = LocationContext->Location.NextPiece;
- LocationContext->Location.NextPiece = NULL;
- while (Piece != NULL) {
- Next = Piece->NextPiece;
- free(Piece);
- Piece = Next;
- }
- return;
- }
- INT
- DwarfpEvaluateSimpleExpression (
- PDWARF_CONTEXT Context,
- UCHAR AddressSize,
- PDWARF_COMPILATION_UNIT Unit,
- ULONGLONG InitialPush,
- PUCHAR Expression,
- UINTN Size,
- PDWARF_LOCATION Location
- )
- /*++
- Routine Description:
- This routine evaluates a simple DWARF expression. A simple expression is
- one that is not possibly a location list, and will ultimately contain only
- a single piece.
- Arguments:
- Context - Supplies a pointer to the DWARF context.
- AddressSize - Supplies the size of an address on the target.
- Unit - Supplies an optional pointer to the compilation unit.
- InitialPush - Supplies a value to push onto the stack initially. Supply
- -1ULL to not push anything onto the stack initially.
- Expression - Supplies a pointer to the expression bytes to evaluate.
- Size - Supplies the size of the expression in bytes.
- Location - Supplies a pointer where the location information will be
- returned on success.
- Return Value:
- 0 on success.
- Returns an error code on failure.
- --*/
- {
- DWARF_LOCATION_CONTEXT LocationContext;
- INT Status;
- memset(&LocationContext, 0, sizeof(DWARF_LOCATION_CONTEXT));
- LocationContext.Unit = Unit;
- LocationContext.AddressSize = AddressSize;
- if (Unit != NULL) {
- LocationContext.AddressSize = Unit->AddressSize;
- }
- if (InitialPush != -1ULL) {
- LocationContext.Stack[0] = InitialPush;
- LocationContext.StackSize = 1;
- }
- Status = DwarfpEvaluateExpression(Context,
- &LocationContext,
- Expression,
- Size);
- if (Status == 0) {
- memcpy(Location, &(LocationContext.Location), sizeof(DWARF_LOCATION));
- if (Location->NextPiece != NULL) {
- DWARF_ERROR("DWARF: Simple expression had multiple pieces!\n");
- Location->NextPiece = NULL;
- }
- }
- DwarfpDestroyLocationContext(Context, &LocationContext);
- return Status;
- }
- VOID
- DwarfpPrintExpression (
- PDWARF_CONTEXT Context,
- UCHAR AddressSize,
- PDWARF_COMPILATION_UNIT Unit,
- PUCHAR Expression,
- UINTN Size
- )
- /*++
- Routine Description:
- This routine prints out a DWARF expression.
- Arguments:
- Context - Supplies a pointer to the context.
- AddressSize - Supplies the size of an address on the target.
- Unit - Supplies an optional pointer to the compilation unit.
- Expression - Supplies a pointer to the expression bytes.
- ExpressionEnd - Supplies the first byte beyond the expression bytes.
- Size - Supplies the size of the expression in bytes.
- Return Value:
- None.
- --*/
- {
- PUCHAR Bytes;
- PUCHAR End;
- DWARF_OP Op;
- CHAR OpBuffer[30];
- ULONGLONG Operand1;
- BOOL Operand1Signed;
- ULONGLONG Operand2;
- BOOL Operand2Signed;
- ULONG OperandCount;
- PSTR OpName;
- Bytes = Expression;
- End = Expression + Size;
- while (Bytes < End) {
- Op = DwarfpRead1(&Bytes);
- OpName = DwarfpGetOpName(Op, OpBuffer, sizeof(OpBuffer));
- DWARF_PRINT("%s ", OpName);
- OperandCount = 1;
- Operand1Signed = FALSE;
- Operand2Signed = FALSE;
- if ((Op >= DwarfOpBreg0) && (Op <= DwarfOpBreg31)) {
- Operand1 = DwarfpReadSleb128(&Bytes);
- Operand1Signed = TRUE;
- } else {
- switch (Op) {
- case DwarfOpAddress:
- if (AddressSize == 4) {
- Operand1 = DwarfpRead4(&Bytes);
- } else {
- assert(AddressSize == 8);
- Operand1 = DwarfpRead8(&Bytes);
- }
- break;
- case DwarfOpConst1U:
- case DwarfOpPick:
- case DwarfOpDerefSize:
- case DwarfOpXDerefSize:
- Operand1 = DwarfpRead1(&Bytes);
- break;
- case DwarfOpConst1S:
- Operand1 = (signed char)(DwarfpRead1(&Bytes));
- Operand1Signed = TRUE;
- break;
- case DwarfOpConst2U:
- case DwarfOpCall2:
- Operand1 = DwarfpRead2(&Bytes);
- break;
- case DwarfOpConst2S:
- case DwarfOpSkip:
- case DwarfOpBra:
- Operand1 = (SHORT)(DwarfpRead2(&Bytes));
- Operand1Signed = TRUE;
- break;
- case DwarfOpConst4U:
- case DwarfOpCall4:
- Operand1 = DwarfpRead4(&Bytes);
- break;
- case DwarfOpConst4S:
- Operand1 = (LONG)(DwarfpRead4(&Bytes));
- Operand1Signed = TRUE;
- break;
- case DwarfOpConst8U:
- Operand1 = DwarfpRead8(&Bytes);
- break;
- case DwarfOpConst8S:
- Operand1 = (LONGLONG)(DwarfpRead8(&Bytes));
- Operand1Signed = TRUE;
- break;
- case DwarfOpConstU:
- case DwarfOpPlusUConst:
- case DwarfOpRegX:
- case DwarfOpPiece:
- Operand1 = DwarfpReadLeb128(&Bytes);
- break;
- case DwarfOpConstS:
- case DwarfOpFbreg:
- Operand1 = DwarfpReadSleb128(&Bytes);
- Operand1Signed = TRUE;
- break;
- case DwarfOpBregX:
- Operand1 = DwarfpReadLeb128(&Bytes);
- Operand2 = DwarfpReadSleb128(&Bytes);
- Operand2Signed = TRUE;
- OperandCount = 2;
- break;
- case DwarfOpCallRef:
- Operand1 = 0;
- if (Unit != NULL) {
- Operand1 = DWARF_READN(&Bytes, Unit->Is64Bit);
- }
- break;
- case DwarfOpBitPiece:
- Operand1 = DwarfpReadLeb128(&Bytes);
- Operand2 = DwarfpReadLeb128(&Bytes);
- OperandCount = 2;
- break;
- case DwarfOpImplicitValue:
- Operand1 = DwarfpReadLeb128(&Bytes);
- Bytes += Operand1;
- break;
- case DwarfOpGnuEntryValue:
- Operand1 = DwarfpReadLeb128(&Bytes);
- break;
- case DwarfOpGnuImplicitPointer:
- if (AddressSize == 8) {
- Operand1 = DwarfpRead8(&Bytes);
- } else {
- Operand1 = DwarfpRead4(&Bytes);
- }
- Operand2 = DwarfpReadSleb128(&Bytes);
- Operand2Signed = TRUE;
- OperandCount = 2;
- break;
- case DwarfOpGnuConstType:
- Operand1 = DwarfpReadLeb128(&Bytes);
- Operand2 = DwarfpRead1(&Bytes);
- Bytes += Operand2;
- break;
- case DwarfOpGnuConvert:
- case DwarfOpGnuReinterpret:
- Operand1 = DwarfpReadLeb128(&Bytes);
- break;
- //
- // Parameter references point to a DIE that contains an
- // optimized-away parameter.
- //
- case DwarfOpGnuParameterRef:
- Operand1 = DwarfpRead4(&Bytes);
- break;
- default:
- OperandCount = 0;
- break;
- }
- }
- if (OperandCount != 0) {
- if (Operand1Signed != FALSE) {
- DWARF_PRINT("%I64d ", Operand1);
- } else {
- DWARF_PRINT("%I64u ", Operand1);
- }
- if (OperandCount == 2) {
- if (Operand2Signed != FALSE) {
- DWARF_PRINT("%I64d ", Operand2);
- } else {
- DWARF_PRINT("%I64u ", Operand2);
- }
- }
- }
- }
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- INT
- DwarfpEvaluateExpression (
- PDWARF_CONTEXT Context,
- PDWARF_LOCATION_CONTEXT LocationContext,
- PUCHAR Expression,
- UINTN Size
- )
- /*++
- Routine Description:
- This routine executes a DWARF expression.
- Arguments:
- Context - Supplies a pointer to the context.
- LocationContext - Supplies a pointer to the location context to clean up.
- Expression - Supplies a pointer to the expression bytes.
- Size - Supplies the size of the expression in bytes.
- Return Value:
- 0 on success.
- Returns a status code on failure.
- --*/
- {
- UCHAR AddressSize;
- PUCHAR End;
- STACK_FRAME Frame;
- ULONG Index;
- PDWARF_LOCATION Location;
- DWARF_OP Op;
- PDWARF_LOCATION PreviousLocation;
- ULONG SizeOperand;
- ULONG StackSize;
- INT Status;
- ULONGLONG Value;
- ULONGLONG Value2;
- ULONGLONG Value3;
- AddressSize = LocationContext->AddressSize;
- assert((AddressSize == 8) || (AddressSize == 4));
- End = Expression + Size;
- PreviousLocation = NULL;
- Location = &(LocationContext->Location);
- Status = 0;
- while (Expression < End) {
- Op = DwarfpRead1(&Expression);
- switch (Op) {
- //
- // Push the one operand, which is the size of a target address.
- //
- case DwarfOpAddress:
- if (AddressSize == 8) {
- Value = DwarfpRead8(&Expression);
- } else {
- Value = DwarfpRead4(&Expression);
- }
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Dereference pops an address, reads up to an address size's worth of
- // data from the target memory at that location, and pushes that back
- // on the stack. The X variants also pop an address space ID. The size
- // variants specify the size to read explicitly.
- //
- case DwarfOpXDerefSize:
- case DwarfOpXDeref:
- case DwarfOpDereference:
- case DwarfOpDerefSize:
- case DwarfOpGnuDerefType:
- Value = DwarfpExpressionPop(LocationContext);
- SizeOperand = AddressSize;
- if ((Op == DwarfOpXDerefSize) || (Op == DwarfOpDerefSize) ||
- (Op == DwarfOpGnuDerefType)) {
- SizeOperand = DwarfpRead1(&Expression);
- if (SizeOperand > AddressSize) {
- SizeOperand = AddressSize;
- }
- }
- //
- // Scan past the DIE offset of a type to interpret this as.
- //
- if (Op == DwarfOpGnuDerefType) {
- DwarfpReadLeb128(&Expression);
- }
- //
- // Pop the address space ID if this is an X operation.
- //
- Value2 = 0;
- if ((Op == DwarfOpXDerefSize) || (Op == DwarfOpXDeref)) {
- Value2 = DwarfpExpressionPop(LocationContext);
- }
- Value3 = 0;
- LocationContext->Constant = FALSE;
- Status = DwarfTargetRead(Context,
- Value,
- SizeOperand,
- Value2,
- &Value3);
- if (Status != 0) {
- DWARF_ERROR("DWARF: Target read failure from address "
- "0x%I64x (address space %d).\n",
- Value,
- (ULONG)Value2);
- goto EvaluateExpressionEnd;
- }
- DwarfpExpressionPush(LocationContext, Value3);
- break;
- case DwarfOpConst1U:
- Value = DwarfpRead1(&Expression);
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConst1S:
- Value = (LONGLONG)(signed char)(DwarfpRead1(&Expression));
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConst2U:
- Value = DwarfpRead2(&Expression);
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConst2S:
- Value = (LONGLONG)(SHORT)(DwarfpRead2(&Expression));
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConst4U:
- Value = DwarfpRead4(&Expression);
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConst4S:
- Value = (LONGLONG)(LONG)(DwarfpRead4(&Expression));
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConst8U:
- Value = DwarfpRead8(&Expression);
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConst8S:
- Value = (LONGLONG)(DwarfpRead8(&Expression));
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConstU:
- Value = DwarfpReadLeb128(&Expression);
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpConstS:
- Value = DwarfpReadSleb128(&Expression);
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Duplicate the value at the top of the stack.
- //
- case DwarfOpDup:
- Value = DwarfpExpressionPop(LocationContext);
- DwarfpExpressionPush(LocationContext, Value);
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Pop and ignore the value at the top of the stack.
- //
- case DwarfOpDrop:
- DwarfpExpressionPop(LocationContext);
- break;
- //
- // Over is equivalent to pick(1).
- //
- case DwarfOpOver:
- Index = 1;
- //
- // Fall through.
- //
- //
- // Copy and push the stack entry at the specified index.
- //
- case DwarfOpPick:
- if (Op == DwarfOpPick) {
- Index = DwarfpRead1(&Expression);
- } else {
- Index = 0;
- }
- StackSize = LocationContext->StackSize;
- if (Index < StackSize) {
- Value = LocationContext->Stack[StackSize - 1 - Index];
- DwarfpExpressionPush(LocationContext, Value);
- } else {
- assert(FALSE);
- }
- break;
- //
- // Swap the top two entries of the stack.
- //
- case DwarfOpSwap:
- Value = DwarfpExpressionPop(LocationContext);
- Value2 = DwarfpExpressionPop(LocationContext);
- DwarfpExpressionPush(LocationContext, Value);
- DwarfpExpressionPush(LocationContext, Value2);
- break;
- //
- // Rotate the first three stack entries.
- //
- case DwarfOpRot:
- Value = DwarfpExpressionPop(LocationContext);
- Value2 = DwarfpExpressionPop(LocationContext);
- Value3 = DwarfpExpressionPop(LocationContext);
- DwarfpExpressionPush(LocationContext, Value);
- DwarfpExpressionPush(LocationContext, Value3);
- DwarfpExpressionPush(LocationContext, Value2);
- break;
- //
- // Handle unary arithmetic operators.
- //
- case DwarfOpAbs:
- case DwarfOpNot:
- case DwarfOpNeg:
- Value = DwarfpExpressionPop(LocationContext);
- switch (Op) {
- case DwarfOpAbs:
- if ((LONGLONG)Value < 0) {
- Value = -Value;
- }
- break;
- case DwarfOpNot:
- Value = ~Value;
- break;
- case DwarfOpNeg:
- Value = -(LONGLONG)Value;
- break;
- default:
- assert(FALSE);
- Value = 0;
- break;
- }
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Handle arithmetic operators, that pop two values, compute something,
- // and then push the value back. The second value on the stack is
- // the "thing to operate on", and the first value is the operand.
- //
- case DwarfOpAnd:
- case DwarfOpDiv:
- case DwarfOpMinus:
- case DwarfOpMod:
- case DwarfOpMul:
- case DwarfOpOr:
- case DwarfOpPlus:
- case DwarfOpShl:
- case DwarfOpShr:
- case DwarfOpShra:
- case DwarfOpXor:
- case DwarfOpEq:
- case DwarfOpGe:
- case DwarfOpGt:
- case DwarfOpLe:
- case DwarfOpLt:
- case DwarfOpNe:
- Value = DwarfpExpressionPop(LocationContext);
- Value2 = DwarfpExpressionPop(LocationContext);
- switch (Op) {
- case DwarfOpAnd:
- Value3 = Value & Value2;
- break;
- case DwarfOpDiv:
- Value3 = 0;
- if (Value != 0) {
- Value3 = (LONGLONG)Value2 / (LONGLONG)Value;
- }
- break;
- case DwarfOpMinus:
- Value3 = Value2 - Value;
- break;
- case DwarfOpMod:
- Value3 = 0;
- if (Value3 != 0) {
- Value3 = (LONGLONG)Value2 % (LONGLONG)Value;
- }
- break;
- case DwarfOpMul:
- Value3 = Value * Value2;
- break;
- case DwarfOpOr:
- Value3 = Value | Value2;
- break;
- case DwarfOpPlus:
- Value3 = Value + Value2;
- break;
- case DwarfOpShl:
- Value3 = Value2 << Value;
- break;
- case DwarfOpShr:
- Value3 = Value2 >> Value;
- break;
- case DwarfOpShra:
- Value3 = ((LONGLONG)Value2) >> Value;
- break;
- case DwarfOpXor:
- Value3 = Value ^ Value2;
- break;
- case DwarfOpEq:
- Value3 = Value == Value2;
- break;
- case DwarfOpGe:
- Value3 = Value2 >= Value;
- break;
- case DwarfOpGt:
- Value3 = Value2 > Value;
- break;
- case DwarfOpLe:
- Value3 = Value2 <= Value;
- break;
- case DwarfOpLt:
- Value3 = Value2 < Value;
- break;
- case DwarfOpNe:
- Value3 = Value2 != Value;
- break;
- default:
- assert(FALSE);
- Value3 = 0;
- break;
- }
- DwarfpExpressionPush(LocationContext, Value3);
- break;
- //
- // Pop the top value, add it to the LEB128 operand, and push the
- // result.
- //
- case DwarfOpPlusUConst:
- Value = DwarfpExpressionPop(LocationContext);
- Value2 = DwarfpReadLeb128(&Expression);
- Value += Value2;
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Conditional branch. If the top value of the stack is non-zero,
- // branch to the 2-byte signed operand away.
- // TODO: Is the branch (and skip) from the next instruction or this one?
- //
- case DwarfOpBra:
- Value = DwarfpExpressionPop(LocationContext);
- Value2 = (SHORT)DwarfpRead2(&Expression);
- if (Value != 0) {
- Expression += Value2;
- }
- break;
- case DwarfOpSkip:
- Value2 = (SHORT)DwarfpRead2(&Expression);
- Expression += Value2;
- break;
- case DwarfOpCall2:
- case DwarfOpCall4:
- case DwarfOpCallRef:
- if ((Op == DwarfOpCall2) || (Op == DwarfOpCall4)) {
- if (Op == DwarfOpCall2) {
- Value = DwarfpRead2(&Expression);
- } else {
- Value = DwarfpRead4(&Expression);
- }
- } else {
- if (LocationContext->Unit == NULL) {
- Status = EINVAL;
- goto EvaluateExpressionEnd;
- }
- if (LocationContext->Unit->Is64Bit != FALSE) {
- Value = DwarfpRead8(&Expression);
- } else {
- Value = DwarfpRead4(&Expression);
- }
- }
- //
- // Calls are not currently implemented. Call2 and Call4 are not
- // so bad as they involve finding the DIE in question (a little
- // trouble, but not too bad), then getting and executing the
- // attribute. The trouble with the ref call is that it points to a
- // DIE in some other module, but with no way to find the
- // abbreviation tables or compilation unit for that DIE. No one
- // seems to implement or use it, so for now just ignore all this.
- //
- assert(FALSE);
- break;
- case DwarfOpFbreg:
- LocationContext->Constant = FALSE;
- Status = DwarfpGetFrameBase(Context,
- LocationContext->CurrentFunction,
- LocationContext->Pc,
- &Value);
- if (Status != 0) {
- DWARF_ERROR("DWARF: Failed to get frame base.\n");
- goto EvaluateExpressionEnd;
- }
- Value2 = DwarfpReadSleb128(&Expression);
- Value += Value2;
- DwarfpExpressionPush(LocationContext, Value);
- break;
- case DwarfOpCallFrameCfa:
- LocationContext->Constant = FALSE;
- Status = DwarfpStackUnwind(Context,
- LocationContext->Pc,
- TRUE,
- &Frame);
- if (Status != 0) {
- DWARF_ERROR("DWARF: Failed to get CFA.\n");
- goto EvaluateExpressionEnd;
- }
- Value = Frame.FramePointer;
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Piece defines that a portion of the location resides here. Bit piece
- // takes the size and offset in bits.
- //
- case DwarfOpPiece:
- case DwarfOpBitPiece:
- if (Op == DwarfOpPiece) {
- Value = DwarfpReadLeb128(&Expression) * BITS_PER_BYTE;
- Value2 = 0;
- } else {
- Value = DwarfpReadLeb128(&Expression);
- Value2 = DwarfpReadLeb128(&Expression);
- }
- //
- // If the location is not yet formed, grab its value off the stack.
- //
- if (Location->Form == DwarfLocationInvalid) {
- StackSize = LocationContext->StackSize;
- if (StackSize != 0) {
- Location->Form = DwarfLocationMemory;
- Location->Value.Address =
- LocationContext->Stack[StackSize - 1];
- } else {
- Location->Form = DwarfLocationUndefined;
- }
- }
- Location->BitSize = Value;
- Location->BitOffset = Value2;
- if (PreviousLocation != NULL) {
- PreviousLocation->NextPiece = Location;
- }
- PreviousLocation = Location;
- //
- // Create a new location piece if there is more stuff.
- //
- Location = NULL;
- if (Expression < End) {
- Location = malloc(sizeof(DWARF_LOCATION));
- if (Location == NULL) {
- Status = ENOMEM;
- goto EvaluateExpressionEnd;
- }
- memset(Location, 0, sizeof(DWARF_LOCATION));
- }
- //
- // Clear the stack. It's not obvious from the spec whether or not
- // this is the right thing to do, so change this if things aren't
- // working.
- //
- LocationContext->StackSize = 0;
- break;
- case DwarfOpNop:
- break;
- case DwarfOpPushObjectAddress:
- Value = LocationContext->ObjectAddress;
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Pop the value, add it to the current thread and module's TLS base,
- // and push it back.
- //
- case DwarfOpFormTlsAddress:
- case DwarfOpGnuPushTlsAddress:
- LocationContext->Constant = FALSE;
- Value = DwarfpExpressionPop(LocationContext);
- Value += LocationContext->TlsBase;
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Implicit value specifies that there is no location, but the value
- // is known.
- //
- case DwarfOpImplicitValue:
- Value = DwarfpReadLeb128(&Expression);
- Location->Form = DwarfLocationKnownData;
- Location->Value.Buffer.Data = Expression;
- Location->Value.Buffer.Size = Value;
- Expression += Value;
- break;
- //
- // Stack value specifies that there is no location, but the value
- // itself is at the top of the stack. This also terminates the
- // expression.
- //
- case DwarfOpStackValue:
- Value = DwarfpExpressionPop(LocationContext);
- Location->Form = DwarfLocationKnownValue;
- Location->Value.Value = Value;
- Status = 0;
- Expression = End;
- break;
- //
- // The variable is uninitialized.
- //
- case DwarfOpGnuUninit:
- break;
- //
- // The entry value contains a LEB128 length, followed by a block of
- // DWARF expression. The expression is either a DWARF register op,
- // or a generic expression. The expression should be evaluated as if
- // the machine was at the beginning of the current function. That is,
- // "unwind this function and then run the inner expression". For now
- // just push 0 and skip the whole thing.
- //
- case DwarfOpGnuEntryValue:
- Value = DwarfpReadLeb128(&Expression);
- Expression += Value;
- DwarfpExpressionPush(LocationContext, 0);
- break;
- //
- // The implicit pointer informs the user that while the location of
- // an object is unavailable, the actual value of that object can be
- // known. It has two operands, an address-sized offset to a DIE
- // describing the value of the variable (in it's location attribute),
- // and a SLEB128 byte offset into that value. Currently this is just
- // returned as undefined.
- //
- case DwarfOpGnuImplicitPointer:
- if (AddressSize == 8) {
- Value = DwarfpRead8(&Expression);
- } else {
- Value = DwarfpRead4(&Expression);
- }
- DwarfpReadSleb128(&Expression);
- Location->Form = DwarfLocationUndefined;
- break;
- case DwarfOpGnuAddrIndex:
- case DwarfOpGnuConstIndex:
- //
- // Consider implementing (or at least ignoring) these extensions.
- //
- assert(FALSE);
- break;
- //
- // Constant data, preceded by a type DIE offset.
- //
- case DwarfOpGnuConstType:
- DwarfpReadLeb128(&Expression);
- Size = DwarfpRead1(&Expression);
- Value = 0;
- if (Size <= sizeof(ULONGLONG)) {
- memcpy(&Value, Expression, Size);
- }
- DwarfpExpressionPush(LocationContext, Value);
- Expression += Size;
- break;
- //
- // Convert and reinterpret pop a value off the stack, cast it to
- // the given type (specified by a DIE offset to a type), and push the
- // value back. Just ignore this for now.
- //
- case DwarfOpGnuConvert:
- case DwarfOpGnuReinterpret:
- DwarfpReadLeb128(&Expression);
- break;
- //
- // Parameter references point to a DIE that contains an optimized-away
- // parameter.
- //
- case DwarfOpGnuParameterRef:
- DwarfpRead4(&Expression);
- DwarfpExpressionPush(LocationContext, 0);
- break;
- //
- // Handle unknown or ranges of values.
- //
- default:
- //
- // Handle the literal encodings.
- //
- if ((Op >= DwarfOpLit0) && (Op <= DwarfOpLit31)) {
- Value = Op - DwarfOpLit0;
- DwarfpExpressionPush(LocationContext, Value);
- break;
- //
- // Return register locations themselves.
- //
- } else if (((Op >= DwarfOpReg0) && (Op <= DwarfOpReg31)) ||
- (Op == DwarfOpRegX)) {
- if (Op == DwarfOpRegX) {
- Value = DwarfpReadLeb128(&Expression);
- } else {
- Value = Op - DwarfOpReg0;
- }
- Location->Form = DwarfLocationRegister;
- Location->Value.Register = Value;
- break;
- //
- // Handle the register encodings.
- //
- } else if (((Op >= DwarfOpBreg0) && (Op <= DwarfOpBreg31)) ||
- (Op == DwarfOpBregX) || (Op == DwarfOpGnuRegvalType)) {
- LocationContext->Constant = FALSE;
- Value2 = 0;
- if (Op == DwarfOpBregX) {
- Value = DwarfpReadLeb128(&Expression);
- Value2 = DwarfpReadSleb128(&Expression);
- //
- // This regval type extension reads a register and interprets
- // it as a given type (specified by a DIE offset).
- //
- } else if (Op == DwarfOpGnuRegvalType) {
- Value = DwarfpReadLeb128(&Expression);
- DwarfpReadLeb128(&Expression);
- Value2 = 0;
- } else {
- Value = Op - DwarfOpBreg0;
- Value2 = DwarfpReadSleb128(&Expression);
- }
- Status = DwarfTargetReadRegister(Context, Value, &Value);
- if (Status != 0) {
- DWARF_ERROR("DWARF: Failed to read register %I64d\n",
- Value);
- goto EvaluateExpressionEnd;
- }
- Value += Value2;
- DwarfpExpressionPush(LocationContext, Value);
- break;
- }
- DWARF_ERROR("DWARF: Unhandled expression op 0x%x", Op);
- assert(FALSE);
- Status = ENOSYS;
- goto EvaluateExpressionEnd;
- }
- }
- //
- // If this is the end and the current location has not yet been filled in,
- // assume it's a memory location at the top of the stack.
- //
- assert(Expression == End);
- if ((Location != NULL) && (Location->Form == DwarfLocationInvalid)) {
- StackSize = LocationContext->StackSize;
- if (StackSize != 0) {
- Location->Form = DwarfLocationMemory;
- Location->Value.Address = LocationContext->Stack[StackSize - 1];
- } else {
- Location->Form = DwarfLocationUndefined;
- }
- if (PreviousLocation != NULL) {
- PreviousLocation->NextPiece = Location;
- }
- Location = NULL;
- }
- EvaluateExpressionEnd:
- //
- // Free a leftover location.
- //
- if ((Location != NULL) && (Location != &(LocationContext->Location))) {
- assert((PreviousLocation != NULL) &&
- (PreviousLocation->NextPiece == NULL));
- free(Location);
- }
- return Status;
- }
- PSTR
- DwarfpGetOpName (
- DWARF_OP Op,
- PSTR Buffer,
- UINTN Size
- )
- /*++
- Routine Description:
- This routine returns the string describing a dwarf op.
- Arguments:
- Op - Supplies the op to decode.
- Buffer - Supplies a pointer to a buffer used for dynamically generated ops.
- Size - Supplies the size of the buffer in bytes.
- Return Value:
- Returns a pointer to a string containing the name of the op. This may
- either be a pointer to a static memory location, or a pointer to the
- buffer passed in.
- --*/
- {
- if (Op <= DwarfOpLit0) {
- return DwarfOpNames[Op];
- } else if (Op <= DwarfOpLit31) {
- snprintf(Buffer, Size, "DwarfOpLit%d", Op - DwarfOpLit0);
- return Buffer;
- } else if (Op <= DwarfOpReg31) {
- snprintf(Buffer, Size, "DwarfReg%d", Op - DwarfOpReg0);
- return Buffer;
- } else if (Op <= DwarfOpBreg31) {
- snprintf(Buffer, Size, "DwarfBreg%d", Op - DwarfOpBreg0);
- return Buffer;
- } else if (Op <= DwarfOpStackValue) {
- assert(Op >= 0x90);
- return DwarfOp90Names[Op - 0x90];
- }
- return "DwarfOpUNKNOWN";
- }
- VOID
- DwarfpExpressionPush (
- PDWARF_LOCATION_CONTEXT LocationContext,
- ULONGLONG Value
- )
- /*++
- Routine Description:
- This routine pushes a value onto the DWARF expression stack.
- Arguments:
- LocationContext - Supplies a pointer to the execution context.
- Value - Supplies the value to push.
- Return Value:
- None.
- --*/
- {
- ULONG StackSize;
- StackSize = LocationContext->StackSize;
- if (StackSize < DWARF_EXPRESSION_STACK_SIZE) {
- LocationContext->Stack[StackSize] = Value;
- LocationContext->StackSize += 1;
- } else {
- assert(FALSE);
- }
- return;
- }
- ULONGLONG
- DwarfpExpressionPop (
- PDWARF_LOCATION_CONTEXT LocationContext
- )
- /*++
- Routine Description:
- This routine pops a value off of the DWARF expression stack.
- Arguments:
- LocationContext - Supplies a pointer to the execution context.
- Return Value:
- Returns the popped value, or 0 if there were not values on the stack.
- --*/
- {
- ULONG StackSize;
- ULONGLONG Value;
- StackSize = LocationContext->StackSize;
- if (StackSize == 0) {
- assert(FALSE);
- return 0;
- }
- Value = LocationContext->Stack[StackSize - 1];
- LocationContext->StackSize -= 1;
- return Value;
- }
- INT
- DwarfpGetFrameBase (
- PDWARF_CONTEXT Context,
- PFUNCTION_SYMBOL Function,
- ULONGLONG Pc,
- PULONGLONG FrameBaseValue
- )
- /*++
- Routine Description:
- This routine returns the current frame base register value. This usually
- resolves to something like "esp+x".
- Arguments:
- Context - Supplies a pointer to the DWARF context.
- Function - Supplies an optional pointer to the current function containing
- the location to evaluate.
- Pc - Supplies the current value of the instruction pointer.
- FrameBaseValue - Supplies a pointer where the frame base register value
- will be returned on success.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PDWARF_FUNCTION_SYMBOL DwarfFunction;
- DWARF_LOCATION_CONTEXT LocationContext;
- INT Status;
- //
- // Just return a zero frame register if there's no current function or no
- // frame base attribute within that function.
- //
- if (Function == NULL) {
- *FrameBaseValue = 0;
- return 0;
- }
- DwarfFunction = Function->SymbolContext;
- if ((DwarfFunction == NULL) ||
- (DwarfFunction->FrameBase.Name != DwarfAtFrameBase)) {
- *FrameBaseValue = 0;
- return 0;
- }
- //
- // Evaluate the frame base location.
- //
- memset(&LocationContext, 0, sizeof(DWARF_LOCATION_CONTEXT));
- LocationContext.Unit = DwarfFunction->Unit;
- LocationContext.Pc = Pc;
- Status = DwarfpGetLocation(Context,
- &LocationContext,
- &(DwarfFunction->FrameBase));
- if (Status == 0) {
- if ((LocationContext.Location.Form != DwarfLocationMemory) ||
- (LocationContext.Location.NextPiece != NULL)) {
- assert(FALSE);
- return EINVAL;
- }
- *FrameBaseValue = LocationContext.Location.Value.Address;
- }
- DwarfpDestroyLocationContext(Context, &LocationContext);
- return Status;
- }
|