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:
Rene Gollent
2012-12-02 15:26:19 -05:00
parent 5ad3b800d5
commit fad00fb02a
6 changed files with 380 additions and 0 deletions
+2
View File
@@ -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
@@ -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;
}
@@ -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