Example #1
0
bool
ValueLocation::SetToByteOffset(const ValueLocation& other, uint64 byteOffset,
	uint64 byteSize)
{
	Clear();

	fBigEndian = other.fBigEndian;
	ValuePieceLocation piece = other.PieceAt(0);
	piece.SetToMemory(piece.address + byteOffset);
	piece.SetSize(byteSize);

	return AddPiece(piece);
}
Example #2
0
status_t
BListValueNode::BListItemCountNodeChild::ResolveLocation(
	ValueLoader* valueLoader, ValueLocation*& _location)
{
	ValueLocation* location = new(std::nothrow) ValueLocation();
	if (location == NULL)
		return B_NO_MEMORY;

	ValuePieceLocation piece;
	piece.SetToMemory(fLocation.ToUInt64());
	piece.SetSize(sizeof(int32));
	location->AddPiece(piece);

	_location = location;
	return B_OK;
}
Example #3
0
status_t
DwarfType::ResolveObjectDataLocation(target_addr_t objectAddress,
	ValueLocation*& _location)
{
	ValuePieceLocation piece;
	piece.SetToMemory(objectAddress);
	piece.SetSize(0);
		// We set the piece size to 0 as an indicator that the size has to be
		// set.
		// TODO: We could set the byte size from type, but that may not be
		// accurate. We may want to add bit offset and size to Type.

	ValueLocation location(fTypeContext->GetArchitecture()->IsBigEndian());
	if (!location.AddPiece(piece))
		return B_NO_MEMORY;

	return ResolveObjectDataLocation(location, _location);
}
Example #4
0
status_t
DwarfType::ResolveObjectDataLocation(const ValueLocation& objectLocation,
	ValueLocation*& _location)
{
	// TODO: In some source languages the object address might be a pointer
	// to a descriptor, not the actual object data.

	// If the given location looks good already, just clone it.
	int32 count = objectLocation.CountPieces();
	if (count == 0)
		return B_BAD_VALUE;

	ValuePieceLocation piece = objectLocation.PieceAt(0);
	if (count > 1 || piece.type != VALUE_PIECE_LOCATION_MEMORY
		|| piece.size != 0 || piece.bitSize != 0) {
		ValueLocation* location
			= new(std::nothrow) ValueLocation(objectLocation);
		if (location == NULL || location->CountPieces() != count) {
			delete location;
			return B_NO_MEMORY;
		}

		_location = location;
		return B_OK;
	}

	// The location contains just a single address piece with a zero size
	// -- set the type's size.
	piece.SetSize(ByteSize());
		// TODO: Use bit size and bit offset, if specified!

	ValueLocation* location = new(std::nothrow) ValueLocation(
		objectLocation.IsBigEndian());
	if (location == NULL || !location->AddPiece(piece)) {
		delete location;
		return B_NO_MEMORY;
	}

	_location = location;
	return B_OK;
}
Example #5
0
status_t
BListValueNode::BListElementNodeChild::ResolveLocation(
	ValueLoader* valueLoader, ValueLocation*& _location)
{
	uint8 addressSize = valueLoader->GetArchitecture()->AddressSize();
	ValueLocation* location = new(std::nothrow) ValueLocation();
	if (location == NULL)
		return B_NO_MEMORY;


	uint64 listAddress = fParent->fDataLocation.ToUInt64();
	listAddress += fElementIndex * addressSize;

	ValuePieceLocation piece;
	piece.SetToMemory(listAddress);
	piece.SetSize(addressSize);
	location->AddPiece(piece);

	_location = location;
	return B_OK;
}
Example #6
0
status_t
ArchitectureX8664::GetReturnAddressLocation(StackFrame* frame,
	target_size_t valueSize, ValueLocation*& _location)
{
	// for the calling conventions currently in use on Haiku,
	// the x86-64 rules for how values are returned are as follows:
	//
	// - 64 bit or smaller values are returned in RAX.
	// - > 64 bit values are returned on the stack.
	ValueLocation* location = new(std::nothrow) ValueLocation(
		IsBigEndian());
	if (location == NULL)
		return B_NO_MEMORY;
	BReference<ValueLocation> locationReference(location,
		true);

	if (valueSize <= 8) {
		ValuePieceLocation piece;
		piece.SetSize(valueSize);
		piece.SetToRegister(X86_64_REGISTER_RAX);
		if (!location->AddPiece(piece))
			return B_NO_MEMORY;
	} else {
		ValuePieceLocation piece;
		CpuStateX8664* state = dynamic_cast<CpuStateX8664*>(frame->GetCpuState());
		piece.SetToMemory(state->IntRegisterValue(X86_64_REGISTER_RAX));
		piece.SetSize(valueSize);
		if (!location->AddPiece(piece))
			return B_NO_MEMORY;
	}

	_location = locationReference.Detach();
	return B_OK;
}
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;
}
Example #8
0
status_t
DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType,
	const MemberLocation* memberLocation,
	const ValueLocation& parentLocation, bool isBitField,
	ValueLocation*& _location)
{
	// create the value location object for the member
	ValueLocation* location = new(std::nothrow) ValueLocation(
		parentLocation.IsBigEndian());
	if (location == NULL)
		return B_NO_MEMORY;
	BReference<ValueLocation> locationReference(location, true);

	switch (memberLocation->attributeClass) {
		case ATTRIBUTE_CLASS_CONSTANT:
		{
			if (isBitField) {
				if (!location->SetTo(parentLocation,
					memberLocation->constant * 8,
					memberType->ByteSize() * 8)) {
					return B_NO_MEMORY;
				}
			} else {
				if (!location->SetToByteOffset(parentLocation,
					memberLocation->constant,
					memberType->ByteSize())) {
					return B_NO_MEMORY;
				}
			}

			break;
		}
		case ATTRIBUTE_CLASS_BLOCK:
		case ATTRIBUTE_CLASS_LOCLISTPTR:
		{
			// The attribute is a location description. Since we need to push
			// the parent object value onto the stack, we require the parent
			// location to be a memory location.
			if (parentLocation.CountPieces() != 1)
				return B_BAD_VALUE;
			ValuePieceLocation piece = parentLocation.PieceAt(0);
			if (piece.type != VALUE_PIECE_LOCATION_MEMORY)
				return B_BAD_VALUE;

			// convert member location to location description
			LocationDescription locationDescription;
			if (memberLocation->attributeClass == ATTRIBUTE_CLASS_BLOCK) {
				locationDescription.SetToExpression(
					memberLocation->expression.data,
					memberLocation->expression.length);
			} else {
				locationDescription.SetToLocationList(
					memberLocation->listOffset);
			}

			// evaluate the location description
			status_t error = memberType->ResolveLocation(TypeContext(),
				&locationDescription, piece.address, true, *location);
			if (error != B_OK)
				return error;

			break;
		}
		default:
		{
			// for unions the member location can be omitted -- all members
			// start at the beginning of the parent object
			if (fEntry->Tag() != DW_TAG_union_type)
				return B_BAD_VALUE;

			// since all members start at the same location, set up
			// the location by hand since we don't want the size difference
			// between the overall union and the member being
			// factored into the assigned address.
			ValuePieceLocation piece = parentLocation.PieceAt(0);
			piece.SetSize(memberType->ByteSize());
			if (!location->AddPiece(piece))
				return B_NO_MEMORY;

			break;
		}
	}

	_location = locationReference.Detach();
	return B_OK;
}
Example #9
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;
}
Example #10
0
status_t
DwarfArrayType::ResolveElementLocation(const ArrayIndexPath& indexPath,
	const ValueLocation& parentLocation, ValueLocation*& _location)
{
	if (indexPath.CountIndices() != CountDimensions())
		return B_BAD_VALUE;
	DwarfTypeContext* typeContext = TypeContext();

	// If the array entry has a bit stride, get it. Otherwise fall back to the
	// element type size.
	int64 bitStride;
	DIEArrayType* bitStrideOwnerEntry = NULL;
	if (fEntry != NULL && (bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate(
			fEntry, HasBitStridePredicate<DIEArrayType>()))) {
		BVariant value;
		status_t error = typeContext->File()->EvaluateDynamicValue(
			typeContext->GetCompilationUnit(), typeContext->AddressSize(),
			typeContext->SubprogramEntry(), bitStrideOwnerEntry->BitStride(),
			typeContext->TargetInterface(), typeContext->InstructionPointer(),
			typeContext->FramePointer(), value);
		if (error != B_OK)
			return error;
		if (!value.IsInteger())
			return B_BAD_VALUE;
		bitStride = value.ToInt64();
	} else
		bitStride = BaseType()->ByteSize() * 8;

	// Iterate backward through the dimensions and compute the total offset of
	// the element.
	int64 elementOffset = 0;
	DwarfArrayDimension* previousDimension = NULL;
	int64 previousDimensionStride = 0;
	for (int32 dimensionIndex = CountDimensions() - 1;
			dimensionIndex >= 0; dimensionIndex--) {
		DwarfArrayDimension* dimension = DwarfDimensionAt(dimensionIndex);
		int64 index = indexPath.IndexAt(dimensionIndex);

		// If the dimension has a special bit/byte stride, get it.
		int64 dimensionStride = 0;
		DwarfType* dimensionType = dimension->GetDwarfType();
		DIEArrayIndexType* dimensionTypeEntry = dimensionType != NULL
			? dynamic_cast<DIEArrayIndexType*>(dimensionType->GetDIEType())
			: NULL;
		if (dimensionTypeEntry != NULL) {
			DIEArrayIndexType* bitStrideOwnerEntry
				= DwarfUtils::GetDIEByPredicate(dimensionTypeEntry,
					HasBitStridePredicate<DIEArrayIndexType>());
			if (bitStrideOwnerEntry != NULL) {
				BVariant value;
				status_t error = typeContext->File()->EvaluateDynamicValue(
					typeContext->GetCompilationUnit(),
					typeContext->AddressSize(),
					typeContext->SubprogramEntry(),
					bitStrideOwnerEntry->BitStride(),
					typeContext->TargetInterface(),
					typeContext->InstructionPointer(),
					typeContext->FramePointer(), value);
				if (error != B_OK)
					return error;
				if (!value.IsInteger())
					return B_BAD_VALUE;
				dimensionStride = value.ToInt64();
			} else {
				DIEArrayIndexType* byteStrideOwnerEntry
					= DwarfUtils::GetDIEByPredicate(dimensionTypeEntry,
						HasByteStridePredicate<DIEArrayIndexType>());
				if (byteStrideOwnerEntry != NULL) {
					BVariant value;
					status_t error = typeContext->File()->EvaluateDynamicValue(
						typeContext->GetCompilationUnit(),
						typeContext->AddressSize(),
						typeContext->SubprogramEntry(),
						byteStrideOwnerEntry->ByteStride(),
						typeContext->TargetInterface(),
						typeContext->InstructionPointer(),
						typeContext->FramePointer(), value);
					if (error != B_OK)
						return error;
					if (!value.IsInteger())
						return B_BAD_VALUE;
					dimensionStride = value.ToInt64() * 8;
				}
			}
		}

		// If we don't have a stride for the dimension yet, use the stride of
		// the previous dimension multiplied by the size of the dimension.
		if (dimensionStride == 0) {
			if (previousDimension != NULL) {
				dimensionStride = previousDimensionStride
					* previousDimension->CountElements();
			} else {
				// the last dimension -- use the element bit stride
				dimensionStride = bitStride;
			}
		}

		// If the dimension stride is still 0 (that can happen, if the dimension
		// doesn't have a stride and the previous dimension's element count is
		// not known), we can only resolve the first element.
		if (dimensionStride == 0 && index != 0) {
			WARNING("No dimension bit stride for dimension %" B_PRId32 " and "
				"element index is not 0.\n", dimensionIndex);
			return B_BAD_VALUE;
		}

		elementOffset += dimensionStride * index;

		previousDimension = dimension;
		previousDimensionStride = dimensionStride;
	}

	TRACE_LOCALS("total element bit offset: %" B_PRId64 "\n", elementOffset);

	// create the value location object for the element
	ValueLocation* location = new(std::nothrow) ValueLocation(
		parentLocation.IsBigEndian());
	if (location == NULL)
		return B_NO_MEMORY;
	BReference<ValueLocation> locationReference(location, true);

	// If we have a single memory piece location for the array, we compute the
	// element's location by hand -- not uncommonly the array size isn't known.
	if (parentLocation.CountPieces() == 1) {
		ValuePieceLocation piece = parentLocation.PieceAt(0);
		if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
			int64 byteOffset = elementOffset >= 0
				? elementOffset / 8 : (elementOffset - 7) / 8;
			piece.SetToMemory(piece.address + byteOffset);
			piece.SetSize(BaseType()->ByteSize());
			// TODO: Support bit offsets correctly!
			// TODO: Support bit fields (primitive types) correctly!

			if (!location->AddPiece(piece))
				return B_NO_MEMORY;

			_location = locationReference.Detach();
			return B_OK;
		}
	}

	// We can't deal with negative element offsets at this point. It doesn't
	// make a lot of sense anyway, if the array location consists of multiple
	// pieces or lives in a register.
	if (elementOffset < 0) {
		WARNING("Negative element offset unsupported for multiple location "
			"pieces or register pieces.\n");
		return B_UNSUPPORTED;
	}

	if (!location->SetTo(parentLocation, elementOffset,
			BaseType()->ByteSize() * 8)) {
		return B_NO_MEMORY;
	}

	_location = locationReference.Detach();
	return B_OK;
}
Example #11
0
bool
ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
	uint64 bitSize)
{
	Clear();

	fBigEndian = other.fBigEndian;

	// compute the total bit size
	int32 count = other.CountPieces();
	uint64 totalBitSize = 0;
	for (int32 i = 0; i < count; i++) {
		const ValuePieceLocation &piece = other.PieceAt(i);
		totalBitSize += piece.bitSize;
	}

	// adjust requested bit offset/size to something reasonable, if necessary
	if (bitOffset + bitSize > totalBitSize) {
		if (bitOffset >= totalBitSize)
			return true;
		bitSize = totalBitSize - bitOffset;
	}

	if (fBigEndian) {
		// Big endian: Skip the superfluous most significant bits, copy the
		// pieces we need (cutting the first and the last one as needed) and
		// ignore the remaining pieces.

		// skip pieces for the most significant bits we don't need anymore
		uint64 bitsToSkip = bitOffset;
		int32 i;
		ValuePieceLocation piece;
		for (i = 0; i < count; i++) {
			const ValuePieceLocation& tempPiece = other.PieceAt(i);
			if (tempPiece.bitSize > bitsToSkip) {
				if (!piece.Copy(tempPiece))
					return false;
				break;
			}
			bitsToSkip -= tempPiece.bitSize;
		}

		// handle partial piece
		if (bitsToSkip > 0) {
			piece.bitOffset += bitsToSkip;
			piece.bitSize -= bitsToSkip;
			piece.Normalize(fBigEndian);
		}

		// handle remaining pieces
		while (bitSize > 0) {
			if (piece.bitSize > bitSize) {
				// the piece is bigger than the remaining size -- cut it
				piece.bitSize = bitSize;
				piece.Normalize(fBigEndian);
				bitSize = 0;
			} else
				bitSize -= piece.bitSize;

			if (!AddPiece(piece))
				return false;

			if (++i >= count)
				break;

			if (!piece.Copy(other.PieceAt(i)))
				return false;
		}
	} else {
		// Little endian: Skip the superfluous least significant bits, copy the
		// pieces we need (cutting the first and the last one as needed) and
		// ignore the remaining pieces.

		// skip pieces for the least significant bits we don't need anymore
		uint64 bitsToSkip = totalBitSize - bitOffset - bitSize;
		int32 i;
		ValuePieceLocation piece;
		for (i = 0; i < count; i++) {
			const ValuePieceLocation& tempPiece = other.PieceAt(i);
			if (tempPiece.bitSize > bitsToSkip) {
				if (!piece.Copy(tempPiece))
					return false;
				break;
			}
			bitsToSkip -= piece.bitSize;
		}

		// handle partial piece
		if (bitsToSkip > 0) {
			piece.bitSize -= bitsToSkip;
			piece.Normalize(fBigEndian);
		}

		// handle remaining pieces
		while (bitSize > 0) {
			if (piece.bitSize > bitSize) {
				// the piece is bigger than the remaining size -- cut it
				piece.bitOffset += piece.bitSize - bitSize;
				piece.bitSize = bitSize;
				piece.Normalize(fBigEndian);
				bitSize = 0;
			} else
				bitSize -= piece.bitSize;

			if (!AddPiece(piece))
				return false;

			if (++i >= count)
				break;

			if (!piece.Copy(other.PieceAt(i)))
				return false;
		}
	}

	return true;
}