[Lldb-commits] [lldb] [lldb] Limit formatter-section extractor range (PR #140139)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Feb 12 07:41:44 PST 2026
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/140139
>From d81a2def0f2b66b42f0e2569b3871fc682aa085c Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Thu, 15 May 2025 22:43:49 +0200
Subject: [PATCH 1/4] [lldb] Limit formatter-section extractor range
---
lldb/source/DataFormatters/FormatterSection.cpp | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/lldb/source/DataFormatters/FormatterSection.cpp b/lldb/source/DataFormatters/FormatterSection.cpp
index 1de633f4998e0..72979ac1923e8 100644
--- a/lldb/source/DataFormatters/FormatterSection.cpp
+++ b/lldb/source/DataFormatters/FormatterSection.cpp
@@ -57,11 +57,15 @@ static void ForEachFormatterInModule(
cursor.seek(cursor.tell() - 1);
break;
}
+ if (!cursor || cursor.tell() >= section_size)
+ break;
+
uint64_t version = section.getULEB128(cursor);
uint64_t record_size = section.getULEB128(cursor);
if (version == 1) {
- llvm::DataExtractor record(section.getData().drop_front(cursor.tell()),
- le, addr_size);
+ llvm::DataExtractor record(
+ section.getData().drop_front(cursor.tell()).take_front(record_size),
+ le, addr_size);
llvm::DataExtractor::Cursor cursor(0);
uint64_t type_size = record.getULEB128(cursor);
llvm::StringRef type_name = record.getBytes(cursor, type_size);
>From 95636b5d80232e980a18047155562ba672f4e2d2 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 28 Jan 2026 20:57:50 +0100
Subject: [PATCH 2/4] Add test
---
lldb/unittests/DataFormatter/CMakeLists.txt | 6 +
.../DataFormatter/FormatterSectionTest.cpp | 143 ++++++++++++++++++
2 files changed, 149 insertions(+)
create mode 100644 lldb/unittests/DataFormatter/FormatterSectionTest.cpp
diff --git a/lldb/unittests/DataFormatter/CMakeLists.txt b/lldb/unittests/DataFormatter/CMakeLists.txt
index 3126a285ab5ac..df9a04bb8773f 100644
--- a/lldb/unittests/DataFormatter/CMakeLists.txt
+++ b/lldb/unittests/DataFormatter/CMakeLists.txt
@@ -2,6 +2,7 @@ add_lldb_unittest(LLDBFormatterTests
FormatManagerTests.cpp
FormattersContainerTest.cpp
FormatterBytecodeTest.cpp
+ FormatterSectionTest.cpp
StringPrinterTests.cpp
LINK_COMPONENTS
@@ -9,7 +10,12 @@ add_lldb_unittest(LLDBFormatterTests
LINK_LIBS
lldbCore
lldbInterpreter
+ lldbPluginObjectFileELF
+ lldbPluginPlatformLinux
+ lldbPluginSymbolFileSymtab
lldbSymbol
lldbTarget
lldbUtility
+ lldbUtilityHelpers
+ LLVMTestingSupport
)
diff --git a/lldb/unittests/DataFormatter/FormatterSectionTest.cpp b/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
new file mode 100644
index 0000000000000..4b088fef184f3
--- /dev/null
+++ b/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/FormatterSection.h"
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "Plugins/Platform/Linux/PlatformLinux.h"
+#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
+#include "TestingSupport/SubsystemRAII.h"
+#include "TestingSupport/TestUtilities.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/ValueObject/ValueObjectConstResult.h"
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+struct MockProcess : Process {
+ MockProcess(TargetSP target_sp, ListenerSP listener_sp)
+ : Process(target_sp, listener_sp) {}
+
+ llvm::StringRef GetPluginName() override { return "mock process"; }
+
+ bool CanDebug(TargetSP target, bool plugin_specified_by_name) override {
+ return false;
+ };
+
+ Status DoDestroy() override { return {}; }
+
+ void RefreshStateAfterStop() override {}
+
+ bool DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) override {
+ return false;
+ };
+
+ size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,
+ Status &error) override {
+ return 0;
+ }
+};
+
+class FormatterSectionTest : public ::testing::Test {
+public:
+ void SetUp() override {
+ ArchSpec arch("x86_64-pc-linux");
+ Platform::SetHostPlatform(
+ platform_linux::PlatformLinux::CreateInstance(true, &arch));
+ m_debugger_sp = Debugger::CreateInstance();
+ ASSERT_TRUE(m_debugger_sp);
+ m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,
+ eLoadDependentsNo,
+ m_platform_sp, m_target_sp);
+ ASSERT_TRUE(m_target_sp);
+ ASSERT_TRUE(m_target_sp->GetArchitecture().IsValid());
+ ASSERT_TRUE(m_platform_sp);
+ m_listener_sp = Listener::MakeListener("dummy");
+ m_process_sp = std::make_shared<MockProcess>(m_target_sp, m_listener_sp);
+ ASSERT_TRUE(m_process_sp);
+ m_exe_ctx = ExecutionContext(m_process_sp);
+ }
+
+ ExecutionContext m_exe_ctx;
+ TypeSystemClang *m_type_system;
+ lldb::TargetSP m_target_sp;
+
+private:
+ SubsystemRAII<FileSystem, HostInfo, ObjectFileELF,
+ platform_linux::PlatformLinux, SymbolFileSymtab>
+ m_subsystems;
+
+ lldb::DebuggerSP m_debugger_sp;
+ lldb::PlatformSP m_platform_sp;
+ lldb::ListenerSP m_listener_sp;
+ lldb::ProcessSP m_process_sp;
+};
+
+} // namespace
+
+/// Test that multiple formatters can be loaded
+TEST_F(FormatterSectionTest, LoadFormattersForModule) {
+ auto ExpectedFile = TestFile::fromYaml(R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+Sections:
+ - Name: .lldbformatters
+ Type: SHT_PROGBITS
+ Flags: [ ]
+ Address: 0x2010
+ AddressAlign: 0x10
+ # Two summaries for "Point" and "Rect" that return "AAAAA" and "BBBBB" respectively
+ Content: 011205506F696E74000009012205414141414113000000000111045265637400000901220542424242421300000000
+ Size: 256
+...
+)");
+ ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
+
+ auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());
+
+ LoadFormattersForModule(module_sp);
+
+ TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(ConstString("default"), category);
+ ASSERT_TRUE(category != nullptr);
+
+ ASSERT_EQ(category->GetCount(), 2);
+
+ TypeSummaryImplSP point_summary_sp =
+ category->GetSummaryForType(std::make_shared<TypeNameSpecifierImpl>(
+ "Point", lldb::eFormatterMatchExact));
+ ASSERT_TRUE(point_summary_sp != nullptr);
+
+ TypeSummaryImplSP rect_summary_sp =
+ category->GetSummaryForType(std::make_shared<TypeNameSpecifierImpl>(
+ "Rect", lldb::eFormatterMatchExact));
+ ASSERT_TRUE(rect_summary_sp != nullptr);
+
+ std::string dest;
+ ValueObjectSP valobj = ValueObjectConstResult::CreateValueObjectFromBool(
+ m_target_sp, false, "mock");
+ ASSERT_TRUE(
+ point_summary_sp->FormatObject(valobj.get(), dest, TypeSummaryOptions()));
+ ASSERT_EQ(dest, "AAAAA");
+ dest.clear();
+ ASSERT_TRUE(
+ rect_summary_sp->FormatObject(valobj.get(), dest, TypeSummaryOptions()));
+ ASSERT_EQ(dest, "BBBBB");
+}
>From 02eed4d5593dfdc9f1ed958e3deaf52926d0ef3c Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 28 Jan 2026 21:06:33 +0100
Subject: [PATCH 3/4] fix: unsigned
---
lldb/unittests/DataFormatter/FormatterSectionTest.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/unittests/DataFormatter/FormatterSectionTest.cpp b/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
index 4b088fef184f3..344b299023d03 100644
--- a/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
+++ b/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
@@ -118,7 +118,7 @@ TEST_F(FormatterSectionTest, LoadFormattersForModule) {
DataVisualization::Categories::GetCategory(ConstString("default"), category);
ASSERT_TRUE(category != nullptr);
- ASSERT_EQ(category->GetCount(), 2);
+ ASSERT_EQ(category->GetCount(), 2u);
TypeSummaryImplSP point_summary_sp =
category->GetSummaryForType(std::make_shared<TypeNameSpecifierImpl>(
>From f01375972009fc230b415335e0a28b4187b8f447 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Thu, 12 Feb 2026 16:41:26 +0100
Subject: [PATCH 4/4] fix: move padding loop out
---
.../DataFormatters/FormatterSection.cpp | 23 ++++++++++++-------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/lldb/source/DataFormatters/FormatterSection.cpp b/lldb/source/DataFormatters/FormatterSection.cpp
index 72979ac1923e8..8534b7b0a81c1 100644
--- a/lldb/source/DataFormatters/FormatterSection.cpp
+++ b/lldb/source/DataFormatters/FormatterSection.cpp
@@ -14,6 +14,20 @@
using namespace lldb;
namespace lldb_private {
+
+static bool skipPadding(llvm::DataExtractor §ion,
+ llvm::DataExtractor::Cursor &cursor) {
+ while (!section.eof(cursor)) {
+ if (section.getU8(cursor) == 0)
+ continue;
+
+ cursor.seek(cursor.tell() - 1);
+ return true;
+ }
+
+ return false; // reached EOF
+}
+
static void ForEachFormatterInModule(
Module &module, SectionType section_type,
std::function<void(llvm::DataExtractor, llvm::StringRef)> fn) {
@@ -50,14 +64,7 @@ static void ForEachFormatterInModule(
uint8_t addr_size = section.getAddressSize();
llvm::DataExtractor::Cursor cursor(0);
while (cursor && cursor.tell() < section_size) {
- while (cursor && cursor.tell() < section_size) {
- // Skip over 0 padding.
- if (section.getU8(cursor) == 0)
- continue;
- cursor.seek(cursor.tell() - 1);
- break;
- }
- if (!cursor || cursor.tell() >= section_size)
+ if (!skipPadding(section, cursor))
break;
uint64_t version = section.getULEB128(cursor);
More information about the lldb-commits
mailing list