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