[llvm] 4f60a42 - DWARFVerifier: Skip resolution failures for locations in dwo files

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 16 22:27:12 PST 2021


Author: David Blaikie
Date: 2021-12-16T22:24:32-08:00
New Revision: 4f60a42878b0d46bc2cc84d8f0d316cac2c60c9d

URL: https://github.com/llvm/llvm-project/commit/4f60a42878b0d46bc2cc84d8f0d316cac2c60c9d
DIFF: https://github.com/llvm/llvm-project/commit/4f60a42878b0d46bc2cc84d8f0d316cac2c60c9d.diff

LOG: DWARFVerifier: Skip resolution failures for locations in dwo files

When reading location lists in dwo files the addresses cannot be
resolved, but that's not a problem.

Long term this probably should be fixed with a different API that
exposes location expressions without the need to resolve the address
ranges, since that's all the verifier (in its current state) requires.
(though the verifier should probably also eventually verify the address
ranges in location lists are a subset of the enclosing scope's address
range)

Added: 
    

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
    llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
    llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
    llvm/test/tools/llvm-dwarfdump/X86/verify_split_cu.s
    llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
index dbc11c51a7890..1794f66498277 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -15,6 +15,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/Support/Errc.h"
 #include <cstdint>
 
 namespace llvm {
@@ -142,6 +143,22 @@ class DWARFDebugLoclists final : public DWARFLocationTable {
   uint16_t Version;
 };
 
+class ResolverError : public ErrorInfo<ResolverError> {
+public:
+  static char ID;
+
+  ResolverError(uint32_t Index, dwarf::LoclistEntries Kind) : Index(Index), Kind(Kind) {}
+
+  void log(raw_ostream &OS) const override;
+  std::error_code convertToErrorCode() const override {
+    return llvm::errc::invalid_argument;
+  }
+
+private:
+  uint32_t Index;
+  dwarf::LoclistEntries Kind;
+};
+
 } // end namespace llvm
 
 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
index cdffb36741c84..f39c7871d6034 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -41,9 +41,7 @@ class DWARFLocationInterpreter {
 } // namespace
 
 static Error createResolverError(uint32_t Index, unsigned Kind) {
-  return createStringError(errc::invalid_argument,
-                           "Unable to resolve indirect address %u for: %s",
-                           Index, dwarf::LocListEncodingString(Kind).data());
+  return make_error<ResolverError>(Index, (dwarf::LoclistEntries)Kind);
 }
 
 Expected<Optional<DWARFLocationExpression>>
@@ -404,3 +402,10 @@ void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size,
     OS << '\n';
   }
 }
+
+void llvm::ResolverError::log(raw_ostream &OS) const {
+  OS << format("unable to resolve indirect address %u for: %s", Index,
+               dwarf::LocListEncodingString(Kind).data());
+}
+
+char llvm::ResolverError::ID;

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 99255f6b5b661..36ca7fe027673 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -534,6 +534,16 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
     ReportError("DIE has invalid DW_AT_stmt_list encoding:");
     break;
   case DW_AT_location: {
+    // FIXME: It might be nice if there's a way to walk location expressions
+    // without trying to resolve the address ranges - it'd be a more efficient
+    // API (since the API is currently unnecessarily resolving addresses for
+    // this use case which only wants to validate the expressions themselves) &
+    // then the expressions could be validated even if the addresses can't be
+    // resolved.
+    // That sort of API would probably look like a callback "for each
+    // expression" with some way to lazily resolve the address ranges when
+    // needed (& then the existing API used here could be built on top of that -
+    // using the callback API to build the data structure and return it).
     if (Expected<std::vector<DWARFLocationExpression>> Loc =
             Die.getLocations(DW_AT_location)) {
       for (const auto &Entry : *Loc) {
@@ -547,8 +557,12 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
         if (Error || !Expression.verify(U))
           ReportError("DIE contains invalid DWARF expression:");
       }
-    } else
-      ReportError(toString(Loc.takeError()));
+    } else if (Error E = handleErrors(
+                   Loc.takeError(), [&](std::unique_ptr<ResolverError> E) {
+                     return U->isDWOUnit() ? Error::success()
+                                           : Error(std::move(E));
+                   }))
+      ReportError(toString(std::move(E)));
     break;
   }
   case DW_AT_specification:

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_split_cu.s b/llvm/test/tools/llvm-dwarfdump/X86/verify_split_cu.s
index 755dc9f67c8ff..3941d9f1a7a57 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/verify_split_cu.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_split_cu.s
@@ -28,7 +28,7 @@
 	.quad	2                               # DWO ID
 	.byte	1                               # Abbrev [1] DW_TAG_compile_unit
 	.byte	0                               # DW_AT_decl_file
