1/* 2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2013, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8#include "DwarfTypeFactory.h" 9 10#include <algorithm> 11#include <new> 12 13#include <AutoLocker.h> 14#include <Variant.h> 15 16#include "ArrayIndexPath.h" 17#include "Architecture.h" 18#include "CompilationUnit.h" 19#include "DebugInfoEntries.h" 20#include "Dwarf.h" 21#include "DwarfFile.h" 22#include "DwarfTargetInterface.h" 23#include "DwarfUtils.h" 24#include "DwarfTypes.h" 25#include "GlobalTypeLookup.h" 26#include "Register.h" 27#include "RegisterMap.h" 28#include "SourceLanguageInfo.h" 29#include "StringUtils.h" 30#include "Tracing.h" 31#include "TypeLookupConstraints.h" 32#include "ValueLocation.h" 33 34 35namespace { 36 37 38// #pragma mark - HasTypePredicate 39 40 41template<typename EntryType> 42struct HasTypePredicate { 43 inline bool operator()(EntryType* entry) const 44 { 45 return entry->GetType() != NULL; 46 } 47}; 48 49 50// #pragma mark - HasReturnTypePredicate 51 52 53template<typename EntryType> 54struct HasReturnTypePredicate { 55 inline bool operator()(EntryType* entry) const 56 { 57 return entry->ReturnType() != NULL; 58 } 59}; 60 61 62// #pragma mark - HasEnumeratorsPredicate 63 64 65struct HasEnumeratorsPredicate { 66 inline bool operator()(DIEEnumerationType* entry) const 67 { 68 return !entry->Enumerators().IsEmpty(); 69 } 70}; 71 72 73// #pragma mark - HasDimensionsPredicate 74 75 76struct HasDimensionsPredicate { 77 inline bool operator()(DIEArrayType* entry) const 78 { 79 return !entry->Dimensions().IsEmpty(); 80 } 81}; 82 83 84// #pragma mark - HasMembersPredicate 85 86 87struct HasMembersPredicate { 88 inline bool operator()(DIECompoundType* entry) const 89 { 90 return !entry->DataMembers().IsEmpty(); 91 } 92}; 93 94 95// #pragma mark - HasBaseTypesPredicate 96 97 98struct HasBaseTypesPredicate { 99 inline bool operator()(DIEClassBaseType* entry) const 100 { 101 return !entry->BaseTypes().IsEmpty(); 102 } 103}; 104 105 106// #pragma mark - HasTemplateParametersPredicate 107 108 109struct HasTemplateParametersPredicate { 110 inline bool operator()(DIEClassBaseType* entry) const 111 { 112 return !entry->TemplateParameters().IsEmpty(); 113 } 114}; 115 116 117// #pragma mark - HasParametersPredicate 118 119 120template<typename EntryType> 121struct HasParametersPredicate { 122 inline bool operator()(EntryType* entry) const 123 { 124 return !entry->Parameters().IsEmpty(); 125 } 126}; 127 128 129// #pragma mark - HasLowerBoundPredicate 130 131 132struct HasLowerBoundPredicate { 133 inline bool operator()(DIESubrangeType* entry) const 134 { 135 return entry->LowerBound()->IsValid(); 136 } 137}; 138 139 140// #pragma mark - HasUpperBoundPredicate 141 142 143struct HasUpperBoundPredicate { 144 inline bool operator()(DIESubrangeType* entry) const 145 { 146 return entry->UpperBound()->IsValid(); 147 } 148}; 149 150 151// #pragma mark - HasCountPredicate 152 153 154struct HasCountPredicate { 155 inline bool operator()(DIESubrangeType* entry) const 156 { 157 return entry->Count()->IsValid(); 158 } 159}; 160 161 162// #pragma mark - HasContainingTypePredicate 163 164 165struct HasContainingTypePredicate { 166 inline bool operator()(DIEPointerToMemberType* entry) const 167 { 168 return entry->ContainingType() != NULL; 169 } 170}; 171 172 173} // unnamed namespace 174 175 176// #pragma mark - ArtificialIntegerType 177 178 179class DwarfTypeFactory::ArtificialIntegerType : public PrimitiveType { 180public: 181 ArtificialIntegerType(const BString& id, const BString& name, 182 target_size_t byteSize, uint32 typeConstant) 183 : 184 fID(id), 185 fName(name), 186 fByteSize(byteSize), 187 fTypeConstant(typeConstant) 188 { 189 } 190 191 static status_t Create(target_size_t byteSize, bool isSigned, Type*& _type) 192 { 193 // get the matching type constant 194 uint32 typeConstant; 195 switch (byteSize) { 196 case 1: 197 typeConstant = isSigned ? B_INT8_TYPE : B_UINT8_TYPE; 198 break; 199 case 2: 200 typeConstant = isSigned ? B_INT16_TYPE : B_UINT16_TYPE; 201 break; 202 case 4: 203 typeConstant = isSigned ? B_INT32_TYPE : B_UINT32_TYPE; 204 break; 205 case 8: 206 typeConstant = isSigned ? B_INT64_TYPE : B_UINT64_TYPE; 207 break; 208 default: 209 return B_BAD_VALUE; 210 } 211 212 // name and ID 213 char buffer[16]; 214 snprintf(buffer, sizeof(buffer), isSigned ? "int%d" : "uint%d", 215 (int)byteSize * 8); 216 BString id(buffer); 217 if (id.Length() == 0) 218 return B_NO_MEMORY; 219 220 // create the type 221 ArtificialIntegerType* type = new(std::nothrow) ArtificialIntegerType( 222 id, id, byteSize, typeConstant); 223 if (type == NULL) 224 return B_NO_MEMORY; 225 226 _type = type; 227 return B_OK; 228 } 229 230 virtual image_id ImageID() const 231 { 232 return -1; 233 } 234 235 virtual const BString& ID() const 236 { 237 return fID; 238 } 239 240 virtual const BString& Name() const 241 { 242 return fName; 243 } 244 245 virtual target_size_t ByteSize() const 246 { 247 return fByteSize; 248 } 249 250 virtual status_t ResolveObjectDataLocation( 251 const ValueLocation& objectLocation, ValueLocation*& _location) 252 { 253 // TODO: Implement! 254 return B_UNSUPPORTED; 255 } 256 257 virtual status_t ResolveObjectDataLocation(target_addr_t objectAddress, 258 ValueLocation*& _location) 259 { 260 // TODO: Implement! 261 return B_UNSUPPORTED; 262 } 263 264 virtual uint32 TypeConstant() const 265 { 266 return fTypeConstant; 267 } 268 269private: 270 BString fID; 271 BString fName; 272 uint32 fByteSize; 273 uint32 fTypeConstant; 274}; 275 276 277// #pragma mark - DwarfTypeFactory 278 279 280DwarfTypeFactory::DwarfTypeFactory(DwarfTypeContext* typeContext, 281 GlobalTypeLookup* typeLookup, GlobalTypeCache* typeCache) 282 : 283 fTypeContext(typeContext), 284 fTypeLookup(typeLookup), 285 fTypeCache(typeCache) 286{ 287 fTypeContext->AcquireReference(); 288 fTypeCache->AcquireReference(); 289} 290 291 292DwarfTypeFactory::~DwarfTypeFactory() 293{ 294 fTypeContext->ReleaseReference(); 295 fTypeCache->ReleaseReference(); 296} 297 298 299status_t 300DwarfTypeFactory::CreateType(DIEType* typeEntry, DwarfType*& _type) 301{ 302 // try the type cache first 303 BString name; 304 DwarfUtils::GetFullyQualifiedDIEName(typeEntry, name); 305 306 TypeLookupConstraints constraints( 307 dwarf_tag_to_type_kind(typeEntry->Tag())); 308 int32 subtypeKind = dwarf_tag_to_subtype_kind(typeEntry->Tag()); 309 if (subtypeKind >= 0) 310 constraints.SetSubtypeKind(subtypeKind); 311 312 AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache); 313 Type* globalType = name.Length() > 0 314 ? fTypeCache->GetType(name, constraints) : NULL; 315 if (globalType == NULL) { 316 // lookup by name failed -- try lookup by ID 317 BString id; 318 if (DwarfType::GetTypeID(typeEntry, id)) 319 globalType = fTypeCache->GetTypeByID(id); 320 } 321 322 if (globalType != NULL) { 323 DwarfType* globalDwarfType = dynamic_cast<DwarfType*>(globalType); 324 if (globalDwarfType != NULL) { 325 globalDwarfType->AcquireReference(); 326 _type = globalDwarfType; 327 return B_OK; 328 } 329 } 330 331 cacheLocker.Unlock(); 332 333 // If the type entry indicates a declaration only, we try to look the 334 // type up globally first. 335 if (typeEntry->IsDeclaration() && name.Length() > 0 336 && fTypeLookup->GetType(fTypeCache, name, 337 constraints, globalType) 338 == B_OK) { 339 DwarfType* globalDwarfType 340 = dynamic_cast<DwarfType*>(globalType); 341 if (globalDwarfType != NULL) { 342 _type = globalDwarfType; 343 return B_OK; 344 } 345 346 globalType->ReleaseReference(); 347 } 348 349 // No luck yet -- create the type. 350 DwarfType* type; 351 status_t error = _CreateTypeInternal(name, typeEntry, type); 352 if (error != B_OK) 353 return error; 354 BReference<DwarfType> typeReference(type, true); 355 356 // Insert the type into the cache. Re-check, as the type may already 357 // have been inserted (e.g. in the compound type case). 358 cacheLocker.Lock(); 359 if (name.Length() > 0 360 ? fTypeCache->GetType(name, constraints) == NULL 361 : fTypeCache->GetTypeByID(type->ID()) == NULL) { 362 error = fTypeCache->AddType(type); 363 if (error != B_OK) 364 return error; 365 } 366 cacheLocker.Unlock(); 367 368 // try to get the type's size 369 uint64 size; 370 if (_ResolveTypeByteSize(typeEntry, size) == B_OK) 371 type->SetByteSize(size); 372 373 _type = typeReference.Detach(); 374 return B_OK; 375} 376 377 378status_t 379DwarfTypeFactory::_CreateTypeInternal(const BString& name, 380 DIEType* typeEntry, DwarfType*& _type) 381{ 382 switch (typeEntry->Tag()) { 383 case DW_TAG_class_type: 384 case DW_TAG_structure_type: 385 case DW_TAG_union_type: 386 case DW_TAG_interface_type: 387 return _CreateCompoundType(name, 388 dynamic_cast<DIECompoundType*>(typeEntry), 389 (compound_type_kind)dwarf_tag_to_subtype_kind( 390 typeEntry->Tag()), _type); 391 392 case DW_TAG_base_type: 393 return _CreatePrimitiveType(name, 394 dynamic_cast<DIEBaseType*>(typeEntry), _type); 395 396 case DW_TAG_pointer_type: 397 return _CreateAddressType(name, 398 dynamic_cast<DIEAddressingType*>(typeEntry), 399 DERIVED_TYPE_POINTER, _type); 400 case DW_TAG_reference_type: 401 return _CreateAddressType(name, 402 dynamic_cast<DIEAddressingType*>(typeEntry), 403 DERIVED_TYPE_REFERENCE, _type); 404 405 case DW_TAG_const_type: 406 return _CreateModifiedType(name, 407 dynamic_cast<DIEModifiedType*>(typeEntry), 408 TYPE_MODIFIER_CONST, _type); 409 case DW_TAG_packed_type: 410 return _CreateModifiedType(name, 411 dynamic_cast<DIEModifiedType*>(typeEntry), 412 TYPE_MODIFIER_PACKED, _type); 413 case DW_TAG_volatile_type: 414 return _CreateModifiedType(name, 415 dynamic_cast<DIEModifiedType*>(typeEntry), 416 TYPE_MODIFIER_VOLATILE, _type); 417 case DW_TAG_restrict_type: 418 return _CreateModifiedType(name, 419 dynamic_cast<DIEModifiedType*>(typeEntry), 420 TYPE_MODIFIER_RESTRICT, _type); 421 case DW_TAG_shared_type: 422 return _CreateModifiedType(name, 423 dynamic_cast<DIEModifiedType*>(typeEntry), 424 TYPE_MODIFIER_SHARED, _type); 425 426 case DW_TAG_typedef: 427 return _CreateTypedefType(name, 428 dynamic_cast<DIETypedef*>(typeEntry), _type); 429 430 case DW_TAG_array_type: 431 return _CreateArrayType(name, 432 dynamic_cast<DIEArrayType*>(typeEntry), _type); 433 434 case DW_TAG_enumeration_type: 435 return _CreateEnumerationType(name, 436 dynamic_cast<DIEEnumerationType*>(typeEntry), _type); 437 438 case DW_TAG_subrange_type: 439 return _CreateSubrangeType(name, 440 dynamic_cast<DIESubrangeType*>(typeEntry), _type); 441 442 case DW_TAG_unspecified_type: 443 return _CreateUnspecifiedType(name, 444 dynamic_cast<DIEUnspecifiedType*>(typeEntry), _type); 445 446 case DW_TAG_subroutine_type: 447 return _CreateFunctionType(name, 448 dynamic_cast<DIESubroutineType*>(typeEntry), _type); 449 450 case DW_TAG_ptr_to_member_type: 451 return _CreatePointerToMemberType(name, 452 dynamic_cast<DIEPointerToMemberType*>(typeEntry), _type); 453 454 case DW_TAG_string_type: 455 case DW_TAG_file_type: 456 case DW_TAG_set_type: 457 // TODO: Implement (not relevant for C++)! 458 return B_UNSUPPORTED; 459 } 460 461 return B_UNSUPPORTED; 462} 463 464 465status_t 466DwarfTypeFactory::_CreateCompoundType(const BString& name, 467 DIECompoundType* typeEntry, compound_type_kind compoundKind, DwarfType*& _type) 468{ 469 TRACE_LOCALS("DwarfTypeFactory::_CreateCompoundType(\"%s\", %p, %d)\n", 470 name.String(), typeEntry, compoundKind); 471 472 // create the type 473 DwarfCompoundType* type = new(std::nothrow) DwarfCompoundType(fTypeContext, 474 name, typeEntry, compoundKind); 475 if (type == NULL) 476 return B_NO_MEMORY; 477 BReference<DwarfCompoundType> typeReference(type, true); 478 479 // Already add the type at this pointer to the cache, since otherwise 480 // we could run into an infinite recursion when trying to create the types 481 // for the data members. 482// TODO: Since access to the type lookup context is multi-threaded, the 483// incomplete type could become visible to other threads. Hence we keep the 484// context locked, but that essentially kills multi-threading for this context. 485 AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache); 486 status_t error = fTypeCache->AddType(type); 487 if (error != B_OK) 488{ 489printf(" -> failed to add type to cache\n"); 490 return error; 491} 492// cacheLocker.Unlock(); 493 494 // find the abstract origin or specification that defines the data members 495 DIECompoundType* memberOwnerEntry = DwarfUtils::GetDIEByPredicate(typeEntry, 496 HasMembersPredicate()); 497 498 // create the data member objects 499 if (memberOwnerEntry != NULL) { 500 for (DebugInfoEntryList::ConstIterator it 501 = memberOwnerEntry->DataMembers().GetIterator(); 502 DebugInfoEntry* _memberEntry = it.Next();) { 503 DIEMember* memberEntry = dynamic_cast<DIEMember*>(_memberEntry); 504 505 TRACE_LOCALS(" member %p\n", memberEntry); 506 507 // get the type 508 DwarfType* memberType; 509 if (CreateType(memberEntry->GetType(), memberType) != B_OK) 510 continue; 511 BReference<DwarfType> memberTypeReference(memberType, true); 512 513 // get the name 514 BString memberName; 515 DwarfUtils::GetDIEName(memberEntry, memberName); 516 517 // create and add the member object 518 DwarfDataMember* member = new(std::nothrow) DwarfDataMember( 519 memberEntry, memberName, memberType); 520 BReference<DwarfDataMember> memberReference(member, true); 521 if (member == NULL || !type->AddDataMember(member)) { 522 cacheLocker.Lock(); 523 fTypeCache->RemoveType(type); 524 return B_NO_MEMORY; 525 } 526 } 527 } 528 529 // If the type is a class/struct/interface type, we also need to add its 530 // base types, and possibly template parameters. 531 if (DIEClassBaseType* classTypeEntry 532 = dynamic_cast<DIEClassBaseType*>(typeEntry)) { 533 // find the abstract origin or specification that defines the base types 534 classTypeEntry = DwarfUtils::GetDIEByPredicate(classTypeEntry, 535 HasBaseTypesPredicate()); 536 537 // create the inheritance objects for the base types 538 if (classTypeEntry != NULL) { 539 for (DebugInfoEntryList::ConstIterator it 540 = classTypeEntry->BaseTypes().GetIterator(); 541 DebugInfoEntry* _inheritanceEntry = it.Next();) { 542 DIEInheritance* inheritanceEntry 543 = dynamic_cast<DIEInheritance*>(_inheritanceEntry); 544 545 // get the type 546 DwarfType* baseType; 547 if (CreateType(inheritanceEntry->GetType(), baseType) != B_OK) 548 continue; 549 BReference<DwarfType> baseTypeReference(baseType, true); 550 551 // create and add the inheritance object 552 DwarfInheritance* inheritance = new(std::nothrow) 553 DwarfInheritance(inheritanceEntry, baseType); 554 BReference<DwarfInheritance> inheritanceReference(inheritance, 555 true); 556 if (inheritance == NULL || !type->AddInheritance(inheritance)) { 557 cacheLocker.Lock(); 558 fTypeCache->RemoveType(type); 559 return B_NO_MEMORY; 560 } 561 } 562 } 563 564 // find the abstract origin or specification that defines the template 565 // parameters 566 classTypeEntry = DwarfUtils::GetDIEByPredicate( 567 dynamic_cast<DIEClassBaseType*>(typeEntry), 568 HasTemplateParametersPredicate()); 569 570 if (classTypeEntry != NULL) { 571 for (DebugInfoEntryList::ConstIterator it 572 = classTypeEntry->TemplateParameters() 573 .GetIterator(); 574 DebugInfoEntry* _typeEntry = it.Next();) { 575 DIETemplateTypeParameter* templateTypeEntry 576 = dynamic_cast<DIETemplateTypeParameter*>(_typeEntry); 577 DwarfType* templateType; 578 if (templateTypeEntry != NULL) { 579 if (templateTypeEntry->GetType() == NULL 580 || CreateType(templateTypeEntry->GetType(), 581 templateType) != B_OK) { 582 continue; 583 } 584 } else { 585 DIETemplateValueParameter* templateValueEntry 586 = dynamic_cast<DIETemplateValueParameter*>(_typeEntry); 587 if (CreateType(templateValueEntry->GetType(), templateType) 588 != B_OK) { 589 continue; 590 } 591 } 592 BReference<DwarfType> templateTypeReference(templateType, 593 true); 594 DwarfTemplateParameter* parameter 595 = new(std::nothrow) DwarfTemplateParameter(_typeEntry, 596 templateType); 597 if (parameter == NULL) { 598 cacheLocker.Lock(); 599 fTypeCache->RemoveType(type); 600 return B_NO_MEMORY; 601 } 602 603 if (!type->AddTemplateParameter(parameter)) { 604 cacheLocker.Lock(); 605 fTypeCache->RemoveType(type); 606 return B_NO_MEMORY; 607 } 608 } 609 } 610 } 611 612 _type = typeReference.Detach(); 613 return B_OK;; 614} 615 616 617status_t 618DwarfTypeFactory::_CreatePrimitiveType(const BString& name, 619 DIEBaseType* typeEntry, DwarfType*& _type) 620{ 621 const DynamicAttributeValue* byteSizeValue = typeEntry->ByteSize(); 622// const DynamicAttributeValue* bitOffsetValue = typeEntry->BitOffset(); 623 const DynamicAttributeValue* bitSizeValue = typeEntry->BitSize(); 624 625 uint32 bitSize = 0; 626 if (byteSizeValue->IsValid()) { 627 BVariant value; 628 status_t error = fTypeContext->File()->EvaluateDynamicValue( 629 fTypeContext->GetCompilationUnit(), 630 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(), 631 fTypeContext->SubprogramEntry(), byteSizeValue, 632 fTypeContext->TargetInterface(), 633 fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), 634 value); 635 if (error == B_OK && value.IsInteger()) 636 bitSize = value.ToUInt32() * 8; 637 } else if (bitSizeValue->IsValid()) { 638 BVariant value; 639 status_t error = fTypeContext->File()->EvaluateDynamicValue( 640 fTypeContext->GetCompilationUnit(), 641 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(), 642 fTypeContext->SubprogramEntry(), bitSizeValue, 643 fTypeContext->TargetInterface(), 644 fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), 645 value); 646 if (error == B_OK && value.IsInteger()) 647 bitSize = value.ToUInt32(); 648 } 649 650 // determine type constant 651 uint32 typeConstant = 0; 652 switch (typeEntry->Encoding()) { 653 case DW_ATE_boolean: 654 typeConstant = B_BOOL_TYPE; 655 break; 656 657 case DW_ATE_float: 658 switch (bitSize) { 659 case 32: 660 typeConstant = B_FLOAT_TYPE; 661 break; 662 case 64: 663 typeConstant = B_DOUBLE_TYPE; 664 break; 665 } 666 break; 667 668 case DW_ATE_signed: 669 case DW_ATE_signed_char: 670 switch (bitSize) { 671 case 8: 672 typeConstant = B_INT8_TYPE; 673 break; 674 case 16: 675 typeConstant = B_INT16_TYPE; 676 break; 677 case 32: 678 typeConstant = B_INT32_TYPE; 679 break; 680 case 64: 681 typeConstant = B_INT64_TYPE; 682 break; 683 } 684 break; 685 686 case DW_ATE_address: 687 case DW_ATE_unsigned: 688 case DW_ATE_unsigned_char: 689 switch (bitSize) { 690 case 8: 691 typeConstant = B_UINT8_TYPE; 692 break; 693 case 16: 694 typeConstant = B_UINT16_TYPE; 695 break; 696 case 32: 697 typeConstant = B_UINT32_TYPE; 698 break; 699 case 64: 700 typeConstant = B_UINT64_TYPE; 701 break; 702 } 703 break; 704 705 case DW_ATE_complex_float: 706 case DW_ATE_imaginary_float: 707 case DW_ATE_packed_decimal: 708 case DW_ATE_numeric_string: 709 case DW_ATE_edited: 710 case DW_ATE_signed_fixed: 711 case DW_ATE_unsigned_fixed: 712 case DW_ATE_decimal_float: 713 default: 714 break; 715 } 716 717 // create the type 718 DwarfPrimitiveType* type = new(std::nothrow) DwarfPrimitiveType( 719 fTypeContext, name, typeEntry, typeConstant); 720 if (type == NULL) 721 return B_NO_MEMORY; 722 723 _type = type; 724 return B_OK; 725} 726 727 728status_t 729DwarfTypeFactory::_CreateAddressType(const BString& name, 730 DIEAddressingType* typeEntry, address_type_kind addressKind, 731 DwarfType*& _type) 732{ 733 // get the base type entry 734 DIEAddressingType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 735 typeEntry, HasTypePredicate<DIEAddressingType>()); 736 737 // create the base type 738 DwarfType* baseType; 739 if (baseTypeOwnerEntry != NULL) { 740 status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType); 741 if (error != B_OK) 742 return error; 743 } else { 744 // According to the DWARF 3 specs a modified type *has* a base type. 745 // GCC 4 doesn't (always?) bother to add one for "void". 746 // TODO: We should probably search for a respective type by name. ATM 747 // we just create a DwarfUnspecifiedType without DIE. 748 TRACE_LOCALS("no base type for address type entry -- creating " 749 "unspecified type\n"); 750 baseType = new(std::nothrow) DwarfUnspecifiedType(fTypeContext, "void", 751 NULL); 752 if (baseType == NULL) 753 return B_NO_MEMORY; 754 } 755 BReference<Type> baseTypeReference(baseType, true); 756 757 DwarfAddressType* type = new(std::nothrow) DwarfAddressType(fTypeContext, 758 name, typeEntry, addressKind, baseType); 759 if (type == NULL) 760 return B_NO_MEMORY; 761 762 _type = type; 763 return B_OK; 764} 765 766 767status_t 768DwarfTypeFactory::_CreateModifiedType(const BString& name, 769 DIEModifiedType* typeEntry, uint32 modifiers, DwarfType*& _type) 770{ 771 // Get the base type entry. If it is a modified type too or a typedef, 772 // collect all modifiers and iterate until hitting an actual base type. 773 DIEType* baseTypeEntry = NULL; 774 DwarfType* baseType = NULL; 775 while (true) { 776 DIEModifiedType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 777 typeEntry, HasTypePredicate<DIEModifiedType>()); 778 if (baseTypeOwnerEntry == NULL) { 779 if (typeEntry->GetType() == NULL) { 780 // in the case of a modified type that points to an 781 // unspecified type (i.e. const void* in C/C++), 782 // gcc appears to omit the base type attribute entirely. 783 status_t result = _CreateUnspecifiedType(name, 784 NULL, baseType); 785 if (result != B_OK) 786 return result; 787 break; 788 } else 789 return B_BAD_VALUE; 790 } else 791 baseTypeEntry = baseTypeOwnerEntry->GetType(); 792 793 // resolve a typedef 794 if (baseTypeEntry->Tag() == DW_TAG_typedef) { 795 status_t error = _ResolveTypedef( 796 dynamic_cast<DIETypedef*>(baseTypeEntry), baseTypeEntry); 797 if (error != B_OK) 798 return error; 799 } 800 801 if (baseTypeEntry == NULL) 802 return B_BAD_VALUE; 803 804 // If the base type is a modified type, too, resolve it. 805 switch (baseTypeEntry->Tag()) { 806 case DW_TAG_const_type: 807 modifiers |= TYPE_MODIFIER_CONST; 808 baseTypeOwnerEntry 809 = dynamic_cast<DIEModifiedType*>(baseTypeEntry); 810 continue; 811 case DW_TAG_packed_type: 812 modifiers |= TYPE_MODIFIER_PACKED; 813 baseTypeOwnerEntry 814 = dynamic_cast<DIEModifiedType*>(baseTypeEntry); 815 continue; 816 case DW_TAG_volatile_type: 817 modifiers |= TYPE_MODIFIER_VOLATILE; 818 baseTypeOwnerEntry 819 = dynamic_cast<DIEModifiedType*>(baseTypeEntry); 820 continue; 821 case DW_TAG_restrict_type: 822 modifiers |= TYPE_MODIFIER_RESTRICT; 823 baseTypeOwnerEntry 824 = dynamic_cast<DIEModifiedType*>(baseTypeEntry); 825 continue; 826 case DW_TAG_shared_type: 827 modifiers |= TYPE_MODIFIER_SHARED; 828 baseTypeOwnerEntry 829 = dynamic_cast<DIEModifiedType*>(baseTypeEntry); 830 continue; 831 832 default: 833 break; 834 } 835 836 // If we get here, we've found an actual base type. 837 break; 838 } 839 840 if (baseType == NULL) { 841 // create the base type 842 status_t error = CreateType(baseTypeEntry, baseType); 843 if (error != B_OK) 844 return error; 845 } 846 847 BReference<Type> baseTypeReference(baseType, true); 848 849 DwarfModifiedType* type = new(std::nothrow) DwarfModifiedType(fTypeContext, 850 name, typeEntry, modifiers, baseType); 851 if (type == NULL) 852 return B_NO_MEMORY; 853 854 _type = type; 855 return B_OK; 856} 857 858 859status_t 860DwarfTypeFactory::_CreateTypedefType(const BString& name, 861 DIETypedef* typeEntry, DwarfType*& _type) 862{ 863 // resolve the base type 864 DIEType* baseTypeEntry; 865 status_t error = _ResolveTypedef(typeEntry, baseTypeEntry); 866 if (error != B_OK) 867 return error; 868 869 // create the base type 870 DwarfType* baseType; 871 error = CreateType(baseTypeEntry, baseType); 872 if (error != B_OK) 873 return error; 874 BReference<Type> baseTypeReference(baseType, true); 875 876 DwarfTypedefType* type = new(std::nothrow) DwarfTypedefType(fTypeContext, 877 name, typeEntry, baseType); 878 if (type == NULL) 879 return B_NO_MEMORY; 880 881 _type = type; 882 return B_OK; 883} 884 885 886status_t 887DwarfTypeFactory::_CreateArrayType(const BString& name, 888 DIEArrayType* typeEntry, DwarfType*& _type) 889{ 890 TRACE_LOCALS("DwarfTypeFactory::_CreateArrayType(\"%s\", %p)\n", 891 name.String(), typeEntry); 892 893 // create the base type 894 DIEArrayType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 895 typeEntry, HasTypePredicate<DIEArrayType>()); 896 if (baseTypeOwnerEntry == NULL) { 897 WARNING("Failed to get base type for array type \"%s\"\n", 898 name.String()); 899 return B_BAD_VALUE; 900 } 901 902 DwarfType* baseType = NULL; 903 status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType); 904 if (error != B_OK) { 905 WARNING("Failed to create base type for array type \"%s\": %s\n", 906 name.String(), strerror(error)); 907 return error; 908 } 909 BReference<Type> baseTypeReference(baseType, true); 910 911 // create the array type 912 DwarfArrayType* type = new(std::nothrow) DwarfArrayType(fTypeContext, name, 913 typeEntry, baseType); 914 if (type == NULL) 915 return B_NO_MEMORY; 916 BReference<DwarfType> typeReference(type, true); 917 918 // add the array dimensions 919 DIEArrayType* dimensionOwnerEntry = DwarfUtils::GetDIEByPredicate( 920 typeEntry, HasDimensionsPredicate()); 921 922 if (dimensionOwnerEntry == NULL) { 923 WARNING("Failed to get dimensions for array type \"%s\"\n", 924 name.String()); 925 return B_BAD_VALUE; 926 } 927 928 for (DebugInfoEntryList::ConstIterator it 929 = dimensionOwnerEntry->Dimensions().GetIterator(); 930 DebugInfoEntry* _dimensionEntry = it.Next();) { 931 DIEType* dimensionEntry = dynamic_cast<DIEType*>(_dimensionEntry); 932 933 // get/create the dimension type 934 DwarfType* dimensionType = NULL; 935 status_t error = CreateType(dimensionEntry, dimensionType); 936 if (error != B_OK) { 937 WARNING("Failed to create type for array dimension: %s\n", 938 strerror(error)); 939 return error; 940 } 941 BReference<Type> dimensionTypeReference(dimensionType, true); 942 943 // create and add the array dimension object 944 DwarfArrayDimension* dimension 945 = new(std::nothrow) DwarfArrayDimension(dimensionType); 946 BReference<DwarfArrayDimension> dimensionReference(dimension, true); 947 if (dimension == NULL || !type->AddDimension(dimension)) 948 return B_NO_MEMORY; 949 } 950 951 _type = typeReference.Detach(); 952 return B_OK; 953} 954 955 956status_t 957DwarfTypeFactory::_CreateEnumerationType(const BString& name, 958 DIEEnumerationType* typeEntry, DwarfType*& _type) 959{ 960 // create the base type (it's optional) 961 DIEEnumerationType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 962 typeEntry, HasTypePredicate<DIEEnumerationType>()); 963 964 DwarfType* baseType = NULL; 965 if (baseTypeOwnerEntry != NULL) { 966 status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType); 967 if (error != B_OK) 968 return error; 969 } 970 BReference<Type> baseTypeReference(baseType, true); 971 972 // create the enumeration type 973 DwarfEnumerationType* type = new(std::nothrow) DwarfEnumerationType( 974 fTypeContext, name, typeEntry, baseType); 975 if (type == NULL) 976 return B_NO_MEMORY; 977 BReference<DwarfEnumerationType> typeReference(type, true); 978 979 // get the enumeration values 980 DIEEnumerationType* enumeratorOwnerEntry = DwarfUtils::GetDIEByPredicate( 981 typeEntry, HasEnumeratorsPredicate()); 982 983 if (enumeratorOwnerEntry != NULL) { 984 for (DebugInfoEntryList::ConstIterator it 985 = enumeratorOwnerEntry->Enumerators().GetIterator(); 986 DebugInfoEntry* _enumeratorEntry = it.Next();) { 987 DIEEnumerator* enumeratorEntry = dynamic_cast<DIEEnumerator*>( 988 _enumeratorEntry); 989 990 // evaluate the value 991 BVariant value; 992 status_t error = fTypeContext->File()->EvaluateConstantValue( 993 fTypeContext->GetCompilationUnit(), 994 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(), 995 fTypeContext->SubprogramEntry(), enumeratorEntry->ConstValue(), 996 fTypeContext->TargetInterface(), 997 fTypeContext->InstructionPointer(), 998 fTypeContext->FramePointer(), value); 999 if (error != B_OK) { 1000 // The value is probably not stored -- just ignore the 1001 // enumerator. 1002 TRACE_LOCALS("Failed to get value for enum type value %s::%s\n", 1003 name.String(), enumeratorEntry->Name()); 1004 continue; 1005 } 1006 1007 // create and add the enumeration value object 1008 DwarfEnumeratorValue* enumValue 1009 = new(std::nothrow) DwarfEnumeratorValue(enumeratorEntry, 1010 enumeratorEntry->Name(), value); 1011 BReference<DwarfEnumeratorValue> enumValueReference(enumValue, 1012 true); 1013 if (enumValue == NULL || !type->AddValue(enumValue)) 1014 return B_NO_MEMORY; 1015 } 1016 } 1017 1018 _type = typeReference.Detach(); 1019 return B_OK; 1020} 1021 1022 1023status_t 1024DwarfTypeFactory::_CreateSubrangeType(const BString& name, 1025 DIESubrangeType* typeEntry, DwarfType*& _type) 1026{ 1027 // get the base type 1028 DIESubrangeType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1029 typeEntry, HasTypePredicate<DIESubrangeType>()); 1030 DIEType* baseTypeEntry = baseTypeOwnerEntry != NULL 1031 ? baseTypeOwnerEntry->GetType() : NULL; 1032 1033 // get the lower bound 1034 BVariant lowerBound; 1035 DIESubrangeType* lowerBoundOwnerEntry = DwarfUtils::GetDIEByPredicate( 1036 typeEntry, HasLowerBoundPredicate()); 1037 if (lowerBoundOwnerEntry != NULL) { 1038 // evaluate it 1039 DIEType* valueType; 1040 status_t error = fTypeContext->File()->EvaluateDynamicValue( 1041 fTypeContext->GetCompilationUnit(), 1042 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(), 1043 fTypeContext->SubprogramEntry(), 1044 lowerBoundOwnerEntry->LowerBound(), 1045 fTypeContext->TargetInterface(), 1046 fTypeContext->InstructionPointer(), 1047 fTypeContext->FramePointer(), lowerBound, &valueType); 1048 if (error != B_OK) { 1049 WARNING(" failed to evaluate lower bound: %s\n", strerror(error)); 1050 return error; 1051 } 1052 1053 // If we don't have a base type yet, and the lower bound attribute 1054 // refers to an object, the type of that object is our base type. 1055 if (baseTypeEntry == NULL) 1056 baseTypeEntry = valueType; 1057 } else { 1058 // that's ok -- use the language default 1059 lowerBound.SetTo(fTypeContext->GetCompilationUnit()->SourceLanguage() 1060 ->subrangeLowerBound); 1061 } 1062 1063 // get the upper bound 1064 BVariant upperBound; 1065 DIESubrangeType* upperBoundOwnerEntry = DwarfUtils::GetDIEByPredicate( 1066 typeEntry, HasUpperBoundPredicate()); 1067 if (upperBoundOwnerEntry != NULL) { 1068 // evaluate it 1069 DIEType* valueType; 1070 status_t error = fTypeContext->File()->EvaluateDynamicValue( 1071 fTypeContext->GetCompilationUnit(), 1072 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(), 1073 fTypeContext->SubprogramEntry(), 1074 upperBoundOwnerEntry->UpperBound(), 1075 fTypeContext->TargetInterface(), 1076 fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), 1077 upperBound, &valueType); 1078 if (error != B_OK) { 1079 WARNING(" failed to evaluate upper bound: %s\n", strerror(error)); 1080 return error; 1081 } 1082 1083 // If we don't have a base type yet, and the upper bound attribute 1084 // refers to an object, the type of that object is our base type. 1085 if (baseTypeEntry == NULL) 1086 baseTypeEntry = valueType; 1087 } else { 1088 // get the count instead 1089 DIESubrangeType* countOwnerEntry = DwarfUtils::GetDIEByPredicate( 1090 typeEntry, HasCountPredicate()); 1091 if (countOwnerEntry != NULL) { 1092 // evaluate it 1093 BVariant count; 1094 DIEType* valueType; 1095 status_t error = fTypeContext->File()->EvaluateDynamicValue( 1096 fTypeContext->GetCompilationUnit(), 1097 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(), 1098 fTypeContext->SubprogramEntry(), 1099 countOwnerEntry->Count(), fTypeContext->TargetInterface(), 1100 fTypeContext->InstructionPointer(), 1101 fTypeContext->FramePointer(), count, &valueType); 1102 if (error != B_OK) { 1103 WARNING(" failed to evaluate count: %s\n", strerror(error)); 1104 return error; 1105 } 1106 1107 // If we don't have a base type yet, and the count attribute refers 1108 // to an object, the type of that object is our base type. 1109 if (baseTypeEntry == NULL) 1110 baseTypeEntry = valueType; 1111 1112 // we only support integers 1113 bool isSigned; 1114 if (!lowerBound.IsInteger(&isSigned) || !count.IsInteger()) { 1115 WARNING(" count given for subrange type, but lower bound or " 1116 "count is not integer\n"); 1117 return B_BAD_VALUE; 1118 } 1119 1120 if (isSigned) 1121 upperBound.SetTo(lowerBound.ToInt64() + count.ToInt64() - 1); 1122 else 1123 upperBound.SetTo(lowerBound.ToUInt64() + count.ToUInt64() - 1); 1124 } 1125 } 1126 1127 // create the base type 1128 Type* baseType = NULL; 1129 status_t error; 1130 if (baseTypeEntry != NULL) { 1131 DwarfType* dwarfBaseType; 1132 error = CreateType(baseTypeEntry, dwarfBaseType); 1133 baseType = dwarfBaseType; 1134 } else { 1135 // We still don't have a base type yet. In this case the base type is 1136 // supposed to be a signed integer type with the same size as an address 1137 // for that compilation unit. 1138 error = ArtificialIntegerType::Create( 1139 fTypeContext->GetCompilationUnit()->AddressSize(), true, baseType); 1140 } 1141 if (error != B_OK) 1142 return error; 1143 BReference<Type> baseTypeReference(baseType, true); 1144 1145 // TODO: Support the thread scaling attribute! 1146 1147 // create the type 1148 DwarfSubrangeType* type = new(std::nothrow) DwarfSubrangeType(fTypeContext, 1149 name, typeEntry, baseType, lowerBound, upperBound); 1150 if (type == NULL) 1151 return B_NO_MEMORY; 1152 1153 _type = type; 1154 return B_OK; 1155} 1156 1157 1158status_t 1159DwarfTypeFactory::_CreateUnspecifiedType(const BString& name, 1160 DIEUnspecifiedType* typeEntry, DwarfType*& _type) 1161{ 1162 DwarfUnspecifiedType* type = new(std::nothrow) DwarfUnspecifiedType( 1163 fTypeContext, name, typeEntry); 1164 if (type == NULL) 1165 return B_NO_MEMORY; 1166 1167 _type = type; 1168 return B_OK; 1169} 1170 1171status_t 1172DwarfTypeFactory::_CreateFunctionType(const BString& name, 1173 DIESubroutineType* typeEntry, DwarfType*& _type) 1174{ 1175 // get the return type 1176 DIESubroutineType* returnTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1177 typeEntry, HasReturnTypePredicate<DIESubroutineType>()); 1178 1179 // create the base type 1180 DwarfType* returnType = NULL; 1181 if (returnTypeOwnerEntry != NULL) { 1182 status_t error = CreateType(returnTypeOwnerEntry->ReturnType(), 1183 returnType); 1184 if (error != B_OK) 1185 return error; 1186 } 1187 BReference<Type> returnTypeReference(returnType, true); 1188 1189 DwarfFunctionType* type = new(std::nothrow) DwarfFunctionType(fTypeContext, 1190 name, typeEntry, returnType); 1191 if (type == NULL) 1192 return B_NO_MEMORY; 1193 BReference<DwarfType> typeReference(type, true); 1194 1195 // get the parameters 1196 DIESubroutineType* parameterOwnerEntry = DwarfUtils::GetDIEByPredicate( 1197 typeEntry, HasParametersPredicate<DIESubroutineType>()); 1198 1199 if (parameterOwnerEntry != NULL) { 1200 for (DebugInfoEntryList::ConstIterator it 1201 = parameterOwnerEntry->Parameters().GetIterator(); 1202 DebugInfoEntry* _parameterEntry = it.Next();) { 1203 if (_parameterEntry->Tag() == DW_TAG_unspecified_parameters) { 1204 type->SetHasVariableArguments(true); 1205 continue; 1206 } 1207 1208 DIEFormalParameter* parameterEntry 1209 = dynamic_cast<DIEFormalParameter*>(_parameterEntry); 1210 1211 // get the type 1212 DIEFormalParameter* typeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1213 parameterEntry, HasTypePredicate<DIEFormalParameter>()); 1214 if (typeOwnerEntry == NULL) 1215 return B_BAD_VALUE; 1216 1217 DwarfType* parameterType; 1218 status_t error = CreateType(typeOwnerEntry->GetType(), 1219 parameterType); 1220 if (error != B_OK) 1221 return error; 1222 BReference<DwarfType> parameterTypeReference(parameterType, true); 1223 1224 // get the name 1225 BString parameterName; 1226 DwarfUtils::GetDIEName(parameterEntry, parameterName); 1227 1228 // create and add the parameter object 1229 DwarfFunctionParameter* parameter 1230 = new(std::nothrow) DwarfFunctionParameter(parameterEntry, 1231 parameterName, parameterType); 1232 BReference<DwarfFunctionParameter> parameterReference(parameter, 1233 true); 1234 if (parameter == NULL || !type->AddParameter(parameter)) 1235 return B_NO_MEMORY; 1236 } 1237 } 1238 1239 1240 _type = typeReference.Detach(); 1241 return B_OK; 1242} 1243 1244 1245status_t 1246DwarfTypeFactory::_CreatePointerToMemberType(const BString& name, 1247 DIEPointerToMemberType* typeEntry, DwarfType*& _type) 1248{ 1249 // get the containing and base type entries 1250 DIEPointerToMemberType* containingTypeOwnerEntry 1251 = DwarfUtils::GetDIEByPredicate(typeEntry, 1252 HasContainingTypePredicate()); 1253 DIEPointerToMemberType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1254 typeEntry, HasTypePredicate<DIEPointerToMemberType>()); 1255 1256 if (containingTypeOwnerEntry == NULL || baseTypeOwnerEntry == NULL) { 1257 WARNING("Failed to get containing or base type for pointer to member " 1258 "type \"%s\"\n", name.String()); 1259 return B_BAD_VALUE; 1260 } 1261 1262 // create the containing type 1263 DwarfType* containingType; 1264 status_t error = CreateType(containingTypeOwnerEntry->ContainingType(), 1265 containingType); 1266 if (error != B_OK) 1267 return error; 1268 BReference<Type> containingTypeReference(containingType, true); 1269 1270 DwarfCompoundType* compoundContainingType 1271 = dynamic_cast<DwarfCompoundType*>(containingType); 1272 if (compoundContainingType == NULL) { 1273 WARNING("Containing type for pointer to member type \"%s\" is not a " 1274 "compound type.\n", name.String()); 1275 return B_BAD_VALUE; 1276 } 1277 1278 // create the base type 1279 DwarfType* baseType; 1280 error = CreateType(baseTypeOwnerEntry->GetType(), baseType); 1281 if (error != B_OK) 1282 return error; 1283 BReference<Type> baseTypeReference(baseType, true); 1284 1285 // create the type object 1286 DwarfPointerToMemberType* type = new(std::nothrow) DwarfPointerToMemberType( 1287 fTypeContext, name, typeEntry, compoundContainingType, baseType); 1288 if (type == NULL) 1289 return B_NO_MEMORY; 1290 1291 _type = type; 1292 return B_OK; 1293} 1294 1295 1296status_t 1297DwarfTypeFactory::_ResolveTypedef(DIETypedef* entry, 1298 DIEType*& _baseTypeEntry) 1299{ 1300 while (true) { 1301 // resolve the base type, possibly following abstract origin or 1302 // specification 1303 DIETypedef* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1304 entry, HasTypePredicate<DIETypedef>()); 1305 if (baseTypeOwnerEntry == NULL) 1306 return B_BAD_VALUE; 1307 1308 DIEType* baseTypeEntry = baseTypeOwnerEntry->GetType(); 1309 if (baseTypeEntry->Tag() != DW_TAG_typedef) { 1310 _baseTypeEntry = baseTypeEntry; 1311 return B_OK; 1312 } 1313 1314 entry = dynamic_cast<DIETypedef*>(baseTypeEntry); 1315 } 1316} 1317 1318 1319status_t 1320DwarfTypeFactory::_ResolveTypeByteSize(DIEType* typeEntry, 1321 uint64& _size) 1322{ 1323 TRACE_LOCALS("DwarfTypeFactory::_ResolveTypeByteSize(%p)\n", 1324 typeEntry); 1325 1326 // get the size attribute 1327 const DynamicAttributeValue* sizeValue; 1328 1329 while (true) { 1330 // resolve a typedef 1331 if (typeEntry->Tag() == DW_TAG_typedef) { 1332 TRACE_LOCALS(" resolving typedef...\n"); 1333 1334 status_t error = _ResolveTypedef( 1335 dynamic_cast<DIETypedef*>(typeEntry), typeEntry); 1336 if (error != B_OK) 1337 return error; 1338 } 1339 1340 sizeValue = typeEntry->ByteSize(); 1341 if (sizeValue != NULL && sizeValue->IsValid()) 1342 break; 1343 1344 // resolve abstract origin 1345 if (DIEType* abstractOrigin = dynamic_cast<DIEType*>( 1346 typeEntry->AbstractOrigin())) { 1347 TRACE_LOCALS(" resolving abstract origin (%p)...\n", 1348 abstractOrigin); 1349 1350 typeEntry = abstractOrigin; 1351 sizeValue = typeEntry->ByteSize(); 1352 if (sizeValue != NULL && sizeValue->IsValid()) 1353 break; 1354 } 1355 1356 // resolve specification 1357 if (DIEType* specification = dynamic_cast<DIEType*>( 1358 typeEntry->Specification())) { 1359 TRACE_LOCALS(" resolving specification (%p)...\n", specification); 1360 1361 typeEntry = specification; 1362 sizeValue = typeEntry->ByteSize(); 1363 if (sizeValue != NULL && sizeValue->IsValid()) 1364 break; 1365 } 1366 1367 // For some types we have a special handling. For modified types we 1368 // follow the base type, for address types we know the size anyway. 1369 TRACE_LOCALS(" nothing yet, special type handling\n"); 1370 1371 switch (typeEntry->Tag()) { 1372 case DW_TAG_const_type: 1373 case DW_TAG_packed_type: 1374 case DW_TAG_volatile_type: 1375 case DW_TAG_restrict_type: 1376 case DW_TAG_shared_type: 1377 typeEntry = dynamic_cast<DIEModifiedType*>(typeEntry) 1378 ->GetType(); 1379 1380 TRACE_LOCALS(" following modified type -> %p\n", typeEntry); 1381 1382 if (typeEntry == NULL) 1383 return B_ENTRY_NOT_FOUND; 1384 break; 1385 case DW_TAG_pointer_type: 1386 case DW_TAG_reference_type: 1387 case DW_TAG_ptr_to_member_type: 1388 _size = fTypeContext->GetCompilationUnit()->AddressSize(); 1389 1390 TRACE_LOCALS(" pointer/reference type: size: %" B_PRIu64 "\n", 1391 _size); 1392 1393 return B_OK; 1394 default: 1395 return B_ENTRY_NOT_FOUND; 1396 } 1397 } 1398 1399 TRACE_LOCALS(" found attribute\n"); 1400 1401 // get the actual value 1402 BVariant size; 1403 status_t error = fTypeContext->File()->EvaluateDynamicValue( 1404 fTypeContext->GetCompilationUnit(), 1405 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(), 1406 fTypeContext->SubprogramEntry(), sizeValue, 1407 fTypeContext->TargetInterface(), fTypeContext->InstructionPointer(), 1408 fTypeContext->FramePointer(), size); 1409 if (error != B_OK) { 1410 TRACE_LOCALS(" failed to resolve attribute: %s\n", strerror(error)); 1411 return error; 1412 } 1413 1414 _size = size.ToUInt64(); 1415 1416 TRACE_LOCALS(" -> size: %" B_PRIu64 "\n", _size); 1417 1418 return B_OK; 1419} 1420