* ArrayIndexPath::SetTo(): Changed return type from bool to status_t.

* Finished support for retrieving and displaying array element values.
* Added work-around for pointer types, if the base type isn't specified in the
  debug info (as it should per specification).
* Added support for unspecified types, function types, and pointer to member
  types. All types relevant for C++ should be supported now. There are still
  quite a few TODOs, though.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33434 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-10-05 03:12:16 +00:00
parent bdfb434cba
commit e10cb2838b
13 changed files with 875 additions and 37 deletions
+58 -9
View File
@@ -546,7 +546,8 @@ GetStackFrameValueJob::_GetValue()
type = dynamic_cast<TypedefType*>(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<ArrayType*>(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;
}
@@ -11,6 +11,7 @@
#include <Variant.h>
#include "ArrayIndexPath.h"
#include "Architecture.h"
#include "CompilationUnit.h"
#include "DebugInfoEntries.h"
@@ -44,6 +45,18 @@ struct HasTypePredicate {
};
// #pragma mark - HasReturnTypePredicate
template<typename EntryType>
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<typename EntryType>
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<typename EntryType>
struct HasBitStridePredicate {
inline bool operator()(EntryType* entry) const
{
return entry->BitStride()->IsValid();
}
};
// #pragma mark - HasByteStridePredicate
template<typename EntryType>
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<DwarfFunctionParameter> 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<DwarfArrayType*>(_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<DIEArrayType>())) {
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<DIEArrayIndexType*>(dimensionType->GetDIEType())
: NULL;
if (dimensionTypeEntry != NULL) {
DIEArrayIndexType* bitStrideOwnerEntry
= DwarfUtils::GetDIEByPredicate(dimensionTypeEntry,
HasBitStridePredicate<DIEArrayIndexType>());
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<DIEArrayIndexType>());
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<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(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<DIESubrangeType*>(typeEntry), _type);
case DW_TAG_unspecified_type:
return _CreateUnspecifiedType(name,
dynamic_cast<DIEUnspecifiedType*>(typeEntry), _type);
case DW_TAG_subroutine_type:
return _CreateFunctionType(name,
dynamic_cast<DIESubroutineType*>(typeEntry), _type);
case DW_TAG_ptr_to_member_type:
// TODO: Implement!
return B_UNSUPPORTED;
return _CreatePointerToMemberType(name,
dynamic_cast<DIEPointerToMemberType*>(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<DIEAddressingType>());
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<Type> 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<DIESubroutineType>());
// create the base type
DwarfType* returnType = NULL;
if (returnTypeOwnerEntry != NULL) {
status_t error = _CreateType(returnTypeOwnerEntry->ReturnType(),
returnType);
if (error != B_OK)
return error;
}
Reference<Type> returnTypeReference(returnType, true);
DwarfFunctionType* type = new(std::nothrow) DwarfFunctionType(name,
typeEntry, returnType);
if (type == NULL)
return B_NO_MEMORY;
Reference<DwarfType> typeReference(type, true);
// get the parameters
DIESubroutineType* parameterOwnerEntry = DwarfUtils::GetDIEByPredicate(
typeEntry, HasParametersPredicate<DIESubroutineType>());
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<DIEFormalParameter*>(_parameterEntry);
// get the type
DIEFormalParameter* typeOwnerEntry = DwarfUtils::GetDIEByPredicate(
parameterEntry, HasTypePredicate<DIEFormalParameter>());
if (typeOwnerEntry == NULL)
return B_BAD_VALUE;
DwarfType* parameterType;
status_t error = _CreateType(typeOwnerEntry->GetType(),
parameterType);
if (error != B_OK)
return error;
Reference<DwarfType> 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<DwarfFunctionParameter> 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<DIEPointerToMemberType>());
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<Type> containingTypeReference(containingType, true);
DwarfCompoundType* compoundContainingType
= dynamic_cast<DwarfCompoundType*>(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<Type> 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);
@@ -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<DwarfTypeHashDefinition> 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,
@@ -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;
}
@@ -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);
};
@@ -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;
@@ -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;
}
+56 -3
View File
@@ -50,20 +50,28 @@ ArrayDimension::CountElements() const
if (type->Kind() == TYPE_SUBRANGE) {
SubrangeType* subrangeType = dynamic_cast<SubrangeType*>(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;
}
+47 -1
View File
@@ -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
@@ -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(" ");
@@ -85,6 +85,8 @@ struct TypeComponent {
return indexPath.GetPathString(this->name);
}
bool HasPrefix(const TypeComponent& other) const;
uint32 HashValue() const;
void Dump() const;
+6 -6
View File
@@ -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;
}
+1 -1
View File
@@ -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;