Skip to content

Commit 6a7f572

Browse files
authored
[LLDB] Fix Memory64 BaseRVA, move all non-stack memory to Mem64. (#146777)
### Context Over a year ago, I landed support for 64b Memory ranges in Minidump (#95312). In this patch we added the Memory64 list stream, which is effectively a Linked List on disk. The layout is a sixteen byte header and then however many Memory descriptors. ### The Bug This is a classic off-by one error, where I added 8 bytes instead of 16 for the header. This caused the first region to start 8 bytes before the correct RVA, thus shifting all memory reads by 8 bytes. We are correctly writing all the regions to disk correctly, with no physical corruption but the RVA is defined wrong, meaning we were incorrectly reading memory ![image](https://github.com/user-attachments/assets/049ef55d-856c-4f3c-9376-aeaa3fe8c0e1) ### Why wasn't this caught? One problem we've had is forcing Minidump to actually use the 64b mode, it would be a massive waste of resources to have a test that actually wrote >4.2gb of IO to validate the 64b regions, and so almost all validation has been manual. As a weakness of manual testing, this issue is psuedo non-deterministic, as what regions end up in 64b or 32b is handled greedily and iterated in the order it's laid out in /proc/pid/maps. We often validated 64b was written correctly by hexdumping the Minidump itself, which was not corrupted (other than the BaseRVA) ![image](https://github.com/user-attachments/assets/b599e3be-2d59-47e2-8a2d-75f182bb0b1d) ### Why is this showing up now? During internal usage, we had a bug report that the Minidump wasn't displaying values. I was unable to repro the issue, but during my investigation I saw the variables were in the 64b regions which resulted in me identifying the bug. ### How do we prevent future regressions? To prevent regressions, and honestly to save my sanity for figuring out where 8 bytes magically came from, I've added a new API to SBSaveCoreOptions. ```SBSaveCoreOptions::GetMemoryRegionsToSave()``` The ability to get the memory regions that we intend to include in the Coredump. I added this so we can compare what we intended to include versus what was actually included. Traditionally we've always had issues comparing regions because Minidump includes `/proc/pid/maps` and it can be difficult to know what memoryregion read failure was a genuine error or just a page that wasn't meant to be included. We are also leveraging this API to choose the memory regions to be generated, as well as for testing what regions should be bytewise 1:1. After much debate with @clayborg, I've moved all non-stack memory to the Memory64 List. This list doesn't incur us any meaningful overhead and Greg originally suggested doing this in the original 64b PR. This also means we're exercising the 64b path every single time we save a Minidump, preventing regressions on this feature from slipping through testing in the future. Snippet produced by [minidump.py](https://github.com/clayborg/scripts) ``` MINIDUMP_MEMORY_LIST: NumberOfMemoryRanges = 0x00000002 MemoryRanges[0] = [0x00007f61085ff9f0 - 0x00007f6108601000) @ 0x0003f655 MemoryRanges[1] = [0x00007ffe47e50910 - 0x00007ffe47e52000) @ 0x00040c65 MINIDUMP_MEMORY64_LIST: NumberOfMemoryRanges = 0x000000000000002e BaseRva = 0x0000000000042669 MemoryRanges[0] = [0x00005584162d8000 - 0x00005584162d9000) MemoryRanges[1] = [0x00005584162d9000 - 0x00005584162db000) MemoryRanges[2] = [0x00005584162db000 - 0x00005584162dd000) MemoryRanges[3] = [0x00005584162dd000 - 0x00005584162ff000) MemoryRanges[4] = [0x00007f6100000000 - 0x00007f6100021000) MemoryRanges[5] = [0x00007f6108800000 - 0x00007f6108828000) MemoryRanges[6] = [0x00007f6108828000 - 0x00007f610899d000) MemoryRanges[7] = [0x00007f610899d000 - 0x00007f61089f9000) MemoryRanges[8] = [0x00007f61089f9000 - 0x00007f6108a08000) MemoryRanges[9] = [0x00007f6108bf5000 - 0x00007f6108bf7000) ``` ### Misc As a part of this fix I had to look at LLDB logs a lot, you'll notice I added `0x` to many of the PRIx64 `LLDB_LOGF`. This is so the user (or I) can directly copy paste the address in the logs instead of adding the hex prefix themselves. Added some SBSaveCore tests for the new GetMemoryAPI, and Docstrings. CC: @DavidSpickett, @da-viper @labath because we've been working together on save-core plugins, review it optional and I didn't tag you but figured you'd want to know
1 parent de59e7b commit 6a7f572

File tree

13 files changed

+290
-58
lines changed

13 files changed

+290
-58
lines changed

lldb/bindings/interface/SBSaveCoreOptionsDocstrings.i

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ Note that currently ELF Core files are not supported."
4545
Resetting will result in the reset of all process specific options, such as Threads to save."
4646
) lldb::SBSaveCoreOptions::SetProcess;
4747

