Index: include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDie.h +++ include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -123,76 +123,17 @@ /// \param Attr the attribute to extract. /// \returns an optional DWARFFormValue that will have the form value if the /// attribute was successfully extracted. - Optional getAttributeValue(dwarf::Attribute Attr) const; + Optional find(dwarf::Attribute Attr) const; + - /// Extract the specified attribute from this DIE as a C string. + /// Extract an attribute value from this DIE and recurse into any + /// DW_AT_specification or DW_AT_abstract_origin referenced DIEs. /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// /// \param Attr the attribute to extract. - /// \param FailValue the value to return if this DIE doesn't have this - /// attribute. - /// \returns the NULL terminated C string value owned by the DWARF section - /// that contains the string or FailValue if the attribute doesn't exist or - /// if the attribute's form isn't a form that describes an string. - const char *getAttributeValueAsString(dwarf::Attribute Attr, - const char *FailValue) const; - - /// Extract the specified attribute from this DIE as an address. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. - /// \returns an optional value for the attribute. - Optional getAttributeValueAsAddress(dwarf::Attribute Attr) const; - - /// Extract the specified attribute from this DIE as a signed integer. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. - /// \returns an optional value for the attribute. - Optional - getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const; - - /// Extract the specified attribute from this DIE as an unsigned integer. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. - /// \returns an optional value for the attribute. - Optional - getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const; + /// \returns an optional DWARFFormValue that will have the form value if the + /// attribute was successfully extracted. + Optional findRecursively(dwarf::Attribute Attr) const; - /// Extract the specified attribute from this DIE as absolute DIE Offset. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. - /// \returns an optional value for the attribute. - Optional getAttributeValueAsReference(dwarf::Attribute Attr) const; - - /// Extract the specified attribute from this DIE as absolute section offset. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. - /// \returns an optional value for the attribute. - Optional - getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const; - /// Extract the specified attribute from this DIE as the referenced DIE. /// /// Regardless of the reference type, return the correct DWARFDie instance if Index: include/llvm/DebugInfo/DWARF/DWARFFormValue.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H #define LLVM_DEBUGINFO_DWARFFORMVALUE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Dwarf.h" @@ -60,6 +61,10 @@ void setUValue(uint64_t V) { Value.uval = V; } void setSValue(int64_t V) { Value.sval = V; } void setPValue(const char *V) { Value.cstr = V; } + void setBlockValue(const ArrayRef &Data) { + Value.data = Data.data(); + setUValue(Data.size()); + } bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS) const; @@ -164,6 +169,153 @@ void dumpString(raw_ostream &OS) const; }; +namespace dwarf { + /// Take an optional DWARFFormValue and try to extract a string value from it. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \returns an optional value that contains a value if the form value + /// was valid and was a string. + inline Optional toString(const Optional& V) { + if (V) + return V->getAsCString(); + return None; + } + + /// Take an optional DWARFFormValue and extract a string value from it. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \param Default the default value to return in case of failure. + /// \returns the string value or Default if the V doesn't have a value or the + /// form value's encoding wasn't a string. + inline const char* + toString(const Optional& V, const char *Default) { + return toString(V).getValueOr(Default); + } + + /// Take an optional DWARFFormValue and try to extract an unsigned constant. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \returns an optional value that contains a value if the form value + /// was valid and has a unsigned constant form. + inline Optional toUnsigned(const Optional& V) { + if (V) + return V->getAsUnsignedConstant(); + return None; + } + + /// Take an optional DWARFFormValue and extract a unsigned constant. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \param Default the default value to return in case of failure. + /// \returns the extracted unsigned value or Default if the V doesn't have a + /// value or the form value's encoding wasn't an unsigned constant form. + inline uint64_t + toUnsigned(const Optional& V, uint64_t Default) { + return toUnsigned(V).getValueOr(Default); + } + + /// Take an optional DWARFFormValue and try to extract an reference. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \returns an optional value that contains a value if the form value + /// was valid and has a reference form. + inline Optional toReference(const Optional& V) { + if (V) + return V->getAsReference(); + return None; + } + + /// Take an optional DWARFFormValue and extract a reference. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \param Default the default value to return in case of failure. + /// \returns the extracted reference value or Default if the V doesn't have a + /// value or the form value's encoding wasn't a reference form. + inline uint64_t + toReference(const Optional& V, uint64_t Default) { + return toReference(V).getValueOr(Default); + } + + /// Take an optional DWARFFormValue and try to extract an signed constant. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \returns an optional value that contains a value if the form value + /// was valid and has a signed constant form. + inline Optional toSigned(const Optional& V) { + if (V) + return V->getAsSignedConstant(); + return None; + } + + /// Take an optional DWARFFormValue and extract a signed integer. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \param Default the default value to return in case of failure. + /// \returns the extracted signed integer value or Default if the V doesn't + /// have a value or the form value's encoding wasn't a signed integer form. + inline int64_t + toSigned(const Optional& V, int64_t Default) { + return toSigned(V).getValueOr(Default); + } + + /// Take an optional DWARFFormValue and try to extract an address. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \returns an optional value that contains a value if the form value + /// was valid and has a address form. + inline Optional toAddress(const Optional& V) { + if (V) + return V->getAsAddress(); + return None; + } + + /// Take an optional DWARFFormValue and extract a address. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \param Default the default value to return in case of failure. + /// \returns the extracted address value or Default if the V doesn't have a + /// value or the form value's encoding wasn't an address form. + inline uint64_t + toAddress(const Optional& V, uint64_t Default) { + return toAddress(V).getValueOr(Default); + } + + /// Take an optional DWARFFormValue and try to extract an section offset. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \returns an optional value that contains a value if the form value + /// was valid and has a section offset form. + inline Optional toSectionOffset(const Optional& V) { + if (V) + return V->getAsSectionOffset(); + return None; + } + + /// Take an optional DWARFFormValue and extract a section offset. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \param Default the default value to return in case of failure. + /// \returns the extracted section offset value or Default if the V doesn't + /// have a value or the form value's encoding wasn't a section offset form. + inline uint64_t + toSectionOffset(const Optional& V, uint64_t Default) { + return toSectionOffset(V).getValueOr(Default); + } + + /// Take an optional DWARFFormValue and try to extract block data. + /// + /// \param V and optional DWARFFormValue to attempt to extract the value from. + /// \returns an optional value that contains a value if the form value + /// was valid and has a block form. + inline Optional> + toBlock(const Optional& V) { + if (V) + return V->getAsBlock(); + return None; + } + +} // end namespace dwarf + } #endif Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -128,8 +128,7 @@ auto CUDIE = CU->getUnitDIE(); if (!CUDIE) continue; - if (auto StmtOffset = - CUDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list)) { + if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) { DataExtractor lineData(getLineSection().Data, isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; @@ -387,7 +386,7 @@ if (!UnitDIE) return nullptr; - auto Offset = UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list); + auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list)); if (!Offset) return nullptr; // No line table for this compile unit. Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -134,7 +134,7 @@ } Optional -DWARFDie::getAttributeValue(dwarf::Attribute Attr) const { +DWARFDie::find(dwarf::Attribute Attr) const { if (!isValid()) return None; auto AbbrevDecl = getAbbreviationDeclarationPtr(); @@ -143,54 +143,24 @@ return None; } -const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr, - const char *FailValue) const { - auto FormValue = getAttributeValue(Attr); - if (!FormValue) - return FailValue; - Optional Result = FormValue->getAsCString(); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -Optional -DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsAddress(); +Optional +DWARFDie::findRecursively(dwarf::Attribute Attr) const { + if (!isValid()) + return None; + if (auto Value = find(Attr)) + return Value; + if (auto Die = getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) + if (auto Value = Die.find(Attr)) + return Value; + if (auto Die = getAttributeValueAsReferencedDie(DW_AT_specification)) + if (auto Value = Die.find(Attr)) + return Value; return None; } -Optional -DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsSignedConstant(); - return None; -} - -Optional -DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsUnsignedConstant(); - return None; -} - -Optional -DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsReference(); - return None; -} - -Optional -DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const { - if (auto FormValue = getAttributeValue(Attr)) - return FormValue->getAsSectionOffset(); - return None; -} - - DWARFDie DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { - auto SpecRef = getAttributeValueAsReference(Attr); + auto SpecRef = toReference(find(Attr)); if (SpecRef) { auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef); if (SpecUnit) @@ -201,14 +171,14 @@ Optional DWARFDie::getRangesBaseAttribute() const { - auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base); + auto Result = toSectionOffset(find(DW_AT_rnglists_base)); if (Result) return Result; - return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base); + return toSectionOffset(find(DW_AT_GNU_ranges_base)); } Optional DWARFDie::getHighPC(uint64_t LowPC) const { - if (auto FormValue = getAttributeValue(DW_AT_high_pc)) { + if (auto FormValue = find(DW_AT_high_pc)) { if (auto Address = FormValue->getAsAddress()) { // High PC is an address. return Address; @@ -222,7 +192,7 @@ } bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const { - auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc); + auto LowPcAddr = toAddress(find(DW_AT_low_pc)); if (!LowPcAddr) return false; if (auto HighPcAddr = getHighPC(*LowPcAddr)) { @@ -243,7 +213,7 @@ return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); } // Multiple ranges from .debug_ranges section. - auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges); + auto RangesOffset = toSectionOffset(find(DW_AT_ranges)); if (RangesOffset) { DWARFDebugRangeList RangeList; if (U->extractRangeList(*RangesOffset, RangeList)) @@ -284,33 +254,25 @@ DWARFDie::getName(DINameKind Kind) const { if (!isValid() || Kind == DINameKind::None) return nullptr; - const char *name = nullptr; // Try to get mangled name only if it was asked for. if (Kind == DINameKind::LinkageName) { - if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr))) - return name; - if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr))) - return name; + if (auto Name = dwarf::toString(findRecursively(DW_AT_MIPS_linkage_name), + nullptr)) + return Name; + if (auto Name = dwarf::toString(findRecursively(DW_AT_linkage_name), + nullptr)) + return Name; } - if ((name = getAttributeValueAsString(DW_AT_name, nullptr))) - return name; - // Try to get name from specification DIE. - DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification); - if (SpecDie && (name = SpecDie.getName(Kind))) - return name; - // Try to get name from abstract origin DIE. - DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin); - if (AbsDie && (name = AbsDie.getName(Kind))) - return name; + if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr)) + return Name; return nullptr; } void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, uint32_t &CallColumn) const { - CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file).getValueOr(0); - CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line).getValueOr(0); - CallColumn = - getAttributeValueAsUnsignedConstant(DW_AT_call_column).getValueOr(0); + CallFile = toUnsigned(find(DW_AT_call_file), 0); + CallLine = toUnsigned(find(DW_AT_call_line), 0); + CallColumn = toUnsigned(find(DW_AT_call_column), 0); } void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, Index: lib/DebugInfo/DWARF/DWARFTypeUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -26,7 +26,7 @@ void DWARFTypeUnit::dump(raw_ostream &OS, bool SummarizeTypes) { DWARFDie TD = getDIEForOffset(TypeOffset + getOffset()); - const char *Name = TD.getAttributeValueAsString(llvm::dwarf::DW_AT_name, ""); + const char *Name = TD.getName(DINameKind::ShortName); if (SummarizeTypes) { OS << "name = '" << Name << "'" Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" @@ -151,11 +152,11 @@ } const char *DWARFUnit::getCompilationDir() { - return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr); + return toString(getUnitDIE().find(DW_AT_comp_dir), nullptr); } Optional DWARFUnit::getDWOId() { - return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id); + return toUnsigned(getUnitDIE().find(DW_AT_GNU_dwo_id)); } void DWARFUnit::extractDIEsToVector( @@ -225,17 +226,13 @@ // If CU DIE was just parsed, copy several attribute values from it. if (!HasCUDie) { DWARFDie UnitDie = getUnitDIE(); - auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc); + auto BaseAddr = toAddress(UnitDie.find(DW_AT_low_pc)); if (!BaseAddr) - BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc); + BaseAddr = toAddress(UnitDie.find(DW_AT_entry_pc)); if (BaseAddr) setBaseAddress(*BaseAddr); - AddrOffsetSectionBase = - UnitDie.getAttributeValueAsSectionOffset(DW_AT_GNU_addr_base) - .getValueOr(0); - RangeSectionBase = - UnitDie.getAttributeValueAsSectionOffset(DW_AT_rnglists_base) - .getValueOr(0); + AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); + RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for // skeleton CU DIE, so that DWARF users not aware of it are not broken. } @@ -266,17 +263,16 @@ DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return false; - const char *DWOFileName = - UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); + auto DWOFileName = toString(UnitDie.find(DW_AT_GNU_dwo_name)); if (!DWOFileName) return false; - const char *CompilationDir = - UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr); + auto CompilationDir = toString(UnitDie.find(DW_AT_comp_dir)); SmallString<16> AbsolutePath; - if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { - sys::path::append(AbsolutePath, CompilationDir); + if (sys::path::is_relative(*DWOFileName) && CompilationDir && + *CompilationDir) { + sys::path::append(AbsolutePath, *CompilationDir); } - sys::path::append(AbsolutePath, DWOFileName); + sys::path::append(AbsolutePath, *DWOFileName); DWO = llvm::make_unique(AbsolutePath); DWARFUnit *DWOCU = DWO->getUnit(); // Verify that compile unit in .dwo file is valid. Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -205,14 +205,12 @@ Info.resize(OrigUnit.getNumDIEs()); auto CUDie = OrigUnit.getUnitDIE(false); - unsigned Lang = - CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_language) - .getValueOr(0); - HasODR = CanUseODR && (Lang == dwarf::DW_LANG_C_plus_plus || - Lang == dwarf::DW_LANG_C_plus_plus_03 || - Lang == dwarf::DW_LANG_C_plus_plus_11 || - Lang == dwarf::DW_LANG_C_plus_plus_14 || - Lang == dwarf::DW_LANG_ObjC_plus_plus); + if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language))) + HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus || + *Lang == dwarf::DW_LANG_C_plus_plus_03 || + *Lang == dwarf::DW_LANG_C_plus_plus_11 || + *Lang == dwarf::DW_LANG_C_plus_plus_14 || + *Lang == dwarf::DW_LANG_ObjC_plus_plus); } DWARFUnit &getOrigUnit() const { return OrigUnit; } @@ -843,8 +841,7 @@ DWARFUnit &OrigUnit = Unit.getOrigUnit(); auto OrigUnitDie = OrigUnit.getUnitDIE(false); int64_t UnitPcOffset = 0; - auto OrigLowPc = OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc); - if (OrigLowPc) + if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc(); for (const auto &Attr : Attributes) { @@ -1558,8 +1555,7 @@ // Do not unique anything inside CU local functions. if ((Context.getTag() == dwarf::DW_TAG_namespace || Context.getTag() == dwarf::DW_TAG_compile_unit) && - !DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_external) - .getValueOr(0)) + !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0)) return PointerIntPair(nullptr); LLVM_FALLTHROUGH; case dwarf::DW_TAG_member: @@ -1573,8 +1569,7 @@ // created on demand. For example implicitely defined constructors // are ambiguous because of the way we identify contexts, and they // won't be generated everytime everywhere. - if (DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_artificial) - .getValueOr(0)) + if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0)) return PointerIntPair(nullptr); break; } @@ -1614,12 +1609,9 @@ // namespaces, use these additional data points to make the process // safer. This is disabled for clang modules, because forward // declarations of module-defined types do not have a file and line. - ByteSize = DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_byte_size) - .getValueOr(UINT64_MAX); + ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size), UINT64_MAX); if (Tag != dwarf::DW_TAG_namespace || !Name) { - if (unsigned FileNum = - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_file) - .getValueOr(0)) { + if (unsigned FileNum = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) { if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit( &U.getOrigUnit())) { // FIXME: dsymutil-classic compatibility. I'd rather not @@ -1632,9 +1624,7 @@ // instead of "" would allow more uniquing, but for now, do // it this way to match dsymutil-classic. if (LT->hasFileAtIndex(FileNum)) { - Line = - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_line) - .getValueOr(0); + Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0); // Cache the resolved paths, because calling realpath is expansive. StringRef ResolvedPath = U.getResolvedPath(FileNum); if (!ResolvedPath.empty()) { @@ -1782,8 +1772,7 @@ // // We treat non-C++ modules like namespaces for this reason. if (DIE.getTag() == dwarf::DW_TAG_module && ParentIdx == 0 && - DIE.getAttributeValueAsString(dwarf::DW_AT_name, - "") != CU.getClangModuleName()) { + dwarf::toString(DIE.find(dwarf::DW_AT_name), "") != CU.getClangModuleName()) { InImportedModule = true; } @@ -1811,8 +1800,7 @@ // forward declarations. Info.Prune &= (DIE.getTag() == dwarf::DW_TAG_module) || - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_declaration) - .getValueOr(0); + dwarf::toUnsigned(DIE.find(dwarf::DW_AT_declaration), 0); // Don't prune it if there is no definition for the DIE. Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset(); @@ -2129,7 +2117,7 @@ std::tie(LowPcOffset, LowPcEndOffset) = getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit); - auto LowPc = DIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc); + auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc)); assert(LowPc.hasValue() && "low_pc attribute is not an address."); if (!LowPc || !RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo)) @@ -2746,14 +2734,11 @@ // file might be start address of another function which got moved // independantly by the linker). The computation of the actual // high_pc value is done in cloneAddressAttribute(). - AttrInfo.OrigHighPc = - InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_high_pc).getValueOr(0); + AttrInfo.OrigHighPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_high_pc), 0); // Also store the low_pc. It might get relocated in an // inline_subprogram that happens at the beginning of its // inlining function. - AttrInfo.OrigLowPc = - InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc) - .getValueOr(UINT64_MAX); + AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), UINT64_MAX); } // Reset the Offset to 0 as we will be working on the local copy of @@ -2872,9 +2857,7 @@ auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; DWARFUnit &OrigUnit = Unit.getOrigUnit(); auto OrigUnitDie = OrigUnit.getUnitDIE(false); - uint64_t OrigLowPc = - OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc) - .getValueOr(-1ULL); + uint64_t OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), -1ULL); // Ranges addresses are based on the unit's low_pc. Compute the // offset we need to apply to adapt to the new unit's low_pc. int64_t UnitPcOffset = 0; @@ -2969,7 +2952,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf) { DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); - auto StmtList = CUDie.getAttributeValueAsSectionOffset(dwarf::DW_AT_stmt_list); + auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list)); if (!StmtList) return; @@ -3201,10 +3184,10 @@ static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) { - auto DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_dwo_id); + auto DwoId = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_dwo_id)); if (DwoId) return *DwoId; - DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_GNU_dwo_id); + DwoId = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_GNU_dwo_id)); if (DwoId) return *DwoId; return 0; @@ -3213,21 +3196,17 @@ bool DwarfLinker::registerModuleReference( const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, unsigned Indent) { - std::string PCMfile = - CUDie.getAttributeValueAsString(dwarf::DW_AT_dwo_name, ""); + std::string PCMfile = dwarf::toString(CUDie.find(dwarf::DW_AT_dwo_name), ""); if (PCMfile.empty()) - PCMfile = - CUDie.getAttributeValueAsString(dwarf::DW_AT_GNU_dwo_name, ""); + PCMfile = dwarf::toString(CUDie.find(dwarf::DW_AT_GNU_dwo_name), ""); if (PCMfile.empty()) return false; // Clang module DWARF skeleton CUs abuse this for the path to the module. - std::string PCMpath = - CUDie.getAttributeValueAsString(dwarf::DW_AT_comp_dir, ""); + std::string PCMpath = dwarf::toString(CUDie.find(dwarf::DW_AT_comp_dir), ""); uint64_t DwoId = getDwoId(CUDie, Unit); - std::string Name = - CUDie.getAttributeValueAsString(dwarf::DW_AT_name, ""); + std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); if (Name.empty()) { reportWarning("Anonymous module skeleton CU for " + PCMfile); return true; Index: tools/obj2yaml/dwarf2yaml.cpp =================================================================== --- tools/obj2yaml/dwarf2yaml.cpp +++ tools/obj2yaml/dwarf2yaml.cpp @@ -126,7 +126,7 @@ DWARFYAML::FormValue NewValue; NewValue.Value = 0xDEADBEEFDEADBEEF; DWARFDie DIEWrapper(CU.get(), &DIE); - auto FormValue = DIEWrapper.getAttributeValue(AttrSpec.Attr); + auto FormValue = DIEWrapper.find(AttrSpec.Attr); if (!FormValue) return; auto Form = FormValue.getValue().getForm(); @@ -228,7 +228,7 @@ if (!CUDIE) continue; if (auto StmtOffset = - CUDIE.getAttributeValueAsSectionOffset(dwarf::DW_AT_stmt_list)) { + dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) { DWARFYAML::LineTable DebugLines; DataExtractor LineData(DCtx.getLineSection().Data, DCtx.isLittleEndian(), CU->getAddressByteSize()); Index: unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp =================================================================== --- unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -228,8 +228,7 @@ //---------------------------------------------------------------------- // Test address forms //---------------------------------------------------------------------- - EXPECT_EQ(DieDG.getAttributeValueAsAddress(Attr_DW_FORM_addr).getValueOr(0), - AddrValue); + EXPECT_EQ(AddrValue, toAddress(DieDG.find(Attr_DW_FORM_addr), 0)); //---------------------------------------------------------------------- // Test block forms @@ -238,7 +237,7 @@ ArrayRef ExtractedBlockData; Optional> BlockDataOpt; - FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block); + FormValue = DieDG.find(Attr_DW_FORM_block); EXPECT_TRUE((bool)FormValue); BlockDataOpt = FormValue->getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); @@ -246,7 +245,7 @@ EXPECT_EQ(ExtractedBlockData.size(), BlockSize); EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0); - FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block1); + FormValue = DieDG.find(Attr_DW_FORM_block1); EXPECT_TRUE((bool)FormValue); BlockDataOpt = FormValue->getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); @@ -254,7 +253,7 @@ EXPECT_EQ(ExtractedBlockData.size(), BlockSize); EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0); - FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block2); + FormValue = DieDG.find(Attr_DW_FORM_block2); EXPECT_TRUE((bool)FormValue); BlockDataOpt = FormValue->getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); @@ -262,7 +261,7 @@ EXPECT_EQ(ExtractedBlockData.size(), BlockSize); EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0); - FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block4); + FormValue = DieDG.find(Attr_DW_FORM_block4); EXPECT_TRUE((bool)FormValue); BlockDataOpt = FormValue->getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); @@ -273,100 +272,64 @@ //---------------------------------------------------------------------- // Test data forms //---------------------------------------------------------------------- - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data1) - .getValueOr(0), - Data1); - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data2) - .getValueOr(0), - Data2); - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data4) - .getValueOr(0), - Data4); - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data8) - .getValueOr(0), - Data8); + EXPECT_EQ(Data1, toUnsigned(DieDG.find(Attr_DW_FORM_data1), 0)); + EXPECT_EQ(Data2, toUnsigned(DieDG.find(Attr_DW_FORM_data2), 0)); + EXPECT_EQ(Data4, toUnsigned(DieDG.find(Attr_DW_FORM_data4), 0)); + EXPECT_EQ(Data8, toUnsigned(DieDG.find(Attr_DW_FORM_data8), 0)); //---------------------------------------------------------------------- // Test string forms //---------------------------------------------------------------------- - const char *ExtractedStringValue = - DieDG.getAttributeValueAsString(Attr_DW_FORM_string, nullptr); - EXPECT_TRUE(ExtractedStringValue != nullptr); - EXPECT_TRUE(strcmp(StringValue, ExtractedStringValue) == 0); + auto ExtractedStringValue = toString(DieDG.find(Attr_DW_FORM_string)); + EXPECT_TRUE((bool)ExtractedStringValue); + EXPECT_TRUE(strcmp(StringValue, *ExtractedStringValue) == 0); - const char *ExtractedStrpValue = - DieDG.getAttributeValueAsString(Attr_DW_FORM_strp, nullptr); - EXPECT_TRUE(ExtractedStrpValue != nullptr); - EXPECT_TRUE(strcmp(StrpValue, ExtractedStrpValue) == 0); + auto ExtractedStrpValue = toString(DieDG.find(Attr_DW_FORM_strp)); + EXPECT_TRUE((bool)ExtractedStrpValue); + EXPECT_TRUE(strcmp(StrpValue, *ExtractedStrpValue) == 0); //---------------------------------------------------------------------- // Test reference forms //---------------------------------------------------------------------- - EXPECT_EQ( - DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_addr).getValueOr(0), - RefAddr); - EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref1).getValueOr(0), - Data1); - EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref2).getValueOr(0), - Data2); - EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref4).getValueOr(0), - Data4); - EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref8).getValueOr(0), - Data8); - EXPECT_EQ( - DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_sig8).getValueOr(0), - Data8_2); - EXPECT_EQ( - DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_udata).getValueOr(0), - UData[0]); + EXPECT_EQ(RefAddr, toReference(DieDG.find(Attr_DW_FORM_ref_addr), 0)); + EXPECT_EQ(Data1, toReference(DieDG.find(Attr_DW_FORM_ref1), 0)); + EXPECT_EQ(Data2, toReference(DieDG.find(Attr_DW_FORM_ref2), 0)); + EXPECT_EQ(Data4, toReference(DieDG.find(Attr_DW_FORM_ref4), 0)); + EXPECT_EQ(Data8, toReference(DieDG.find(Attr_DW_FORM_ref8), 0)); + EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0)); + EXPECT_EQ(UData[0], toReference(DieDG.find(Attr_DW_FORM_ref_udata), 0)); //---------------------------------------------------------------------- // Test flag forms //---------------------------------------------------------------------- - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_flag_true) - .getValueOr(0), - 1ULL); - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_flag_false) - .getValueOr(1), - 0ULL); - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_flag_present) - .getValueOr(0ULL), - 1ULL); + EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_true), 0)); + EXPECT_EQ(0ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_false), 1)); + EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_present), 0)); //---------------------------------------------------------------------- // Test SLEB128 based forms //---------------------------------------------------------------------- - EXPECT_EQ( - DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_sdata).getValueOr(0), - SData); + EXPECT_EQ(SData, toSigned(DieDG.find(Attr_DW_FORM_sdata), 0)); if (Version >= 5) - EXPECT_EQ( - DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_implicit_const) - .getValueOr(0), - ICSData); + EXPECT_EQ(ICSData, toSigned(DieDG.find(Attr_DW_FORM_implicit_const), 0)); //---------------------------------------------------------------------- // Test ULEB128 based forms //---------------------------------------------------------------------- - EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_udata) - .getValueOr(0), - UData[0]); + EXPECT_EQ(UData[0], toUnsigned(DieDG.find(Attr_DW_FORM_udata), 0)); //---------------------------------------------------------------------- // Test DWARF32/DWARF64 forms //---------------------------------------------------------------------- - EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_GNU_ref_alt) - .getValueOr(0), - Dwarf32Values[0]); - EXPECT_EQ(DieDG.getAttributeValueAsSectionOffset(Attr_DW_FORM_sec_offset) - .getValueOr(0), - Dwarf32Values[1]); + EXPECT_EQ(Dwarf32Values[0], + toReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0)); + EXPECT_EQ(Dwarf32Values[1], + toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0)); //---------------------------------------------------------------------- // Add an address at the end to make sure we can decode this value //---------------------------------------------------------------------- - EXPECT_EQ(DieDG.getAttributeValueAsAddress(Attr_Last).getValueOr(0), - AddrValue); + EXPECT_EQ(AddrValue, toAddress(DieDG.find(Attr_Last), 0)); } TEST(DWARFDebugInfo, TestDWARF32Version2Addr4AllForms) { @@ -672,123 +635,107 @@ auto CU1TypeDieDG = Unit1DieDG.getFirstChild(); EXPECT_TRUE(CU1TypeDieDG.isValid()); EXPECT_EQ(CU1TypeDieDG.getTag(), DW_TAG_base_type); - EXPECT_EQ(CU1TypeDieDG.getAttributeValueAsUnsignedConstant(DW_AT_encoding) - .getValueOr(0), - DW_ATE_signed); + EXPECT_EQ(DW_ATE_signed, toUnsigned(CU1TypeDieDG.find(DW_AT_encoding), 0)); // Verify the first child of the compile unit 2 DIE is our float base type. auto CU2TypeDieDG = Unit2DieDG.getFirstChild(); EXPECT_TRUE(CU2TypeDieDG.isValid()); EXPECT_EQ(CU2TypeDieDG.getTag(), DW_TAG_base_type); - EXPECT_EQ(CU2TypeDieDG.getAttributeValueAsUnsignedConstant(DW_AT_encoding) - .getValueOr(0), - DW_ATE_float); + EXPECT_EQ(DW_ATE_float, toUnsigned(CU2TypeDieDG.find(DW_AT_encoding), 0)); // Verify the sibling of the base type DIE is our Ref1 DIE and that its // DW_AT_type points to our base type DIE. auto CU1Ref1DieDG = CU1TypeDieDG.getSibling(); EXPECT_TRUE(CU1Ref1DieDG.isValid()); EXPECT_EQ(CU1Ref1DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU1Ref1DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU1TypeDieDG.getOffset()); + EXPECT_EQ(CU1TypeDieDG.getOffset(), + toReference(CU1Ref1DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our Ref2 DIE and that its DW_AT_type points to our // base type DIE in CU1. auto CU1Ref2DieDG = CU1Ref1DieDG.getSibling(); EXPECT_TRUE(CU1Ref2DieDG.isValid()); EXPECT_EQ(CU1Ref2DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU1Ref2DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU1TypeDieDG.getOffset()); + EXPECT_EQ(CU1TypeDieDG.getOffset(), + toReference(CU1Ref2DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our Ref4 DIE and that its DW_AT_type points to our // base type DIE in CU1. auto CU1Ref4DieDG = CU1Ref2DieDG.getSibling(); EXPECT_TRUE(CU1Ref4DieDG.isValid()); EXPECT_EQ(CU1Ref4DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU1Ref4DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU1TypeDieDG.getOffset()); + EXPECT_EQ(CU1TypeDieDG.getOffset(), + toReference(CU1Ref4DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our Ref8 DIE and that its DW_AT_type points to our // base type DIE in CU1. auto CU1Ref8DieDG = CU1Ref4DieDG.getSibling(); EXPECT_TRUE(CU1Ref8DieDG.isValid()); EXPECT_EQ(CU1Ref8DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU1Ref8DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU1TypeDieDG.getOffset()); + EXPECT_EQ(CU1TypeDieDG.getOffset(), + toReference(CU1Ref8DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our RefAddr DIE and that its DW_AT_type points to our // base type DIE in CU1. auto CU1RefAddrDieDG = CU1Ref8DieDG.getSibling(); EXPECT_TRUE(CU1RefAddrDieDG.isValid()); EXPECT_EQ(CU1RefAddrDieDG.getTag(), DW_TAG_variable); - EXPECT_EQ(CU1RefAddrDieDG.getAttributeValueAsReference(DW_AT_type) - .getValueOr(-1ULL), - CU1TypeDieDG.getOffset()); + EXPECT_EQ(CU1TypeDieDG.getOffset(), + toReference(CU1RefAddrDieDG.find(DW_AT_type), -1ULL)); // Verify the sibling of the Ref4 DIE is our RefAddr DIE and that its // DW_AT_type points to our base type DIE. auto CU1ToCU2RefAddrDieDG = CU1RefAddrDieDG.getSibling(); EXPECT_TRUE(CU1ToCU2RefAddrDieDG.isValid()); EXPECT_EQ(CU1ToCU2RefAddrDieDG.getTag(), DW_TAG_variable); - EXPECT_EQ(CU1ToCU2RefAddrDieDG.getAttributeValueAsReference(DW_AT_type) - .getValueOr(-1ULL), - CU2TypeDieDG.getOffset()); + EXPECT_EQ(CU2TypeDieDG.getOffset(), + toReference(CU1ToCU2RefAddrDieDG.find(DW_AT_type), -1ULL)); // Verify the sibling of the base type DIE is our Ref1 DIE and that its // DW_AT_type points to our base type DIE. auto CU2Ref1DieDG = CU2TypeDieDG.getSibling(); EXPECT_TRUE(CU2Ref1DieDG.isValid()); EXPECT_EQ(CU2Ref1DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU2Ref1DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU2TypeDieDG.getOffset()); + EXPECT_EQ(CU2TypeDieDG.getOffset(), + toReference(CU2Ref1DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our Ref2 DIE and that its DW_AT_type points to our // base type DIE in CU2. auto CU2Ref2DieDG = CU2Ref1DieDG.getSibling(); EXPECT_TRUE(CU2Ref2DieDG.isValid()); EXPECT_EQ(CU2Ref2DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU2Ref2DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU2TypeDieDG.getOffset()); + EXPECT_EQ(CU2TypeDieDG.getOffset(), + toReference(CU2Ref2DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our Ref4 DIE and that its DW_AT_type points to our // base type DIE in CU2. auto CU2Ref4DieDG = CU2Ref2DieDG.getSibling(); EXPECT_TRUE(CU2Ref4DieDG.isValid()); EXPECT_EQ(CU2Ref4DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU2Ref4DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU2TypeDieDG.getOffset()); + EXPECT_EQ(CU2TypeDieDG.getOffset(), + toReference(CU2Ref4DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our Ref8 DIE and that its DW_AT_type points to our // base type DIE in CU2. auto CU2Ref8DieDG = CU2Ref4DieDG.getSibling(); EXPECT_TRUE(CU2Ref8DieDG.isValid()); EXPECT_EQ(CU2Ref8DieDG.getTag(), DW_TAG_variable); - EXPECT_EQ( - CU2Ref8DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL), - CU2TypeDieDG.getOffset()); + EXPECT_EQ(CU2TypeDieDG.getOffset(), + toReference(CU2Ref8DieDG.find(DW_AT_type), -1ULL)); // Verify the sibling is our RefAddr DIE and that its DW_AT_type points to our // base type DIE in CU2. auto CU2RefAddrDieDG = CU2Ref8DieDG.getSibling(); EXPECT_TRUE(CU2RefAddrDieDG.isValid()); EXPECT_EQ(CU2RefAddrDieDG.getTag(), DW_TAG_variable); - EXPECT_EQ(CU2RefAddrDieDG.getAttributeValueAsReference(DW_AT_type) - .getValueOr(-1ULL), - CU2TypeDieDG.getOffset()); + EXPECT_EQ(CU2TypeDieDG.getOffset(), + toReference(CU2RefAddrDieDG.find(DW_AT_type), -1ULL)); // Verify the sibling of the Ref4 DIE is our RefAddr DIE and that its // DW_AT_type points to our base type DIE. auto CU2ToCU1RefAddrDieDG = CU2RefAddrDieDG.getSibling(); EXPECT_TRUE(CU2ToCU1RefAddrDieDG.isValid()); EXPECT_EQ(CU2ToCU1RefAddrDieDG.getTag(), DW_TAG_variable); - EXPECT_EQ(CU2ToCU1RefAddrDieDG.getAttributeValueAsReference(DW_AT_type) - .getValueOr(-1ULL), - CU1TypeDieDG.getOffset()); + EXPECT_EQ(CU1TypeDieDG.getOffset(), + toReference(CU2ToCU1RefAddrDieDG.find(DW_AT_type), -1ULL)); } TEST(DWARFDebugInfo, TestDWARF32Version2Addr4References) { @@ -896,14 +843,14 @@ auto SubprogramDieNoPC = DieDG.getFirstChild(); EXPECT_TRUE(SubprogramDieNoPC.isValid()); EXPECT_EQ(SubprogramDieNoPC.getTag(), DW_TAG_subprogram); - OptU64 = SubprogramDieNoPC.getAttributeValueAsAddress(DW_AT_low_pc); + OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_low_pc)); EXPECT_FALSE((bool)OptU64); - OptU64 = SubprogramDieNoPC.getAttributeValueAsAddress(DW_AT_high_pc); + OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC)); - OptU64 = SubprogramDieNoPC.getAttributeValueAsAddress(DW_AT_high_pc); + OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); - OptU64 = SubprogramDieNoPC.getAttributeValueAsUnsignedConstant(DW_AT_high_pc); + OptU64 = toUnsigned(SubprogramDieNoPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); OptU64 = SubprogramDieNoPC.getHighPC(ActualLowPC); EXPECT_FALSE((bool)OptU64); @@ -916,12 +863,12 @@ auto SubprogramDieLowPC = SubprogramDieNoPC.getSibling(); EXPECT_TRUE(SubprogramDieLowPC.isValid()); EXPECT_EQ(SubprogramDieLowPC.getTag(), DW_TAG_subprogram); - OptU64 = SubprogramDieLowPC.getAttributeValueAsAddress(DW_AT_low_pc); + OptU64 = toAddress(SubprogramDieLowPC.find(DW_AT_low_pc)); EXPECT_TRUE((bool)OptU64); EXPECT_EQ(OptU64.getValue(), ActualLowPC); - OptU64 = SubprogramDieLowPC.getAttributeValueAsAddress(DW_AT_high_pc); + OptU64 = toAddress(SubprogramDieLowPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); - OptU64 = SubprogramDieLowPC.getAttributeValueAsUnsignedConstant(DW_AT_high_pc); + OptU64 = toUnsigned(SubprogramDieLowPC.find(DW_AT_high_pc)); EXPECT_FALSE((bool)OptU64); OptU64 = SubprogramDieLowPC.getHighPC(ActualLowPC); EXPECT_FALSE((bool)OptU64); @@ -934,12 +881,12 @@ auto SubprogramDieLowHighPC = SubprogramDieLowPC.getSibling(); EXPECT_TRUE(SubprogramDieLowHighPC.isValid()); EXPECT_EQ(SubprogramDieLowHighPC.getTag(), DW_TAG_subprogram); - OptU64 = SubprogramDieLowHighPC.getAttributeValueAsAddress(DW_AT_low_pc); + OptU64 = toAddress(SubprogramDieLowHighPC.find(DW_AT_low_pc)); EXPECT_TRUE((bool)OptU64); EXPECT_EQ(OptU64.getValue(), ActualLowPC); // Get the high PC as an address. This should succeed if the high PC was // encoded as an address and fail if the high PC was encoded as an offset. - OptU64 = SubprogramDieLowHighPC.getAttributeValueAsAddress(DW_AT_high_pc); + OptU64 = toAddress(SubprogramDieLowHighPC.find(DW_AT_high_pc)); if (SupportsHighPCAsOffset) { EXPECT_FALSE((bool)OptU64); } else { @@ -948,8 +895,7 @@ } // Get the high PC as an unsigned constant. This should succeed if the high PC // was encoded as an offset and fail if the high PC was encoded as an address. - OptU64 = SubprogramDieLowHighPC.getAttributeValueAsUnsignedConstant( - DW_AT_high_pc); + OptU64 = toUnsigned(SubprogramDieLowHighPC.find(DW_AT_high_pc)); if (SupportsHighPCAsOffset) { EXPECT_TRUE((bool)OptU64); EXPECT_EQ(OptU64.getValue(), ActualHighPCOffset); @@ -1255,7 +1201,6 @@ // Get the compile unit DIE is valid. auto CUDie = U->getUnitDIE(false); EXPECT_TRUE(CUDie.isValid()); - CUDie.dump(llvm::outs(), UINT32_MAX); // Verify that the CU Die that says it has children, but doesn't, actually // has begin and end iterators that are equal. We want to make sure we don't @@ -1263,4 +1208,215 @@ EXPECT_EQ(CUDie.begin(), CUDie.end()); } +TEST(DWARFDebugInfo, TestFindRecurse) { + uint16_t Version = 4; + + const uint8_t AddrSize = sizeof(void *); + initLLVMIfNeeded(); + Triple Triple = getHostTripleForAddrSize(AddrSize); + auto ExpectedDG = dwarfgen::Generator::create(Triple, Version); + if (HandleExpectedError(ExpectedDG)) + return; + dwarfgen::Generator *DG = ExpectedDG.get().get(); + dwarfgen::CompileUnit &CU = DG->addCompileUnit(); + + StringRef SpecDieName("spec"); + StringRef AbsDieName("abs"); + // Scope to allow us to re-use the same DIE names + { + // Create a compile unit DIE that has an abbreviation that says it has + // children, but doesn't have any actual attributes. This helps us test + // a DIE that has only one child: a NULL DIE. + auto CUDie = CU.getUnitDIE(); + auto FuncSpecDie = CUDie.addChild(DW_TAG_subprogram); + auto FuncDie = CUDie.addChild(DW_TAG_subprogram); + auto VarAbsDie = CUDie.addChild(DW_TAG_variable); + auto VarDie = CUDie.addChild(DW_TAG_variable); + FuncSpecDie.addAttribute(DW_AT_name, DW_FORM_strp, SpecDieName); + FuncDie.addAttribute(DW_AT_specification, DW_FORM_ref4, FuncSpecDie); + VarAbsDie.addAttribute(DW_AT_name, DW_FORM_strp, AbsDieName); + VarDie.addAttribute(DW_AT_abstract_origin, DW_FORM_ref4, VarAbsDie); + } + + MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); + auto Obj = object::ObjectFile::createObjectFile(FileBuffer); + EXPECT_TRUE((bool)Obj); + DWARFContextInMemory DwarfContext(*Obj.get()); + + // Verify the number of compile units is correct. + uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + EXPECT_EQ(NumCUs, 1u); + DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + + // Get the compile unit DIE is valid. + auto CUDie = U->getUnitDIE(false); + EXPECT_TRUE(CUDie.isValid()); + + auto FuncSpecDie = CUDie.getFirstChild(); + auto FuncDie = FuncSpecDie.getSibling(); + auto VarAbsDie = FuncDie.getSibling(); + auto VarDie = VarAbsDie.getSibling(); + + // Make sure we can't extract the name from the specification die when using + // DWARFDie::find() since it won't check the DW_AT_specification DIE. + EXPECT_FALSE(FuncDie.find(DW_AT_name).hasValue()); + + // Make sure we can extract the name from the specification die when using + // DWARFDie::findRecursively() since it should recurse through the + // DW_AT_specification DIE. + auto NameOpt = FuncDie.findRecursively(DW_AT_name); + EXPECT_TRUE(NameOpt.hasValue()); + // Test the dwarf::toString() helper function. + auto StringOpt = toString(NameOpt); + EXPECT_TRUE(StringOpt.hasValue()); + EXPECT_EQ(SpecDieName, StringOpt.getValueOr(nullptr)); + // Test the dwarf::toString() helper function with a default value specified. + EXPECT_EQ(SpecDieName, toString(NameOpt, nullptr)); + + // Make sure we can't extract the name from the abstract origin die when using + // DWARFDie::find() since it won't check the DW_AT_abstract_origin DIE. + EXPECT_FALSE(VarDie.find(DW_AT_name).hasValue()); + + // Make sure we can extract the name from the abstract origin die when using + // DWARFDie::findRecursively() since it should recurse through the + // DW_AT_abstract_origin DIE. + NameOpt = VarDie.findRecursively(DW_AT_name); + EXPECT_TRUE(NameOpt.hasValue()); + // Test the dwarf::toString() helper function. + StringOpt = toString(NameOpt); + EXPECT_TRUE(StringOpt.hasValue()); + EXPECT_EQ(AbsDieName, StringOpt.getValueOr(nullptr)); + // Test the dwarf::toString() helper function with a default value specified. + EXPECT_EQ(AbsDieName, toString(NameOpt, nullptr)); +} +TEST(DWARFDebugInfo, TestDwarfToFunctions) { + // Test all of the dwarf::toXXX functions that take a + // Optional and extract the values from it. + DWARFFormValue FormVal; + uint64_t InvalidU64 = 0xBADBADBADBADBADB; + int64_t InvalidS64 = 0xBADBADBADBADBADB; + // First test that we don't get valid values back when using an optional with + // no value. + Optional FormValOpt; + EXPECT_FALSE(toString(FormValOpt).hasValue()); + EXPECT_FALSE(toUnsigned(FormValOpt).hasValue()); + EXPECT_FALSE(toReference(FormValOpt).hasValue()); + EXPECT_FALSE(toSigned(FormValOpt).hasValue()); + EXPECT_FALSE(toAddress(FormValOpt).hasValue()); + EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue()); + EXPECT_FALSE(toBlock(FormValOpt).hasValue()); + EXPECT_EQ(nullptr, toString(FormValOpt, nullptr)); + EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidS64)); + + + // Test successful and unsuccessful address decoding. + uint64_t Address = 0x100000000ULL; + FormVal.setForm(DW_FORM_addr); + FormVal.setUValue(Address); + FormValOpt = FormVal; + + EXPECT_FALSE(toString(FormValOpt).hasValue()); + EXPECT_FALSE(toUnsigned(FormValOpt).hasValue()); + EXPECT_FALSE(toReference(FormValOpt).hasValue()); + EXPECT_FALSE(toSigned(FormValOpt).hasValue()); + EXPECT_TRUE(toAddress(FormValOpt).hasValue()); + EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue()); + EXPECT_FALSE(toBlock(FormValOpt).hasValue()); + EXPECT_EQ(nullptr, toString(FormValOpt, nullptr)); + EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64)); + EXPECT_EQ(Address, toAddress(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidU64)); + + // Test successful and unsuccessful unsigned constant decoding. + uint64_t UData8 = 0x1020304050607080ULL; + FormVal.setForm(DW_FORM_udata); + FormVal.setUValue(UData8); + FormValOpt = FormVal; + + EXPECT_FALSE(toString(FormValOpt).hasValue()); + EXPECT_TRUE(toUnsigned(FormValOpt).hasValue()); + EXPECT_FALSE(toReference(FormValOpt).hasValue()); + EXPECT_TRUE(toSigned(FormValOpt).hasValue()); + EXPECT_FALSE(toAddress(FormValOpt).hasValue()); + EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue()); + EXPECT_FALSE(toBlock(FormValOpt).hasValue()); + EXPECT_EQ(nullptr, toString(FormValOpt, nullptr)); + EXPECT_EQ(UData8, toUnsigned(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64)); + EXPECT_EQ((int64_t)UData8, toSigned(FormValOpt, InvalidU64)); + + // Test successful and unsuccessful reference decoding. + uint32_t RefData = 0x11223344U; + FormVal.setForm(DW_FORM_ref_addr); + FormVal.setUValue(RefData); + FormValOpt = FormVal; + + EXPECT_FALSE(toString(FormValOpt).hasValue()); + EXPECT_FALSE(toUnsigned(FormValOpt).hasValue()); + EXPECT_TRUE(toReference(FormValOpt).hasValue()); + EXPECT_FALSE(toSigned(FormValOpt).hasValue()); + EXPECT_FALSE(toAddress(FormValOpt).hasValue()); + EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue()); + EXPECT_FALSE(toBlock(FormValOpt).hasValue()); + EXPECT_EQ(nullptr, toString(FormValOpt, nullptr)); + EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64)); + EXPECT_EQ(RefData, toReference(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidU64)); + + // Test successful and unsuccessful signed constant decoding. + int64_t SData8 = 0x1020304050607080ULL; + FormVal.setForm(DW_FORM_udata); + FormVal.setSValue(SData8); + FormValOpt = FormVal; + + EXPECT_FALSE(toString(FormValOpt).hasValue()); + EXPECT_TRUE(toUnsigned(FormValOpt).hasValue()); + EXPECT_FALSE(toReference(FormValOpt).hasValue()); + EXPECT_TRUE(toSigned(FormValOpt).hasValue()); + EXPECT_FALSE(toAddress(FormValOpt).hasValue()); + EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue()); + EXPECT_FALSE(toBlock(FormValOpt).hasValue()); + EXPECT_EQ(nullptr, toString(FormValOpt, nullptr)); + EXPECT_EQ((uint64_t)SData8, toUnsigned(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64)); + EXPECT_EQ(SData8, toSigned(FormValOpt, InvalidU64)); + + // Test successful and unsuccessful block decoding. + uint8_t Data[] = { 2, 3, 4 }; + ArrayRef Array(Data); + FormVal.setForm(DW_FORM_block1); + FormVal.setBlockValue(Array); + FormValOpt = FormVal; + + EXPECT_FALSE(toString(FormValOpt).hasValue()); + EXPECT_FALSE(toUnsigned(FormValOpt).hasValue()); + EXPECT_FALSE(toReference(FormValOpt).hasValue()); + EXPECT_FALSE(toSigned(FormValOpt).hasValue()); + EXPECT_FALSE(toAddress(FormValOpt).hasValue()); + EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue()); + auto BlockOpt = toBlock(FormValOpt); + EXPECT_TRUE(BlockOpt.hasValue()); + EXPECT_EQ(*BlockOpt, Array); + EXPECT_EQ(nullptr, toString(FormValOpt, nullptr)); + EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64)); + EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidU64)); + + // Test +} + } // end anonymous namespace