[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