[Lldb-commits] [lldb] [LLDB] Reappply SBSaveCore AddMemoryList (PR #107159)
Jacob Lalonde via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 3 17:15:58 PDT 2024
https://github.com/Jlalond updated https://github.com/llvm/llvm-project/pull/107159
>From 63a343d2613d09a866180c8bebdf4568e20fd3b7 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Thu, 29 Aug 2024 10:09:19 -0700
Subject: [PATCH 1/3] =?UTF-8?q?Reapply=20"[LLDB][SBSaveCore]=20Add=20selec?=
=?UTF-8?q?table=20memory=20regions=20to=20SBSaveCor=E2=80=A6=20(#106293)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit b9595324846a96dd3443359a62c70cec5aa352b8.
---
lldb/include/lldb/API/SBMemoryRegionInfo.h | 2 +-
lldb/include/lldb/API/SBSaveCoreOptions.h | 11 ++
lldb/include/lldb/Symbol/SaveCoreOptions.h | 11 +-
lldb/include/lldb/Target/Process.h | 5 +-
lldb/include/lldb/Utility/RangeMap.h | 2 +
lldb/include/lldb/lldb-enumerations.h | 1 +
lldb/include/lldb/lldb-forward.h | 1 +
lldb/include/lldb/lldb-private-interfaces.h | 1 -
lldb/source/API/SBSaveCoreOptions.cpp | 11 ++
lldb/source/Commands/CommandObjectProcess.cpp | 1 +
.../ObjectFile/Mach-O/ObjectFileMachO.cpp | 4 +-
.../ObjectFile/Mach-O/ObjectFileMachO.h | 1 +
.../Minidump/MinidumpFileBuilder.cpp | 33 ++--
.../ObjectFile/Minidump/MinidumpFileBuilder.h | 9 +-
.../ObjectFile/Minidump/ObjectFileMinidump.h | 1 +
.../ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 1 +
.../ObjectFile/PECOFF/ObjectFilePECOFF.h | 1 +
lldb/source/Symbol/SaveCoreOptions.cpp | 14 ++
lldb/source/Target/Process.cpp | 70 +++++++-
.../TestProcessSaveCoreMinidump.py | 155 ++++++++++++++++++
20 files changed, 304 insertions(+), 31 deletions(-)
diff --git a/lldb/include/lldb/API/SBMemoryRegionInfo.h b/lldb/include/lldb/API/SBMemoryRegionInfo.h
index be55de4ead1fa8..f9a5dc993d7cb6 100644
--- a/lldb/include/lldb/API/SBMemoryRegionInfo.h
+++ b/lldb/include/lldb/API/SBMemoryRegionInfo.h
@@ -120,7 +120,7 @@ class LLDB_API SBMemoryRegionInfo {
private:
friend class SBProcess;
friend class SBMemoryRegionInfoList;
-
+ friend class SBSaveCoreOptions;
friend class lldb_private::ScriptInterpreter;
lldb_private::MemoryRegionInfo &ref();
diff --git a/lldb/include/lldb/API/SBSaveCoreOptions.h b/lldb/include/lldb/API/SBSaveCoreOptions.h
index ba48ba5eaea5a0..c076d3ce6f7575 100644
--- a/lldb/include/lldb/API/SBSaveCoreOptions.h
+++ b/lldb/include/lldb/API/SBSaveCoreOptions.h
@@ -80,6 +80,17 @@ class LLDB_API SBSaveCoreOptions {
/// \return True if the thread was removed, false if it was not in the list.
bool RemoveThread(lldb::SBThread thread);
+ /// Add a memory region to save in the core file.
+ ///
+ /// \param region The memory region to save.
+ /// \returns An empty SBError upon success, or an error if the region is
+ /// invalid.
+ /// \note Ranges that overlapped will be unioned into a single region, this
+ /// also supercedes stack minification. Specifying full regions and a
+ /// non-custom core style will include the specified regions and union them
+ /// with all style specific regions.
+ SBError AddMemoryRegionToSave(const SBMemoryRegionInfo ®ion);
+
/// Reset all options.
void Clear();
diff --git a/lldb/include/lldb/Symbol/SaveCoreOptions.h b/lldb/include/lldb/Symbol/SaveCoreOptions.h
index f4fed4676fa4ae..d90d08026016dc 100644
--- a/lldb/include/lldb/Symbol/SaveCoreOptions.h
+++ b/lldb/include/lldb/Symbol/SaveCoreOptions.h
@@ -10,13 +10,15 @@
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_SaveCoreOPTIONS_H
#include "lldb/Utility/FileSpec.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h"
+#include "lldb/Utility/RangeMap.h"
#include <optional>
+#include <set>
#include <string>
#include <unordered_set>
+using MemoryRanges = lldb_private::RangeVector<lldb::addr_t, lldb::addr_t>;
+
namespace lldb_private {
class SaveCoreOptions {
@@ -38,8 +40,12 @@ class SaveCoreOptions {
Status AddThread(lldb::ThreadSP thread_sp);
bool RemoveThread(lldb::ThreadSP thread_sp);
bool ShouldThreadBeSaved(lldb::tid_t tid) const;
+ bool HasSpecifiedThreads() const;
Status EnsureValidConfiguration(lldb::ProcessSP process_sp) const;
+ const MemoryRanges &GetCoreFileMemoryRanges() const;
+
+ void AddMemoryRegionToSave(const lldb_private::MemoryRegionInfo ®ion);
void Clear();
@@ -51,6 +57,7 @@ class SaveCoreOptions {
std::optional<lldb::SaveCoreStyle> m_style;
lldb::ProcessSP m_process_sp;
std::unordered_set<lldb::tid_t> m_threads_to_save;
+ MemoryRanges m_regions_to_save;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index a7de991104434d..6506f8f9c16167 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -35,6 +35,7 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Host/ProcessRunLock.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Target/Memory.h"
@@ -731,7 +732,9 @@ class Process : public std::enable_shared_from_this<Process>,
}
};
- using CoreFileMemoryRanges = std::vector<CoreFileMemoryRange>;
+ using CoreFileMemoryRanges =
+ lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t,
+ CoreFileMemoryRange>;
/// Helper function for Process::SaveCore(...) that calculates the address
/// ranges that should be saved. This allows all core file plug-ins to save
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index 8cc382bcc046ce..c636348129b647 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -450,6 +450,8 @@ class RangeDataVector {
void Append(const Entry &entry) { m_entries.emplace_back(entry); }
+ void Append(B &&b, S &&s, T &&t) { m_entries.emplace_back(Entry(b, s, t)); }
+
bool Erase(uint32_t start, uint32_t end) {
if (start >= end || end > m_entries.size())
return false;
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 7bfde8b9de1271..938f6e3abe8f2a 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -1222,6 +1222,7 @@ enum SaveCoreStyle {
eSaveCoreFull = 1,
eSaveCoreDirtyOnly = 2,
eSaveCoreStackOnly = 3,
+ eSaveCoreCustomOnly = 4,
};
/// Events that might happen during a trace session.
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 337eff696fcf3f..5fb288ad43af48 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -207,6 +207,7 @@ class StackFrameRecognizer;
class StackFrameRecognizerManager;
class StackID;
class Status;
+class SaveCoreOptions;
class StopInfo;
class Stoppoint;
class StoppointCallbackContext;
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index b3c8cda899b95e..5bac5cd3e86b59 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -9,7 +9,6 @@
#ifndef LLDB_LLDB_PRIVATE_INTERFACES_H
#define LLDB_LLDB_PRIVATE_INTERFACES_H
-#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
diff --git a/lldb/source/API/SBSaveCoreOptions.cpp b/lldb/source/API/SBSaveCoreOptions.cpp
index 2cd431611ef558..5e75aa911b650b 100644
--- a/lldb/source/API/SBSaveCoreOptions.cpp
+++ b/lldb/source/API/SBSaveCoreOptions.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/API/SBSaveCoreOptions.h"
+#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Utility/Instrumentation.h"
@@ -90,6 +91,16 @@ bool SBSaveCoreOptions::RemoveThread(lldb::SBThread thread) {
return m_opaque_up->RemoveThread(thread.GetSP());
}
+lldb::SBError
+SBSaveCoreOptions::AddMemoryRegionToSave(const SBMemoryRegionInfo ®ion) {
+ LLDB_INSTRUMENT_VA(this, region);
+ // Currently add memory region can't fail, so we always return a success
+ // SBerror, but because these API's live forever, this is the most future
+ // proof thing to do.
+ m_opaque_up->AddMemoryRegionToSave(region.ref());
+ return SBError();
+}
+
void SBSaveCoreOptions::Clear() {
LLDB_INSTRUMENT_VA(this);
m_opaque_up->Clear();
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 25eb633f1e6dad..5b0f4f66f248b6 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -25,6 +25,7 @@
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
#include "lldb/Interpreter/Options.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 2004622e547be9..e756eddb5f9a86 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -6568,7 +6568,9 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
const uint32_t addr_byte_size = target_arch.GetAddressByteSize();
const ByteOrder byte_order = target_arch.GetByteOrder();
std::vector<llvm::MachO::segment_command_64> segment_load_commands;
- for (const auto &core_range : core_ranges) {
+ for (const auto &core_range_info : core_ranges) {
+ // TODO: Refactor RangeDataVector to have a data iterator.
+ const auto &core_range = core_range_info.data;
uint32_t cmd_type = LC_SEGMENT_64;
uint32_t segment_size = sizeof(llvm::MachO::segment_command_64);
if (addr_byte_size == 4) {
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 27bc237aaac48d..be87112df7d898 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -12,6 +12,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Host/SafeMachO.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/FileSpecList.h"
#include "lldb/Utility/RangeMap.h"
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
index 13355afb58dbd1..96180bf0356e9a 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
@@ -828,25 +828,32 @@ Status MinidumpFileBuilder::AddMemoryList() {
// bytes of the core file. Thread structures in minidump files can only use
// 32 bit memory descriptiors, so we emit them first to ensure the memory is
// in accessible with a 32 bit offset.
- Process::CoreFileMemoryRanges ranges_32;
- Process::CoreFileMemoryRanges ranges_64;
+ std::vector<Process::CoreFileMemoryRange> ranges_32;
+ std::vector<Process::CoreFileMemoryRange> ranges_64;
Process::CoreFileMemoryRanges all_core_memory_ranges;
error = m_process_sp->CalculateCoreFileSaveRanges(m_save_core_options,
all_core_memory_ranges);
+
+ std::vector<Process::CoreFileMemoryRange> all_core_memory_vec;
+ // Extract all the data into just a vector of data. So we can mutate this in
+ // place.
+ for (const auto &core_range : all_core_memory_ranges)
+ all_core_memory_vec.push_back(core_range.data);
+
if (error.Fail())
return error;
// Start by saving all of the stacks and ensuring they fit under the 32b
// limit.
uint64_t total_size = GetCurrentDataEndOffset();
- auto iterator = all_core_memory_ranges.begin();
- while (iterator != all_core_memory_ranges.end()) {
+ auto iterator = all_core_memory_vec.begin();
+ while (iterator != all_core_memory_vec.end()) {
if (m_saved_stack_ranges.count(iterator->range.start()) > 0) {
// We don't save stacks twice.
ranges_32.push_back(*iterator);
total_size +=
iterator->range.size() + sizeof(llvm::minidump::MemoryDescriptor);
- iterator = all_core_memory_ranges.erase(iterator);
+ iterator = all_core_memory_vec.erase(iterator);
} else {
iterator++;
}
@@ -866,11 +873,11 @@ Status MinidumpFileBuilder::AddMemoryList() {
// Then anything overflow extends into 64b addressable space.
// All core memeroy ranges will either container nothing on stacks only
// or all the memory ranges including stacks
- if (!all_core_memory_ranges.empty())
- total_size += 256 + (all_core_memory_ranges.size() *
+ if (!all_core_memory_vec.empty())
+ total_size += 256 + (all_core_memory_vec.size() *
sizeof(llvm::minidump::MemoryDescriptor_64));
- for (const auto &core_range : all_core_memory_ranges) {
+ for (const auto &core_range : all_core_memory_vec) {
const addr_t range_size = core_range.range.size();
// We don't need to check for stacks here because we already removed them
// from all_core_memory_ranges.
@@ -955,15 +962,15 @@ Status MinidumpFileBuilder::DumpDirectories() const {
}
static uint64_t
-GetLargestRangeSize(const Process::CoreFileMemoryRanges &ranges) {
+GetLargestRangeSize(const std::vector<Process::CoreFileMemoryRange> &ranges) {
uint64_t max_size = 0;
for (const auto &core_range : ranges)
max_size = std::max(max_size, core_range.range.size());
return max_size;
}
-Status
-MinidumpFileBuilder::AddMemoryList_32(Process::CoreFileMemoryRanges &ranges) {
+Status MinidumpFileBuilder::AddMemoryList_32(
+ std::vector<Process::CoreFileMemoryRange> &ranges) {
std::vector<MemoryDescriptor> descriptors;
Status error;
if (ranges.size() == 0)
@@ -1039,8 +1046,8 @@ MinidumpFileBuilder::AddMemoryList_32(Process::CoreFileMemoryRanges &ranges) {
return error;
}
-Status
-MinidumpFileBuilder::AddMemoryList_64(Process::CoreFileMemoryRanges &ranges) {
+Status MinidumpFileBuilder::AddMemoryList_64(
+ std::vector<Process::CoreFileMemoryRange> &ranges) {
Status error;
if (ranges.empty())
return error;
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
index 762de83db5a39c..8651cddeedb216 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
@@ -23,6 +23,7 @@
#include <utility>
#include <variant>
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -119,10 +120,10 @@ class MinidumpFileBuilder {
// trigger a flush.
lldb_private::Status AddData(const void *data, uint64_t size);
// Add MemoryList stream, containing dumps of important memory segments
- lldb_private::Status
- AddMemoryList_64(lldb_private::Process::CoreFileMemoryRanges &ranges);
- lldb_private::Status
- AddMemoryList_32(lldb_private::Process::CoreFileMemoryRanges &ranges);
+ lldb_private::Status AddMemoryList_64(
+ std::vector<lldb_private::Process::CoreFileMemoryRange> &ranges);
+ lldb_private::Status AddMemoryList_32(
+ std::vector<lldb_private::Process::CoreFileMemoryRange> &ranges);
// Update the thread list on disk with the newly emitted stack RVAs.
lldb_private::Status FixThreadStacks();
lldb_private::Status FlushBufferToDisk();
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
index b76fcd0052a8a8..2f45f01558e667 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
+++ b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h
@@ -21,6 +21,7 @@
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_OBJECTFILEMINIDUMP_H
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Utility/ArchSpec.h"
class ObjectFileMinidump : public lldb_private::PluginInterface {
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 9d01089745dfc9..8d9c919bc9b101 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -17,6 +17,7 @@
#include "lldb/Interpreter/OptionValueDictionary.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index 8bccf3be3e5f63..4f4dedf773c5ba 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -13,6 +13,7 @@
#include <vector>
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SaveCoreOptions.h"
#include "llvm/Object/COFF.h"
class ObjectFilePECOFF : public lldb_private::ObjectFile {
diff --git a/lldb/source/Symbol/SaveCoreOptions.cpp b/lldb/source/Symbol/SaveCoreOptions.cpp
index 35943726f2e4ef..8d9aadece2152d 100644
--- a/lldb/source/Symbol/SaveCoreOptions.cpp
+++ b/lldb/source/Symbol/SaveCoreOptions.cpp
@@ -102,6 +102,19 @@ bool SaveCoreOptions::ShouldThreadBeSaved(lldb::tid_t tid) const {
return m_threads_to_save.count(tid) > 0;
}
+bool SaveCoreOptions::HasSpecifiedThreads() const {
+ return !m_threads_to_save.empty();
+}
+
+void SaveCoreOptions::AddMemoryRegionToSave(
+ const lldb_private::MemoryRegionInfo ®ion) {
+ m_regions_to_save.Insert(region.GetRange(), /*combine=*/true);
+}
+
+const MemoryRanges &SaveCoreOptions::GetCoreFileMemoryRanges() const {
+ return m_regions_to_save;
+}
+
Status SaveCoreOptions::EnsureValidConfiguration(
lldb::ProcessSP process_sp) const {
Status error;
@@ -131,4 +144,5 @@ void SaveCoreOptions::Clear() {
m_style = std::nullopt;
m_threads_to_save.clear();
m_process_sp.reset();
+ m_regions_to_save.Clear();
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index ae64f6f261bad7..e063c4774f4a2e 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -6529,14 +6529,14 @@ static bool AddDirtyPages(const MemoryRegionInfo ®ion,
} else {
// Add previous contiguous range and init the new range with the
// current dirty page.
- ranges.push_back({range, lldb_permissions});
+ ranges.Append(range.start(), range.end(), {range, lldb_permissions});
range = llvm::AddressRange(page_addr, page_addr + page_size);
}
}
}
// The last range
if (!range.empty())
- ranges.push_back({range, lldb_permissions});
+ ranges.Append(range.start(), range.end(), {range, lldb_permissions});
return true;
}
@@ -6557,7 +6557,10 @@ static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages,
return;
if (try_dirty_pages && AddDirtyPages(region, ranges))
return;
- ranges.push_back(CreateCoreFileMemoryRange(region));
+
+ ranges.Append(region.GetRange().GetRangeBase(),
+ region.GetRange().GetByteSize(),
+ CreateCoreFileMemoryRange(region));
}
static void SaveOffRegionsWithStackPointers(
@@ -6607,7 +6610,7 @@ static void GetCoreFileSaveRangesFull(Process &process,
std::set<addr_t> &stack_ends) {
// Don't add only dirty pages, add full regions.
-const bool try_dirty_pages = false;
+ const bool try_dirty_pages = false;
for (const auto ®ion : regions)
if (stack_ends.count(region.GetRange().GetRangeEnd()) == 0)
AddRegion(region, try_dirty_pages, ranges);
@@ -6663,6 +6666,49 @@ static void GetCoreFileSaveRangesStackOnly(
}
}
+static void GetUserSpecifiedCoreFileSaveRanges(
+ Process &process, const MemoryRegionInfos ®ions,
+ const SaveCoreOptions &options, Process::CoreFileMemoryRanges &ranges) {
+ const auto &option_ranges = options.GetCoreFileMemoryRanges();
+ if (option_ranges.IsEmpty())
+ return;
+
+ for (const auto &range : regions) {
+ auto entry = option_ranges.FindEntryThatContains(range.GetRange());
+ if (entry)
+ ranges.Append(range.GetRange().GetRangeBase(),
+ range.GetRange().GetByteSize(),
+ CreateCoreFileMemoryRange(range));
+ }
+}
+
+static Status
+FinalizeCoreFileSaveRanges(Process::CoreFileMemoryRanges &ranges) {
+ Status error;
+ ranges.Sort();
+ for (size_t i = ranges.GetSize() - 1; i > 0; i--) {
+ auto region = ranges.GetMutableEntryAtIndex(i);
+ auto next_region = ranges.GetMutableEntryAtIndex(i - 1);
+ if (next_region->GetRangeEnd() >= region->GetRangeBase() &&
+ region->GetRangeBase() <= next_region->GetRangeEnd() &&
+ region->data.lldb_permissions == next_region->data.lldb_permissions) {
+ const addr_t base =
+ std::min(region->GetRangeBase(), next_region->GetRangeBase());
+ const addr_t byte_size =
+ std::max(region->GetRangeEnd(), next_region->GetRangeEnd()) - base;
+ next_region->SetRangeBase(base);
+ next_region->SetByteSize(byte_size);
+ if (!ranges.Erase(i, i + 1)) {
+ error = Status::FromErrorString(
+ "Core file memory ranges mutated outside of "
+ "CalculateCoreFileSaveRanges");
+ return error;
+ }
+ }
+ }
+ return error;
+}
+
Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
CoreFileMemoryRanges &ranges) {
lldb_private::MemoryRegionInfos regions;
@@ -6678,11 +6724,18 @@ Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
"callers must set the core_style to something other than "
"eSaveCoreUnspecified");
+ GetUserSpecifiedCoreFileSaveRanges(*this, regions, options, ranges);
+
std::set<addr_t> stack_ends;
- SaveOffRegionsWithStackPointers(*this, options, regions, ranges, stack_ends);
+ // For fully custom set ups, we don't want to even look at threads if there
+ // are no threads specified.
+ if (core_style != lldb::eSaveCoreCustomOnly || options.HasSpecifiedThreads())
+ SaveOffRegionsWithStackPointers(*this, options, regions, ranges,
+ stack_ends);
switch (core_style) {
case eSaveCoreUnspecified:
+ case eSaveCoreCustomOnly:
break;
case eSaveCoreFull:
@@ -6701,10 +6754,11 @@ Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
if (err.Fail())
return err;
- if (ranges.empty())
- return Status("no valid address ranges found for core style");
+ if (ranges.IsEmpty())
+ return Status::FromErrorString(
+ "no valid address ranges found for core style");
- return Status(); // Success!
+ return FinalizeCoreFileSaveRanges(ranges);
}
std::vector<ThreadSP>
diff --git a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
index ea59aef004aff5..eb1259bfc74d1e 100644
--- a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
+++ b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
@@ -305,9 +305,12 @@ def test_save_linux_mini_dump_default_options(self):
thread_id = thread.GetThreadID()
expected_threads.append(thread_id)
stacks_to_sp_map[thread_id] = thread.GetFrameAtIndex(0).GetSP()
+<<<<<<< HEAD
stacks_to_registers_map[thread_id] = thread.GetFrameAtIndex(
0
).GetRegisters()
+=======
+>>>>>>> 32f571ab967c (Reapply "[LLDB][SBSaveCore] Add selectable memory regions to SBSaveCor… (#106293))
# This is almost identical to the single thread test case because
# minidump defaults to stacks only, so we want to see if the
@@ -325,10 +328,162 @@ def test_save_linux_mini_dump_default_options(self):
expected_modules,
expected_threads,
stacks_to_sp_map,
+<<<<<<< HEAD
stacks_to_registers_map,
+=======
+>>>>>>> 32f571ab967c (Reapply "[LLDB][SBSaveCore] Add selectable memory regions to SBSaveCor… (#106293))
)
finally:
self.assertTrue(self.dbg.DeleteTarget(target))
if os.path.isfile(default_value_file):
os.unlink(default_value_file)
+
+ @skipUnlessArch("x86_64")
+ @skipUnlessPlatform(["linux"])
+ def test_save_linux_minidump_one_region(self):
+ """Test that we can save a Linux mini dump with one region in sbsavecore regions"""
+
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ one_region_file = self.getBuildArtifact("core.one_region.dmp")
+ try:
+ target = self.dbg.CreateTarget(exe)
+ process = target.LaunchSimple(
+ None, None, self.get_process_working_directory()
+ )
+ self.assertState(process.GetState(), lldb.eStateStopped)
+
+ memory_region = lldb.SBMemoryRegionInfo()
+ memory_list = process.GetMemoryRegions()
+ memory_list.GetMemoryRegionAtIndex(0, memory_region)
+
+ # This is almost identical to the single thread test case because
+ # minidump defaults to stacks only, so we want to see if the
+ # default options work as expected.
+ options = lldb.SBSaveCoreOptions()
+ file_spec = lldb.SBFileSpec(one_region_file)
+ options.SetOutputFile(file_spec)
+ options.SetPluginName("minidump")
+ options.AddMemoryRegionToSave(memory_region)
+ options.SetStyle(lldb.eSaveCoreCustomOnly)
+ error = process.SaveCore(options)
+ print(f"Error: {error.GetCString()}")
+ self.assertTrue(error.Success(), error.GetCString())
+
+ core_target = self.dbg.CreateTarget(None)
+ core_proc = core_target.LoadCore(one_region_file)
+ core_memory_list = core_proc.GetMemoryRegions()
+ # Note because the /proc/pid maps are included on linux, we can't
+ # depend on size for validation, so we'll ensure the first region
+ # is present and then assert we fail on the second.
+ core_memory_region = lldb.SBMemoryRegionInfo()
+ core_memory_list.GetMemoryRegionAtIndex(0, core_memory_region)
+ self.assertEqual(
+ core_memory_region.GetRegionBase(), memory_region.GetRegionBase()
+ )
+ self.assertEqual(
+ core_memory_region.GetRegionEnd(), memory_region.GetRegionEnd()
+ )
+
+ region_two = lldb.SBMemoryRegionInfo()
+ core_memory_list.GetMemoryRegionAtIndex(1, region_two)
+ err = lldb.SBError()
+ content = core_proc.ReadMemory(region_two.GetRegionBase(), 1, err)
+ self.assertTrue(err.Fail(), "Should fail to read memory")
+
+ finally:
+ self.assertTrue(self.dbg.DeleteTarget(target))
+ if os.path.isfile(one_region_file):
+ os.unlink(one_region_file)
+
+ @skipUnlessArch("x86_64")
+ @skipUnlessPlatform(["linux"])
+ def test_save_minidump_custom_save_style(self):
+ """Test that verifies a custom and unspecified save style fails for
+ containing no data to save"""
+
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ custom_file = self.getBuildArtifact("core.custom.dmp")
+ try:
+ target = self.dbg.CreateTarget(exe)
+ process = target.LaunchSimple(
+ None, None, self.get_process_working_directory()
+ )
+ self.assertState(process.GetState(), lldb.eStateStopped)
+
+ options = lldb.SBSaveCoreOptions()
+ options.SetOutputFile(lldb.SBFileSpec(custom_file))
+ options.SetPluginName("minidump")
+ options.SetStyle(lldb.eSaveCoreCustomOnly)
+
+ error = process.SaveCore(options)
+ self.assertTrue(error.Fail())
+ self.assertEqual(
+ error.GetCString(), "no valid address ranges found for core style"
+ )
+
+ finally:
+ self.assertTrue(self.dbg.DeleteTarget(target))
+ if os.path.isfile(custom_file):
+ os.unlink(custom_file)
+
+ def save_core_with_region(self, process, region_index):
+ try:
+ custom_file = self.getBuildArtifact("core.custom.dmp")
+ memory_region = lldb.SBMemoryRegionInfo()
+ memory_list = process.GetMemoryRegions()
+ memory_list.GetMemoryRegionAtIndex(0, memory_region)
+ options = lldb.SBSaveCoreOptions()
+ options.SetOutputFile(lldb.SBFileSpec(custom_file))
+ options.SetPluginName("minidump")
+ options.SetStyle(lldb.eSaveCoreFull)
+
+ error = process.SaveCore(options)
+ self.assertTrue(error.Success())
+ core_target = self.dbg.CreateTarget(None)
+ core_proc = core_target.LoadCore(custom_file)
+ core_memory_list = core_proc.GetMemoryRegions()
+ # proc/pid/ maps are included on linux, so we can't depend on size
+ # for validation, we make a set of all the ranges,
+ # and ensure no duplicates!
+ range_set = set()
+ for x in range(core_memory_list.GetSize()):
+ core_memory_region = lldb.SBMemoryRegionInfo()
+ core_memory_list.GetMemoryRegionAtIndex(x, core_memory_region)
+ mem_tuple = (
+ core_memory_region.GetRegionBase(),
+ core_memory_region.GetRegionEnd(),
+ )
+ self.assertTrue(
+ mem_tuple not in range_set, "Duplicate memory region found"
+ )
+ range_set.add(mem_tuple)
+ finally:
+ if os.path.isfile(custom_file):
+ os.unlink(custom_file)
+
+ @skipUnlessArch("x86_64")
+ @skipUnlessPlatform(["linux"])
+ def test_save_minidump_custom_save_style_duplicated_regions(self):
+ """Test that verifies a custom and unspecified save style fails for
+ containing no data to save"""
+
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ try:
+ target = self.dbg.CreateTarget(exe)
+ process = target.LaunchSimple(
+ None, None, self.get_process_working_directory()
+ )
+ self.assertState(process.GetState(), lldb.eStateStopped)
+
+ memory_list = process.GetMemoryRegions()
+ # Test that we don't duplicate regions, by duplicating regions
+ # at various indices.
+ self.save_core_with_region(process, 0)
+ self.save_core_with_region(process, len(memory_list) - 1)
+
+ finally:
+ self.assertTrue(self.dbg.DeleteTarget(target))
>From 6b40db1c986dedcaea50b2eeb3ad1e5815cbc1e9 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Tue, 3 Sep 2024 15:15:18 -0700
Subject: [PATCH 2/3] Move the CoreFileMemoryRanges to it's own class, and add
some unit tests. Fix the big where we only update the range on data, not the
entry list
---
.../lldb/Target/CoreFileMemoryRanges.h | 49 ++++++++
lldb/include/lldb/Target/Process.h | 26 +----
.../ObjectFile/Mach-O/ObjectFileMachO.cpp | 2 +-
.../Minidump/MinidumpFileBuilder.cpp | 14 +--
.../ObjectFile/Minidump/MinidumpFileBuilder.h | 4 +-
lldb/source/Target/CMakeLists.txt | 1 +
lldb/source/Target/CoreFileMemoryRanges.cpp | 48 ++++++++
lldb/source/Target/Process.cpp | 45 ++------
.../TestProcessSaveCoreMinidump.py | 6 -
lldb/unittests/Process/Utility/CMakeLists.txt | 1 +
.../Utility/CoreFileMemoryRangesTest.cpp | 105 ++++++++++++++++++
11 files changed, 224 insertions(+), 77 deletions(-)
create mode 100644 lldb/include/lldb/Target/CoreFileMemoryRanges.h
create mode 100644 lldb/source/Target/CoreFileMemoryRanges.cpp
create mode 100644 lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp
diff --git a/lldb/include/lldb/Target/CoreFileMemoryRanges.h b/lldb/include/lldb/Target/CoreFileMemoryRanges.h
new file mode 100644
index 00000000000000..705ad9bab8a944
--- /dev/null
+++ b/lldb/include/lldb/Target/CoreFileMemoryRanges.h
@@ -0,0 +1,49 @@
+//===-- CoreFileMemoryRanges.h ----------------------------------*- C++ -*-===//
+//
+// 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/Utility/RangeMap.h"
+#include "lldb/Utility/Status.h"
+
+#include "llvm/ADT/AddressRanges.h"
+
+#ifndef LLDB_TARGET_COREFILEMEMORYRANGES_H
+#define LLDB_TARGET_COREFILEMEMORYRANGES_H
+
+namespace lldb_private {
+
+struct CoreFileMemoryRange {
+ llvm::AddressRange range; /// The address range to save into the core file.
+ uint32_t lldb_permissions; /// A bit set of lldb::Permissions bits.
+
+ bool operator==(const CoreFileMemoryRange &rhs) const {
+ return range == rhs.range && lldb_permissions == rhs.lldb_permissions;
+ }
+
+ bool operator!=(const CoreFileMemoryRange &rhs) const {
+ return !(*this == rhs);
+ }
+
+ bool operator<(const CoreFileMemoryRange &rhs) const {
+ if (range < rhs.range)
+ return true;
+ if (range == rhs.range)
+ return lldb_permissions < rhs.lldb_permissions;
+ return false;
+ }
+};
+
+
+class CoreFileMemoryRanges : public lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, CoreFileMemoryRange> {
+ public:
+ /// Finalize and merge all overlapping ranges in this collection. Ranges
+ /// will be seperated based on permissions.
+ Status FinalizeCoreFileSaveRanges();
+};
+} // namespace lldb_private
+
+#endif // LLDB_TARGET_COREFILEMEMORYRANGES_H
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 6506f8f9c16167..c9df4bd1aa2b0b 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -36,6 +36,7 @@
#include "lldb/Host/ProcessRunLock.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SaveCoreOptions.h"
+#include "lldb/Target/CoreFileMemoryRanges.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Target/Memory.h"
@@ -711,31 +712,6 @@ class Process : public std::enable_shared_from_this<Process>,
/// is not supported by the plugin, error otherwise.
virtual llvm::Expected<bool> SaveCore(llvm::StringRef outfile);
- struct CoreFileMemoryRange {
- llvm::AddressRange range; /// The address range to save into the core file.
- uint32_t lldb_permissions; /// A bit set of lldb::Permissions bits.
-
- bool operator==(const CoreFileMemoryRange &rhs) const {
- return range == rhs.range && lldb_permissions == rhs.lldb_permissions;
- }
-
- bool operator!=(const CoreFileMemoryRange &rhs) const {
- return !(*this == rhs);
- }
-
- bool operator<(const CoreFileMemoryRange &rhs) const {
- if (range < rhs.range)
- return true;
- if (range == rhs.range)
- return lldb_permissions < rhs.lldb_permissions;
- return false;
- }
- };
-
- using CoreFileMemoryRanges =
- lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t,
- CoreFileMemoryRange>;
-
/// Helper function for Process::SaveCore(...) that calculates the address
/// ranges that should be saved. This allows all core file plug-ins to save
/// consistent memory ranges given a \a core_style.
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index e756eddb5f9a86..3284119b6dbd40 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -6562,7 +6562,7 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
}
if (make_core) {
- Process::CoreFileMemoryRanges core_ranges;
+ CoreFileMemoryRanges core_ranges;
error = process_sp->CalculateCoreFileSaveRanges(options, core_ranges);
if (error.Success()) {
const uint32_t addr_byte_size = target_arch.GetAddressByteSize();
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
index 96180bf0356e9a..e621de24d12ec6 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
@@ -828,13 +828,13 @@ Status MinidumpFileBuilder::AddMemoryList() {
// bytes of the core file. Thread structures in minidump files can only use
// 32 bit memory descriptiors, so we emit them first to ensure the memory is
// in accessible with a 32 bit offset.
- std::vector<Process::CoreFileMemoryRange> ranges_32;
- std::vector<Process::CoreFileMemoryRange> ranges_64;
- Process::CoreFileMemoryRanges all_core_memory_ranges;
+ std::vector<CoreFileMemoryRange> ranges_32;
+ std::vector<CoreFileMemoryRange> ranges_64;
+ CoreFileMemoryRanges all_core_memory_ranges;
error = m_process_sp->CalculateCoreFileSaveRanges(m_save_core_options,
all_core_memory_ranges);
- std::vector<Process::CoreFileMemoryRange> all_core_memory_vec;
+ std::vector<CoreFileMemoryRange> all_core_memory_vec;
// Extract all the data into just a vector of data. So we can mutate this in
// place.
for (const auto &core_range : all_core_memory_ranges)
@@ -962,7 +962,7 @@ Status MinidumpFileBuilder::DumpDirectories() const {
}
static uint64_t
-GetLargestRangeSize(const std::vector<Process::CoreFileMemoryRange> &ranges) {
+GetLargestRangeSize(const std::vector<CoreFileMemoryRange> &ranges) {
uint64_t max_size = 0;
for (const auto &core_range : ranges)
max_size = std::max(max_size, core_range.range.size());
@@ -970,7 +970,7 @@ GetLargestRangeSize(const std::vector<Process::CoreFileMemoryRange> &ranges) {
}
Status MinidumpFileBuilder::AddMemoryList_32(
- std::vector<Process::CoreFileMemoryRange> &ranges) {
+ std::vector<CoreFileMemoryRange> &ranges) {
std::vector<MemoryDescriptor> descriptors;
Status error;
if (ranges.size() == 0)
@@ -1047,7 +1047,7 @@ Status MinidumpFileBuilder::AddMemoryList_32(
}
Status MinidumpFileBuilder::AddMemoryList_64(
- std::vector<Process::CoreFileMemoryRange> &ranges) {
+ std::vector<CoreFileMemoryRange> &ranges) {
Status error;
if (ranges.empty())
return error;
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
index 8651cddeedb216..d7417dd26d796c 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
@@ -121,9 +121,9 @@ class MinidumpFileBuilder {
lldb_private::Status AddData(const void *data, uint64_t size);
// Add MemoryList stream, containing dumps of important memory segments
lldb_private::Status AddMemoryList_64(
- std::vector<lldb_private::Process::CoreFileMemoryRange> &ranges);
+ std::vector<lldb_private::CoreFileMemoryRange> &ranges);
lldb_private::Status AddMemoryList_32(
- std::vector<lldb_private::Process::CoreFileMemoryRange> &ranges);
+ std::vector<lldb_private::CoreFileMemoryRange> &ranges);
// Update the thread list on disk with the newly emitted stack RVAs.
lldb_private::Status FixThreadStacks();
lldb_private::Status FlushBufferToDisk();
diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt
index a42c44b761dc56..a6d2eace975420 100644
--- a/lldb/source/Target/CMakeLists.txt
+++ b/lldb/source/Target/CMakeLists.txt
@@ -11,6 +11,7 @@ add_lldb_library(lldbTarget
ABI.cpp
AssertFrameRecognizer.cpp
DynamicRegisterInfo.cpp
+ CoreFileMemoryRanges.cpp
ExecutionContext.cpp
InstrumentationRuntime.cpp
InstrumentationRuntimeStopInfo.cpp
diff --git a/lldb/source/Target/CoreFileMemoryRanges.cpp b/lldb/source/Target/CoreFileMemoryRanges.cpp
new file mode 100644
index 00000000000000..c935a3afafe393
--- /dev/null
+++ b/lldb/source/Target/CoreFileMemoryRanges.cpp
@@ -0,0 +1,48 @@
+//===-- CoreFileMemoryRanges.cpp --------------------------------*- C++ -*-===//
+//
+// 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/Target/CoreFileMemoryRanges.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Status CoreFileMemoryRanges::FinalizeCoreFileSaveRanges() {
+ Status error;
+ std::vector<size_t> indexes_to_remove;
+ this->Sort();
+ for (size_t i = this->GetSize() - 1; i > 0; i--) {
+ auto region = this->GetMutableEntryAtIndex(i);
+ auto next_region = this->GetMutableEntryAtIndex(i - 1);
+ if (next_region->GetRangeEnd() >= region->GetRangeBase() &&
+ region->GetRangeBase() <= next_region->GetRangeEnd() &&
+ region->data.lldb_permissions == next_region->data.lldb_permissions) {
+ const addr_t base =
+ std::min(region->GetRangeBase(), next_region->GetRangeBase());
+ const addr_t byte_size =
+ std::max(region->GetRangeEnd(), next_region->GetRangeEnd()) - base;
+
+ next_region->SetRangeBase(base);
+ next_region->SetByteSize(byte_size);
+
+ // Because this is a range data vector, the entry has a base as well
+ // as the data contained in the entry. So we have to update both.
+ // And llvm::AddressRange isn't mutable so we have to create a new one.
+ llvm::AddressRange range (base, base + byte_size);
+ const CoreFileMemoryRange core_range = {range, next_region->data.lldb_permissions};
+ next_region->data = core_range;
+ if (!this->Erase(i, i + 1)) {
+ error = Status::FromErrorString(
+ "Core file memory ranges mutated outside of "
+ "CalculateCoreFileSaveRanges");
+ return error;
+ }
+ }
+ }
+
+ return error;
+}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index e063c4774f4a2e..88c305a5512190 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -6498,7 +6498,7 @@ Status Process::WriteMemoryTags(lldb::addr_t addr, size_t len,
}
// Create a CoreFileMemoryRange from a MemoryRegionInfo
-static Process::CoreFileMemoryRange
+static CoreFileMemoryRange
CreateCoreFileMemoryRange(const MemoryRegionInfo ®ion) {
const addr_t addr = region.GetRange().GetRangeBase();
llvm::AddressRange range(addr, addr + region.GetRange().GetByteSize());
@@ -6509,7 +6509,7 @@ CreateCoreFileMemoryRange(const MemoryRegionInfo ®ion) {
// were added. Return false if the dirty page information is not valid or in
// the region.
static bool AddDirtyPages(const MemoryRegionInfo ®ion,
- Process::CoreFileMemoryRanges &ranges) {
+ CoreFileMemoryRanges &ranges) {
const auto &dirty_page_list = region.GetDirtyPageList();
if (!dirty_page_list)
return false;
@@ -6548,7 +6548,7 @@ static bool AddDirtyPages(const MemoryRegionInfo ®ion,
// will be added to \a ranges, else the entire range will be added to \a
// ranges.
static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages,
- Process::CoreFileMemoryRanges &ranges) {
+ CoreFileMemoryRanges &ranges) {
// Don't add empty ranges.
if (region.GetRange().GetByteSize() == 0)
return;
@@ -6565,7 +6565,7 @@ static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages,
static void SaveOffRegionsWithStackPointers(
Process &process, const SaveCoreOptions &core_options,
- const MemoryRegionInfos ®ions, Process::CoreFileMemoryRanges &ranges,
+ const MemoryRegionInfos ®ions, CoreFileMemoryRanges &ranges,
std::set<addr_t> &stack_ends) {
const bool try_dirty_pages = true;
@@ -6606,7 +6606,7 @@ static void SaveOffRegionsWithStackPointers(
// for a full core file style.
static void GetCoreFileSaveRangesFull(Process &process,
const MemoryRegionInfos ®ions,
- Process::CoreFileMemoryRanges &ranges,
+ CoreFileMemoryRanges &ranges,
std::set<addr_t> &stack_ends) {
// Don't add only dirty pages, add full regions.
@@ -6622,7 +6622,7 @@ static void GetCoreFileSaveRangesFull(Process &process,
// page information fall back to saving out all ranges with write permissions.
static void GetCoreFileSaveRangesDirtyOnly(
Process &process, const MemoryRegionInfos ®ions,
- Process::CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
+ CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
// Iterate over the regions and find all dirty pages.
bool have_dirty_page_info = false;
@@ -6653,7 +6653,7 @@ static void GetCoreFileSaveRangesDirtyOnly(
// stack region.
static void GetCoreFileSaveRangesStackOnly(
Process &process, const MemoryRegionInfos ®ions,
- Process::CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
+ CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
const bool try_dirty_pages = true;
// Some platforms support annotating the region information that tell us that
// it comes from a thread stack. So look for those regions first.
@@ -6668,7 +6668,7 @@ static void GetCoreFileSaveRangesStackOnly(
static void GetUserSpecifiedCoreFileSaveRanges(
Process &process, const MemoryRegionInfos ®ions,
- const SaveCoreOptions &options, Process::CoreFileMemoryRanges &ranges) {
+ const SaveCoreOptions &options, CoreFileMemoryRanges &ranges) {
const auto &option_ranges = options.GetCoreFileMemoryRanges();
if (option_ranges.IsEmpty())
return;
@@ -6682,33 +6682,6 @@ static void GetUserSpecifiedCoreFileSaveRanges(
}
}
-static Status
-FinalizeCoreFileSaveRanges(Process::CoreFileMemoryRanges &ranges) {
- Status error;
- ranges.Sort();
- for (size_t i = ranges.GetSize() - 1; i > 0; i--) {
- auto region = ranges.GetMutableEntryAtIndex(i);
- auto next_region = ranges.GetMutableEntryAtIndex(i - 1);
- if (next_region->GetRangeEnd() >= region->GetRangeBase() &&
- region->GetRangeBase() <= next_region->GetRangeEnd() &&
- region->data.lldb_permissions == next_region->data.lldb_permissions) {
- const addr_t base =
- std::min(region->GetRangeBase(), next_region->GetRangeBase());
- const addr_t byte_size =
- std::max(region->GetRangeEnd(), next_region->GetRangeEnd()) - base;
- next_region->SetRangeBase(base);
- next_region->SetByteSize(byte_size);
- if (!ranges.Erase(i, i + 1)) {
- error = Status::FromErrorString(
- "Core file memory ranges mutated outside of "
- "CalculateCoreFileSaveRanges");
- return error;
- }
- }
- }
- return error;
-}
-
Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
CoreFileMemoryRanges &ranges) {
lldb_private::MemoryRegionInfos regions;
@@ -6758,7 +6731,7 @@ Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
return Status::FromErrorString(
"no valid address ranges found for core style");
- return FinalizeCoreFileSaveRanges(ranges);
+ return ranges.FinalizeCoreFileSaveRanges();
}
std::vector<ThreadSP>
diff --git a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
index eb1259bfc74d1e..bf57dcf4d6531b 100644
--- a/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
+++ b/lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py
@@ -305,12 +305,9 @@ def test_save_linux_mini_dump_default_options(self):
thread_id = thread.GetThreadID()
expected_threads.append(thread_id)
stacks_to_sp_map[thread_id] = thread.GetFrameAtIndex(0).GetSP()
-<<<<<<< HEAD
stacks_to_registers_map[thread_id] = thread.GetFrameAtIndex(
0
).GetRegisters()
-=======
->>>>>>> 32f571ab967c (Reapply "[LLDB][SBSaveCore] Add selectable memory regions to SBSaveCor… (#106293))
# This is almost identical to the single thread test case because
# minidump defaults to stacks only, so we want to see if the
@@ -328,10 +325,7 @@ def test_save_linux_mini_dump_default_options(self):
expected_modules,
expected_threads,
stacks_to_sp_map,
-<<<<<<< HEAD
stacks_to_registers_map,
-=======
->>>>>>> 32f571ab967c (Reapply "[LLDB][SBSaveCore] Add selectable memory regions to SBSaveCor… (#106293))
)
finally:
diff --git a/lldb/unittests/Process/Utility/CMakeLists.txt b/lldb/unittests/Process/Utility/CMakeLists.txt
index 651f871621fdfc..ec0ff95d073b92 100644
--- a/lldb/unittests/Process/Utility/CMakeLists.txt
+++ b/lldb/unittests/Process/Utility/CMakeLists.txt
@@ -18,6 +18,7 @@ add_lldb_unittest(ProcessUtilityTests
LinuxProcMapsTest.cpp
MemoryTagManagerAArch64MTETest.cpp
RegisterContextTest.cpp
+ CoreFileMemoryRangesTest.cpp
${PLATFORM_SOURCES}
LINK_LIBS
diff --git a/lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp b/lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp
new file mode 100644
index 00000000000000..2bec705feac72a
--- /dev/null
+++ b/lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp
@@ -0,0 +1,105 @@
+//===-- CoreFileMemoryRangesTests.cpp ---------------------------------------------===//
+//
+// 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 "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "lldb/lldb-types.h"
+#include "lldb/Target/CoreFileMemoryRanges.h"
+
+using namespace lldb_private;
+
+TEST(CoreFileMemoryRangesTest, MapOverlappingRanges) {
+ lldb_private::CoreFileMemoryRanges ranges;
+ const lldb::addr_t start_addr = 0x1000;
+ const lldb::addr_t increment_addr = 0x1000;
+ const size_t iterations = 10;
+ for (size_t i = 0; i < iterations; i++) {
+ const lldb::addr_t start = start_addr + (i * increment_addr);
+ const lldb::addr_t end = start + increment_addr;
+ // Arbitrary value
+ const uint32_t permissions = 0x3;
+ llvm::AddressRange range(start, end);
+ const CoreFileMemoryRange core_range = {range, permissions};
+ // The range data is Start, Size, While the range is start-end.
+ CoreFileMemoryRanges::Entry entry = {start, end - start, core_range};
+ ranges.Append(entry);
+ }
+
+ Status error = ranges.FinalizeCoreFileSaveRanges();
+ EXPECT_TRUE(error.Success());
+ ASSERT_THAT(1, ranges.GetSize());
+ const auto range = ranges.GetEntryAtIndex(0);
+ ASSERT_TRUE(range);
+ ASSERT_THAT(start_addr, range->GetRangeBase());
+ ASSERT_THAT(start_addr + (iterations * increment_addr), range->GetRangeEnd());
+}
+
+TEST(CoreFileMemoryRangesTest, RangesSplitByPermissions) {
+ lldb_private::CoreFileMemoryRanges ranges;
+ const lldb::addr_t start_addr = 0x1000;
+ const lldb::addr_t increment_addr = 0x1000;
+ const size_t iterations = 10;
+ for (size_t i = 0; i < iterations; i++) {
+ const lldb::addr_t start = start_addr + (i * increment_addr);
+ const lldb::addr_t end = start + increment_addr;
+ const uint32_t permissions = i;
+ llvm::AddressRange range(start, end);
+ const CoreFileMemoryRange core_range = {range, permissions};
+ // The range data is Start, Size, While the range is start-end.
+ CoreFileMemoryRanges::Entry entry = {start, end - start, core_range};
+ ranges.Append(entry);
+ }
+
+ Status error = ranges.FinalizeCoreFileSaveRanges();
+ EXPECT_TRUE(error.Success());
+ ASSERT_THAT(10, ranges.GetSize());
+ const auto range = ranges.GetEntryAtIndex(0);
+ ASSERT_TRUE(range);
+ ASSERT_THAT(start_addr, range->GetRangeBase());
+ ASSERT_THAT(start_addr + increment_addr, range->GetRangeEnd());
+}
+
+TEST(CoreFileMemoryRangesTest, MapPartialOverlappingRanges) {
+ lldb_private::CoreFileMemoryRanges ranges;
+ const lldb::addr_t start_addr = 0x1000;
+ const lldb::addr_t increment_addr = 0x1000;
+ const size_t iterations = 10;
+ for (size_t i = 0; i < iterations; i++) {
+ const lldb::addr_t start = start_addr + (i * increment_addr);
+ const lldb::addr_t end = start + increment_addr;
+ // Arbitrary value
+ const uint32_t permissions = 0x3;
+ llvm::AddressRange range(start, end);
+ const CoreFileMemoryRange core_range = {range, permissions};
+ // The range data is Start, Size, While the range is start-end.
+ CoreFileMemoryRanges::Entry entry = {start, end - start, core_range};
+ ranges.Append(entry);
+ }
+
+ const lldb::addr_t unique_start = 0x7fff0000;
+ const lldb::addr_t unique_end = unique_start + increment_addr;
+ llvm::AddressRange range(unique_start, unique_end);
+ const uint32_t permissions = 0x3;
+ const CoreFileMemoryRange core_range = {range, permissions};
+ // The range data is Start, Size, While the range is start-end.
+ CoreFileMemoryRanges::Entry entry = {unique_start, unique_end - unique_start, core_range};
+ ranges.Append(entry);
+
+ Status error = ranges.FinalizeCoreFileSaveRanges();
+ EXPECT_TRUE(error.Success());
+ ASSERT_THAT(2, ranges.GetSize());
+ const auto merged_range = ranges.GetEntryAtIndex(0);
+ ASSERT_TRUE(merged_range);
+ ASSERT_THAT(start_addr, merged_range->GetRangeBase());
+ ASSERT_THAT(start_addr + (iterations * increment_addr), merged_range->GetRangeEnd());
+ const auto unique_range = ranges.GetEntryAtIndex(1);
+ ASSERT_TRUE(unique_range);
+ ASSERT_THAT(unique_start, unique_range->GetRangeBase());
+ ASSERT_THAT(unique_end, unique_range->GetRangeEnd());
+}
>From 7e31143a2fc07bf009a095b932a7d42379be0068 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Tue, 3 Sep 2024 17:15:48 -0700
Subject: [PATCH 3/3] Run gcf
---
.../lldb/Target/CoreFileMemoryRanges.h | 13 ++--
.../ObjectFile/Minidump/MinidumpFileBuilder.h | 8 +--
lldb/source/Target/CoreFileMemoryRanges.cpp | 59 ++++++++++---------
lldb/source/Target/Process.cpp | 30 ++++++----
.../Utility/CoreFileMemoryRangesTest.cpp | 11 ++--
5 files changed, 65 insertions(+), 56 deletions(-)
diff --git a/lldb/include/lldb/Target/CoreFileMemoryRanges.h b/lldb/include/lldb/Target/CoreFileMemoryRanges.h
index 705ad9bab8a944..503ecd691e5948 100644
--- a/lldb/include/lldb/Target/CoreFileMemoryRanges.h
+++ b/lldb/include/lldb/Target/CoreFileMemoryRanges.h
@@ -37,12 +37,13 @@ struct CoreFileMemoryRange {
}
};
-
-class CoreFileMemoryRanges : public lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, CoreFileMemoryRange> {
- public:
- /// Finalize and merge all overlapping ranges in this collection. Ranges
- /// will be seperated based on permissions.
- Status FinalizeCoreFileSaveRanges();
+class CoreFileMemoryRanges
+ : public lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t,
+ CoreFileMemoryRange> {
+public:
+ /// Finalize and merge all overlapping ranges in this collection. Ranges
+ /// will be seperated based on permissions.
+ Status FinalizeCoreFileSaveRanges();
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
index d7417dd26d796c..71001e26c00e91 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h
@@ -120,10 +120,10 @@ class MinidumpFileBuilder {
// trigger a flush.
lldb_private::Status AddData(const void *data, uint64_t size);
// Add MemoryList stream, containing dumps of important memory segments
- lldb_private::Status AddMemoryList_64(
- std::vector<lldb_private::CoreFileMemoryRange> &ranges);
- lldb_private::Status AddMemoryList_32(
- std::vector<lldb_private::CoreFileMemoryRange> &ranges);
+ lldb_private::Status
+ AddMemoryList_64(std::vector<lldb_private::CoreFileMemoryRange> &ranges);
+ lldb_private::Status
+ AddMemoryList_32(std::vector<lldb_private::CoreFileMemoryRange> &ranges);
// Update the thread list on disk with the newly emitted stack RVAs.
lldb_private::Status FixThreadStacks();
lldb_private::Status FlushBufferToDisk();
diff --git a/lldb/source/Target/CoreFileMemoryRanges.cpp b/lldb/source/Target/CoreFileMemoryRanges.cpp
index c935a3afafe393..c244b5890ac364 100644
--- a/lldb/source/Target/CoreFileMemoryRanges.cpp
+++ b/lldb/source/Target/CoreFileMemoryRanges.cpp
@@ -12,37 +12,38 @@ using namespace lldb;
using namespace lldb_private;
Status CoreFileMemoryRanges::FinalizeCoreFileSaveRanges() {
- Status error;
- std::vector<size_t> indexes_to_remove;
- this->Sort();
- for (size_t i = this->GetSize() - 1; i > 0; i--) {
- auto region = this->GetMutableEntryAtIndex(i);
- auto next_region = this->GetMutableEntryAtIndex(i - 1);
- if (next_region->GetRangeEnd() >= region->GetRangeBase() &&
- region->GetRangeBase() <= next_region->GetRangeEnd() &&
- region->data.lldb_permissions == next_region->data.lldb_permissions) {
- const addr_t base =
- std::min(region->GetRangeBase(), next_region->GetRangeBase());
- const addr_t byte_size =
- std::max(region->GetRangeEnd(), next_region->GetRangeEnd()) - base;
+ Status error;
+ std::vector<size_t> indexes_to_remove;
+ this->Sort();
+ for (size_t i = this->GetSize() - 1; i > 0; i--) {
+ auto region = this->GetMutableEntryAtIndex(i);
+ auto next_region = this->GetMutableEntryAtIndex(i - 1);
+ if (next_region->GetRangeEnd() >= region->GetRangeBase() &&
+ region->GetRangeBase() <= next_region->GetRangeEnd() &&
+ region->data.lldb_permissions == next_region->data.lldb_permissions) {
+ const addr_t base =
+ std::min(region->GetRangeBase(), next_region->GetRangeBase());
+ const addr_t byte_size =
+ std::max(region->GetRangeEnd(), next_region->GetRangeEnd()) - base;
- next_region->SetRangeBase(base);
- next_region->SetByteSize(byte_size);
+ next_region->SetRangeBase(base);
+ next_region->SetByteSize(byte_size);
- // Because this is a range data vector, the entry has a base as well
- // as the data contained in the entry. So we have to update both.
- // And llvm::AddressRange isn't mutable so we have to create a new one.
- llvm::AddressRange range (base, base + byte_size);
- const CoreFileMemoryRange core_range = {range, next_region->data.lldb_permissions};
- next_region->data = core_range;
- if (!this->Erase(i, i + 1)) {
- error = Status::FromErrorString(
- "Core file memory ranges mutated outside of "
- "CalculateCoreFileSaveRanges");
- return error;
- }
+ // Because this is a range data vector, the entry has a base as well
+ // as the data contained in the entry. So we have to update both.
+ // And llvm::AddressRange isn't mutable so we have to create a new one.
+ llvm::AddressRange range(base, base + byte_size);
+ const CoreFileMemoryRange core_range = {
+ range, next_region->data.lldb_permissions};
+ next_region->data = core_range;
+ if (!this->Erase(i, i + 1)) {
+ error = Status::FromErrorString(
+ "Core file memory ranges mutated outside of "
+ "CalculateCoreFileSaveRanges");
+ return error;
}
}
-
- return error;
+ }
+
+ return error;
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 88c305a5512190..94bcd0a0715e53 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -6563,10 +6563,11 @@ static void AddRegion(const MemoryRegionInfo ®ion, bool try_dirty_pages,
CreateCoreFileMemoryRange(region));
}
-static void SaveOffRegionsWithStackPointers(
- Process &process, const SaveCoreOptions &core_options,
- const MemoryRegionInfos ®ions, CoreFileMemoryRanges &ranges,
- std::set<addr_t> &stack_ends) {
+static void SaveOffRegionsWithStackPointers(Process &process,
+ const SaveCoreOptions &core_options,
+ const MemoryRegionInfos ®ions,
+ CoreFileMemoryRanges &ranges,
+ std::set<addr_t> &stack_ends) {
const bool try_dirty_pages = true;
// Before we take any dump, we want to save off the used portions of the
@@ -6620,9 +6621,10 @@ static void GetCoreFileSaveRangesFull(Process &process,
// least some dirty pages, as some OS versions don't support reporting what
// pages are dirty within an memory region. If no memory regions have dirty
// page information fall back to saving out all ranges with write permissions.
-static void GetCoreFileSaveRangesDirtyOnly(
- Process &process, const MemoryRegionInfos ®ions,
- CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
+static void GetCoreFileSaveRangesDirtyOnly(Process &process,
+ const MemoryRegionInfos ®ions,
+ CoreFileMemoryRanges &ranges,
+ std::set<addr_t> &stack_ends) {
// Iterate over the regions and find all dirty pages.
bool have_dirty_page_info = false;
@@ -6651,9 +6653,10 @@ static void GetCoreFileSaveRangesDirtyOnly(
// dirty regions as this will make the core file smaller. If the process
// doesn't support dirty regions, then it will fall back to adding the full
// stack region.
-static void GetCoreFileSaveRangesStackOnly(
- Process &process, const MemoryRegionInfos ®ions,
- CoreFileMemoryRanges &ranges, std::set<addr_t> &stack_ends) {
+static void GetCoreFileSaveRangesStackOnly(Process &process,
+ const MemoryRegionInfos ®ions,
+ CoreFileMemoryRanges &ranges,
+ std::set<addr_t> &stack_ends) {
const bool try_dirty_pages = true;
// Some platforms support annotating the region information that tell us that
// it comes from a thread stack. So look for those regions first.
@@ -6666,9 +6669,10 @@ static void GetCoreFileSaveRangesStackOnly(
}
}
-static void GetUserSpecifiedCoreFileSaveRanges(
- Process &process, const MemoryRegionInfos ®ions,
- const SaveCoreOptions &options, CoreFileMemoryRanges &ranges) {
+static void GetUserSpecifiedCoreFileSaveRanges(Process &process,
+ const MemoryRegionInfos ®ions,
+ const SaveCoreOptions &options,
+ CoreFileMemoryRanges &ranges) {
const auto &option_ranges = options.GetCoreFileMemoryRanges();
if (option_ranges.IsEmpty())
return;
diff --git a/lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp b/lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp
index 2bec705feac72a..7f1254acf6f53a 100644
--- a/lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp
+++ b/lldb/unittests/Process/Utility/CoreFileMemoryRangesTest.cpp
@@ -1,4 +1,5 @@
-//===-- CoreFileMemoryRangesTests.cpp ---------------------------------------------===//
+//===-- CoreFileMemoryRangesTests.cpp
+//---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -9,8 +10,8 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "lldb/lldb-types.h"
#include "lldb/Target/CoreFileMemoryRanges.h"
+#include "lldb/lldb-types.h"
using namespace lldb_private;
@@ -88,7 +89,8 @@ TEST(CoreFileMemoryRangesTest, MapPartialOverlappingRanges) {
const uint32_t permissions = 0x3;
const CoreFileMemoryRange core_range = {range, permissions};
// The range data is Start, Size, While the range is start-end.
- CoreFileMemoryRanges::Entry entry = {unique_start, unique_end - unique_start, core_range};
+ CoreFileMemoryRanges::Entry entry = {unique_start, unique_end - unique_start,
+ core_range};
ranges.Append(entry);
Status error = ranges.FinalizeCoreFileSaveRanges();
@@ -97,7 +99,8 @@ TEST(CoreFileMemoryRangesTest, MapPartialOverlappingRanges) {
const auto merged_range = ranges.GetEntryAtIndex(0);
ASSERT_TRUE(merged_range);
ASSERT_THAT(start_addr, merged_range->GetRangeBase());
- ASSERT_THAT(start_addr + (iterations * increment_addr), merged_range->GetRangeEnd());
+ ASSERT_THAT(start_addr + (iterations * increment_addr),
+ merged_range->GetRangeEnd());
const auto unique_range = ranges.GetEntryAtIndex(1);
ASSERT_TRUE(unique_range);
ASSERT_THAT(unique_start, unique_range->GetRangeBase());
More information about the lldb-commits
mailing list