diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index dbb658940eef12..563887d1149a8c 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -107,12 +107,10 @@ class DWARFFormValue { /// getAsFoo functions below return the extracted value as Foo if only /// DWARFFormValue has form class is suitable for representing Foo. - std::optional getAsReference() const; - struct UnitOffset { - DWARFUnit *Unit; - uint64_t Offset; - }; - std::optional getAsRelativeReference() const; + std::optional getAsRelativeReference() const; + std::optional getAsDebugInfoReference() const; + std::optional getAsSignatureReference() const; + std::optional getAsSupplementaryReference() const; std::optional getAsUnsignedConstant() const; std::optional getAsSignedConstant() const; Expected getAsCString() const; @@ -242,27 +240,102 @@ inline uint64_t toUnsigned(const std::optional &V, return toUnsigned(V).value_or(Default); } -/// Take an optional DWARFFormValue and try to extract an reference. +/// Take an optional DWARFFormValue and try to extract a relative offset +/// reference. /// -/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param V an 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. +/// was valid and has a relative reference form. inline std::optional -toReference(const std::optional &V) { +toRelativeReference(const std::optional &V) { if (V) - return V->getAsReference(); + return V->getAsRelativeReference(); return std::nullopt; } -/// Take an optional DWARFFormValue and extract a reference. +/// Take an optional DWARFFormValue and extract a relative offset reference. /// -/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \param V an 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 relative offset reference form. +inline uint64_t toRelativeReference(const std::optional &V, + uint64_t Default) { + return toRelativeReference(V).value_or(Default); +} + +/// Take an optional DWARFFormValue and try to extract an absolute debug info +/// offset reference. +/// +/// \param V an 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 an (absolute) debug info offset reference form. +inline std::optional +toDebugInfoReference(const std::optional &V) { + if (V) + return V->getAsDebugInfoReference(); + return std::nullopt; +} + +/// Take an optional DWARFFormValue and extract an absolute debug info offset +/// reference. +/// +/// \param V an 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 an absolute debug info offset +/// reference form. +inline uint64_t toDebugInfoReference(const std::optional &V, + uint64_t Default) { + return toDebugInfoReference(V).value_or(Default); +} + +/// Take an optional DWARFFormValue and try to extract a signature reference. +/// +/// \param V an 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 signature reference form. +inline std::optional +toSignatureReference(const std::optional &V) { + if (V) + return V->getAsSignatureReference(); + return std::nullopt; +} + +/// Take an optional DWARFFormValue and extract a signature reference. +/// +/// \param V an 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 signature reference form. +inline uint64_t toSignatureReference(const std::optional &V, + uint64_t Default) { + return toSignatureReference(V).value_or(Default); +} + +/// Take an optional DWARFFormValue and try to extract a supplementary debug +/// info reference. +/// +/// \param V an 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 supplementary reference form. +inline std::optional +toSupplementaryReference(const std::optional &V) { + if (V) + return V->getAsSupplementaryReference(); + return std::nullopt; +} + +/// Take an optional DWARFFormValue and extract a supplementary debug info +/// reference. +/// +/// \param V an 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 std::optional &V, - uint64_t Default) { - return toReference(V).value_or(Default); +/// value or the form value's encoding wasn't a supplementary reference form. +inline uint64_t toSupplementaryReference(const std::optional &V, + uint64_t Default) { + return toSupplementaryReference(V).value_or(Default); } /// Take an optional DWARFFormValue and try to extract an signed constant. diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index c6312c387744aa..7510326f2e1b34 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -77,7 +77,15 @@ DWARFDie DWARFLinker::resolveDIEReference(const DWARFFile &File, const DWARFDie &DIE, CompileUnit *&RefCU) { assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); - uint64_t RefOffset = *RefValue.getAsReference(); + uint64_t RefOffset; + if (std::optional Off = RefValue.getAsRelativeReference()) { + RefOffset = RefValue.getUnit()->getOffset() + *Off; + } else if (Off = RefValue.getAsDebugInfoReference(); Off) { + RefOffset = *Off; + } else { + reportWarning("Unsupported reference type", File, &DIE); + return DWARFDie(); + } if ((RefCU = getUnitForOffset(Units, RefOffset))) if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) { // In a file with broken references, an attribute might point to a NULL @@ -1073,7 +1081,13 @@ unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute( unsigned AttrSize, const DWARFFormValue &Val, const DWARFFile &File, CompileUnit &Unit) { const DWARFUnit &U = Unit.getOrigUnit(); - uint64_t Ref = *Val.getAsReference(); + uint64_t Ref; + if (std::optional Off = Val.getAsRelativeReference()) + Ref = Val.getUnit()->getOffset() + *Off; + else if (Off = Val.getAsDebugInfoReference(); Off) + Ref = *Off; + else + return 0; DIE *NewRefDie = nullptr; CompileUnit *RefUnit = nullptr; diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp index 6f659eb8576b79..4daf781a2b53fa 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp @@ -381,38 +381,36 @@ void CompileUnit::updateDieRefPatchesWithClonedOffsets() { std::optional CompileUnit::resolveDIEReference( const DWARFFormValue &RefValue, ResolveInterCUReferencesMode CanResolveInterCUReferences) { - if (std::optional Ref = - *RefValue.getAsRelativeReference()) { - if (Ref->Unit == OrigUnit) { - // Referenced DIE is in current compile unit. - if (std::optional RefDieIdx = - getDIEIndexForOffset(OrigUnit->getOffset() + Ref->Offset)) - return UnitEntryPairTy{this, OrigUnit->getDebugInfoEntry(*RefDieIdx)}; - } - uint64_t RefDIEOffset = - Ref->Unit ? Ref->Unit->getOffset() + Ref->Offset : Ref->Offset; - if (CompileUnit *RefCU = getUnitFromOffset(RefDIEOffset)) { - if (RefCU == this) { - // Referenced DIE is in current compile unit. - if (std::optional RefDieIdx = - getDIEIndexForOffset(RefDIEOffset)) - return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)}; - } else if (CanResolveInterCUReferences) { - // Referenced DIE is in other compile unit. - - // Check whether DIEs are loaded for that compile unit. - enum Stage ReferredCUStage = RefCU->getStage(); - if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned) - return UnitEntryPairTy{RefCU, nullptr}; - - if (std::optional RefDieIdx = - RefCU->getDIEIndexForOffset(RefDIEOffset)) - return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)}; - } else - return UnitEntryPairTy{RefCU, nullptr}; - } + CompileUnit *RefCU; + uint64_t RefDIEOffset; + if (std::optional Offset = RefValue.getAsRelativeReference()) { + RefCU = this; + RefDIEOffset = RefValue.getUnit()->getOffset() + *Offset; + } else if (Offset = RefValue.getAsDebugInfoReference(); Offset) { + RefCU = getUnitFromOffset(*Offset); + RefDIEOffset = *Offset; + } else { + return std::nullopt; } + if (RefCU == this) { + // Referenced DIE is in current compile unit. + if (std::optional RefDieIdx = getDIEIndexForOffset(RefDIEOffset)) + return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)}; + } else if (RefCU && CanResolveInterCUReferences) { + // Referenced DIE is in other compile unit. + + // Check whether DIEs are loaded for that compile unit. + enum Stage ReferredCUStage = RefCU->getStage(); + if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned) + return UnitEntryPairTy{RefCU, nullptr}; + + if (std::optional RefDieIdx = + RefCU->getDIEIndexForOffset(RefDIEOffset)) + return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)}; + } else { + return UnitEntryPairTy{RefCU, nullptr}; + } return std::nullopt; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 410842a80b0151..72e7464b689716 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -313,13 +313,12 @@ DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { DWARFDie DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { DWARFDie Result; - if (auto SpecRef = V.getAsRelativeReference()) { - if (SpecRef->Unit) - Result = SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + - SpecRef->Offset); - else if (auto SpecUnit = - U->getUnitVector().getUnitForOffset(SpecRef->Offset)) - Result = SpecUnit->getDIEForOffset(SpecRef->Offset); + if (std::optional Offset = V.getAsRelativeReference()) { + Result = const_cast(V.getUnit()) + ->getDIEForOffset(V.getUnit()->getOffset() + *Offset); + } else if (Offset = V.getAsDebugInfoReference(); Offset) { + if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(*Offset)) + Result = SpecUnit->getDIEForOffset(*Offset); } return Result; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index b9cf7d22c80d4b..bc4badc7713802 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -665,16 +665,7 @@ DWARFFormValue::getAsSectionedAddress() const { return getAsSectionedAddress(Value, Form, U); } -std::optional DWARFFormValue::getAsReference() const { - if (auto R = getAsRelativeReference()) - return R->Unit ? R->Unit->getOffset() + R->Offset : R->Offset; - return std::nullopt; -} - -std::optional -DWARFFormValue::getAsRelativeReference() const { - if (!isFormClass(FC_Reference)) - return std::nullopt; +std::optional DWARFFormValue::getAsRelativeReference() const { switch (Form) { case DW_FORM_ref1: case DW_FORM_ref2: @@ -683,11 +674,30 @@ DWARFFormValue::getAsRelativeReference() const { case DW_FORM_ref_udata: if (!U) return std::nullopt; - return UnitOffset{const_cast(U), Value.uval}; - case DW_FORM_ref_addr: - case DW_FORM_ref_sig8: + return Value.uval; + default: + return std::nullopt; + } +} + +std::optional DWARFFormValue::getAsDebugInfoReference() const { + if (Form == DW_FORM_ref_addr) + return Value.uval; + return std::nullopt; +} + +std::optional DWARFFormValue::getAsSignatureReference() const { + if (Form == DW_FORM_ref_sig8) + return Value.uval; + return std::nullopt; +} + +std::optional DWARFFormValue::getAsSupplementaryReference() const { + switch (Form) { case DW_FORM_GNU_ref_alt: - return UnitOffset{nullptr, Value.uval}; + case DW_FORM_ref_sup4: + case DW_FORM_ref_sup8: + return Value.uval; default: return std::nullopt; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 4ef6c80ed0289d..a804deb446186d 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -836,7 +836,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, case DW_FORM_ref8: case DW_FORM_ref_udata: { // Verify all CU relative references are valid CU offsets. - std::optional RefVal = AttrValue.Value.getAsReference(); + std::optional RefVal = AttrValue.Value.getAsRelativeReference(); assert(RefVal); if (RefVal) { auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset(); @@ -854,7 +854,8 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, } else { // Valid reference, but we will verify it points to an actual // DIE later. - LocalReferences[*RefVal].insert(Die.getOffset()); + LocalReferences[AttrValue.Value.getUnit()->getOffset() + *RefVal] + .insert(Die.getOffset()); } } break; @@ -862,7 +863,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, case DW_FORM_ref_addr: { // Verify all absolute DIE references have valid offsets in the // .debug_info section. - std::optional RefVal = AttrValue.Value.getAsReference(); + std::optional RefVal = AttrValue.Value.getAsDebugInfoReference(); assert(RefVal); if (RefVal) { if (*RefVal >= DieCU->getInfoSection().Data.size()) { diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 6a97bed9e3a838..68a14b8b0ad33e 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -1082,10 +1082,17 @@ void LVDWARFReader::updateReference(dwarf::Attribute Attr, // FIXME: We are assuming that at most one Reference (DW_AT_specification, // DW_AT_abstract_origin, ...) and at most one Type (DW_AT_import, DW_AT_type) // appear in any single DIE, but this may not be true. - uint64_t Reference = *FormValue.getAsReference(); + uint64_t Offset; + if (std::optional Off = FormValue.getAsRelativeReference()) + Offset = FormValue.getUnit()->getOffset() + *Off; + else if (Off = FormValue.getAsDebugInfoReference(); Off) + Offset = *Off; + else + llvm_unreachable("Unsupported reference type"); + // Get target for the given reference, if already created. LVElement *Target = getElementForOffset( - Reference, CurrentElement, + Offset, CurrentElement, /*IsType=*/Attr == dwarf::DW_AT_import || Attr == dwarf::DW_AT_type); // Check if we are dealing with cross CU references. if (FormValue.getForm() == dwarf::DW_FORM_ref_addr) { @@ -1093,10 +1100,10 @@ void LVDWARFReader::updateReference(dwarf::Attribute Attr, // The global reference is ready. Mark it as global. Target->setIsGlobalReference(); // Remove global reference from the unseen list. - removeGlobalOffset(Reference); + removeGlobalOffset(Offset); } else // Record the unseen cross CU reference. - addGlobalOffset(Reference); + addGlobalOffset(Offset); } // At this point, 'Target' can be null, in the case of the target element diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp index 5cb0310c0ad097..373a58d259af5e 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -384,15 +384,18 @@ void TestAllForms() { //---------------------------------------------------------------------- // Test reference forms //---------------------------------------------------------------------- - 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(RefAddr, + toDebugInfoReference(DieDG.find(Attr_DW_FORM_ref_addr), 0)); + EXPECT_EQ(Data1, toRelativeReference(DieDG.find(Attr_DW_FORM_ref1), 0)); + EXPECT_EQ(Data2, toRelativeReference(DieDG.find(Attr_DW_FORM_ref2), 0)); + EXPECT_EQ(Data4, toRelativeReference(DieDG.find(Attr_DW_FORM_ref4), 0)); + EXPECT_EQ(Data8, toRelativeReference(DieDG.find(Attr_DW_FORM_ref8), 0)); if (Version >= 4) { - EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0)); + EXPECT_EQ(Data8_2, + toSignatureReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0)); } - EXPECT_EQ(UData[0], toReference(DieDG.find(Attr_DW_FORM_ref_udata), 0)); + EXPECT_EQ(UData[0], + toRelativeReference(DieDG.find(Attr_DW_FORM_ref_udata), 0)); //---------------------------------------------------------------------- // Test flag forms @@ -420,7 +423,7 @@ void TestAllForms() { // Test DWARF32/DWARF64 forms //---------------------------------------------------------------------- EXPECT_EQ(Dwarf32Values[0], - toReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0)); + toSupplementaryReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0)); if (Version >= 4) { EXPECT_EQ(Dwarf32Values[1], toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0)); @@ -761,14 +764,14 @@ template void TestReferences() { EXPECT_TRUE(CU1Ref1DieDG.isValid()); EXPECT_EQ(CU1Ref1DieDG.getTag(), DW_TAG_variable); EXPECT_EQ(CU1TypeDieDG.getOffset(), - toReference(CU1Ref1DieDG.find(DW_AT_type), -1ULL)); + toRelativeReference(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(CU1TypeDieDG.getOffset(), - toReference(CU1Ref2DieDG.find(DW_AT_type), -1ULL)); + toRelativeReference(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. @@ -776,7 +779,7 @@ template void TestReferences() { EXPECT_TRUE(CU1Ref4DieDG.isValid()); EXPECT_EQ(CU1Ref4DieDG.getTag(), DW_TAG_variable); EXPECT_EQ(CU1TypeDieDG.getOffset(), - toReference(CU1Ref4DieDG.find(DW_AT_type), -1ULL)); + toRelativeReference(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. @@ -784,7 +787,7 @@ template void TestReferences() { EXPECT_TRUE(CU1Ref8DieDG.isValid()); EXPECT_EQ(CU1Ref8DieDG.getTag(), DW_TAG_variable); EXPECT_EQ(CU1TypeDieDG.getOffset(), - toReference(CU1Ref8DieDG.find(DW_AT_type), -1ULL)); + toRelativeReference(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. @@ -792,7 +795,7 @@ template void TestReferences() { EXPECT_TRUE(CU1RefAddrDieDG.isValid()); EXPECT_EQ(CU1RefAddrDieDG.getTag(), DW_TAG_variable); EXPECT_EQ(CU1TypeDieDG.getOffset(), - toReference(CU1RefAddrDieDG.find(DW_AT_type), -1ULL)); + toDebugInfoReference(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. @@ -800,38 +803,38 @@ template void TestReferences() { EXPECT_TRUE(CU1ToCU2RefAddrDieDG.isValid()); EXPECT_EQ(CU1ToCU2RefAddrDieDG.getTag(), DW_TAG_variable); EXPECT_EQ(CU2TypeDieDG.getOffset(), - toReference(CU1ToCU2RefAddrDieDG.find(DW_AT_type), -1ULL)); + toDebugInfoReference(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(CU2TypeDieDG.getOffset(), - toReference(CU2Ref1DieDG.find(DW_AT_type), -1ULL)); + EXPECT_EQ(CU2TypeDieDG.getOffset() - CU2TypeDieDG.getDwarfUnit()->getOffset(), + toRelativeReference(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(CU2TypeDieDG.getOffset(), - toReference(CU2Ref2DieDG.find(DW_AT_type), -1ULL)); + EXPECT_EQ(CU2TypeDieDG.getOffset() - CU2TypeDieDG.getDwarfUnit()->getOffset(), + toRelativeReference(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(CU2TypeDieDG.getOffset(), - toReference(CU2Ref4DieDG.find(DW_AT_type), -1ULL)); + EXPECT_EQ(CU2TypeDieDG.getOffset() - CU2TypeDieDG.getDwarfUnit()->getOffset(), + toRelativeReference(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(CU2TypeDieDG.getOffset(), - toReference(CU2Ref8DieDG.find(DW_AT_type), -1ULL)); + EXPECT_EQ(CU2TypeDieDG.getOffset() - CU2TypeDieDG.getDwarfUnit()->getOffset(), + toRelativeReference(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. @@ -839,7 +842,7 @@ template void TestReferences() { EXPECT_TRUE(CU2RefAddrDieDG.isValid()); EXPECT_EQ(CU2RefAddrDieDG.getTag(), DW_TAG_variable); EXPECT_EQ(CU2TypeDieDG.getOffset(), - toReference(CU2RefAddrDieDG.find(DW_AT_type), -1ULL)); + toDebugInfoReference(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. @@ -847,7 +850,7 @@ template void TestReferences() { EXPECT_TRUE(CU2ToCU1RefAddrDieDG.isValid()); EXPECT_EQ(CU2ToCU1RefAddrDieDG.getTag(), DW_TAG_variable); EXPECT_EQ(CU1TypeDieDG.getOffset(), - toReference(CU2ToCU1RefAddrDieDG.find(DW_AT_type), -1ULL)); + toDebugInfoReference(CU2ToCU1RefAddrDieDG.find(DW_AT_type), -1ULL)); } TEST(DWARFDebugInfo, TestDWARF32Version2Addr4References) { @@ -1662,14 +1665,20 @@ TEST(DWARFDebugInfo, TestDwarfToFunctions) { std::optional FormValOpt1 = DWARFFormValue(); EXPECT_FALSE(toString(FormValOpt1).has_value()); EXPECT_FALSE(toUnsigned(FormValOpt1).has_value()); - EXPECT_FALSE(toReference(FormValOpt1).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt1).has_value()); + EXPECT_FALSE(toDebugInfoReference(FormValOpt1).has_value()); + EXPECT_FALSE(toSignatureReference(FormValOpt1).has_value()); + EXPECT_FALSE(toSupplementaryReference(FormValOpt1).has_value()); EXPECT_FALSE(toSigned(FormValOpt1).has_value()); EXPECT_FALSE(toAddress(FormValOpt1).has_value()); EXPECT_FALSE(toSectionOffset(FormValOpt1).has_value()); EXPECT_FALSE(toBlock(FormValOpt1).has_value()); EXPECT_EQ(nullptr, toString(FormValOpt1, nullptr)); EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt1, InvalidU64)); - EXPECT_EQ(InvalidU64, toReference(FormValOpt1, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt1, InvalidU64)); + EXPECT_EQ(InvalidU64, toDebugInfoReference(FormValOpt1, InvalidU64)); + EXPECT_EQ(InvalidU64, toSignatureReference(FormValOpt1, InvalidU64)); + EXPECT_EQ(InvalidU64, toSupplementaryReference(FormValOpt1, InvalidU64)); EXPECT_EQ(InvalidU64, toAddress(FormValOpt1, InvalidU64)); EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt1, InvalidU64)); EXPECT_EQ(InvalidS64, toSigned(FormValOpt1, InvalidS64)); @@ -1681,14 +1690,20 @@ TEST(DWARFDebugInfo, TestDwarfToFunctions) { EXPECT_FALSE(toString(FormValOpt2).has_value()); EXPECT_FALSE(toUnsigned(FormValOpt2).has_value()); - EXPECT_FALSE(toReference(FormValOpt2).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt2).has_value()); + EXPECT_FALSE(toDebugInfoReference(FormValOpt2).has_value()); + EXPECT_FALSE(toSignatureReference(FormValOpt2).has_value()); + EXPECT_FALSE(toSupplementaryReference(FormValOpt2).has_value()); EXPECT_FALSE(toSigned(FormValOpt2).has_value()); EXPECT_TRUE(toAddress(FormValOpt2).has_value()); EXPECT_FALSE(toSectionOffset(FormValOpt2).has_value()); EXPECT_FALSE(toBlock(FormValOpt2).has_value()); EXPECT_EQ(nullptr, toString(FormValOpt2, nullptr)); EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt2, InvalidU64)); - EXPECT_EQ(InvalidU64, toReference(FormValOpt2, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt2, InvalidU64)); + EXPECT_EQ(InvalidU64, toDebugInfoReference(FormValOpt2, InvalidU64)); + EXPECT_EQ(InvalidU64, toSignatureReference(FormValOpt2, InvalidU64)); + EXPECT_EQ(InvalidU64, toSupplementaryReference(FormValOpt2, InvalidU64)); EXPECT_EQ(Address, toAddress(FormValOpt2, InvalidU64)); EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt2, InvalidU64)); EXPECT_EQ(InvalidS64, toSigned(FormValOpt2, InvalidU64)); @@ -1700,36 +1715,98 @@ TEST(DWARFDebugInfo, TestDwarfToFunctions) { EXPECT_FALSE(toString(FormValOpt3).has_value()); EXPECT_TRUE(toUnsigned(FormValOpt3).has_value()); - EXPECT_FALSE(toReference(FormValOpt3).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt3).has_value()); + EXPECT_FALSE(toDebugInfoReference(FormValOpt3).has_value()); + EXPECT_FALSE(toSignatureReference(FormValOpt3).has_value()); + EXPECT_FALSE(toSupplementaryReference(FormValOpt3).has_value()); EXPECT_TRUE(toSigned(FormValOpt3).has_value()); EXPECT_FALSE(toAddress(FormValOpt3).has_value()); EXPECT_FALSE(toSectionOffset(FormValOpt3).has_value()); EXPECT_FALSE(toBlock(FormValOpt3).has_value()); EXPECT_EQ(nullptr, toString(FormValOpt3, nullptr)); EXPECT_EQ(UData8, toUnsigned(FormValOpt3, InvalidU64)); - EXPECT_EQ(InvalidU64, toReference(FormValOpt3, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt3, InvalidU64)); + EXPECT_EQ(InvalidU64, toDebugInfoReference(FormValOpt3, InvalidU64)); + EXPECT_EQ(InvalidU64, toSignatureReference(FormValOpt3, InvalidU64)); + EXPECT_EQ(InvalidU64, toSupplementaryReference(FormValOpt3, InvalidU64)); EXPECT_EQ(InvalidU64, toAddress(FormValOpt3, InvalidU64)); EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt3, InvalidU64)); EXPECT_EQ((int64_t)UData8, toSigned(FormValOpt3, InvalidU64)); - // Test successful and unsuccessful reference decoding. + // Test successful and unsuccessful ref_addr decoding. uint32_t RefData = 0x11223344U; - std::optional FormValOpt4 = + std::optional FormValOpt4Addr = DWARFFormValue::createFromUValue(DW_FORM_ref_addr, RefData); - EXPECT_FALSE(toString(FormValOpt4).has_value()); - EXPECT_FALSE(toUnsigned(FormValOpt4).has_value()); - EXPECT_TRUE(toReference(FormValOpt4).has_value()); - EXPECT_FALSE(toSigned(FormValOpt4).has_value()); - EXPECT_FALSE(toAddress(FormValOpt4).has_value()); - EXPECT_FALSE(toSectionOffset(FormValOpt4).has_value()); - EXPECT_FALSE(toBlock(FormValOpt4).has_value()); - EXPECT_EQ(nullptr, toString(FormValOpt4, nullptr)); - EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt4, InvalidU64)); - EXPECT_EQ(RefData, toReference(FormValOpt4, InvalidU64)); - EXPECT_EQ(InvalidU64, toAddress(FormValOpt4, InvalidU64)); - EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt4, InvalidU64)); - EXPECT_EQ(InvalidS64, toSigned(FormValOpt4, InvalidU64)); + EXPECT_FALSE(toString(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toUnsigned(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt4Addr).has_value()); + EXPECT_TRUE(toDebugInfoReference(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toSignatureReference(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toSupplementaryReference(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toSigned(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toAddress(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toSectionOffset(FormValOpt4Addr).has_value()); + EXPECT_FALSE(toBlock(FormValOpt4Addr).has_value()); + EXPECT_EQ(nullptr, toString(FormValOpt4Addr, nullptr)); + EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt4Addr, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt4Addr, InvalidU64)); + EXPECT_EQ(RefData, toDebugInfoReference(FormValOpt4Addr, InvalidU64)); + EXPECT_EQ(InvalidU64, toSignatureReference(FormValOpt4Addr, InvalidU64)); + EXPECT_EQ(InvalidU64, toSupplementaryReference(FormValOpt4Addr, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt4Addr, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt4Addr, InvalidU64)); + EXPECT_EQ(InvalidS64, toSigned(FormValOpt4Addr, InvalidU64)); + + // Test successful and unsuccessful ref_sig8 decoding. + std::optional FormValOpt4Sig = + DWARFFormValue::createFromUValue(DW_FORM_ref_sig8, RefData); + + EXPECT_FALSE(toString(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toUnsigned(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toDebugInfoReference(FormValOpt4Sig).has_value()); + EXPECT_TRUE(toSignatureReference(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toSupplementaryReference(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toSigned(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toAddress(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toSectionOffset(FormValOpt4Sig).has_value()); + EXPECT_FALSE(toBlock(FormValOpt4Sig).has_value()); + EXPECT_EQ(nullptr, toString(FormValOpt4Sig, nullptr)); + EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt4Sig, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt4Sig, InvalidU64)); + EXPECT_EQ(InvalidU64, toDebugInfoReference(FormValOpt4Sig, InvalidU64)); + EXPECT_EQ(RefData, toSignatureReference(FormValOpt4Sig, InvalidU64)); + EXPECT_EQ(InvalidU64, toSupplementaryReference(FormValOpt4Sig, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt4Sig, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt4Sig, InvalidU64)); + EXPECT_EQ(InvalidS64, toSigned(FormValOpt4Sig, InvalidU64)); + + // Test successful and unsuccessful ref_alt decoding. + // Not testing relative reference forms here, as they require a valid + // DWARFUnit object. + std::optional FormValOpt4Alt = + DWARFFormValue::createFromUValue(DW_FORM_GNU_ref_alt, RefData); + + EXPECT_FALSE(toString(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toUnsigned(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toDebugInfoReference(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toSignatureReference(FormValOpt4Alt).has_value()); + EXPECT_TRUE(toSupplementaryReference(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toSigned(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toAddress(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toSectionOffset(FormValOpt4Alt).has_value()); + EXPECT_FALSE(toBlock(FormValOpt4Alt).has_value()); + EXPECT_EQ(nullptr, toString(FormValOpt4Alt, nullptr)); + EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt4Alt, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt4Alt, InvalidU64)); + EXPECT_EQ(InvalidU64, toDebugInfoReference(FormValOpt4Alt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSignatureReference(FormValOpt4Alt, InvalidU64)); + EXPECT_EQ(RefData, toSupplementaryReference(FormValOpt4Alt, InvalidU64)); + EXPECT_EQ(InvalidU64, toAddress(FormValOpt4Alt, InvalidU64)); + EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt4Alt, InvalidU64)); + EXPECT_EQ(InvalidS64, toSigned(FormValOpt4Alt, InvalidU64)); // Test successful and unsuccessful signed constant decoding. int64_t SData8 = 0x1020304050607080ULL; @@ -1738,14 +1815,20 @@ TEST(DWARFDebugInfo, TestDwarfToFunctions) { EXPECT_FALSE(toString(FormValOpt5).has_value()); EXPECT_TRUE(toUnsigned(FormValOpt5).has_value()); - EXPECT_FALSE(toReference(FormValOpt5).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt5).has_value()); + EXPECT_FALSE(toDebugInfoReference(FormValOpt5).has_value()); + EXPECT_FALSE(toSignatureReference(FormValOpt5).has_value()); + EXPECT_FALSE(toSupplementaryReference(FormValOpt5).has_value()); EXPECT_TRUE(toSigned(FormValOpt5).has_value()); EXPECT_FALSE(toAddress(FormValOpt5).has_value()); EXPECT_FALSE(toSectionOffset(FormValOpt5).has_value()); EXPECT_FALSE(toBlock(FormValOpt5).has_value()); EXPECT_EQ(nullptr, toString(FormValOpt5, nullptr)); EXPECT_EQ((uint64_t)SData8, toUnsigned(FormValOpt5, InvalidU64)); - EXPECT_EQ(InvalidU64, toReference(FormValOpt5, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt5, InvalidU64)); + EXPECT_EQ(InvalidU64, toDebugInfoReference(FormValOpt5, InvalidU64)); + EXPECT_EQ(InvalidU64, toSignatureReference(FormValOpt5, InvalidU64)); + EXPECT_EQ(InvalidU64, toSupplementaryReference(FormValOpt5, InvalidU64)); EXPECT_EQ(InvalidU64, toAddress(FormValOpt5, InvalidU64)); EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt5, InvalidU64)); EXPECT_EQ(SData8, toSigned(FormValOpt5, InvalidU64)); @@ -1758,7 +1841,10 @@ TEST(DWARFDebugInfo, TestDwarfToFunctions) { EXPECT_FALSE(toString(FormValOpt6).has_value()); EXPECT_FALSE(toUnsigned(FormValOpt6).has_value()); - EXPECT_FALSE(toReference(FormValOpt6).has_value()); + EXPECT_FALSE(toRelativeReference(FormValOpt6).has_value()); + EXPECT_FALSE(toDebugInfoReference(FormValOpt6).has_value()); + EXPECT_FALSE(toSignatureReference(FormValOpt6).has_value()); + EXPECT_FALSE(toSupplementaryReference(FormValOpt6).has_value()); EXPECT_FALSE(toSigned(FormValOpt6).has_value()); EXPECT_FALSE(toAddress(FormValOpt6).has_value()); EXPECT_FALSE(toSectionOffset(FormValOpt6).has_value()); @@ -1767,7 +1853,10 @@ TEST(DWARFDebugInfo, TestDwarfToFunctions) { EXPECT_EQ(*BlockOpt, Array); EXPECT_EQ(nullptr, toString(FormValOpt6, nullptr)); EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt6, InvalidU64)); - EXPECT_EQ(InvalidU64, toReference(FormValOpt6, InvalidU64)); + EXPECT_EQ(InvalidU64, toRelativeReference(FormValOpt6, InvalidU64)); + EXPECT_EQ(InvalidU64, toDebugInfoReference(FormValOpt6, InvalidU64)); + EXPECT_EQ(InvalidU64, toSignatureReference(FormValOpt6, InvalidU64)); + EXPECT_EQ(InvalidU64, toSupplementaryReference(FormValOpt6, InvalidU64)); EXPECT_EQ(InvalidU64, toAddress(FormValOpt6, InvalidU64)); EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt6, InvalidU64)); EXPECT_EQ(InvalidS64, toSigned(FormValOpt6, InvalidU64));