https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/135944
>From 28ffd29ac558c8eb3ec8b3305480f237c822b4fd Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Wed, 16 Apr 2025 11:46:29 +0200 Subject: [PATCH 1/2] [lldb][DataFormatter] Surface CalculateNumChildren errors in std::vector summary When the data-formatters happen to break (e.g., due to layout changes in libc++), there's no clear indicator of them failing from a user's perspective. We just show: ``` (std::vector<int>) v = size=0 {} ``` which is highly misleading, especially if `v.size()` returns a non-zero size. This patch surfaces the various errors that could occur when calculating the number of children of a vector. --- .../Language/CPlusPlus/LibCxxVector.cpp | 21 ++++++++--- lldb/source/ValueObject/ValueObject.cpp | 12 +++++-- .../libcxx-simulators/invalid-vector/Makefile | 3 ++ ...taFormatterLibcxxInvalidVectorSimulator.py | 35 +++++++++++++++++++ .../libcxx-simulators/invalid-vector/main.cpp | 26 ++++++++++++++ 5 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/Makefile create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py create mode 100644 lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index d538cac9f9134..ce2261b6f03c3 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -83,19 +83,30 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd:: llvm::Expected<uint32_t> lldb_private::formatters:: LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren() { if (!m_start || !m_finish) - return 0; + return llvm::createStringError( + "Failed to determine start/end of vector data."); + uint64_t start_val = m_start->GetValueAsUnsigned(0); uint64_t finish_val = m_finish->GetValueAsUnsigned(0); - if (start_val == 0 || finish_val == 0) + // A default-initialized empty vector. + if (start_val == 0 && finish_val == 0) return 0; - if (start_val >= finish_val) - return 0; + if (start_val == 0) + return llvm::createStringError("Invalid value for start of vector."); + + if (finish_val == 0) + return llvm::createStringError("Invalid value for end of vector."); + + if (start_val > finish_val) + return llvm::createStringError( + "Start of vector data begins after end pointer."); size_t num_children = (finish_val - start_val); if (num_children % m_element_size) - return 0; + return llvm::createStringError("Size not multiple of element size."); + return num_children / m_element_size; } diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp index eac24353de90b..8741cb7343166 100644 --- a/lldb/source/ValueObject/ValueObject.cpp +++ b/lldb/source/ValueObject/ValueObject.cpp @@ -1521,10 +1521,16 @@ bool ValueObject::DumpPrintableRepresentation( str = GetLocationAsCString(); break; - case eValueObjectRepresentationStyleChildrenCount: - strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors()); - str = strm.GetString(); + case eValueObjectRepresentationStyleChildrenCount: { + if (auto err = GetNumChildren()) { + strm.Printf("%" PRIu32, *err); + str = strm.GetString(); + } else { + strm << "error: " << toString(err.takeError()); + str = strm.GetString(); + } break; + } case eValueObjectRepresentationStyleType: str = GetTypeName().GetStringRef(); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/Makefile new file mode 100644 index 0000000000000..38cfa81053488 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +override CXXFLAGS_EXTRAS += -std=c++14 +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py new file mode 100644 index 0000000000000..6986d71c37a8b --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py @@ -0,0 +1,35 @@ +""" +Test we can understand various layouts of the libc++'s std::string +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import functools + + +class LibcxxInvalidVectorDataFormatterSimulatorTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "return 0", lldb.SBFileSpec("main.cpp")) + + self.expect( + "frame variable v1", + substrs=["size=error: Invalid value for end of vector."], + ) + self.expect( + "frame variable v2", + substrs=["size=error: Invalid value for start of vector."], + ) + self.expect( + "frame variable v3", + substrs=["size=error: Start of vector data begins after end pointer."], + ) + self.expect( + "frame variable v4", + substrs=["size=error: Failed to determine start/end of vector data."], + ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp new file mode 100644 index 0000000000000..c1b9b6724787b --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp @@ -0,0 +1,26 @@ +#define COMPRESSED_PAIR_REV 2 +#include <libcxx-simulators-common/compressed_pair.h> + +namespace std { +namespace __1 { +template <typename T> struct vector { + T *__begin_; + T *__end_; + _LLDB_COMPRESSED_PAIR(T *, __cap_ = nullptr, void *, __alloc_); +}; +} // namespace __1 + +namespace __2 { +template <typename T> struct vector {}; +} // namespace __2 +} // namespace std + +int main() { + int arr[] = {1, 2, 3}; + std::__1::vector<int> v1{.__begin_ = arr, .__end_ = nullptr}; + std::__1::vector<int> v2{.__begin_ = nullptr, .__end_ = arr}; + std::__1::vector<int> v3{.__begin_ = &arr[3], .__end_ = arr}; + std::__2::vector<int> v4; + + return 0; +} >From b5b1b76bb0258d22fed1967f96d60f4adfbf9d4a Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Wed, 16 Apr 2025 13:17:18 +0200 Subject: [PATCH 2/2] fixup! add another test-case --- ...TestDataFormatterLibcxxInvalidVectorSimulator.py | 4 ++++ .../libcxx-simulators/invalid-vector/main.cpp | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py index 6986d71c37a8b..8788ea7be882d 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py @@ -33,3 +33,7 @@ def test(self): "frame variable v4", substrs=["size=error: Failed to determine start/end of vector data."], ) + self.expect( + "frame variable v5", + substrs=["size=error: Size not multiple of element size."], + ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp index c1b9b6724787b..b8f0eccf0057b 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp @@ -13,14 +13,25 @@ template <typename T> struct vector { namespace __2 { template <typename T> struct vector {}; } // namespace __2 + +namespace __3 { +template <typename T> struct vector { + T *__begin_; + T *__end_; + _LLDB_COMPRESSED_PAIR(short *, __cap_ = nullptr, void *, __alloc_); +}; +} // namespace __3 } // namespace std int main() { int arr[] = {1, 2, 3}; std::__1::vector<int> v1{.__begin_ = arr, .__end_ = nullptr}; std::__1::vector<int> v2{.__begin_ = nullptr, .__end_ = arr}; - std::__1::vector<int> v3{.__begin_ = &arr[3], .__end_ = arr}; + std::__1::vector<int> v3{.__begin_ = &arr[2], .__end_ = arr}; std::__2::vector<int> v4; + char carr[] = {'a'}; + std::__3::vector<char> v5{.__begin_=carr, .__end_=carr + 1}; + return 0; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits