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 <jalalo...@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 <jalalo...@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 <jalalo...@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 <jalalo...@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) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits