https://github.com/felipepiovezan updated 
https://github.com/llvm/llvm-project/pull/172026

>From a19137b4d145ca3d7d91a148f926ae431d8b1fcc Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Thu, 11 Dec 2025 14:08:01 +0000
Subject: [PATCH 1/6] [lldb] Add ReadCStrings API to Process

This commit uses Process::ReadMemoryRanges to create an efficient method
for reading multiple strings at once. This method works like the
single-string version, reading 256 bytes at a time, but instead doing it
for _every_ string requested at the same time.
---
 lldb/include/lldb/API/SBProcess.h             |  3 +
 lldb/include/lldb/Target/Process.h            |  3 +
 lldb/source/API/SBProcess.cpp                 | 31 ++++++++++
 lldb/source/Target/Process.cpp                | 57 +++++++++++++++++++
 .../process/read_multiple_cstrings/Makefile   |  3 +
 .../TestReadMultipleStrings.py                | 46 +++++++++++++++
 .../process/read_multiple_cstrings/main.c     |  8 +++
 7 files changed, 151 insertions(+)
 create mode 100644 
lldb/test/API/python_api/process/read_multiple_cstrings/Makefile
 create mode 100644 
lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
 create mode 100644 
lldb/test/API/python_api/process/read_multiple_cstrings/main.c

diff --git a/lldb/include/lldb/API/SBProcess.h 
b/lldb/include/lldb/API/SBProcess.h
index 882b8bd837131..5f04d3330a1d1 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -205,6 +205,9 @@ class LLDB_API SBProcess {
   size_t ReadCStringFromMemory(addr_t addr, void *char_buf, size_t size,
                                lldb::SBError &error);
 
+  SBStringList ReadCStringsFromMemory(SBValueList string_addresses,
+                                      SBError &error);
+
   uint64_t ReadUnsignedFromMemory(addr_t addr, uint32_t byte_size,
                                   lldb::SBError &error);
 
diff --git a/lldb/include/lldb/Target/Process.h 
b/lldb/include/lldb/Target/Process.h
index 8e6c16cbfe0fc..4493e81ce0eae 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1680,6 +1680,9 @@ class Process : public 
std::enable_shared_from_this<Process>,
   size_t ReadCStringFromMemory(lldb::addr_t vm_addr, std::string &out_str,
                                Status &error);
 
+  llvm::SmallVector<std::optional<std::string>>
+  ReadCStringsFromMemory(llvm::ArrayRef<lldb::addr_t> addresses);
+
   /// Reads an unsigned integer of the specified byte size from process
   /// memory.
   ///
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 14aa9432eed83..1a83a3d164e53 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -876,6 +876,37 @@ lldb::addr_t SBProcess::FindInMemory(const void *buf, 
uint64_t size,
                                   range.ref(), alignment, error.ref());
 }
 
+SBStringList SBProcess::ReadCStringsFromMemory(SBValueList sb_string_addresses,
+                                               SBError &error) {
+  std::vector<lldb::addr_t> string_addresses;
+  string_addresses.reserve(sb_string_addresses.GetSize());
+
+  for (size_t idx = 0; idx < sb_string_addresses.GetSize(); idx++) {
+    SBValue sb_address = sb_string_addresses.GetValueAtIndex(idx);
+    string_addresses.push_back(sb_address.GetValueAsAddress());
+  }
+
+  ProcessSP process_sp(GetSP());
+  if (!process_sp) {
+    error = Status::FromErrorString("SBProcess is invalid");
+    return {};
+  }
+  Process::StopLocker stop_locker;
+  if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
+    error = Status::FromErrorString("process is running");
+    return {};
+  }
+
+  SBStringList strings;
+  llvm::SmallVector<std::optional<std::string>> maybe_strings =
+      process_sp->ReadCStringsFromMemory(string_addresses);
+
+  for (std::optional<std::string> maybe_str : maybe_strings)
+    strings.AppendString(maybe_str ? maybe_str->c_str() : "");
+
+  return strings;
+}
+
 size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len,
                              SBError &sb_error) {
   LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error);
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 9c8e8fa7041ee..3890a91dc4608 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -2135,6 +2135,63 @@ lldb::addr_t Process::FindInMemory(const uint8_t *buf, 
uint64_t size,
   return matches[0].GetBaseAddress().GetLoadAddress(&target);
 }
 
