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 // discard column info until proper support is implemented 841 // statementColumn = std::max(state.column - 1, (int32)0); 842 statementColumn = 0; 843 } 844 } 845 846 TRACE_CODE(" -> no line number program match\n"); 847 return B_ENTRY_NOT_FOUND; 848 } 849 850 851 status_t 852 DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function, 853 const SourceLocation& sourceLocation, Statement*& _statement) 854 { 855 DwarfFunctionDebugInfo* function 856 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 857 if (function == NULL) 858 return B_BAD_VALUE; 859 860 target_addr_t functionStartAddress = function->Address() - fRelocationDelta; 861 target_addr_t functionEndAddress = functionStartAddress + function->Size(); 862 863 TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, " 864 "(%" B_PRId32 ", %" B_PRId32 ")): function range: %#" B_PRIx64 " - %#" 865 B_PRIx64 "\n", function, sourceLocation.Line(), sourceLocation.Column(), 866 functionStartAddress, functionEndAddress); 867 868 AutoLocker<BLocker> locker(fLock); 869 870 // get the source file 871 LocatableFile* file = function->SourceFile(); 872 if (file == NULL) 873 return B_ENTRY_NOT_FOUND; 874 875 CompilationUnit* unit = function->GetCompilationUnit(); 876 877 // get the index of the source file in the compilation unit for cheaper 878 // comparison below 879 int32 fileIndex = _GetSourceFileIndex(unit, file); 880 881 // Get the statement by executing the line number program for the 882 // compilation unit. 883 LineNumberProgram& program = unit->GetLineNumberProgram(); 884 if (!program.IsValid()) 885 return B_BAD_DATA; 886 887 LineNumberProgram::State state; 888 program.GetInitialState(state); 889 890 target_addr_t statementAddress = 0; 891 int32 statementLine = -1; 892 int32 statementColumn = -1; 893 while (program.GetNextRow(state)) { 894 bool isOurFile = state.file == fileIndex; 895 896 if (statementAddress != 0 897 && (!isOurFile || state.isStatement || state.isSequenceEnd)) { 898 target_addr_t endAddress = state.address; 899 900 if (statementAddress < endAddress) { 901 TRACE_LINES2(" statement: %#" B_PRIx64 " - %#" B_PRIx64 902 ", location: (%" B_PRId32 ", %" B_PRId32 ")\n", 903 statementAddress, endAddress, statementLine, 904 statementColumn); 905 } 906 907 if (statementAddress < endAddress 908 && statementAddress >= functionStartAddress 909 && statementAddress < functionEndAddress 910 && statementLine == (int32)sourceLocation.Line() 911 && statementColumn == (int32)sourceLocation.Column()) { 912 TRACE_LINES2(" -> found statement!\n"); 913 914 ContiguousStatement* statement = new(std::nothrow) 915 ContiguousStatement( 916 SourceLocation(statementLine, statementColumn), 917 TargetAddressRange(fRelocationDelta + statementAddress, 918 endAddress - statementAddress)); 919 if (statement == NULL) 920 return B_NO_MEMORY; 921 922 _statement = statement; 923 return B_OK; 924 } 925 926 statementAddress = 0; 927 } 928 929 // skip statements of other files 930 if (!isOurFile) 931 continue; 932 933 if (state.isStatement) { 934 statementAddress = state.address; 935 statementLine = state.line - 1; 936 // discard column info until proper support is implemented 937 // statementColumn = std::max(state.column - 1, (int32)0); 938 statementColumn = 0; 939 } 940 } 941 942 return B_ENTRY_NOT_FOUND; 943 } 944 945 946 status_t 947 DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo* _function, 948 SourceLanguage*& _language) 949 { 950 DwarfFunctionDebugInfo* function 951 = dynamic_cast<DwarfFunctionDebugInfo*>(_function); 952 if (function == NULL) 953 return B_BAD_VALUE; 954 955 SourceLanguage* language; 956 CompilationUnit* unit = function->GetCompilationUnit(); 957 switch (unit->UnitEntry()->Language()) { 958 case DW_LANG_C89: 959 case DW_LANG_C: 960 case DW_LANG_C99: 961 language = new(std::nothrow) CLanguage; 962 break; 963 case DW_LANG_C_plus_plus: 964 language = new(std::nothrow) CppLanguage; 965 break; 966 case 0: 967 default: 968 language = new(std::nothrow) UnsupportedLanguage; 969 break; 970 } 971 972 if (language == NULL) 973 return B_NO_MEMORY; 974 975 _language = language; 976 return B_OK; 977 } 978 979 980 ssize_t 981 DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size) 982 { 983 target_addr_t offset = address - fRelocationDelta 984 - fTextSegment->LoadAddress() + fTextSegment->FileOffset(); 985 ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset); 986 return bytesRead >= 0 ? bytesRead : errno; 987 } 988 989 990 status_t 991 DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file, 992 FileSourceCode* sourceCode) 993 { 994 bool addedAny = false; 995 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 996 i++) { 997 int32 fileIndex = _GetSourceFileIndex(unit, file); 998 if (fileIndex < 0) 999 continue; 1000 1001 status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex); 1002 if (error == B_NO_MEMORY) 1003 return error; 1004 addedAny |= error == B_OK; 1005 } 1006 1007 return addedAny ? B_OK : B_ENTRY_NOT_FOUND; 1008 } 1009 1010 1011 status_t 1012 DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit, 1013 FileSourceCode* sourceCode, int32 fileIndex) 1014 { 1015 // Get the statements by executing the line number program for the 1016 // compilation unit and filtering the rows for our source file. 1017 LineNumberProgram& program = unit->GetLineNumberProgram(); 1018 if (!program.IsValid()) 1019 return B_BAD_DATA; 1020 1021 LineNumberProgram::State state; 1022 program.GetInitialState(state); 1023 1024 target_addr_t statementAddress = 0; 1025 int32 statementLine = -1; 1026 int32 statementColumn = -1; 1027 while (program.GetNextRow(state)) { 1028 TRACE_LINES2(" %#" B_PRIx64 " (%" B_PRId32 ", %" B_PRId32 ", %" 1029 B_PRId32 ") %d\n", state.address, state.file, state.line, 1030 state.column, state.isStatement); 1031 1032 bool isOurFile = state.file == fileIndex; 1033 1034 if (statementAddress != 0 1035 && (!isOurFile || state.isStatement || state.isSequenceEnd)) { 1036 target_addr_t endAddress = state.address; 1037 if (endAddress > statementAddress) { 1038 // add the statement 1039 status_t error = sourceCode->AddSourceLocation( 1040 SourceLocation(statementLine, statementColumn)); 1041 if (error != B_OK) 1042 return error; 1043 1044 TRACE_LINES2(" -> statement: %#" B_PRIx64 " - %#" B_PRIx64 1045 ", source location: (%" B_PRId32 ", %" B_PRId32 ")\n", 1046 statementAddress, endAddress, statementLine, 1047 statementColumn); 1048 } 1049 1050 statementAddress = 0; 1051 } 1052 1053 // skip statements of other files 1054 if (!isOurFile) 1055 continue; 1056 1057 if (state.isStatement) { 1058 statementAddress = state.address; 1059 statementLine = state.line - 1; 1060 // discard column info until proper support is implemented 1061 // statementColumn = std::max(state.column - 1, (int32)0); 1062 statementColumn = 0; 1063 } 1064 } 1065 1066 return B_OK; 1067 } 1068 1069 1070 int32 1071 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit, 1072 LocatableFile* sourceFile) const 1073 { 1074 // get the index of the source file in the compilation unit for cheaper 1075 // comparison below 1076 const char* directory; 1077 for (int32 i = 0; const char* fileName = unit->FileAt(i, &directory); i++) { 1078 LocatableFile* file = fFileManager->GetSourceFile(directory, fileName); 1079 if (file != NULL) { 1080 BReference<LocatableFile> fileReference(file, true); 1081 if (file == sourceFile) { 1082 return i + 1; 1083 // indices are one-based 1084 } 1085 } 1086 } 1087 1088 return -1; 1089 } 1090 1091 1092 status_t 1093 DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit, 1094 StackFrame* frame, FunctionID* functionID, 1095 DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer, 1096 target_addr_t lowPC, const EntryListWrapper& variableEntries, 1097 const EntryListWrapper& blockEntries) 1098 { 1099 TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64 1100 ", low PC: %#" B_PRIx64 "\n", instructionPointer, lowPC); 1101 1102 // iterate through the variables and add the ones in scope 1103 for (DebugInfoEntryList::ConstIterator it 1104 = variableEntries.list.GetIterator(); 1105 DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) { 1106 1107 TRACE_LOCALS(" variableEntry %p, scope start: %" B_PRIu64 "\n", 1108 variableEntry, variableEntry->StartScope()); 1109 1110 // check the variable's scope 1111 if (instructionPointer < lowPC + variableEntry->StartScope()) 1112 continue; 1113 1114 // add the variable 1115 Variable* variable; 1116 if (factory.CreateLocalVariable(functionID, variableEntry, variable) 1117 != B_OK) { 1118 continue; 1119 } 1120 BReference<Variable> variableReference(variable, true); 1121 1122 if (!frame->AddLocalVariable(variable)) 1123 return B_NO_MEMORY; 1124 } 1125 1126 // iterate through the blocks and find the one we're currently in (if any) 1127 for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator(); 1128 DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) { 1129 1130 TRACE_LOCALS(" lexical block: %p\n", block); 1131 1132 // check whether the block has low/high PC attributes 1133 if (block->LowPC() != 0) { 1134 TRACE_LOCALS(" has lowPC\n"); 1135 1136 // yep, compare with the instruction pointer 1137 if (instructionPointer < block->LowPC() 1138 || instructionPointer >= block->HighPC()) { 1139 continue; 1140 } 1141 } else { 1142 TRACE_LOCALS(" no lowPC\n"); 1143 1144 // check the address ranges instead 1145 TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit, 1146 block->AddressRangesOffset()); 1147 if (rangeList == NULL) { 1148 TRACE_LOCALS(" failed to get ranges\n"); 1149 continue; 1150 } 1151 BReference<TargetAddressRangeList> rangeListReference(rangeList, 1152 true); 1153 1154 if (!rangeList->Contains(instructionPointer)) { 1155 TRACE_LOCALS(" ranges don't contain IP\n"); 1156 continue; 1157 } 1158 } 1159 1160 // found a block -- recurse 1161 return _CreateLocalVariables(unit, frame, functionID, factory, 1162 instructionPointer, lowPC, block->Variables(), block->Blocks()); 1163 } 1164 1165 return B_OK; 1166 } 1167 1168 1169 status_t 1170 DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos, 1171 Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory) 1172 { 1173 for (int32 i = 0; i < returnValueInfos->CountItems(); i++) { 1174 Image* targetImage = image; 1175 ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i); 1176 target_addr_t subroutineAddress = valueInfo->SubroutineAddress(); 1177 CpuState* subroutineState = valueInfo->State(); 1178 if (!targetImage->ContainsAddress(subroutineAddress)) { 1179 // our current image doesn't contain the target function, 1180 // locate the one which does. 1181 targetImage = image->GetTeam()->ImageByAddress(subroutineAddress); 1182 if (targetImage == NULL) { 1183 // nothing we can do, try the next entry (if any) 1184 continue; 1185 } 1186 } 1187 1188 status_t result = B_OK; 1189 ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo(); 1190 if (imageInfo == NULL) { 1191 // the subroutine may have resolved to a different image 1192 // that doesn't have debug information available. 1193 continue; 1194 } 1195 1196 FunctionInstance* targetFunction; 1197 if (imageInfo->GetAddressSectionType(subroutineAddress) 1198 == ADDRESS_SECTION_TYPE_PLT) { 1199 result = fArchitecture->ResolvePICFunctionAddress( 1200 subroutineAddress, subroutineState, subroutineAddress); 1201 if (result != B_OK) 1202 continue; 1203 if (!targetImage->ContainsAddress(subroutineAddress)) { 1204 // the PLT entry doesn't necessarily point to a function 1205 // in the same image; as such we may need to try to 1206 // resolve the target address again. 1207 targetImage = image->GetTeam()->ImageByAddress( 1208 subroutineAddress); 1209 if (targetImage == NULL) 1210 continue; 1211 imageInfo = targetImage->GetImageDebugInfo(); 1212 if (imageInfo == NULL) { 1213 // As above, since the indirection here may have 1214 // landed us in an entirely different image, there is 1215 // no guarantee that debug info is available, 1216 // depending on which image it was. 1217 continue; 1218 } 1219 1220 } 1221 } 1222 1223 targetFunction = imageInfo->FunctionAtAddress(subroutineAddress); 1224 if (targetFunction != NULL) { 1225 DwarfFunctionDebugInfo* targetInfo = 1226 dynamic_cast<DwarfFunctionDebugInfo*>( 1227 targetFunction->GetFunctionDebugInfo()); 1228 if (targetInfo != NULL) { 1229 DIESubprogram* subProgram = targetInfo->SubprogramEntry(); 1230 DIEType* returnType = subProgram->ReturnType(); 1231 if (returnType == NULL) { 1232 // check if we have a specification, and if so, if that has 1233 // a return type 1234 subProgram = dynamic_cast<DIESubprogram*>( 1235 subProgram->Specification()); 1236 if (subProgram != NULL) 1237 returnType = subProgram->ReturnType(); 1238 1239 // function doesn't return a value, we're done. 1240 if (returnType == NULL) 1241 return B_OK; 1242 } 1243 1244 uint32 byteSize = 0; 1245 if (returnType->ByteSize() == NULL) { 1246 if (dynamic_cast<DIEAddressingType*>(returnType) != NULL) 1247 byteSize = fArchitecture->AddressSize(); 1248 } else 1249 byteSize = returnType->ByteSize()->constant; 1250 1251 // if we were unable to determine a size for the type, 1252 // simply default to the architecture's register width. 1253 if (byteSize == 0) 1254 byteSize = fArchitecture->AddressSize(); 1255 1256 ValueLocation* location; 1257 result = fArchitecture->GetReturnAddressLocation(frame, 1258 byteSize, location); 1259 if (result != B_OK) 1260 return result; 1261 1262 BReference<ValueLocation> locationReference(location, true); 1263 Variable* variable = NULL; 1264 BReference<FunctionID> idReference( 1265 targetFunction->GetFunctionID(), true); 1266 result = factory.CreateReturnValue(idReference, returnType, 1267 location, subroutineState, variable); 1268 if (result != B_OK) 1269 return result; 1270 1271 BReference<Variable> variableReference(variable, true); 1272 if (!frame->AddLocalVariable(variable)) 1273 return B_NO_MEMORY; 1274 } 1275 } 1276 } 1277 1278 return B_OK; 1279 } 1280 1281 1282 bool 1283 DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type, 1284 const TypeLookupConstraints& constraints) const 1285 { 1286 if (constraints.HasBaseTypeName()) { 1287 BString baseEntryName; 1288 DIEType* baseTypeOwnerEntry = NULL; 1289 1290 switch (constraints.TypeKind()) { 1291 case TYPE_ADDRESS: 1292 { 1293 DIEAddressingType* addressType = 1294 dynamic_cast<DIEAddressingType*>(type); 1295 if (addressType != NULL) { 1296 baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1297 addressType, HasTypePredicate<DIEAddressingType>()); 1298 } 1299 break; 1300 } 1301 case TYPE_ARRAY: 1302 { 1303 DIEArrayType* arrayType = 1304 dynamic_cast<DIEArrayType*>(type); 1305 if (arrayType != NULL) { 1306 baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( 1307 arrayType, HasTypePredicate<DIEArrayType>()); 1308 } 1309 break; 1310 } 1311 default: 1312 break; 1313 } 1314 1315 if (baseTypeOwnerEntry != NULL) { 1316 DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry, 1317 baseEntryName); 1318 1319 if (baseEntryName != constraints.BaseTypeName()) 1320 return false; 1321 } 1322 } 1323 1324 return true; 1325 } 1326 1327 1328 status_t 1329 DwarfImageDebugInfo::_RecursiveTraverseNamespaceForFunctions( 1330 DIENamespace* nsEntry, CompilationUnit* unit, 1331 BObjectList<FunctionDebugInfo>& functions) 1332 { 1333 status_t error = B_OK; 1334 for (DebugInfoEntryList::ConstIterator it 1335 = nsEntry->Children().GetIterator(); 1336 DebugInfoEntry* entry = it.Next();) { 1337 if (entry->Tag() == DW_TAG_subprogram) { 1338 DIESubprogram* subprogramEntry 1339 = static_cast<DIESubprogram*>(entry); 1340 error = _AddFunction(subprogramEntry, unit, functions); 1341 if (error != B_OK) 1342 return error; 1343 } 1344 1345 DIENamespace* nsEntry = dynamic_cast<DIENamespace*>(entry); 1346 if (nsEntry != NULL) { 1347 error = _RecursiveTraverseNamespaceForFunctions(nsEntry, unit, 1348 functions); 1349 if (error != B_OK) 1350 return error; 1351 continue; 1352 } 1353 1354 DIEClassBaseType* classEntry = dynamic_cast<DIEClassBaseType*>(entry); 1355 if (classEntry != NULL) { 1356 for (DebugInfoEntryList::ConstIterator it 1357 = classEntry->MemberFunctions().GetIterator(); 1358 DebugInfoEntry* memberEntry = it.Next();) { 1359 error = _AddFunction(static_cast<DIESubprogram*>(memberEntry), 1360 unit, functions); 1361 if (error != B_OK) 1362 return error; 1363 } 1364 } 1365 } 1366 1367 return B_OK; 1368 } 1369 1370 1371 status_t 1372 DwarfImageDebugInfo::_AddFunction(DIESubprogram* subprogramEntry, 1373 CompilationUnit* unit, BObjectList<FunctionDebugInfo>& functions) 1374 { 1375 // ignore declarations and inlined functions 1376 if (subprogramEntry->IsDeclaration() 1377 || subprogramEntry->Inline() == DW_INL_inlined 1378 || subprogramEntry->Inline() == DW_INL_declared_inlined) { 1379 return B_OK; 1380 } 1381 1382 // get the name 1383 BString name; 1384 DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name); 1385 if (name.Length() == 0) 1386 return B_OK; 1387 1388 // get the address ranges 1389 TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit, 1390 subprogramEntry->AddressRangesOffset()); 1391 if (rangeList == NULL) { 1392 target_addr_t lowPC = subprogramEntry->LowPC(); 1393 target_addr_t highPC = subprogramEntry->HighPC(); 1394 if (highPC <= lowPC) 1395 return B_OK; 1396 1397 rangeList = new(std::nothrow) TargetAddressRangeList( 1398 TargetAddressRange(lowPC, highPC - lowPC)); 1399 if (rangeList == NULL) 1400 return B_NO_MEMORY; 1401 // TODO: Clean up already added functions! 1402 } 1403 BReference<TargetAddressRangeList> rangeListReference(rangeList, 1404 true); 1405 1406 // get the source location 1407 const char* directoryPath = NULL; 1408 const char* fileName = NULL; 1409 int32 line = -1; 1410 int32 column = -1; 1411 DwarfUtils::GetDeclarationLocation(fFile, subprogramEntry, 1412 directoryPath, fileName, line, column); 1413 1414 LocatableFile* file = NULL; 1415 if (fileName != NULL) { 1416 file = fFileManager->GetSourceFile(directoryPath, 1417 fileName); 1418 } 1419 BReference<LocatableFile> fileReference(file, true); 1420 1421 // create and add the functions 1422 DwarfFunctionDebugInfo* function 1423 = new(std::nothrow) DwarfFunctionDebugInfo(this, unit, 1424 subprogramEntry, rangeList, name, file, 1425 SourceLocation(line, std::max(column, (int32)0))); 1426 if (function == NULL || !functions.AddItem(function)) { 1427 delete function; 1428 return B_NO_MEMORY; 1429 // TODO: Clean up already added functions! 1430 } 1431 1432 return B_OK; 1433 } 1434 1435 1436 status_t 1437 DwarfImageDebugInfo::_BuildTypeNameTable() 1438 { 1439 fTypeNameTable = new(std::nothrow) TypeNameTable; 1440 if (fTypeNameTable == NULL) 1441 return B_NO_MEMORY; 1442 1443 status_t error = fTypeNameTable->Init(); 1444 if (error != B_OK) 1445 return error; 1446 1447 // iterate through all compilation units 1448 for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); 1449 i++) { 1450 // iterate through all types of the compilation unit 1451 for (DebugInfoEntryList::ConstIterator it 1452 = unit->UnitEntry()->Types().GetIterator(); 1453 DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) { 1454 1455 if (_RecursiveAddTypeNames(typeEntry, unit) != B_OK) 1456 return B_NO_MEMORY; 1457 } 1458 1459 for (DebugInfoEntryList::ConstIterator it 1460 = unit->UnitEntry()->OtherChildren().GetIterator(); 1461 DebugInfoEntry* child = it.Next();) { 1462 DIENamespace* namespaceEntry = dynamic_cast<DIENamespace*>(child); 1463 if (namespaceEntry == NULL) 1464 continue; 1465 1466 if (_RecursiveTraverseNamespaceForTypes(namespaceEntry, unit) 1467 != B_OK) { 1468 return B_NO_MEMORY; 1469 } 1470 } 1471 } 1472 1473 return B_OK; 1474 } 1475 1476 1477 status_t 1478 DwarfImageDebugInfo::_RecursiveAddTypeNames(DIEType* type, CompilationUnit* unit) 1479 { 1480 if (type->IsDeclaration()) 1481 return B_OK; 1482 1483 BString typeEntryName; 1484 DwarfUtils::GetFullyQualifiedDIEName(type, typeEntryName); 1485 1486 status_t error = B_OK; 1487 TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName); 1488 if (entry == NULL) { 1489 entry = new(std::nothrow) TypeNameEntry(typeEntryName); 1490 if (entry == NULL) 1491 return B_NO_MEMORY; 1492 1493 error = fTypeNameTable->Insert(entry); 1494 if (error != B_OK) 1495 return error; 1496 } 1497 1498 TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(type, unit); 1499 if (info == NULL) 1500 return B_NO_MEMORY; 1501 1502 if (!entry->types.AddItem(info)) { 1503 delete info; 1504 return B_NO_MEMORY; 1505 } 1506 1507 DIEClassBaseType* classType = dynamic_cast<DIEClassBaseType*>(type); 1508 if (classType == NULL) 1509 return B_OK; 1510 1511 for (DebugInfoEntryList::ConstIterator it 1512 = classType->InnerTypes().GetIterator(); 1513 DIEType* innerType = dynamic_cast<DIEType*>(it.Next());) { 1514 error = _RecursiveAddTypeNames(innerType, unit); 1515 if (error != B_OK) 1516 return error; 1517 } 1518 1519 return B_OK; 1520 } 1521 1522 1523 status_t 1524 DwarfImageDebugInfo::_RecursiveTraverseNamespaceForTypes(DIENamespace* nsEntry, 1525 CompilationUnit* unit) 1526 { 1527 for (DebugInfoEntryList::ConstIterator it 1528 = nsEntry->Children().GetIterator(); 1529 DebugInfoEntry* child = it.Next();) { 1530 1531 if (child->IsType()) { 1532 DIEType* type = dynamic_cast<DIEType*>(child); 1533 if (_RecursiveAddTypeNames(type, unit) != B_OK) 1534 return B_NO_MEMORY; 1535 } else { 1536 DIENamespace* nameSpace = dynamic_cast<DIENamespace*>(child); 1537 if (nameSpace == NULL) 1538 continue; 1539 1540 status_t error = _RecursiveTraverseNamespaceForTypes(nameSpace, 1541 unit); 1542 if (error != B_OK) 1543 return error; 1544 continue; 1545 } 1546 } 1547 1548 return B_OK; 1549 } 1550