Skip to content

[LLDB][SBSaveCoreOptions] Add new API to expose the expected core size in bytes #138169

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

Merged
merged 7 commits into from
May 9, 2025

Conversation

Jlalond
Copy link
Contributor

@Jlalond Jlalond commented May 1, 2025

My current internal work requires some sensitivity to IO usage. I had a work around to calculate the expected size of a Minidump, but I've added this PR so an automated system could look at the expected size of an LLDB generated Minidump and then choose if it has the space or wants to generate it.

There are some prerequisites to calculating the correct size, so I have the API take a reference for an SBError, I originally tried to return an SBError and instead take a uint64_t reference, but this made the API very difficult to use in python.

Added a test case as well.

@Jlalond Jlalond requested review from dmpots and bulbazord May 1, 2025 17:15
@Jlalond Jlalond requested a review from JDevlieghere as a code owner May 1, 2025 17:15
@llvmbot llvmbot added the lldb label May 1, 2025
@llvmbot
Copy link
Member

llvmbot commented May 1, 2025

@llvm/pr-subscribers-lldb

Author: Jacob Lalonde (Jlalond)

Changes

My current internal work requires some sensitivity to IO usage. I had a work around to calculate the expected size of a Minidump, but I've added this PR so an automated system could look at the expected size of an LLDB generated Minidump and then choose if it has the space or wants to generate it.

There are some prerequisites to calculating the correct size, so I have the API take a reference for an SBError, I originally tried to return an SBError and instead take a uint64_t reference, but this made the API very difficult to use in python.

Added a test case as well.


Full diff: https://github.com/llvm/llvm-project/pull/138169.diff

6 Files Affected:

  • (modified) lldb/include/lldb/API/SBSaveCoreOptions.h (+13)
  • (modified) lldb/include/lldb/Symbol/SaveCoreOptions.h (+2)
  • (modified) lldb/source/API/SBSaveCoreOptions.cpp (+5)
  • (modified) lldb/source/Symbol/SaveCoreOptions.cpp (+18)
  • (modified) lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py (+21)
  • (modified) lldb/test/API/python_api/sbsavecoreoptions/basic_minidump.yaml (+5)