+llvm::SmallVector<std::optional<std::string>>
+Process::ReadCStringsFromMemory(llvm::ArrayRef<lldb::addr_t> addresses) {
+  // Make the same read width choice as ReadCStringFromMemory.
+  constexpr auto read_width = 256;
+
+  llvm::SmallVector<std::optional<std::string>> output_strs(addresses.size(),
+                                                            "");
+  llvm::SmallVector<Range<addr_t, size_t>> ranges{
+      llvm::map_range(addresses, [=](addr_t ptr) {
+        return Range<addr_t, size_t>(ptr, read_width);
+      })};
+
+  std::vector<uint8_t> buffer(read_width * addresses.size(), 0);
+  uint64_t num_completed_strings = 0;
+
+  while (num_completed_strings != addresses.size()) {
+    llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> read_results =
+        ReadMemoryRanges(ranges, buffer);
+
+    // Each iteration of this loop either increments num_completed_strings or
+    // updates the base pointer of some range, guaranteeing forward progress of
+    // the outer loop.
+    for (auto [range, read_result, output_str] :
+         llvm::zip(ranges, read_results, output_strs)) {
+      // A previously completed string.
+      if (range.GetByteSize() == 0)
+        continue;
+
+      // The read failed, set the range to 0 to avoid reading it again.
+      if (read_result.empty()) {
+        output_str = std::nullopt;
+        range.SetByteSize(0);
+        num_completed_strings++;
+        continue;
+      }
+
+      // Convert ArrayRef to StringRef so the pointers work with std::string.
+      auto read_result_str = llvm::toStringRef(read_result);
+
+      const char *null_terminator_pos = llvm::find(read_result_str, '\0');
+      output_str->append(read_result_str.begin(), null_terminator_pos);
+
+      // If the terminator was found, this string is complete.
+      if (null_terminator_pos != read_result_str.end()) {
+        range.SetByteSize(0);
+        num_completed_strings++;
+      }
+      // Otherwise increment the base pointer for the next read.
+      else {
+        range.SetRangeBase(range.GetRangeBase() + read_result.size());
+      }
+    }
+  }
+
+  return output_strs;
+}
+
 size_t Process::ReadCStringFromMemory(addr_t addr, std::string &out_str,
                                       Status &error) {
   char buf[256];
diff --git a/lldb/test/API/python_api/process/read_multiple_cstrings/Makefile 
b/lldb/test/API/python_api/process/read_multiple_cstrings/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/python_api/process/read_multiple_cstrings/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git 
a/lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
 
b/lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
new file mode 100644
index 0000000000000..75ecfb13d8b77
--- /dev/null
+++ 
b/lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
@@ -0,0 +1,46 @@
+"""Test reading c-strings from memory via SB API."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestReadMultipleStrings(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def test_read_multiple_strings(self):
+        """Test corner case behavior of SBProcess::ReadCStringFromMemory"""
+        self.build()
+
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "breakpoint here", lldb.SBFileSpec("main.c")
+        )
+
+        frame = thread.GetFrameAtIndex(0)
+        err = lldb.SBError()
+
+        empty_str_addr = frame.FindVariable("empty_string")
+        self.assertSuccess(err)
+        str1_addr = frame.FindVariable("str1")
+        self.assertSuccess(err)
+        banana_addr = frame.FindVariable("banana")
+        self.assertSuccess(err)
+        bad_addr = frame.FindVariable("bad_addr")
+        self.assertSuccess(err)
+
+        string_addresses = [empty_str_addr, str1_addr, banana_addr, bad_addr]
+        for addr in string_addresses:
+            self.assertNotEqual(addr.GetValueAsUnsigned(), 
lldb.LLDB_INVALID_ADDRESS)
+
+        addresses = lldb.SBValueList()
+        for addr in string_addresses:
+            addresses.Append(addr)
+
+        strings = process.ReadCStringsFromMemory(addresses, err)
+        self.assertSuccess(err)
+        self.assertEqual(strings.GetStringAtIndex(0), "")
+        self.assertEqual(strings.GetStringAtIndex(1), "1")
+        self.assertEqual(strings.GetStringAtIndex(2), "banana")
+        # invalid address will also return an empty string.
+        self.assertEqual(strings.GetStringAtIndex(3), "")
diff --git a/lldb/test/API/python_api/process/read_multiple_cstrings/main.c 
b/lldb/test/API/python_api/process/read_multiple_cstrings/main.c
new file mode 100644
index 0000000000000..d7affad6734da
--- /dev/null
+++ b/lldb/test/API/python_api/process/read_multiple_cstrings/main.c
@@ -0,0 +1,8 @@
+int main(int argc, char **argv) {
+  const char *empty_string = "";
+  const char *str1 = "1";
+  const char *banana = "banana";
+  const char *bad_addr = (char *)0x100;
+
+  return 0; // breakpoint here
+}

>From b3eb28ef9e6f7beb28ded0fc0d21b2368b3e3b76 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Sun, 14 Dec 2025 11:07:15 +0000
Subject: [PATCH 2/6] fixup! address review comments

---
 lldb/include/lldb/API/SBProcess.h | 11 +++++++++++
 lldb/source/Target/Process.cpp    | 11 +++++------
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/lldb/include/lldb/API/SBProcess.h 
b/lldb/include/lldb/API/SBProcess.h
index 5f04d3330a1d1..49fab59aec041 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -205,6 +205,17 @@ class LLDB_API SBProcess {
   size_t ReadCStringFromMemory(addr_t addr, void *char_buf, size_t size,
                                lldb::SBError &error);
 
+  /// Given a list of addresses, read one NULL-terminated string per address.
+  ///
+  /// \param [in] string_addresses
+  ///   The list of addresses to read from.
+  /// \param [in] error
+  ///   An error that gets populated if the process is not in a valid state.
+  ///
+  /// \return
+  ///   A list of strings read, which is guaranteed to contain as
+  ///   many strings as there are addresses in the input. If reading from an
+  ///   address fails, an empty string is returned for that address.
   SBStringList ReadCStringsFromMemory(SBValueList string_addresses,
                                       SBError &error);
 
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 3890a91dc4608..ab250941b183b 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -117,6 +117,8 @@ static constexpr OptionEnumValueElement 
g_follow_fork_mode_values[] = {
     },
 };
 
+static constexpr unsigned g_string_read_width = 256;
+
 #define LLDB_PROPERTIES_process
 #include "TargetProperties.inc"
 
@@ -2137,17 +2139,14 @@ lldb::addr_t Process::FindInMemory(const uint8_t *buf, 
uint64_t size,
 
 llvm::SmallVector<std::optional<std::string>>
 Process::ReadCStringsFromMemory(llvm::ArrayRef<lldb::addr_t> addresses) {
-  // Make the same read width choice as ReadCStringFromMemory.
-  constexpr auto read_width = 256;
-
   llvm::SmallVector<std::optional<std::string>> output_strs(addresses.size(),
                                                             "");
   llvm::SmallVector<Range<addr_t, size_t>> ranges{
       llvm::map_range(addresses, [=](addr_t ptr) {
-        return Range<addr_t, size_t>(ptr, read_width);
+        return Range<addr_t, size_t>(ptr, g_string_read_width);
       })};
 
-  std::vector<uint8_t> buffer(read_width * addresses.size(), 0);
+  std::vector<uint8_t> buffer(g_string_read_width * addresses.size(), 0);
   uint64_t num_completed_strings = 0;
 
   while (num_completed_strings != addresses.size()) {
@@ -2194,7 +2193,7 @@ 
Process::ReadCStringsFromMemory(llvm::ArrayRef<lldb::addr_t> addresses) {
 
 size_t Process::ReadCStringFromMemory(addr_t addr, std::string &out_str,
                                       Status &error) {
-  char buf[256];
+  char buf[g_string_read_width];
   out_str.clear();
   addr_t curr_addr = addr;
   while (true) {

>From 6716c871423a1ed33263da81acf14f1173a5a552 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Thu, 18 Dec 2025 12:40:42 +0000
Subject: [PATCH 3/6] fixup! remove all changes from SBAPI

---
 lldb/include/lldb/API/SBProcess.h             | 14 ----
 lldb/source/API/SBProcess.cpp                 | 31 ---------
 .../process/read_multiple_cstrings/Makefile   |  3 -
 .../TestReadMultipleStrings.py                | 46 -------------
 .../process/read_multiple_cstrings/main.c     |  8 ---
 lldb/unittests/Target/MemoryTest.cpp          | 66 +++++++++++++++++++
 6 files changed, 66 insertions(+), 102 deletions(-)
 delete mode 100644 
lldb/test/API/python_api/process/read_multiple_cstrings/Makefile
 delete mode 100644 
lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
 delete mode 100644 
lldb/test/API/python_api/process/read_multiple_cstrings/main.c

diff --git a/lldb/include/lldb/API/SBProcess.h 
b/lldb/include/lldb/API/SBProcess.h
index 49fab59aec041..882b8bd837131 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -205,20 +205,6 @@ class LLDB_API SBProcess {
   size_t ReadCStringFromMemory(addr_t addr, void *char_buf, size_t size,
                                lldb::SBError &error);
 
-  /// Given a list of addresses, read one NULL-terminated string per address.
-  ///
-  /// \param [in] string_addresses
-  ///   The list of addresses to read from.
-  /// \param [in] error
-  ///   An error that gets populated if the process is not in a valid state.
-  ///
-  /// \return
-  ///   A list of strings read, which is guaranteed to contain as
-  ///   many strings as there are addresses in the input. If reading from an
-  ///   address fails, an empty string is returned for that address.
-  SBStringList ReadCStringsFromMemory(SBValueList string_addresses,
-                                      SBError &error);
-
   uint64_t ReadUnsignedFromMemory(addr_t addr, uint32_t byte_size,
                                   lldb::SBError &error);
 
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 1a83a3d164e53..14aa9432eed83 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -876,37 +876,6 @@ lldb::addr_t SBProcess::FindInMemory(const void *buf, 
uint64_t size,
                                   range.ref(), alignment, error.ref());
 }
 
-SBStringList SBProcess::ReadCStringsFromMemory(SBValueList sb_string_addresses,
-                                               SBError &error) {
-  std::vector<lldb::addr_t> string_addresses;
-  string_addresses.reserve(sb_string_addresses.GetSize());
-
-  for (size_t idx = 0; idx < sb_string_addresses.GetSize(); idx++) {
-    SBValue sb_address = sb_string_addresses.GetValueAtIndex(idx);
-    string_addresses.push_back(sb_address.GetValueAsAddress());
-  }
-
-  ProcessSP process_sp(GetSP());
-  if (!process_sp) {
-    error = Status::FromErrorString("SBProcess is invalid");
-    return {};
-  }
-  Process::StopLocker stop_locker;
-  if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
-    error = Status::FromErrorString("process is running");
-    return {};
-  }
-
-  SBStringList strings;
-  llvm::SmallVector<std::optional<std::string>> maybe_strings =
-      process_sp->ReadCStringsFromMemory(string_addresses);
-
-  for (std::optional<std::string> maybe_str : maybe_strings)
-    strings.AppendString(maybe_str ? maybe_str->c_str() : "");
-
-  return strings;
-}
-
 size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len,
                              SBError &sb_error) {
   LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error);
diff --git a/lldb/test/API/python_api/process/read_multiple_cstrings/Makefile 
b/lldb/test/API/python_api/process/read_multiple_cstrings/Makefile
deleted file mode 100644
index 10495940055b6..0000000000000
--- a/lldb/test/API/python_api/process/read_multiple_cstrings/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-C_SOURCES := main.c
-
-include Makefile.rules
diff --git 
a/lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
 
b/lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
deleted file mode 100644
index 75ecfb13d8b77..0000000000000
--- 
a/lldb/test/API/python_api/process/read_multiple_cstrings/TestReadMultipleStrings.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""Test reading c-strings from memory via SB API."""
-
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestReadMultipleStrings(TestBase):
-    NO_DEBUG_INFO_TESTCASE = True
-
-    def test_read_multiple_strings(self):
-        """Test corner case behavior of SBProcess::ReadCStringFromMemory"""
-        self.build()
-
-        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
-            self, "breakpoint here", lldb.SBFileSpec("main.c")
-        )
-
-        frame = thread.GetFrameAtIndex(0)
-        err = lldb.SBError()
-
-        empty_str_addr = frame.FindVariable("empty_string")
-        self.assertSuccess(err)
-        str1_addr = frame.FindVariable("str1")
-        self.assertSuccess(err)
-        banana_addr = frame.FindVariable("banana")
-        self.assertSuccess(err)
-        bad_addr = frame.FindVariable("bad_addr")
-        self.assertSuccess(err)
-
-        string_addresses = [empty_str_addr, str1_addr, banana_addr, bad_addr]
-        for addr in string_addresses:
-            self.assertNotEqual(addr.GetValueAsUnsigned(), 
lldb.LLDB_INVALID_ADDRESS)
-
-        addresses = lldb.SBValueList()
-        for addr in string_addresses:
-            addresses.Append(addr)
-
-        strings = process.ReadCStringsFromMemory(addresses, err)
-        self.assertSuccess(err)
-        self.assertEqual(strings.GetStringAtIndex(0), "")
-        self.assertEqual(strings.GetStringAtIndex(1), "1")
-        self.assertEqual(strings.GetStringAtIndex(2), "banana")
-        # invalid address will also return an empty string.
-        self.assertEqual(strings.GetStringAtIndex(3), "")
diff --git a/lldb/test/API/python_api/process/read_multiple_cstrings/main.c 
b/lldb/test/API/python_api/process/read_multiple_cstrings/main.c
deleted file mode 100644
index d7affad6734da..0000000000000
--- a/lldb/test/API/python_api/process/read_multiple_cstrings/main.c
+++ /dev/null
@@ -1,8 +0,0 @@
-int main(int argc, char **argv) {
-  const char *empty_string = "";
-  const char *str1 = "1";
-  const char *banana = "banana";
-  const char *bad_addr = (char *)0x100;
-
-  return 0; // breakpoint here
-}
diff --git a/lldb/unittests/Target/MemoryTest.cpp 
b/lldb/unittests/Target/MemoryTest.cpp
index 131a3cabdd896..3ba5f8259c024 100644
--- a/lldb/unittests/Target/MemoryTest.cpp
+++ b/lldb/unittests/Target/MemoryTest.cpp
@@ -434,3 +434,69 @@ TEST_F(MemoryDeathTest, 
TestReadMemoryRangesWithShortBuffer) {
     ASSERT_TRUE(result.empty());
 #endif
 }
