From 936954631b57a3dd18dec62c847a8d6305b37385 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Tue, 7 Mar 2023 13:46:21 +0100 Subject: [PATCH] [DebugInfo][DWARF] Add doesFormBelongToClass function. The result of DWARFFormValue::isFormClass depends on DWARF version in some cases. The current implementation takes DWARF version from the stored DWARFUnit. If there is no stored DWARFUnit then the current behavior is to assume DwarfVersion <= 3. This patch adds new function which has a DWARF version as a parameter so it is possible to check form class for various DWARF versions. Differential Revision: https://reviews.llvm.org/D145499 --- llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h | 8 +++ llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 66 ++++++++++++---------- .../DebugInfo/DWARF/DWARFFormValueTest.cpp | 4 ++ 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 1951d08..f22e4c3 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -349,6 +349,14 @@ toBlock(const std::optional &V) { return std::nullopt; } +/// Check whether specified \p Form belongs to the \p FC class. +/// \param Form an attribute form. +/// \param FC an attribute form class to check. +/// \param DwarfVersion the version of DWARF debug info keeping the attribute. +/// \returns true if specified \p Form belongs to the \p FC class. +bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, + uint16_t DwarfVersion); + } // end namespace dwarf } // end namespace llvm diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 804b877..e7b39c7 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -214,35 +214,7 @@ bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, } bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { - // First, check DWARF5 form classes. - if (Form < ArrayRef(DWARF5FormClasses).size() && - DWARF5FormClasses[Form] == FC) - return true; - // Check more forms from extensions and proposals. - switch (Form) { - case DW_FORM_GNU_ref_alt: - return (FC == FC_Reference); - case DW_FORM_GNU_addr_index: - return (FC == FC_Address); - case DW_FORM_GNU_str_index: - case DW_FORM_GNU_strp_alt: - return (FC == FC_String); - case DW_FORM_LLVM_addrx_offset: - return (FC == FC_Address); - default: - break; - } - - if (FC == FC_SectionOffset) { - if (Form == DW_FORM_strp || Form == DW_FORM_line_strp) - return true; - // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section - // offset. If we don't have a DWARFUnit, default to the old behavior. - if (Form == DW_FORM_data4 || Form == DW_FORM_data8) - return !U || U->getVersion() <= 3; - } - - return false; + return doesFormBelongToClass(Form, FC, U ? U->getVersion() : 3); } bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, @@ -778,3 +750,39 @@ DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const { } return std::nullopt; } + +namespace llvm { +namespace dwarf { + +bool doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC, + uint16_t DwarfVersion) { + // First, check DWARF5 form classes. + if (Form < ArrayRef(DWARF5FormClasses).size() && + DWARF5FormClasses[Form] == FC) + return true; + // Check more forms from extensions and proposals. + switch (Form) { + case DW_FORM_GNU_ref_alt: + return (FC == DWARFFormValue::FC_Reference); + case DW_FORM_GNU_addr_index: + return (FC == DWARFFormValue::FC_Address); + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_strp_alt: + return (FC == DWARFFormValue::FC_String); + case DW_FORM_LLVM_addrx_offset: + return (FC == DWARFFormValue::FC_Address); + case DW_FORM_strp: + case DW_FORM_line_strp: + return (FC == DWARFFormValue::FC_SectionOffset); + case DW_FORM_data4: + case DW_FORM_data8: + // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section + // offset. + return (FC == DWARFFormValue::FC_SectionOffset) && (DwarfVersion <= 3); + default: + return false; + } +} + +} // end namespace dwarf +} // end namespace llvm diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp index a7f2722..c79daa6 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp @@ -30,6 +30,10 @@ TEST(DWARFFormValue, FormClass) { EXPECT_FALSE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Address)); EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Constant)); EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_SectionOffset)); + EXPECT_TRUE(doesFormBelongToClass(DW_FORM_data8, + DWARFFormValue::FC_SectionOffset, 3)); + EXPECT_FALSE(doesFormBelongToClass(DW_FORM_data8, + DWARFFormValue::FC_SectionOffset, 5)); EXPECT_TRUE( isFormClass(DW_FORM_sec_offset, DWARFFormValue::FC_SectionOffset)); EXPECT_TRUE(isFormClass(DW_FORM_GNU_str_index, DWARFFormValue::FC_String)); -- 2.7.4