status_t DwarfExpressionEvaluator::EvaluateLocation(const void* expression, size_t size, ValueLocation& _location) { _location.Clear(); // the empty expression is a valid one if (size == 0) { ValuePieceLocation piece; piece.SetToUnknown(); piece.SetSize(0); return _location.AddPiece(piece) ? B_OK : B_NO_MEMORY; } fDataReader.SetTo(expression, size, fContext->AddressSize()); // parse the first (and maybe only) expression try { // push the object address, if any target_addr_t objectAddress; if (fContext->GetObjectAddress(objectAddress)) _Push(objectAddress); ValuePieceLocation piece; status_t error = _Evaluate(&piece); if (error != B_OK) return error; // if that's all, it's only a simple expression without composition if (fDataReader.BytesRemaining() == 0) { if (!piece.IsValid()) piece.SetToMemory(_Pop()); piece.SetSize(0); return _location.AddPiece(piece) ? B_OK : B_NO_MEMORY; } // there's more, so it must be a composition operator uint8 opcode = fDataReader.Read<uint8>(0); if (opcode == DW_OP_piece) { piece.SetSize(fDataReader.ReadUnsignedLEB128(0)); } else if (opcode == DW_OP_bit_piece) { uint64 bitSize = fDataReader.ReadUnsignedLEB128(0); piece.SetSize(bitSize, fDataReader.ReadUnsignedLEB128(0)); } else return B_BAD_DATA; // If there's a composition operator, there must be at least two // simple expressions, so this must not be the end. if (fDataReader.BytesRemaining() == 0) return B_BAD_DATA; } catch (const EvaluationException& exception) { WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message); return B_BAD_VALUE; } catch (const std::bad_alloc& exception) { return B_NO_MEMORY; } // parse subsequent expressions (at least one) while (fDataReader.BytesRemaining() > 0) { // Restrict the data reader to the remaining bytes to prevent jumping // back. fDataReader.SetTo(fDataReader.Data(), fDataReader.BytesRemaining(), fDataReader.AddressSize()); try { // push the object address, if any target_addr_t objectAddress; if (fContext->GetObjectAddress(objectAddress)) _Push(objectAddress); ValuePieceLocation piece; status_t error = _Evaluate(&piece); if (error != B_OK) return error; if (!piece.IsValid()) piece.SetToMemory(_Pop()); // each expression must be followed by a composition operator if (fDataReader.BytesRemaining() == 0) return B_BAD_DATA; uint8 opcode = fDataReader.Read<uint8>(0); if (opcode == DW_OP_piece) { piece.SetSize(fDataReader.ReadUnsignedLEB128(0)); } else if (opcode == DW_OP_bit_piece) { uint64 bitSize = fDataReader.ReadUnsignedLEB128(0); piece.SetSize(bitSize, fDataReader.ReadUnsignedLEB128(0)); } else return B_BAD_DATA; } catch (const EvaluationException& exception) { WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message); return B_BAD_VALUE; } catch (const std::bad_alloc& exception) { return B_NO_MEMORY; } } return B_OK; }
status_t DwarfType::ResolveLocation(DwarfTypeContext* typeContext, const LocationDescription* description, target_addr_t objectAddress, bool hasObjectAddress, ValueLocation& _location) { status_t error = typeContext->File()->ResolveLocation( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), description, typeContext->TargetInterface(), typeContext->InstructionPointer(), objectAddress, hasObjectAddress, typeContext->FramePointer(), typeContext->RelocationDelta(), _location); if (error != B_OK) return error; // translate the DWARF register indices and the bit offset/size semantics const Register* registers = typeContext->GetArchitecture()->Registers(); bool bigEndian = typeContext->GetArchitecture()->IsBigEndian(); int32 count = _location.CountPieces(); for (int32 i = 0; i < count; i++) { ValuePieceLocation piece = _location.PieceAt(i); if (piece.type == VALUE_PIECE_LOCATION_REGISTER) { int32 reg = typeContext->FromDwarfRegisterMap()->MapRegisterIndex( piece.reg); if (reg >= 0) { piece.reg = reg; // The bit offset for registers is to the least // significant bit, while we want the offset to the most // significant bit. if (registers[reg].BitSize() > piece.bitSize) { piece.bitOffset = registers[reg].BitSize() - piece.bitSize - piece.bitOffset; } } else piece.SetToUnknown(); } else if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { // Whether the bit offset is to the least or most significant bit // is target architecture and source language specific. // TODO: Check whether this is correct! // TODO: Source language! if (!bigEndian && piece.size * 8 > piece.bitSize) { piece.bitOffset = piece.size * 8 - piece.bitSize - piece.bitOffset; } } piece.Normalize(bigEndian); _location.SetPieceAt(i, piece); } // If we only have one piece and that doesn't have a size, try to retrieve // the size of the type. if (count == 1) { ValuePieceLocation piece = _location.PieceAt(0); if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) { piece.SetSize(ByteSize()); // TODO: Use bit size and bit offset, if specified! _location.SetPieceAt(0, piece); TRACE_LOCALS(" set single piece size to %" B_PRIu64 "\n", ByteSize()); } } return B_OK; }