+
+/// A process class whose memory contains the following map of addresses to
+/// strings:
+///   100 -> "hello\0"
+///   200 -> "\0"
+///   201 -> "goodbye"
+///   300 -> a string composed of 500 'c' characters, followed by '\0'.
+class StringReaderProcess : public Process {
+public:
+  char memory[1024];
+  void initialize_memory() {
+    // Use some easily identifiable character for the areas of memory we're not
+    // intending to read.
+    memset(memory, '?', 1024);
+    strcpy(&memory[100], "hello");
+    strcpy(&memory[200], "");
+    strcpy(&memory[201], "goodbye");
+    std::vector<char> long_str(500, 'c');
+    long_str.push_back('\0');
+    strcpy(&memory[300], long_str.data());
+  }
+
+  size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+                      Status &error) override {
+    memcpy(buf, memory+vm_addr, size);
+    return size;
+  }
+  StringReaderProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
+      : Process(target_sp, listener_sp) {
+    initialize_memory();
+  }
+  // Boilerplate, nothing interesting below.
+  bool CanDebug(lldb::TargetSP, bool) override { return true; }
+  Status DoDestroy() override { return {}; }
+  void RefreshStateAfterStop() override {}
+  bool DoUpdateThreadList(ThreadList &, ThreadList &) override { return false; 
}
+  llvm::StringRef GetPluginName() override { return "Dummy"; }
+};
+
+TEST_F(MemoryTest, TestReadCStringsFromMemory) {
+  ArchSpec arch("x86_64-apple-macosx-");
+  Platform::SetHostPlatform(PlatformRemoteMacOSX::CreateInstance(true, &arch));
+  DebuggerSP debugger_sp = Debugger::CreateInstance();
+  ASSERT_TRUE(debugger_sp);
+  TargetSP target_sp = CreateTarget(debugger_sp, arch);
+  ASSERT_TRUE(target_sp);
+  ListenerSP listener_sp(Listener::MakeListener("dummy"));
+  ProcessSP process_sp =
+      std::make_shared<StringReaderProcess>(target_sp, listener_sp);
+  ASSERT_TRUE(process_sp);
+
+  // See the docs for StringReaderProcess above for an explanation of these
+  // addresses.
+  llvm::SmallVector<std::optional<std::string>> maybe_strings =
+      process_sp->ReadCStringsFromMemory({100, 200, 201, 300});
+
+  std::vector<char> long_str(500, 'c');
+  long_str.push_back('\0');
+  std::string big_str(long_str.data());
+
+  const std::string expected_answers[4] = {"hello", "", "goodbye", big_str};
+  for (auto [maybe_str, expected_answer] : llvm::zip(maybe_strings, 
expected_answers)) {
+    EXPECT_TRUE(maybe_str);
+    EXPECT_EQ(*maybe_str, expected_answer);
+  }
+}

