Skip to content

Commit d517b22

Browse files
authored
[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.
1 parent 556e9d0 commit d517b22

20 files changed

+302
-32
lines changed

lldb/include/lldb/API/SBMemoryRegionInfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class LLDB_API SBMemoryRegionInfo {
120120
private:
121121
friend class SBProcess;
122122
friend class SBMemoryRegionInfoList;
123-
123+
friend class SBSaveCoreOptions;
124124
friend class lldb_private::ScriptInterpreter;
125125

126126
lldb_private::MemoryRegionInfo &ref();

lldb/include/lldb/API/SBSaveCoreOptions.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ class LLDB_API SBSaveCoreOptions {
8080
/// \return True if the thread was removed, false if it was not in the list.
8181
bool RemoveThread(lldb::SBThread thread);
8282

83+
/// Add a memory region to save in the core file.
84+
///
85+
/// \param region The memory region to save.
86+
/// \returns An empty SBError upon success, or an error if the region is
87+
/// invalid.
88+
/// \note Ranges that overlapped will be unioned into a single region, this
89+
/// also supercedes stack minification. Specifying full regions and a
90+
/// non-custom core style will include the specified regions and union them
91+
/// with all style specific regions.
92+
SBError AddMemoryRegionToSave(const SBMemoryRegionInfo &region);
93+
8394
/// Reset all options.
8495
void Clear();
8596

lldb/include/lldb/Symbol/SaveCoreOptions.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_SaveCoreOPTIONS_H
1111

1212
#include "lldb/Utility/FileSpec.h"
13-
#include "lldb/lldb-forward.h"
14-
#include "lldb/lldb-types.h"
13+
#include "lldb/Utility/RangeMap.h"
1514

1615
#include <optional>
16+
#include <set>
1717
#include <string>
1818
#include <unordered_set>
1919

20+
using MemoryRanges = lldb_private::RangeVector<lldb::addr_t, lldb::addr_t>;
21+
2022
namespace lldb_private {
2123

2224
class SaveCoreOptions {
@@ -38,8 +40,12 @@ class SaveCoreOptions {
3840
Status AddThread(lldb::ThreadSP thread_sp);
3941
bool RemoveThread(lldb::ThreadSP thread_sp);
4042
bool ShouldThreadBeSaved(lldb::tid_t tid) const;
43+
bool HasSpecifiedThreads() const;
4144

4245
Status EnsureValidConfiguration(lldb::ProcessSP process_sp) const;
46+
const MemoryRanges &GetCoreFileMemoryRanges() const;
47+
48+
void AddMemoryRegionToSave(const lldb_private::MemoryRegionInfo &region);
4349

4450
void Clear();
4551

@@ -51,6 +57,7 @@ class SaveCoreOptions {
5157
std::optional<lldb::SaveCoreStyle> m_style;
5258
lldb::ProcessSP m_process_sp;
5359
std::unordered_set<lldb::tid_t> m_threads_to_save;
60+
MemoryRanges m_regions_to_save;
5461
};
5562
} // namespace lldb_private
5663

lldb/include/lldb/Target/Process.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "lldb/Host/ProcessLaunchInfo.h"
3636
#include "lldb/Host/ProcessRunLock.h"
3737
#include "lldb/Symbol/ObjectFile.h"
38+
#include "lldb/Symbol/SaveCoreOptions.h"
3839
#include "lldb/Target/ExecutionContextScope.h"
3940
#include "lldb/Target/InstrumentationRuntime.h"
4041
#include "lldb/Target/Memory.h"
@@ -733,7 +734,9 @@ class Process : public std::enable_shared_from_this<Process>,
733734
}
734735
};
735736

736-
using CoreFileMemoryRanges = std::vector<CoreFileMemoryRange>;
737+
using CoreFileMemoryRanges =
738+
lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t,
739+
CoreFileMemoryRange>;
737740

738741
/// Helper function for Process::SaveCore(...) that calculates the address
739742
/// ranges that should be saved. This allows all core file plug-ins to save

lldb/include/lldb/Utility/RangeMap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,8 @@ class RangeDataVector {
450450

451451
void Append(const Entry &entry) { m_entries.emplace_back(entry); }
452452

453+
void Append(B &&b, S &&s, T &&t) { m_entries.emplace_back(Entry(b, s, t)); }
454+
453455
bool Erase(uint32_t start, uint32_t end) {
454456
if (start >= end || end > m_entries.size())
455457
return false;

lldb/include/lldb/lldb-enumerations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,7 @@ enum SaveCoreStyle {
12221222
eSaveCoreFull = 1,
12231223
eSaveCoreDirtyOnly = 2,
12241224
eSaveCoreStackOnly = 3,
1225+
eSaveCoreCustomOnly = 4,
12251226
};
12261227

12271228
/// Events that might happen during a trace session.

lldb/include/lldb/lldb-forward.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ class StackFrameRecognizer;
207207
class StackFrameRecognizerManager;
208208
class StackID;
209209
class Status;
210+
class SaveCoreOptions;
210211
class StopInfo;
211212
class Stoppoint;
212213
class StoppointCallbackContext;

lldb/include/lldb/lldb-private-interfaces.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#ifndef LLDB_LLDB_PRIVATE_INTERFACES_H
1010
#define LLDB_LLDB_PRIVATE_INTERFACES_H
1111

12-
#include "lldb/Symbol/SaveCoreOptions.h"
1312
#include "lldb/lldb-enumerations.h"
1413
#include "lldb/lldb-forward.h"
1514
#include "lldb/lldb-private-enumerations.h"

lldb/source/API/SBSaveCoreOptions.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/API/SBSaveCoreOptions.h"
10+
#include "lldb/API/SBMemoryRegionInfo.h"
1011
#include "lldb/Host/FileSystem.h"
1112
#include "lldb/Symbol/SaveCoreOptions.h"
1213
#include "lldb/Utility/Instrumentation.h"
@@ -90,6 +91,16 @@ bool SBSaveCoreOptions::RemoveThread(lldb::SBThread thread) {
9091
return m_opaque_up->RemoveThread(thread.GetSP());
9192
}
9293

94+
lldb::SBError
95+
SBSaveCoreOptions::AddMemoryRegionToSave(const SBMemoryRegionInfo &region) {
96+
LLDB_INSTRUMENT_VA(this, region);
97+
// Currently add memory region can't fail, so we always return a success
98+
// SBerror, but because these API's live forever, this is the most future
99+
// proof thing to do.
100+
m_opaque_up->AddMemoryRegionToSave(region.ref());
101+
return SBError();
102+
}
103+
93104
void SBSaveCoreOptions::Clear() {
94105
LLDB_INSTRUMENT_VA(this);
95106
m_opaque_up->Clear();

lldb/source/Commands/CommandObjectProcess.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "lldb/Interpreter/OptionArgParser.h"
2626
#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
2727
#include "lldb/Interpreter/Options.h"
28+
#include "lldb/Symbol/SaveCoreOptions.h"
2829
#include "lldb/Target/Platform.h"
2930
#include "lldb/Target/Process.h"
3031
#include "lldb/Target/StopInfo.h"

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6568,7 +6568,9 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
65686568
const uint32_t addr_byte_size = target_arch.GetAddressByteSize();
65696569
const ByteOrder byte_order = target_arch.GetByteOrder();
65706570
std::vector<llvm::MachO::segment_command_64> segment_load_commands;
6571-
for (const auto &core_range : core_ranges) {
6571+
for (const auto &core_range_info : core_ranges) {
6572+
// TODO: Refactor RangeDataVector to have a data iterator.
6573+
const auto &core_range = core_range_info.data;
65726574
uint32_t cmd_type = LC_SEGMENT_64;
65736575
uint32_t segment_size = sizeof(llvm::MachO::segment_command_64);
65746576
if (addr_byte_size == 4) {

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "lldb/Core/Address.h"
1313
#include "lldb/Host/SafeMachO.h"
1414
#include "lldb/Symbol/ObjectFile.h"
15+
#include "lldb/Symbol/SaveCoreOptions.h"
1516
#include "lldb/Utility/FileSpec.h"
1617
#include "lldb/Utility/FileSpecList.h"
1718
#include "lldb/Utility/RangeMap.h"

lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -823,25 +823,32 @@ Status MinidumpFileBuilder::AddMemoryList() {
823823
// bytes of the core file. Thread structures in minidump files can only use
824824
// 32 bit memory descriptiors, so we emit them first to ensure the memory is
825825
// in accessible with a 32 bit offset.
826-
Process::CoreFileMemoryRanges ranges_32;
827-
Process::CoreFileMemoryRanges ranges_64;
826+
std::vector<Process::CoreFileMemoryRange> ranges_32;
827+
std::vector<Process::CoreFileMemoryRange> ranges_64;
828828
Process::CoreFileMemoryRanges all_core_memory_ranges;
829829
error = m_process_sp->CalculateCoreFileSaveRanges(m_save_core_options,
830830
all_core_memory_ranges);
831+
832+
std::vector<Process::CoreFileMemoryRange> all_core_memory_vec;
833+
// Extract all the data into just a vector of data. So we can mutate this in
834+
// place.
835+
for (const auto &core_range : all_core_memory_ranges)
836+
all_core_memory_vec.push_back(core_range.data);
837+
831838
if (error.Fail())
832839
return error;
833840

834841
// Start by saving all of the stacks and ensuring they fit under the 32b
835842
// limit.
836843
uint64_t total_size = GetCurrentDataEndOffset();
837-
auto iterator = all_core_memory_ranges.begin();
838-
while (iterator != all_core_memory_ranges.end()) {
844+
auto iterator = all_core_memory_vec.begin();
845+
while (iterator != all_core_memory_vec.end()) {
839846
if (m_saved_stack_ranges.count(iterator->range.start()) > 0) {
840847
// We don't save stacks twice.
841848
ranges_32.push_back(*iterator);
842849
total_size +=
843850
iterator->range.size() + sizeof(llvm::minidump::MemoryDescriptor);
844-
iterator = all_core_memory_ranges.erase(iterator);
851+
iterator = all_core_memory_vec.erase(iterator);
845852
} else {
846853
iterator++;
847854
}
@@ -860,11 +867,11 @@ Status MinidumpFileBuilder::AddMemoryList() {
860867
// Then anything overflow extends into 64b addressable space.
861868
// All core memeroy ranges will either container nothing on stacks only
862869
// or all the memory ranges including stacks
863-
if (!all_core_memory_ranges.empty())
864-
total_size += 256 + (all_core_memory_ranges.size() *
870+
if (!all_core_memory_vec.empty())
871+
total_size += 256 + (all_core_memory_vec.size() *
865872
sizeof(llvm::minidump::MemoryDescriptor_64));
866873

867-
for (const auto &core_range : all_core_memory_ranges) {
874+
for (const auto &core_range : all_core_memory_vec) {
868875
const addr_t range_size = core_range.range.size();
869876
// We don't need to check for stacks here because we already removed them
870877
// from all_core_memory_ranges.
@@ -949,15 +956,15 @@ Status MinidumpFileBuilder::DumpDirectories() const {
949956
}
950957

951958
static uint64_t
952-
GetLargestRangeSize(const Process::CoreFileMemoryRanges &ranges) {
959+
GetLargestRangeSize(const std::vector<Process::CoreFileMemoryRange> &ranges) {
953960
uint64_t max_size = 0;
954961
for (const auto &core_range : ranges)
955962
max_size = std::max(max_size, core_range.range.size());
956963
return max_size;
957964
}
958965

959-
Status
960-
MinidumpFileBuilder::AddMemoryList_32(Process::CoreFileMemoryRanges &ranges) {
966+
Status MinidumpFileBuilder::AddMemoryList_32(
967+
std::vector<Process::CoreFileMemoryRange> &ranges) {
961968
std::vector<MemoryDescriptor> descriptors;
962969
Status error;
963970
if (ranges.size() == 0)
@@ -1033,8 +1040,8 @@ MinidumpFileBuilder::AddMemoryList_32(Process::CoreFileMemoryRanges &ranges) {
10331040
return error;
10341041
}
10351042

1036-
Status
1037-
MinidumpFileBuilder::AddMemoryList_64(Process::CoreFileMemoryRanges &ranges) {
1043+
Status MinidumpFileBuilder::AddMemoryList_64(
1044+
std::vector<Process::CoreFileMemoryRange> &ranges) {
10381045
Status error;
10391046
if (ranges.empty())
10401047
return error;

lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <utility>
2424
#include <variant>
2525

26+
#include "lldb/Symbol/SaveCoreOptions.h"
2627
#include "lldb/Target/Process.h"
2728
#include "lldb/Target/Target.h"
2829
#include "lldb/Utility/DataBufferHeap.h"
@@ -119,10 +120,10 @@ class MinidumpFileBuilder {
119120
// trigger a flush.
120121
lldb_private::Status AddData(const void *data, uint64_t size);
121122
// Add MemoryList stream, containing dumps of important memory segments
122-
lldb_private::Status
123-
AddMemoryList_64(lldb_private::Process::CoreFileMemoryRanges &ranges);
124-
lldb_private::Status
125-
AddMemoryList_32(lldb_private::Process::CoreFileMemoryRanges &ranges);
123+
lldb_private::Status AddMemoryList_64(
124+
std::vector<lldb_private::Process::CoreFileMemoryRange> &ranges);
125+
lldb_private::Status AddMemoryList_32(
126+
std::vector<lldb_private::Process::CoreFileMemoryRange> &ranges);
126127
// Update the thread list on disk with the newly emitted stack RVAs.
127128
lldb_private::Status FixThreadStacks();
128129
lldb_private::Status FlushBufferToDisk();

lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_OBJECTFILEMINIDUMP_H
2222

2323
#include "lldb/Symbol/ObjectFile.h"
24+
#include "lldb/Symbol/SaveCoreOptions.h"
2425
#include "lldb/Utility/ArchSpec.h"
2526

2627
class ObjectFileMinidump : public lldb_private::PluginInterface {

lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "lldb/Interpreter/OptionValueDictionary.h"
1818
#include "lldb/Interpreter/OptionValueProperties.h"
1919
#include "lldb/Symbol/ObjectFile.h"
20+
#include "lldb/Symbol/SaveCoreOptions.h"
2021
#include "lldb/Target/Process.h"
2122
#include "lldb/Target/SectionLoadList.h"
2223
#include "lldb/Target/Target.h"

lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <vector>
1414

1515
#include "lldb/Symbol/ObjectFile.h"
16+
#include "lldb/Symbol/SaveCoreOptions.h"
1617
#include "llvm/Object/COFF.h"
1718

1819
class ObjectFilePECOFF : public lldb_private::ObjectFile {

lldb/source/Symbol/SaveCoreOptions.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,19 @@ bool SaveCoreOptions::ShouldThreadBeSaved(lldb::tid_t tid) const {
101101
return m_threads_to_save.count(tid) > 0;
102102
}
103103

104+
bool SaveCoreOptions::HasSpecifiedThreads() const {
105+
return !m_threads_to_save.empty();
106+
}
107+
108+
void SaveCoreOptions::AddMemoryRegionToSave(
109+
const lldb_private::MemoryRegionInfo &region) {
110+
m_regions_to_save.Insert(region.GetRange(), /*combine=*/true);
111+
}
112+
113+
const MemoryRanges &SaveCoreOptions::GetCoreFileMemoryRanges() const {
114+
return m_regions_to_save;
115+
}
116+
104117
Status SaveCoreOptions::EnsureValidConfiguration(
105118
lldb::ProcessSP process_sp) const {
106119
Status error;
@@ -130,4 +143,5 @@ void SaveCoreOptions::Clear() {
130143
m_style = std::nullopt;
131144
m_threads_to_save.clear();
132145
m_process_sp.reset();
146+
m_regions_to_save.Clear();
133147
}

0 commit comments

Comments
 (0)