-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[LLDB] Fix Memory64 BaseRVA, move all non-stack memory to Mem64. #146777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e2a8be4
b8ccf45
8f4a37e
50bddba
a9949d9
ef065b1
1685399
b1f4250
b9f46c7
f43d14c
362f5b5
ef67314
b8af394
154cda1
8c52ca7
7aef618
b2e941d
829cb99
efed2cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -836,13 +836,13 @@ Status MinidumpFileBuilder::AddMemoryList() { | |
| // 32 bit memory descriptiors, so we emit them first to ensure the memory is | ||
| // in accessible with a 32 bit offset. | ||
| 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); | ||
| llvm::Expected<CoreFileMemoryRanges> all_core_memory_ranges_maybe = | ||
| m_save_core_options.GetMemoryRegionsToSave(); | ||
| if (!all_core_memory_ranges_maybe) | ||
| return Status::FromError(all_core_memory_ranges_maybe.takeError()); | ||
|
|
||
| if (error.Fail()) | ||
| return error; | ||
| const CoreFileMemoryRanges &all_core_memory_ranges = | ||
| *all_core_memory_ranges_maybe; | ||
|
|
||
| lldb_private::Progress progress("Saving Minidump File", "", | ||
| all_core_memory_ranges.GetSize()); | ||
|
|
@@ -868,6 +868,10 @@ Status MinidumpFileBuilder::AddMemoryList() { | |
| } | ||
| } | ||
|
|
||
| // The header has to be in 32b memory, as it needs to be addressable by a 32b | ||
| // RVA. Everything else can be 64b. | ||
| total_size += sizeof(llvm::minidump::MemoryListHeader); | ||
|
|
||
| if (total_size >= UINT32_MAX) { | ||
| error = Status::FromErrorStringWithFormat( | ||
| "Unable to write minidump. Stack memory " | ||
|
|
@@ -876,35 +880,15 @@ Status MinidumpFileBuilder::AddMemoryList() { | |
| return error; | ||
| } | ||
|
|
||
| // After saving the stacks, we start packing as much as we can into 32b. | ||
| // We apply a generous padding here so that the Directory, MemoryList and | ||
| // Memory64List sections all begin in 32b addressable space. | ||
| // Then anything overflow extends into 64b addressable space. | ||
| // all_core_memory_vec will either contain all stack regions at this point, | ||
| // or be empty if it's a stack only minidump. | ||
| 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_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. | ||
| if (total_size + range_size < UINT32_MAX) { | ||
| ranges_32.push_back(core_range); | ||
| total_size += range_size; | ||
| } else { | ||
| ranges_64.push_back(core_range); | ||
| } | ||
| } | ||
|
|
||
| // Save only the thread stacks to the 32b memory list. Everything else will | ||
| // get put in Memory64, this simplifies tracking | ||
| error = AddMemoryList_32(ranges_32, progress); | ||
| if (error.Fail()) | ||
| return error; | ||
|
|
||
| // Add the remaining memory as a 64b range. | ||
| if (!ranges_64.empty()) { | ||
| error = AddMemoryList_64(ranges_64, progress); | ||
| if (!all_core_memory_ranges.IsEmpty()) { | ||
| error = AddMemoryList_64(all_core_memory_vec, progress); | ||
| if (error.Fail()) | ||
| return error; | ||
| } | ||
|
|
@@ -977,14 +961,15 @@ Status MinidumpFileBuilder::ReadWriteMemoryInChunks( | |
| const lldb::addr_t addr = range.range.start(); | ||
| const lldb::addr_t size = range.range.size(); | ||
| Log *log = GetLog(LLDBLog::Object); | ||
| uint64_t total_bytes_read = 0; | ||
| Status addDataError; | ||
| Process::ReadMemoryChunkCallback callback = | ||
| [&](Status &error, lldb::addr_t current_addr, const void *buf, | ||
| uint64_t bytes_read) -> lldb_private::IterationAction { | ||
| if (error.Fail() || bytes_read == 0) { | ||
| LLDB_LOGF(log, | ||
| "Failed to read memory region at: 0x%" PRIx64 | ||
| ". Bytes read: %" PRIx64 ", error: %s", | ||
| ". Bytes read: 0x%" PRIx64 ", error: %s", | ||
| current_addr, bytes_read, error.AsCString()); | ||
|
|
||
| // If we failed in a memory read, we would normally want to skip | ||
|
|
@@ -997,6 +982,21 @@ Status MinidumpFileBuilder::ReadWriteMemoryInChunks( | |
| return lldb_private::IterationAction::Stop; | ||
| } | ||
|
|
||
| if (current_addr != addr + total_bytes_read) { | ||
| LLDB_LOGF(log, | ||
| "Current addr is at unexpected address, 0x%" PRIx64 | ||
| ", expected at 0x%" PRIx64, | ||
| current_addr, addr + total_bytes_read); | ||
|
|
||
| // Something went wrong and the address is not where it should be | ||
| // we'll error out of this Minidump generation. | ||
| addDataError = Status::FromErrorStringWithFormat( | ||
| "Unexpected address encounterd when reading memory in chunks " | ||
| "0x%" PRIx64 " expected 0x%" PRIx64, | ||
| current_addr, addr + total_bytes_read); | ||
| return lldb_private::IterationAction::Stop; | ||
| } | ||
|
|
||
| // Write to the minidump file with the chunk potentially flushing to | ||
| // disk. | ||
| // This error will be captured by the outer scope and is considered fatal. | ||
|
|
@@ -1006,13 +1006,13 @@ Status MinidumpFileBuilder::ReadWriteMemoryInChunks( | |
| if (addDataError.Fail()) | ||
| return lldb_private::IterationAction::Stop; | ||
|
|
||
| total_bytes_read += bytes_read; | ||
| // If we have a partial read, report it, but only if the partial read | ||
| // didn't finish reading the entire region. | ||
| if (bytes_read != data_buffer.GetByteSize() && | ||
| current_addr + bytes_read != size) { | ||
| if (bytes_read != data_buffer.GetByteSize() && total_bytes_read != size) { | ||
| LLDB_LOGF(log, | ||
| "Memory region at: %" PRIx64 " partiall read 0x%" PRIx64 | ||
| " bytes out of %" PRIx64 " bytes.", | ||
| "Memory region at: 0x%" PRIx64 " partial read 0x%" PRIx64 | ||
| " bytes out of 0x%" PRIx64 " bytes.", | ||
| current_addr, bytes_read, | ||
| data_buffer.GetByteSize() - bytes_read); | ||
|
|
||
|
|
@@ -1059,7 +1059,7 @@ MinidumpFileBuilder::AddMemoryList_32(std::vector<CoreFileMemoryRange> &ranges, | |
|
|
||
| LLDB_LOGF(log, | ||
| "AddMemoryList %zu/%zu reading memory for region " | ||
| "(%" PRIx64 " bytes) [%" PRIx64 ", %" PRIx64 ")", | ||
| "(0x%" PRIx64 " bytes) [0x%" PRIx64 ", 0x%" PRIx64 ")", | ||
| region_index, ranges.size(), size, addr, addr + size); | ||
| ++region_index; | ||
|
|
||
|
|
@@ -1117,7 +1117,7 @@ MinidumpFileBuilder::AddMemoryList_64(std::vector<CoreFileMemoryRange> &ranges, | |
| return error; | ||
|
|
||
| error = AddDirectory(StreamType::Memory64List, | ||
| (sizeof(llvm::support::ulittle64_t) * 2) + | ||
| (sizeof(llvm::minidump::Memory64ListHeader)) + | ||
| ranges.size() * | ||
| sizeof(llvm::minidump::MemoryDescriptor_64)); | ||
| if (error.Fail()) | ||
|
|
@@ -1130,9 +1130,9 @@ MinidumpFileBuilder::AddMemoryList_64(std::vector<CoreFileMemoryRange> &ranges, | |
| // Capture the starting offset for all the descriptors so we can clean them up | ||
| // if needed. | ||
| offset_t starting_offset = | ||
| GetCurrentDataEndOffset() + sizeof(llvm::support::ulittle64_t); | ||
| GetCurrentDataEndOffset() + sizeof(llvm::minidump::Memory64ListHeader); | ||
|
||
| // The base_rva needs to start after the directories, which is right after | ||
| // this 8 byte variable. | ||
| // the descriptors + the size of the header. | ||
| offset_t base_rva = | ||
| starting_offset + | ||
| (ranges.size() * sizeof(llvm::minidump::MemoryDescriptor_64)); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.