>From f5403aa9cd431f252d0202cd1eb5076c8abae6b3 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Thu, 18 Dec 2025 12:44:00 +0000
Subject: [PATCH 4/6] fixup! clang-format

---
 lldb/unittests/Target/MemoryTest.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lldb/unittests/Target/MemoryTest.cpp 
b/lldb/unittests/Target/MemoryTest.cpp
index 3ba5f8259c024..53783b9286d22 100644
--- a/lldb/unittests/Target/MemoryTest.cpp
+++ b/lldb/unittests/Target/MemoryTest.cpp
@@ -458,7 +458,7 @@ class StringReaderProcess : public Process {
 
   size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
                       Status &error) override {
-    memcpy(buf, memory+vm_addr, size);
+    memcpy(buf, memory + vm_addr, size);
     return size;
   }
   StringReaderProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
@@ -495,7 +495,8 @@ TEST_F(MemoryTest, TestReadCStringsFromMemory) {
   std::string big_str(long_str.data());
 
   const std::string expected_answers[4] = {"hello", "", "goodbye", big_str};
-  for (auto [maybe_str, expected_answer] : llvm::zip(maybe_strings, 
expected_answers)) {
+  for (auto [maybe_str, expected_answer] :
+       llvm::zip(maybe_strings, expected_answers)) {
     EXPECT_TRUE(maybe_str);
     EXPECT_EQ(*maybe_str, expected_answer);
   }

>From 9dcf8791d726d72be4f8b2b63ee72281dfa1b9de Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Thu, 18 Dec 2025 15:55:44 +0000
Subject: [PATCH 5/6] fixup! Add test for the error case

---
 lldb/unittests/Target/MemoryTest.cpp | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/lldb/unittests/Target/MemoryTest.cpp 
b/lldb/unittests/Target/MemoryTest.cpp
index 53783b9286d22..5703213202495 100644
--- a/lldb/unittests/Target/MemoryTest.cpp
+++ b/lldb/unittests/Target/MemoryTest.cpp
@@ -441,6 +441,7 @@ TEST_F(MemoryDeathTest, 
TestReadMemoryRangesWithShortBuffer) {
 ///   200 -> "\0"
 ///   201 -> "goodbye"
 ///   300 -> a string composed of 500 'c' characters, followed by '\0'.
+///   addresses >= 1024 -> error
 class StringReaderProcess : public Process {
 public:
   char memory[1024];
@@ -458,6 +459,10 @@ class StringReaderProcess : public Process {
 
   size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
                       Status &error) override {
+    if (vm_addr >= 1024) {
+      error = Status::FromErrorString("out of bounds!");
+      return 0;
+    }
     memcpy(buf, memory + vm_addr, size);
     return size;
   }
@@ -488,7 +493,9 @@ TEST_F(MemoryTest, TestReadCStringsFromMemory) {
   // See the docs for StringReaderProcess above for an explanation of these
   // addresses.
   llvm::SmallVector<std::optional<std::string>> maybe_strings =
-      process_sp->ReadCStringsFromMemory({100, 200, 201, 300});
+      process_sp->ReadCStringsFromMemory({100, 200, 201, 300, 0xffffff});
+  ASSERT_EQ(maybe_strings.size(), 5);
+  auto expected_valid_strings = llvm::ArrayRef(maybe_strings).take_front(4);
 
   std::vector<char> long_str(500, 'c');
   long_str.push_back('\0');
@@ -496,8 +503,11 @@ TEST_F(MemoryTest, TestReadCStringsFromMemory) {
 
   const std::string expected_answers[4] = {"hello", "", "goodbye", big_str};
   for (auto [maybe_str, expected_answer] :
-       llvm::zip(maybe_strings, expected_answers)) {
+       llvm::zip(expected_valid_strings, expected_answers)) {
     EXPECT_TRUE(maybe_str);
     EXPECT_EQ(*maybe_str, expected_answer);
   }
+
+  // The last address should have produced an error.
+  EXPECT_FALSE(maybe_strings.back());
 }

>From ce4de361a9763aeeec6c08e1d812a4154a665e33 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Thu, 18 Dec 2025 16:07:03 +0000
Subject: [PATCH 6/6] fixup! Fix unsigned vs signed comparison in test

---
 lldb/unittests/Target/MemoryTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/unittests/Target/MemoryTest.cpp 
b/lldb/unittests/Target/MemoryTest.cpp
index 5703213202495..c972a5008cb03 100644
--- a/lldb/unittests/Target/MemoryTest.cpp
+++ b/lldb/unittests/Target/MemoryTest.cpp
@@ -494,7 +494,7 @@ TEST_F(MemoryTest, TestReadCStringsFromMemory) {
   // addresses.
   llvm::SmallVector<std::optional<std::string>> maybe_strings =
       process_sp->ReadCStringsFromMemory({100, 200, 201, 300, 0xffffff});
-  ASSERT_EQ(maybe_strings.size(), 5);
+  ASSERT_EQ(maybe_strings.size(), 5ull);
   auto expected_valid_strings = llvm::ArrayRef(maybe_strings).take_front(4);
 
   std::vector<char> long_str(500, 'c');

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to