From ef826895ffe809578436d6f6d1c9503d38d3fe16 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 2 Jul 2011 20:11:54 +0000 Subject: [PATCH] * Restructure things a bit so we store the message's message and field headers after resolving them. This allows us to reuse BMessage's logic for computing the offsets of values in the data buffer. * Resolve fields to their types and correctly resolve the locations of their data. This means we can now see the values of fields inside the message, with some caveats: string types aren't yet handled properly, and we don't yet properly deal with fields that have multiple indices. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42365 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../value/value_nodes/BMessageValueNode.cpp | 327 +++++++++++++++--- .../value/value_nodes/BMessageValueNode.h | 31 +- 2 files changed, 301 insertions(+), 57 deletions(-) diff --git a/src/apps/debugger/value/value_nodes/BMessageValueNode.cpp b/src/apps/debugger/value/value_nodes/BMessageValueNode.cpp index 9475d60c9c..65124cae7f 100644 --- a/src/apps/debugger/value/value_nodes/BMessageValueNode.cpp +++ b/src/apps/debugger/value/value_nodes/BMessageValueNode.cpp @@ -15,6 +15,7 @@ #include "StringValue.h" #include "Tracing.h" #include "Type.h" +#include "TypeLookupConstraints.h" #include "ValueLoader.h" #include "ValueLocation.h" #include "ValueNodeContainer.h" @@ -92,7 +93,10 @@ BMessageValueNode::BMessageValueNode(ValueNodeChild* nodeChild, ValueNode(nodeChild), fType(type), fMessageType(NULL), - fMessage() + fLoader(NULL), + fHeader(NULL), + fFields(NULL), + fData(NULL) { fType->AcquireReference(); } @@ -103,6 +107,11 @@ BMessageValueNode::~BMessageValueNode() fType->ReleaseReference(); for (int32 i = 0; i < fChildren.CountItems(); i++) fChildren.ItemAt(i)->ReleaseReference(); + + delete fLoader; + delete fHeader; + delete[] fFields; + delete[] fData; } @@ -162,7 +171,6 @@ BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, BVariant headerAddress; BVariant fieldAddress; - BVariant dataAddress; BVariant what; for (int32 i = 0; i < baseType->CountDataMembers(); i++) { @@ -224,7 +232,7 @@ BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, return error; } error = valueLoader->LoadValue(memberLocation, valueType, - false, dataAddress); + false, fDataLocation); delete memberLocation; if (error != B_OK) return error; @@ -235,61 +243,66 @@ BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, TRACE_LOCALS("BMessage: what: 0x%" B_PRIx32 ", result: %ld\n", what.ToUInt32(), error); - uint8 headerBuffer[sizeof(BMessage::message_header)]; - error = valueLoader->LoadRawValue(headerAddress, sizeof(headerBuffer), - headerBuffer); + + fHeader = new(std::nothrow) BMessage::message_header(); + if (fHeader == NULL) + return B_NO_MEMORY; + error = valueLoader->LoadRawValue(headerAddress, sizeof( + BMessage::message_header), fHeader); TRACE_LOCALS("BMessage: Header Address: 0x%" B_PRIx64 ", result: %ld\n", headerAddress.ToUInt64(), error); if (error != B_OK) return error; + fHeader->what = what.ToUInt32(); - BMessage::message_header* header = (BMessage::message_header*)headerBuffer; - header->what = what.ToUInt32(); - size_t fieldsSize = header->field_count * sizeof(BMessage::field_header); - size_t totalMessageSize = sizeof(BMessage::message_header) - + fieldsSize + header->data_size; - - uint8* messageBuffer = new(std::nothrow)uint8[totalMessageSize]; + size_t fieldsSize = fHeader->field_count * sizeof( + BMessage::field_header); + size_t totalSize = sizeof(BMessage::message_header) + fieldsSize + fHeader->data_size; + uint8* messageBuffer = new(std::nothrow) uint8[totalSize]; if (messageBuffer == NULL) return B_NO_MEMORY; - - memset(messageBuffer, 0, totalMessageSize); - - ArrayDeleter deleter(messageBuffer); - - // This more or less follows the logic of BMessage::Flatten - // in order to reconstruct the flattened buffer ; thus if the - // internal representation of that changes, this will have to - // follow suit - uint8* currentBuffer = messageBuffer; - memcpy(currentBuffer, header, - sizeof(BMessage::message_header)); - + memset(messageBuffer, 0, totalSize); + memcpy(messageBuffer, fHeader, sizeof(BMessage::message_header)); + uint8* tempBuffer = messageBuffer + sizeof(BMessage::message_header); if (fieldsSize > 0) { - currentBuffer += sizeof(BMessage::message_header); + fFields = new(std::nothrow) + BMessage::field_header[fHeader->field_count]; + if (fFields == NULL) + return B_NO_MEMORY; + error = valueLoader->LoadRawValue(fieldAddress, fieldsSize, - currentBuffer); + fFields); TRACE_LOCALS("BMessage: Field Header Address: 0x%" B_PRIx64 ", result: %ld\n", headerAddress.ToUInt64(), error); if (error != B_OK) return error; - headerAddress.SetTo(dataAddress); - currentBuffer += fieldsSize; - error = valueLoader->LoadRawValue(dataAddress, header->data_size, - currentBuffer); - TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64 ", result: %ld\n", - headerAddress.ToUInt64(), error); + fData = new(std::nothrow) uint8[fHeader->data_size]; + if (fData == NULL) + return B_NO_MEMORY; + + error = valueLoader->LoadRawValue(fDataLocation, fHeader->data_size, + fData); + TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64 + ", result: %ld\n", fDataLocation.ToUInt64(), error); if (error != B_OK) - return B_ERROR; + return error; + memcpy(tempBuffer, fFields, fieldsSize); + tempBuffer += fieldsSize; + memcpy(tempBuffer, fData, fHeader->data_size); } - error = fMessage.Unflatten((const char *)messageBuffer); - TRACE_LOCALS("BMessage: Unflatten result: %s\n", strerror(error)); - + error = fMessage.Unflatten((const char*)messageBuffer); + delete[] messageBuffer; if (error != B_OK) return error; + if (fLoader == NULL) { + fLoader = new(std::nothrow)ValueLoader(*valueLoader); + if (fLoader == NULL) + return B_NO_MEMORY; + } + return B_OK; } @@ -303,7 +316,6 @@ BMessageValueNode::CreateChildren() if (fMessageType == NULL) return B_BAD_VALUE; - DataMember* member = NULL; Type* whatType = NULL; @@ -326,13 +338,16 @@ BMessageValueNode::CreateChildren() char* name; type_code type; int32 count; - for (int32 i = 0; - fMessage.GetInfo(B_ANY_TYPE, i, &name, &type, &count) == B_OK; - i++) { - // TODO: split FieldHeaderNode into two variants in order to - // present fields with a count of 1 without subindices. + Type* fieldType = NULL; + for (int32 i = 0; fMessage.GetInfo(B_ANY_TYPE, i, &name, &type, + &count) == B_OK; i++) { + fieldType = NULL; + + _GetTypeForTypeCode(type, fieldType); + BMessageFieldNodeChild* node = new(std::nothrow) - BMessageFieldNodeChild(this, name, type, count); + BMessageFieldNodeChild(this, fieldType != NULL ? fieldType : fType, + name, type, count); if (node == NULL) return B_NO_MEMORY; @@ -361,15 +376,220 @@ BMessageValueNode::ChildAt(int32 index) const } +status_t +BMessageValueNode::_GetTypeForTypeCode(type_code type, + Type*& _type) +{ + BString typeName; + TypeLookupConstraints constraints; + + switch(type) { + case B_BOOL_TYPE: + typeName = "bool"; + constraints.SetTypeKind(TYPE_PRIMITIVE); + break; + + case B_INT8_TYPE: + typeName = "int8"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_UINT8_TYPE: + typeName = "uint8"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_INT16_TYPE: + typeName = "int16"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_UINT16_TYPE: + typeName = "uint16"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_INT32_TYPE: + typeName = "int32"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_UINT32_TYPE: + typeName = "uint32"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_INT64_TYPE: + typeName = "int64"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_UINT64_TYPE: + typeName = "uint64"; + constraints.SetTypeKind(TYPE_TYPEDEF); + break; + + case B_FLOAT_TYPE: + typeName = "float"; + constraints.SetTypeKind(TYPE_PRIMITIVE); + break; + + case B_DOUBLE_TYPE: + typeName = "double"; + constraints.SetTypeKind(TYPE_PRIMITIVE); + break; + + case B_MESSAGE_TYPE: + typeName = "BMessage"; + constraints.SetTypeKind(TYPE_COMPOUND); + break; + + case B_MESSENGER_TYPE: + typeName = "BMessenger"; + constraints.SetTypeKind(TYPE_COMPOUND); + break; + + case B_POINT_TYPE: + typeName = "BPoint"; + constraints.SetTypeKind(TYPE_COMPOUND); + break; + + case B_POINTER_TYPE: + typeName = "void"; + constraints.SetTypeKind(TYPE_ADDRESS); + break; + + case B_RECT_TYPE: + typeName = "BRect"; + constraints.SetTypeKind(TYPE_COMPOUND); + break; + + case B_REF_TYPE: + typeName = "entry_ref"; + constraints.SetTypeKind(TYPE_COMPOUND); + break; + + case B_RGB_COLOR_TYPE: + typeName = "rgb_color"; + constraints.SetTypeKind(TYPE_COMPOUND); + break; + + case B_STRING_TYPE: + typeName = "char"; + constraints.SetTypeKind(TYPE_ARRAY); + break; + + default: + return B_BAD_VALUE; + break; + } + + return fLoader->LookupTypeByName(typeName, constraints, _type); +} + + +status_t +BMessageValueNode::_FindField(const char* name, type_code type, + BMessage::field_header** result) const +{ + if (name == NULL) + return B_BAD_VALUE; + + if (fHeader == NULL) + return B_NO_INIT; + + if (fHeader->field_count == 0 || fFields == NULL || fData == NULL) + return B_NAME_NOT_FOUND; + + uint32 hash = _HashName(name) % fHeader->hash_table_size; + int32 nextField = fHeader->hash_table[hash]; + + while (nextField >= 0) { + BMessage::field_header* field = &fFields[nextField]; + if ((field->flags & FIELD_FLAG_VALID) == 0) + break; + + if (strncmp((const char*)(fData + field->offset), name, + field->name_length) == 0) { + if (type != B_ANY_TYPE && field->type != type) + return B_BAD_TYPE; + + *result = field; + return B_OK; + } + + nextField = field->next_field; + } + + return B_NAME_NOT_FOUND; +} + + +uint32 +BMessageValueNode::_HashName(const char* name) const +{ + char ch; + uint32 result = 0; + + while ((ch = *name++) != 0) { + result = (result << 7) ^ (result >> 24); + result ^= ch; + } + + result ^= result << 12; + return result; +} + + +status_t +BMessageValueNode::_FindDataLocation(const char* name, type_code type, + int32 index, ValueLocation& location) const +{ + BMessage::field_header* field = NULL; + int32 offset = 0; + int32 size = 0; + status_t result = _FindField(name, type, &field); + if (result != B_OK) + return result; + + if (index < 0 || (uint32)index >= field->count) + return B_BAD_INDEX; + + if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) { + size = field->data_size / field->count; + offset = field->offset + field->name_length + index * size; + } else { + offset = field->offset + field->name_length; + uint8 *pointer = fData + field->offset + field->name_length; + for (int32 i = 0; i < index; i++) { + pointer += *(uint32*)pointer + sizeof(uint32); + offset += *(uint32*)pointer + sizeof(uint32); + } + + size = *(uint32*)pointer; + offset += sizeof(uint32); + } + + ValuePieceLocation piece; + piece.SetToMemory(fDataLocation.ToUInt64() + offset); + piece.SetSize(size); + location.Clear(); + location.AddPiece(piece); + + return B_OK; +} + + // #pragma mark - BMessageValueNode::BMessageFieldNode + BMessageValueNode::BMessageFieldNode::BMessageFieldNode( BMessageFieldNodeChild *child, BMessageValueNode* parent, const BString &name, type_code type, int32 count) : ValueNode(child), fName(name), - fType(parent->GetType()), + fType(parent->fMessageType), fParent(parent), fFieldType(type), fFieldCount(count) @@ -428,12 +648,12 @@ BMessageValueNode::BMessageFieldNode::ResolvedLocationAndValue( BMessageValueNode::BMessageFieldNodeChild::BMessageFieldNodeChild( - BMessageValueNode* parent, const BString &name, type_code type, - int32 count) + BMessageValueNode* parent, Type* nodeType, const BString &name, + type_code type, int32 count) : ValueNodeChild(), fName(name), - fType(parent->GetType()), + fType(nodeType), fParent(parent), fFieldType(type), fFieldCount(count) @@ -474,7 +694,7 @@ BMessageValueNode::BMessageFieldNodeChild::Parent() const bool BMessageValueNode::BMessageFieldNodeChild::IsInternal() const { - return true; + return fFieldCount > 1; } @@ -496,7 +716,10 @@ status_t BMessageValueNode::BMessageFieldNodeChild::ResolveLocation( ValueLoader* valueLoader, ValueLocation*& _location) { - _location = fParent->Location(); + _location = new(std::nothrow)ValueLocation(); - return B_OK; + if (_location == NULL) + return B_NO_MEMORY; + + return fParent->_FindDataLocation(fName, fFieldType, 0, *_location); } diff --git a/src/apps/debugger/value/value_nodes/BMessageValueNode.h b/src/apps/debugger/value/value_nodes/BMessageValueNode.h index f774f96f50..9fca6cce07 100644 --- a/src/apps/debugger/value/value_nodes/BMessageValueNode.h +++ b/src/apps/debugger/value/value_nodes/BMessageValueNode.h @@ -6,8 +6,11 @@ #define BMESSAGE_VALUE_NODE_H #include +#include #include +#include +#include "ValueLocation.h" #include "ValueNode.h" @@ -35,6 +38,17 @@ public: CompoundType* GetMessageType() const { return fMessageType; } +private: + status_t _GetTypeForTypeCode(type_code type, + Type*& _type); + status_t _FindField(const char* name, + type_code type, + BMessage::field_header** result) const; + uint32 _HashName(const char* name) const; + status_t _FindDataLocation(const char* name, + type_code type, int32 index, + ValueLocation& location) const; + private: class BMessageFieldNode; class BMessageFieldNodeChild; @@ -48,8 +62,14 @@ private: private: Type* fType; CompoundType* fMessageType; - BMessage fMessage; ChildNodeList fChildren; + ValueLoader* fLoader; + BVariant fDataLocation; + BMessage::message_header* + fHeader; + BMessage::field_header* fFields; + uint8* fData; + BMessage fMessage; }; @@ -65,15 +85,15 @@ public: virtual Type* GetType() const; - virtual status_t CreateChildren(); - virtual int32 CountChildren() const; - virtual ValueNodeChild* ChildAt(int32 index) const; - virtual status_t ResolvedLocationAndValue( ValueLoader* loader, ValueLocation *& _location, Value*& _value); + virtual status_t CreateChildren(); + virtual int32 CountChildren() const; + virtual ValueNodeChild* ChildAt(int32 index) const; + private: BString fName; Type* fType; @@ -87,6 +107,7 @@ class BMessageValueNode::BMessageFieldNodeChild : public ValueNodeChild { public: BMessageFieldNodeChild( BMessageValueNode* parent, + Type* nodeType, const BString &name, type_code type, int32 count);