From fad00fb02a262b92a1ac2f3ddbe8d5b15310b1fa Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sun, 2 Dec 2012 15:19:08 -0500 Subject: [PATCH] Add type handler and corresponding value node for BList. - When a debugging libbe is present, and a BList is encountered, we now read its internal structure and expose it as if it were an array of pointers. Combined with typecasting, this means one can now easily inspect the content of such a list. --- src/apps/debugger/Jamfile | 2 + src/apps/debugger/value/TypeHandlerRoster.cpp | 2 + .../value/type_handlers/BListTypeHandler.cpp | 47 ++++ .../value/type_handlers/BListTypeHandler.h | 21 ++ .../value/value_nodes/BListValueNode.cpp | 255 ++++++++++++++++++ .../value/value_nodes/BListValueNode.h | 53 ++++ 6 files changed, 380 insertions(+) create mode 100644 src/apps/debugger/value/type_handlers/BListTypeHandler.cpp create mode 100644 src/apps/debugger/value/type_handlers/BListTypeHandler.h create mode 100644 src/apps/debugger/value/value_nodes/BListValueNode.cpp create mode 100644 src/apps/debugger/value/value_nodes/BListValueNode.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 4eb12819dd..ac597c6973 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -265,6 +265,7 @@ Application Debugger : ValueNodeContainer.cpp # value/type_handlers + BListTypeHandler.cpp BMessageTypeHandler.cpp CStringTypeHandler.cpp @@ -279,6 +280,7 @@ Application Debugger : # value/value_nodes AddressValueNode.cpp ArrayValueNode.cpp + BListValueNode.cpp BMessageValueNode.cpp CompoundValueNode.cpp CStringValueNode.cpp diff --git a/src/apps/debugger/value/TypeHandlerRoster.cpp b/src/apps/debugger/value/TypeHandlerRoster.cpp index eda2839ba7..985d03cb0d 100644 --- a/src/apps/debugger/value/TypeHandlerRoster.cpp +++ b/src/apps/debugger/value/TypeHandlerRoster.cpp @@ -14,6 +14,7 @@ #include "AddressValueNode.h" #include "ArrayValueNode.h" #include "CompoundValueNode.h" +#include "BListTypeHandler.h" #include "BMessageTypeHandler.h" #include "CStringTypeHandler.h" #include "EnumerationValueNode.h" @@ -152,6 +153,7 @@ TypeHandlerRoster::RegisterDefaultHandlers() REGISTER_SPECIALIZED_HANDLER(CString); REGISTER_SPECIALIZED_HANDLER(BMessage); + REGISTER_SPECIALIZED_HANDLER(BList); return B_OK; } diff --git a/src/apps/debugger/value/type_handlers/BListTypeHandler.cpp b/src/apps/debugger/value/type_handlers/BListTypeHandler.cpp new file mode 100644 index 0000000000..c5918ed287 --- /dev/null +++ b/src/apps/debugger/value/type_handlers/BListTypeHandler.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "BListTypeHandler.h" + +#include + +#include "BListValueNode.h" +#include "Type.h" + + +BListTypeHandler::~BListTypeHandler() +{ +} + + +float +BListTypeHandler::SupportsType(Type* type) +{ + if (dynamic_cast(type) != NULL + && type->Name() == "BList") + return 1.0f; + + return 0.0f; +} + + +status_t +BListTypeHandler::CreateValueNode(ValueNodeChild* nodeChild, Type* type, + ValueNode*& _node) +{ + if (SupportsType(type) == 0.0f) + return B_BAD_VALUE; + + ValueNode* node = new(std::nothrow) BListValueNode(nodeChild, + type); + + if (node == NULL) + return B_NO_MEMORY; + + _node = node; + + return B_OK; +} diff --git a/src/apps/debugger/value/type_handlers/BListTypeHandler.h b/src/apps/debugger/value/type_handlers/BListTypeHandler.h new file mode 100644 index 0000000000..12f37546bd --- /dev/null +++ b/src/apps/debugger/value/type_handlers/BListTypeHandler.h @@ -0,0 +1,21 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef BLIST_TYPE_HANDLER_H +#define BLIST_TYPE_HANDLER_H + + +#include "TypeHandler.h" + + +class BListTypeHandler : public TypeHandler { +public: + virtual ~BListTypeHandler(); + + virtual float SupportsType(Type* type); + virtual status_t CreateValueNode(ValueNodeChild* nodeChild, + Type* type, ValueNode*& _node); +}; + +#endif // BLIST_TYPE_HANDLER_H diff --git a/src/apps/debugger/value/value_nodes/BListValueNode.cpp b/src/apps/debugger/value/value_nodes/BListValueNode.cpp new file mode 100644 index 0000000000..167c8884c0 --- /dev/null +++ b/src/apps/debugger/value/value_nodes/BListValueNode.cpp @@ -0,0 +1,255 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com + * Distributed under the terms of the MIT License. + */ + + +#include "BListValueNode.h" + +#include + +#include + +#include "AddressValueNode.h" +#include "Architecture.h" +#include "StringValue.h" +#include "Tracing.h" +#include "Type.h" +#include "TypeLookupConstraints.h" +#include "ValueLoader.h" +#include "ValueLocation.h" +#include "ValueNodeContainer.h" + + +// maximum number of array elements to show by default +static const int64 kMaxArrayElementCount = 20; + + +//#pragma mark - BListValueNode::BListElementNodeChild + + +class BListValueNode::BListElementNodeChild : public ValueNodeChild { +public: + BListElementNodeChild(BListValueNode* parent, + int64 elementIndex, Type* type); + virtual ~BListElementNodeChild(); + + virtual const BString& Name() const { return fName; }; + virtual Type* GetType() const { return fType; }; + virtual ValueNode* Parent() const { return fParent; }; + + virtual status_t ResolveLocation(ValueLoader* valueLoader, + ValueLocation*& _location); + +private: + Type* fType; + BListValueNode* fParent; + int64 fElementIndex; + BString fName; +}; + + +BListValueNode::BListElementNodeChild::BListElementNodeChild( + BListValueNode* parent, int64 elementIndex, Type* type) + : + ValueNodeChild(), + fType(type), + fParent(parent), + fElementIndex(elementIndex), + fName() +{ + fType->AcquireReference(); + fParent->AcquireReference(); + fName.SetToFormat("[%" B_PRId64 "]", fElementIndex); +} + + +BListValueNode::BListElementNodeChild::~BListElementNodeChild() +{ + fType->ReleaseReference(); + fParent->ReleaseReference(); +} + + +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; +} + + +//#pragma mark - BListValueNode + +BListValueNode::BListValueNode(ValueNodeChild* nodeChild, + Type* type) + : + ValueNode(nodeChild), + fType(type), + fLoader(NULL) +{ + fType->AcquireReference(); +} + + +BListValueNode::~BListValueNode() +{ + fType->ReleaseReference(); + for (int32 i = 0; i < fChildren.CountItems(); i++) + fChildren.ItemAt(i)->ReleaseReference(); + + delete fLoader; +} + + +Type* +BListValueNode::GetType() const +{ + return fType; +} + + +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(fType); + + 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); + if (error != B_OK) { + TRACE_LOCALS( + "BListValueNode::ResolvedLocationAndValue(): " + "failed to resolve location of header member: %s\n", + strerror(error)); + delete memberLocation; + return error; + } + + error = valueLoader->LoadValue(memberLocation, valueType, + false, fDataLocation); + delete memberLocation; + if (error != B_OK) + return error; + } else if (strcmp(member->Name(), "fItemCount") == 0) { + error = baseType->ResolveDataMemberLocation(member, + *location, memberLocation); + if (error != B_OK) { + TRACE_LOCALS( + "BListValueNode::ResolvedLocationAndValue(): " + "failed to resolve location of header member: %s\n", + strerror(error)); + delete memberLocation; + return error; + } + + BVariant listSize; + error = valueLoader->LoadValue(memberLocation, valueType, + false, listSize); + delete memberLocation; + if (error != B_OK) + return error; + + fItemCount = listSize.ToInt32(); + TRACE_LOCALS( + "BListValueNode::ResolvedLocationAndValue(): " + "detected list size %" B_PRId32 "\n", + fItemCount); + } + memberLocation = NULL; + } + + if (fLoader == NULL) { + fLoader = new(std::nothrow)ValueLoader(*valueLoader); + if (fLoader == NULL) + return B_NO_MEMORY; + } + + return B_OK; +} + + +status_t +BListValueNode::CreateChildren() +{ + BString typeName; + TypeLookupConstraints constraints; + constraints.SetTypeKind(TYPE_ADDRESS); + constraints.SetBaseTypeName("void"); + Type* type = NULL; + status_t result = fLoader->LookupTypeByName(typeName, constraints, type); + if (result != B_OK) + return result; + + for (int32 i = 0; i < fItemCount && i < kMaxArrayElementCount; i++) + { + BListElementNodeChild* child = + new(std::nothrow) BListElementNodeChild(this, i, type); + if (child == NULL) + return B_NO_MEMORY; + child->SetContainer(fContainer); + fChildren.AddItem(child); + } + + fChildrenCreated = true; + + if (fContainer != NULL) + fContainer->NotifyValueNodeChildrenCreated(this); + + return B_OK; +} + + +int32 +BListValueNode::CountChildren() const +{ + return fChildren.CountItems(); +} + + +ValueNodeChild* +BListValueNode::ChildAt(int32 index) const +{ + return fChildren.ItemAt(index); +} diff --git a/src/apps/debugger/value/value_nodes/BListValueNode.h b/src/apps/debugger/value/value_nodes/BListValueNode.h new file mode 100644 index 0000000000..252cf332e4 --- /dev/null +++ b/src/apps/debugger/value/value_nodes/BListValueNode.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef BLIST_VALUE_NODE_H +#define BLIST_VALUE_NODE_H + + +#include +#include + +#include + +#include "ValueLocation.h" +#include "ValueNode.h" + + +class CompoundType; + + +class BListValueNode : public ValueNode { +public: + BListValueNode(ValueNodeChild* nodeChild, + Type* type); + virtual ~BListValueNode(); + + virtual Type* GetType() const; + virtual status_t ResolvedLocationAndValue( + ValueLoader* valueLoader, + ValueLocation*& _location, + Value*& _value); + + virtual bool ChildCreationNeedsValue() const + { return true; } + virtual status_t CreateChildren(); + virtual int32 CountChildren() const; + virtual ValueNodeChild* ChildAt(int32 index) const; + +private: + class BListElementNodeChild; + typedef BObjectList ChildNodeList; + +private: + + Type* fType; + ChildNodeList fChildren; + ValueLoader* fLoader; + BVariant fDataLocation; + int32 fItemCount; +}; + + +#endif // BLIST_VALUE_NODE_H