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