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