示例#1
0
status_t
AbstractArrayValueNode::CreateChildrenInRange(int32 lowIndex,
	int32 highIndex)
{
	// TODO: ensure that we don't already have children in the specified
	// index range. These need to be skipped if so.
	TRACE_LOCALS("TYPE_ARRAY\n");

	int32 dimensionCount = fType->CountDimensions();
	bool isFinalDimension = fDimension + 1 == dimensionCount;
	status_t error = B_OK;

	if (!fBoundsInitialized) {
		int32 lowerBound, upperBound;
		error = SupportedChildRange(lowerBound, upperBound);
		if (error != B_OK)
			return error;

		fLowerBound = lowerBound;
		fUpperBound = upperBound;
		fBoundsInitialized = true;
	}

	if (lowIndex < fLowerBound)
		lowIndex = fLowerBound;
	if (highIndex > fUpperBound)
		highIndex = fUpperBound;

	// create children for the array elements
	for (int32 i = lowIndex; i <= highIndex; i++) {
		BString name(Name());
		name << '[' << i << ']';
		if (name.Length() <= Name().Length())
			return B_NO_MEMORY;

		AbstractArrayValueNodeChild* child;
		if (isFinalDimension) {
			child = new(std::nothrow) ArrayValueNodeChild(this, name, i,
				fType->BaseType());
		} else {
			child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i,
				fType);
		}

		if (child == NULL || !fChildren.AddItem(child)) {
			delete child;
			return B_NO_MEMORY;
		}

		child->SetContainer(fContainer);
	}

	if (fContainer != NULL)
		fContainer->NotifyValueNodeChildrenCreated(this);

	return B_OK;
}
status_t
AbstractArrayValueNode::CreateChildren()
{
	if (!fChildren.IsEmpty())
		return B_OK;

	TRACE_LOCALS("TYPE_ARRAY\n");

	int32 dimensionCount = fType->CountDimensions();
	bool isFinalDimension = fDimension + 1 == dimensionCount;

	ArrayDimension* dimension = fType->DimensionAt(fDimension);
	uint64 elementCount = dimension->CountElements();
	if (elementCount == 0 || elementCount > kMaxArrayElementCount)
		elementCount = kMaxArrayElementCount;

	// create children for the array elements
	for (int32 i = 0; i < (int32)elementCount; i++) {
		BString name(Name());
		name << '[' << i << ']';
		if (name.Length() <= Name().Length())
			return B_NO_MEMORY;

		AbstractArrayValueNodeChild* child;
		if (isFinalDimension) {
			child = new(std::nothrow) ArrayValueNodeChild(this, name, i,
				fType->BaseType());
		} else {
			child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i,
				fType);
		}

		if (child == NULL || !fChildren.AddItem(child)) {
			delete child;
			return B_NO_MEMORY;
		}

		child->SetContainer(fContainer);
	}

	if (fContainer != NULL)
		fContainer->NotifyValueNodeChildrenCreated(this);

	return B_OK;
}
status_t
ArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
	ValueLocation*& _location)
{
	// get the parent (== array) location
	ValueLocation* parentLocation = fParent->Location();
	if (parentLocation == NULL)
		return B_BAD_VALUE;

	// create an array index path
	ArrayType* arrayType = fParent->GetArrayType();
	int32 dimensionCount = arrayType->CountDimensions();

	// add dummy indices first -- we'll replace them on our way back through
	// our ancestors
	ArrayIndexPath indexPath;
	for (int32 i = 0; i < dimensionCount; i++) {
		if (!indexPath.AddIndex(0))
			return B_NO_MEMORY;
	}

	AbstractArrayValueNodeChild* child = this;
	for (int32 i = dimensionCount - 1; i >= 0; i--) {
		indexPath.SetIndexAt(i, child->ElementIndex());

		child = dynamic_cast<AbstractArrayValueNodeChild*>(
			child->ArrayParent()->NodeChild());
	}

	// resolve the element location
	ValueLocation* location;
	status_t error = arrayType->ResolveElementLocation(indexPath,
		*parentLocation, location);
	if (error != B_OK) {
		TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): "
			"ResolveElementLocation() failed: %s\n", strerror(error));
		return error;
	}

	_location = location;
	return B_OK;
}
示例#4
0
status_t
DwarfCompoundType::ResolveDataMemberLocation(DataMember* _member,
	const ValueLocation& parentLocation, ValueLocation*& _location)
{
	DwarfDataMember* member = dynamic_cast<DwarfDataMember*>(_member);
	if (member == NULL)
		return B_BAD_VALUE;
	DwarfTypeContext* typeContext = TypeContext();

	bool isBitField = true;
	DIEMember* memberEntry = member->Entry();
	// TODO: handle DW_AT_data_bit_offset
	if (!memberEntry->ByteSize()->IsValid()
		&& !memberEntry->BitOffset()->IsValid()
		&& !memberEntry->BitSize()->IsValid()) {
		isBitField = false;
	}

	ValueLocation* location;
	status_t error = _ResolveDataMemberLocation(member->GetDwarfType(),
		member->Entry()->Location(), parentLocation, isBitField, location);
	if (error != B_OK)
		return error;

	// If the member isn't a bit field, we're done.
	if (!isBitField) {
		_location = location;
		return B_OK;
	}

	BReference<ValueLocation> locationReference(location);

	// get the byte size
	target_addr_t byteSize;
	if (memberEntry->ByteSize()->IsValid()) {
		BVariant value;
		error = typeContext->File()->EvaluateDynamicValue(
			typeContext->GetCompilationUnit(), typeContext->AddressSize(),
			typeContext->SubprogramEntry(), memberEntry->ByteSize(),
			typeContext->TargetInterface(), typeContext->InstructionPointer(),
			typeContext->FramePointer(), value);
		if (error != B_OK)
			return error;
		byteSize = value.ToUInt64();
	} else
		byteSize = ByteSize();

	// get the bit offset
	uint64 bitOffset = 0;
	if (memberEntry->BitOffset()->IsValid()) {
		BVariant value;
		error = typeContext->File()->EvaluateDynamicValue(
			typeContext->GetCompilationUnit(), typeContext->AddressSize(),
			typeContext->SubprogramEntry(), memberEntry->BitOffset(),
			typeContext->TargetInterface(), typeContext->InstructionPointer(),
			typeContext->FramePointer(), value);
		if (error != B_OK)
			return error;
		bitOffset = value.ToUInt64();
	}

	// get the bit size
	uint64 bitSize = byteSize * 8;
	if (memberEntry->BitSize()->IsValid()) {
		BVariant value;
		error = typeContext->File()->EvaluateDynamicValue(
			typeContext->GetCompilationUnit(), typeContext->AddressSize(),
			typeContext->SubprogramEntry(), memberEntry->BitSize(),
			typeContext->TargetInterface(), typeContext->InstructionPointer(),
			typeContext->FramePointer(), value);
		if (error != B_OK)
			return error;
		bitSize = value.ToUInt64();
	}

	TRACE_LOCALS("bit field: byte size: %" B_PRIu64 ", bit offset/size: %"
		B_PRIu64 "/%" B_PRIu64 "\n", byteSize, bitOffset, bitSize);

	if (bitOffset + bitSize > byteSize * 8)
		return B_BAD_VALUE;

	// create the bit field value location
	ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation;
	if (bitFieldLocation == NULL)
		return B_NO_MEMORY;
	BReference<ValueLocation> bitFieldLocationReference(bitFieldLocation, true);

	if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize))
		return B_NO_MEMORY;

	_location = bitFieldLocationReference.Detach();
	return B_OK;
}
示例#5
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;
}
示例#6
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;
}
示例#7
0
status_t
ResolveValueNodeValueJob::_ResolveNodeValue()
{
    // get the node child and parent node
    AutoLocker<ValueNodeContainer> containerLocker(fContainer);
    ValueNodeChild* nodeChild = fValueNode->NodeChild();
    BReference<ValueNodeChild> nodeChildReference(nodeChild);

    ValueNode* parentNode = nodeChild->Parent();
    BReference<ValueNode> parentNodeReference(parentNode);

    // Check whether the node child location has been resolved already
    // (successfully).
    status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
    bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED;
    if (nodeChildDone && nodeChildResolutionState != B_OK)
        return nodeChildResolutionState;

    // If the child node location has not been resolved yet, check whether the
    // parent node location and value have been resolved already (successfully).
    bool parentDone = true;
    if (!nodeChildDone && parentNode != NULL) {
        status_t parentResolutionState
            = parentNode->LocationAndValueResolutionState();
        parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED;
        if (parentDone && parentResolutionState != B_OK)
            return parentResolutionState;
    }

    containerLocker.Unlock();

    // resolve the parent node location and value, if necessary
    if (!parentDone) {
        status_t error = _ResolveParentNodeValue(parentNode);
        if (error != B_OK) {
            TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
                         "node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
                         fValueNode, fValueNode->Name().String(), parentNode);
            return error;
        }
    }

    // resolve the node child location, if necessary
    if (!nodeChildDone) {
        status_t error = _ResolveNodeChildLocation(nodeChild);
        if (error != B_OK) {
            TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
                         "node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
                         fValueNode, fValueNode->Name().String(), nodeChild);
            return error;
        }
    }

    // resolve the node location and value
    ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
                            fTypeInformation, fCpuState);
    ValueLocation* location;
    Value* value;
    status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader,
                     location, value);
    if (error != B_OK) {
        TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
                     "node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
                     "failed\n", fValueNode, fValueNode->Name().String());
        return error;
    }
    BReference<ValueLocation> locationReference(location, true);
    BReference<Value> valueReference(value, true);

    // set location and value on the node
    containerLocker.Lock();
    status_t nodeResolutionState
        = fValueNode->LocationAndValueResolutionState();
    if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
        return nodeResolutionState;
    fValueNode->SetLocationAndValue(location, value, B_OK);
    containerLocker.Unlock();

    return B_OK;
}
示例#8
0
status_t
ValueLoader::LoadValue(ValueLocation* location, type_code valueType,
                       bool shortValueIsFine, BVariant& _value)
{
    static const size_t kMaxPieceSize = 16;
    uint64 totalBitSize = 0;
    int32 count = location->CountPieces();
    for (int32 i = 0; i < count; i++) {
        ValuePieceLocation piece = location->PieceAt(i);
        switch (piece.type) {
        case VALUE_PIECE_LOCATION_INVALID:
        case VALUE_PIECE_LOCATION_UNKNOWN:
            return B_ENTRY_NOT_FOUND;
        case VALUE_PIECE_LOCATION_MEMORY:
        case VALUE_PIECE_LOCATION_REGISTER:
            break;
        }

        if (piece.size > kMaxPieceSize) {
            TRACE_LOCALS("  -> overly long piece size (%" B_PRIu64 " bytes)\n",
                         piece.size);
            return B_UNSUPPORTED;
        }

        totalBitSize += piece.bitSize;
    }

    TRACE_LOCALS("  -> totalBitSize: %" B_PRIu64 "\n", totalBitSize);

    if (totalBitSize == 0) {
        TRACE_LOCALS("  -> no size\n");
        return B_ENTRY_NOT_FOUND;
    }

    if (totalBitSize > 64) {
        TRACE_LOCALS("  -> longer than 64 bits: unsupported\n");
        return B_UNSUPPORTED;
    }

    uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8;
    if (!shortValueIsFine && totalBitSize < valueBitSize) {
        TRACE_LOCALS("  -> too short for value type (%" B_PRIu64 " vs. %"
                     B_PRIu64 " bits)\n", totalBitSize, valueBitSize);
        return B_BAD_VALUE;
    }

    // Load the data. Since the BitBuffer class we're using only supports big
    // endian bit semantics, we convert all data to big endian before pushing
    // them to the buffer. For later conversion to BVariant we need to make sure
    // the final buffer has the size of the value type, so we pad the most
    // significant bits with zeros.
    BitBuffer valueBuffer;
    if (totalBitSize < valueBitSize)
        valueBuffer.AddZeroBits(valueBitSize - totalBitSize);

    bool bigEndian = fArchitecture->IsBigEndian();
    const Register* registers = fArchitecture->Registers();
    for (int32 i = 0; i < count; i++) {
        ValuePieceLocation piece = location->PieceAt(
                                       bigEndian ? i : count - i - 1);
        uint32 bytesToRead = piece.size;
        uint32 bitSize = piece.bitSize;
        uint8 bitOffset = piece.bitOffset;
        // TODO: the offset's ordinal position and direction aren't
        // specified by DWARF, and simply follow the target language.
        // To handle non C/C++ languages properly, the corresponding
        // SourceLanguage will need to be passed in and extended to
        // return the relevant information.

        switch (piece.type) {
        case VALUE_PIECE_LOCATION_INVALID:
        case VALUE_PIECE_LOCATION_UNKNOWN:
            return B_ENTRY_NOT_FOUND;
        case VALUE_PIECE_LOCATION_MEMORY:
        {
            target_addr_t address = piece.address;

            TRACE_LOCALS("  piece %" B_PRId32 ": memory address: %#"
                         B_PRIx64 ", bits: %" B_PRIu32 "\n", i, address, bitSize);

            uint8 pieceBuffer[kMaxPieceSize];
            ssize_t bytesRead = fTeamMemory->ReadMemory(address,
                                pieceBuffer, bytesToRead);
            if (bytesRead < 0)
                return bytesRead;
            if ((uint32)bytesRead != bytesToRead)
                return B_BAD_ADDRESS;

            TRACE_LOCALS_ONLY(
                TRACE_LOCALS("  -> read: ");
                for (ssize_t k = 0; k < bytesRead; k++)
                TRACE_LOCALS("%02x", pieceBuffer[k]);
                TRACE_LOCALS("\n");
            )

                // convert to big endian
                if (!bigEndian) {
                    for (int32 k = bytesRead / 2 - 1; k >= 0; k--) {
                        std::swap(pieceBuffer[k],
                                  pieceBuffer[bytesRead - k - 1]);
                    }
                }

            valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
            break;
        }
        case VALUE_PIECE_LOCATION_REGISTER:
        {
            TRACE_LOCALS("  piece %" B_PRId32 ": register: %" B_PRIu32
                         ", bits: %" B_PRIu32 "\n", i, piece.reg, bitSize);

            if (fCpuState == NULL) {
                WARNING("ValueLoader::LoadValue(): register piece, but no "
                        "CpuState\n");
                return B_UNSUPPORTED;
            }

            BVariant registerValue;
            if (!fCpuState->GetRegisterValue(registers + piece.reg,
                                             registerValue)) {
                return B_ENTRY_NOT_FOUND;
            }
            if (registerValue.Size() < bytesToRead)
                return B_ENTRY_NOT_FOUND;

            if (!bigEndian) {
                registerValue.SwapEndianess();
                bitOffset = registerValue.Size() * 8 - bitOffset - bitSize;
            }
            valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
            break;
        }
        }
    }
示例#9
0
status_t
BListValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
	ValueLocation*& _location, Value*& _value)
{
	// get the location
	ValueLocation* location = NodeChild()->Location();
	if (location == NULL)
		return B_BAD_VALUE;


	// get the value type
	type_code valueType;
	if (valueLoader->GetArchitecture()->AddressSize() == 4) {
		valueType = B_UINT32_TYPE;
		TRACE_LOCALS("    -> 32 bit\n");
	} else {
		valueType = B_UINT64_TYPE;
		TRACE_LOCALS("    -> 64 bit\n");
	}

	// load the value data

	status_t error = B_OK;
	_location = location;
	_value = NULL;

	ValueLocation* memberLocation = NULL;
	CompoundType* baseType = dynamic_cast<CompoundType*>(fType);

	if (baseType->CountTemplateParameters() != 0) {
		// for BObjectList we need to walk up
		// the hierarchy: BObjectList -> _PointerList_ -> BList
		if (baseType->CountBaseTypes() == 0)
			return B_BAD_DATA;

		baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0)
			->GetType());
		if (baseType == NULL || baseType->Name() != "_PointerList_")
			return B_BAD_DATA;

		if (baseType->CountBaseTypes() == 0)
			return B_BAD_DATA;

		baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0)
			->GetType());
		if (baseType == NULL || baseType->Name() != "BList")
			return B_BAD_DATA;

	}

	for (int32 i = 0; i < baseType->CountDataMembers(); i++) {
		DataMember* member = baseType->DataMemberAt(i);
		if (strcmp(member->Name(), "fObjectList") == 0) {
			error = baseType->ResolveDataMemberLocation(member,
				*location, memberLocation);
			BReference<ValueLocation> locationRef(memberLocation, true);
			if (error != B_OK) {
				TRACE_LOCALS(
					"BListValueNode::ResolvedLocationAndValue(): "
					"failed to resolve location of header member: %s\n",
					strerror(error));
				return error;
			}

			error = valueLoader->LoadValue(memberLocation, valueType,
				false, fDataLocation);
			if (error != B_OK)
				return error;
		} else if (strcmp(member->Name(), "fItemCount") == 0) {
			error = baseType->ResolveDataMemberLocation(member,
				*location, memberLocation);
			BReference<ValueLocation> locationRef(memberLocation, true);
			if (error != B_OK) {
				TRACE_LOCALS(
					"BListValueNode::ResolvedLocationAndValue(): "
					"failed to resolve location of header member: %s\n",
					strerror(error));
				return error;
			}

			fItemCountType = member->GetType();
			fItemCountType->AcquireReference();

			fItemCountLocation = memberLocation->PieceAt(0).address;

			BVariant listSize;
			error = valueLoader->LoadValue(memberLocation, valueType,
				false, listSize);
			if (error != B_OK)
				return error;

			fItemCount = listSize.ToInt32();
			TRACE_LOCALS(
				"BListValueNode::ResolvedLocationAndValue(): "
				"detected list size %" B_PRId32 "\n",
				fItemCount);
		}
		memberLocation = NULL;
	}

	return B_OK;
}