1 /* 2 * Copyright 2011-2015, Rene Gollent, rene@gollent.com 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "BMessageValueNode.h" 8 9 #include <new> 10 11 #include <AutoDeleter.h> 12 #include <MessageAdapter.h> 13 #include <MessagePrivate.h> 14 15 #include "Architecture.h" 16 #include "StringValue.h" 17 #include "TeamTypeInformation.h" 18 #include "Tracing.h" 19 #include "Type.h" 20 #include "TypeLookupConstraints.h" 21 #include "ValueLoader.h" 22 #include "ValueLocation.h" 23 #include "ValueNodeContainer.h" 24 25 26 static const int64 kMaxStringSize = 64; 27 28 29 // #pragma mark - BMessageWhatNodeChild 30 31 32 class BMessageWhatNodeChild : public ValueNodeChild { 33 public: 34 BMessageWhatNodeChild(BMessageValueNode* parent, DataMember* member, 35 Type* type) 36 : 37 ValueNodeChild(), 38 fMember(member), 39 fName("what"), 40 fParent(parent), 41 fType(type) 42 { 43 fParent->AcquireReference(); 44 fType->AcquireReference(); 45 } 46 47 virtual ~BMessageWhatNodeChild() 48 { 49 fParent->ReleaseReference(); 50 fType->ReleaseReference(); 51 } 52 53 virtual const BString& Name() const 54 { 55 return fName; 56 } 57 58 virtual Type* GetType() const 59 { 60 return fType; 61 } 62 63 virtual ValueNode* Parent() const 64 { 65 return fParent; 66 } 67 68 virtual status_t ResolveLocation(ValueLoader* valueLoader, 69 ValueLocation*& _location) 70 { 71 ValueLocation* parentLocation = fParent->Location(); 72 ValueLocation* location; 73 CompoundType* type = dynamic_cast<CompoundType*>(fParent->GetType()); 74 status_t error = B_OK; 75 if (fParent->fIsFlatMessage) { 76 location = new ValueLocation(); 77 if (location == NULL) 78 return B_NO_MEMORY; 79 80 ValuePieceLocation piece; 81 piece.SetToMemory(parentLocation->PieceAt(0).address 82 + sizeof(uint32)); 83 piece.SetSize(sizeof(uint32)); 84 location->AddPiece(piece); 85 } else { 86 error = type->ResolveDataMemberLocation(fMember, 87 *parentLocation, location); 88 } 89 90 if (error != B_OK) 91 return error; 92 93 _location = location; 94 return B_OK; 95 } 96 97 private: 98 DataMember* fMember; 99 BString fName; 100 BMessageValueNode* fParent; 101 Type* fType; 102 }; 103 104 105 // #pragma mark - BMessageValueNode 106 107 108 BMessageValueNode::BMessageValueNode(ValueNodeChild* nodeChild, 109 Type* type) 110 : 111 ValueNode(nodeChild), 112 fType(type), 113 fHeader(NULL), 114 fFields(NULL), 115 fData(NULL), 116 fIsFlatMessage(false) 117 { 118 fType->AcquireReference(); 119 } 120 121 122 BMessageValueNode::~BMessageValueNode() 123 { 124 fType->ReleaseReference(); 125 for (int32 i = 0; i < fChildren.CountItems(); i++) 126 fChildren.ItemAt(i)->ReleaseReference(); 127 128 delete fHeader; 129 delete[] fFields; 130 delete[] fData; 131 } 132 133 134 Type* 135 BMessageValueNode::GetType() const 136 { 137 return fType; 138 } 139 140 141 status_t 142 BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, 143 ValueLocation*& _location, Value*& _value) 144 { 145 fIsFlatMessage = dynamic_cast<BMessageFieldNodeChild*>(NodeChild()) 146 != NULL; 147 148 // get the location 149 ValueLocation* location = NodeChild()->Location(); 150 if (location == NULL) 151 return B_BAD_VALUE; 152 153 154 // get the value type 155 type_code valueType; 156 if (valueLoader->GetArchitecture()->AddressSize() == 4) { 157 valueType = B_UINT32_TYPE; 158 TRACE_LOCALS(" -> 32 bit\n"); 159 } else { 160 valueType = B_UINT64_TYPE; 161 TRACE_LOCALS(" -> 64 bit\n"); 162 } 163 164 // load the value data 165 166 status_t error = B_OK; 167 ValueLocation* memberLocation = NULL; 168 169 BVariant headerAddress; 170 BVariant fieldAddress; 171 BVariant what; 172 173 CompoundType* baseType = dynamic_cast<CompoundType*>(fType); 174 175 if (fIsFlatMessage) { 176 headerAddress.SetTo(location->PieceAt(0).address); 177 fieldAddress.SetTo(headerAddress.ToUInt64() 178 + sizeof(BMessage::message_header)); 179 } else { 180 for (int32 i = 0; i < baseType->CountDataMembers(); i++) { 181 DataMember* member = baseType->DataMemberAt(i); 182 if (strcmp(member->Name(), "fHeader") == 0) { 183 error = baseType->ResolveDataMemberLocation(member, 184 *location, memberLocation); 185 BReference<ValueLocation> locationRef(memberLocation, true); 186 if (error != B_OK) { 187 TRACE_LOCALS( 188 "BMessageValueNode::ResolvedLocationAndValue(): " 189 "failed to resolve location of header member: %s\n", 190 strerror(error)); 191 return error; 192 } 193 194 error = valueLoader->LoadValue(memberLocation, valueType, 195 false, headerAddress); 196 if (error != B_OK) 197 return error; 198 } else if (strcmp(member->Name(), "what") == 0) { 199 error = baseType->ResolveDataMemberLocation(member, 200 *location, memberLocation); 201 BReference<ValueLocation> locationRef(memberLocation, true); 202 if (error != B_OK) { 203 TRACE_LOCALS( 204 "BMessageValueNode::ResolvedLocationAndValue(): " 205 "failed to resolve location of header member: %s\n", 206 strerror(error)); 207 return error; 208 } 209 error = valueLoader->LoadValue(memberLocation, B_UINT32_TYPE, 210 false, what); 211 if (error != B_OK) 212 return error; 213 } else if (strcmp(member->Name(), "fFields") == 0) { 214 error = baseType->ResolveDataMemberLocation(member, 215 *location, memberLocation); 216 BReference<ValueLocation> locationRef(memberLocation, true); 217 if (error != B_OK) { 218 TRACE_LOCALS( 219 "BMessageValueNode::ResolvedLocationAndValue(): " 220 "failed to resolve location of field member: %s\n", 221 strerror(error)); 222 return error; 223 } 224 error = valueLoader->LoadValue(memberLocation, valueType, 225 false, fieldAddress); 226 if (error != B_OK) 227 return error; 228 } else if (strcmp(member->Name(), "fData") == 0) { 229 error = baseType->ResolveDataMemberLocation(member, 230 *location, memberLocation); 231 BReference<ValueLocation> locationRef(memberLocation, true); 232 if (error != B_OK) { 233 TRACE_LOCALS( 234 "BMessageValueNode::ResolvedLocationAndValue(): " 235 "failed to resolve location of data member: %s\n", 236 strerror(error)); 237 return error; 238 } 239 error = valueLoader->LoadValue(memberLocation, valueType, 240 false, fDataLocation); 241 if (error != B_OK) 242 return error; 243 } 244 memberLocation = NULL; 245 } 246 } 247 248 fHeader = new(std::nothrow) BMessage::message_header(); 249 if (fHeader == NULL) 250 return B_NO_MEMORY; 251 error = valueLoader->LoadRawValue(headerAddress, sizeof( 252 BMessage::message_header), fHeader); 253 TRACE_LOCALS("BMessage: Header Address: 0x%" B_PRIx64 ", result: %s\n", 254 headerAddress.ToUInt64(), strerror(error)); 255 if (error != B_OK) 256 return error; 257 258 if (fHeader->format != MESSAGE_FORMAT_HAIKU 259 || (fHeader->flags & MESSAGE_FLAG_VALID) == 0) 260 return B_NOT_A_MESSAGE; 261 262 if (fIsFlatMessage) 263 what.SetTo(fHeader->what); 264 else 265 fHeader->what = what.ToUInt32(); 266 267 TRACE_LOCALS("BMessage: what: 0x%" B_PRIx32 ", result: %s\n", 268 what.ToUInt32(), strerror(error)); 269 270 size_t fieldsSize = fHeader->field_count * sizeof( 271 BMessage::field_header); 272 if (fIsFlatMessage) 273 fDataLocation.SetTo(fieldAddress.ToUInt64() + fieldsSize); 274 275 size_t totalSize = sizeof(BMessage::message_header) + fieldsSize 276 + fHeader->data_size; 277 uint8* messageBuffer = new(std::nothrow) uint8[totalSize]; 278 if (messageBuffer == NULL) 279 return B_NO_MEMORY; 280 281 ArrayDeleter<uint8> deleter(messageBuffer); 282 283 memset(messageBuffer, 0, totalSize); 284 memcpy(messageBuffer, fHeader, sizeof(BMessage::message_header)); 285 uint8* tempBuffer = messageBuffer + sizeof(BMessage::message_header); 286 if (fieldsSize > 0) { 287 fFields = new(std::nothrow) 288 BMessage::field_header[fHeader->field_count]; 289 if (fFields == NULL) 290 return B_NO_MEMORY; 291 292 error = valueLoader->LoadRawValue(fieldAddress, fieldsSize, 293 fFields); 294 TRACE_LOCALS("BMessage: Field Header Address: 0x%" B_PRIx64 295 ", result: %s\n", headerAddress.ToUInt64(), strerror(error)); 296 if (error != B_OK) 297 return error; 298 299 fData = new(std::nothrow) uint8[fHeader->data_size]; 300 if (fData == NULL) 301 return B_NO_MEMORY; 302 303 error = valueLoader->LoadRawValue(fDataLocation, fHeader->data_size, 304 fData); 305 TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64 306 ", result: %s\n", fDataLocation.ToUInt64(), strerror(error)); 307 if (error != B_OK) 308 return error; 309 memcpy(tempBuffer, fFields, fieldsSize); 310 tempBuffer += fieldsSize; 311 memcpy(tempBuffer, fData, fHeader->data_size); 312 } 313 314 error = fMessage.Unflatten((const char*)messageBuffer); 315 if (error != B_OK) 316 return error; 317 318 location->AcquireReference(); 319 _location = location; 320 _value = NULL; 321 322 return B_OK; 323 } 324 325 326 status_t 327 BMessageValueNode::CreateChildren(TeamTypeInformation* info) 328 { 329 DataMember* member = NULL; 330 CompoundType* messageType = dynamic_cast<CompoundType*>(fType); 331 for (int32 i = 0; i < messageType->CountDataMembers(); i++) { 332 member = messageType->DataMemberAt(i); 333 if (strcmp(member->Name(), "what") == 0) { 334 ValueNodeChild* whatNode 335 = new(std::nothrow) BMessageWhatNodeChild(this, member, 336 member->GetType()); 337 if (whatNode == NULL) 338 return B_NO_MEMORY; 339 340 whatNode->SetContainer(fContainer); 341 fChildren.AddItem(whatNode); 342 break; 343 } 344 } 345 346 char* name; 347 type_code type; 348 int32 count; 349 Type* fieldType = NULL; 350 BReference<Type> typeRef; 351 for (int32 i = 0; fMessage.GetInfo(B_ANY_TYPE, i, &name, &type, 352 &count) == B_OK; i++) { 353 fieldType = NULL; 354 355 _GetTypeForTypeCode(info, type, fieldType); 356 if (fieldType != NULL) 357 typeRef.SetTo(fieldType, true); 358 359 BMessageFieldNodeChild* node = new(std::nothrow) 360 BMessageFieldNodeChild(this, 361 fieldType != NULL ? fieldType : fType, name, type, 362 count); 363 if (node == NULL) 364 return B_NO_MEMORY; 365 366 node->SetContainer(fContainer); 367 fChildren.AddItem(node); 368 } 369 370 fChildrenCreated = true; 371 372 if (fContainer != NULL) 373 fContainer->NotifyValueNodeChildrenCreated(this); 374 375 return B_OK; 376 } 377 378 379 int32 380 BMessageValueNode::CountChildren() const 381 { 382 return fChildren.CountItems(); 383 } 384 385 386 ValueNodeChild* 387 BMessageValueNode::ChildAt(int32 index) const 388 { 389 return fChildren.ItemAt(index); 390 } 391 392 393 status_t 394 BMessageValueNode::_GetTypeForTypeCode(TeamTypeInformation* info, 395 type_code type, Type*& _type) 396 { 397 BString typeName; 398 TypeLookupConstraints constraints; 399 400 switch(type) { 401 case B_BOOL_TYPE: 402 typeName = "bool"; 403 constraints.SetTypeKind(TYPE_PRIMITIVE); 404 break; 405 406 case B_INT8_TYPE: 407 typeName = "int8"; 408 constraints.SetTypeKind(TYPE_TYPEDEF); 409 break; 410 411 case B_UINT8_TYPE: 412 typeName = "uint8"; 413 constraints.SetTypeKind(TYPE_TYPEDEF); 414 break; 415 416 case B_INT16_TYPE: 417 typeName = "int16"; 418 constraints.SetTypeKind(TYPE_TYPEDEF); 419 break; 420 421 case B_UINT16_TYPE: 422 typeName = "uint16"; 423 constraints.SetTypeKind(TYPE_TYPEDEF); 424 break; 425 426 case B_INT32_TYPE: 427 typeName = "int32"; 428 constraints.SetTypeKind(TYPE_TYPEDEF); 429 break; 430 431 case B_UINT32_TYPE: 432 typeName = "uint32"; 433 constraints.SetTypeKind(TYPE_TYPEDEF); 434 break; 435 436 case B_INT64_TYPE: 437 typeName = "int64"; 438 constraints.SetTypeKind(TYPE_TYPEDEF); 439 break; 440 441 case B_UINT64_TYPE: 442 typeName = "uint64"; 443 constraints.SetTypeKind(TYPE_TYPEDEF); 444 break; 445 446 case B_FLOAT_TYPE: 447 typeName = "float"; 448 constraints.SetTypeKind(TYPE_PRIMITIVE); 449 break; 450 451 case B_DOUBLE_TYPE: 452 typeName = "double"; 453 constraints.SetTypeKind(TYPE_PRIMITIVE); 454 break; 455 456 case B_MESSAGE_TYPE: 457 typeName = "BMessage"; 458 constraints.SetTypeKind(TYPE_COMPOUND); 459 break; 460 461 case B_MESSENGER_TYPE: 462 typeName = "BMessenger"; 463 constraints.SetTypeKind(TYPE_COMPOUND); 464 break; 465 466 case B_POINT_TYPE: 467 typeName = "BPoint"; 468 constraints.SetTypeKind(TYPE_COMPOUND); 469 break; 470 471 case B_RECT_TYPE: 472 typeName = "BRect"; 473 constraints.SetTypeKind(TYPE_COMPOUND); 474 break; 475 476 case B_REF_TYPE: 477 typeName = "entry_ref"; 478 constraints.SetTypeKind(TYPE_COMPOUND); 479 break; 480 481 case B_NODE_REF_TYPE: 482 typeName = "node_ref"; 483 constraints.SetTypeKind(TYPE_COMPOUND); 484 break; 485 486 case B_RGB_COLOR_TYPE: 487 typeName = "rgb_color"; 488 constraints.SetTypeKind(TYPE_COMPOUND); 489 break; 490 491 case B_STRING_TYPE: 492 { 493 typeName = "char"; 494 constraints.SetTypeKind(TYPE_PRIMITIVE); 495 Type* baseType = NULL; 496 status_t result = info->LookupTypeByName(typeName, constraints, 497 baseType); 498 if (result != B_OK) 499 return result; 500 BReference<Type> typeReference(baseType, true); 501 ArrayType* arrayType; 502 result = baseType->CreateDerivedArrayType(0, kMaxStringSize, true, 503 arrayType); 504 if (result == B_OK) 505 _type = arrayType; 506 507 return result; 508 break; 509 } 510 511 case B_POINTER_TYPE: 512 default: 513 typeName = "void*"; 514 constraints.SetTypeKind(TYPE_ADDRESS); 515 break; 516 } 517 518 return info->LookupTypeByName(typeName, constraints, _type); 519 } 520 521 522 status_t 523 BMessageValueNode::_FindField(const char* name, type_code type, 524 BMessage::field_header** result) const 525 { 526 if (name == NULL) 527 return B_BAD_VALUE; 528 529 if (fHeader == NULL) 530 return B_NO_INIT; 531 532 if (fHeader->field_count == 0 || fFields == NULL || fData == NULL) 533 return B_NAME_NOT_FOUND; 534 535 uint32 hash = _HashName(name) % fHeader->hash_table_size; 536 int32 nextField = fHeader->hash_table[hash]; 537 538 while (nextField >= 0) { 539 BMessage::field_header* field = &fFields[nextField]; 540 if ((field->flags & FIELD_FLAG_VALID) == 0) 541 break; 542 543 if (strncmp((const char*)(fData + field->offset), name, 544 field->name_length) == 0) { 545 if (type != B_ANY_TYPE && field->type != type) 546 return B_BAD_TYPE; 547 548 *result = field; 549 return B_OK; 550 } 551 552 nextField = field->next_field; 553 } 554 555 return B_NAME_NOT_FOUND; 556 } 557 558 559 uint32 560 BMessageValueNode::_HashName(const char* name) const 561 { 562 char ch; 563 uint32 result = 0; 564 565 while ((ch = *name++) != 0) { 566 result = (result << 7) ^ (result >> 24); 567 result ^= ch; 568 } 569 570 result ^= result << 12; 571 return result; 572 } 573 574 575 status_t 576 BMessageValueNode::_FindDataLocation(const char* name, type_code type, 577 int32 index, ValueLocation& location) const 578 { 579 BMessage::field_header* field = NULL; 580 int32 offset = 0; 581 int32 size = 0; 582 status_t result = _FindField(name, type, &field); 583 if (result != B_OK) 584 return result; 585 586 if (index < 0 || (uint32)index >= field->count) 587 return B_BAD_INDEX; 588 589 if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) { 590 size = field->data_size / field->count; 591 offset = field->offset + field->name_length + index * size; 592 } else { 593 offset = field->offset + field->name_length; 594 uint8 *pointer = fData + field->offset + field->name_length; 595 for (int32 i = 0; i < index; i++) { 596 pointer += *(uint32*)pointer + sizeof(uint32); 597 offset += *(uint32*)pointer + sizeof(uint32); 598 } 599 600 size = *(uint32*)pointer; 601 offset += sizeof(uint32); 602 } 603 604 ValuePieceLocation piece; 605 piece.SetToMemory(fDataLocation.ToUInt64() + offset); 606 piece.SetSize(size); 607 location.Clear(); 608 location.AddPiece(piece); 609 610 return B_OK; 611 } 612 613 614 // #pragma mark - BMessageValueNode::BMessageFieldNode 615 616 617 BMessageValueNode::BMessageFieldNode::BMessageFieldNode( 618 BMessageFieldNodeChild *child, BMessageValueNode* parent, 619 const BString &name, type_code type, int32 count) 620 : 621 ValueNode(child), 622 fName(name), 623 fType(parent->GetType()), 624 fParent(parent), 625 fFieldType(type), 626 fFieldCount(count) 627 { 628 fParent->AcquireReference(); 629 fType->AcquireReference(); 630 } 631 632 633 BMessageValueNode::BMessageFieldNode::~BMessageFieldNode() 634 { 635 fParent->ReleaseReference(); 636 fType->ReleaseReference(); 637 } 638 639 640 Type* 641 BMessageValueNode::BMessageFieldNode::GetType() const 642 { 643 return fType; 644 } 645 646 647 status_t 648 BMessageValueNode::BMessageFieldNode::CreateChildren(TeamTypeInformation* info) 649 { 650 Type* type = NULL; 651 status_t error = fParent->_GetTypeForTypeCode(info, fFieldType, type); 652 if (error != B_OK) 653 return error; 654 655 BReference<Type> typeRef(type, true); 656 for (int32 i = 0; i < fFieldCount; i++) { 657 BMessageFieldNodeChild* child = new(std::nothrow) 658 BMessageFieldNodeChild(fParent, type, fName, fFieldType, 659 fFieldCount, i); 660 661 if (child == NULL) 662 return B_NO_MEMORY; 663 664 if (fContainer != NULL) 665 child->SetContainer(fContainer); 666 667 fChildren.AddItem(child); 668 } 669 670 fChildrenCreated = true; 671 672 if (fContainer != NULL) 673 fContainer->NotifyValueNodeChildrenCreated(this); 674 675 return B_OK; 676 } 677 678 679 int32 680 BMessageValueNode::BMessageFieldNode::CountChildren() const 681 { 682 return fChildren.CountItems(); 683 } 684 685 ValueNodeChild* 686 BMessageValueNode::BMessageFieldNode::ChildAt(int32 index) const 687 { 688 return fChildren.ItemAt(index); 689 } 690 691 692 status_t 693 BMessageValueNode::BMessageFieldNode::ResolvedLocationAndValue( 694 ValueLoader* loader, ValueLocation *& _location, Value*& _value) 695 { 696 _location = NULL; 697 _value = NULL; 698 699 return B_OK; 700 } 701 702 703 // #pragma mark - BMessageValueNode::BMessageFieldNodeChild 704 705 706 BMessageValueNode::BMessageFieldNodeChild::BMessageFieldNodeChild( 707 BMessageValueNode* parent, Type* nodeType, const BString &name, 708 type_code type, int32 count, int32 index) 709 : 710 ValueNodeChild(), 711 fName(name), 712 fPresentationName(name), 713 fType(nodeType), 714 fParent(parent), 715 fFieldType(type), 716 fFieldCount(count), 717 fFieldIndex(index) 718 { 719 fParent->AcquireReference(); 720 fType->AcquireReference(); 721 722 if (fFieldIndex >= 0) 723 fPresentationName.SetToFormat("[%" B_PRId32 "]", fFieldIndex); 724 } 725 726 727 BMessageValueNode::BMessageFieldNodeChild::~BMessageFieldNodeChild() 728 { 729 fParent->ReleaseReference(); 730 fType->ReleaseReference(); 731 } 732 733 734 const BString& 735 BMessageValueNode::BMessageFieldNodeChild::Name() const 736 { 737 return fPresentationName; 738 } 739 740 741 Type* 742 BMessageValueNode::BMessageFieldNodeChild::GetType() const 743 { 744 return fType; 745 } 746 747 748 ValueNode* 749 BMessageValueNode::BMessageFieldNodeChild::Parent() const 750 { 751 return fParent; 752 } 753 754 755 bool 756 BMessageValueNode::BMessageFieldNodeChild::IsInternal() const 757 { 758 return fFieldCount > 1 && fFieldIndex == -1; 759 } 760 761 762 status_t 763 BMessageValueNode::BMessageFieldNodeChild::CreateInternalNode( 764 ValueNode*& _node) 765 { 766 BMessageFieldNode* node = new(std::nothrow) 767 BMessageFieldNode(this, fParent, fName, fFieldType, fFieldCount); 768 if (node == NULL) 769 return B_NO_MEMORY; 770 771 _node = node; 772 return B_OK; 773 } 774 775 776 status_t 777 BMessageValueNode::BMessageFieldNodeChild::ResolveLocation( 778 ValueLoader* valueLoader, ValueLocation*& _location) 779 { 780 _location = new(std::nothrow)ValueLocation(); 781 782 if (_location == NULL) 783 return B_NO_MEMORY; 784 785 return fParent->_FindDataLocation(fName, fFieldType, fFieldIndex >= 0 786 ? fFieldIndex : 0, *_location); 787 } 788 789 790