[llvm] [llvm-debuginfo-analyzer] Fix a couple of unhandled DWARF situations leading to a crash (PR #137221)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 24 11:09:00 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-debuginfo

Author: Javier Lopez-Gomez (jalopezg-git)

<details>
<summary>Changes</summary>

This pull request fixes a couple of unhandled situations in DWARF input leading to a crash.  Specifically,

- If the DWARF input contains a declaration of a C variadic function (where `...` translates to `DW_TAG_unspecified_parameters`), which is then followed by a definition, `llvm_unreachable()` is hit in `LVScope::addMissingElements()`.  
This is only visible in Debug builds (see stack trace below), but still.  `test-dwarf-clang-unspec-params.elf` triggers this condition.
```
Invalid symbol kind.
UNREACHABLE executed at /home/jalopezg/repos/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:345!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: _build/Debug/bin/llvm-debuginfo-analyzer --print=all --attribute=all /tmp/test-dwarf-clang-unspec-params.elf
 #<!-- -->0 0x00005577295666f6 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/jalopezg/repos/llvm-project/llvm/lib/Support/Unix/Signals.inc:804:22
 #<!-- -->1 0x0000557729566b09 PrintStackTraceSignalHandler(void*) /home/jalopezg/repos/llvm-project/llvm/lib/Support/Unix/Signals.inc:880:1
 #<!-- -->2 0x0000557729563f1f llvm::sys::RunSignalHandlers() /home/jalopezg/repos/llvm-project/llvm/lib/Support/Signals.cpp:105:20
 #<!-- -->3 0x0000557729565fb4 SignalHandler(int, siginfo_t*, void*) /home/jalopezg/repos/llvm-project/llvm/lib/Support/Unix/Signals.inc:418:13
 #<!-- -->4 0x00007fc5ff23e710 (/usr/lib/libc.so.6+0x3e710)
 #<!-- -->5 0x00007fc5ff28e83c (/usr/lib/libc.so.6+0x8e83c)
 #<!-- -->6 0x00007fc5ff23e668 gsignal (/usr/lib/libc.so.6+0x3e668)
 #<!-- -->7 0x00007fc5ff2264b8 abort (/usr/lib/libc.so.6+0x264b8)
 #<!-- -->8 0x00005577294ad073 bindingsErrorHandler(void*, char const*, bool) /home/jalopezg/repos/llvm-project/llvm/lib/Support/ErrorHandling.cpp:223:55
 #<!-- -->9 0x0000557728f56b0c llvm::logicalview::LVScope::addMissingElements(llvm::logicalview::LVScope*) /home/jalopezg/repos/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:322:5
#<!-- -->10 0x0000557728f5f4b7 llvm::logicalview::LVScopeFunction::resolveReferences() /home/jalopezg/repos/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:1773:9
```

- Parsing of instructions in `LVBinaryReader::createInstructions()` does not check whether `Offset` lies within the `Bytes` ArrayRef.  A specially crafted DWARF input can lead to this condition.

FYI, @<!-- -->CarlosAlbertoEnciso.  I believe this patchset is ready; feel free to start review.

---
Full diff: https://github.com/llvm/llvm-project/pull/137221.diff


4 Files Affected:

- (modified) llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp (+4-1) 
- (modified) llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp (+7) 
- (modified) llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp (+32-1) 
- (added) llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-unspec-params.elf () 


``````````diff
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
index 8bbaf93db0caa..f187b1a57bd45 100644
--- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
@@ -330,13 +330,16 @@ void LVScope::addMissingElements(LVScope *Reference) {
       Symbol->setIsOptimized();
       Symbol->setReference(Reference);
 
-      // The symbol can be a constant, parameter or variable.
+      // The symbol can be a constant, parameter, variable or unspecified
+      // parameters (i.e. `...`).
       if (Reference->getIsConstant())
         Symbol->setIsConstant();
       else if (Reference->getIsParameter())
         Symbol->setIsParameter();
       else if (Reference->getIsVariable())
         Symbol->setIsVariable();
+      else if (Reference->getIsUnspecified())
+        Symbol->setIsUnspecified();
       else
         llvm_unreachable("Invalid symbol kind.");
     }
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
index ad14baa0c9269..b12208c53b8e3 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
@@ -433,6 +433,13 @@ Error LVBinaryReader::createInstructions(LVScope *Scope,
 
   ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(*SectionContentsOrErr);
   uint64_t Offset = Address - SectionAddress;
+  if (Offset > Bytes.size()) {
+    LLVM_DEBUG({
+      dbgs() << "offset (" << hexValue(Offset) << ") is beyond section size ("
+             << hexValue(Bytes.size()) << "); malformed input?\n";
+    });
+    return Error::success();
+  }
   uint8_t const *Begin = Bytes.data() + Offset;
   uint8_t const *End = Bytes.data() + Offset + Size;
 
diff --git a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
index c062c15481da9..7262da634d18d 100644
--- a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
+++ b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
@@ -30,6 +30,7 @@ extern const char *TestMainArgv0;
 namespace {
 
 const char *DwarfClang = "test-dwarf-clang.o";
+const char *DwarfClangUnspecParams = "test-dwarf-clang-unspec-params.elf";
 const char *DwarfGcc = "test-dwarf-gcc.o";
 
 // Helper function to get the first compile unit.
@@ -37,7 +38,7 @@ LVScopeCompileUnit *getFirstCompileUnit(LVScopeRoot *Root) {
   EXPECT_NE(Root, nullptr);
   const LVScopes *CompileUnits = Root->getScopes();
   EXPECT_NE(CompileUnits, nullptr);
-  EXPECT_EQ(CompileUnits->size(), 1u);
+  EXPECT_GT(CompileUnits->size(), 0u);
 
   LVScopes::const_iterator Iter = CompileUnits->begin();
   EXPECT_NE(Iter, nullptr);
@@ -124,6 +125,32 @@ void checkElementProperties(LVReader *Reader) {
   ASSERT_EQ(Lines->size(), 0x12u);
 }
 
+// Check proper handling of DW_AT_unspecified_parameters in
+// LVScope::addMissingElements().
+void checkUnspecifiedParameters(LVReader *Reader) {
+  LVScopeRoot *Root = Reader->getScopesRoot();
+  LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root);
+
+  EXPECT_EQ(Root->getFileFormatName(), "elf64-x86-64");
+  EXPECT_EQ(Root->getName(), DwarfClangUnspecParams);
+
+  const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
+  ASSERT_EQ(PublicNames.size(), 1u);
+
+  LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
+  LVScope *Function = (*IterNames).first;
+  EXPECT_EQ(Function->getName(), "foo_printf");
+  const LVElements *Elements = Function->getChildren();
+  ASSERT_NE(Elements, nullptr);
+  EXPECT_EQ(std::any_of(
+                Elements->begin(), Elements->end(),
+                [](const LVElement *elt) {
+                  return elt->getIsSymbol() &&
+                         static_cast<const LVSymbol *>(elt)->getIsUnspecified();
+                }),
+            true);
+}
+
 // Check the logical elements selection.
 void checkElementSelection(LVReader *Reader) {
   LVScopeRoot *Root = Reader->getScopesRoot();
@@ -253,6 +280,7 @@ void elementProperties(SmallString<128> &InputsDir) {
   ReaderOptions.setAttributePublics();
   ReaderOptions.setAttributeRange();
   ReaderOptions.setAttributeLocation();
+  ReaderOptions.setAttributeInserted();
   ReaderOptions.setPrintAll();
   ReaderOptions.resolveDependencies();
 
@@ -264,6 +292,9 @@ void elementProperties(SmallString<128> &InputsDir) {
   std::unique_ptr<LVReader> Reader =
       createReader(ReaderHandler, InputsDir, DwarfClang);
   checkElementProperties(Reader.get());
+
+  Reader = createReader(ReaderHandler, InputsDir, DwarfClangUnspecParams);
+  checkUnspecifiedParameters(Reader.get());
 }
 
 // Logical elements selection.
diff --git a/llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-unspec-params.elf b/llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-unspec-params.elf
new file mode 100755
index 0000000000000..67c6e71fbf7b9
Binary files /dev/null and b/llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-unspec-params.elf differ

``````````

</details>


https://github.com/llvm/llvm-project/pull/137221


More information about the llvm-commits mailing list