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 status_t error = B_OK; 413 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 414 i++) { 415 DIECompileUnitBase* unitEntry = unit->UnitEntry(); 416 // printf(" %s:\n", unitEntry->Name()); 417 // printf(" address ranges:\n"); 418 // TargetAddressRangeList* rangeList = unitEntry->AddressRanges(); 419 // if (rangeList != NULL) { 420 // int32 count = rangeList->CountRanges(); 421 // for (int32 i = 0; i < count; i++) { 422 // TargetAddressRange range = rangeList->RangeAt(i); 423 // printf(" %#llx - %#llx\n", range.Start(), range.End()); 424 // } 425 // } else { 426 // printf(" %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(), 427 // (target_addr_t)unitEntry->HighPC()); 428 // } 429 430 // printf(" functions:\n"); 431 for (DebugInfoEntryList::ConstIterator it 432 = unitEntry->OtherChildren().GetIterator(); 433 DebugInfoEntry* entry = it.Next();) { 434 if (entry->Tag() == DW_TAG_subprogram) { 435 DIESubprogram* subprogramEntry 436 = static_cast<DIESubprogram*>(entry); 437 error = _AddFunction(subprogramEntry, unit, functions); 438 if (error != B_OK) 439 return error; 440 } 441 442 DIENamespace* nsEntry = dynamic_cast<DIENamespace*>(entry); 443 if (nsEntry != NULL) { 444 error = _RecursiveTraverseNamespaceForFunctions(nsEntry, unit, 445 functions); 446 if (error != B_OK) 447 return error; 448 } 449 } 450 } 451 452 if (fFile->CountCompilationUnits() != 0) 453 return B_OK; 454 455 // if we had no compilation units, fall back to providing basic 456 // debug infos with DWARF-supported call frame unwinding, 457 // if available. 458 if (fFile->HasFrameInformation()) { 459 return SpecificImageDebugInfo::GetFunctionsFromSymbols(symbols, 460 functions, fDebuggerInterface, fImageInfo, this); 461 } 462 463 return B_OK; 464 } 465 466 467 status_t 468 DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, 469 const TypeLookupConstraints& constraints, Type*& _type) 470 { 471 TypeNameEntry* entry = fTypeNameTable->Lookup(name); 472 if (entry == NULL) 473 return B_ENTRY_NOT_FOUND; 474 475 for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) { 476 DIEType* typeEntry = info->type; 477 if (constraints.HasTypeKind()) { 478 if (dwarf_tag_to_type_kind(typeEntry->Tag()) 479 != constraints.TypeKind()) { 480 continue; 481 } 482 483 if (!_EvaluateBaseTypeConstraints(typeEntry, constraints)) 484 continue; 485 } 486 487 if (constraints.HasSubtypeKind() 488 && dwarf_tag_to_subtype_kind(typeEntry->Tag()) 489 != constraints.SubtypeKind()) { 490 continue; 491 } 492 493 int32 registerCount = fArchitecture->CountRegisters(); 494 const Register* registers = fArchitecture->Registers(); 495 496 // get the DWARF <-> architecture register maps 497 RegisterMap* toDwarfMap; 498 RegisterMap* fromDwarfMap; 499 status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, 500 &fromDwarfMap); 501 if (error != B_OK) 502 return error; 503 504 BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true); 505 BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); 506 507 // create the target interface 508 BasicTargetInterface* targetInterface 509 = new(std::nothrow) BasicTargetInterface(registers, registerCount, 510 fromDwarfMap, fArchitecture, fDebuggerInterface); 511 if (targetInterface == NULL) 512 return B_NO_MEMORY; 513 514 BReference<BasicTargetInterface> targetInterfaceReference( 515 targetInterface, true); 516 517 DwarfTypeContext* typeContext = new(std::nothrow) 518 DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile, 519 info->unit, NULL, 0, 0, fRelocationDelta, targetInterface, NULL); 520 if (typeContext == NULL) 521 return B_NO_MEMORY; 522 BReference<DwarfTypeContext> typeContextReference(typeContext, true); 523 524 // create the type 525 DwarfType* type; 526 DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache); 527 error = typeFactory.CreateType(typeEntry, type); 528 if (error != B_OK) 529 continue; 530 531 _type = type; 532 return B_OK; 533 } 534 535 return B_ENTRY_NOT_FOUND; 536 } 537 538 539 bool 540 DwarfImageDebugInfo::HasType(const BString& name, 541 const TypeLookupConstraints& constraints) const 542 { 543 TypeNameEntry* entry = fTypeNameTable->Lookup(name); 544 if (entry == NULL) 545 return false; 546 547 for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) { 548 DIEType* typeEntry = info->type; 549 if (constraints.HasTypeKind()) { 550 if (dwarf_tag_to_type_kind(typeEntry->Tag()) 551 != constraints.TypeKind()) { 552 continue; 553 } 554 555 if (!_EvaluateBaseTypeConstraints(typeEntry, constraints)) 556 continue; 557 } 558 559 if (constraints.HasSubtypeKind() 560 && dwarf_tag_to_subtype_kind(typeEntry->Tag()) 561 != constraints.SubtypeKind()) { 562 continue; 563 } 564 565 return true; 566 } 567 568 return false; 569 } 570 571 572 AddressSectionType 573 DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address) 574 { 575 if (address >= fTextSectionStart && address < fTextSectionEnd) 576 return ADDRESS_SECTION_TYPE_FUNCTION; 577 578 if (address >= fPLTSectionStart && address < fPLTSectionEnd) 579 return ADDRESS_SECTION_TYPE_PLT; 580 581 return ADDRESS_SECTION_TYPE_UNKNOWN; 582 } 583 584 585 status_t 586 DwarfImageDebugInfo::CreateFrame(Image* image, 587 FunctionInstance* functionInstance, CpuState* cpuState, 588 bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos, 589 StackFrame*& _frame, CpuState*& _previousCpuState) 590 { 591 DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( 592 functionInstance->GetFunctionDebugInfo()); 593 594 FunctionID* functionID = functionInstance->GetFunctionID(); 595 BReference<FunctionID> functionIDReference; 596 if (functionID != NULL) 597 functionIDReference.SetTo(functionID, true); 598 599 DIESubprogram* entry = function != NULL 600 ? function->SubprogramEntry() : NULL; 601 602 TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, " 603 "function: %s\n", entry, 604 functionID->FunctionName().String()); 605 606 int32 registerCount = fArchitecture->CountRegisters(); 607 const Register* registers = fArchitecture->Registers(); 608 609 // get the DWARF <-> architecture register maps 610 RegisterMap* toDwarfMap; 611 RegisterMap* fromDwarfMap; 612 status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, 613 &fromDwarfMap); 614 if (error != B_OK) 615 return error; 616 BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true); 617 BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); 618 619 // create a clean CPU state for the previous frame 620 CpuState* previousCpuState; 621 error = fArchitecture->CreateCpuState(previousCpuState); 622 if (error != B_OK) 623 return error; 624 BReference<CpuState> previousCpuStateReference(previousCpuState, true); 625 626 // create the target interfaces 627 UnwindTargetInterface* inputInterface 628 = new(std::nothrow) UnwindTargetInterface(registers, registerCount, 629 fromDwarfMap, toDwarfMap, cpuState, fArchitecture, 630 fDebuggerInterface); 631 if (inputInterface == NULL) 632 return B_NO_MEMORY; 633 BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface, 634 true); 635 636 UnwindTargetInterface* outputInterface 637 = new(std::nothrow) UnwindTargetInterface(registers, registerCount, 638 fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, 639 fDebuggerInterface); 640 if (outputInterface == NULL) 641 return B_NO_MEMORY; 642 BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface, 643 true); 644 645 // do the unwinding 646 target_addr_t instructionPointer 647 = cpuState->InstructionPointer() - fRelocationDelta; 648 target_addr_t framePointer; 649 CompilationUnit* unit = function != NULL ? function->GetCompilationUnit() 650 : NULL; 651 error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry, 652 instructionPointer, inputInterface, outputInterface, framePointer); 653 654 if (error != B_OK) { 655 TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); 656 return B_UNSUPPORTED; 657 } 658 659 TRACE_CFI_ONLY( 660 TRACE_CFI("unwound registers:\n"); 661 for (int32 i = 0; i < registerCount; i++) { 662 const Register* reg = registers + i; 663 BVariant value; 664 if (previousCpuState->GetRegisterValue(reg, value)) { 665 TRACE_CFI(" %3s: %#" B_PRIx64 "\n", reg->Name(), 666 value.ToUInt64()); 667 } else 668 TRACE_CFI(" %3s: undefined\n", reg->Name()); 669 } 670 ) 671 672 // create the stack frame debug info 673 DIESubprogram* subprogramEntry = function != NULL ? 674 function->SubprogramEntry() : NULL; 675 DwarfStackFrameDebugInfo* stackFrameDebugInfo 676 = new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, 677 fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup, 678 fTypeCache, instructionPointer, framePointer, fRelocationDelta, 679 inputInterface, fromDwarfMap); 680 if (stackFrameDebugInfo == NULL) 681 return B_NO_MEMORY; 682 BReference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference( 683 stackFrameDebugInfo, true); 684 685 error = stackFrameDebugInfo->Init(); 686 if (error != B_OK) 687 return error; 688 689 // create the stack frame 690 StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD, 691 cpuState, framePointer, cpuState->InstructionPointer(), 692 stackFrameDebugInfo); 693 if (frame == NULL) 694 return B_NO_MEMORY; 695 BReference<StackFrame> frameReference(frame, true); 696 697 error = frame->Init(); 698 if (error != B_OK) 699 return error; 700 701 frame->SetReturnAddress(previousCpuState->InstructionPointer()); 702 // Note, this is correct, since we actually retrieved the return 703 // address. Our caller will fix the IP for us. 704 705 // The subprogram entry may not be available since this may be a case 706 // where .eh_frame was used to unwind the stack without other DWARF 707 // info being available. 708 if (subprogramEntry != NULL && getFullFrameInfo) { 709 // create function parameter objects 710 for (DebugInfoEntryList::ConstIterator it 711 = subprogramEntry->Parameters().GetIterator(); 712 DebugInfoEntry* entry = it.Next();) { 713 if (entry->Tag() != DW_TAG_formal_parameter) 714 continue; 715 716 BString parameterName; 717 DwarfUtils::GetDIEName(entry, parameterName); 718 if (parameterName.Length() == 0) 719 continue; 720 721 DIEFormalParameter* parameterEntry 722 = dynamic_cast<DIEFormalParameter*>(entry); 723 Variable* parameter; 724 if (stackFrameDebugInfo->CreateParameter(functionID, 725 parameterEntry, parameter) != B_OK) { 726 continue; 727 } 728 BReference<Variable> parameterReference(parameter, true); 729 730 if (!frame->AddParameter(parameter)) 731 return B_NO_MEMORY; 732 } 733 734 // create objects for the local variables 735 _CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo, 736 instructionPointer, functionInstance->Address() - fRelocationDelta, 737 subprogramEntry->Variables(), subprogramEntry->Blocks()); 738 739 if (returnValueInfos != NULL && !returnValueInfos->IsEmpty()) { 740 _CreateReturnValues(returnValueInfos, image, frame, 741 *stackFrameDebugInfo); 742 } 743 } 744 745 _frame = frameReference.Detach(); 746 _previousCpuState = previousCpuStateReference.Detach(); 747 748 frame->SetPreviousCpuState(_previousCpuState); 749 750 return B_OK; 751 } 752 753 754 status_t 755 DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function, 756 target_addr_t address, Statement*& _statement) 757 { 758 TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#" 759 B_PRIx64 ")\n", _function, address); 760 761 DwarfFunctionDebugInfo* function 762 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 763 if (function == NULL) { 764 TRACE_LINES(" -> no dwarf function\n"); 765 // fall back to assembly 766 return fArchitecture->GetStatement(function, address, _statement); 767 } 768 769 AutoLocker<BLocker> locker(fLock); 770 771 // check whether we have the source code 772 CompilationUnit* unit = function->GetCompilationUnit(); 773 LocatableFile* file = function->SourceFile(); 774 if (file == NULL) { 775 TRACE_CODE(" -> no source file\n"); 776 777 // no source code -- rather return the assembly statement 778 return fArchitecture->GetStatement(function, address, _statement); 779 } 780 781 SourceCode* sourceCode = NULL; 782 status_t error = fSourceInfo->GetActiveSourceCode(_function, sourceCode); 783 BReference<SourceCode> sourceReference(sourceCode, true); 784 if (error != B_OK || dynamic_cast<DisassembledCode*>(sourceCode) != NULL) { 785 // either no source code or disassembly is currently active (i.e. 786 // due to failing to locate the source file on disk or the user 787 // deliberately switching to disassembly view). 788 // return the assembly statement. 789 return fArchitecture->GetStatement(function, address, _statement); 790 } 791 792 // get the index of the source file in the compilation unit for cheaper 793 // comparison below 794 int32 fileIndex = _GetSourceFileIndex(unit, file); 795 796 // Get the statement by executing the line number program for the 797 // compilation unit. 798 LineNumberProgram& program = unit->GetLineNumberProgram(); 799 if (!program.IsValid()) { 800 TRACE_CODE(" -> no line number program\n"); 801 return B_BAD_DATA; 802 } 803 804 // adjust address 805 address -= fRelocationDelta; 806 807 LineNumberProgram::State state; 808 program.GetInitialState(state); 809 810 target_addr_t statementAddress = 0; 811 int32 statementLine = -1; 812 int32 statementColumn = -1; 813 while (program.GetNextRow(state)) { 814 // skip statements of other files 815 if (state.file != fileIndex) 816 continue; 817 818 if (statementAddress != 0 819 && (state.isStatement || state.isSequenceEnd)) { 820 target_addr_t endAddress = state.address; 821 if (address >= statementAddress && address < endAddress) { 822 ContiguousStatement* statement = new(std::nothrow) 823 ContiguousStatement( 824 SourceLocation(statementLine, statementColumn), 825 TargetAddressRange(fRelocationDelta + statementAddress, 826 endAddress - statementAddress)); 827 if (statement == NULL) 828 return B_NO_MEMORY; 829 830 _statement = statement; 831 return B_OK; 832 } 833 834 statementAddress = 0; 835 } 836 837 if (state.isStatement) { 838 statementAddress = state.address; 839 statementLine = state.line - 1; 840 statementColumn = std::max(state.column - 1, (int32)0); 841 } 842 } 843 844 TRACE_CODE(" -> no line number program match\n"); 845 return B_ENTRY_NOT_FOUND; 846 } 847 848 849 status_t 850 DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function, 851 const SourceLocation& sourceLocation, Statement*& _statement) 852 { 853 DwarfFunctionDebugInfo* function 854 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 855 if (function == NULL) 856 return B_BAD_VALUE; 857 858 target_addr_t functionStartAddress = function->Address() - fRelocationDelta; 859 target_addr_t functionEndAddress = functionStartAddress + function->Size(); 860 861 TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, " 862 "(%" B_PRId32 ", %" B_PRId32 ")): function range: %#" B_PRIx64 " - %#" 863 B_PRIx64 "\n", function, sourceLocation.Line(), sourceLocation.Column(), 864 functionStartAddress, functionEndAddress); 865 866 AutoLocker<BLocker> locker(fLock); 867 868 // get the source file 869 LocatableFile* file = function->SourceFile(); 870 if (file == NULL) 871 return B_ENTRY_NOT_FOUND; 872 873 CompilationUnit* unit = function->GetCompilationUnit(); 874 875 // get the index of the source file in the compilation unit for cheaper 876 // comparison below 877 int32 fileIndex = _GetSourceFileIndex(unit, file); 878 879 // Get the statement by executing the line number program for the 880 // compilation unit. 881 LineNumberProgram& program = unit->GetLineNumberProgram(); 882 if (!program.IsValid()) 883 return B_BAD_DATA; 884 885 LineNumberProgram::State state; 886 program.GetInitialState(state); 887 888 target_addr_t statementAddress = 0; 889 int32 statementLine = -1; 890 int32 statementColumn = -1; 891 while (program.GetNextRow(state)) { 892 bool isOurFile = state.file == fileIndex; 893 894 if (statementAddress != 0 895 && (!isOurFile || state.isStatement || state.isSequenceEnd)) { 896 target_addr_t endAddress = state.address; 897 898 if (statementAddress < endAddress) { 899 TRACE_LINES2(" statement: %#" B_PRIx64 " - %#" B_PRIx64 900 ", location: (%" B_PRId32 ", %" B_PRId32 ")\n", 901 statementAddress, endAddress, statementLine, 902 statementColumn); 903 } 904 905 if (statementAddress < endAddress 906 && statementAddress >= functionStartAddress 907 && statementAddress < functionEndAddress 908 && statementLine == (int32)sourceLocation.Line() 909 && statementColumn == (int32)sourceLocation.Column()) { 910 TRACE_LINES2(" -> found statement!\n"); 911 912 ContiguousStatement* statement = new(std::nothrow) 913 ContiguousStatement( 914 SourceLocation(statementLine, statementColumn), 915 TargetAddressRange(fRelocationDelta + statementAddress, 916 endAddress - statementAddress)); 917 if (statement == NULL) 918 return B_NO_MEMORY; 919 920 _statement = statement; 921 return B_OK; 922 } 923 924 statementAddress = 0; 925 } 926 927 // skip statements of other files 928 if (!isOurFile) 929 continue; 930 931 if (state.isStatement) { 932 statementAddress = state.address; 933 statementLine = state.line - 1; 934 statementColumn = std::max(state.column - 1, (int32)0); 935 } 936 } 937 938 return B_ENTRY_NOT_FOUND; 939 } 940 941 942 status_t 943 DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo* _function, 944 SourceLanguage*& _language) 945 { 946 DwarfFunctionDebugInfo* function 947 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 948 if (function == NULL) 949 return B_BAD_VALUE; 950 951 SourceLanguage* language; 952 CompilationUnit* unit = function->GetCompilationUnit(); 953 switch (unit->UnitEntry()->Language()) { 954 case DW_LANG_C89: 955 case DW_LANG_C: 956 case DW_LANG_C99: 957 language = new(std::nothrow) CLanguage; 958 break; 959 case DW_LANG_C_plus_plus: 960 language = new(std::nothrow) CppLanguage; 961 break; 962 case 0: 963 default: 964 language = new(std::nothrow) UnsupportedLanguage; 965 break; 966 } 967 968 if (language == NULL) 969 return B_NO_MEMORY; 970 971 _language = language; 972 return B_OK; 973 } 974 975 976 ssize_t 977 DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size) 978 { 979 target_addr_t offset = address - fRelocationDelta 980 - fTextSegment->LoadAddress() + fTextSegment->FileOffset(); 981 ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset); 982 return bytesRead >= 0 ? bytesRead : errno; 983 } 984 985 986 status_t 987 DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file, 988 FileSourceCode* sourceCode) 989 { 990 bool addedAny = false; 991 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 992 i++) { 993 int32 fileIndex = _GetSourceFileIndex(unit, file); 994 if (fileIndex < 0) 995 continue; 996 997 status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex); 998 if (error == B_NO_MEMORY) 999 return error; 1000 addedAny |= error == B_OK; 1001 } 1002 1003 return addedAny ? B_OK : B_ENTRY_NOT_FOUND; 1004 } 1005 1006 1007 status_t 1008 DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit, 1009 FileSourceCode* sourceCode, int32 fileIndex) 1010 { 1011 // Get the statements by executing the line number program for the 1012 // compilation unit and filtering the rows for our source file. 1013 LineNumberProgram& program = unit->GetLineNumberProgram(); 1014 if (!program.IsValid()) 1015 return B_BAD_DATA; 1016 1017 LineNumberProgram::State state; 1018 program.GetInitialState(state); 1019 1020 target_addr_t statementAddress = 0; 1021 int32 statementLine = -1; 1022 int32 statementColumn = -1; 1023 while (program.GetNextRow(state)) { 1024 TRACE_LINES2(" %#" B_PRIx64 " (%" B_PRId32 ", %" B_PRId32 ", %" 1025 B_PRId32 ") %d\n", state.address, state.file, state.line, 1026 state.column, state.isStatement); 1027 1028 bool isOurFile = state.file == fileIndex; 1029 1030 if (statementAddress != 0 1031 && (!isOurFile || state.isStatement || state.isSequenceEnd)) { 1032 target_addr_t endAddress = state.address; 1033 if (endAddress > statementAddress) { 1034 // add the statement 1035 status_t error = sourceCode->AddSourceLocation( 1036 SourceLocation(statementLine, statementColumn)); 1037 if (error != B_OK) 1038 return error; 1039 1040 TRACE_LINES2(" -> statement: %#" B_PRIx64 " - %#" B_PRIx64 1041 ", source location: (%" B_PRId32 ", %" B_PRId32 ")\n", 1042 statementAddress, endAddress, statementLine, 1043 statementColumn); 1044 } 1045 1046 statementAddress = 0; 1047 } 1048 1049 // skip statements of other files 1050 if (!isOurFile) 1051 continue; 1052 1053 if (state.isStatement) { 1054 statementAddress = state.address; 1055 statementLine = state.line - 1; 1056 statementColumn = std::max(state.column - 1, (int32)0); 1057 } 1058 } 1059 1060 return B_OK; 1061 } 1062 1063 1064 int32 1065 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit, 1066 LocatableFile* sourceFile) const 1067 { 1068 // get the index of the source file in the compilation unit for cheaper 1069 // comparison below 1070 const char* directory; 1071 for (int32 i = 0; const char* fileName = unit->FileAt(i, &directory); i++) { 1072 LocatableFile* file = fFileManager->GetSourceFile(directory, fileName); 1073 if (file != NULL) { 1074 BReference<LocatableFile> fileReference(file, true); 1075 if (file == sourceFile) { 1076 return i + 1; 1077 // indices are one-based 1078 } 1079 } 1080 } 1081 1082 return -1; 1083 } 1084 1085 1086 status_t 1087 DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit, 1088 StackFrame* frame, FunctionID* functionID, 1089 DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer, 1090 target_addr_t lowPC, const EntryListWrapper& variableEntries, 1091 const EntryListWrapper& blockEntries) 1092 { 1093 TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64 1094 ", low PC: %#" B_PRIx64 "\n", instructionPointer, lowPC); 1095 1096 // iterate through the variables and add the ones in scope 1097 for (DebugInfoEntryList::ConstIterator it 1098 = variableEntries.list.GetIterator(); 1099 DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) { 1100 1101 TRACE_LOCALS(" variableEntry %p, scope start: %" B_PRIu64 "\n", 1102 variableEntry, variableEntry->StartScope()); 1103 1104 // check the variable's scope 1105 if (instructionPointer < lowPC + variableEntry->StartScope()) 1106 continue; 1107 1108 // add the variable 1109 Variable* variable; 1110 if (factory.CreateLocalVariable(functionID, variableEntry, variable) 1111 != B_OK) { 1112 continue; 1113 } 1114 BReference<Variable> variableReference(variable, true); 1115 1116 if (!frame->AddLocalVariable(variable)) 1117 return B_NO_MEMORY; 1118 } 1119 1120 // iterate through the blocks and find the one we're currently in (if any) 1121 for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator(); 1122 DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) { 1123 1124 TRACE_LOCALS(" lexical block: %p\n", block); 1125 1126 // check whether the block has low/high PC attributes 1127 if (block->LowPC() != 0) { 1128 TRACE_LOCALS(" has lowPC\n"); 1129 1130 // yep, compare with the instruction pointer 1131 if (instructionPointer < block->LowPC() 1132 || instructionPointer >= block->HighPC()) { 1133 continue; 1134 } 1135 } else { 1136 TRACE_LOCALS(" no lowPC\n"); 1137 1138 // check the address ranges instead 1139 TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit, 1140 block->AddressRangesOffset()); 1141 if (rangeList == NULL) { 1142 TRACE_LOCALS(" failed to get ranges\n"); 1143 continue; 1144 } 1145 BReference<TargetAddressRangeList> rangeListReference(rangeList, 1146 true); 1147 1148 if (!rangeList->Contains(instructionPointer)) { 1149 TRACE_LOCALS(" ranges don't contain IP\n"); 1150 continue; 1151 } 1152 } 1153 1154 // found a block -- recurse 1155 return _CreateLocalVariables(unit, frame, functionID, factory, 1156 instructionPointer, lowPC, block->Variables(), block->Blocks()); 1157 } 1158 1159 return B_OK; 1160 } 1161 1162 1163 status_t 1164 DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos, 1165 Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory) 1166 { 1167 for (int32 i = 0; i < returnValueInfos->CountItems(); i++) { 1168 Image* targetImage = image; 1169 ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i); 1170 target_addr_t subroutineAddress = valueInfo->SubroutineAddress(); 1171 CpuState* subroutineState = valueInfo->State(); 1172 if (!targetImage->ContainsAddress(subroutineAddress)) { 1173 // our current image doesn't contain the target function, 1174 // locate the one which does. 1175 targetImage = image->GetTeam()->ImageByAddress(subroutineAddress); 1176 if (targetImage == NULL) { 1177 // nothing we can do, try the next entry (if any) 1178 continue; 1179 } 1180 } 1181 1182 status_t result = B_OK; 1183 ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo(); 1184 if (imageInfo == NULL) { 1185 // the subroutine may have resolved to a different image 1186 // that doesn't have debug information available. 1187 continue; 1188 } 1189 1190 FunctionInstance* targetFunction; 1191 if (imageInfo->GetAddressSectionType(subroutineAddress) 1192 == ADDRESS_SECTION_TYPE_PLT) { 1193 result = fArchitecture->ResolvePICFunctionAddress( 1194 subroutineAddress, subroutineState, subroutineAddress); 1195 if (result != B_OK) 1196 continue; 1197 if (!targetImage->ContainsAddress(subroutineAddress)) { 1198 // the PLT entry doesn't necessarily point to a function 1199 // in the same image; as such we may need to try to 1200 // resolve the target address again. 1201 targetImage = image->GetTeam()->ImageByAddress( 1202 subroutineAddress); 1203 if (targetImage == NULL) 1204 continue; 1205 imageInfo = targetImage->GetImageDebugInfo(); 1206 if (imageInfo == NULL) { 1207 // As above, since the indirection here may have 1208 // landed us in an entirely different image, there is 1209 // no guarantee that debug info is available, 1210 // depending on which image it was. 1211 continue; 1212 } 1213 1214 } 1215 } 1216 1217 targetFunction = imageInfo->FunctionAtAddress(subroutineAddress); 1218 if (targetFunction != NULL) { 1219 DwarfFunctionDebugInfo* targetInfo = 1220 dynamic_cast<DwarfFunctionDebugInfo*>( 1221 targetFunction->GetFunctionDebugInfo()); 1222 if (targetInfo != NULL) { 1223 DIESubprogram* subProgram = targetInfo->SubprogramEntry(); 1224 DIEType* returnType = subProgram->ReturnType(); 1225 if (returnType == NULL) { 1226 // check if we have a specification, and if so, if that has 1227 // a return type 1228 subProgram = dynamic_cast<DIESubprogram*>( 1229 subProgram->Specification()); 1230 if (subProgram != NULL) 1231 returnType = subProgram->ReturnType(); 1232 1233 // function doesn't return a value, we're done. 1234 if (returnType == NULL) 1235 return B_OK; 1236 } 1237 1238 uint32 byteSize = 0; 1239 if (returnType->ByteSize() == NULL) { 1240 if (dynamic_cast<DIEAddressingType*>(returnType) != NULL) 1241 byteSize = fArchitecture->AddressSize(); 1242 } else 1243 byteSize = returnType->ByteSize()->constant; 1244 1245 // if we were unable to determine a size for the type, 1246 // simply default to the architecture's register width. 1247 if (byteSize == 0) 1248 byteSize = fArchitecture->AddressSize(); 1249 1250 ValueLocation* location; 1251 result = fArchitecture->GetReturnAddressLocation(frame, 1252 byteSize, location); 1253 if (result != B_OK) 1254 return result; 1255 1256 BReference<ValueLocation> locationReference(location, true); 1257 Variable* variable = NULL; 1258 BReference<FunctionID> idReference( 1259 targetFunction->GetFunctionID(), true); 1260 result = factory.CreateReturnValue(idReference, returnType, 1261 location, subroutineState, variable); 1262 if (result != B_OK) 1263 return result; 1264 1265 BReference<Variable> variableReference(variable, true); 1266 if (!frame->AddLocalVariable(variable)) 1267 return B_NO_MEMORY; 1268 } 1269 } 1270 } 1271 1272 return B_OK; 1273 } 1274 1275 1276 bool 1277 DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type, 1278 const TypeLookupConstraints& constraints) const 1279 { 1280 if (constraints.HasBaseTypeName()) { 1281 BString baseEntryName; 1282 DIEType* baseTypeOwnerEntry = NULL; 1283 1284 switch (constraints.TypeKind()) { 1285 case TYPE_ADDRESS: 1286 { 1287 DIEAddressingType* addressType = 1288 dynamic_cast<DIEAddressingType*>(type); 1289 if (addressType != NULL) { 1290 baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1291 addressType, HasTypePredicate<DIEAddressingType>()); 1292 } 1293 break; 1294 } 1295 case TYPE_ARRAY: 1296 { 1297 DIEArrayType* arrayType = 1298 dynamic_cast<DIEArrayType*>(type); 1299 if (arrayType != NULL) { 1300 baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1301 arrayType, HasTypePredicate<DIEArrayType>()); 1302 } 1303 break; 1304 } 1305 default: 1306 break; 1307 } 1308 1309 if (baseTypeOwnerEntry != NULL) { 1310 DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry, 1311 baseEntryName); 1312 1313 if (baseEntryName != constraints.BaseTypeName()) 1314 return false; 1315 } 1316 } 1317 1318 return true; 1319 } 1320 1321 1322 status_t 1323 DwarfImageDebugInfo::_RecursiveTraverseNamespaceForFunctions( 1324 DIENamespace* nsEntry, CompilationUnit* unit, 1325 BObjectList<FunctionDebugInfo>& functions) 1326 { 1327 status_t error = B_OK; 1328 for (DebugInfoEntryList::ConstIterator it 1329 = nsEntry->Children().GetIterator(); 1330 DebugInfoEntry* entry = it.Next();) { 1331 if (entry->Tag() == DW_TAG_subprogram) { 1332 DIESubprogram* subprogramEntry 1333 = static_cast<DIESubprogram*>(entry); 1334 error = _AddFunction(subprogramEntry, unit, functions); 1335 if (error != B_OK) 1336 return error; 1337 } 1338 1339 DIENamespace* nsEntry = dynamic_cast<DIENamespace*>(entry); 1340 if (nsEntry != NULL) { 1341 error = _RecursiveTraverseNamespaceForFunctions(nsEntry, unit, 1342 functions); 1343 if (error != B_OK) 1344 return error; 1345 continue; 1346 } 1347 1348 DIEClassBaseType* classEntry = dynamic_cast<DIEClassBaseType*>(entry); 1349 if (classEntry != NULL) { 1350 for (DebugInfoEntryList::ConstIterator it 1351 = classEntry->MemberFunctions().GetIterator(); 1352 DebugInfoEntry* memberEntry = it.Next();) { 1353 error = _AddFunction(static_cast<DIESubprogram*>(memberEntry), 1354 unit, functions); 1355 if (error != B_OK) 1356 return error; 1357 } 1358 } 1359 } 1360 1361 return B_OK; 1362 } 1363 1364 1365 status_t 1366 DwarfImageDebugInfo::_AddFunction(DIESubprogram* subprogramEntry, 1367 CompilationUnit* unit, BObjectList<FunctionDebugInfo>& functions) 1368 { 1369 // ignore declarations and inlined functions 1370 if (subprogramEntry->IsDeclaration() 1371 || subprogramEntry->Inline() == DW_INL_inlined 1372 || subprogramEntry->Inline() == DW_INL_declared_inlined) { 1373 return B_OK; 1374 } 1375 1376 // get the name 1377 BString name; 1378 DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name); 1379 if (name.Length() == 0) 1380 return B_OK; 1381 1382 // get the address ranges 1383 TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit, 1384 subprogramEntry->AddressRangesOffset()); 1385 if (rangeList == NULL) { 1386 target_addr_t lowPC = subprogramEntry->LowPC(); 1387 target_addr_t highPC = subprogramEntry->HighPC(); 1388 if (highPC <= lowPC) 1389 return B_OK; 1390 1391 rangeList = new(std::nothrow) TargetAddressRangeList( 1392 TargetAddressRange(lowPC, highPC - lowPC)); 1393 if (rangeList == NULL) 1394 return B_NO_MEMORY; 1395 // TODO: Clean up already added functions! 1396 } 1397 BReference<TargetAddressRangeList> rangeListReference(rangeList, 1398 true); 1399 1400 // get the source location 1401 const char* directoryPath = NULL; 1402 const char* fileName = NULL; 1403 int32 line = -1; 1404 int32 column = -1; 1405 DwarfUtils::GetDeclarationLocation(fFile, subprogramEntry, 1406 directoryPath, fileName, line, column); 1407 1408 LocatableFile* file = NULL; 1409 if (fileName != NULL) { 1410 file = fFileManager->GetSourceFile(directoryPath, 1411 fileName); 1412 } 1413 BReference<LocatableFile> fileReference(file, true); 1414 1415 // create and add the functions 1416 DwarfFunctionDebugInfo* function 1417 = new(std::nothrow) DwarfFunctionDebugInfo(this, unit, 1418 subprogramEntry, rangeList, name, file, 1419 SourceLocation(line, std::max(column, (int32)0))); 1420 if (function == NULL || !functions.AddItem(function)) { 1421 delete function; 1422 return B_NO_MEMORY; 1423 // TODO: Clean up already added functions! 1424 } 1425 1426 return B_OK; 1427 } 1428 1429 1430 status_t 1431 DwarfImageDebugInfo::_BuildTypeNameTable() 1432 { 1433 fTypeNameTable = new(std::nothrow) TypeNameTable; 1434 if (fTypeNameTable == NULL) 1435 return B_NO_MEMORY; 1436 1437 status_t error = fTypeNameTable->Init(); 1438 if (error != B_OK) 1439 return error; 1440 1441 // iterate through all compilation units 1442 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 1443 i++) { 1444 // iterate through all types of the compilation unit 1445 for (DebugInfoEntryList::ConstIterator it 1446 = unit->UnitEntry()->Types().GetIterator(); 1447 DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) { 1448 1449 if (_RecursiveAddTypeNames(typeEntry, unit) != B_OK) 1450 return B_NO_MEMORY; 1451 } 1452 1453 for (DebugInfoEntryList::ConstIterator it 1454 = unit->UnitEntry()->OtherChildren().GetIterator(); 1455 DebugInfoEntry* child = it.Next();) { 1456 DIENamespace* namespaceEntry = dynamic_cast<DIENamespace*>(child); 1457 if (namespaceEntry == NULL) 1458 continue; 1459 1460 if (_RecursiveTraverseNamespaceForTypes(namespaceEntry, unit) 1461 != B_OK) { 1462 return B_NO_MEMORY; 1463 } 1464 } 1465 } 1466 1467 return B_OK; 1468 } 1469 1470 1471 status_t 1472 DwarfImageDebugInfo::_RecursiveAddTypeNames(DIEType* type, CompilationUnit* unit) 1473 { 1474 if (type->IsDeclaration()) 1475 return B_OK; 1476 1477 BString typeEntryName; 1478 DwarfUtils::GetFullyQualifiedDIEName(type, typeEntryName); 1479 1480 status_t error = B_OK; 1481 TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName); 1482 if (entry == NULL) { 1483 entry = new(std::nothrow) TypeNameEntry(typeEntryName); 1484 if (entry == NULL) 1485 return B_NO_MEMORY; 1486 1487 error = fTypeNameTable->Insert(entry); 1488 if (error != B_OK) 1489 return error; 1490 } 1491 1492 TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(type, unit); 1493 if (info == NULL) 1494 return B_NO_MEMORY; 1495 1496 if (!entry->types.AddItem(info)) { 1497 delete info; 1498 return B_NO_MEMORY; 1499 } 1500 1501 DIEClassBaseType* classType = dynamic_cast<DIEClassBaseType*>(type); 1502 if (classType == NULL) 1503 return B_OK; 1504 1505 for (DebugInfoEntryList::ConstIterator it 1506 = classType->InnerTypes().GetIterator(); 1507 DIEType* innerType = dynamic_cast<DIEType*>(it.Next());) { 1508 error = _RecursiveAddTypeNames(innerType, unit); 1509 if (error != B_OK) 1510 return error; 1511 } 1512 1513 return B_OK; 1514 } 1515 1516 1517 status_t 1518 DwarfImageDebugInfo::_RecursiveTraverseNamespaceForTypes(DIENamespace* nsEntry, 1519 CompilationUnit* unit) 1520 { 1521 for (DebugInfoEntryList::ConstIterator it 1522 = nsEntry->Children().GetIterator(); 1523 DebugInfoEntry* child = it.Next();) { 1524 1525 if (child->IsType()) { 1526 DIEType* type = dynamic_cast<DIEType*>(child); 1527 if (_RecursiveAddTypeNames(type, unit) != B_OK) 1528 return B_NO_MEMORY; 1529 } else { 1530 DIENamespace* nameSpace = dynamic_cast<DIENamespace*>(child); 1531 if (nameSpace == NULL) 1532 continue; 1533 1534 status_t error = _RecursiveTraverseNamespaceForTypes(nameSpace, 1535 unit); 1536 if (error != B_OK) 1537 return error; 1538 continue; 1539 } 1540 } 1541 1542 return B_OK; 1543 } 1544