diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp index 609b376712..336dfee235 100644 --- a/src/apps/debugger/Jobs.cpp +++ b/src/apps/debugger/Jobs.cpp @@ -546,7 +546,8 @@ GetStackFrameValueJob::_GetValue() type = dynamic_cast(type)->BaseType(); break; case TYPE_ADDRESS: - TRACE_LOCALS(" TYPE_ADDRESS\n"); + case TYPE_POINTER_TO_MEMBER: + TRACE_LOCALS(" TYPE_ADDRESS/TYPE_POINTER_TO_MEMBER\n"); if (fArchitecture->AddressSize() == 4) { valueType = B_UINT32_TYPE; TRACE_LOCALS(" -> 32 bit\n"); @@ -595,9 +596,16 @@ GetStackFrameValueJob::_GetValue() shortValueIsFine = true; break; } - default: - TRACE_LOCALS(" default -> unsupported\n"); + case TYPE_SUBRANGE: + TRACE_LOCALS(" TYPE_SUBRANGE -> unsupported\n"); return B_UNSUPPORTED; + case TYPE_UNSPECIFIED: + // Can't get the value for an unspecified type! + return B_BAD_VALUE; + case TYPE_FUNCTION: + TRACE_LOCALS(" TYPE_FUNCTION\n"); + // Can't get the value for a function type! + return B_BAD_VALUE; } } @@ -833,9 +841,15 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type, switch (component.typeKind) { case TYPE_PRIMITIVE: case TYPE_ENUMERATION: + case TYPE_SUBRANGE: + case TYPE_UNSPECIFIED: + case TYPE_FUNCTION: + case TYPE_POINTER_TO_MEMBER: // cannot happen TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): " - "TYPE_PRIMITIVE/TYPE_ENUMERATION subcomponent!\n"); + "TYPE_PRIMITIVE/TYPE_ENUMERATION/TYPE_SUBRANGE/" + "TYPE_UNSPECIFIED/TYPE_FUNCTION/TYPE_POINTER_TO_MEMBER " + "subcomponent!\n"); return B_BAD_VALUE; case TYPE_COMPOUND: { @@ -921,8 +935,9 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type, fStackFrame, type, parentValue.ToUInt64(), location); if (error != B_OK) { TRACE_LOCALS("GetStackFrameValueJob::" - "_ResolveTypeAndLocation(): TYPE_ADDRESS: " - "ResolveObjectDataLocation() failed: %s\n", + "_ResolveTypeAndLocation(): " + "TYPE_ADDRESS/TYPE_POINTER_TO_MEMBER: " + "ResolveObjectDataLocation() failed: %s\n", strerror(error)); return error; } @@ -935,10 +950,44 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type, return B_OK; } case TYPE_ARRAY: - // TODO:... - default: - return B_UNSUPPORTED; + { + ArrayType* arrayType = dynamic_cast(parentType); + + if (component.componentKind != TYPE_COMPONENT_ARRAY_ELEMENT) + return B_UNSUPPORTED; + + // get the index path + ArrayIndexPath indexPath; + error = indexPath.SetTo(component.name.String()); + if (error != B_OK) + return error; + + if (indexPath.CountIndices() != arrayType->CountDimensions()) + return B_UNSUPPORTED; + + // resolve the element location + ValueLocation* location; + error = fStackFrame->DebugInfo()->ResolveArrayElementLocation( + fStackFrame, arrayType, indexPath, *parentLocation, location); + if (error != B_OK) { + TRACE_LOCALS("GetStackFrameValueJob::" + "_ResolveTypeAndLocation(): TYPE_ARRAY: " + "ResolveArrayElementLocation() failed: %s\n", + strerror(error)); + return error; + } + + arrayType->BaseType()->AcquireReference(); + _type = arrayType->BaseType(); + _location = location; + _valueResolved = false; + + return B_OK; + } } + + // Can never get here. + return B_UNSUPPORTED; } diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp index c81b361897..fe822d23e1 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp @@ -11,6 +11,7 @@ #include +#include "ArrayIndexPath.h" #include "Architecture.h" #include "CompilationUnit.h" #include "DebugInfoEntries.h" @@ -44,6 +45,18 @@ struct HasTypePredicate { }; +// #pragma mark - HasReturnTypePredicate + + +template +struct HasReturnTypePredicate { + inline bool operator()(EntryType* entry) const + { + return entry->ReturnType() != NULL; + } +}; + + // #pragma mark - HasEnumeratorsPredicate @@ -88,6 +101,18 @@ struct HasBaseTypesPredicate { }; +// #pragma mark - HasParametersPredicate + + +template +struct HasParametersPredicate { + inline bool operator()(EntryType* entry) const + { + return !entry->Parameters().IsEmpty(); + } +}; + + // #pragma mark - HasLowerBoundPredicate @@ -121,6 +146,41 @@ struct HasCountPredicate { }; +// #pragma mark - HasBitStridePredicate + + +template +struct HasBitStridePredicate { + inline bool operator()(EntryType* entry) const + { + return entry->BitStride()->IsValid(); + } +}; + + +// #pragma mark - HasByteStridePredicate + + +template +struct HasByteStridePredicate { + inline bool operator()(EntryType* entry) const + { + return entry->ByteStride()->IsValid(); + } +}; + + +// #pragma mark - HasContainingTypePredicate + + +struct HasContainingTypePredicate { + inline bool operator()(DIEPointerToMemberType* entry) const + { + return entry->ContainingType() != NULL; + } +}; + + } // unnamed namespace @@ -390,12 +450,60 @@ public: return fType; } + DwarfType* GetDwarfType() const + { + return fType; + } + private: DwarfType* fType; }; +// #pragma mark - DwarfFunctionParameter + + +struct DwarfStackFrameDebugInfo::DwarfFunctionParameter : FunctionParameter { +public: + DwarfFunctionParameter(DIEFormalParameter* entry, const BString& name, + DwarfType* type) + : + fEntry(entry), + fName(name), + fType(type) + { + fType->AcquireReference(); + } + + ~DwarfFunctionParameter() + { + fType->ReleaseReference(); + } + + virtual const char* Name() const + { + return fName.Length() > 0 ? fName.String() : NULL; + } + + virtual Type* GetType() const + { + return fType; + } + + DIEFormalParameter* Entry() const + { + return fEntry; + } + +private: + DIEFormalParameter* fEntry; + BString fName; + DwarfType* fType; + +}; + + // #pragma mark - DwarfPrimitiveType @@ -814,6 +922,11 @@ struct DwarfStackFrameDebugInfo::DwarfArrayType : ArrayType, DwarfType { return fDimensions.ItemAt(index); } + DwarfArrayDimension* DwarfDimensionAt(int32 index) const + { + return fDimensions.ItemAt(index); + } + virtual DIEType* GetDIEType() const { return fEntry; @@ -843,6 +956,177 @@ private: }; +// #pragma mark - DwarfUnspecifiedType + + +struct DwarfStackFrameDebugInfo::DwarfUnspecifiedType : UnspecifiedType, + DwarfType { +public: + // NOTE: The entry may be NULL. + DwarfUnspecifiedType(const BString& name, DIEUnspecifiedType* entry) + : + DwarfType(name), + fEntry(entry) + { + } + + ~DwarfUnspecifiedType() + { + } + + virtual DIEType* GetDIEType() const + { + return fEntry; + } + + DIEUnspecifiedType* Entry() const + { + return fEntry; + } + +private: + DIEUnspecifiedType* fEntry; +}; + + +// #pragma mark - DwarfFunctionType + + +struct DwarfStackFrameDebugInfo::DwarfFunctionType : FunctionType, DwarfType { + DwarfFunctionType(const BString& name, DIESubroutineType* entry, + DwarfType* returnType) + : + DwarfType(name), + fEntry(entry), + fReturnType(returnType), + fHasVariableArguments(false) + { + if (fReturnType != NULL) + fReturnType->AcquireReference(); + } + + ~DwarfFunctionType() + { + for (int32 i = 0; + DwarfFunctionParameter* parameter = fParameters.ItemAt(i); i++) { + parameter->ReleaseReference(); + } + + if (fReturnType != NULL) + fReturnType->ReleaseReference(); + } + + virtual Type* ReturnType() const + { + return fReturnType; + } + + virtual int32 CountParameters() const + { + return fParameters.CountItems(); + } + + virtual FunctionParameter* ParameterAt(int32 index) const + { + return fParameters.ItemAt(index); + } + + DwarfFunctionParameter* DwarfParameterAt(int32 index) const + { + return fParameters.ItemAt(index); + } + + virtual bool HasVariableArguments() const + { + return fHasVariableArguments; + } + + void SetHasVariableArguments(bool hasVarArgs) + { + fHasVariableArguments = hasVarArgs; + } + + virtual DIEType* GetDIEType() const + { + return fEntry; + } + + DIESubroutineType* Entry() const + { + return fEntry; + } + + bool AddParameter(DwarfFunctionParameter* parameter) + { + if (!fParameters.AddItem(parameter)) + return false; + + parameter->AcquireReference(); + return true; + } + +private: + typedef BObjectList ParameterList; + +private: + DIESubroutineType* fEntry; + DwarfType* fReturnType; + ParameterList fParameters; + bool fHasVariableArguments; +}; + + +// #pragma mark - DwarfPointerToMemberType + + +struct DwarfStackFrameDebugInfo::DwarfPointerToMemberType : PointerToMemberType, + DwarfType { +public: + DwarfPointerToMemberType(const BString& name, DIEPointerToMemberType* entry, + DwarfCompoundType* containingType, DwarfType* baseType) + : + DwarfType(name), + fEntry(entry), + fContainingType(containingType), + fBaseType(baseType) + { + fContainingType->AcquireReference(); + fBaseType->AcquireReference(); + } + + ~DwarfPointerToMemberType() + { + fContainingType->ReleaseReference(); + fBaseType->ReleaseReference(); + } + + virtual CompoundType* ContainingType() const + { + return fContainingType; + } + + virtual Type* BaseType() const + { + return fBaseType; + } + + virtual DIEType* GetDIEType() const + { + return fEntry; + } + + DIEPointerToMemberType* Entry() const + { + return fEntry; + } + +private: + DIEPointerToMemberType* fEntry; + DwarfCompoundType* fContainingType; + DwarfType* fBaseType; +}; + + // #pragma mark - DwarfTypeHashDefinition @@ -1063,6 +1347,158 @@ DwarfStackFrameDebugInfo::ResolveDataMemberLocation(StackFrame* stackFrame, } +status_t +DwarfStackFrameDebugInfo::ResolveArrayElementLocation(StackFrame* stackFrame, + ArrayType* _type, const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, ValueLocation*& _location) +{ + DwarfArrayType* type = dynamic_cast(_type); + if (type == NULL || indexPath.CountIndices() != type->CountDimensions()) + return B_BAD_VALUE; + DIEArrayType* typeEntry = type->Entry(); + + // If the array entry has a bit stride, get it. Otherwise fall back to the + // element type size. + int64 bitStride; + if (DIEArrayType* bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasBitStridePredicate())) { + BVariant value; + status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, + fSubprogramEntry, bitStrideOwnerEntry->BitStride(), + fTargetInterface, fInstructionPointer, fFramePointer, value); + if (error != B_OK) + return error; + if (!value.IsInteger()) + return B_BAD_VALUE; + bitStride = value.ToInt64(); + } else + bitStride = type->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 = type->CountDimensions() - 1; + dimensionIndex >= 0; dimensionIndex--) { + DwarfArrayDimension* dimension = type->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(dimensionType->GetDIEType()) + : NULL; + if (dimensionTypeEntry != NULL) { + DIEArrayIndexType* bitStrideOwnerEntry + = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, + HasBitStridePredicate()); + if (bitStrideOwnerEntry != NULL) { + BVariant value; + status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, + fSubprogramEntry, bitStrideOwnerEntry->BitStride(), + fTargetInterface, fInstructionPointer, fFramePointer, + value); + if (error != B_OK) + return error; + if (!value.IsInteger()) + return B_BAD_VALUE; + dimensionStride = value.ToInt64(); + } else { + DIEArrayIndexType* byteStrideOwnerEntry + = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, + HasByteStridePredicate()); + if (byteStrideOwnerEntry != NULL) { + BVariant value; + status_t error = fFile->EvaluateDynamicValue( + fCompilationUnit, fSubprogramEntry, + byteStrideOwnerEntry->ByteStride(), fTargetInterface, + fInstructionPointer, fFramePointer, 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 %ld 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: %lld\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; + Reference 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(type->BaseType()->ByteSize() * 8); + // 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, + type->BaseType()->ByteSize() * 8)) { + return B_NO_MEMORY; + } + + _location = locationReference.Detach(); + return B_OK; +} + + status_t DwarfStackFrameDebugInfo::CreateType(DIEType* typeEntry, Type*& _type) { @@ -1303,10 +1739,16 @@ DwarfStackFrameDebugInfo::_CreateTypeInternal(DIEType* typeEntry, dynamic_cast(typeEntry), _type); case DW_TAG_unspecified_type: + return _CreateUnspecifiedType(name, + dynamic_cast(typeEntry), _type); + case DW_TAG_subroutine_type: + return _CreateFunctionType(name, + dynamic_cast(typeEntry), _type); + case DW_TAG_ptr_to_member_type: - // TODO: Implement! - return B_UNSUPPORTED; + return _CreatePointerToMemberType(name, + dynamic_cast(typeEntry), _type); case DW_TAG_string_type: case DW_TAG_file_type: @@ -1523,14 +1965,24 @@ DwarfStackFrameDebugInfo::_CreateAddressType(const BString& name, // get the base type entry DIEAddressingType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( typeEntry, HasTypePredicate()); - if (baseTypeOwnerEntry == NULL) - return B_BAD_VALUE; // create the base type DwarfType* baseType; - status_t error = _CreateType(baseTypeOwnerEntry->GetType(), baseType); - if (error != B_OK) - return error; + if (baseTypeOwnerEntry != NULL) { + status_t error = _CreateType(baseTypeOwnerEntry->GetType(), baseType); + if (error != B_OK) + return error; + } else { + // According to the DWARF 3 specs a modified type *has* a base type. + // GCC 4 doesn't (always?) bother to add one for "void". + // TODO: We should probably search for a respective type by name. ATM + // we just create a DwarfUnspecifiedType without DIE. + TRACE_LOCALS("no base type for address type entry -- creating " + "unspecified type\n"); + baseType = new(std::nothrow) DwarfUnspecifiedType("void", NULL); + if (baseType == NULL) + return B_NO_MEMORY; + } Reference baseTypeReference(baseType, true); DwarfAddressType* type = new(std::nothrow) DwarfAddressType(name, typeEntry, @@ -1867,9 +2319,9 @@ DwarfStackFrameDebugInfo::_CreateSubrangeType(const BString& name, } if (isSigned) - upperBound.SetTo(lowerBound.ToInt64() + count.ToInt64()); + upperBound.SetTo(lowerBound.ToInt64() + count.ToInt64() - 1); else - upperBound.SetTo(lowerBound.ToUInt64() + count.ToUInt64()); + upperBound.SetTo(lowerBound.ToUInt64() + count.ToUInt64() - 1); } } @@ -1902,6 +2354,144 @@ DwarfStackFrameDebugInfo::_CreateSubrangeType(const BString& name, } +status_t +DwarfStackFrameDebugInfo::_CreateUnspecifiedType(const BString& name, + DIEUnspecifiedType* typeEntry, DwarfType*& _type) +{ + DwarfUnspecifiedType* type = new(std::nothrow) DwarfUnspecifiedType(name, + typeEntry); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + +status_t +DwarfStackFrameDebugInfo::_CreateFunctionType(const BString& name, + DIESubroutineType* typeEntry, DwarfType*& _type) +{ + // get the return type + DIESubroutineType* returnTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasReturnTypePredicate()); + + // create the base type + DwarfType* returnType = NULL; + if (returnTypeOwnerEntry != NULL) { + status_t error = _CreateType(returnTypeOwnerEntry->ReturnType(), + returnType); + if (error != B_OK) + return error; + } + Reference returnTypeReference(returnType, true); + + DwarfFunctionType* type = new(std::nothrow) DwarfFunctionType(name, + typeEntry, returnType); + if (type == NULL) + return B_NO_MEMORY; + Reference typeReference(type, true); + + // get the parameters + DIESubroutineType* parameterOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasParametersPredicate()); + + if (parameterOwnerEntry != NULL) { + for (DebugInfoEntryList::ConstIterator it + = parameterOwnerEntry->Parameters().GetIterator(); + DebugInfoEntry* _parameterEntry = it.Next();) { + if (_parameterEntry->Tag() == DW_TAG_unspecified_parameters) { + type->SetHasVariableArguments(true); + continue; + } + + DIEFormalParameter* parameterEntry + = dynamic_cast(_parameterEntry); + + // get the type + DIEFormalParameter* typeOwnerEntry = DwarfUtils::GetDIEByPredicate( + parameterEntry, HasTypePredicate()); + if (typeOwnerEntry == NULL) + return B_BAD_VALUE; + + DwarfType* parameterType; + status_t error = _CreateType(typeOwnerEntry->GetType(), + parameterType); + if (error != B_OK) + return error; + Reference parameterTypeReference(parameterType, true); + + // get the name + BString parameterName; + DwarfUtils::GetDIEName(parameterEntry, parameterName); + + // create and add the parameter object + DwarfFunctionParameter* parameter + = new(std::nothrow) DwarfFunctionParameter(parameterEntry, + parameterName, parameterType); + Reference parameterReference(parameter, + true); + if (parameter == NULL || !type->AddParameter(parameter)) + return B_NO_MEMORY; + } + } + + + _type = typeReference.Detach(); + return B_OK; +} + + +status_t +DwarfStackFrameDebugInfo::_CreatePointerToMemberType(const BString& name, + DIEPointerToMemberType* typeEntry, DwarfType*& _type) +{ + // get the containing and base type entries + DIEPointerToMemberType* containingTypeOwnerEntry + = DwarfUtils::GetDIEByPredicate(typeEntry, + HasContainingTypePredicate()); + DIEPointerToMemberType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasTypePredicate()); + + if (containingTypeOwnerEntry == NULL || baseTypeOwnerEntry == NULL) { + WARNING("Failed to get containing or base type for pointer to member " + "type \"%s\"\n", name.String()); + return B_BAD_VALUE; + } + + // create the containing type + DwarfType* containingType; + status_t error = _CreateType(containingTypeOwnerEntry->ContainingType(), + containingType); + if (error != B_OK) + return error; + Reference containingTypeReference(containingType, true); + + DwarfCompoundType* compoundContainingType + = dynamic_cast(containingType); + if (compoundContainingType == NULL) { + WARNING("Containing type for pointer to member type \"%s\" is not a " + "compound type.\n", name.String()); + return B_BAD_VALUE; + } + + // create the base type + DwarfType* baseType; + error = _CreateType(baseTypeOwnerEntry->GetType(), baseType); + if (error != B_OK) + return error; + Reference baseTypeReference(baseType, true); + + // create the type object + DwarfPointerToMemberType* type = new(std::nothrow) DwarfPointerToMemberType( + name, typeEntry, compoundContainingType, baseType); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + + status_t DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, DIEType* typeEntry, LocationDescription* locationDescription, @@ -2034,6 +2624,7 @@ DwarfStackFrameDebugInfo::_ResolveTypeByteSize(DIEType* typeEntry, break; case DW_TAG_pointer_type: case DW_TAG_reference_type: + case DW_TAG_ptr_to_member_type: _size = fCompilationUnit->AddressSize(); TRACE_LOCALS(" pointer/reference type: size: %llu\n", _size); diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h index fdd62ff8db..2daab2b433 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h @@ -22,10 +22,13 @@ class DIECompoundType; class DIEEnumerationType; class DIEFormalParameter; class DIEModifiedType; +class DIEPointerToMemberType; class DIESubprogram; class DIESubrangeType; +class DIESubroutineType; class DIEType; class DIETypedef; +class DIEUnspecifiedType; class DIEVariable; class DwarfFile; class DwarfTargetInterface; @@ -65,6 +68,11 @@ public: DataMember* member, const ValueLocation& parentLocation, ValueLocation*& _location); + virtual status_t ResolveArrayElementLocation( + StackFrame* stackFrame, ArrayType* type, + const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, + ValueLocation*& _location); status_t CreateType(DIEType* typeEntry, Type*& _type); // returns reference @@ -85,6 +93,7 @@ private: struct DwarfDataMember; struct DwarfEnumerationValue; struct DwarfArrayDimension; + struct DwarfFunctionParameter; struct DwarfPrimitiveType; struct DwarfCompoundType; struct DwarfModifiedType; @@ -93,6 +102,9 @@ private: struct DwarfEnumerationType; struct DwarfSubrangeType; struct DwarfArrayType; + struct DwarfUnspecifiedType; + struct DwarfFunctionType; + struct DwarfPointerToMemberType; struct DwarfTypeHashDefinition; typedef BOpenHashTable TypeTable; @@ -136,6 +148,15 @@ private: status_t _CreateSubrangeType(const BString& name, DIESubrangeType* typeEntry, DwarfType*& _type); + status_t _CreateUnspecifiedType(const BString& name, + DIEUnspecifiedType* typeEntry, + DwarfType*& _type); + status_t _CreateFunctionType(const BString& name, + DIESubroutineType* typeEntry, + DwarfType*& _type); + status_t _CreatePointerToMemberType(const BString& name, + DIEPointerToMemberType* typeEntry, + DwarfType*& _type); status_t _CreateVariable(ObjectID* id, const BString& name, DIEType* typeEntry, diff --git a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp index 8fdf26128e..bc8e7df992 100644 --- a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp +++ b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp @@ -43,3 +43,12 @@ NoOpStackFrameDebugInfo::ResolveDataMemberLocation(StackFrame* stackFrame, { return B_UNSUPPORTED; } + + +status_t +NoOpStackFrameDebugInfo::ResolveArrayElementLocation(StackFrame* stackFrame, + ArrayType* type, const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, ValueLocation*& _location) +{ + return B_UNSUPPORTED; +} diff --git a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h index f2a9f96afb..5c639f77a6 100644 --- a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h @@ -29,6 +29,11 @@ public: DataMember* member, const ValueLocation& parentLocation, ValueLocation*& _location); + virtual status_t ResolveArrayElementLocation( + StackFrame* stackFrame, ArrayType* type, + const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, + ValueLocation*& _location); }; diff --git a/src/apps/debugger/debug_info/StackFrameDebugInfo.h b/src/apps/debugger/debug_info/StackFrameDebugInfo.h index bf3cf8d836..caead5eed1 100644 --- a/src/apps/debugger/debug_info/StackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/StackFrameDebugInfo.h @@ -11,6 +11,8 @@ #include "Types.h" +class ArrayIndexPath; +class ArrayType; class Architecture; class BaseType; class DataMember; @@ -46,6 +48,12 @@ public: const ValueLocation& parentLocation, ValueLocation*& _location) = 0; // returns a reference + virtual status_t ResolveArrayElementLocation( + StackFrame* stackFrame, ArrayType* type, + const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, + ValueLocation*& _location) = 0; + // returns a reference protected: Architecture* fArchitecture; diff --git a/src/apps/debugger/gui/team_window/VariablesView.cpp b/src/apps/debugger/gui/team_window/VariablesView.cpp index 35f4ad89c1..b0a331669f 100644 --- a/src/apps/debugger/gui/team_window/VariablesView.cpp +++ b/src/apps/debugger/gui/team_window/VariablesView.cpp @@ -548,7 +548,9 @@ private: return; } - if (!baseIndexPath.SetTo(arrayComponent.name.String())) + status_t error + = baseIndexPath.SetTo(arrayComponent.name.String()); + if (error != B_OK) return; baseDimension = baseIndexPath.CountIndices(); @@ -579,10 +581,8 @@ private: component.SetToArrayElement(type->Kind(), indexPath); TypeComponentPath* elementPath - = new(std::nothrow) TypeComponentPath(*path); + = path->CreateSubPath(path->CountComponents() - 1); if (elementPath == NULL - || elementPath->CountComponents() - != path->CountComponents() || !elementPath->AddComponent(component)) { delete elementPath; return; @@ -604,10 +604,24 @@ private: case TYPE_ENUMERATION: TRACE_LOCALS("TYPE_ENUMERATION\n"); done = true; + break; + case TYPE_SUBRANGE: + TRACE_LOCALS("TYPE_SUBRANGE -> unsupported\n"); + // TODO: Support! return; - default: - TRACE_LOCALS("unknown\n"); + case TYPE_UNSPECIFIED: + // Should never get here -- we don't create nodes for + // unspecified types. + TRACE_LOCALS("TYPE_UNSPECIFIED\n"); return; + case TYPE_FUNCTION: + TRACE_LOCALS("TYPE_FUNCTION -> unsupported\n"); + // TODO: Support! + return; + case TYPE_POINTER_TO_MEMBER: + TRACE_LOCALS("TYPE_POINTER_TO_MEMBER\n"); + done = true; + break; } if (done) { @@ -627,6 +641,11 @@ private: TypeComponentPath* path, const BString& name, Type* type, bool isPresentationNode = false) { + // Don't create nodes for unspecified types -- we can't get/show their + // value anyway. + if (type->Kind() == TYPE_UNSPECIFIED) + return; + ValueNode* node = new(std::nothrow) ValueNode(parent, variable, path, name, type, isPresentationNode); if (node == NULL || !parent->AddChild(node)) { @@ -660,8 +679,22 @@ private: for (int32 componentIndex = i; componentIndex < childComponentCount; componentIndex++) { - if (childPath->ComponentAt(componentIndex) - != path->ComponentAt(componentIndex)) { + TypeComponent childComponent + = childPath->ComponentAt(componentIndex); + TypeComponent pathComponent + = path->ComponentAt(componentIndex); + if (childComponent != pathComponent) { + if (componentIndex + 1 == childComponentCount + && pathComponent.HasPrefix(childComponent)) { + // The last child component is a prefix of the + // corresponding path component. We consider this a + // match, but need to recheck the component with the + // next node level. + childComponentCount--; + break; + } + + // mismatch -- skip the child childNode = NULL; break; } diff --git a/src/apps/debugger/model/Type.cpp b/src/apps/debugger/model/Type.cpp index 6fa71d6bf9..2316dc69a6 100644 --- a/src/apps/debugger/model/Type.cpp +++ b/src/apps/debugger/model/Type.cpp @@ -50,20 +50,28 @@ ArrayDimension::CountElements() const if (type->Kind() == TYPE_SUBRANGE) { SubrangeType* subrangeType = dynamic_cast(type); BVariant lower = subrangeType->LowerBound(); - BVariant upper = subrangeType->LowerBound(); + BVariant upper = subrangeType->UpperBound(); bool isSigned; if (!lower.IsInteger(&isSigned) || !upper.IsInteger()) return 0; return isSigned - ? upper.ToInt64() - lower.ToInt64() - : upper.ToUInt64() - lower.ToUInt64(); + ? upper.ToInt64() - lower.ToInt64() + 1 + : upper.ToUInt64() - lower.ToUInt64() + 1; } return 0; } +// #pragma mark - FunctionParameter + + +FunctionParameter::~FunctionParameter() +{ +} + + // #pragma mark - Type @@ -224,3 +232,48 @@ ArrayType::Kind() const { return TYPE_ARRAY; } + + +// #pragma mark - UnspecifiedType + + +UnspecifiedType::~UnspecifiedType() +{ +} + + +type_kind +UnspecifiedType::Kind() const +{ + return TYPE_UNSPECIFIED; +} + + +// #pragma mark - FunctionType + + +FunctionType::~FunctionType() +{ +} + + +type_kind +FunctionType::Kind() const +{ + return TYPE_FUNCTION; +} + + +// #pragma mark - PointerToMemberType + + +PointerToMemberType::~PointerToMemberType() +{ +} + + +type_kind +PointerToMemberType::Kind() const +{ + return TYPE_POINTER_TO_MEMBER; +} diff --git a/src/apps/debugger/model/Type.h b/src/apps/debugger/model/Type.h index 0e8adac556..6178aede35 100644 --- a/src/apps/debugger/model/Type.h +++ b/src/apps/debugger/model/Type.h @@ -20,7 +20,10 @@ enum type_kind { TYPE_ADDRESS, TYPE_ENUMERATION, TYPE_SUBRANGE, - TYPE_ARRAY + TYPE_ARRAY, + TYPE_UNSPECIFIED, + TYPE_FUNCTION, + TYPE_POINTER_TO_MEMBER }; @@ -79,6 +82,15 @@ public: }; +class FunctionParameter : public Referenceable { +public: + virtual ~FunctionParameter(); + + virtual const char* Name() const = 0; + virtual Type* GetType() const = 0; +}; + + class Type : public Referenceable { public: virtual ~Type(); @@ -190,4 +202,38 @@ public: }; +class UnspecifiedType : public virtual Type { +public: + virtual ~UnspecifiedType(); + + virtual type_kind Kind() const; +}; + + +class FunctionType : public virtual Type { +public: + virtual ~FunctionType(); + + virtual type_kind Kind() const; + + virtual Type* ReturnType() const = 0; + + virtual int32 CountParameters() const = 0; + virtual FunctionParameter* ParameterAt(int32 index) const = 0; + + virtual bool HasVariableArguments() const = 0; +}; + + +class PointerToMemberType : public virtual Type { +public: + virtual ~PointerToMemberType(); + + virtual type_kind Kind() const; + + virtual CompoundType* ContainingType() const = 0; + virtual Type* BaseType() const = 0; +}; + + #endif // TYPE_H diff --git a/src/apps/debugger/model/TypeComponentPath.cpp b/src/apps/debugger/model/TypeComponentPath.cpp index b0dd5aa1ec..f969aa8c13 100644 --- a/src/apps/debugger/model/TypeComponentPath.cpp +++ b/src/apps/debugger/model/TypeComponentPath.cpp @@ -16,6 +16,18 @@ // #pragma mark - TypeComponent +bool +TypeComponent::HasPrefix(const TypeComponent& other) const +{ + if (*this == other) + return true; + + return componentKind == TYPE_COMPONENT_ARRAY_ELEMENT + && other.componentKind == TYPE_COMPONENT_ARRAY_ELEMENT + && name.Compare(other.name, other.name.Length()) == 0; +} + + uint32 TypeComponent::HashValue() const { @@ -52,6 +64,15 @@ TypeComponent::Dump() const case TYPE_ARRAY: printf("array"); break; + case TYPE_UNSPECIFIED: + printf("unspecified"); + break; + case TYPE_FUNCTION: + printf("function"); + break; + case TYPE_POINTER_TO_MEMBER: + printf("pointer to member"); + break; } printf(" "); diff --git a/src/apps/debugger/model/TypeComponentPath.h b/src/apps/debugger/model/TypeComponentPath.h index 831d22a01e..25e7058e94 100644 --- a/src/apps/debugger/model/TypeComponentPath.h +++ b/src/apps/debugger/model/TypeComponentPath.h @@ -85,6 +85,8 @@ struct TypeComponent { return indexPath.GetPathString(this->name); } + bool HasPrefix(const TypeComponent& other) const; + uint32 HashValue() const; void Dump() const; diff --git a/src/apps/debugger/types/ArrayIndexPath.cpp b/src/apps/debugger/types/ArrayIndexPath.cpp index 1eba023b44..c91cdf4080 100644 --- a/src/apps/debugger/types/ArrayIndexPath.cpp +++ b/src/apps/debugger/types/ArrayIndexPath.cpp @@ -31,33 +31,33 @@ ArrayIndexPath::~ArrayIndexPath() } -bool +status_t ArrayIndexPath::SetTo(const char* path) { fIndices.Clear(); if (path == NULL) - return true; + return B_OK; while (*path != '\0') { char* numberEnd; int64 index = strtoll(path, &numberEnd, 0); if (numberEnd == path) - return false; + return B_BAD_VALUE; path = numberEnd; if (!fIndices.Add(index)) - return false; + return B_NO_MEMORY; if (*path == '\0') break; if (*path != kIndexSeparator) - return false; + return B_BAD_VALUE; path++; } - return true; + return B_OK; } diff --git a/src/apps/debugger/types/ArrayIndexPath.h b/src/apps/debugger/types/ArrayIndexPath.h index 4b8548544f..a0e48aaf10 100644 --- a/src/apps/debugger/types/ArrayIndexPath.h +++ b/src/apps/debugger/types/ArrayIndexPath.h @@ -19,7 +19,7 @@ public: ArrayIndexPath(const ArrayIndexPath& other); ~ArrayIndexPath(); - bool SetTo(const char* path); + status_t SetTo(const char* path); void Clear(); bool GetPathString(BString& path) const;