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.
This commit is contained in:
@@ -265,6 +265,7 @@ Application Debugger :
|
|||||||
ValueNodeContainer.cpp
|
ValueNodeContainer.cpp
|
||||||
|
|
||||||
# value/type_handlers
|
# value/type_handlers
|
||||||
|
BListTypeHandler.cpp
|
||||||
BMessageTypeHandler.cpp
|
BMessageTypeHandler.cpp
|
||||||
CStringTypeHandler.cpp
|
CStringTypeHandler.cpp
|
||||||
|
|
||||||
@@ -279,6 +280,7 @@ Application Debugger :
|
|||||||
# value/value_nodes
|
# value/value_nodes
|
||||||
AddressValueNode.cpp
|
AddressValueNode.cpp
|
||||||
ArrayValueNode.cpp
|
ArrayValueNode.cpp
|
||||||
|
BListValueNode.cpp
|
||||||
BMessageValueNode.cpp
|
BMessageValueNode.cpp
|
||||||
CompoundValueNode.cpp
|
CompoundValueNode.cpp
|
||||||
CStringValueNode.cpp
|
CStringValueNode.cpp
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "AddressValueNode.h"
|
#include "AddressValueNode.h"
|
||||||
#include "ArrayValueNode.h"
|
#include "ArrayValueNode.h"
|
||||||
#include "CompoundValueNode.h"
|
#include "CompoundValueNode.h"
|
||||||
|
#include "BListTypeHandler.h"
|
||||||
#include "BMessageTypeHandler.h"
|
#include "BMessageTypeHandler.h"
|
||||||
#include "CStringTypeHandler.h"
|
#include "CStringTypeHandler.h"
|
||||||
#include "EnumerationValueNode.h"
|
#include "EnumerationValueNode.h"
|
||||||
@@ -152,6 +153,7 @@ TypeHandlerRoster::RegisterDefaultHandlers()
|
|||||||
|
|
||||||
REGISTER_SPECIALIZED_HANDLER(CString);
|
REGISTER_SPECIALIZED_HANDLER(CString);
|
||||||
REGISTER_SPECIALIZED_HANDLER(BMessage);
|
REGISTER_SPECIALIZED_HANDLER(BMessage);
|
||||||
|
REGISTER_SPECIALIZED_HANDLER(BList);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "BListTypeHandler.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "BListValueNode.h"
|
||||||
|
#include "Type.h"
|
||||||
|
|
||||||
|
|
||||||
|
BListTypeHandler::~BListTypeHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
BListTypeHandler::SupportsType(Type* type)
|
||||||
|
{
|
||||||
|
if (dynamic_cast<CompoundType*>(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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, [email protected].
|
||||||
|
* 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
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, [email protected]
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "BListValueNode.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#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<CompoundType*>(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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef BLIST_VALUE_NODE_H
|
||||||
|
#define BLIST_VALUE_NODE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
#include <Variant.h>
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
#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<ValueNodeChild> ChildNodeList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Type* fType;
|
||||||
|
ChildNodeList fChildren;
|
||||||
|
ValueLoader* fLoader;
|
||||||
|
BVariant fDataLocation;
|
||||||
|
int32 fItemCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BLIST_VALUE_NODE_H
|
||||||
Reference in New Issue
Block a user