[lldb] [llvm] [LLDB][Minidump] Add 64b support to LLDB's minidump file builder. (PR #95312)

Jacob Lalonde via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 18 09:49:45 PDT 2024


================
@@ -791,26 +807,101 @@ void MinidumpFileBuilder::AddLinuxFileStreams(
       size_t size = memory_buffer->getBufferSize();
       if (size == 0)
         continue;
-      AddDirectory(stream, size);
+      error = AddDirectory(stream, size);
+      if (error.Fail())
+        return error;
       m_data.AppendData(memory_buffer->getBufferStart(), size);
     }
   }
+
+  return error;
 }
 
-Status MinidumpFileBuilder::Dump(lldb::FileUP &core_file) const {
-  constexpr size_t header_size = sizeof(llvm::minidump::Header);
-  constexpr size_t directory_size = sizeof(llvm::minidump::Directory);
+Status MinidumpFileBuilder::AddMemoryList(SaveCoreStyle core_style) {
+  Status error;
+
+  // We first save the thread stacks to ensure they fit in the first UINT32_MAX
+  // 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;
+  error = m_process_sp->CalculateCoreFileSaveRanges(
+      SaveCoreStyle::eSaveCoreStackOnly, ranges_32);
+  if (error.Fail())
+    return error;
 
+  uint64_t total_size =
+      ranges_32.size() * sizeof(llvm::minidump::MemoryDescriptor);
+  std::unordered_set<addr_t> stack_start_addresses;
+  for (const auto &core_range : ranges_32) {
+    stack_start_addresses.insert(core_range.range.start());
+    total_size += core_range.range.size();
+  }
+
+  if (total_size >= UINT32_MAX) {
+    error.SetErrorStringWithFormat("Unable to write minidump. Stack memory "
+                                   "exceeds 32b limit. (Num Stacks %zu)",
+                                   ranges_32.size());
+    return error;
+  }
+
+  Process::CoreFileMemoryRanges all_core_memory_ranges;
+  if (core_style != SaveCoreStyle::eSaveCoreStackOnly) {
+    error = m_process_sp->CalculateCoreFileSaveRanges(core_style,
+                                                      all_core_memory_ranges);
+    if (error.Fail())
+      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.
+  total_size +=
+      256 + (all_core_memory_ranges.size() - stack_start_addresses.size()) *
+                sizeof(llvm::minidump::MemoryDescriptor_64);
----------------
Jlalond wrote:

This actually works, because we'll never enter the loop unless `all_core_memory_ranges` is non empty, where total_size will actually be used. Prior to code review feedback we always called to get memory ranges, even when it's just stacks, ensuring we would always have at least stacks in `all_core_memory_ranges`. 

I have added the check for empty and an explanation comment as well.

https://github.com/llvm/llvm-project/pull/95312


More information about the llvm-commits mailing list