brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.8 KiB · deafee8 Raw
874 lines · cpp
1//===- DWARFDie.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#include "llvm/DebugInfo/DWARF/DWARFDie.h"10#include "llvm/ADT/SmallPtrSet.h"11#include "llvm/ADT/SmallSet.h"12#include "llvm/ADT/StringRef.h"13#include "llvm/BinaryFormat/Dwarf.h"14#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"15#include "llvm/DebugInfo/DWARF/DWARFContext.h"16#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"17#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"18#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"19#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"20#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"21#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"22#include "llvm/DebugInfo/DWARF/DWARFUnit.h"23#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"24#include "llvm/Object/ObjectFile.h"25#include "llvm/Support/DataExtractor.h"26#include "llvm/Support/Format.h"27#include "llvm/Support/FormatVariadic.h"28#include "llvm/Support/WithColor.h"29#include "llvm/Support/raw_ostream.h"30#include <cassert>31#include <cinttypes>32#include <cstdint>33#include <string>34 35using namespace llvm;36using namespace dwarf;37using namespace object;38 39static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {40  OS << " (";41  do {42    uint64_t Shift = llvm::countr_zero(Val);43    assert(Shift < 64 && "undefined behavior");44    uint64_t Bit = 1ULL << Shift;45    auto PropName = ApplePropertyString(Bit);46    if (!PropName.empty())47      OS << PropName;48    else49      OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);50    if (!(Val ^= Bit))51      break;52    OS << ", ";53  } while (true);54  OS << ")";55}56 57static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS,58                       const DWARFAddressRangesVector &Ranges,59                       unsigned AddressSize, unsigned Indent,60                       const DIDumpOptions &DumpOpts) {61  if (!DumpOpts.ShowAddresses)62    return;63 64  for (const DWARFAddressRange &R : Ranges) {65    OS << '\n';66    OS.indent(Indent);67    R.dump(OS, AddressSize, DumpOpts, &Obj);68  }69}70 71static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue,72                             DWARFUnit *U, unsigned Indent,73                             DIDumpOptions DumpOpts) {74  assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) &&75         "bad FORM for location list");76  DWARFContext &Ctx = U->getContext();77  uint64_t Offset = *FormValue.getAsSectionOffset();78 79  if (FormValue.getForm() == DW_FORM_loclistx) {80    FormValue.dump(OS, DumpOpts);81 82    if (auto LoclistOffset = U->getLoclistOffset(Offset))83      Offset = *LoclistOffset;84    else85      return;86  }87  U->getLocationTable().dumpLocationList(88      &Offset, OS, U->getBaseAddress(), Ctx.getDWARFObj(), U, DumpOpts, Indent);89}90 91static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,92                             DWARFUnit *U, unsigned Indent,93                             DIDumpOptions DumpOpts) {94  assert((FormValue.isFormClass(DWARFFormValue::FC_Block) ||95          FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) &&96         "bad FORM for location expression");97  DWARFContext &Ctx = U->getContext();98  ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();99  DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),100                     Ctx.isLittleEndian(), 0);101  DWARFExpression DE(Data, U->getAddressByteSize(), U->getFormParams().Format);102  printDwarfExpression(&DE, OS, DumpOpts, U);103}104 105static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {106  return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();107}108 109static llvm::StringRef110prettyLanguageVersionString(const DWARFAttribute &AttrValue,111                            const DWARFDie &Die) {112  if (AttrValue.Attr != DW_AT_language_version)113    return {};114 115  auto NameForm = Die.find(DW_AT_language_name);116  if (!NameForm)117    return {};118 119  auto LName = NameForm->getAsUnsignedConstant();120  if (!LName)121    return {};122 123  auto LVersion = AttrValue.Value.getAsUnsignedConstant();124  if (!LVersion)125    return {};126 127  return llvm::dwarf::LanguageDescription(128      static_cast<SourceLanguageName>(*LName), *LVersion);129}130 131static llvm::Expected<llvm::StringRef>132getApplePropertyName(const DWARFDie &PropDIE) {133  if (!PropDIE)134    return llvm::createStringError("invalid DIE");135 136  if (PropDIE.getTag() != DW_TAG_APPLE_property)137    return llvm::createStringError("not referencing a DW_TAG_APPLE_property");138 139  auto PropNameForm = PropDIE.find(DW_AT_APPLE_property_name);140  if (!PropNameForm)141    return "";142 143  auto NameOrErr = PropNameForm->getAsCString();144  if (!NameOrErr)145    return NameOrErr.takeError();146 147  return *NameOrErr;148}149 150static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,151                          const DWARFAttribute &AttrValue, unsigned Indent,152                          DIDumpOptions DumpOpts) {153  if (!Die.isValid())154    return;155  const char BaseIndent[] = "            ";156  OS << BaseIndent;157  OS.indent(Indent + 2);158  dwarf::Attribute Attr = AttrValue.Attr;159  WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr);160 161  dwarf::Form Form = AttrValue.Value.getForm();162  if (DumpOpts.Verbose || DumpOpts.ShowForm)163    OS << formatv(" [{0}]", Form);164 165  DWARFUnit *U = Die.getDwarfUnit();166  const DWARFFormValue &FormValue = AttrValue.Value;167 168  OS << "\t(";169 170  StringRef Name;171  std::string File;172  auto Color = HighlightColor::Enumerator;173  if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {174    Color = HighlightColor::String;175    if (const auto *LT = U->getContext().getLineTableForUnit(U)) {176      if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) {177        if (LT->getFileNameByIndex(178                *Val, U->getCompilationDir(),179                DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,180                File)) {181          File = '"' + File + '"';182          Name = File;183        }184      }185    }186  } else if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())187    Name = AttributeValueString(Attr, *Val);188 189  auto DumpUnsignedConstant = [&OS,190                               &DumpOpts](const DWARFFormValue &FormValue) {191    if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())192      OS << *Val;193    else194      FormValue.dump(OS, DumpOpts);195  };196 197  llvm::StringRef PrettyVersionName =198      prettyLanguageVersionString(AttrValue, Die);199  bool ShouldDumpRawLanguageVersion =200      Attr == DW_AT_language_version &&201      (DumpOpts.Verbose || PrettyVersionName.empty());202 203  if (!Name.empty())204    WithColor(OS, Color) << Name;205  else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column ||206           Attr == DW_AT_call_line || Attr == DW_AT_call_column) {207    DumpUnsignedConstant(FormValue);208  } else if (Attr == DW_AT_language_version) {209    if (ShouldDumpRawLanguageVersion)210      DumpUnsignedConstant(FormValue);211  } else if (Attr == DW_AT_low_pc &&212             (FormValue.getAsAddress() ==213              dwarf::computeTombstoneAddress(U->getAddressByteSize()))) {214    if (DumpOpts.Verbose) {215      FormValue.dump(OS, DumpOpts);216      OS << " (";217    }218    OS << "dead code";219    if (DumpOpts.Verbose)220      OS << ')';221  } else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose &&222             FormValue.getAsUnsignedConstant()) {223    if (DumpOpts.ShowAddresses) {224      // Print the actual address rather than the offset.225      uint64_t LowPC, HighPC, Index;226      if (Die.getLowAndHighPC(LowPC, HighPC, Index))227        DWARFFormValue::dumpAddress(OS, U->getAddressByteSize(), HighPC);228      else229        FormValue.dump(OS, DumpOpts);230    }231  } else if (DWARFAttribute::mayHaveLocationList(Attr) &&232             FormValue.isFormClass(DWARFFormValue::FC_SectionOffset))233    dumpLocationList(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4,234                     DumpOpts);235  else if (FormValue.isFormClass(DWARFFormValue::FC_Exprloc) ||236           (DWARFAttribute::mayHaveLocationExpr(Attr) &&237            FormValue.isFormClass(DWARFFormValue::FC_Block)))238    dumpLocationExpr(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4,239                     DumpOpts);240  else241    FormValue.dump(OS, DumpOpts);242 243  std::string Space = DumpOpts.ShowAddresses ? " " : "";244 245  // We have dumped the attribute raw value. For some attributes246  // having both the raw value and the pretty-printed value is247  // interesting. These attributes are handled below.248  if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin ||249      Attr == DW_AT_call_origin) {250    if (const char *Name =251            Die.getAttributeValueAsReferencedDie(FormValue).getName(252                DINameKind::LinkageName))253      OS << Space << "\"" << Name << '\"';254  } else if (Attr == DW_AT_APPLE_property) {255    auto PropDIE = Die.getAttributeValueAsReferencedDie(FormValue);256    if (auto PropNameOrErr = getApplePropertyName(PropDIE))257      OS << Space << "\"" << *PropNameOrErr << '\"';258    else259      DumpOpts.RecoverableErrorHandler(createStringError(260          errc::invalid_argument,261          llvm::formatv("decoding DW_AT_APPLE_property_name: {}",262                        toString(PropNameOrErr.takeError()))));263  } else if (Attr == DW_AT_type || Attr == DW_AT_containing_type) {264    DWARFDie D = resolveReferencedType(Die, FormValue);265    if (D && !D.isNULL()) {266      OS << Space << "\"";267      dumpTypeQualifiedName(D, OS);268      OS << '"';269    }270  } else if (Attr == DW_AT_APPLE_property_attribute) {271    if (std::optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant())272      dumpApplePropertyAttribute(OS, *OptVal);273  } else if (Attr == DW_AT_ranges) {274    const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();275    // For DW_FORM_rnglistx we need to dump the offset separately, since276    // we have only dumped the index so far.277    if (FormValue.getForm() == DW_FORM_rnglistx)278      if (auto RangeListOffset =279              U->getRnglistOffset(*FormValue.getAsSectionOffset())) {280        DWARFFormValue FV = DWARFFormValue::createFromUValue(281            dwarf::DW_FORM_sec_offset, *RangeListOffset);282        FV.dump(OS, DumpOpts);283      }284    if (auto RangesOrError = Die.getAddressRanges())285      dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(),286                 sizeof(BaseIndent) + Indent + 4, DumpOpts);287    else288      DumpOpts.RecoverableErrorHandler(createStringError(289          errc::invalid_argument, "decoding address ranges: %s",290          toString(RangesOrError.takeError()).c_str()));291  } else if (Attr == DW_AT_language_version) {292    if (!PrettyVersionName.empty())293      WithColor(OS, Color) << (ShouldDumpRawLanguageVersion ? " " : "")294                           << PrettyVersionName;295  }296 297  OS << ")\n";298}299 300void DWARFDie::getFullName(raw_string_ostream &OS,301                           std::string *OriginalFullName) const {302  const char *NamePtr = getShortName();303  if (!NamePtr)304    return;305  if (getTag() == DW_TAG_GNU_template_parameter_pack)306    return;307  dumpTypeUnqualifiedName(*this, OS, OriginalFullName);308}309 310bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; }311 312bool DWARFDie::isSubroutineDIE() const {313  auto Tag = getTag();314  return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;315}316 317std::optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const {318  if (!isValid())319    return std::nullopt;320  auto AbbrevDecl = getAbbreviationDeclarationPtr();321  if (AbbrevDecl)322    return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);323  return std::nullopt;324}325 326std::optional<DWARFFormValue>327DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {328  if (!isValid())329    return std::nullopt;330  auto AbbrevDecl = getAbbreviationDeclarationPtr();331  if (AbbrevDecl) {332    for (auto Attr : Attrs) {333      if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))334        return Value;335    }336  }337  return std::nullopt;338}339 340std::optional<DWARFFormValue>341DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {342  SmallVector<DWARFDie, 3> Worklist;343  Worklist.push_back(*this);344 345  // Keep track if DIEs already seen to prevent infinite recursion.346  // Empirically we rarely see a depth of more than 3 when dealing with valid347  // DWARF. This corresponds to following the DW_AT_abstract_origin and348  // DW_AT_specification just once.349  SmallSet<DWARFDie, 3> Seen;350  Seen.insert(*this);351 352  while (!Worklist.empty()) {353    DWARFDie Die = Worklist.pop_back_val();354 355    if (!Die.isValid())356      continue;357 358    if (auto Value = Die.find(Attrs))359      return Value;360 361    for (dwarf::Attribute Attr :362         {DW_AT_abstract_origin, DW_AT_specification, DW_AT_signature}) {363      if (auto D = Die.getAttributeValueAsReferencedDie(Attr))364        if (Seen.insert(D).second)365          Worklist.push_back(D);366    }367  }368 369  return std::nullopt;370}371 372DWARFDie373DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {374  if (std::optional<DWARFFormValue> F = find(Attr))375    return getAttributeValueAsReferencedDie(*F);376  return DWARFDie();377}378 379DWARFDie380DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {381  DWARFDie Result;382  if (std::optional<uint64_t> Offset = V.getAsRelativeReference()) {383    Result = const_cast<DWARFUnit *>(V.getUnit())384                 ->getDIEForOffset(V.getUnit()->getOffset() + *Offset);385  } else if (Offset = V.getAsDebugInfoReference(); Offset) {386    if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(*Offset))387      Result = SpecUnit->getDIEForOffset(*Offset);388  } else if (std::optional<uint64_t> Sig = V.getAsSignatureReference()) {389    if (DWARFTypeUnit *TU =390            U->getContext().getTypeUnitForHash(*Sig, U->isDWOUnit()))391      Result = TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());392  }393  return Result;394}395 396DWARFDie DWARFDie::resolveTypeUnitReference() const {397  if (auto Attr = find(DW_AT_signature)) {398    if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {399      if (DWARFTypeUnit *TU =400              U->getContext().getTypeUnitForHash(*Sig, U->isDWOUnit()))401        return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());402    }403  }404  return *this;405}406 407DWARFDie DWARFDie::resolveReferencedType(dwarf::Attribute Attr) const {408  return getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();409}410DWARFDie DWARFDie::resolveReferencedType(const DWARFFormValue &V) const {411  return getAttributeValueAsReferencedDie(V).resolveTypeUnitReference();412}413 414std::optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {415  return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));416}417 418std::optional<uint64_t> DWARFDie::getLocBaseAttribute() const {419  return toSectionOffset(find(DW_AT_loclists_base));420}421 422std::optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {423  uint64_t Tombstone = dwarf::computeTombstoneAddress(U->getAddressByteSize());424  if (LowPC == Tombstone)425    return std::nullopt;426  if (auto FormValue = find(DW_AT_high_pc)) {427    if (auto Address = FormValue->getAsAddress()) {428      // High PC is an address.429      return Address;430    }431    if (auto Offset = FormValue->getAsUnsignedConstant()) {432      // High PC is an offset from LowPC.433      return LowPC + *Offset;434    }435  }436  return std::nullopt;437}438 439bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,440                               uint64_t &SectionIndex) const {441  auto F = find(DW_AT_low_pc);442  auto LowPcAddr = toSectionedAddress(F);443  if (!LowPcAddr)444    return false;445  if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) {446    LowPC = LowPcAddr->Address;447    HighPC = *HighPcAddr;448    SectionIndex = LowPcAddr->SectionIndex;449    return true;450  }451  return false;452}453 454Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const {455  if (isNULL())456    return DWARFAddressRangesVector();457  // Single range specified by low/high PC.458  uint64_t LowPC, HighPC, Index;459  if (getLowAndHighPC(LowPC, HighPC, Index))460    return DWARFAddressRangesVector{{LowPC, HighPC, Index}};461 462  std::optional<DWARFFormValue> Value = find(DW_AT_ranges);463  if (Value) {464    if (Value->getForm() == DW_FORM_rnglistx)465      return U->findRnglistFromIndex(*Value->getAsSectionOffset());466    return U->findRnglistFromOffset(*Value->getAsSectionOffset());467  }468  return DWARFAddressRangesVector();469}470 471bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {472  auto RangesOrError = getAddressRanges();473  if (!RangesOrError) {474    llvm::consumeError(RangesOrError.takeError());475    return false;476  }477 478  for (const auto &R : RangesOrError.get())479    if (R.LowPC <= Address && Address < R.HighPC)480      return true;481  return false;482}483 484std::optional<uint64_t> DWARFDie::getLanguage() const {485  if (isValid()) {486    if (std::optional<DWARFFormValue> LV =487            U->getUnitDIE().find(dwarf::DW_AT_language))488      return LV->getAsUnsignedConstant();489  }490  return std::nullopt;491}492 493Expected<DWARFLocationExpressionsVector>494DWARFDie::getLocations(dwarf::Attribute Attr) const {495  std::optional<DWARFFormValue> Location = find(Attr);496  if (!Location)497    return createStringError(inconvertibleErrorCode(), "No %s",498                             dwarf::AttributeString(Attr).data());499 500  if (std::optional<uint64_t> Off = Location->getAsSectionOffset()) {501    uint64_t Offset = *Off;502 503    if (Location->getForm() == DW_FORM_loclistx) {504      if (auto LoclistOffset = U->getLoclistOffset(Offset))505        Offset = *LoclistOffset;506      else507        return createStringError(inconvertibleErrorCode(),508                                 "Loclist table not found");509    }510    return U->findLoclistFromOffset(Offset);511  }512 513  if (std::optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) {514    return DWARFLocationExpressionsVector{515        DWARFLocationExpression{std::nullopt, to_vector<4>(*Expr)}};516  }517 518  return createStringError(519      inconvertibleErrorCode(), "Unsupported %s encoding: %s",520      dwarf::AttributeString(Attr).data(),521      dwarf::FormEncodingString(Location->getForm()).data());522}523 524const char *DWARFDie::getSubroutineName(DINameKind Kind) const {525  if (!isSubroutineDIE())526    return nullptr;527  return getName(Kind);528}529 530const char *DWARFDie::getName(DINameKind Kind) const {531  if (!isValid() || Kind == DINameKind::None)532    return nullptr;533  // Try to get mangled name only if it was asked for.534  if (Kind == DINameKind::LinkageName) {535    if (auto Name = getLinkageName())536      return Name;537  }538  return getShortName();539}540 541const char *DWARFDie::getShortName() const {542  if (!isValid())543    return nullptr;544 545  return dwarf::toString(findRecursively(dwarf::DW_AT_name), nullptr);546}547 548const char *DWARFDie::getLinkageName() const {549  if (!isValid())550    return nullptr;551 552  return dwarf::toString(findRecursively({dwarf::DW_AT_MIPS_linkage_name,553                                          dwarf::DW_AT_linkage_name}),554                         nullptr);555}556 557uint64_t DWARFDie::getDeclLine() const {558  return toUnsigned(findRecursively(DW_AT_decl_line), 0);559}560 561std::string562DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {563  if (auto FormValue = findRecursively(DW_AT_decl_file))564    if (auto OptString = FormValue->getAsFile(Kind))565      return *OptString;566  return {};567}568 569void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,570                              uint32_t &CallColumn,571                              uint32_t &CallDiscriminator) const {572  CallFile = toUnsigned(find(DW_AT_call_file), 0);573  CallLine = toUnsigned(find(DW_AT_call_line), 0);574  CallColumn = toUnsigned(find(DW_AT_call_column), 0);575  CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0);576}577 578static std::optional<uint64_t>579getTypeSizeImpl(DWARFDie Die, uint64_t PointerSize,580                SmallPtrSetImpl<const DWARFDebugInfoEntry *> &Visited) {581  // Cycle detected?582  if (!Visited.insert(Die.getDebugInfoEntry()).second)583    return {};584  if (auto SizeAttr = Die.find(DW_AT_byte_size))585    if (std::optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant())586      return Size;587 588  switch (Die.getTag()) {589  case DW_TAG_pointer_type:590  case DW_TAG_reference_type:591  case DW_TAG_rvalue_reference_type:592    return PointerSize;593  case DW_TAG_ptr_to_member_type: {594    if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))595      if (BaseType.getTag() == DW_TAG_subroutine_type)596        return 2 * PointerSize;597    return PointerSize;598  }599  case DW_TAG_const_type:600  case DW_TAG_immutable_type:601  case DW_TAG_volatile_type:602  case DW_TAG_restrict_type:603  case DW_TAG_template_alias:604  case DW_TAG_typedef: {605    if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))606      return getTypeSizeImpl(BaseType, PointerSize, Visited);607    break;608  }609  case DW_TAG_array_type: {610    DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type);611    if (!BaseType)612      return std::nullopt;613    std::optional<uint64_t> BaseSize =614        getTypeSizeImpl(BaseType, PointerSize, Visited);615    if (!BaseSize)616      return std::nullopt;617    uint64_t Size = *BaseSize;618    for (DWARFDie Child : Die) {619      if (Child.getTag() != DW_TAG_subrange_type)620        continue;621 622      if (auto ElemCountAttr = Child.find(DW_AT_count))623        if (std::optional<uint64_t> ElemCount =624                ElemCountAttr->getAsUnsignedConstant())625          Size *= *ElemCount;626      if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound))627        if (std::optional<int64_t> UpperBound =628                UpperBoundAttr->getAsSignedConstant()) {629          int64_t LowerBound = 0;630          if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound))631            LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(0);632          Size *= *UpperBound - LowerBound + 1;633        }634    }635    return Size;636  }637  default:638    if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))639      return getTypeSizeImpl(BaseType, PointerSize, Visited);640    break;641  }642  return std::nullopt;643}644 645std::optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) {646  SmallPtrSet<const DWARFDebugInfoEntry *, 4> Visited;647  return getTypeSizeImpl(*this, PointerSize, Visited);648}649 650/// Helper to dump a DIE with all of its parents, but no siblings.651static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent,652                                DIDumpOptions DumpOpts, unsigned Depth = 0) {653  if (!Die)654    return Indent;655  if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth)656    return Indent;657  Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1);658  Die.dump(OS, Indent, DumpOpts);659  return Indent + 2;660}661 662void DWARFDie::dump(raw_ostream &OS, unsigned Indent,663                    DIDumpOptions DumpOpts) const {664  if (!isValid())665    return;666  DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();667  const uint64_t Offset = getOffset();668  uint64_t offset = Offset;669  if (DumpOpts.ShowParents) {670    DIDumpOptions ParentDumpOpts = DumpOpts;671    ParentDumpOpts.ShowParents = false;672    ParentDumpOpts.ShowChildren = false;673    Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts);674  }675 676  if (debug_info_data.isValidOffset(offset)) {677    uint32_t abbrCode = debug_info_data.getULEB128(&offset);678    if (DumpOpts.ShowAddresses)679      WithColor(OS, HighlightColor::Address).get()680          << format("\n0x%8.8" PRIx64 ": ", Offset);681 682    if (abbrCode) {683      auto AbbrevDecl = getAbbreviationDeclarationPtr();684      if (AbbrevDecl) {685        WithColor(OS, HighlightColor::Tag).get().indent(Indent)686            << formatv("{0}", getTag());687        if (DumpOpts.Verbose) {688          OS << format(" [%u] %c", abbrCode,689                       AbbrevDecl->hasChildren() ? '*' : ' ');690          if (std::optional<uint32_t> ParentIdx = Die->getParentIdx())691            OS << format(" (0x%8.8" PRIx64 ")",692                         U->getDIEAtIndex(*ParentIdx).getOffset());693        }694        OS << '\n';695 696        // Dump all data in the DIE for the attributes.697        for (const DWARFAttribute &AttrValue : attributes())698          dumpAttribute(OS, *this, AttrValue, Indent, DumpOpts);699 700        if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0) {701          DWARFDie Child = getFirstChild();702          DumpOpts.ChildRecurseDepth--;703          DIDumpOptions ChildDumpOpts = DumpOpts;704          ChildDumpOpts.ShowParents = false;705          while (Child) {706            if (DumpOpts.FilterChildTag.empty() ||707                llvm::is_contained(DumpOpts.FilterChildTag, Child.getTag()))708              Child.dump(OS, Indent + 2, ChildDumpOpts);709            Child = Child.getSibling();710          }711        }712      } else {713        OS << "Abbreviation code not found in 'debug_abbrev' class for code: "714           << abbrCode << '\n';715      }716    } else {717      OS.indent(Indent) << "NULL\n";718    }719  }720}721 722LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); }723 724DWARFDie DWARFDie::getParent() const {725  if (isValid())726    return U->getParent(Die);727  return DWARFDie();728}729 730DWARFDie DWARFDie::getSibling() const {731  if (isValid())732    return U->getSibling(Die);733  return DWARFDie();734}735 736DWARFDie DWARFDie::getPreviousSibling() const {737  if (isValid())738    return U->getPreviousSibling(Die);739  return DWARFDie();740}741 742DWARFDie DWARFDie::getFirstChild() const {743  if (isValid())744    return U->getFirstChild(Die);745  return DWARFDie();746}747 748DWARFDie DWARFDie::getLastChild() const {749  if (isValid())750    return U->getLastChild(Die);751  return DWARFDie();752}753 754iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const {755  return make_range(attribute_iterator(*this, false),756                    attribute_iterator(*this, true));757}758 759DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End)760    : Die(D), Index(0) {761  auto AbbrDecl = Die.getAbbreviationDeclarationPtr();762  assert(AbbrDecl && "Must have abbreviation declaration");763  if (End) {764    // This is the end iterator so we set the index to the attribute count.765    Index = AbbrDecl->getNumAttributes();766  } else {767    // This is the begin iterator so we extract the value for this->Index.768    AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize();769    updateForIndex(*AbbrDecl, 0);770  }771}772 773void DWARFDie::attribute_iterator::updateForIndex(774    const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) {775  Index = I;776  // AbbrDecl must be valid before calling this function.777  auto NumAttrs = AbbrDecl.getNumAttributes();778  if (Index < NumAttrs) {779    AttrValue.Attr = AbbrDecl.getAttrByIndex(Index);780    // Add the previous byte size of any previous attribute value.781    AttrValue.Offset += AttrValue.ByteSize;782    uint64_t ParseOffset = AttrValue.Offset;783    if (AbbrDecl.getAttrIsImplicitConstByIndex(Index))784      AttrValue.Value = DWARFFormValue::createFromSValue(785          AbbrDecl.getFormByIndex(Index),786          AbbrDecl.getAttrImplicitConstValueByIndex(Index));787    else {788      auto U = Die.getDwarfUnit();789      assert(U && "Die must have valid DWARF unit");790      AttrValue.Value = DWARFFormValue::createFromUnit(791          AbbrDecl.getFormByIndex(Index), U, &ParseOffset);792    }793    AttrValue.ByteSize = ParseOffset - AttrValue.Offset;794  } else {795    assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");796    AttrValue = {};797  }798}799 800DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {801  if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())802    updateForIndex(*AbbrDecl, Index + 1);803  return *this;804}805 806bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr) {807  switch(Attr) {808  case DW_AT_location:809  case DW_AT_string_length:810  case DW_AT_return_addr:811  case DW_AT_data_member_location:812  case DW_AT_frame_base:813  case DW_AT_static_link:814  case DW_AT_segment:815  case DW_AT_use_location:816  case DW_AT_vtable_elem_location:817    return true;818  default:819    return false;820  }821}822 823bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr) {824  switch (Attr) {825  // From the DWARF v5 specification.826  case DW_AT_location:827  case DW_AT_byte_size:828  case DW_AT_bit_offset:829  case DW_AT_bit_size:830  case DW_AT_string_length:831  case DW_AT_lower_bound:832  case DW_AT_return_addr:833  case DW_AT_bit_stride:834  case DW_AT_upper_bound:835  case DW_AT_count:836  case DW_AT_data_member_location:837  case DW_AT_frame_base:838  case DW_AT_segment:839  case DW_AT_static_link:840  case DW_AT_use_location:841  case DW_AT_vtable_elem_location:842  case DW_AT_allocated:843  case DW_AT_associated:844  case DW_AT_data_location:845  case DW_AT_byte_stride:846  case DW_AT_rank:847  case DW_AT_call_value:848  case DW_AT_call_origin:849  case DW_AT_call_target:850  case DW_AT_call_target_clobbered:851  case DW_AT_call_data_location:852  case DW_AT_call_data_value:853  // Extensions.854  case DW_AT_GNU_call_site_value:855  case DW_AT_GNU_call_site_target:856    return true;857  default:858    return false;859  }860}861 862namespace llvm {863 864void dumpTypeQualifiedName(const DWARFDie &DIE, raw_ostream &OS) {865  DWARFTypePrinter<DWARFDie>(OS).appendQualifiedName(DIE);866}867 868void dumpTypeUnqualifiedName(const DWARFDie &DIE, raw_ostream &OS,869                             std::string *OriginalFullName) {870  DWARFTypePrinter<DWARFDie>(OS).appendUnqualifiedName(DIE, OriginalFullName);871}872 873} // namespace llvm874