1 /* 2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2012-2018, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "DwarfImageDebugInfo.h" 9 10 #include <errno.h> 11 #include <stdio.h> 12 #include <unistd.h> 13 14 #include <algorithm> 15 #include <new> 16 17 #include <AutoDeleter.h> 18 #include <AutoLocker.h> 19 20 #include "Architecture.h" 21 #include "BasicFunctionDebugInfo.h" 22 #include "CLanguage.h" 23 #include "CompilationUnit.h" 24 #include "CppLanguage.h" 25 #include "CpuState.h" 26 #include "DebuggerInterface.h" 27 #include "DebugInfoEntries.h" 28 #include "Demangler.h" 29 #include "DisassembledCode.h" 30 #include "Dwarf.h" 31 #include "DwarfFile.h" 32 #include "DwarfFunctionDebugInfo.h" 33 #include "DwarfStackFrameDebugInfo.h" 34 #include "DwarfTargetInterface.h" 35 #include "DwarfTypeFactory.h" 36 #include "DwarfTypes.h" 37 #include "DwarfUtils.h" 38 #include "ElfFile.h" 39 #include "FileManager.h" 40 #include "FileSourceCode.h" 41 #include "FunctionID.h" 42 #include "FunctionInstance.h" 43 #include "GlobalTypeLookup.h" 44 #include "Image.h" 45 #include "ImageDebugInfo.h" 46 #include "InstructionInfo.h" 47 #include "LocatableFile.h" 48 #include "Register.h" 49 #include "RegisterMap.h" 50 #include "SourceFile.h" 51 #include "StackFrame.h" 52 #include "Statement.h" 53 #include "StringUtils.h" 54 #include "SymbolInfo.h" 55 #include "TargetAddressRangeList.h" 56 #include "Team.h" 57 #include "TeamFunctionSourceInformation.h" 58 #include "TeamMemory.h" 59 #include "Tracing.h" 60 #include "TypeLookupConstraints.h" 61 #include "UnsupportedLanguage.h" 62 #include "Variable.h" 63 #include "ValueLocation.h" 64 65 66 namespace { 67 68 69 // #pragma mark - HasTypePredicate 70 71 72 template<typename EntryType> 73 struct HasTypePredicate { 74 inline bool operator()(EntryType* entry) const 75 { 76 return entry->GetType() != NULL; 77 } 78 }; 79 80 } 81 82 83 // #pragma mark - BasicTargetInterface 84 85 86 struct DwarfImageDebugInfo::BasicTargetInterface : DwarfTargetInterface { 87 BasicTargetInterface(const Register* registers, int32 registerCount, 88 RegisterMap* fromDwarfMap, Architecture* architecture, 89 TeamMemory* teamMemory) 90 : 91 fRegisters(registers), 92 fRegisterCount(registerCount), 93 fFromDwarfMap(fromDwarfMap), 94 fArchitecture(architecture), 95 fTeamMemory(teamMemory) 96 { 97 fFromDwarfMap->AcquireReference(); 98 } 99 100 ~BasicTargetInterface() 101 { 102 fFromDwarfMap->ReleaseReference(); 103 } 104 105 virtual uint32 CountRegisters() const 106 { 107 return fRegisterCount; 108 } 109 110 virtual uint32 RegisterValueType(uint32 index) const 111 { 112 const Register* reg = _RegisterAt(index); 113 return reg != NULL ? reg->ValueType() : 0; 114 } 115 116 virtual bool GetRegisterValue(uint32 index, BVariant& _value) const 117 { 118 return false; 119 } 120 121 virtual bool SetRegisterValue(uint32 index, const BVariant& value) 122 { 123 return false; 124 } 125 126 virtual bool IsCalleePreservedRegister(uint32 index) const 127 { 128 const Register* reg = _RegisterAt(index); 129 return reg != NULL && reg->IsCalleePreserved(); 130 } 131 132 virtual status_t InitRegisterRules(CfaContext& context) const 133 { 134 return fArchitecture->InitRegisterRules(context); 135 } 136 137 virtual bool ReadMemory(target_addr_t address, void* buffer, 138 size_t size) const 139 { 140 ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, size); 141 return bytesRead >= 0 && (size_t)bytesRead == size; 142 } 143 144 virtual bool ReadValueFromMemory(target_addr_t address, 145 uint32 valueType, BVariant& _value) const 146 { 147 return fArchitecture->ReadValueFromMemory(address, valueType, _value) 148 == B_OK; 149 } 150 151 virtual bool ReadValueFromMemory(target_addr_t addressSpace, 152 target_addr_t address, uint32 valueType, BVariant& _value) const 153 { 154 return fArchitecture->ReadValueFromMemory(addressSpace, address, 155 valueType, _value) == B_OK; 156 } 157 158 protected: 159 const Register* _RegisterAt(uint32 dwarfIndex) const 160 { 161 int32 index = fFromDwarfMap->MapRegisterIndex(dwarfIndex); 162 return index >= 0 && index < fRegisterCount ? fRegisters + index : NULL; 163 } 164 165 protected: 166 const Register* fRegisters; 167 int32 fRegisterCount; 168 RegisterMap* fFromDwarfMap; 169 Architecture* fArchitecture; 170 TeamMemory* fTeamMemory; 171 }; 172 173 174 // #pragma mark - UnwindTargetInterface 175 176 177 struct DwarfImageDebugInfo::UnwindTargetInterface : BasicTargetInterface { 178 UnwindTargetInterface(const Register* registers, int32 registerCount, 179 RegisterMap* fromDwarfMap, RegisterMap* toDwarfMap, CpuState* cpuState, 180 Architecture* architecture, TeamMemory* teamMemory) 181 : 182 BasicTargetInterface(registers, registerCount, fromDwarfMap, 183 architecture, teamMemory), 184 fToDwarfMap(toDwarfMap), 185 fCpuState(cpuState) 186 { 187 fToDwarfMap->AcquireReference(); 188 fCpuState->AcquireReference(); 189 } 190 191 ~UnwindTargetInterface() 192 { 193 fToDwarfMap->ReleaseReference(); 194 fCpuState->ReleaseReference(); 195 } 196 197 virtual bool GetRegisterValue(uint32 index, BVariant& _value) const 198 { 199 const Register* reg = _RegisterAt(index); 200 if (reg == NULL) 201 return false; 202 return fCpuState->GetRegisterValue(reg, _value); 203 } 204 205 virtual bool SetRegisterValue(uint32 index, const BVariant& value) 206 { 207 const Register* reg = _RegisterAt(index); 208 if (reg == NULL) 209 return false; 210 return fCpuState->SetRegisterValue(reg, value); 211 } 212 213 private: 214 RegisterMap* fToDwarfMap; 215 CpuState* fCpuState; 216 }; 217 218 219 // #pragma mark - EntryListWrapper 220 221 222 /*! Wraps a DebugInfoEntryList, which is a typedef and thus cannot appear in 223 the header, since our policy disallows us to include DWARF headers there. 224 */ 225 struct DwarfImageDebugInfo::EntryListWrapper { 226 const DebugInfoEntryList& list; 227 228 EntryListWrapper(const DebugInfoEntryList& list) 229 : 230 list(list) 231 { 232 } 233 }; 234 235 236 // #pragma mark - DwarfImageDebugInfo::TypeNameKey 237 238 239 struct DwarfImageDebugInfo::TypeNameKey { 240 BString typeName; 241 242 TypeNameKey(const BString& typeName) 243 : 244 typeName(typeName) 245 { 246 } 247 248 uint32 HashValue() const 249 { 250 return StringUtils::HashValue(typeName); 251 } 252 253 bool operator==(const TypeNameKey& other) const 254 { 255 return typeName == other.typeName; 256 } 257 }; 258 259 260 // #pragma mark - DwarfImageDebugInfo::TypeNameEntry 261 262 263 struct DwarfImageDebugInfo::TypeNameEntry : TypeNameKey { 264 TypeNameEntry* next; 265 TypeEntryList types; 266 267 TypeNameEntry(const BString& name) 268 : 269 TypeNameKey(name), 270 types(10, true) 271 { 272 } 273 274 ~TypeNameEntry() 275 { 276 } 277 278 }; 279 280 281 // #pragma mark - DwarfImageDebugInfo::TypeNameEntryHashDefinition 282 283 284 struct DwarfImageDebugInfo::TypeNameEntryHashDefinition { 285 typedef TypeNameKey KeyType; 286 typedef TypeNameEntry ValueType; 287 288 size_t HashKey(const TypeNameKey& key) const 289 { 290 return key.HashValue(); 291 } 292 293 size_t Hash(const TypeNameEntry* value) const 294 { 295 return value->HashValue(); 296 } 297 298 bool Compare(const TypeNameKey& key, 299 const TypeNameEntry* value) const 300 { 301 return key == *value; 302 } 303 304 TypeNameEntry*& GetLink(TypeNameEntry* value) const 305 { 306 return value->next; 307 } 308 }; 309 310 311 // #pragma mark - DwarfImageDebugInfo::TypeEntryInfo 312 313 314 struct DwarfImageDebugInfo::TypeEntryInfo { 315 DIEType* type; 316 CompilationUnit* unit; 317 318 TypeEntryInfo(DIEType* type, CompilationUnit* unit) 319 : 320 type(type), 321 unit(unit) 322 { 323 } 324 }; 325 326 327 // #pragma mark - DwarfImageDebugInfo 328 329 330 DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, 331 DebuggerInterface* interface, Architecture* architecture, 332 FileManager* fileManager, GlobalTypeLookup* typeLookup, 333 GlobalTypeCache* typeCache, TeamFunctionSourceInformation* sourceInfo, 334 DwarfFile* file) 335 : 336 fLock("dwarf image debug info"), 337 fImageInfo(imageInfo), 338 fDebuggerInterface(interface), 339 fArchitecture(architecture), 340 fFileManager(fileManager), 341 fTypeLookup(typeLookup), 342 fTypeCache(typeCache), 343 fSourceInfo(sourceInfo), 344 fTypeNameTable(NULL), 345 fFile(file), 346 fTextSegment(NULL), 347 fRelocationDelta(0), 348 fTextSectionStart(0), 349 fTextSectionEnd(0), 350 fPLTSectionStart(0), 351 fPLTSectionEnd(0) 352 { 353 fDebuggerInterface->AcquireReference(); 354 fFile->AcquireReference(); 355 fTypeCache->AcquireReference(); 356 } 357 358 359 DwarfImageDebugInfo::~DwarfImageDebugInfo() 360 { 361 fDebuggerInterface->ReleaseReference(); 362 fFile->ReleaseReference(); 363 fTypeCache->ReleaseReference(); 364 365 TypeNameEntry* entry = fTypeNameTable->Clear(true); 366 while (entry != NULL) { 367 TypeNameEntry* next = entry->next; 368 delete entry; 369 entry = next; 370 } 371 delete fTypeNameTable; 372 } 373 374 375 status_t 376 DwarfImageDebugInfo::Init() 377 { 378 status_t error = fLock.InitCheck(); 379 if (error != B_OK) 380 return error; 381 382 fTextSegment = fFile->GetElfFile()->TextSegment(); 383 if (fTextSegment == NULL) 384 return B_ENTRY_NOT_FOUND; 385 386 fRelocationDelta = fImageInfo.TextBase() - fTextSegment->LoadAddress(); 387 388 ElfSection* section = fFile->GetElfFile()->FindSection(".text"); 389 if (section != NULL) { 390 fTextSectionStart = section->LoadAddress() + fRelocationDelta; 391 fTextSectionEnd = fTextSectionStart + section->Size(); 392 } 393 394 section = fFile->GetElfFile()->FindSection(".plt"); 395 if (section != NULL) { 396 fPLTSectionStart = section->LoadAddress() + fRelocationDelta; 397 fPLTSectionEnd = fPLTSectionStart + section->Size(); 398 } 399 400 return _BuildTypeNameTable(); 401 } 402 403 404 status_t 405 DwarfImageDebugInfo::GetFunctions(const BObjectList<SymbolInfo>& symbols, 406 BObjectList<FunctionDebugInfo>& functions) 407 { 408 TRACE_IMAGES("DwarfImageDebugInfo::GetFunctions()\n"); 409 TRACE_IMAGES(" %" B_PRId32 " compilation units\n", 410 fFile->CountCompilationUnits()); 411 412 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 413 i++) { 414 DIECompileUnitBase* unitEntry = unit->UnitEntry(); 415 // printf(" %s:\n", unitEntry->Name()); 416 // printf(" address ranges:\n"); 417 // TargetAddressRangeList* rangeList = unitEntry->AddressRanges(); 418 // if (rangeList != NULL) { 419 // int32 count = rangeList->CountRanges(); 420 // for (int32 i = 0; i < count; i++) { 421 // TargetAddressRange range = rangeList->RangeAt(i); 422 // printf(" %#llx - %#llx\n", range.Start(), range.End()); 423 // } 424 // } else { 425 // printf(" %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(), 426 // (target_addr_t)unitEntry->HighPC()); 427 // } 428 429 // printf(" functions:\n"); 430 for (DebugInfoEntryList::ConstIterator it 431 = unitEntry->OtherChildren().GetIterator(); 432 DebugInfoEntry* entry = it.Next();) { 433 if (entry->Tag() != DW_TAG_subprogram) 434 continue; 435 436 DIESubprogram* subprogramEntry = static_cast<DIESubprogram*>(entry); 437 438 // ignore declarations and inlined functions 439 if (subprogramEntry->IsDeclaration() 440 || subprogramEntry->Inline() == DW_INL_inlined 441 || subprogramEntry->Inline() == DW_INL_declared_inlined) { 442 continue; 443 } 444 445 // get the name 446 BString name; 447 DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name); 448 if (name.Length() == 0) 449 continue; 450 451 // get the address ranges 452 TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit, 453 subprogramEntry->AddressRangesOffset()); 454 if (rangeList == NULL) { 455 target_addr_t lowPC = subprogramEntry->LowPC(); 456 target_addr_t highPC = subprogramEntry->HighPC(); 457 if (highPC <= lowPC) 458 continue; 459 460 rangeList = new(std::nothrow) TargetAddressRangeList( 461 TargetAddressRange(lowPC, highPC - lowPC)); 462 if (rangeList == NULL) 463 return B_NO_MEMORY; 464 // TODO: Clean up already added functions! 465 } 466 BReference<TargetAddressRangeList> rangeListReference(rangeList, 467 true); 468 469 // get the source location 470 const char* directoryPath = NULL; 471 const char* fileName = NULL; 472 int32 line = -1; 473 int32 column = -1; 474 DwarfUtils::GetDeclarationLocation(fFile, subprogramEntry, 475 directoryPath, fileName, line, column); 476 477 LocatableFile* file = NULL; 478 if (fileName != NULL) { 479 file = fFileManager->GetSourceFile(directoryPath, 480 fileName); 481 } 482 BReference<LocatableFile> fileReference(file, true); 483 484 // create and add the functions 485 DwarfFunctionDebugInfo* function 486 = new(std::nothrow) DwarfFunctionDebugInfo(this, unit, 487 subprogramEntry, rangeList, name, file, 488 SourceLocation(line, std::max(column, (int32)0))); 489 if (function == NULL || !functions.AddItem(function)) { 490 delete function; 491 return B_NO_MEMORY; 492 // TODO: Clean up already added functions! 493 } 494 495 // BString name; 496 // DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name); 497 // printf(" subprogram entry: %p, name: %s, declaration: %d\n", 498 // subprogramEntry, name.String(), 499 // subprogramEntry->IsDeclaration()); 500 // 501 // rangeList = subprogramEntry->AddressRanges(); 502 // if (rangeList != NULL) { 503 // int32 count = rangeList->CountRanges(); 504 // for (int32 i = 0; i < count; i++) { 505 // TargetAddressRange range = rangeList->RangeAt(i); 506 // printf(" %#llx - %#llx\n", range.Start(), range.End()); 507 // } 508 // } else { 509 // printf(" %#llx - %#llx\n", 510 // (target_addr_t)subprogramEntry->LowPC(), 511 // (target_addr_t)subprogramEntry->HighPC()); 512 // } 513 } 514 } 515 516 if (fFile->CountCompilationUnits() != 0) 517 return B_OK; 518 519 // if we had no compilation units, fall back to providing basic 520 // debug infos with DWARF-supported call frame unwinding, 521 // if available. 522 if (fFile->HasFrameInformation()) { 523 return SpecificImageDebugInfo::GetFunctionsFromSymbols(symbols, 524 functions, fDebuggerInterface, fImageInfo, this); 525 } 526 527 return B_OK; 528 } 529 530 531 status_t 532 DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, 533 const TypeLookupConstraints& constraints, Type*& _type) 534 { 535 TypeNameEntry* entry = fTypeNameTable->Lookup(name); 536 if (entry == NULL) 537 return B_ENTRY_NOT_FOUND; 538 539 for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) { 540 DIEType* typeEntry = info->type; 541 if (constraints.HasTypeKind()) { 542 if (dwarf_tag_to_type_kind(typeEntry->Tag()) 543 != constraints.TypeKind()) { 544 continue; 545 } 546 547 if (!_EvaluateBaseTypeConstraints(typeEntry, constraints)) 548 continue; 549 } 550 551 if (constraints.HasSubtypeKind() 552 && dwarf_tag_to_subtype_kind(typeEntry->Tag()) 553 != constraints.SubtypeKind()) { 554 continue; 555 } 556 557 int32 registerCount = fArchitecture->CountRegisters(); 558 const Register* registers = fArchitecture->Registers(); 559 560 // get the DWARF <-> architecture register maps 561 RegisterMap* toDwarfMap; 562 RegisterMap* fromDwarfMap; 563 status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, 564 &fromDwarfMap); 565 if (error != B_OK) 566 return error; 567 568 BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true); 569 BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); 570 571 // create the target interface 572 BasicTargetInterface* targetInterface 573 = new(std::nothrow) BasicTargetInterface(registers, registerCount, 574 fromDwarfMap, fArchitecture, fDebuggerInterface); 575 if (targetInterface == NULL) 576 return B_NO_MEMORY; 577 578 BReference<BasicTargetInterface> targetInterfaceReference( 579 targetInterface, true); 580 581 DwarfTypeContext* typeContext = new(std::nothrow) 582 DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile, 583 info->unit, NULL, 0, 0, fRelocationDelta, targetInterface, NULL); 584 if (typeContext == NULL) 585 return B_NO_MEMORY; 586 BReference<DwarfTypeContext> typeContextReference(typeContext, true); 587 588 // create the type 589 DwarfType* type; 590 DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache); 591 error = typeFactory.CreateType(typeEntry, type); 592 if (error != B_OK) 593 continue; 594 595 _type = type; 596 return B_OK; 597 } 598 599 return B_ENTRY_NOT_FOUND; 600 } 601 602 603 bool 604 DwarfImageDebugInfo::HasType(const BString& name, 605 const TypeLookupConstraints& constraints) const 606 { 607 TypeNameEntry* entry = fTypeNameTable->Lookup(name); 608 if (entry == NULL) 609 return false; 610 611 for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) { 612 DIEType* typeEntry = info->type; 613 if (constraints.HasTypeKind()) { 614 if (dwarf_tag_to_type_kind(typeEntry->Tag()) 615 != constraints.TypeKind()) { 616 continue; 617 } 618 619 if (!_EvaluateBaseTypeConstraints(typeEntry, constraints)) 620 continue; 621 } 622 623 if (constraints.HasSubtypeKind() 624 && dwarf_tag_to_subtype_kind(typeEntry->Tag()) 625 != constraints.SubtypeKind()) { 626 continue; 627 } 628 629 return true; 630 } 631 632 return false; 633 } 634 635 636 AddressSectionType 637 DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address) 638 { 639 if (address >= fTextSectionStart && address < fTextSectionEnd) 640 return ADDRESS_SECTION_TYPE_FUNCTION; 641 642 if (address >= fPLTSectionStart && address < fPLTSectionEnd) 643 return ADDRESS_SECTION_TYPE_PLT; 644 645 return ADDRESS_SECTION_TYPE_UNKNOWN; 646 } 647 648 649 status_t 650 DwarfImageDebugInfo::CreateFrame(Image* image, 651 FunctionInstance* functionInstance, CpuState* cpuState, 652 bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos, 653 StackFrame*& _frame, CpuState*& _previousCpuState) 654 { 655 DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( 656 functionInstance->GetFunctionDebugInfo()); 657 658 FunctionID* functionID = functionInstance->GetFunctionID(); 659 BReference<FunctionID> functionIDReference; 660 if (functionID != NULL) 661 functionIDReference.SetTo(functionID, true); 662 663 DIESubprogram* entry = function != NULL 664 ? function->SubprogramEntry() : NULL; 665 666 TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, " 667 "function: %s\n", entry, 668 functionID->FunctionName().String()); 669 670 int32 registerCount = fArchitecture->CountRegisters(); 671 const Register* registers = fArchitecture->Registers(); 672 673 // get the DWARF <-> architecture register maps 674 RegisterMap* toDwarfMap; 675 RegisterMap* fromDwarfMap; 676 status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, 677 &fromDwarfMap); 678 if (error != B_OK) 679 return error; 680 BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true); 681 BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); 682 683 // create a clean CPU state for the previous frame 684 CpuState* previousCpuState; 685 error = fArchitecture->CreateCpuState(previousCpuState); 686 if (error != B_OK) 687 return error; 688 BReference<CpuState> previousCpuStateReference(previousCpuState, true); 689 690 // create the target interfaces 691 UnwindTargetInterface* inputInterface 692 = new(std::nothrow) UnwindTargetInterface(registers, registerCount, 693 fromDwarfMap, toDwarfMap, cpuState, fArchitecture, 694 fDebuggerInterface); 695 if (inputInterface == NULL) 696 return B_NO_MEMORY; 697 BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface, 698 true); 699 700 UnwindTargetInterface* outputInterface 701 = new(std::nothrow) UnwindTargetInterface(registers, registerCount, 702 fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, 703 fDebuggerInterface); 704 if (outputInterface == NULL) 705 return B_NO_MEMORY; 706 BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface, 707 true); 708 709 // do the unwinding 710 target_addr_t instructionPointer 711 = cpuState->InstructionPointer() - fRelocationDelta; 712 target_addr_t framePointer; 713 CompilationUnit* unit = function != NULL ? function->GetCompilationUnit() 714 : NULL; 715 error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry, 716 instructionPointer, inputInterface, outputInterface, framePointer); 717 718 if (error != B_OK) { 719 TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); 720 return B_UNSUPPORTED; 721 } 722 723 TRACE_CFI_ONLY( 724 TRACE_CFI("unwound registers:\n"); 725 for (int32 i = 0; i < registerCount; i++) { 726 const Register* reg = registers + i; 727 BVariant value; 728 if (previousCpuState->GetRegisterValue(reg, value)) { 729 TRACE_CFI(" %3s: %#" B_PRIx64 "\n", reg->Name(), 730 value.ToUInt64()); 731 } else 732 TRACE_CFI(" %3s: undefined\n", reg->Name()); 733 } 734 ) 735 736 // create the stack frame debug info 737 DIESubprogram* subprogramEntry = function != NULL ? 738 function->SubprogramEntry() : NULL; 739 DwarfStackFrameDebugInfo* stackFrameDebugInfo 740 = new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, 741 fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup, 742 fTypeCache, instructionPointer, framePointer, fRelocationDelta, 743 inputInterface, fromDwarfMap); 744 if (stackFrameDebugInfo == NULL) 745 return B_NO_MEMORY; 746 BReference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference( 747 stackFrameDebugInfo, true); 748 749 error = stackFrameDebugInfo->Init(); 750 if (error != B_OK) 751 return error; 752 753 // create the stack frame 754 StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD, 755 cpuState, framePointer, cpuState->InstructionPointer(), 756 stackFrameDebugInfo); 757 if (frame == NULL) 758 return B_NO_MEMORY; 759 BReference<StackFrame> frameReference(frame, true); 760 761 error = frame->Init(); 762 if (error != B_OK) 763 return error; 764 765 frame->SetReturnAddress(previousCpuState->InstructionPointer()); 766 // Note, this is correct, since we actually retrieved the return 767 // address. Our caller will fix the IP for us. 768 769 // The subprogram entry may not be available since this may be a case 770 // where .eh_frame was used to unwind the stack without other DWARF 771 // info being available. 772 if (subprogramEntry != NULL && getFullFrameInfo) { 773 // create function parameter objects 774 for (DebugInfoEntryList::ConstIterator it 775 = subprogramEntry->Parameters().GetIterator(); 776 DebugInfoEntry* entry = it.Next();) { 777 if (entry->Tag() != DW_TAG_formal_parameter) 778 continue; 779 780 BString parameterName; 781 DwarfUtils::GetDIEName(entry, parameterName); 782 if (parameterName.Length() == 0) 783 continue; 784 785 DIEFormalParameter* parameterEntry 786 = dynamic_cast<DIEFormalParameter*>(entry); 787 Variable* parameter; 788 if (stackFrameDebugInfo->CreateParameter(functionID, 789 parameterEntry, parameter) != B_OK) { 790 continue; 791 } 792 BReference<Variable> parameterReference(parameter, true); 793 794 if (!frame->AddParameter(parameter)) 795 return B_NO_MEMORY; 796 } 797 798 // create objects for the local variables 799 _CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo, 800 instructionPointer, functionInstance->Address() - fRelocationDelta, 801 subprogramEntry->Variables(), subprogramEntry->Blocks()); 802 803 if (returnValueInfos != NULL && !returnValueInfos->IsEmpty()) { 804 _CreateReturnValues(returnValueInfos, image, frame, 805 *stackFrameDebugInfo); 806 } 807 } 808 809 _frame = frameReference.Detach(); 810 _previousCpuState = previousCpuStateReference.Detach(); 811 812 frame->SetPreviousCpuState(_previousCpuState); 813 814 return B_OK; 815 } 816 817 818 status_t 819 DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function, 820 target_addr_t address, Statement*& _statement) 821 { 822 TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#" 823 B_PRIx64 ")\n", _function, address); 824 825 DwarfFunctionDebugInfo* function 826 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 827 if (function == NULL) { 828 TRACE_LINES(" -> no dwarf function\n"); 829 // fall back to assembly 830 return fArchitecture->GetStatement(function, address, _statement); 831 } 832 833 AutoLocker<BLocker> locker(fLock); 834 835 // check whether we have the source code 836 CompilationUnit* unit = function->GetCompilationUnit(); 837 LocatableFile* file = function->SourceFile(); 838 if (file == NULL) { 839 TRACE_CODE(" -> no source file\n"); 840 841 // no source code -- rather return the assembly statement 842 return fArchitecture->GetStatement(function, address, _statement); 843 } 844 845 SourceCode* sourceCode = NULL; 846 status_t error = fSourceInfo->GetActiveSourceCode(_function, sourceCode); 847 BReference<SourceCode> sourceReference(sourceCode, true); 848 if (error != B_OK || dynamic_cast<DisassembledCode*>(sourceCode) != NULL) { 849 // either no source code or disassembly is currently active (i.e. 850 // due to failing to locate the source file on disk or the user 851 // deliberately switching to disassembly view). 852 // return the assembly statement. 853 return fArchitecture->GetStatement(function, address, _statement); 854 } 855 856 // get the index of the source file in the compilation unit for cheaper 857 // comparison below 858 int32 fileIndex = _GetSourceFileIndex(unit, file); 859 860 // Get the statement by executing the line number program for the 861 // compilation unit. 862 LineNumberProgram& program = unit->GetLineNumberProgram(); 863 if (!program.IsValid()) { 864 TRACE_CODE(" -> no line number program\n"); 865 return B_BAD_DATA; 866 } 867 868 // adjust address 869 address -= fRelocationDelta; 870 871 LineNumberProgram::State state; 872 program.GetInitialState(state); 873 874 target_addr_t statementAddress = 0; 875 int32 statementLine = -1; 876 int32 statementColumn = -1; 877 while (program.GetNextRow(state)) { 878 // skip statements of other files 879 if (state.file != fileIndex) 880 continue; 881 882 if (statementAddress != 0 883 && (state.isStatement || state.isSequenceEnd)) { 884 target_addr_t endAddress = state.address; 885 if (address >= statementAddress && address < endAddress) { 886 ContiguousStatement* statement = new(std::nothrow) 887 ContiguousStatement( 888 SourceLocation(statementLine, statementColumn), 889 TargetAddressRange(fRelocationDelta + statementAddress, 890 endAddress - statementAddress)); 891 if (statement == NULL) 892 return B_NO_MEMORY; 893 894 _statement = statement; 895 return B_OK; 896 } 897 898 statementAddress = 0; 899 } 900 901 if (state.isStatement) { 902 statementAddress = state.address; 903 statementLine = state.line - 1; 904 statementColumn = std::max(state.column - 1, (int32)0); 905 } 906 } 907 908 TRACE_CODE(" -> no line number program match\n"); 909 return B_ENTRY_NOT_FOUND; 910 } 911 912 913 status_t 914 DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function, 915 const SourceLocation& sourceLocation, Statement*& _statement) 916 { 917 DwarfFunctionDebugInfo* function 918 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 919 if (function == NULL) 920 return B_BAD_VALUE; 921 922 target_addr_t functionStartAddress = function->Address() - fRelocationDelta; 923 target_addr_t functionEndAddress = functionStartAddress + function->Size(); 924 925 TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, " 926 "(%" B_PRId32 ", %" B_PRId32 ")): function range: %#" B_PRIx64 " - %#" 927 B_PRIx64 "\n", function, sourceLocation.Line(), sourceLocation.Column(), 928 functionStartAddress, functionEndAddress); 929 930 AutoLocker<BLocker> locker(fLock); 931 932 // get the source file 933 LocatableFile* file = function->SourceFile(); 934 if (file == NULL) 935 return B_ENTRY_NOT_FOUND; 936 937 CompilationUnit* unit = function->GetCompilationUnit(); 938 939 // get the index of the source file in the compilation unit for cheaper 940 // comparison below 941 int32 fileIndex = _GetSourceFileIndex(unit, file); 942 943 // Get the statement by executing the line number program for the 944 // compilation unit. 945 LineNumberProgram& program = unit->GetLineNumberProgram(); 946 if (!program.IsValid()) 947 return B_BAD_DATA; 948 949 LineNumberProgram::State state; 950 program.GetInitialState(state); 951 952 target_addr_t statementAddress = 0; 953 int32 statementLine = -1; 954 int32 statementColumn = -1; 955 while (program.GetNextRow(state)) { 956 bool isOurFile = state.file == fileIndex; 957 958 if (statementAddress != 0 959 && (!isOurFile || state.isStatement || state.isSequenceEnd)) { 960 target_addr_t endAddress = state.address; 961 962 if (statementAddress < endAddress) { 963 TRACE_LINES2(" statement: %#" B_PRIx64 " - %#" B_PRIx64 964 ", location: (%" B_PRId32 ", %" B_PRId32 ")\n", 965 statementAddress, endAddress, statementLine, 966 statementColumn); 967 } 968 969 if (statementAddress < endAddress 970 && statementAddress >= functionStartAddress 971 && statementAddress < functionEndAddress 972 && statementLine == (int32)sourceLocation.Line() 973 && statementColumn == (int32)sourceLocation.Column()) { 974 TRACE_LINES2(" -> found statement!\n"); 975 976 ContiguousStatement* statement = new(std::nothrow) 977 ContiguousStatement( 978 SourceLocation(statementLine, statementColumn), 979 TargetAddressRange(fRelocationDelta + statementAddress, 980 endAddress - statementAddress)); 981 if (statement == NULL) 982 return B_NO_MEMORY; 983 984 _statement = statement; 985 return B_OK; 986 } 987 988 statementAddress = 0; 989 } 990 991 // skip statements of other files 992 if (!isOurFile) 993 continue; 994 995 if (state.isStatement) { 996 statementAddress = state.address; 997 statementLine = state.line - 1; 998 statementColumn = std::max(state.column - 1, (int32)0); 999 } 1000 } 1001 1002 return B_ENTRY_NOT_FOUND; 1003 } 1004 1005 1006 status_t 1007 DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo* _function, 1008 SourceLanguage*& _language) 1009 { 1010 DwarfFunctionDebugInfo* function 1011 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 1012 if (function == NULL) 1013 return B_BAD_VALUE; 1014 1015 SourceLanguage* language; 1016 CompilationUnit* unit = function->GetCompilationUnit(); 1017 switch (unit->UnitEntry()->Language()) { 1018 case DW_LANG_C89: 1019 case DW_LANG_C: 1020 case DW_LANG_C99: 1021 language = new(std::nothrow) CLanguage; 1022 break; 1023 case DW_LANG_C_plus_plus: 1024 language = new(std::nothrow) CppLanguage; 1025 break; 1026 case 0: 1027 default: 1028 language = new(std::nothrow) UnsupportedLanguage; 1029 break; 1030 } 1031 1032 if (language == NULL) 1033 return B_NO_MEMORY; 1034 1035 _language = language; 1036 return B_OK; 1037 } 1038 1039 1040 ssize_t 1041 DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size) 1042 { 1043 target_addr_t offset = address - fRelocationDelta 1044 - fTextSegment->LoadAddress() + fTextSegment->FileOffset(); 1045 ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset); 1046 return bytesRead >= 0 ? bytesRead : errno; 1047 } 1048 1049 1050 status_t 1051 DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file, 1052 FileSourceCode* sourceCode) 1053 { 1054 bool addedAny = false; 1055 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 1056 i++) { 1057 int32 fileIndex = _GetSourceFileIndex(unit, file); 1058 if (fileIndex < 0) 1059 continue; 1060 1061 status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex); 1062 if (error == B_NO_MEMORY) 1063 return error; 1064 addedAny |= error == B_OK; 1065 } 1066 1067 return addedAny ? B_OK : B_ENTRY_NOT_FOUND; 1068 } 1069 1070 1071 status_t 1072 DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit, 1073 FileSourceCode* sourceCode, int32 fileIndex) 1074 { 1075 // Get the statements by executing the line number program for the 1076 // compilation unit and filtering the rows for our source file. 1077 LineNumberProgram& program = unit->GetLineNumberProgram(); 1078 if (!program.IsValid()) 1079 return B_BAD_DATA; 1080 1081 LineNumberProgram::State state; 1082 program.GetInitialState(state); 1083 1084 target_addr_t statementAddress = 0; 1085 int32 statementLine = -1; 1086 int32 statementColumn = -1; 1087 while (program.GetNextRow(state)) { 1088 TRACE_LINES2(" %#" B_PRIx64 " (%" B_PRId32 ", %" B_PRId32 ", %" 1089 B_PRId32 ") %d\n", state.address, state.file, state.line, 1090 state.column, state.isStatement); 1091 1092 bool isOurFile = state.file == fileIndex; 1093 1094 if (statementAddress != 0 1095 && (!isOurFile || state.isStatement || state.isSequenceEnd)) { 1096 target_addr_t endAddress = state.address; 1097 if (endAddress > statementAddress) { 1098 // add the statement 1099 status_t error = sourceCode->AddSourceLocation( 1100 SourceLocation(statementLine, statementColumn)); 1101 if (error != B_OK) 1102 return error; 1103 1104 TRACE_LINES2(" -> statement: %#" B_PRIx64 " - %#" B_PRIx64 1105 ", source location: (%" B_PRId32 ", %" B_PRId32 ")\n", 1106 statementAddress, endAddress, statementLine, 1107 statementColumn); 1108 } 1109 1110 statementAddress = 0; 1111 } 1112 1113 // skip statements of other files 1114 if (!isOurFile) 1115 continue; 1116 1117 if (state.isStatement) { 1118 statementAddress = state.address; 1119 statementLine = state.line - 1; 1120 statementColumn = std::max(state.column - 1, (int32)0); 1121 } 1122 } 1123 1124 return B_OK; 1125 } 1126 1127 1128 int32 1129 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit, 1130 LocatableFile* sourceFile) const 1131 { 1132 // get the index of the source file in the compilation unit for cheaper 1133 // comparison below 1134 const char* directory; 1135 for (int32 i = 0; const char* fileName = unit->FileAt(i, &directory); i++) { 1136 LocatableFile* file = fFileManager->GetSourceFile(directory, fileName); 1137 if (file != NULL) { 1138 BReference<LocatableFile> fileReference(file, true); 1139 if (file == sourceFile) { 1140 return i + 1; 1141 // indices are one-based 1142 } 1143 } 1144 } 1145 1146 return -1; 1147 } 1148 1149 1150 status_t 1151 DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit, 1152 StackFrame* frame, FunctionID* functionID, 1153 DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer, 1154 target_addr_t lowPC, const EntryListWrapper& variableEntries, 1155 const EntryListWrapper& blockEntries) 1156 { 1157 TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64 1158 ", low PC: %#" B_PRIx64 "\n", instructionPointer, lowPC); 1159 1160 // iterate through the variables and add the ones in scope 1161 for (DebugInfoEntryList::ConstIterator it 1162 = variableEntries.list.GetIterator(); 1163 DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) { 1164 1165 TRACE_LOCALS(" variableEntry %p, scope start: %" B_PRIu64 "\n", 1166 variableEntry, variableEntry->StartScope()); 1167 1168 // check the variable's scope 1169 if (instructionPointer < lowPC + variableEntry->StartScope()) 1170 continue; 1171 1172 // add the variable 1173 Variable* variable; 1174 if (factory.CreateLocalVariable(functionID, variableEntry, variable) 1175 != B_OK) { 1176 continue; 1177 } 1178 BReference<Variable> variableReference(variable, true); 1179 1180 if (!frame->AddLocalVariable(variable)) 1181 return B_NO_MEMORY; 1182 } 1183 1184 // iterate through the blocks and find the one we're currently in (if any) 1185 for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator(); 1186 DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) { 1187 1188 TRACE_LOCALS(" lexical block: %p\n", block); 1189 1190 // check whether the block has low/high PC attributes 1191 if (block->LowPC() != 0) { 1192 TRACE_LOCALS(" has lowPC\n"); 1193 1194 // yep, compare with the instruction pointer 1195 if (instructionPointer < block->LowPC() 1196 || instructionPointer >= block->HighPC()) { 1197 continue; 1198 } 1199 } else { 1200 TRACE_LOCALS(" no lowPC\n"); 1201 1202 // check the address ranges instead 1203 TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit, 1204 block->AddressRangesOffset()); 1205 if (rangeList == NULL) { 1206 TRACE_LOCALS(" failed to get ranges\n"); 1207 continue; 1208 } 1209 BReference<TargetAddressRangeList> rangeListReference(rangeList, 1210 true); 1211 1212 if (!rangeList->Contains(instructionPointer)) { 1213 TRACE_LOCALS(" ranges don't contain IP\n"); 1214 continue; 1215 } 1216 } 1217 1218 // found a block -- recurse 1219 return _CreateLocalVariables(unit, frame, functionID, factory, 1220 instructionPointer, lowPC, block->Variables(), block->Blocks()); 1221 } 1222 1223 return B_OK; 1224 } 1225 1226 1227 status_t 1228 DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos, 1229 Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory) 1230 { 1231 for (int32 i = 0; i < returnValueInfos->CountItems(); i++) { 1232 Image* targetImage = image; 1233 ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i); 1234 target_addr_t subroutineAddress = valueInfo->SubroutineAddress(); 1235 CpuState* subroutineState = valueInfo->State(); 1236 if (!targetImage->ContainsAddress(subroutineAddress)) { 1237 // our current image doesn't contain the target function, 1238 // locate the one which does. 1239 targetImage = image->GetTeam()->ImageByAddress(subroutineAddress); 1240 if (targetImage == NULL) { 1241 // nothing we can do, try the next entry (if any) 1242 continue; 1243 } 1244 } 1245 1246 status_t result = B_OK; 1247 ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo(); 1248 if (imageInfo == NULL) { 1249 // the subroutine may have resolved to a different image 1250 // that doesn't have debug information available. 1251 continue; 1252 } 1253 1254 FunctionInstance* targetFunction; 1255 if (imageInfo->GetAddressSectionType(subroutineAddress) 1256 == ADDRESS_SECTION_TYPE_PLT) { 1257 result = fArchitecture->ResolvePICFunctionAddress( 1258 subroutineAddress, subroutineState, subroutineAddress); 1259 if (result != B_OK) 1260 continue; 1261 if (!targetImage->ContainsAddress(subroutineAddress)) { 1262 // the PLT entry doesn't necessarily point to a function 1263 // in the same image; as such we may need to try to 1264 // resolve the target address again. 1265 targetImage = image->GetTeam()->ImageByAddress( 1266 subroutineAddress); 1267 if (targetImage == NULL) 1268 continue; 1269 imageInfo = targetImage->GetImageDebugInfo(); 1270 if (imageInfo == NULL) { 1271 // As above, since the indirection here may have 1272 // landed us in an entirely different image, there is 1273 // no guarantee that debug info is available, 1274 // depending on which image it was. 1275 continue; 1276 } 1277 1278 } 1279 } 1280 1281 targetFunction = imageInfo->FunctionAtAddress(subroutineAddress); 1282 if (targetFunction != NULL) { 1283 DwarfFunctionDebugInfo* targetInfo = 1284 dynamic_cast<DwarfFunctionDebugInfo*>( 1285 targetFunction->GetFunctionDebugInfo()); 1286 if (targetInfo != NULL) { 1287 DIESubprogram* subProgram = targetInfo->SubprogramEntry(); 1288 DIEType* returnType = subProgram->ReturnType(); 1289 if (returnType == NULL) { 1290 // check if we have a specification, and if so, if that has 1291 // a return type 1292 subProgram = dynamic_cast<DIESubprogram*>( 1293 subProgram->Specification()); 1294 if (subProgram != NULL) 1295 returnType = subProgram->ReturnType(); 1296 1297 // function doesn't return a value, we're done. 1298 if (returnType == NULL) 1299 return B_OK; 1300 } 1301 1302 uint32 byteSize = 0; 1303 if (returnType->ByteSize() == NULL) { 1304 if (dynamic_cast<DIEAddressingType*>(returnType) != NULL) 1305 byteSize = fArchitecture->AddressSize(); 1306 } else 1307 byteSize = returnType->ByteSize()->constant; 1308 1309 // if we were unable to determine a size for the type, 1310 // simply default to the architecture's register width. 1311 if (byteSize == 0) 1312 byteSize = fArchitecture->AddressSize(); 1313 1314 ValueLocation* location; 1315 result = fArchitecture->GetReturnAddressLocation(frame, 1316 byteSize, location); 1317 if (result != B_OK) 1318 return result; 1319 1320 BReference<ValueLocation> locationReference(location, true); 1321 Variable* variable = NULL; 1322 BReference<FunctionID> idReference( 1323 targetFunction->GetFunctionID(), true); 1324 result = factory.CreateReturnValue(idReference, returnType, 1325 location, subroutineState, variable); 1326 if (result != B_OK) 1327 return result; 1328 1329 BReference<Variable> variableReference(variable, true); 1330 if (!frame->AddLocalVariable(variable)) 1331 return B_NO_MEMORY; 1332 } 1333 } 1334 } 1335 1336 return B_OK; 1337 } 1338 1339 1340 bool 1341 DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type, 1342 const TypeLookupConstraints& constraints) const 1343 { 1344 if (constraints.HasBaseTypeName()) { 1345 BString baseEntryName; 1346 DIEType* baseTypeOwnerEntry = NULL; 1347 1348 switch (constraints.TypeKind()) { 1349 case TYPE_ADDRESS: 1350 { 1351 DIEAddressingType* addressType = 1352 dynamic_cast<DIEAddressingType*>(type); 1353 if (addressType != NULL) { 1354 baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1355 addressType, HasTypePredicate<DIEAddressingType>()); 1356 } 1357 break; 1358 } 1359 case TYPE_ARRAY: 1360 { 1361 DIEArrayType* arrayType = 1362 dynamic_cast<DIEArrayType*>(type); 1363 if (arrayType != NULL) { 1364 baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1365 arrayType, HasTypePredicate<DIEArrayType>()); 1366 } 1367 break; 1368 } 1369 default: 1370 break; 1371 } 1372 1373 if (baseTypeOwnerEntry != NULL) { 1374 DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry, 1375 baseEntryName); 1376 1377 if (baseEntryName != constraints.BaseTypeName()) 1378 return false; 1379 } 1380 } 1381 1382 return true; 1383 } 1384 1385 1386 status_t 1387 DwarfImageDebugInfo::_BuildTypeNameTable() 1388 { 1389 fTypeNameTable = new(std::nothrow) TypeNameTable; 1390 if (fTypeNameTable == NULL) 1391 return B_NO_MEMORY; 1392 1393 status_t error = fTypeNameTable->Init(); 1394 if (error != B_OK) 1395 return error; 1396 1397 // iterate through all compilation units 1398 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 1399 i++) { 1400 // iterate through all types of the compilation unit 1401 for (DebugInfoEntryList::ConstIterator it 1402 = unit->UnitEntry()->Types().GetIterator(); 1403 DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) { 1404 1405 if (_RecursiveAddTypeNames(typeEntry, unit) != B_OK) 1406 return B_NO_MEMORY; 1407 } 1408 1409 for (DebugInfoEntryList::ConstIterator it 1410 = unit->UnitEntry()->OtherChildren().GetIterator(); 1411 DebugInfoEntry* child = it.Next();) { 1412 if (child->Tag() != DW_TAG_namespace) 1413 continue; 1414 1415 DIENamespace* namespaceEntry = dynamic_cast<DIENamespace*>(child); 1416 if (_RecursiveTraverseNamespaceForTypes(namespaceEntry, unit) 1417 != B_OK) { 1418 return B_NO_MEMORY; 1419 } 1420 } 1421 } 1422 1423 return B_OK; 1424 } 1425 1426 1427 status_t 1428 DwarfImageDebugInfo::_RecursiveAddTypeNames(DIEType* type, CompilationUnit* unit) 1429 { 1430 if (type->IsDeclaration()) 1431 return B_OK; 1432 1433 BString typeEntryName; 1434 DwarfUtils::GetFullyQualifiedDIEName(type, typeEntryName); 1435 1436 status_t error = B_OK; 1437 TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName); 1438 if (entry == NULL) { 1439 entry = new(std::nothrow) TypeNameEntry(typeEntryName); 1440 if (entry == NULL) 1441 return B_NO_MEMORY; 1442 1443 error = fTypeNameTable->Insert(entry); 1444 if (error != B_OK) 1445 return error; 1446 } 1447 1448 TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(type, unit); 1449 if (info == NULL) 1450 return B_NO_MEMORY; 1451 1452 if (!entry->types.AddItem(info)) { 1453 delete info; 1454 return B_NO_MEMORY; 1455 } 1456 1457 DIEClassBaseType* classType = dynamic_cast<DIEClassBaseType*>(type); 1458 if (classType != NULL) { 1459 for (DebugInfoEntryList::ConstIterator it 1460 = classType->InnerTypes().GetIterator(); 1461 DIEType* innerType = dynamic_cast<DIEType*>(it.Next());) { 1462 error = _RecursiveAddTypeNames(innerType, unit); 1463 if (error != B_OK) 1464 return error; 1465 } 1466 } 1467 1468 return B_OK; 1469 } 1470 1471 1472 status_t 1473 DwarfImageDebugInfo::_RecursiveTraverseNamespaceForTypes(DIENamespace* nsEntry, 1474 CompilationUnit* unit) 1475 { 1476 for (DebugInfoEntryList::ConstIterator it 1477 = nsEntry->Children().GetIterator(); 1478 DebugInfoEntry* child = it.Next();) { 1479 if (child->Tag() == DW_TAG_namespace) { 1480 DIENamespace* entry = dynamic_cast<DIENamespace*>(child); 1481 status_t error = _RecursiveTraverseNamespaceForTypes(entry, unit); 1482 if (error != B_OK) 1483 return error; 1484 continue; 1485 } 1486 1487 if (!child->IsType()) 1488 continue; 1489 1490 DIEType* type = dynamic_cast<DIEType*>(child); 1491 if (_RecursiveAddTypeNames(type, unit) != B_OK) 1492 return B_NO_MEMORY; 1493 } 1494 1495 return B_OK; 1496 } 1497