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; }
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); }
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; }
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); }
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; }
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 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; }