48+
%feature("docstring", "
49+
Get the process to save. If a process is not defined, whether by calling clear or by not setting a process, an invalid process will be returned."
50+
) lldb::SBSaveCoreOptions::GetProcess;
51+
4852
%feature("docstring", "
4953
Add an SBThread to be saved, an error will be returned if an SBThread from a different process is specified.
5054
The process is set either by the first SBThread added to the options container, or explicitly by the SetProcess call."
@@ -63,6 +67,12 @@ Note that currently ELF Core files are not supported."
6367
Get an SBThreadCollection of all threads marked to be saved. This collection is not sorted according to insertion order."
6468
) lldb::SBSaveCoreOptions::GetThreadsToSave;
6569

70+
%feature("docstring", "
71+
Get an SBMemoryRegionInfoList of all the Regions that LLDB will attempt to write into the Core. Note, reading from these
72+
regions can fail, and it's not guaraunteed every region will be present in the resulting core. If called without a valid process or style set an empty
73+
collection will be returned."
74+
) lldb::SBSaveCoreOptions::GetMemoryRegionsToSave;
75+
6676
%feature("docstring", "
6777
Get the current total number of bytes the core is expected to have, excluding the overhead of the core file format.
6878
Requires both a Process and a Style to be specified. An error will be returned if the provided options would result in no data being saved."

lldb/include/lldb/API/SBMemoryRegionInfoList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class LLDB_API SBMemoryRegionInfoList {
4545

4646
private:
4747
friend class SBProcess;
48+
friend class SBSaveCoreOptions;
4849

4950
lldb_private::MemoryRegionInfos &ref();
5051

lldb/include/lldb/API/SBSaveCoreOptions.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "lldb/API/SBDefines.h"
1313
#include "lldb/API/SBError.h"
1414
#include "lldb/API/SBFileSpec.h"
15+
#include "lldb/API/SBMemoryRegionInfoList.h"
1516
#include "lldb/API/SBProcess.h"
1617
#include "lldb/API/SBThread.h"
1718
#include "lldb/API/SBThreadCollection.h"
@@ -78,6 +79,13 @@ class LLDB_API SBSaveCoreOptions {
7879
/// api, or implicitly from any function that requires a process.
7980
SBError SetProcess(lldb::SBProcess process);
8081

82+
/// Get the process to save, if the process is not set an invalid SBProcess
83+
/// will be returned.
84+
///
85+
/// \return
86+
/// The set process, or an invalid SBProcess if no process is set.
87+
SBProcess GetProcess();
88+
8189
/// Add a thread to save in the core file.
8290
///
8391
/// \param thread
@@ -119,6 +127,13 @@ class LLDB_API SBSaveCoreOptions {
119127
/// an empty collection will be returned.
120128
SBThreadCollection GetThreadsToSave() const;
121129

130+
/// Get an unsorted copy of all memory regions to save
131+
///
132+
/// \returns
133+
/// An unsorted copy of all memory regions to save. If no process or style
134+
/// is specified an empty collection will be returned.
135+
SBMemoryRegionInfoList GetMemoryRegionsToSave();
136+
122137
/// Get the current total number of bytes the core is expected to have
123138
/// excluding the overhead of the core file format. Requires a Process and
124139
/// Style to be specified.

lldb/include/lldb/Core/PluginManager.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,7 @@ class PluginManager {
261261
static ObjectFileCreateMemoryInstance
262262
GetObjectFileCreateMemoryCallbackForPluginName(llvm::StringRef name);
263263

264-
static Status SaveCore(const lldb::ProcessSP &process_sp,
265-
lldb_private::SaveCoreOptions &core_options);
264+
static Status SaveCore(lldb_private::SaveCoreOptions &core_options);
266265

267266
static std::vector<llvm::StringRef> GetSaveCorePluginNames();
268267

lldb/include/lldb/Symbol/SaveCoreOptions.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_SaveCoreOPTIONS_H
1010
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_SaveCoreOPTIONS_H
1111

12+
#include "lldb/Target/CoreFileMemoryRanges.h"
1213
#include "lldb/Target/ThreadCollection.h"
1314
#include "lldb/Utility/FileSpec.h"
1415
#include "lldb/Utility/RangeMap.h"
@@ -23,7 +24,7 @@ namespace lldb_private {
2324

2425
class SaveCoreOptions {
2526
public:
26-
SaveCoreOptions(){};
27+
SaveCoreOptions() = default;
2728
~SaveCoreOptions() = default;
2829

2930
lldb_private::Status SetPluginName(const char *name);
@@ -36,17 +37,19 @@ class SaveCoreOptions {
3637
const std::optional<lldb_private::FileSpec> GetOutputFile() const;
3738

3839
Status SetProcess(lldb::ProcessSP process_sp);
40+
lldb::ProcessSP GetProcess() { return m_process_sp; }
3941

4042
Status AddThread(lldb::ThreadSP thread_sp);
4143
bool RemoveThread(lldb::ThreadSP thread_sp);
4244
bool ShouldThreadBeSaved(lldb::tid_t tid) const;
4345
bool HasSpecifiedThreads() const;
4446

45-
Status EnsureValidConfiguration(lldb::ProcessSP process_sp) const;
47+
Status EnsureValidConfiguration() const;
4648
const MemoryRanges &GetCoreFileMemoryRanges() const;
4749

4850
void AddMemoryRegionToSave(const lldb_private::MemoryRegionInfo &region);
4951

52+
llvm::Expected<lldb_private::CoreFileMemoryRanges> GetMemoryRegionsToSave();
5053
lldb_private::ThreadCollection::collection GetThreadsToSave() const;
5154

5255
llvm::Expected<uint64_t> GetCurrentSizeInBytes();

lldb/source/API/SBProcess.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,15 @@ lldb::SBError SBProcess::SaveCore(SBSaveCoreOptions &options) {
12631263
return error;
12641264
}
12651265

1266+
if (!options.GetProcess())
1267+
options.SetProcess(process_sp);
1268+
1269+
if (options.GetProcess().GetSP() != process_sp) {
1270+
error = Status::FromErrorString(
1271+
"Save Core Options configured for a different process.");
1272+
return error;
1273+
}
1274+
12661275
std::lock_guard<std::recursive_mutex> guard(
12671276
process_sp->GetTarget().GetAPIMutex());
12681277

@@ -1271,7 +1280,7 @@ lldb::SBError SBProcess::SaveCore(SBSaveCoreOptions &options) {
12711280
return error;
12721281
}
12731282

1274-
error.ref() = PluginManager::SaveCore(process_sp, options.ref());
1283+
error.ref() = PluginManager::SaveCore(options.ref());
12751284

12761285
return error;
12771286
}

lldb/source/API/SBSaveCoreOptions.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ SBError SBSaveCoreOptions::SetProcess(lldb::SBProcess process) {
8181
return m_opaque_up->SetProcess(process.GetSP());
8282
}
8383

84+
SBProcess SBSaveCoreOptions::GetProcess() {
85+
LLDB_INSTRUMENT_VA(this);
86+
return SBProcess(m_opaque_up->GetProcess());
87+
}
88+
8489
SBError SBSaveCoreOptions::AddThread(lldb::SBThread thread) {
8590
LLDB_INSTRUMENT_VA(this, thread);
8691
return m_opaque_up->AddThread(thread.GetSP());
@@ -128,6 +133,26 @@ uint64_t SBSaveCoreOptions::GetCurrentSizeInBytes(SBError &error) {
128133
return *expected_bytes;
129134
}
130135

136+
lldb::SBMemoryRegionInfoList SBSaveCoreOptions::GetMemoryRegionsToSave() {
137+
LLDB_INSTRUMENT_VA(this);
138+
llvm::Expected<lldb_private::CoreFileMemoryRanges> memory_ranges =
139+
m_opaque_up->GetMemoryRegionsToSave();
140+
if (!memory_ranges) {
141+
llvm::consumeError(memory_ranges.takeError());
142+
return SBMemoryRegionInfoList();
143+
}
144+
145+
SBMemoryRegionInfoList memory_region_infos;
146+
for (const auto &range : *memory_ranges) {
147+
SBMemoryRegionInfo region_info(
148+
nullptr, range.GetRangeBase(), range.GetRangeEnd(),
149+
range.data.lldb_permissions, /*mapped=*/true);
150+
memory_region_infos.Append(region_info);
151+
}
152+
153+
return memory_region_infos;
154+
}
155+
131156
lldb_private::SaveCoreOptions &SBSaveCoreOptions::ref() const {
132157
return *m_opaque_up;
133158
}

lldb/source/Commands/CommandObjectProcess.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1354,7 +1354,8 @@ class CommandObjectProcessSaveCore : public CommandObjectParsed {
13541354
FileSystem::Instance().Resolve(output_file);
13551355
auto &core_dump_options = m_options.m_core_dump_options;
13561356
core_dump_options.SetOutputFile(output_file);
1357-
Status error = PluginManager::SaveCore(process_sp, core_dump_options);
1357+
core_dump_options.SetProcess(process_sp);
1358+
Status error = PluginManager::SaveCore(core_dump_options);
13581359
if (error.Success()) {
13591360
if (core_dump_options.GetStyle() ==
13601361
SaveCoreStyle::eSaveCoreDirtyOnly ||

lldb/source/Core/PluginManager.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -952,27 +952,26 @@ PluginManager::GetObjectFileCreateMemoryCallbackForPluginName(
952952
return nullptr;
953953
}
954954

955-
Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp,
956-
lldb_private::SaveCoreOptions &options) {
955+
Status PluginManager::SaveCore(lldb_private::SaveCoreOptions &options) {
957956
Status error;
958957
if (!options.GetOutputFile()) {
959958
error = Status::FromErrorString("No output file specified");
960959
return error;
961960
}
962961

963-
if (!process_sp) {
962+
if (!options.GetProcess()) {
964963
error = Status::FromErrorString("Invalid process");
965964
return error;
966965
}
967966

968-
error = options.EnsureValidConfiguration(process_sp);
967+
error = options.EnsureValidConfiguration();
969968
if (error.Fail())
970969
return error;
971970

972971
if (!options.GetPluginName().has_value()) {
973972
// Try saving core directly from the process plugin first.
974973
llvm::Expected<bool> ret =
975-
process_sp->SaveCore(options.GetOutputFile()->GetPath());
974+
options.GetProcess()->SaveCore(options.GetOutputFile()->GetPath());
976975
if (!ret)
977976
return Status::FromError(ret.takeError());
978977
if (ret.get())
@@ -984,7 +983,10 @@ Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp,
984983
auto instances = GetObjectFileInstances().GetSnapshot();
985984
for (auto &instance : instances) {
986985
if (plugin_name.empty() || instance.name == plugin_name) {
987-
if (instance.save_core && instance.save_core(process_sp, options, error))
986+
// TODO: Refactor the instance.save_core() to not require a process and
987+
// get it from options instead.
988+
if (instance.save_core &&
989+
instance.save_core(options.GetProcess(), options, error))
988990
return error;
989991
}
990992
}

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

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -836,13 +836,13 @@ Status MinidumpFileBuilder::AddMemoryList() {
836836
// 32 bit memory descriptiors, so we emit them first to ensure the memory is
837837
// in accessible with a 32 bit offset.
838838
std::vector<CoreFileMemoryRange> ranges_32;
839-
std::vector<CoreFileMemoryRange> ranges_64;
840-
CoreFileMemoryRanges all_core_memory_ranges;
841-
error = m_process_sp->CalculateCoreFileSaveRanges(m_save_core_options,
842-
all_core_memory_ranges);
839+
llvm::Expected<CoreFileMemoryRanges> all_core_memory_ranges_maybe =
840+
m_save_core_options.GetMemoryRegionsToSave();
841+
if (!all_core_memory_ranges_maybe)
842+
return Status::FromError(all_core_memory_ranges_maybe.takeError());
843843

844-
if (error.Fail())
845-
return error;
844+
const CoreFileMemoryRanges &all_core_memory_ranges =
845+
*all_core_memory_ranges_maybe;
846846

847847
lldb_private::Progress progress("Saving Minidump File", "",
848848
all_core_memory_ranges.GetSize());
@@ -868,6 +868,10 @@ Status MinidumpFileBuilder::AddMemoryList() {
868868
}
869869
}
870870

871+
// The header has to be in 32b memory, as it needs to be addressable by a 32b
872+
// RVA. Everything else can be 64b.
873+
total_size += sizeof(llvm::minidump::MemoryListHeader);
874+
871875
if (total_size >= UINT32_MAX) {
872876
error = Status::FromErrorStringWithFormat(
873877
"Unable to write minidump. Stack memory "
@@ -876,35 +880,15 @@ Status MinidumpFileBuilder::AddMemoryList() {
876880
return error;
877881
}
878882

879-
// After saving the stacks, we start packing as much as we can into 32b.
880-
// We apply a generous padding here so that the Directory, MemoryList and
881-
// Memory64List sections all begin in 32b addressable space.
882-
// Then anything overflow extends into 64b addressable space.
883-
// all_core_memory_vec will either contain all stack regions at this point,
884-
// or be empty if it's a stack only minidump.
885-
if (!all_core_memory_vec.empty())
886-
total_size += 256 + (all_core_memory_vec.size() *
887-
sizeof(llvm::minidump::MemoryDescriptor_64));
888-
889-
for (const auto &core_range : all_core_memory_vec) {
890-
const addr_t range_size = core_range.range.size();
891-
// We don't need to check for stacks here because we already removed them
892-
// from all_core_memory_ranges.
893-
if (total_size + range_size < UINT32_MAX) {
894-
ranges_32.push_back(core_range);
895-
total_size += range_size;
896-
} else {
897-
ranges_64.push_back(core_range);
898-
}
899-
}
900-
883+
// Save only the thread stacks to the 32b memory list. Everything else will
884+
// get put in Memory64, this simplifies tracking
901885
error = AddMemoryList_32(ranges_32, progress);
902886
if (error.Fail())
903887
return error;
904888

905889
// Add the remaining memory as a 64b range.
906-
if (!ranges_64.empty()) {
907-
error = AddMemoryList_64(ranges_64, progress);
890+
if (!all_core_memory_ranges.IsEmpty()) {
891+
error = AddMemoryList_64(all_core_memory_vec, progress);
908892
if (error.Fail())
909893
return error;
910894
}
@@ -977,14 +961,15 @@ Status MinidumpFileBuilder::ReadWriteMemoryInChunks(
977961
const lldb::addr_t addr = range.range.start();
978962
const lldb::addr_t size = range.range.size();
979963
Log *log = GetLog(LLDBLog::Object);
964+
uint64_t total_bytes_read = 0;
980965
Status addDataError;
981966
Process::ReadMemoryChunkCallback callback =
982967
[&](Status &error, lldb::addr_t current_addr, const void *buf,
983968
uint64_t bytes_read) -> lldb_private::IterationAction {
984969
if (error.Fail() || bytes_read == 0) {
985970
LLDB_LOGF(log,
986971
"Failed to read memory region at: 0x%" PRIx64
987-
". Bytes read: %" PRIx64 ", error: %s",
972+
". Bytes read: 0x%" PRIx64 ", error: %s",
988973
current_addr, bytes_read, error.AsCString());
989974

990975
// If we failed in a memory read, we would normally want to skip
@@ -997,6 +982,21 @@ Status MinidumpFileBuilder::ReadWriteMemoryInChunks(
997982
return lldb_private::IterationAction::Stop;
998983
}
999984

985+
if (current_addr != addr + total_bytes_read) {
986+
LLDB_LOGF(log,
987+
"Current addr is at unexpected address, 0x%" PRIx64
988+
", expected at 0x%" PRIx64,
989+
current_addr, addr + total_bytes_read);
990+
991+
// Something went wrong and the address is not where it should be
992+
// we'll error out of this Minidump generation.
993+
addDataError = Status::FromErrorStringWithFormat(
994+
"Unexpected address encounterd when reading memory in chunks "
995+
"0x%" PRIx64 " expected 0x%" PRIx64,
996+
current_addr, addr + total_bytes_read);
997+
return lldb_private::IterationAction::Stop;
998+
}
999+
10001000
// Write to the minidump file with the chunk potentially flushing to
10011001
// disk.
10021002
// This error will be captured by the outer scope and is considered fatal.
@@ -1006,13 +1006,13 @@ Status MinidumpFileBuilder::ReadWriteMemoryInChunks(
10061006
if (addDataError.Fail())
10071007
return lldb_private::IterationAction::Stop;
10081008

1009+
total_bytes_read += bytes_read;
10091010
// If we have a partial read, report it, but only if the partial read
10101011
// didn't finish reading the entire region.
1011-
if (bytes_read != data_buffer.GetByteSize() &&
1012-
current_addr + bytes_read != size) {
1012+
if (bytes_read != data_buffer.GetByteSize() && total_bytes_read != size) {
10131013
LLDB_LOGF(log,
1014-
"Memory region at: %" PRIx64 " partiall read 0x%" PRIx64
1015-
" bytes out of %" PRIx64 " bytes.",
1014+
"Memory region at: 0x%" PRIx64 " partial read 0x%" PRIx64
1015+
" bytes out of 0x%" PRIx64 " bytes.",
10161016
current_addr, bytes_read,
10171017
data_buffer.GetByteSize() - bytes_read);
10181018

@@ -1059,7 +1059,7 @@ MinidumpFileBuilder::AddMemoryList_32(std::vector<CoreFileMemoryRange> &ranges,
10591059

10601060
LLDB_LOGF(log,
10611061
"AddMemoryList %zu/%zu reading memory for region "
1062-
"(%" PRIx64 " bytes) [%" PRIx64 ", %" PRIx64 ")",
1062+
"(0x%" PRIx64 " bytes) [0x%" PRIx64 ", 0x%" PRIx64 ")",
10631063
region_index, ranges.size(), size, addr, addr + size);
10641064
++region_index;
10651065

@@ -1117,7 +1117,7 @@ MinidumpFileBuilder::AddMemoryList_64(std::vector<CoreFileMemoryRange> &ranges,
11171117
return error;
11181118

11191119
error = AddDirectory(StreamType::Memory64List,
1120-
(sizeof(llvm::support::ulittle64_t) * 2) +
1120+
(sizeof(llvm::minidump::Memory64ListHeader)) +
11211121
ranges.size() *
11221122
sizeof(llvm::minidump::MemoryDescriptor_64));
11231123
if (error.Fail())
@@ -1130,9 +1130,9 @@ MinidumpFileBuilder::AddMemoryList_64(std::vector<CoreFileMemoryRange> &ranges,
11301130
// Capture the starting offset for all the descriptors so we can clean them up
11311131
// if needed.
11321132
offset_t starting_offset =
1133-
GetCurrentDataEndOffset() + sizeof(llvm::support::ulittle64_t);
1133+
GetCurrentDataEndOffset() + sizeof(llvm::minidump::Memory64ListHeader);
11341134
// The base_rva needs to start after the directories, which is right after
1135-
// this 8 byte variable.
1135+
// the descriptors + the size of the header.
11361136
offset_t base_rva =
11371137
starting_offset +
11381138
(ranges.size() * sizeof(llvm::minidump::MemoryDescriptor_64));

0 commit comments

Comments
 (0)