diff --git a/lldb/include/lldb/API/SBSaveCoreOptions.h b/lldb/include/lldb/API/SBSaveCoreOptions.h
index c6d2ab6099b3c..4c051353a714e 100644
--- a/lldb/include/lldb/API/SBSaveCoreOptions.h
+++ b/lldb/include/lldb/API/SBSaveCoreOptions.h
@@ -119,6 +119,19 @@ class LLDB_API SBSaveCoreOptions {
   ///   an empty collection will be returned.
   SBThreadCollection GetThreadsToSave() const;
 
+  /// Get the current total number of bytes the core is expected to be but not
+  /// including the overhead of the core file format. Requires a Process and 
+  /// Style to be specified.
+  /// 
+  /// \note
+  ///   This can cause some modification of the underlying data store 
+  ///   as regions with no permissions, or invalid permissions will be removed
+  ///   and stacks will be minified up to their stack pointer + the redzone.
+  ///
+  /// \returns
+  ///   The expected size of the data contained in the core in bytes.
+  uint64_t GetCurrentSizeInBytes(SBError &error);
+
   /// Reset all options.
   void Clear();
 
diff --git a/lldb/include/lldb/Symbol/SaveCoreOptions.h b/lldb/include/lldb/Symbol/SaveCoreOptions.h
index bcf0087fbea5c..319d44a6b0c87 100644
--- a/lldb/include/lldb/Symbol/SaveCoreOptions.h
+++ b/lldb/include/lldb/Symbol/SaveCoreOptions.h
@@ -49,6 +49,8 @@ class SaveCoreOptions {
 
   lldb_private::ThreadCollection::collection GetThreadsToSave() const;
 
+  uint64_t GetCurrentSizeInBytes(Status &error);
+
   void Clear();
 
 private:
diff --git a/lldb/source/API/SBSaveCoreOptions.cpp b/lldb/source/API/SBSaveCoreOptions.cpp
index 35b9da569dfa1..b67df513fe91b 100644
--- a/lldb/source/API/SBSaveCoreOptions.cpp
+++ b/lldb/source/API/SBSaveCoreOptions.cpp
@@ -114,6 +114,11 @@ void SBSaveCoreOptions::Clear() {
   m_opaque_up->Clear();
 }
 
+uint64_t SBSaveCoreOptions::GetCurrentSizeInBytes(SBError &error) {
+  LLDB_INSTRUMENT_VA(this, error);
+  return m_opaque_up->GetCurrentSizeInBytes(error.ref());
+}
+
 lldb_private::SaveCoreOptions &SBSaveCoreOptions::ref() const {
   return *m_opaque_up.get();
 }
diff --git a/lldb/source/Symbol/SaveCoreOptions.cpp b/lldb/source/Symbol/SaveCoreOptions.cpp
index c9f6efeb25d22..1da3e1cc9f834 100644
--- a/lldb/source/Symbol/SaveCoreOptions.cpp
+++ b/lldb/source/Symbol/SaveCoreOptions.cpp
@@ -145,6 +145,24 @@ SaveCoreOptions::GetThreadsToSave() const {
   return thread_collection;
 }
 
+uint64_t SaveCoreOptions::GetCurrentSizeInBytes(Status &error) {
+  if (!m_process_sp) {
+    error = Status::FromErrorString("Requires a process to be set.");
+    return 0;
+  }
+
+  CoreFileMemoryRanges ranges;
+  error = m_process_sp->CalculateCoreFileSaveRanges(*this, ranges);
+  if (error.Fail())
+    return 0;
+
+  uint64_t total_in_bytes = 0;
+  for (auto& core_range : ranges)
+    total_in_bytes += core_range.data.range.size();
+
+  return total_in_bytes;
+}
+
 void SaveCoreOptions::ClearProcessSpecificData() {
   // Deliberately not following the formatter style here to indicate that
   // this method will be expanded in the future.
diff --git a/lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py b/lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py
index ace84e8497a59..215f8440cc68a 100644
--- a/lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py
+++ b/lldb/test/API/python_api/sbsavecoreoptions/TestSBSaveCoreOptions.py
@@ -104,3 +104,24 @@ def test_removing_and_adding_insertion_order(self):
         thread_collection = options.GetThreadsToSave()
         self.assertEqual(thread_collection.GetSize(), 3)
         self.assertIn(middle_thread, thread_collection)
+
+    def test_get_total_in_bytes(self):
+        """
+        Tests that get total in bytes properly returns an error without a process, 
+        and the readable regions with a process.
+        """
+
+        options = lldb.SBSaveCoreOptions()
+        options.SetStyle(lldb.eSaveCoreCustomOnly)
+        process = self.get_basic_process()
+        memory_range = lldb.SBMemoryRegionInfo()
+        process.GetMemoryRegionInfo(0x7FFF12A84030, memory_range)
+        options.AddMemoryRegionToSave(memory_range)
+        error = lldb.SBError()
+        total = options.GetCurrentSizeInBytes(error)
+        self.assertTrue(error.Fail(), error.GetCString())
+        options.SetProcess(process)
+        total = options.GetCurrentSizeInBytes(error)
+        self.assertTrue(error.Success(), error.GetCString())
+        expected_size = memory_range.GetRegionEnd() - memory_range.GetRegionBase()
+        self.assertEqual(total, expected_size)
diff --git a/lldb/test/API/python_api/sbsavecoreoptions/basic_minidump.yaml b/lldb/test/API/python_api/sbsavecoreoptions/basic_minidump.yaml
index 96302fbfb6b5c..5033787019d7b 100644
--- a/lldb/test/API/python_api/sbsavecoreoptions/basic_minidump.yaml
+++ b/lldb/test/API/python_api/sbsavecoreoptions/basic_minidump.yaml
@@ -34,3 +34,8 @@ Streams:
         Stack:
           Start of Memory Range: 0x00007FFFC8DFF000
           Content:               'BAADBEEF'
+  - Type:            Memory64List
+    Memory Ranges:
+      - Start of Memory Range: 0x7FFF12A84030
+        Data Size:       0x2FD0
+        Content :        ''

@Jlalond Jlalond requested review from clayborg and jeffreytan81 May 1, 2025 17:17
Copy link

github-actions bot commented May 1, 2025

✅ With the latest revision this PR passed the Python code formatter.

@Jlalond
Copy link
Contributor Author

Jlalond commented May 2, 2025

@bulbazord as always thanks for your insight Alex. I added a docstring with your improved comment, almost forgot about that.

@Jlalond Jlalond force-pushed the sbsavecore-options-accounting branch from 02231e9 to 0f5c5a2 Compare May 2, 2025 21:39
Copy link

github-actions bot commented May 2, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@Jlalond Jlalond force-pushed the sbsavecore-options-accounting branch from 0f5c5a2 to a823853 Compare May 3, 2025 01:35
@Jlalond
Copy link
Contributor Author

Jlalond commented May 8, 2025

@clayborg, @dmpots bump if you have time

Copy link
Contributor

@dmpots dmpots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few suggestions for expanding test coverage.

Regarding your comment

I have the API take a reference for an SBError, I originally tried to return an SBError and instead take a uint64_t reference, but this made the API very difficult to use in python.

It looks there is precedent for doing this in other API calls (e.g. SBProcess.WriteMemory) and seems like a fine choice to me
https://lldb.llvm.org/python_api/lldb.SBProcess.html#lldb.SBProcess.WriteMemory

@Jlalond
Copy link
Contributor Author

Jlalond commented May 9, 2025

@dmpots Thanks for the feedback, I implemented several more test cases, and fixed those typos.

Copy link
Contributor

@dmpots dmpots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@Jlalond Jlalond merged commit 7517a1b into llvm:main May 9, 2025
6 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants