[Lldb-commits] [lldb] [LLDB] Process minidump is in memory check command (PR #149401)
Jacob Lalonde via lldb-commits
lldb-commits at lists.llvm.org
Fri Jul 18 13:34:56 PDT 2025
https://github.com/Jlalond updated https://github.com/llvm/llvm-project/pull/149401
>From 4e692b251329196ff09aa8fc7d0e329c42df1b50 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Wed, 16 Jul 2025 12:57:58 -0700
Subject: [PATCH 1/4] Add check-memory command to see if an address is in a
Minidump
---
lldb/include/lldb/Target/MemoryRegionInfo.h | 30 +++++++
lldb/include/lldb/Utility/RangeMap.h | 21 +++++
.../Process/minidump/MinidumpParser.cpp | 22 ++++++
.../Plugins/Process/minidump/MinidumpParser.h | 5 ++
.../Process/minidump/ProcessMinidump.cpp | 79 +++++++++++++++++++
.../Process/minidump/ProcessMinidump.h | 4 +
6 files changed, 161 insertions(+)
diff --git a/lldb/include/lldb/Target/MemoryRegionInfo.h b/lldb/include/lldb/Target/MemoryRegionInfo.h
index dc37a7dbeda52..ad254084a40d3 100644
--- a/lldb/include/lldb/Target/MemoryRegionInfo.h
+++ b/lldb/include/lldb/Target/MemoryRegionInfo.h
@@ -14,6 +14,7 @@
#include <vector>
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/RangeMap.h"
#include "llvm/Support/FormatProviders.h"
@@ -141,6 +142,35 @@ class MemoryRegionInfo {
m_dirty_pages = std::move(pagelist);
}
+ std::string Dump() const {
+ lldb_private::StreamString stream;
+ stream << "[";
+ stream.PutHex64(GetRange().GetRangeBase());
+ stream << "-";
+ stream.PutHex64(GetRange().GetRangeEnd());
+ stream << ") ";
+ if (m_read == eYes)
+ stream << "r";
+ else if (m_read == eNo)
+ stream << "-";
+ else
+ stream << "?";
+ if (m_write == eYes)
+ stream << "w";
+ else if (m_write == eNo)
+ stream << "-";
+ else
+ stream << "?";
+ if (m_execute == eYes)
+ stream << "x";
+ else if (m_execute == eNo)
+ stream << "-";
+ else
+ stream << "?";
+
+ return stream.GetString().str();
+ }
+
protected:
RangeType m_range;
OptionalBool m_read = eDontKnow;
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index e701ae1ba96c8..5bb3d67309cbd 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -648,6 +648,27 @@ class RangeDataVector {
return nullptr;
}
+ const Entry *FindEntryThatContainsOrPrior(B addr) const {
+#ifdef ASSERT_RANGEMAP_ARE_SORTED
+ assert(IsSorted());
+#endif
+ if (!m_entries.empty()) {
+ typename Collection::const_iterator begin = m_entries.begin();
+ typename Collection::const_iterator end = m_entries.end();
+ typename Collection::const_iterator pos = llvm::lower_bound(
+ m_entries, addr, [](const Entry &lhs, B rhs_base) -> bool {
+ return lhs.GetRangeEnd() <= rhs_base;
+ });
+
+ while (pos != begin && pos[-1].Contains(addr))
+ ++pos;
+
+ if (pos != end)
+ return &(*pos);
+ }
+ return nullptr;
+ }
+
uint32_t FindEntryIndexThatContainsOrFollows(B addr) const {
#ifdef ASSERT_RANGEMAP_ARE_SORTED
assert(IsSorted());
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 58ebb7be11994..a81213ed858c8 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -711,3 +711,25 @@ MinidumpParser::GetMemoryRegionInfo(const MemoryRegionInfos ®ions,
region.SetMapped(MemoryRegionInfo::eNo);
return region;
}
+
+std::optional<minidump::Range> MinidumpParser::GetClosestPriorRegion(lldb::addr_t load_addr) {
+ if (m_memory_ranges.IsEmpty())
+ PopulateMemoryRanges();
+
+ const MemoryRangeVector::Entry *entry = m_memory_ranges.FindEntryThatContainsOrPrior(load_addr);
+ if (!entry)
+ return std::nullopt;
+
+ return entry->data;
+}
+
+std::optional<minidump::Range> MinidumpParser::GetClosestFollowingRegion(lldb::addr_t load_addr) {
+ if (m_memory_ranges.IsEmpty())
+ PopulateMemoryRanges();
+
+ const MemoryRangeVector::Entry *entry = m_memory_ranges.FindEntryThatContainsOrFollows(load_addr);
+ if (!entry)
+ return std::nullopt;
+
+ return entry->data;
+}
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index 3b7d33daca717..fdd8600d15054 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -107,6 +107,11 @@ class MinidumpParser {
llvm::Expected<llvm::ArrayRef<uint8_t>> GetMemory(lldb::addr_t addr,
size_t size);
+ // Pair of functions to get relative memory regions from the minidump file. These aren't for
+ // evaluating the data, but checking the ranges stored in the minidump and their permissions.
+ std::optional<Range> GetClosestPriorRegion(lldb::addr_t addr);
+ std::optional<Range> GetClosestFollowingRegion(lldb::addr_t addr);
+
/// Returns a list of memory regions and a flag indicating whether the list is
/// complete (includes all regions mapped into the process memory).
std::pair<MemoryRegionInfos, bool> BuildMemoryRegions();
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 17a421a722743..29494fc13c9ff 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -601,6 +601,25 @@ bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) {
return true;
}
+std::optional<lldb_private::MemoryRegionInfo> ProcessMinidump::TryGetMemoryRegionInCore(lldb::addr_t addr, std::optional<lldb_private::MemoryRegionInfo> &closest_prior_region, std::optional<lldb_private::MemoryRegionInfo> & closest_following_region) {
+ std::optional<minidump::Range> addr_region_maybe = m_minidump_parser->FindMemoryRange(addr);
+ if (addr_region_maybe) {
+ MemoryRegionInfo region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, addr_region_maybe->start);
+ return region;
+ }
+
+ // If we didn't find a region, try to find the closest prior and following
+ std::optional<minidump::Range> closest_prior_range_maybe = m_minidump_parser->GetClosestPriorRegion(addr);
+ if (closest_prior_range_maybe)
+ closest_prior_region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, closest_prior_range_maybe->start);
+
+ std::optional<minidump::Range> closest_following_range_maybe = m_minidump_parser->GetClosestFollowingRegion(addr);
+ if (closest_following_range_maybe)
+ closest_following_region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, closest_following_range_maybe->start);
+
+ return std::nullopt;
+}
+
// For minidumps there's no runtime generated code so we don't need JITLoader(s)
// Avoiding them will also speed up minidump loading since JITLoaders normally
// try to set up symbolic breakpoints, which in turn may force loading more
@@ -961,6 +980,65 @@ class CommandObjectProcessMinidumpDump : public CommandObjectParsed {
}
};
+class CommandObjectProcessMinidumpCheckMemory : public CommandObjectParsed {
+public:
+ CommandObjectProcessMinidumpCheckMemory(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin check-memory",
+ "Check if a memory address is stored in the Minidump, or the closest ranges.", nullptr) {
+ CommandArgumentEntry arg1;
+ CommandArgumentData addr_arg;
+ addr_arg.arg_type = eArgTypeAddressOrExpression;
+
+ arg1.push_back(addr_arg);
+ m_arguments.push_back(arg1);
+ }
+
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ result.AppendErrorWithFormat("'%s' Requires a memory address",
+ m_cmd_name.c_str());
+ return;
+ }
+
+ Status error;
+ lldb::addr_t address = OptionArgParser::ToAddress(&m_exe_ctx, command[0].ref(),
+ LLDB_INVALID_ADDRESS, &error);
+
+ if (error.Fail() || address == LLDB_INVALID_ADDRESS) {
+ result.AppendErrorWithFormat("'%s' Is an invalid address.", command[0].c_str());
+ return;
+ }
+
+ ProcessMinidump *process = static_cast<ProcessMinidump *>(
+ m_interpreter.GetExecutionContext().GetProcessPtr());
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ std::optional<lldb_private::MemoryRegionInfo> closest_prior_region;
+ std::optional<lldb_private::MemoryRegionInfo> closest_following_region;
+ std::optional<lldb_private::MemoryRegionInfo> memory_region_maybe =
+ process->TryGetMemoryRegionInCore(address, closest_prior_region, closest_following_region);
+
+ if (memory_region_maybe) {
+ result.AppendMessageWithFormat("Address found in Minidump. Address located in range: %s", memory_region_maybe->Dump().c_str());
+ return;
+ }
+
+ lldb_private::StreamString result_stream;
+ result_stream << "Address not found in Minidump";
+ if (closest_prior_region)
+ result_stream << "Closest prior range: " << closest_prior_region->Dump().c_str();
+ else
+ result_stream << "No prior range found";
+ if (closest_following_region)
+ result_stream << "Closest superior range: " << closest_following_region->Dump().c_str();
+ else
+ result_stream << "No superior range found";
+
+ result.AppendMessage(result_stream.GetString());
+ }
+};
+
class CommandObjectMultiwordProcessMinidump : public CommandObjectMultiword {
public:
CommandObjectMultiwordProcessMinidump(CommandInterpreter &interpreter)
@@ -969,6 +1047,7 @@ class CommandObjectMultiwordProcessMinidump : public CommandObjectMultiword {
"process plugin <subcommand> [<subcommand-options>]") {
LoadSubCommand("dump",
CommandObjectSP(new CommandObjectProcessMinidumpDump(interpreter)));
+ LoadSubCommand("check-memory", CommandObjectSP(new CommandObjectProcessMinidumpCheckMemory(interpreter)));
}
~CommandObjectMultiwordProcessMinidump() override = default;
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index ad8d0ed7a4832..41132c5d2eacd 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -74,6 +74,10 @@ class ProcessMinidump : public PostMortemProcess {
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) override;
+ std::optional<lldb_private::MemoryRegionInfo> TryGetMemoryRegionInCore(lldb::addr_t addr,
+ std::optional<lldb_private::MemoryRegionInfo> &closest_prior_region,
+ std::optional<lldb_private::MemoryRegionInfo> &closest_following_region);
+
ArchSpec GetArchitecture();
Status
>From ff66c231c82da9da77546a8c799ceab962bc424f Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Thu, 17 Jul 2025 13:27:49 -0700
Subject: [PATCH 2/4] Fix rangemap for entry or prior and add test
---
lldb/include/lldb/Utility/RangeMap.h | 11 ++--
.../Process/minidump/ProcessMinidump.cpp | 15 +++---
lldb/test/Shell/Minidump/check-memory.yaml | 52 +++++++++++++++++++
3 files changed, 66 insertions(+), 12 deletions(-)
create mode 100644 lldb/test/Shell/Minidump/check-memory.yaml
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index 5bb3d67309cbd..894b08493a5cd 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -654,17 +654,16 @@ class RangeDataVector {
#endif
if (!m_entries.empty()) {
typename Collection::const_iterator begin = m_entries.begin();
- typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = llvm::lower_bound(
m_entries, addr, [](const Entry &lhs, B rhs_base) -> bool {
return lhs.GetRangeEnd() <= rhs_base;
});
+
+ if (pos->Contains(addr))
+ return &(*pos);
- while (pos != begin && pos[-1].Contains(addr))
- ++pos;
-
- if (pos != end)
- return &(*pos);
+ if (pos != begin)
+ return &(*std::prev(pos));
}
return nullptr;
}
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 29494fc13c9ff..4fa312d7533e8 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -602,6 +602,10 @@ bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) {
}
std::optional<lldb_private::MemoryRegionInfo> ProcessMinidump::TryGetMemoryRegionInCore(lldb::addr_t addr, std::optional<lldb_private::MemoryRegionInfo> &closest_prior_region, std::optional<lldb_private::MemoryRegionInfo> & closest_following_region) {
+ // Ensure memory regions are built!
+ BuildMemoryRegions();
+
+ // First try to find the region that contains the address (if any
std::optional<minidump::Range> addr_region_maybe = m_minidump_parser->FindMemoryRange(addr);
if (addr_region_maybe) {
MemoryRegionInfo region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, addr_region_maybe->start);
@@ -622,7 +626,6 @@ std::optional<lldb_private::MemoryRegionInfo> ProcessMinidump::TryGetMemoryRegio
// For minidumps there's no runtime generated code so we don't need JITLoader(s)
// Avoiding them will also speed up minidump loading since JITLoaders normally
-// try to set up symbolic breakpoints, which in turn may force loading more
// debug information than needed.
JITLoaderList &ProcessMinidump::GetJITLoaders() {
if (!m_jit_loaders_up) {
@@ -1025,15 +1028,15 @@ class CommandObjectProcessMinidumpCheckMemory : public CommandObjectParsed {
}
lldb_private::StreamString result_stream;
- result_stream << "Address not found in Minidump";
+ result_stream << "Address not found in Minidump" << "\n";
if (closest_prior_region)
- result_stream << "Closest prior range: " << closest_prior_region->Dump().c_str();
+ result_stream << "Closest prior range: " << closest_prior_region->Dump().c_str() << "\n";
else
- result_stream << "No prior range found";
+ result_stream << "No prior range found" << "\n";
if (closest_following_region)
- result_stream << "Closest superior range: " << closest_following_region->Dump().c_str();
+ result_stream << "Closest following range: " << closest_following_region->Dump().c_str() << "\n";
else
- result_stream << "No superior range found";
+ result_stream << "No following range found" << "\n";
result.AppendMessage(result_stream.GetString());
}
diff --git a/lldb/test/Shell/Minidump/check-memory.yaml b/lldb/test/Shell/Minidump/check-memory.yaml
new file mode 100644
index 0000000000000..cce315fb687fe
--- /dev/null
+++ b/lldb/test/Shell/Minidump/check-memory.yaml
@@ -0,0 +1,52 @@
+# Check that looking up a memory region not present in the Minidump fails
+# even if it's in the /proc/<pid>/maps file.
+
+# RUN: yaml2obj %s -o %t
+# RUN: %lldb -c %t -o "process plugin check-memory 0x1000" \
+# RUN: -o "process plugin check-memory 0x800" \
+# RUN: -o "process plugin check-memory 0x1500" \
+# RUN: -o "process plugin check-memory 0x2400" | FileCheck %s
+
+# CHECK-LABEL: (lldb) process plugin check-memory 0x1000
+# CHECK-NEXT: Address found in Minidump. Address located in range: [0000000000001000-0000000000001100) r??
+# CHECK-LABEL: (lldb) process plugin check-memory 0x800
+# CHECK-NEXT: Address not found in Minidump
+# CHECK-NEXT: No prior range found
+# CHECK-NEXT: Closest following range: [0000000000001000-0000000000001100) r??
+# CHECK-LABEL: (lldb) process plugin check-memory 0x1500
+# CHECK-NEXT: Address not found in Minidump
+# CHECK-NEXT: Closest prior range: [0000000000001000-0000000000001100) r??
+# CHECK-NEXT: Closest following range: [0000000000002000-0000000000002200) r??
+# CHECK-LABEL: (lldb) process plugin check-memory 0x2400
+# CHECK-NEXT: Address not found in Minidump
+# CHECK-NEXT: Closest prior range: [0000000000002000-0000000000002200) r??
+# CHECK-NEXT: No following range found
+
+--- !minidump
+Streams:
+ - Type: SystemInfo
+ Processor Arch: AMD64
+ Processor Level: 6
+ Processor Revision: 15876
+ Number of Processors: 40
+ Platform ID: Linux
+ CSD Version: 'Linux 3.13.0-91-generic #138-Ubuntu SMP Fri Jun 24 17:00:34 UTC 2016 x86_64'
+ CPU:
+ Vendor ID: GenuineIntel
+ Version Info: 0x00000000
+ Feature Info: 0x00000000
+ - Type: LinuxProcStatus
+ Text: |
+ Name: test-yaml
+ Umask: 0002
+ State: t (tracing stop)
+ Pid: 8567
+ - Type: Memory64List
+ Memory Ranges:
+ - Start of Memory Range: 0x1000
+ Data Size: 0x100
+ Content : ''
+ - Start of Memory Range: 0x2000
+ Data Size: 0x200
+ Content : ''
+...
>From 9c9866dae9794aea76f3f94fe5f614fd610116f1 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Thu, 17 Jul 2025 13:28:04 -0700
Subject: [PATCH 3/4] Formatting
---
lldb/include/lldb/Target/MemoryRegionInfo.h | 4 +-
lldb/include/lldb/Utility/RangeMap.h | 4 +-
.../Process/minidump/MinidumpParser.cpp | 12 ++-
.../Plugins/Process/minidump/MinidumpParser.h | 5 +-
.../Process/minidump/ProcessMinidump.cpp | 80 ++++++++++++-------
.../Process/minidump/ProcessMinidump.h | 7 +-
6 files changed, 69 insertions(+), 43 deletions(-)
diff --git a/lldb/include/lldb/Target/MemoryRegionInfo.h b/lldb/include/lldb/Target/MemoryRegionInfo.h
index ad254084a40d3..2957709692307 100644
--- a/lldb/include/lldb/Target/MemoryRegionInfo.h
+++ b/lldb/include/lldb/Target/MemoryRegionInfo.h
@@ -14,8 +14,8 @@
#include <vector>
#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/RangeMap.h"
+#include "lldb/Utility/StreamString.h"
#include "llvm/Support/FormatProviders.h"
namespace lldb_private {
@@ -165,7 +165,7 @@ class MemoryRegionInfo {
stream << "x";
else if (m_execute == eNo)
stream << "-";
- else
+ else
stream << "?";
return stream.GetString().str();
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index 894b08493a5cd..da17aee1fde1d 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -658,9 +658,9 @@ class RangeDataVector {
m_entries, addr, [](const Entry &lhs, B rhs_base) -> bool {
return lhs.GetRangeEnd() <= rhs_base;
});
-
+
if (pos->Contains(addr))
- return &(*pos);
+ return &(*pos);
if (pos != begin)
return &(*std::prev(pos));
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index a81213ed858c8..16eeb99d91ad8 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -712,22 +712,26 @@ MinidumpParser::GetMemoryRegionInfo(const MemoryRegionInfos ®ions,
return region;
}
-std::optional<minidump::Range> MinidumpParser::GetClosestPriorRegion(lldb::addr_t load_addr) {
+std::optional<minidump::Range>
+MinidumpParser::GetClosestPriorRegion(lldb::addr_t load_addr) {
if (m_memory_ranges.IsEmpty())
PopulateMemoryRanges();
- const MemoryRangeVector::Entry *entry = m_memory_ranges.FindEntryThatContainsOrPrior(load_addr);
+ const MemoryRangeVector::Entry *entry =
+ m_memory_ranges.FindEntryThatContainsOrPrior(load_addr);
if (!entry)
return std::nullopt;
return entry->data;
}
-std::optional<minidump::Range> MinidumpParser::GetClosestFollowingRegion(lldb::addr_t load_addr) {
+std::optional<minidump::Range>
+MinidumpParser::GetClosestFollowingRegion(lldb::addr_t load_addr) {
if (m_memory_ranges.IsEmpty())
PopulateMemoryRanges();
- const MemoryRangeVector::Entry *entry = m_memory_ranges.FindEntryThatContainsOrFollows(load_addr);
+ const MemoryRangeVector::Entry *entry =
+ m_memory_ranges.FindEntryThatContainsOrFollows(load_addr);
if (!entry)
return std::nullopt;
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index fdd8600d15054..ac8fc682925ee 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -107,8 +107,9 @@ class MinidumpParser {
llvm::Expected<llvm::ArrayRef<uint8_t>> GetMemory(lldb::addr_t addr,
size_t size);
- // Pair of functions to get relative memory regions from the minidump file. These aren't for
- // evaluating the data, but checking the ranges stored in the minidump and their permissions.
+ // Pair of functions to get relative memory regions from the minidump file.
+ // These aren't for evaluating the data, but checking the ranges stored in the
+ // minidump and their permissions.
std::optional<Range> GetClosestPriorRegion(lldb::addr_t addr);
std::optional<Range> GetClosestFollowingRegion(lldb::addr_t addr);
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 4fa312d7533e8..79ccafe7a561c 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -601,25 +601,35 @@ bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) {
return true;
}
-std::optional<lldb_private::MemoryRegionInfo> ProcessMinidump::TryGetMemoryRegionInCore(lldb::addr_t addr, std::optional<lldb_private::MemoryRegionInfo> &closest_prior_region, std::optional<lldb_private::MemoryRegionInfo> & closest_following_region) {
+std::optional<lldb_private::MemoryRegionInfo>
+ProcessMinidump::TryGetMemoryRegionInCore(
+ lldb::addr_t addr,
+ std::optional<lldb_private::MemoryRegionInfo> &closest_prior_region,
+ std::optional<lldb_private::MemoryRegionInfo> &closest_following_region) {
// Ensure memory regions are built!
BuildMemoryRegions();
// First try to find the region that contains the address (if any
- std::optional<minidump::Range> addr_region_maybe = m_minidump_parser->FindMemoryRange(addr);
+ std::optional<minidump::Range> addr_region_maybe =
+ m_minidump_parser->FindMemoryRange(addr);
if (addr_region_maybe) {
- MemoryRegionInfo region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, addr_region_maybe->start);
+ MemoryRegionInfo region = MinidumpParser::GetMemoryRegionInfo(
+ *m_memory_regions, addr_region_maybe->start);
return region;
}
// If we didn't find a region, try to find the closest prior and following
- std::optional<minidump::Range> closest_prior_range_maybe = m_minidump_parser->GetClosestPriorRegion(addr);
+ std::optional<minidump::Range> closest_prior_range_maybe =
+ m_minidump_parser->GetClosestPriorRegion(addr);
if (closest_prior_range_maybe)
- closest_prior_region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, closest_prior_range_maybe->start);
+ closest_prior_region = MinidumpParser::GetMemoryRegionInfo(
+ *m_memory_regions, closest_prior_range_maybe->start);
- std::optional<minidump::Range> closest_following_range_maybe = m_minidump_parser->GetClosestFollowingRegion(addr);
+ std::optional<minidump::Range> closest_following_range_maybe =
+ m_minidump_parser->GetClosestFollowingRegion(addr);
if (closest_following_range_maybe)
- closest_following_region = MinidumpParser::GetMemoryRegionInfo(*m_memory_regions, closest_following_range_maybe->start);
+ closest_following_region = MinidumpParser::GetMemoryRegionInfo(
+ *m_memory_regions, closest_following_range_maybe->start);
return std::nullopt;
}
@@ -986,16 +996,18 @@ class CommandObjectProcessMinidumpDump : public CommandObjectParsed {
class CommandObjectProcessMinidumpCheckMemory : public CommandObjectParsed {
public:
CommandObjectProcessMinidumpCheckMemory(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "process plugin check-memory",
- "Check if a memory address is stored in the Minidump, or the closest ranges.", nullptr) {
- CommandArgumentEntry arg1;
- CommandArgumentData addr_arg;
- addr_arg.arg_type = eArgTypeAddressOrExpression;
-
- arg1.push_back(addr_arg);
- m_arguments.push_back(arg1);
- }
-
+ : CommandObjectParsed(interpreter, "process plugin check-memory",
+ "Check if a memory address is stored in the "
+ "Minidump, or the closest ranges.",
+ nullptr) {
+ CommandArgumentEntry arg1;
+ CommandArgumentData addr_arg;
+ addr_arg.arg_type = eArgTypeAddressOrExpression;
+
+ arg1.push_back(addr_arg);
+ m_arguments.push_back(arg1);
+ }
+
void DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
if (argc == 0) {
@@ -1005,39 +1017,45 @@ class CommandObjectProcessMinidumpCheckMemory : public CommandObjectParsed {
}
Status error;
- lldb::addr_t address = OptionArgParser::ToAddress(&m_exe_ctx, command[0].ref(),
- LLDB_INVALID_ADDRESS, &error);
+ lldb::addr_t address = OptionArgParser::ToAddress(
+ &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
if (error.Fail() || address == LLDB_INVALID_ADDRESS) {
- result.AppendErrorWithFormat("'%s' Is an invalid address.", command[0].c_str());
+ result.AppendErrorWithFormat("'%s' Is an invalid address.",
+ command[0].c_str());
return;
}
ProcessMinidump *process = static_cast<ProcessMinidump *>(
- m_interpreter.GetExecutionContext().GetProcessPtr());
+ m_interpreter.GetExecutionContext().GetProcessPtr());
result.SetStatus(eReturnStatusSuccessFinishResult);
std::optional<lldb_private::MemoryRegionInfo> closest_prior_region;
std::optional<lldb_private::MemoryRegionInfo> closest_following_region;
- std::optional<lldb_private::MemoryRegionInfo> memory_region_maybe =
- process->TryGetMemoryRegionInCore(address, closest_prior_region, closest_following_region);
+ std::optional<lldb_private::MemoryRegionInfo> memory_region_maybe =
+ process->TryGetMemoryRegionInCore(address, closest_prior_region,
+ closest_following_region);
if (memory_region_maybe) {
- result.AppendMessageWithFormat("Address found in Minidump. Address located in range: %s", memory_region_maybe->Dump().c_str());
+ result.AppendMessageWithFormat(
+ "Address found in Minidump. Address located in range: %s",
+ memory_region_maybe->Dump().c_str());
return;
}
lldb_private::StreamString result_stream;
result_stream << "Address not found in Minidump" << "\n";
if (closest_prior_region)
- result_stream << "Closest prior range: " << closest_prior_region->Dump().c_str() << "\n";
- else
+ result_stream << "Closest prior range: "
+ << closest_prior_region->Dump().c_str() << "\n";
+ else
result_stream << "No prior range found" << "\n";
if (closest_following_region)
- result_stream << "Closest following range: " << closest_following_region->Dump().c_str() << "\n";
- else
+ result_stream << "Closest following range: "
+ << closest_following_region->Dump().c_str() << "\n";
+ else
result_stream << "No following range found" << "\n";
-
+
result.AppendMessage(result_stream.GetString());
}
};
@@ -1050,7 +1068,9 @@ class CommandObjectMultiwordProcessMinidump : public CommandObjectMultiword {
"process plugin <subcommand> [<subcommand-options>]") {
LoadSubCommand("dump",
CommandObjectSP(new CommandObjectProcessMinidumpDump(interpreter)));
- LoadSubCommand("check-memory", CommandObjectSP(new CommandObjectProcessMinidumpCheckMemory(interpreter)));
+ LoadSubCommand("check-memory",
+ CommandObjectSP(new CommandObjectProcessMinidumpCheckMemory(
+ interpreter)));
}
~CommandObjectMultiwordProcessMinidump() override = default;
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index 41132c5d2eacd..f5a3a87260521 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -74,9 +74,10 @@ class ProcessMinidump : public PostMortemProcess {
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) override;
- std::optional<lldb_private::MemoryRegionInfo> TryGetMemoryRegionInCore(lldb::addr_t addr,
- std::optional<lldb_private::MemoryRegionInfo> &closest_prior_region,
- std::optional<lldb_private::MemoryRegionInfo> &closest_following_region);
+ std::optional<lldb_private::MemoryRegionInfo> TryGetMemoryRegionInCore(
+ lldb::addr_t addr,
+ std::optional<lldb_private::MemoryRegionInfo> &closest_prior_region,
+ std::optional<lldb_private::MemoryRegionInfo> &closest_following_region);
ArchSpec GetArchitecture();
>From cc41f5f40c09997544147af37cc6918142690406 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Fri, 18 Jul 2025 13:34:40 -0700
Subject: [PATCH 4/4] Add a check for the iterator being equal to end before
checking contains
---
lldb/include/lldb/Utility/RangeMap.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index da17aee1fde1d..81be259b5366d 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -654,12 +654,13 @@ class RangeDataVector {
#endif
if (!m_entries.empty()) {
typename Collection::const_iterator begin = m_entries.begin();
+ typename Collection::const_iterator end = m_entries.end();
typename Collection::const_iterator pos = llvm::lower_bound(
m_entries, addr, [](const Entry &lhs, B rhs_base) -> bool {
return lhs.GetRangeEnd() <= rhs_base;
});
- if (pos->Contains(addr))
+ if (pos != end && pos->Contains(addr))
return &(*pos);
if (pos != begin)
More information about the lldb-commits
mailing list