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;
}
Beispiel #2
0
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;
}