[llvm] 211ee04 - [llvm-debuginfo-analyzer] Fix a couple of unhandled DWARF situations leading to a crash (#137221)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 20 21:29:45 PDT 2025
Author: Javier Lopez-Gomez
Date: 2025-05-21T05:29:41+01:00
New Revision: 211ee04a616b0071adefe57015daf5702b0a09b4
URL: https://github.com/llvm/llvm-project/commit/211ee04a616b0071adefe57015daf5702b0a09b4
DIFF: https://github.com/llvm/llvm-project/commit/211ee04a616b0071adefe57015daf5702b0a09b4.diff
LOG: [llvm-debuginfo-analyzer] Fix a couple of unhandled DWARF situations leading to a crash (#137221)
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.
- 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.
Added:
llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-unspec-params.elf
Modified:
llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
index e1ea5da4dc51a..594b6816f14c5 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 cad53b8079e70..434709f076dc5 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
@@ -433,6 +433,15 @@ 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 createStringError(
+ errc::bad_address,
+ "Failed to parse instructions; offset beyond section size");
+ }
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..03bf394631c99 100644
--- a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
+++ b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp
@@ -30,6 +30,9 @@ extern const char *TestMainArgv0;
namespace {
const char *DwarfClang = "test-dwarf-clang.o";
+// Two compile units: one declares `extern int foo_printf(const char *, ...);`
+// and another one that defines the function.
+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 +40,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 +127,36 @@ 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);
+ // foo_printf is a variadic function whose prototype is
+ // `int foo_printf(const char *, ...)`, where the '...' is represented by a
+ // DW_TAG_unspecified_parameters, i.e. we expect to find at least one child
+ // for which getIsUnspecified() returns true.
+ 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 +286,7 @@ void elementProperties(SmallString<128> &InputsDir) {
ReaderOptions.setAttributePublics();
ReaderOptions.setAttributeRange();
ReaderOptions.setAttributeLocation();
+ ReaderOptions.setAttributeInserted();
ReaderOptions.setPrintAll();
ReaderOptions.resolveDependencies();
@@ -264,6 +298,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
diff er
More information about the llvm-commits
mailing list