-	.byte	0				# DW_AT_location
+	.byte	0                               # DW_AT_location
 .Ldebug_info_dwo_end2:
 .Ldebug_info_dwo_prestart3:
 	.long	.Ldebug_info_dwo_end3-.Ldebug_info_dwo_start3 # Length of Unit
@@ -57,6 +57,16 @@
 	.long	0                               # DW_AT_stmt_list
 	.byte	0                               # DW_AT_decl_file
 .Ldebug_info_dwo_end4:
+	.long	.Ldebug_info_dwo_end5-.Ldebug_info_dwo_start5 # Length of Unit
+.Ldebug_info_dwo_start5:
+	.short	5                               # DWARF version number
+	.byte	5                               # DWARF Unit Type
+	.byte	8                               # Address Size (in bytes)
+	.long	0                               # Offset Into Abbrev. Section
+	.quad	2                               # DWO ID
+	.byte	4                               # Abbrev [1] DW_TAG_compile_unit
+	.uleb128	0                       # DW_AT_location
+.Ldebug_info_dwo_end5:
 	.section	.debug_abbrev.dwo,"e", at progbits
 	.byte	1                               # Abbreviation Code
 	.byte	17                              # DW_TAG_compile_unit
@@ -83,6 +93,13 @@
 	.byte	11                              # DW_FORM_data1
 	.byte	0                               # EOM(1)
 	.byte	0                               # EOM(2)
+	.byte	4                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	34                              # DW_FORM_loclistx
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
 	.byte	0                               # EOM(3)
 	.section	.debug_line.dwo,"e", at progbits
 .Ltmp2:
@@ -122,3 +139,24 @@
 	.byte	0x36, 0xb7, 0x17, 0xbf
 .Lprologue_end0:
 .Ldebug_line_end0:
+	.section	.debug_loclists.dwo,"e", at progbits
+	.long	.Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
+.Ldebug_list_header_start0:
+	.short	5                               # Version
+	.byte	8                               # Address size
+	.byte	0                               # Segment selector size
+	.long	1                               # Offset entry count
+.Lloclists_table_base0:
+	.long	.Ldebug_loc0-.Lloclists_table_base0
+.Ldebug_loc0:
+	.byte	1                               # DW_LLE_base_addressx
+	.byte	0                               #   base address index
+	.byte	4                               # DW_LLE_offset_pair
+	.uleb128 0                              #   starting offset
+	.uleb128 1                              #   ending offset
+	.byte	3                               # Loc expr size
+	.byte	17                              # DW_OP_consts
+	.byte	3                               # 3
+	.byte	159                             # DW_OP_stack_value
+	.byte	0                               # DW_LLE_end_of_list
+.Ldebug_list_header_end0:

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
index 82aaa458515a5..a7443056645a4 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp
@@ -87,7 +87,7 @@ TEST(DWARFDie, getLocations) {
       Die.getLocations(DW_AT_vtable_elem_location),
       Failed<ErrorInfoBase>(testing::Property(
           &ErrorInfoBase::message,
-          "Unable to resolve indirect address 1 for: DW_LLE_startx_length")));
+          "unable to resolve indirect address 1 for: DW_LLE_startx_length")));
 
   EXPECT_THAT_EXPECTED(
       Die.getLocations(DW_AT_call_data_location),


        


More information about the llvm-commits mailing list