[LLDB][SBSaveCore] Add selectable memory regions to SBSaveCore (#105442)

This patch adds the option to specify specific memory ranges to be
included in a given core file. The current implementation lets user
specified ranges either be in addition to a certain save style, or
independent of them via the newly added custom enum.

To achieve being inclusive of save style, I've moved from a std::vector
of ranges to a RangeDataVector, and to join overlapping ranges to
prevent duplication of memory ranges in the core file.

As a non function bonus, when SBSavecore was initially created, the
header was included in the lldb-private interfaces, and I've fixed that
and moved it the forward declare as an oversight. CC @bulbazord in case
we need to include that into swift.
This commit is contained in:
Jacob Lalonde
2024-08-27 07:33:12 -07:00
committed by GitHub
parent 556e9d0386
commit d517b22411
20 changed files with 302 additions and 32 deletions

View File

@@ -6517,14 +6517,14 @@ static bool AddDirtyPages(const MemoryRegionInfo &region,
} 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;
}
@@ -6545,7 +6545,10 @@ static void AddRegion(const MemoryRegionInfo &region, 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(
@@ -6595,7 +6598,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 &region : regions)
if (stack_ends.count(region.GetRange().GetRangeEnd()) == 0)
AddRegion(region, try_dirty_pages, ranges);
@@ -6651,6 +6654,48 @@ static void GetCoreFileSaveRangesStackOnly(
}
}
static void GetUserSpecifiedCoreFileSaveRanges(
Process &process, const MemoryRegionInfos &regions,
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.SetErrorString("Core file memory ranges mutated outside of "
"CalculateCoreFileSaveRanges");
return error;
}
}
}
return error;
}
Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
CoreFileMemoryRanges &ranges) {
lldb_private::MemoryRegionInfos regions;
@@ -6664,11 +6709,18 @@ Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
return Status("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:
@@ -6687,10 +6739,10 @@ Status Process::CalculateCoreFileSaveRanges(const SaveCoreOptions &options,
if (err.Fail())
return err;
if (ranges.empty())
if (ranges.IsEmpty())
return Status("no valid address ranges found for core style");
return Status(); // Success!
return FinalizeCoreFileSaveRanges(ranges);
}
std::vector<ThreadSP>