1/* 2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copryight 2012-2014, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8#include "DwarfTypes.h" 9 10#include <new> 11 12#include "Architecture.h" 13#include "ArrayIndexPath.h" 14#include "CompilationUnit.h" 15#include "Dwarf.h" 16#include "DwarfFile.h" 17#include "DwarfTargetInterface.h" 18#include "DwarfUtils.h" 19#include "Register.h" 20#include "RegisterMap.h" 21#include "Tracing.h" 22#include "ValueLocation.h" 23 24 25namespace { 26 27 28// #pragma mark - HasBitStridePredicate 29 30 31template<typename EntryType> 32struct HasBitStridePredicate { 33 inline bool operator()(EntryType* entry) const 34 { 35 return entry->BitStride()->IsValid(); 36 } 37}; 38 39 40// #pragma mark - HasByteStridePredicate 41 42 43template<typename EntryType> 44struct HasByteStridePredicate { 45 inline bool operator()(EntryType* entry) const 46 { 47 return entry->ByteStride()->IsValid(); 48 } 49}; 50 51 52} // unnamed namespace 53 54 55type_kind 56dwarf_tag_to_type_kind(int32 tag) 57{ 58 switch (tag) { 59 case DW_TAG_class_type: 60 case DW_TAG_structure_type: 61 case DW_TAG_union_type: 62 case DW_TAG_interface_type: 63 return TYPE_COMPOUND; 64 65 case DW_TAG_base_type: 66 return TYPE_PRIMITIVE; 67 68 case DW_TAG_pointer_type: 69 case DW_TAG_reference_type: 70 return TYPE_ADDRESS; 71 72 case DW_TAG_const_type: 73 case DW_TAG_packed_type: 74 case DW_TAG_volatile_type: 75 case DW_TAG_restrict_type: 76 case DW_TAG_shared_type: 77 return TYPE_MODIFIED; 78 79 case DW_TAG_typedef: 80 return TYPE_TYPEDEF; 81 82 case DW_TAG_array_type: 83 return TYPE_ARRAY; 84 85 case DW_TAG_enumeration_type: 86 return TYPE_ENUMERATION; 87 88 case DW_TAG_subrange_type: 89 return TYPE_SUBRANGE; 90 91 case DW_TAG_unspecified_type: 92 return TYPE_UNSPECIFIED; 93 94 case DW_TAG_subroutine_type: 95 return TYPE_FUNCTION; 96 97 case DW_TAG_ptr_to_member_type: 98 return TYPE_POINTER_TO_MEMBER; 99 100 } 101 102 return TYPE_UNSPECIFIED; 103} 104 105 106int32 107dwarf_tag_to_subtype_kind(int32 tag) 108{ 109 switch (tag) { 110 case DW_TAG_class_type: 111 return COMPOUND_TYPE_CLASS; 112 113 case DW_TAG_structure_type: 114 return COMPOUND_TYPE_STRUCT; 115 116 case DW_TAG_union_type: 117 return COMPOUND_TYPE_UNION; 118 119 case DW_TAG_interface_type: 120 return COMPOUND_TYPE_INTERFACE; 121 122 case DW_TAG_pointer_type: 123 return DERIVED_TYPE_POINTER; 124 125 case DW_TAG_reference_type: 126 return DERIVED_TYPE_REFERENCE; 127 } 128 129 return -1; 130} 131 132 133// #pragma mark - DwarfTypeContext 134 135 136DwarfTypeContext::DwarfTypeContext(Architecture* architecture, image_id imageID, 137 DwarfFile* file, CompilationUnit* compilationUnit, 138 DIESubprogram* subprogramEntry, target_addr_t instructionPointer, 139 target_addr_t framePointer, target_addr_t relocationDelta, 140 DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap) 141 : 142 fArchitecture(architecture), 143 fImageID(imageID), 144 fFile(file), 145 fCompilationUnit(compilationUnit), 146 fSubprogramEntry(subprogramEntry), 147 fInstructionPointer(instructionPointer), 148 fFramePointer(framePointer), 149 fRelocationDelta(relocationDelta), 150 fTargetInterface(targetInterface), 151 fFromDwarfRegisterMap(fromDwarfRegisterMap) 152{ 153 fArchitecture->AcquireReference(); 154 fFile->AcquireReference(); 155 if (fTargetInterface != NULL) 156 fTargetInterface->AcquireReference(); 157} 158 159 160DwarfTypeContext::~DwarfTypeContext() 161{ 162 fArchitecture->ReleaseReference(); 163 fFile->ReleaseReference(); 164 if (fTargetInterface != NULL) 165 fTargetInterface->ReleaseReference(); 166} 167 168 169uint8 170DwarfTypeContext::AddressSize() const 171{ 172 return fCompilationUnit != NULL ? fCompilationUnit->AddressSize() 173 : fArchitecture->AddressSize(); 174} 175 176 177bool 178DwarfTypeContext::IsBigEndian() const 179{ 180 return fCompilationUnit != NULL ? fCompilationUnit->IsBigEndian() 181 : fArchitecture->IsBigEndian(); 182} 183 184 185// #pragma mark - DwarfType 186 187 188DwarfType::DwarfType(DwarfTypeContext* typeContext, const BString& name, 189 const DIEType* entry) 190 : 191 fTypeContext(typeContext), 192 fName(name), 193 fByteSize(0) 194{ 195 fTypeContext->AcquireReference(); 196 197 GetTypeID(entry, fID); 198} 199 200 201DwarfType::~DwarfType() 202{ 203 fTypeContext->ReleaseReference(); 204} 205 206 207/*static*/ bool 208DwarfType::GetTypeID(const DIEType* entry, BString& _id) 209{ 210 char buffer[32]; 211 snprintf(buffer, sizeof(buffer), "dwarf:%p", entry); 212 BString id = buffer; 213 if (id.Length() == 0) 214 return false; 215 216 _id = id; 217 return true; 218} 219 220 221image_id 222DwarfType::ImageID() const 223{ 224 return fTypeContext->ImageID(); 225} 226 227 228const BString& 229DwarfType::ID() const 230{ 231 return fID; 232} 233 234 235const BString& 236DwarfType::Name() const 237{ 238 return fName; 239} 240 241 242target_size_t 243DwarfType::ByteSize() const 244{ 245 return fByteSize; 246} 247 248 249status_t 250DwarfType::CreateDerivedAddressType(address_type_kind addressType, 251 AddressType*& _resultType) 252{ 253 BString derivedName; 254 derivedName.SetToFormat("%s%c", fName.String(), 255 addressType == DERIVED_TYPE_POINTER ? '*' : '&'); 256 DwarfAddressType* resultType = new(std::nothrow) 257 DwarfAddressType(fTypeContext, derivedName, NULL, addressType, this); 258 259 if (resultType == NULL) 260 return B_NO_MEMORY; 261 262 resultType->SetByteSize(fTypeContext->GetArchitecture()->AddressSize()); 263 264 _resultType = resultType; 265 return B_OK; 266} 267 268 269status_t 270DwarfType::CreateDerivedArrayType(int64 lowerBound, int64 elementCount, 271 bool extendExisting, ArrayType*& _resultType) 272{ 273 DwarfArrayType* resultType = NULL; 274 BReference<DwarfType> baseTypeReference; 275 if (extendExisting) 276 resultType = dynamic_cast<DwarfArrayType*>(this); 277 278 if (resultType == NULL) { 279 BString derivedName; 280 derivedName.SetToFormat("%s[]", fName.String()); 281 resultType = new(std::nothrow) 282 DwarfArrayType(fTypeContext, derivedName, NULL, this); 283 baseTypeReference.SetTo(resultType, true); 284 } 285 286 if (resultType == NULL) 287 return B_NO_MEMORY; 288 289 DwarfSubrangeType* subrangeType = new(std::nothrow) DwarfSubrangeType( 290 fTypeContext, fName, NULL, resultType, BVariant(lowerBound), 291 BVariant(lowerBound + elementCount - 1)); 292 if (subrangeType == NULL) 293 return B_NO_MEMORY; 294 295 BReference<DwarfSubrangeType> subrangeReference(subrangeType, true); 296 297 DwarfArrayDimension* dimension = new(std::nothrow) DwarfArrayDimension( 298 subrangeType); 299 if (dimension == NULL) 300 return B_NO_MEMORY; 301 BReference<DwarfArrayDimension> dimensionReference(dimension, true); 302 303 if (!resultType->AddDimension(dimension)) 304 return B_NO_MEMORY; 305 306 baseTypeReference.Detach(); 307 308 _resultType = resultType; 309 return B_OK; 310} 311 312 313status_t 314DwarfType::ResolveObjectDataLocation(const ValueLocation& objectLocation, 315 ValueLocation*& _location) 316{ 317 // TODO: In some source languages the object address might be a pointer 318 // to a descriptor, not the actual object data. 319 320 // If the given location looks good already, just clone it. 321 int32 count = objectLocation.CountPieces(); 322 if (count == 0) 323 return B_BAD_VALUE; 324 325 ValuePieceLocation piece; 326 if (!piece.Copy(objectLocation.PieceAt(0))) 327 return B_NO_MEMORY; 328 329 if (count > 1 || piece.type != VALUE_PIECE_LOCATION_MEMORY 330 || piece.size != 0 || piece.bitSize != 0) { 331 ValueLocation* location 332 = new(std::nothrow) ValueLocation(objectLocation); 333 if (location == NULL || location->CountPieces() != count) { 334 delete location; 335 return B_NO_MEMORY; 336 } 337 338 _location = location; 339 return B_OK; 340 } 341 342 // The location contains just a single address piece with a zero size 343 // -- set the type's size. 344 piece.SetSize(ByteSize()); 345 // TODO: Use bit size and bit offset, if specified! 346 347 ValueLocation* location = new(std::nothrow) ValueLocation( 348 objectLocation.IsBigEndian()); 349 if (location == NULL || !location->AddPiece(piece)) { 350 delete location; 351 return B_NO_MEMORY; 352 } 353 354 _location = location; 355 return B_OK; 356} 357 358 359status_t 360DwarfType::ResolveObjectDataLocation(target_addr_t objectAddress, 361 ValueLocation*& _location) 362{ 363 ValuePieceLocation piece; 364 piece.SetToMemory(objectAddress); 365 piece.SetSize(0); 366 // We set the piece size to 0 as an indicator that the size has to be 367 // set. 368 // TODO: We could set the byte size from type, but that may not be 369 // accurate. We may want to add bit offset and size to Type. 370 371 ValueLocation location(fTypeContext->GetArchitecture()->IsBigEndian()); 372 if (!location.AddPiece(piece)) 373 return B_NO_MEMORY; 374 375 return ResolveObjectDataLocation(location, _location); 376} 377 378 379status_t 380DwarfType::ResolveLocation(DwarfTypeContext* typeContext, 381 const LocationDescription* description, target_addr_t objectAddress, 382 bool hasObjectAddress, ValueLocation& _location) 383{ 384 status_t error = typeContext->File()->ResolveLocation( 385 typeContext->GetCompilationUnit(), 386 typeContext->AddressSize(), typeContext->IsBigEndian(), 387 typeContext->SubprogramEntry(), description, 388 typeContext->TargetInterface(), typeContext->InstructionPointer(), 389 objectAddress, hasObjectAddress, typeContext->FramePointer(), 390 typeContext->RelocationDelta(), _location); 391 if (error != B_OK) 392 return error; 393 394 // translate the DWARF register indices and the bit offset/size semantics 395 const Register* registers = typeContext->GetArchitecture()->Registers(); 396 bool bigEndian = typeContext->GetArchitecture()->IsBigEndian(); 397 int32 count = _location.CountPieces(); 398 for (int32 i = 0; i < count; i++) { 399 ValuePieceLocation piece; 400 if (!piece.Copy(_location.PieceAt(i))) 401 return B_NO_MEMORY; 402 403 if (piece.type == VALUE_PIECE_LOCATION_REGISTER) { 404 int32 reg = typeContext->FromDwarfRegisterMap()->MapRegisterIndex( 405 piece.reg); 406 if (reg >= 0) { 407 piece.reg = reg; 408 // The bit offset for registers is to the least 409 // significant bit, while we want the offset to the most 410 // significant bit. 411 if (registers[reg].BitSize() > piece.bitSize) { 412 piece.bitOffset = registers[reg].BitSize() - piece.bitSize 413 - piece.bitOffset; 414 } 415 } else 416 piece.SetToUnknown(); 417 } else if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { 418 // Whether the bit offset is to the least or most significant bit 419 // is target architecture and source language specific. 420 // TODO: Check whether this is correct! 421 // TODO: Source language! 422 if (!bigEndian && piece.size * 8 > piece.bitSize) { 423 piece.bitOffset = piece.size * 8 - piece.bitSize 424 - piece.bitOffset; 425 } 426 } 427 428 piece.Normalize(bigEndian); 429 if (!_location.SetPieceAt(i, piece)) 430 return B_NO_MEMORY; 431 } 432 433 // If we only have one piece and that doesn't have a size, try to retrieve 434 // the size of the type. 435 if (count == 1) { 436 ValuePieceLocation piece; 437 if (!piece.Copy(_location.PieceAt(0))) 438 return B_NO_MEMORY; 439 440 if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) { 441 piece.SetSize(ByteSize()); 442 // TODO: Use bit size and bit offset, if specified! 443 if (!_location.SetPieceAt(0, piece)) 444 return B_NO_MEMORY; 445 446 TRACE_LOCALS(" set single piece size to %" B_PRIu64 "\n", 447 ByteSize()); 448 } 449 } 450 451 return B_OK; 452} 453 454 455// #pragma mark - DwarfInheritance 456 457 458DwarfInheritance::DwarfInheritance(DIEInheritance* entry, DwarfType* type) 459 : 460 fEntry(entry), 461 fType(type) 462{ 463 fType->AcquireReference(); 464} 465 466 467DwarfInheritance::~DwarfInheritance() 468{ 469 fType->ReleaseReference(); 470} 471 472 473Type* 474DwarfInheritance::GetType() const 475{ 476 return fType; 477} 478 479 480// #pragma mark - DwarfDataMember 481 482 483DwarfDataMember::DwarfDataMember(DIEMember* entry, const BString& name, 484 DwarfType* type) 485 : 486 fEntry(entry), 487 fName(name), 488 fType(type) 489{ 490 fType->AcquireReference(); 491} 492 493 494DwarfDataMember::~DwarfDataMember() 495{ 496 fType->ReleaseReference(); 497} 498 499const char* 500DwarfDataMember::Name() const 501{ 502 return fName.Length() > 0 ? fName.String() : NULL; 503} 504 505 506Type* 507DwarfDataMember::GetType() const 508{ 509 return fType; 510} 511 512 513// #pragma mark - DwarfEnumeratorValue 514 515 516DwarfEnumeratorValue::DwarfEnumeratorValue(DIEEnumerator* entry, 517 const BString& name, const BVariant& value) 518 : 519 fEntry(entry), 520 fName(name), 521 fValue(value) 522{ 523} 524 525 526DwarfEnumeratorValue::~DwarfEnumeratorValue() 527{ 528} 529 530const char* 531DwarfEnumeratorValue::Name() const 532{ 533 return fName.Length() > 0 ? fName.String() : NULL; 534} 535 536 537BVariant 538DwarfEnumeratorValue::Value() const 539{ 540 return fValue; 541} 542 543 544// #pragma mark - DwarfArrayDimension 545 546 547DwarfArrayDimension::DwarfArrayDimension(DwarfType* type) 548 : 549 fType(type) 550{ 551 fType->AcquireReference(); 552} 553 554 555DwarfArrayDimension::~DwarfArrayDimension() 556{ 557 fType->ReleaseReference(); 558} 559 560 561Type* 562DwarfArrayDimension::GetType() const 563{ 564 return fType; 565} 566 567 568// #pragma mark - DwarfFunctionParameter 569 570 571DwarfFunctionParameter::DwarfFunctionParameter(DIEFormalParameter* entry, 572 const BString& name, DwarfType* type) 573 : 574 fEntry(entry), 575 fName(name), 576 fType(type) 577{ 578 fType->AcquireReference(); 579} 580 581 582DwarfFunctionParameter::~DwarfFunctionParameter() 583{ 584 fType->ReleaseReference(); 585} 586 587 588const char* 589DwarfFunctionParameter::Name() const 590{ 591 return fName.Length() > 0 ? fName.String() : NULL; 592} 593 594 595Type* 596DwarfFunctionParameter::GetType() const 597{ 598 return fType; 599} 600 601 602// #pragma mark - DwarfTemplateParameter 603 604 605DwarfTemplateParameter::DwarfTemplateParameter(DebugInfoEntry* entry, 606 DwarfType* type) 607 : 608 fEntry(entry), 609 fType(type) 610{ 611 fType->AcquireReference(); 612 DIETemplateTypeParameter* typeParameter 613 = dynamic_cast<DIETemplateTypeParameter *>(entry); 614 if (typeParameter != NULL) 615 fTemplateKind = TEMPLATE_TYPE_TYPE; 616 else { 617 DIETemplateValueParameter* valueParameter 618 = dynamic_cast<DIETemplateValueParameter *>(entry); 619 fTemplateKind = TEMPLATE_TYPE_VALUE; 620 const ConstantAttributeValue* constValue = valueParameter 621 ->ConstValue(); 622 switch (constValue->attributeClass) { 623 case ATTRIBUTE_CLASS_CONSTANT: 624 fValue.SetTo(constValue->constant); 625 break; 626 case ATTRIBUTE_CLASS_STRING: 627 fValue.SetTo(constValue->string); 628 break; 629 // TODO: ATTRIBUTE_CLASS_BLOCK_DATA 630 } 631 } 632} 633 634 635DwarfTemplateParameter::~DwarfTemplateParameter() 636{ 637 fType->ReleaseReference(); 638} 639 640 641// #pragma mark - DwarfPrimitiveType 642 643 644DwarfPrimitiveType::DwarfPrimitiveType(DwarfTypeContext* typeContext, 645 const BString& name, DIEBaseType* entry, uint32 typeConstant) 646 : 647 DwarfType(typeContext, name, entry), 648 fEntry(entry), 649 fTypeConstant(typeConstant) 650{ 651} 652 653 654DIEType* 655DwarfPrimitiveType::GetDIEType() const 656{ 657 return fEntry; 658} 659 660 661uint32 662DwarfPrimitiveType::TypeConstant() const 663{ 664 return fTypeConstant; 665} 666 667 668// #pragma mark - DwarfCompoundType 669 670 671DwarfCompoundType::DwarfCompoundType(DwarfTypeContext* typeContext, 672 const BString& name, DIECompoundType* entry, 673 compound_type_kind compoundKind) 674 : 675 DwarfType(typeContext, name, entry), 676 fCompoundKind(compoundKind), 677 fEntry(entry) 678{ 679} 680 681 682DwarfCompoundType::~DwarfCompoundType() 683{ 684 for (int32 i = 0; 685 DwarfInheritance* inheritance = fInheritances.ItemAt(i); i++) { 686 inheritance->ReleaseReference(); 687 } 688 for (int32 i = 0; DwarfDataMember* member = fDataMembers.ItemAt(i); i++) 689 member->ReleaseReference(); 690 691 for (int32 i = 0; DwarfTemplateParameter* parameter 692 = fTemplateParameters.ItemAt(i); i++) { 693 parameter->ReleaseReference(); 694 } 695} 696 697 698compound_type_kind 699DwarfCompoundType::CompoundKind() const 700{ 701 return fCompoundKind; 702} 703 704 705int32 706DwarfCompoundType::CountBaseTypes() const 707{ 708 return fInheritances.CountItems(); 709} 710 711 712BaseType* 713DwarfCompoundType::BaseTypeAt(int32 index) const 714{ 715 return fInheritances.ItemAt(index); 716} 717 718 719int32 720DwarfCompoundType::CountDataMembers() const 721{ 722 return fDataMembers.CountItems(); 723} 724 725 726DataMember* 727DwarfCompoundType::DataMemberAt(int32 index) const 728{ 729 return fDataMembers.ItemAt(index); 730} 731 732 733int32 734DwarfCompoundType::CountTemplateParameters() const 735{ 736 return fTemplateParameters.CountItems(); 737} 738 739 740TemplateParameter* 741DwarfCompoundType::TemplateParameterAt(int32 index) const 742{ 743 return fTemplateParameters.ItemAt(index); 744} 745 746 747status_t 748DwarfCompoundType::ResolveBaseTypeLocation(BaseType* _baseType, 749 const ValueLocation& parentLocation, ValueLocation*& _location) 750{ 751 DwarfInheritance* baseType = dynamic_cast<DwarfInheritance*>(_baseType); 752 if (baseType == NULL) 753 return B_BAD_VALUE; 754 755 return _ResolveDataMemberLocation(baseType->GetDwarfType(), 756 baseType->Entry()->Location(), parentLocation, false, _location); 757} 758 759 760status_t 761DwarfCompoundType::ResolveDataMemberLocation(DataMember* _member, 762 const ValueLocation& parentLocation, ValueLocation*& _location) 763{ 764 DwarfDataMember* member = dynamic_cast<DwarfDataMember*>(_member); 765 if (member == NULL) 766 return B_BAD_VALUE; 767 DwarfTypeContext* typeContext = TypeContext(); 768 769 bool isBitField = true; 770 DIEMember* memberEntry = member->Entry(); 771 // TODO: handle DW_AT_data_bit_offset 772 if (!memberEntry->ByteSize()->IsValid() 773 && !memberEntry->BitOffset()->IsValid() 774 && !memberEntry->BitSize()->IsValid()) { 775 isBitField = false; 776 } 777 778 ValueLocation* location; 779 status_t error = _ResolveDataMemberLocation(member->GetDwarfType(), 780 member->Entry()->Location(), parentLocation, isBitField, location); 781 if (error != B_OK) 782 return error; 783 784 // If the member isn't a bit field, we're done. 785 if (!isBitField) { 786 _location = location; 787 return B_OK; 788 } 789 790 BReference<ValueLocation> locationReference(location); 791 792 // get the byte size 793 target_addr_t byteSize; 794 if (memberEntry->ByteSize()->IsValid()) { 795 BVariant value; 796 error = typeContext->File()->EvaluateDynamicValue( 797 typeContext->GetCompilationUnit(), 798 typeContext->AddressSize(), typeContext->IsBigEndian(), 799 typeContext->SubprogramEntry(), memberEntry->ByteSize(), 800 typeContext->TargetInterface(), typeContext->InstructionPointer(), 801 typeContext->FramePointer(), value); 802 if (error != B_OK) 803 return error; 804 byteSize = value.ToUInt64(); 805 } else 806 byteSize = ByteSize(); 807 808 // get the bit offset 809 uint64 bitOffset = 0; 810 if (memberEntry->BitOffset()->IsValid()) { 811 BVariant value; 812 error = typeContext->File()->EvaluateDynamicValue( 813 typeContext->GetCompilationUnit(), 814 typeContext->AddressSize(), typeContext->IsBigEndian(), 815 typeContext->SubprogramEntry(), memberEntry->BitOffset(), 816 typeContext->TargetInterface(), typeContext->InstructionPointer(), 817 typeContext->FramePointer(), value); 818 if (error != B_OK) 819 return error; 820 bitOffset = value.ToUInt64(); 821 } 822 823 // get the bit size 824 uint64 bitSize = byteSize * 8; 825 if (memberEntry->BitSize()->IsValid()) { 826 BVariant value; 827 error = typeContext->File()->EvaluateDynamicValue( 828 typeContext->GetCompilationUnit(), 829 typeContext->AddressSize(), typeContext->IsBigEndian(), 830 typeContext->SubprogramEntry(), memberEntry->BitSize(), 831 typeContext->TargetInterface(), typeContext->InstructionPointer(), 832 typeContext->FramePointer(), value); 833 if (error != B_OK) 834 return error; 835 bitSize = value.ToUInt64(); 836 } 837 838 TRACE_LOCALS("bit field: byte size: %" B_PRIu64 ", bit offset/size: %" 839 B_PRIu64 "/%" B_PRIu64 "\n", byteSize, bitOffset, bitSize); 840 841 if (bitOffset + bitSize > byteSize * 8) 842 return B_BAD_VALUE; 843 844 // create the bit field value location 845 ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation; 846 if (bitFieldLocation == NULL) 847 return B_NO_MEMORY; 848 BReference<ValueLocation> bitFieldLocationReference(bitFieldLocation, true); 849 850 if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize)) 851 return B_NO_MEMORY; 852 853 _location = bitFieldLocationReference.Detach(); 854 return B_OK; 855} 856 857 858DIEType* 859DwarfCompoundType::GetDIEType() const 860{ 861 return fEntry; 862} 863 864 865bool 866DwarfCompoundType::AddInheritance(DwarfInheritance* inheritance) 867{ 868 if (!fInheritances.AddItem(inheritance)) 869 return false; 870 871 inheritance->AcquireReference(); 872 return true; 873} 874 875 876bool 877DwarfCompoundType::AddDataMember(DwarfDataMember* member) 878{ 879 if (!fDataMembers.AddItem(member)) 880 return false; 881 882 member->AcquireReference(); 883 return true; 884} 885 886 887bool 888DwarfCompoundType::AddTemplateParameter(DwarfTemplateParameter* parameter) 889{ 890 if (!fTemplateParameters.AddItem(parameter)) 891 return false; 892 893 parameter->AcquireReference(); 894 return true; 895} 896 897 898status_t 899DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType, 900 const MemberLocation* memberLocation, 901 const ValueLocation& parentLocation, bool isBitField, 902 ValueLocation*& _location) 903{ 904 // create the value location object for the member 905 ValueLocation* location = new(std::nothrow) ValueLocation( 906 parentLocation.IsBigEndian()); 907 if (location == NULL) 908 return B_NO_MEMORY; 909 BReference<ValueLocation> locationReference(location, true); 910 911 switch (memberLocation->attributeClass) { 912 case ATTRIBUTE_CLASS_CONSTANT: 913 { 914 if (isBitField) { 915 if (!location->SetTo(parentLocation, 916 memberLocation->constant * 8, 917 memberType->ByteSize() * 8)) { 918 return B_NO_MEMORY; 919 } 920 } else { 921 if (!location->SetToByteOffset(parentLocation, 922 memberLocation->constant, 923 memberType->ByteSize())) { 924 return B_NO_MEMORY; 925 } 926 } 927 928 break; 929 } 930 case ATTRIBUTE_CLASS_BLOCK: 931 case ATTRIBUTE_CLASS_LOCLISTPTR: 932 { 933 // The attribute is a location description. Since we need to push 934 // the parent object value onto the stack, we require the parent 935 // location to be a memory location. 936 if (parentLocation.CountPieces() != 1) 937 return B_BAD_VALUE; 938 const ValuePieceLocation& piece = parentLocation.PieceAt(0); 939 940 if (piece.type != VALUE_PIECE_LOCATION_MEMORY) 941 return B_BAD_VALUE; 942 943 // convert member location to location description 944 LocationDescription locationDescription; 945 if (memberLocation->attributeClass == ATTRIBUTE_CLASS_BLOCK) { 946 locationDescription.SetToExpression( 947 memberLocation->expression.data, 948 memberLocation->expression.length); 949 } else { 950 locationDescription.SetToLocationList( 951 memberLocation->listOffset); 952 } 953 954 // evaluate the location description 955 status_t error = memberType->ResolveLocation(TypeContext(), 956 &locationDescription, piece.address, true, *location); 957 if (error != B_OK) 958 return error; 959 960 break; 961 } 962 default: 963 { 964 // for unions the member location can be omitted -- all members 965 // start at the beginning of the parent object 966 if (fEntry->Tag() != DW_TAG_union_type) 967 return B_BAD_VALUE; 968 969 // since all members start at the same location, set up 970 // the location by hand since we don't want the size difference 971 // between the overall union and the member being 972 // factored into the assigned address. 973 ValuePieceLocation piece; 974 if (!piece.Copy(parentLocation.PieceAt(0))) 975 return B_NO_MEMORY; 976 977 piece.SetSize(memberType->ByteSize()); 978 if (!location->AddPiece(piece)) 979 return B_NO_MEMORY; 980 981 break; 982 } 983 } 984 985 _location = locationReference.Detach(); 986 return B_OK; 987} 988 989 990// #pragma mark - DwarfArrayType 991 992 993DwarfArrayType::DwarfArrayType(DwarfTypeContext* typeContext, 994 const BString& name, DIEArrayType* entry, DwarfType* baseType) 995 : 996 DwarfType(typeContext, name, entry), 997 fEntry(entry), 998 fBaseType(baseType) 999{ 1000 fBaseType->AcquireReference(); 1001} 1002 1003 1004DwarfArrayType::~DwarfArrayType() 1005{ 1006 for (int32 i = 0; 1007 DwarfArrayDimension* dimension = fDimensions.ItemAt(i); i++) { 1008 dimension->ReleaseReference(); 1009 } 1010 1011 fBaseType->ReleaseReference(); 1012} 1013 1014 1015Type* 1016DwarfArrayType::BaseType() const 1017{ 1018 return fBaseType; 1019} 1020 1021 1022int32 1023DwarfArrayType::CountDimensions() const 1024{ 1025 return fDimensions.CountItems(); 1026} 1027 1028 1029ArrayDimension* 1030DwarfArrayType::DimensionAt(int32 index) const 1031{ 1032 return fDimensions.ItemAt(index); 1033} 1034 1035 1036status_t 1037DwarfArrayType::ResolveElementLocation(const ArrayIndexPath& indexPath, 1038 const ValueLocation& parentLocation, ValueLocation*& _location) 1039{ 1040 if (indexPath.CountIndices() != CountDimensions()) 1041 return B_BAD_VALUE; 1042 DwarfTypeContext* typeContext = TypeContext(); 1043 1044 // If the array entry has a bit stride, get it. Otherwise fall back to the 1045 // element type size. 1046 int64 bitStride; 1047 DIEArrayType* bitStrideOwnerEntry = NULL; 1048 if (fEntry != NULL && (bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate( 1049 fEntry, HasBitStridePredicate<DIEArrayType>()))) { 1050 BVariant value; 1051 status_t error = typeContext->File()->EvaluateDynamicValue( 1052 typeContext->GetCompilationUnit(), 1053 typeContext->AddressSize(), typeContext->IsBigEndian(), 1054 typeContext->SubprogramEntry(), bitStrideOwnerEntry->BitStride(), 1055 typeContext->TargetInterface(), typeContext->InstructionPointer(), 1056 typeContext->FramePointer(), value); 1057 if (error != B_OK) 1058 return error; 1059 if (!value.IsInteger()) 1060 return B_BAD_VALUE; 1061 bitStride = value.ToInt64(); 1062 } else 1063 bitStride = BaseType()->ByteSize() * 8; 1064 1065 // Iterate backward through the dimensions and compute the total offset of 1066 // the element. 1067 int64 elementOffset = 0; 1068 DwarfArrayDimension* previousDimension = NULL; 1069 int64 previousDimensionStride = 0; 1070 for (int32 dimensionIndex = CountDimensions() - 1; 1071 dimensionIndex >= 0; dimensionIndex--) { 1072 DwarfArrayDimension* dimension = DwarfDimensionAt(dimensionIndex); 1073 int64 index = indexPath.IndexAt(dimensionIndex); 1074 1075 // If the dimension has a special bit/byte stride, get it. 1076 int64 dimensionStride = 0; 1077 DwarfType* dimensionType = dimension->GetDwarfType(); 1078 DIEArrayIndexType* dimensionTypeEntry = dimensionType != NULL 1079 ? dynamic_cast<DIEArrayIndexType*>(dimensionType->GetDIEType()) 1080 : NULL; 1081 if (dimensionTypeEntry != NULL) { 1082 DIEArrayIndexType* bitStrideOwnerEntry 1083 = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, 1084 HasBitStridePredicate<DIEArrayIndexType>()); 1085 if (bitStrideOwnerEntry != NULL) { 1086 BVariant value; 1087 status_t error = typeContext->File()->EvaluateDynamicValue( 1088 typeContext->GetCompilationUnit(), 1089 typeContext->AddressSize(), typeContext->IsBigEndian(), 1090 typeContext->SubprogramEntry(), 1091 bitStrideOwnerEntry->BitStride(), 1092 typeContext->TargetInterface(), 1093 typeContext->InstructionPointer(), 1094 typeContext->FramePointer(), value); 1095 if (error != B_OK) 1096 return error; 1097 if (!value.IsInteger()) 1098 return B_BAD_VALUE; 1099 dimensionStride = value.ToInt64(); 1100 } else { 1101 DIEArrayIndexType* byteStrideOwnerEntry 1102 = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, 1103 HasByteStridePredicate<DIEArrayIndexType>()); 1104 if (byteStrideOwnerEntry != NULL) { 1105 BVariant value; 1106 status_t error = typeContext->File()->EvaluateDynamicValue( 1107 typeContext->GetCompilationUnit(), 1108 typeContext->AddressSize(), typeContext->IsBigEndian(), 1109 typeContext->SubprogramEntry(), 1110 byteStrideOwnerEntry->ByteStride(), 1111 typeContext->TargetInterface(), 1112 typeContext->InstructionPointer(), 1113 typeContext->FramePointer(), value); 1114 if (error != B_OK) 1115 return error; 1116 if (!value.IsInteger()) 1117 return B_BAD_VALUE; 1118 dimensionStride = value.ToInt64() * 8; 1119 } 1120 } 1121 } 1122 1123 // If we don't have a stride for the dimension yet, use the stride of 1124 // the previous dimension multiplied by the size of the dimension. 1125 if (dimensionStride == 0) { 1126 if (previousDimension != NULL) { 1127 dimensionStride = previousDimensionStride 1128 * previousDimension->CountElements(); 1129 } else { 1130 // the last dimension -- use the element bit stride 1131 dimensionStride = bitStride; 1132 } 1133 } 1134 1135 // If the dimension stride is still 0 (that can happen, if the dimension 1136 // doesn't have a stride and the previous dimension's element count is 1137 // not known), we can only resolve the first element. 1138 if (dimensionStride == 0 && index != 0) { 1139 WARNING("No dimension bit stride for dimension %" B_PRId32 " and " 1140 "element index is not 0.\n", dimensionIndex); 1141 return B_BAD_VALUE; 1142 } 1143 1144 elementOffset += dimensionStride * index; 1145 1146 previousDimension = dimension; 1147 previousDimensionStride = dimensionStride; 1148 } 1149 1150 TRACE_LOCALS("total element bit offset: %" B_PRId64 "\n", elementOffset); 1151 1152 // create the value location object for the element 1153 ValueLocation* location = new(std::nothrow) ValueLocation( 1154 parentLocation.IsBigEndian()); 1155 if (location == NULL) 1156 return B_NO_MEMORY; 1157 BReference<ValueLocation> locationReference(location, true); 1158 1159 // If we have a single memory piece location for the array, we compute the 1160 // element's location by hand -- not uncommonly the array size isn't known. 1161 if (parentLocation.CountPieces() == 1) { 1162 ValuePieceLocation piece; 1163 if (!piece.Copy(parentLocation.PieceAt(0))) 1164 return B_NO_MEMORY; 1165 1166 if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { 1167 int64 byteOffset = elementOffset >= 0 1168 ? elementOffset / 8 : (elementOffset - 7) / 8; 1169 piece.SetToMemory(piece.address + byteOffset); 1170 piece.SetSize(BaseType()->ByteSize()); 1171 // TODO: Support bit offsets correctly! 1172 // TODO: Support bit fields (primitive types) correctly! 1173 1174 if (!location->AddPiece(piece)) 1175 return B_NO_MEMORY; 1176 1177 _location = locationReference.Detach(); 1178 return B_OK; 1179 } 1180 } 1181 1182 // We can't deal with negative element offsets at this point. It doesn't 1183 // make a lot of sense anyway, if the array location consists of multiple 1184 // pieces or lives in a register. 1185 if (elementOffset < 0) { 1186 WARNING("Negative element offset unsupported for multiple location " 1187 "pieces or register pieces.\n"); 1188 return B_UNSUPPORTED; 1189 } 1190 1191 if (!location->SetTo(parentLocation, elementOffset, 1192 BaseType()->ByteSize() * 8)) { 1193 return B_NO_MEMORY; 1194 } 1195 1196 _location = locationReference.Detach(); 1197 return B_OK; 1198} 1199 1200 1201 1202DIEType* 1203DwarfArrayType::GetDIEType() const 1204{ 1205 return fEntry; 1206} 1207 1208 1209bool 1210DwarfArrayType::AddDimension(DwarfArrayDimension* dimension) 1211{ 1212 if (!fDimensions.AddItem(dimension)) 1213 return false; 1214 1215 dimension->AcquireReference(); 1216 return true; 1217} 1218 1219 1220// #pragma mark - DwarfModifiedType 1221 1222 1223DwarfModifiedType::DwarfModifiedType(DwarfTypeContext* typeContext, 1224 const BString& name, DIEModifiedType* entry, uint32 modifiers, 1225 DwarfType* baseType) 1226 : 1227 DwarfType(typeContext, name, entry), 1228 fEntry(entry), 1229 fModifiers(modifiers), 1230 fBaseType(baseType) 1231{ 1232 fBaseType->AcquireReference(); 1233} 1234 1235 1236DwarfModifiedType::~DwarfModifiedType() 1237{ 1238 fBaseType->ReleaseReference(); 1239} 1240 1241 1242uint32 1243DwarfModifiedType::Modifiers() const 1244{ 1245 return fModifiers; 1246} 1247 1248 1249Type* 1250DwarfModifiedType::BaseType() const 1251{ 1252 return fBaseType; 1253} 1254 1255 1256DIEType* 1257DwarfModifiedType::GetDIEType() const 1258{ 1259 return fEntry; 1260} 1261 1262 1263// #pragma mark - DwarfTypedefType 1264 1265 1266DwarfTypedefType::DwarfTypedefType(DwarfTypeContext* typeContext, 1267 const BString& name, DIETypedef* entry, DwarfType* baseType) 1268 : 1269 DwarfType(typeContext, name, entry), 1270 fEntry(entry), 1271 fBaseType(baseType) 1272{ 1273 fBaseType->AcquireReference(); 1274} 1275 1276 1277DwarfTypedefType::~DwarfTypedefType() 1278{ 1279 fBaseType->ReleaseReference(); 1280} 1281 1282 1283Type* 1284DwarfTypedefType::BaseType() const 1285{ 1286 return fBaseType; 1287} 1288 1289 1290DIEType* 1291DwarfTypedefType::GetDIEType() const 1292{ 1293 return fEntry; 1294} 1295 1296 1297// #pragma mark - DwarfAddressType 1298 1299 1300DwarfAddressType::DwarfAddressType(DwarfTypeContext* typeContext, 1301 const BString& name, DIEAddressingType* entry, 1302 address_type_kind addressKind, DwarfType* baseType) 1303 : 1304 DwarfType(typeContext, name, entry), 1305 fEntry(entry), 1306 fAddressKind(addressKind), 1307 fBaseType(baseType) 1308{ 1309 fBaseType->AcquireReference(); 1310} 1311 1312 1313DwarfAddressType::~DwarfAddressType() 1314{ 1315 fBaseType->ReleaseReference(); 1316} 1317 1318 1319address_type_kind 1320DwarfAddressType::AddressKind() const 1321{ 1322 return fAddressKind; 1323} 1324 1325 1326Type* 1327DwarfAddressType::BaseType() const 1328{ 1329 return fBaseType; 1330} 1331 1332 1333DIEType* 1334DwarfAddressType::GetDIEType() const 1335{ 1336 return fEntry; 1337} 1338 1339 1340// #pragma mark - DwarfEnumerationType 1341 1342 1343DwarfEnumerationType::DwarfEnumerationType(DwarfTypeContext* typeContext, 1344 const BString& name, DIEEnumerationType* entry, DwarfType* baseType) 1345 : 1346 DwarfType(typeContext, name, entry), 1347 fEntry(entry), 1348 fBaseType(baseType) 1349{ 1350 if (fBaseType != NULL) 1351 fBaseType->AcquireReference(); 1352} 1353 1354 1355DwarfEnumerationType::~DwarfEnumerationType() 1356{ 1357 for (int32 i = 0; DwarfEnumeratorValue* value = fValues.ItemAt(i); i++) 1358 value->ReleaseReference(); 1359 1360 if (fBaseType != NULL) 1361 fBaseType->ReleaseReference(); 1362} 1363 1364 1365Type* 1366DwarfEnumerationType::BaseType() const 1367{ 1368 return fBaseType; 1369} 1370 1371 1372int32 1373DwarfEnumerationType::CountValues() const 1374{ 1375 return fValues.CountItems(); 1376} 1377 1378 1379EnumeratorValue* 1380DwarfEnumerationType::ValueAt(int32 index) const 1381{ 1382 return fValues.ItemAt(index); 1383} 1384 1385 1386DIEType* 1387DwarfEnumerationType::GetDIEType() const 1388{ 1389 return fEntry; 1390} 1391 1392 1393bool 1394DwarfEnumerationType::AddValue(DwarfEnumeratorValue* value) 1395{ 1396 if (!fValues.AddItem(value)) 1397 return false; 1398 1399 value->AcquireReference(); 1400 return true; 1401} 1402 1403 1404// #pragma mark - DwarfSubrangeType 1405 1406 1407DwarfSubrangeType::DwarfSubrangeType(DwarfTypeContext* typeContext, 1408 const BString& name, DIESubrangeType* entry, Type* baseType, 1409 const BVariant& lowerBound, const BVariant& upperBound) 1410 : 1411 DwarfType(typeContext, name, entry), 1412 fEntry(entry), 1413 fBaseType(baseType), 1414 fLowerBound(lowerBound), 1415 fUpperBound(upperBound) 1416{ 1417 fBaseType->AcquireReference(); 1418} 1419 1420 1421DwarfSubrangeType::~DwarfSubrangeType() 1422{ 1423 fBaseType->ReleaseReference(); 1424} 1425 1426 1427Type* 1428DwarfSubrangeType::BaseType() const 1429{ 1430 return fBaseType; 1431} 1432 1433 1434DIEType* 1435DwarfSubrangeType::GetDIEType() const 1436{ 1437 return fEntry; 1438} 1439 1440 1441BVariant 1442DwarfSubrangeType::LowerBound() const 1443{ 1444 return fLowerBound; 1445} 1446 1447 1448BVariant 1449DwarfSubrangeType::UpperBound() const 1450{ 1451 return fUpperBound; 1452} 1453 1454 1455// #pragma mark - DwarfUnspecifiedType 1456 1457 1458DwarfUnspecifiedType::DwarfUnspecifiedType(DwarfTypeContext* typeContext, 1459 const BString& name, DIEUnspecifiedType* entry) 1460 : 1461 DwarfType(typeContext, name, entry), 1462 fEntry(entry) 1463{ 1464} 1465 1466 1467DwarfUnspecifiedType::~DwarfUnspecifiedType() 1468{ 1469} 1470 1471 1472DIEType* 1473DwarfUnspecifiedType::GetDIEType() const 1474{ 1475 return fEntry; 1476} 1477 1478 1479// #pragma mark - DwarfFunctionType 1480 1481 1482DwarfFunctionType::DwarfFunctionType(DwarfTypeContext* typeContext, 1483 const BString& name, DIESubroutineType* entry, DwarfType* returnType) 1484 : 1485 DwarfType(typeContext, name, entry), 1486 fEntry(entry), 1487 fReturnType(returnType), 1488 fHasVariableArguments(false) 1489{ 1490 if (fReturnType != NULL) 1491 fReturnType->AcquireReference(); 1492} 1493 1494 1495DwarfFunctionType::~DwarfFunctionType() 1496{ 1497 for (int32 i = 0; 1498 DwarfFunctionParameter* parameter = fParameters.ItemAt(i); i++) { 1499 parameter->ReleaseReference(); 1500 } 1501 1502 if (fReturnType != NULL) 1503 fReturnType->ReleaseReference(); 1504} 1505 1506 1507Type* 1508DwarfFunctionType::ReturnType() const 1509{ 1510 return fReturnType; 1511} 1512 1513 1514int32 1515DwarfFunctionType::CountParameters() const 1516{ 1517 return fParameters.CountItems(); 1518} 1519 1520 1521FunctionParameter* 1522DwarfFunctionType::ParameterAt(int32 index) const 1523{ 1524 return fParameters.ItemAt(index); 1525} 1526 1527 1528bool 1529DwarfFunctionType::HasVariableArguments() const 1530{ 1531 return fHasVariableArguments; 1532} 1533 1534 1535void 1536DwarfFunctionType::SetHasVariableArguments(bool hasVarArgs) 1537{ 1538 fHasVariableArguments = hasVarArgs; 1539} 1540 1541 1542DIEType* 1543DwarfFunctionType::GetDIEType() const 1544{ 1545 return fEntry; 1546} 1547 1548 1549bool 1550DwarfFunctionType::AddParameter(DwarfFunctionParameter* parameter) 1551{ 1552 if (!fParameters.AddItem(parameter)) 1553 return false; 1554 1555 parameter->AcquireReference(); 1556 return true; 1557} 1558 1559 1560// #pragma mark - DwarfPointerToMemberType 1561 1562 1563DwarfPointerToMemberType::DwarfPointerToMemberType( 1564 DwarfTypeContext* typeContext, const BString& name, 1565 DIEPointerToMemberType* entry, DwarfCompoundType* containingType, 1566 DwarfType* baseType) 1567 : 1568 DwarfType(typeContext, name, entry), 1569 fEntry(entry), 1570 fContainingType(containingType), 1571 fBaseType(baseType) 1572{ 1573 fContainingType->AcquireReference(); 1574 fBaseType->AcquireReference(); 1575} 1576 1577 1578DwarfPointerToMemberType::~DwarfPointerToMemberType() 1579{ 1580 fContainingType->ReleaseReference(); 1581 fBaseType->ReleaseReference(); 1582} 1583 1584 1585CompoundType* 1586DwarfPointerToMemberType::ContainingType() const 1587{ 1588 return fContainingType; 1589} 1590 1591 1592Type* 1593DwarfPointerToMemberType::BaseType() const 1594{ 1595 return fBaseType; 1596} 1597 1598 1599DIEType* 1600DwarfPointerToMemberType::GetDIEType() const 1601{ 1602 return fEntry; 1603} 1604