1063 lines · cpp
1//===-- LVDWARFReader.cpp -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This implements the LVDWARFReader class.10// It supports ELF, Mach-O and Wasm binary formats.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h"15#include "llvm/DebugInfo/DIContext.h"16#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"17#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"18#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"19#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"20#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"21#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"22#include "llvm/DebugInfo/LogicalView/Core/LVType.h"23#include "llvm/Object/MachO.h"24#include "llvm/Support/FormatVariadic.h"25 26using namespace llvm;27using namespace llvm::object;28using namespace llvm::logicalview;29 30#define DEBUG_TYPE "DWARFReader"31 32void LVDWARFReader::processOneAttribute(const DWARFDie &Die,33 LVOffset *OffsetPtr,34 const AttributeSpec &AttrSpec) {35 uint64_t OffsetOnEntry = *OffsetPtr;36 DWARFUnit *U = Die.getDwarfUnit();37 const DWARFFormValue &FormValue =38 DWARFFormValue::createFromUnit(AttrSpec.Form, U, OffsetPtr);39 40 // We are processing .debug_info section, implicit_const attribute41 // values are not really stored here, but in .debug_abbrev section.42 auto GetAsUnsignedConstant = [&]() -> int64_t {43 if (AttrSpec.isImplicitConst())44 return AttrSpec.getImplicitConstValue();45 if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())46 return *Val;47 return 0;48 };49 50 auto GetFlag = [](const DWARFFormValue &FormValue) -> bool {51 return FormValue.isFormClass(DWARFFormValue::FC_Flag);52 };53 54 auto GetBoundValue = [&AttrSpec](const DWARFFormValue &FormValue) -> int64_t {55 switch (FormValue.getForm()) {56 case dwarf::DW_FORM_ref_addr:57 case dwarf::DW_FORM_ref1:58 case dwarf::DW_FORM_ref2:59 case dwarf::DW_FORM_ref4:60 case dwarf::DW_FORM_ref8:61 case dwarf::DW_FORM_ref_udata:62 case dwarf::DW_FORM_ref_sig8:63 return *FormValue.getAsReferenceUVal();64 case dwarf::DW_FORM_data1:65 case dwarf::DW_FORM_flag:66 case dwarf::DW_FORM_data2:67 case dwarf::DW_FORM_data4:68 case dwarf::DW_FORM_data8:69 case dwarf::DW_FORM_udata:70 case dwarf::DW_FORM_ref_sup4:71 case dwarf::DW_FORM_ref_sup8:72 return *FormValue.getAsUnsignedConstant();73 case dwarf::DW_FORM_sdata:74 return *FormValue.getAsSignedConstant();75 case dwarf::DW_FORM_implicit_const:76 return AttrSpec.getImplicitConstValue();77 default:78 return 0;79 }80 };81 82 LLVM_DEBUG({83 dbgs() << " " << hexValue(OffsetOnEntry)84 << formatv(" {0}", AttrSpec.Attr) << "\n";85 });86 87 switch (AttrSpec.Attr) {88 case dwarf::DW_AT_accessibility:89 CurrentElement->setAccessibilityCode(GetAsUnsignedConstant());90 break;91 case dwarf::DW_AT_artificial:92 CurrentElement->setIsArtificial();93 break;94 case dwarf::DW_AT_bit_size:95 CurrentElement->setBitSize(GetAsUnsignedConstant());96 break;97 case dwarf::DW_AT_byte_size:98 CurrentElement->setBitSize(GetAsUnsignedConstant() * DWARF_CHAR_BIT);99 break;100 case dwarf::DW_AT_call_file:101 CurrentElement->setCallFilenameIndex(IncrementFileIndex102 ? GetAsUnsignedConstant() + 1103 : GetAsUnsignedConstant());104 break;105 case dwarf::DW_AT_call_line:106 CurrentElement->setCallLineNumber(GetAsUnsignedConstant());107 break;108 case dwarf::DW_AT_comp_dir:109 CompileUnit->setCompilationDirectory(dwarf::toStringRef(FormValue));110 break;111 case dwarf::DW_AT_const_value:112 if (FormValue.isFormClass(DWARFFormValue::FC_Block)) {113 ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();114 // Store the expression as a hexadecimal string.115 CurrentElement->setValue(116 llvm::toHex(llvm::toStringRef(Expr), /*LowerCase=*/true));117 } else if (FormValue.isFormClass(DWARFFormValue::FC_Constant)) {118 // In the case of negative values, generate the string representation119 // for a positive value prefixed with the negative sign.120 if (FormValue.getForm() == dwarf::DW_FORM_sdata) {121 std::stringstream Stream;122 int64_t Value = *FormValue.getAsSignedConstant();123 if (Value < 0) {124 Stream << "-";125 Value = std::abs(Value);126 }127 Stream << hexString(Value, 2);128 CurrentElement->setValue(Stream.str());129 } else130 CurrentElement->setValue(hexString(GetAsUnsignedConstant(), 2));131 } else132 CurrentElement->setValue(dwarf::toStringRef(FormValue));133 break;134 case dwarf::DW_AT_count:135 CurrentElement->setCount(GetAsUnsignedConstant());136 break;137 case dwarf::DW_AT_decl_line:138 CurrentElement->setLineNumber(GetAsUnsignedConstant());139 break;140 case dwarf::DW_AT_decl_file:141 CurrentElement->setFilenameIndex(IncrementFileIndex142 ? GetAsUnsignedConstant() + 1143 : GetAsUnsignedConstant());144 break;145 case dwarf::DW_AT_enum_class:146 if (GetFlag(FormValue))147 CurrentElement->setIsEnumClass();148 break;149 case dwarf::DW_AT_external:150 if (GetFlag(FormValue))151 CurrentElement->setIsExternal();152 break;153 case dwarf::DW_AT_GNU_discriminator:154 CurrentElement->setDiscriminator(GetAsUnsignedConstant());155 break;156 case dwarf::DW_AT_inline:157 CurrentElement->setInlineCode(GetAsUnsignedConstant());158 break;159 case dwarf::DW_AT_lower_bound:160 CurrentElement->setLowerBound(GetBoundValue(FormValue));161 break;162 case dwarf::DW_AT_name:163 CurrentElement->setName(dwarf::toStringRef(FormValue));164 break;165 case dwarf::DW_AT_GNU_template_name:166 CurrentElement->setValue(dwarf::toStringRef(FormValue));167 break;168 case dwarf::DW_AT_linkage_name:169 case dwarf::DW_AT_MIPS_linkage_name:170 CurrentElement->setLinkageName(dwarf::toStringRef(FormValue));171 break;172 case dwarf::DW_AT_producer:173 if (options().getAttributeProducer())174 CurrentElement->setProducer(dwarf::toStringRef(FormValue));175 break;176 case dwarf::DW_AT_language:177 if (options().getAttributeLanguage())178 CurrentElement->setSourceLanguage(LVSourceLanguage{179 static_cast<llvm::dwarf::SourceLanguage>(GetAsUnsignedConstant())});180 break;181 case dwarf::DW_AT_upper_bound:182 CurrentElement->setUpperBound(GetBoundValue(FormValue));183 break;184 case dwarf::DW_AT_virtuality:185 CurrentElement->setVirtualityCode(GetAsUnsignedConstant());186 break;187 188 case dwarf::DW_AT_abstract_origin:189 case dwarf::DW_AT_call_origin:190 case dwarf::DW_AT_extension:191 case dwarf::DW_AT_import:192 case dwarf::DW_AT_specification:193 case dwarf::DW_AT_type:194 updateReference(AttrSpec.Attr, FormValue);195 break;196 197 case dwarf::DW_AT_low_pc:198 if (options().getGeneralCollectRanges()) {199 FoundLowPC = true;200 // For toolchains that support the removal of unused code, the linker201 // marks functions that have been removed, by setting the value for the202 // low_pc to the max address.203 if (std::optional<uint64_t> Value = FormValue.getAsAddress()) {204 CurrentLowPC = *Value;205 } else {206 uint64_t UValue = FormValue.getRawUValue();207 if (U->getAddrOffsetSectionItem(UValue)) {208 CurrentLowPC = *FormValue.getAsAddress();209 } else {210 FoundLowPC = false;211 // We are dealing with an index into the .debug_addr section.212 LLVM_DEBUG({213 dbgs() << format("indexed (%8.8x) address = ", (uint32_t)UValue);214 });215 }216 }217 if (FoundLowPC) {218 if (CurrentLowPC == getTombstoneAddress())219 CurrentElement->setIsDiscarded();220 else221 // Consider the case of WebAssembly.222 CurrentLowPC += WasmCodeSectionOffset;223 if (CurrentElement->isCompileUnit())224 setCUBaseAddress(CurrentLowPC);225 }226 }227 break;228 229 case dwarf::DW_AT_high_pc:230 if (options().getGeneralCollectRanges()) {231 FoundHighPC = true;232 if (std::optional<uint64_t> Address = FormValue.getAsAddress())233 // High PC is an address.234 CurrentHighPC = *Address;235 if (std::optional<uint64_t> Offset = FormValue.getAsUnsignedConstant())236 // High PC is an offset from LowPC.237 // Don't add the WebAssembly offset if we have seen a DW_AT_low_pc, as238 // the CurrentLowPC has already that offset added. Basically, use the239 // original DW_AT_loc_pc value.240 CurrentHighPC =241 (FoundLowPC ? CurrentLowPC - WasmCodeSectionOffset : CurrentLowPC) +242 *Offset;243 // Store the real upper limit for the address range.244 if (UpdateHighAddress && CurrentHighPC > 0)245 --CurrentHighPC;246 // Consider the case of WebAssembly.247 CurrentHighPC += WasmCodeSectionOffset;248 if (CurrentElement->isCompileUnit())249 setCUHighAddress(CurrentHighPC);250 }251 break;252 253 case dwarf::DW_AT_ranges:254 if (RangesDataAvailable && options().getGeneralCollectRanges()) {255 auto GetRanges = [](const DWARFFormValue &FormValue,256 DWARFUnit *U) -> Expected<DWARFAddressRangesVector> {257 if (FormValue.getForm() == dwarf::DW_FORM_rnglistx)258 return U->findRnglistFromIndex(*FormValue.getAsSectionOffset());259 return U->findRnglistFromOffset(*FormValue.getAsSectionOffset());260 };261 Expected<DWARFAddressRangesVector> RangesOrError =262 GetRanges(FormValue, U);263 if (!RangesOrError) {264 LLVM_DEBUG({265 std::string TheError(toString(RangesOrError.takeError()));266 dbgs() << format("error decoding address ranges = ",267 TheError.c_str());268 });269 consumeError(RangesOrError.takeError());270 break;271 }272 // The address ranges are absolute. There is no need to add any addend.273 DWARFAddressRangesVector Ranges = RangesOrError.get();274 for (DWARFAddressRange &Range : Ranges) {275 // This seems to be a tombstone for empty ranges.276 if ((Range.LowPC == Range.HighPC) ||277 (Range.LowPC == getTombstoneAddress()))278 continue;279 // Store the real upper limit for the address range.280 if (UpdateHighAddress && Range.HighPC > 0)281 --Range.HighPC;282 // Consider the case of WebAssembly.283 Range.LowPC += WasmCodeSectionOffset;284 Range.HighPC += WasmCodeSectionOffset;285 // Add the pair of addresses.286 CurrentScope->addObject(Range.LowPC, Range.HighPC);287 // If the scope is the CU, do not update the ranges set.288 if (!CurrentElement->isCompileUnit())289 CurrentRanges.emplace_back(Range.LowPC, Range.HighPC);290 }291 }292 break;293 294 // Get the location list for the symbol.295 case dwarf::DW_AT_data_member_location:296 if (options().getAttributeAnyLocation())297 processLocationMember(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);298 break;299 300 // Get the location list for the symbol.301 case dwarf::DW_AT_location:302 case dwarf::DW_AT_string_length:303 case dwarf::DW_AT_use_location:304 if (options().getAttributeAnyLocation() && CurrentSymbol)305 processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);306 break;307 308 case dwarf::DW_AT_call_data_value:309 case dwarf::DW_AT_call_value:310 case dwarf::DW_AT_GNU_call_site_data_value:311 case dwarf::DW_AT_GNU_call_site_value:312 if (options().getAttributeAnyLocation() && CurrentSymbol)313 processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry,314 /*CallSiteLocation=*/true);315 break;316 317 default:318 break;319 }320}321 322LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent,323 DWARFDie &SkeletonDie) {324 // If the input DIE corresponds to the compile unit, it can be:325 // a) Simple DWARF: a standard DIE. Ignore the skeleton DIE (is empty).326 // b) Split DWARF: the DIE for the split DWARF. The skeleton is the DIE327 // for the skeleton DWARF. Process both DIEs.328 const DWARFDie &DIE = SkeletonDie.isValid() ? SkeletonDie : InputDIE;329 DWARFDataExtractor DebugInfoData =330 DIE.getDwarfUnit()->getDebugInfoExtractor();331 LVOffset Offset = DIE.getOffset();332 333 // Reset values for the current DIE.334 CurrentLowPC = 0;335 CurrentHighPC = 0;336 CurrentOffset = Offset;337 CurrentEndOffset = 0;338 FoundLowPC = false;339 FoundHighPC = false;340 341 // Process supported attributes.342 if (DebugInfoData.isValidOffset(Offset)) {343 344 LLVM_DEBUG({345 dbgs() << "DIE: " << hexValue(Offset) << formatv(" {0}", DIE.getTag())346 << "\n";347 });348 349 // Create the logical view element for the current DIE.350 dwarf::Tag Tag = DIE.getTag();351 CurrentElement = createElement(Tag);352 if (!CurrentElement)353 return CurrentScope;354 355 CurrentElement->setTag(Tag);356 CurrentElement->setOffset(Offset);357 358 if (options().getAttributeAnySource() && CurrentElement->isCompileUnit())359 addCompileUnitOffset(Offset,360 static_cast<LVScopeCompileUnit *>(CurrentElement));361 362 // Insert the newly created element into the element symbol table. If the363 // element is in the list, it means there are previously created elements364 // referencing this element.365 auto [It, Inserted] = ElementTable.try_emplace(Offset, CurrentElement);366 if (!Inserted) {367 // There are previous references to this element. We need to update the368 // element and all the references pointing to this element.369 LVElementEntry &Reference = ElementTable[Offset];370 Reference.Element = CurrentElement;371 // Traverse the element set and update the elements (backtracking).372 for (LVElement *Target : Reference.References)373 Target->setReference(CurrentElement);374 for (LVElement *Target : Reference.Types)375 Target->setType(CurrentElement);376 // Clear the pending elements.377 Reference.References.clear();378 Reference.Types.clear();379 }380 381 // Add the current element to its parent as there are attributes382 // (locations) that require the scope level.383 if (CurrentScope)384 Parent->addElement(CurrentScope);385 else if (CurrentSymbol)386 Parent->addElement(CurrentSymbol);387 else if (CurrentType)388 Parent->addElement(CurrentType);389 390 // Process the attributes for the given DIE.391 auto ProcessAttributes = [&](const DWARFDie &TheDIE,392 DWARFDataExtractor &DebugData) {393 CurrentEndOffset = Offset;394 uint32_t abbrCode = DebugData.getULEB128(&CurrentEndOffset);395 if (abbrCode) {396 if (const DWARFAbbreviationDeclaration *AbbrevDecl =397 TheDIE.getAbbreviationDeclarationPtr())398 if (AbbrevDecl)399 for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :400 AbbrevDecl->attributes())401 processOneAttribute(TheDIE, &CurrentEndOffset, AttrSpec);402 }403 };404 405 ProcessAttributes(DIE, DebugInfoData);406 407 // If the input DIE is for a compile unit, process its attributes in408 // the case of split DWARF, to override any common attribute values.409 if (SkeletonDie.isValid()) {410 DWARFDataExtractor DebugInfoData =411 InputDIE.getDwarfUnit()->getDebugInfoExtractor();412 LVOffset Offset = InputDIE.getOffset();413 if (DebugInfoData.isValidOffset(Offset))414 ProcessAttributes(InputDIE, DebugInfoData);415 }416 }417 418 if (CurrentScope) {419 if (CurrentScope->getCanHaveRanges()) {420 // If the scope has ranges, they are already added to the scope.421 // Add any collected LowPC/HighPC values.422 bool IsCompileUnit = CurrentScope->getIsCompileUnit();423 if (FoundLowPC && FoundHighPC) {424 CurrentScope->addObject(CurrentLowPC, CurrentHighPC);425 if (!IsCompileUnit) {426 // If the scope is a function, add it to the public names.427 if ((options().getAttributePublics() ||428 options().getPrintAnyLine()) &&429 CurrentScope->getIsFunction() &&430 !CurrentScope->getIsInlinedFunction())431 CompileUnit->addPublicName(CurrentScope, CurrentLowPC,432 CurrentHighPC);433 }434 }435 436 // Look for scopes with ranges and no linkage name information that437 // are referencing another scopes via DW_AT_specification. They are438 // possible candidates for a comdat scope.439 if (CurrentScope->getHasRanges() &&440 !CurrentScope->getLinkageNameIndex() &&441 CurrentScope->getHasReferenceSpecification()) {442 // Get the linkage name in order to search for a possible comdat.443 std::optional<DWARFFormValue> LinkageDIE =444 DIE.findRecursively(dwarf::DW_AT_linkage_name);445 if (LinkageDIE.has_value()) {446 StringRef Name(dwarf::toStringRef(LinkageDIE));447 if (!Name.empty())448 CurrentScope->setLinkageName(Name);449 }450 }451 452 // If the current scope is in the 'LinkageNames' table, update its453 // logical scope. For other scopes, always we will assume the default454 // ".text" section index.455 LVSectionIndex SectionIndex = updateSymbolTable(CurrentScope);456 if (CurrentScope->getIsComdat())457 CompileUnit->setHasComdatScopes();458 459 // Update section index contained ranges.460 if (SectionIndex) {461 if (!CurrentRanges.empty()) {462 for (LVAddressRange &Range : CurrentRanges)463 addSectionRange(SectionIndex, CurrentScope, Range.first,464 Range.second > Range.first465 ? Range.second - 1 // Make hi-pc exclusive466 : Range.second);467 CurrentRanges.clear();468 }469 // If the scope is the CU, do not update the ranges set.470 if (FoundLowPC && FoundHighPC && !IsCompileUnit) {471 addSectionRange(SectionIndex, CurrentScope, CurrentLowPC,472 CurrentHighPC > CurrentLowPC473 ? CurrentHighPC - 1 // Make hi-pc exclusive474 : CurrentHighPC);475 }476 }477 }478 // Mark member functions.479 if (Parent->getIsAggregate())480 CurrentScope->setIsMember();481 }482 483 // Keep track of symbols with locations.484 if (options().getAttributeAnyLocation() && CurrentSymbol &&485 CurrentSymbol->getHasLocation())486 SymbolsWithLocations.push_back(CurrentSymbol);487 488 // If we have template parameters, mark the parent as template.489 if (CurrentType && CurrentType->getIsTemplateParam())490 Parent->setIsTemplate();491 492 return CurrentScope;493}494 495void LVDWARFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent,496 DWARFDie &SkeletonDie) {497 // Process the current DIE.498 LVScope *Scope = processOneDie(DIE, Parent, SkeletonDie);499 if (Scope) {500 LVOffset Lower = DIE.getOffset();501 LVOffset Upper = CurrentEndOffset;502 DWARFDie DummyDie;503 // Traverse the children chain.504 DWARFDie Child = DIE.getFirstChild();505 while (Child) {506 traverseDieAndChildren(Child, Scope, DummyDie);507 Upper = Child.getOffset();508 Child = Child.getSibling();509 }510 // Calculate contributions to the debug info section.511 if (options().getPrintSizes() && Upper)512 CompileUnit->addSize(Scope, Lower, Upper);513 }514}515 516void LVDWARFReader::processLocationGaps() {517 if (options().getAttributeAnyLocation())518 for (LVSymbol *Symbol : SymbolsWithLocations)519 Symbol->fillLocationGaps();520}521 522void LVDWARFReader::createLineAndFileRecords(523 const DWARFDebugLine::LineTable *Lines) {524 if (!Lines)525 return;526 527 // Get the source filenames.528 if (!Lines->Prologue.FileNames.empty())529 for (const DWARFDebugLine::FileNameEntry &Entry :530 Lines->Prologue.FileNames) {531 std::string Directory;532 if (Lines->getDirectoryForEntry(Entry, Directory))533 Directory = transformPath(Directory);534 if (Directory.empty())535 Directory = std::string(CompileUnit->getCompilationDirectory());536 std::string File = transformPath(dwarf::toStringRef(Entry.Name));537 std::string String;538 raw_string_ostream(String) << Directory << "/" << File;539 CompileUnit->addFilename(String);540 }541 542 // In DWARF5 the file indexes start at 0;543 bool IncrementIndex = Lines->Prologue.getVersion() >= 5;544 545 // Get the source lines if requested by command line option.546 if (options().getPrintLines() && Lines->Rows.size())547 for (const DWARFDebugLine::Row &Row : Lines->Rows) {548 // Here we collect logical debug lines in CULines. Later on,549 // the 'processLines()' function will move each created logical line550 // to its enclosing logical scope, using the debug ranges information551 // and they will be released when its scope parent is deleted.552 LVLineDebug *Line = createLineDebug();553 CULines.push_back(Line);554 // Consider the case of WebAssembly.555 Line->setAddress(Row.Address.Address + WasmCodeSectionOffset);556 Line->setFilename(557 CompileUnit->getFilename(IncrementIndex ? Row.File + 1 : Row.File));558 Line->setLineNumber(Row.Line);559 if (Row.Discriminator)560 Line->setDiscriminator(Row.Discriminator);561 if (Row.IsStmt)562 Line->setIsNewStatement();563 if (Row.BasicBlock)564 Line->setIsBasicBlock();565 if (Row.EndSequence)566 Line->setIsEndSequence();567 if (Row.EpilogueBegin)568 Line->setIsEpilogueBegin();569 if (Row.PrologueEnd)570 Line->setIsPrologueEnd();571 LLVM_DEBUG({572 dbgs() << "Address: " << hexValue(Line->getAddress())573 << " Line: " << Line->lineNumberAsString(/*ShowZero=*/true)574 << "\n";575 });576 }577}578 579std::string LVDWARFReader::getRegisterName(LVSmall Opcode,580 ArrayRef<uint64_t> Operands) {581 // The 'prettyPrintRegisterOp' function uses the DWARFUnit to support582 // DW_OP_regval_type. At this point we are operating on a logical view583 // item, with no access to the underlying DWARF data used by LLVM.584 // We do not support DW_OP_regval_type here.585 if (Opcode == dwarf::DW_OP_regval_type)586 return {};587 588 std::string string;589 raw_string_ostream Stream(string);590 DIDumpOptions DumpOpts;591 auto *MCRegInfo = MRI.get();592 auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> StringRef {593 if (!MCRegInfo)594 return {};595 if (std::optional<MCRegister> LLVMRegNum =596 MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))597 if (const char *RegName = MCRegInfo->getName(*LLVMRegNum))598 return StringRef(RegName);599 return {};600 };601 DumpOpts.GetNameForDWARFReg = GetRegName;602 prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts, Opcode, Operands);603 return Stream.str();604}605 606Error LVDWARFReader::createScopes() {607 LLVM_DEBUG({608 W.startLine() << "\n";609 W.printString("File", Obj.getFileName().str());610 W.printString("Format", FileFormatName);611 });612 613 if (Error Err = LVReader::createScopes())614 return Err;615 616 // As the DwarfContext object is valid only during the scopes creation,617 // we need to create our own Target information, to be used during the618 // logical view printing, in the case of instructions being requested.619 std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(Obj);620 if (!DwarfContext)621 return createStringError(errc::invalid_argument,622 "Could not create DWARF information: %s",623 getFilename().str().c_str());624 625 if (Error Err = loadTargetInfo(Obj))626 return Err;627 628 // Create a mapping for virtual addresses.629 mapVirtualAddress(Obj);630 631 // Select the correct compile unit range, depending if we are dealing with632 // a standard or split DWARF object.633 DWARFContext::compile_unit_range CompileUnits =634 DwarfContext->getNumCompileUnits() ? DwarfContext->compile_units()635 : DwarfContext->dwo_compile_units();636 for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) {637 638 // Take into account the address byte size for a correct 'tombstone'639 // value identification.640 setTombstoneAddress(641 dwarf::computeTombstoneAddress(CU->getAddressByteSize()));642 643 // Deduction of index used for the line records.644 //645 // For the following test case: test.cpp646 // void foo(void ParamPtr) { }647 648 // Both GCC and Clang generate DWARF-5 .debug_line layout.649 650 // * GCC (GNU C++17 11.3.0) - All DW_AT_decl_file use index 1.651 //652 // .debug_info:653 // format = DWARF32, version = 0x0005654 // DW_TAG_compile_unit655 // DW_AT_name ("test.cpp")656 // DW_TAG_subprogram ("foo")657 // DW_AT_decl_file (1)658 // DW_TAG_formal_parameter ("ParamPtr")659 // DW_AT_decl_file (1)660 // .debug_line:661 // Line table prologue: format (DWARF32), version (5)662 // include_directories[0] = "..."663 // file_names[0]: name ("test.cpp"), dir_index (0)664 // file_names[1]: name ("test.cpp"), dir_index (0)665 666 // * Clang (14.0.6) - All DW_AT_decl_file use index 0.667 //668 // .debug_info:669 // format = DWARF32, version = 0x0005670 // DW_AT_producer ("clang version 14.0.6")671 // DW_AT_name ("test.cpp")672 //673 // DW_TAG_subprogram ("foo")674 // DW_AT_decl_file (0)675 // DW_TAG_formal_parameter ("ParamPtr")676 // DW_AT_decl_file (0)677 // .debug_line:678 // Line table prologue: format (DWARF32), version (5)679 // include_directories[0] = "..."680 // file_names[0]: name ("test.cpp"), dir_index (0)681 682 // From DWARFDebugLine::getFileNameByIndex documentation:683 // In Dwarf 4, the files are 1-indexed.684 // In Dwarf 5, the files are 0-indexed.685 // Additional discussions here:686 // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00883.html687 688 // The DWARF reader is expecting the files are 1-indexed, so using689 // the .debug_line header information decide if the indexed require690 // an internal adjustment.691 692 // For the case of GCC (DWARF5), if the entries[0] and [1] are the693 // same, do not perform any adjustment.694 auto DeduceIncrementFileIndex = [&]() -> bool {695 if (CU->getVersion() < 5)696 // DWARF-4 or earlier -> Don't increment index.697 return false;698 699 if (const DWARFDebugLine::LineTable *LT =700 CU->getContext().getLineTableForUnit(CU.get())) {701 // Check if there are at least 2 entries and if they are the same.702 if (LT->hasFileAtIndex(0) && LT->hasFileAtIndex(1)) {703 const DWARFDebugLine::FileNameEntry &EntryZero =704 LT->Prologue.getFileNameEntry(0);705 const DWARFDebugLine::FileNameEntry &EntryOne =706 LT->Prologue.getFileNameEntry(1);707 // Check directory indexes.708 if (EntryZero.DirIdx != EntryOne.DirIdx)709 // DWARF-5 -> Increment index.710 return true;711 // Check filename.712 std::string FileZero;713 std::string FileOne;714 StringRef None;715 LT->getFileNameByIndex(716 0, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,717 FileZero);718 LT->getFileNameByIndex(719 1, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,720 FileOne);721 return FileZero != FileOne;722 }723 }724 725 // DWARF-5 -> Increment index.726 return true;727 };728 // The DWARF reader expects the indexes as 1-indexed.729 IncrementFileIndex = DeduceIncrementFileIndex();730 731 DWARFDie UnitDie = CU->getUnitDIE();732 SmallString<16> DWOAlternativeLocation;733 if (UnitDie) {734 std::optional<const char *> DWOFileName =735 CU->getVersion() >= 5736 ? dwarf::toString(UnitDie.find(dwarf::DW_AT_dwo_name))737 : dwarf::toString(UnitDie.find(dwarf::DW_AT_GNU_dwo_name));738 StringRef From(DWOFileName.value_or(""));739 DWOAlternativeLocation = createAlternativePath(From);740 }741 742 // The current CU can be a normal compile unit (standard) or a skeleton743 // compile unit (split). For both cases, the returned die, will be used744 // to create the logical scopes.745 DWARFDie CUDie = CU->getNonSkeletonUnitDIE(746 /*ExtractUnitDIEOnly=*/false,747 /*DWOAlternativeLocation=*/DWOAlternativeLocation);748 if (!CUDie.isValid())749 continue;750 751 // The current unit corresponds to the .dwo file. We need to get the752 // skeleton unit and query for any ranges that will enclose any ranges753 // in the non-skeleton unit.754 DWARFDie DummyDie;755 DWARFDie SkeletonDie =756 CUDie.getDwarfUnit()->isDWOUnit() ? CU->getUnitDIE(false) : DummyDie;757 // Disable the ranges processing if we have just a single .dwo object,758 // as any DW_AT_ranges will access not available range information.759 RangesDataAvailable =760 (!CUDie.getDwarfUnit()->isDWOUnit() ||761 (SkeletonDie.isValid() ? !SkeletonDie.getDwarfUnit()->isDWOUnit()762 : true));763 764 traverseDieAndChildren(CUDie, Root, SkeletonDie);765 766 createLineAndFileRecords(DwarfContext->getLineTableForUnit(CU.get()));767 if (Error Err = createInstructions())768 return Err;769 770 // Process the compilation unit, as there are cases where enclosed771 // functions have the same ranges values. Insert the compilation unit772 // ranges at the end, to allow enclosing ranges to be first in the list.773 LVSectionIndex SectionIndex = getSectionIndex(CompileUnit);774 addSectionRange(SectionIndex, CompileUnit);775 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);776 ScopesWithRanges->sort();777 778 processLines(&CULines, SectionIndex);779 processLocationGaps();780 781 // These are per compile unit.782 ScopesWithRanges->clear();783 SymbolsWithLocations.clear();784 CULines.clear();785 }786 787 return Error::success();788}789 790// Get the location information for the associated attribute.791void LVDWARFReader::processLocationList(dwarf::Attribute Attr,792 const DWARFFormValue &FormValue,793 const DWARFDie &Die,794 uint64_t OffsetOnEntry,795 bool CallSiteLocation) {796 797 auto ProcessLocationExpression = [&](const DWARFExpression &Expression) {798 for (const DWARFExpression::Operation &Op : Expression)799 CurrentSymbol->addLocationOperands(Op.getCode(), Op.getRawOperands());800 };801 802 DWARFUnit *U = Die.getDwarfUnit();803 DWARFContext &DwarfContext = U->getContext();804 bool IsLittleEndian = DwarfContext.isLittleEndian();805 if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||806 (DWARFAttribute::mayHaveLocationExpr(Attr) &&807 FormValue.isFormClass(DWARFFormValue::FC_Exprloc))) {808 ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();809 DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),810 IsLittleEndian, 0);811 DWARFExpression Expression(Data, U->getAddressByteSize(),812 U->getFormParams().Format);813 814 // Add location and operation entries.815 CurrentSymbol->addLocation(Attr, /*LowPC=*/0, /*HighPC=*/-1,816 /*SectionOffset=*/0, OffsetOnEntry,817 CallSiteLocation);818 ProcessLocationExpression(Expression);819 return;820 }821 822 if (DWARFAttribute::mayHaveLocationList(Attr) &&823 FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {824 uint64_t Offset = *FormValue.getAsSectionOffset();825 if (FormValue.getForm() == dwarf::DW_FORM_loclistx) {826 std::optional<uint64_t> LoclistOffset = U->getLoclistOffset(Offset);827 if (!LoclistOffset)828 return;829 Offset = *LoclistOffset;830 }831 uint64_t BaseAddr = 0;832 if (std::optional<SectionedAddress> BA = U->getBaseAddress())833 BaseAddr = BA->Address;834 LVAddress LowPC = 0;835 LVAddress HighPC = 0;836 837 auto ProcessLocationEntry = [&](const DWARFLocationEntry &Entry) {838 if (Entry.Kind == dwarf::DW_LLE_base_address) {839 BaseAddr = Entry.Value0;840 return;841 }842 if (Entry.Kind == dwarf::DW_LLE_offset_pair) {843 LowPC = BaseAddr + Entry.Value0;844 HighPC = BaseAddr + Entry.Value1;845 DWARFAddressRange Range{LowPC, HighPC, Entry.SectionIndex};846 if (Range.SectionIndex == SectionedAddress::UndefSection)847 Range.SectionIndex = Entry.SectionIndex;848 DWARFLocationExpression Loc{Range, Entry.Loc};849 DWARFDataExtractor Data(Loc.Expr, IsLittleEndian,850 U->getAddressByteSize());851 DWARFExpression Expression(Data, U->getAddressByteSize());852 853 // Store the real upper limit for the address range.854 if (UpdateHighAddress && HighPC > 0)855 --HighPC;856 // Add location and operation entries.857 CurrentSymbol->addLocation(Attr, LowPC, HighPC, Offset, OffsetOnEntry,858 CallSiteLocation);859 ProcessLocationExpression(Expression);860 }861 };862 Error E = U->getLocationTable().visitLocationList(863 &Offset, [&](const DWARFLocationEntry &E) {864 ProcessLocationEntry(E);865 return true;866 });867 if (E)868 consumeError(std::move(E));869 }870}871 872void LVDWARFReader::processLocationMember(dwarf::Attribute Attr,873 const DWARFFormValue &FormValue,874 const DWARFDie &Die,875 uint64_t OffsetOnEntry) {876 // Check if the value is an integer constant.877 if (FormValue.isFormClass(DWARFFormValue::FC_Constant))878 // Add a record to hold a constant as location.879 CurrentSymbol->addLocationConstant(Attr, *FormValue.getAsUnsignedConstant(),880 OffsetOnEntry);881 else882 // This is a location description, or a reference to one.883 processLocationList(Attr, FormValue, Die, OffsetOnEntry);884}885 886// Update the current element with the reference.887void LVDWARFReader::updateReference(dwarf::Attribute Attr,888 const DWARFFormValue &FormValue) {889 // FIXME: We are assuming that at most one Reference (DW_AT_specification,890 // DW_AT_abstract_origin, ...) and at most one Type (DW_AT_import, DW_AT_type)891 // appear in any single DIE, but this may not be true.892 uint64_t Offset;893 if (std::optional<uint64_t> Off = FormValue.getAsRelativeReference())894 Offset = FormValue.getUnit()->getOffset() + *Off;895 else if (Off = FormValue.getAsDebugInfoReference(); Off)896 Offset = *Off;897 else898 llvm_unreachable("Unsupported reference type");899 900 // Get target for the given reference, if already created.901 LVElement *Target = getElementForOffset(902 Offset, CurrentElement,903 /*IsType=*/Attr == dwarf::DW_AT_import || Attr == dwarf::DW_AT_type);904 // Check if we are dealing with cross CU references.905 if (FormValue.getForm() == dwarf::DW_FORM_ref_addr) {906 if (Target) {907 // The global reference is ready. Mark it as global.908 Target->setIsGlobalReference();909 // Remove global reference from the unseen list.910 removeGlobalOffset(Offset);911 } else912 // Record the unseen cross CU reference.913 addGlobalOffset(Offset);914 }915 916 // At this point, 'Target' can be null, in the case of the target element917 // not being seen. But the correct bit is set, to indicate that the target918 // is being referenced by (abstract_origin, extension, specification) or919 // (import, type).920 // We must differentiate between the kind of reference. This is needed to921 // complete inlined function instances with dropped abstract references,922 // in order to facilitate a logical comparison.923 switch (Attr) {924 case dwarf::DW_AT_abstract_origin:925 case dwarf::DW_AT_call_origin:926 CurrentElement->setReference(Target);927 CurrentElement->setHasReferenceAbstract();928 break;929 case dwarf::DW_AT_extension:930 CurrentElement->setReference(Target);931 CurrentElement->setHasReferenceExtension();932 break;933 case dwarf::DW_AT_specification:934 CurrentElement->setReference(Target);935 CurrentElement->setHasReferenceSpecification();936 break;937 case dwarf::DW_AT_import:938 case dwarf::DW_AT_type:939 CurrentElement->setType(Target);940 break;941 default:942 break;943 }944}945 946// Get an element given the DIE offset.947LVElement *LVDWARFReader::getElementForOffset(LVOffset Offset,948 LVElement *Element, bool IsType) {949 // Update the element and all the references pointing to this element.950 LVElementEntry &Entry = ElementTable[Offset];951 if (!Entry.Element) {952 if (IsType)953 Entry.Types.insert(Element);954 else955 Entry.References.insert(Element);956 }957 return Entry.Element;958}959 960Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) {961 // Detect the architecture from the object file. We usually don't need OS962 // info to lookup a target and create register info.963 Triple TT = Obj.makeTriple();964 965 // Features to be passed to target/subtarget966 Expected<SubtargetFeatures> Features = Obj.getFeatures();967 SubtargetFeatures FeaturesValue;968 if (!Features) {969 consumeError(Features.takeError());970 FeaturesValue = SubtargetFeatures();971 }972 FeaturesValue = *Features;973 974 StringRef CPU;975 if (auto OptCPU = Obj.tryGetCPUName())976 CPU = *OptCPU;977 978 return loadGenericTargetInfo(TT.str(), FeaturesValue.getString(), CPU);979}980 981void LVDWARFReader::mapRangeAddress(const ObjectFile &Obj) {982 for (auto Iter = Obj.symbol_begin(); Iter != Obj.symbol_end(); ++Iter) {983 const SymbolRef &Symbol = *Iter;984 985 Expected<SymbolRef::Type> TypeOrErr = Symbol.getType();986 if (!TypeOrErr) {987 consumeError(TypeOrErr.takeError());988 continue;989 }990 991 // Process only symbols that represent a function.992 SymbolRef::Type Type = *TypeOrErr;993 if (Type != SymbolRef::ST_Function)994 continue;995 996 // In the case of a Mach-O STAB symbol, get its section only if997 // the STAB symbol's section field refers to a valid section index.998 // Otherwise the symbol may error trying to load a section that999 // does not exist.1000 const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&Obj);1001 bool IsSTAB = false;1002 if (MachO) {1003 DataRefImpl SymDRI = Symbol.getRawDataRefImpl();1004 uint8_t NType =1005 (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type1006 : MachO->getSymbolTableEntry(SymDRI).n_type);1007 if (NType & MachO::N_STAB)1008 IsSTAB = true;1009 }1010 1011 Expected<section_iterator> IterOrErr = Symbol.getSection();1012 if (!IterOrErr) {1013 consumeError(IterOrErr.takeError());1014 continue;1015 }1016 section_iterator Section = IsSTAB ? Obj.section_end() : *IterOrErr;1017 if (Section == Obj.section_end())1018 continue;1019 1020 // Get the symbol value.1021 Expected<uint64_t> AddressOrErr = Symbol.getAddress();1022 if (!AddressOrErr) {1023 consumeError(AddressOrErr.takeError());1024 continue;1025 }1026 uint64_t Address = *AddressOrErr;1027 1028 // Get symbol name.1029 StringRef Name;1030 Expected<StringRef> NameOrErr = Symbol.getName();1031 if (!NameOrErr) {1032 consumeError(NameOrErr.takeError());1033 continue;1034 }1035 Name = *NameOrErr;1036 1037 // Check if the symbol is Comdat.1038 Expected<uint32_t> FlagsOrErr = Symbol.getFlags();1039 if (!FlagsOrErr) {1040 consumeError(FlagsOrErr.takeError());1041 continue;1042 }1043 uint32_t Flags = *FlagsOrErr;1044 1045 // Mark the symbol as 'comdat' in any of the following cases:1046 // - Symbol has the SF_Weak flag or1047 // - Symbol section index different from the DotTextSectionIndex.1048 LVSectionIndex SectionIndex = Section->getIndex();1049 bool IsComdat =1050 (Flags & SymbolRef::SF_Weak) || (SectionIndex != DotTextSectionIndex);1051 1052 // Record the symbol name (linkage) and its loading address.1053 addToSymbolTable(Name, Address, SectionIndex, IsComdat);1054 }1055}1056 1057void LVDWARFReader::sortScopes() { Root->sort(); }1058 1059void LVDWARFReader::print(raw_ostream &OS) const {1060 OS << "LVType\n";1061 LLVM_DEBUG(dbgs() << "CreateReaders\n");1062}1063