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