[Lldb-commits] [PATCH] D107625: Add a stack-memory-only style for Darwin process save-core

2021-08-11 Thread Jason Molenda via Phabricator via lldb-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8c31efeed600: Add the ability to process save-core 
stack-memory-only corefiles (authored by jasonmolenda).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107625/new/

https://reviews.llvm.org/D107625

Files:
  lldb/docs/lldb-gdb-remote.txt
  lldb/include/lldb/Target/MemoryRegionInfo.h
  lldb/include/lldb/lldb-enumerations.h
  lldb/source/Commands/CommandObjectProcess.cpp
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/test/API/macosx/skinny-corefile/TestSkinnyCorefile.py
  lldb/test/API/macosx/stack-corefile/Makefile
  lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
  lldb/test/API/macosx/stack-corefile/main.c
  lldb/tools/debugserver/source/DNBDefs.h
  lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
  lldb/tools/debugserver/source/RNBRemote.cpp

Index: lldb/tools/debugserver/source/RNBRemote.cpp
===
--- lldb/tools/debugserver/source/RNBRemote.cpp
+++ lldb/tools/debugserver/source/RNBRemote.cpp
@@ -4310,6 +4310,14 @@
   }
 }
 ostrm << ";";
+if (!region_info.vm_types.empty()) {
+  for (size_t i = 0; i < region_info.vm_types.size(); i++) {
+if (i)
+  ostrm << ",";
+ostrm << region_info.vm_types[i];
+  }
+  ostrm << ";";
+}
   }
   return SendPacket(ostrm.str());
 }
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
@@ -40,6 +40,7 @@
   vm_prot_t prot);
   bool RestoreProtections();
   bool GetRegionForAddress(nub_addr_t addr);
+  std::vector GetMemoryTypes() const;
 
   uint32_t GetDNBPermissions() const;
 
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
@@ -182,3 +182,43 @@
 dnb_permissions |= eMemoryPermissionsExecutable;
   return dnb_permissions;
 }
+
+std::vector MachVMRegion::GetMemoryTypes() const {
+  std::vector types;
+  if (m_data.user_tag == VM_MEMORY_STACK) {
+if (m_data.protection == VM_PROT_NONE) {
+  types.push_back("stack-guard");
+} else {
+  types.push_back("stack");
+}
+  }
+  if (m_data.user_tag == VM_MEMORY_MALLOC) {
+if (m_data.protection == VM_PROT_NONE)
+  types.push_back("malloc-guard");
+else if (m_data.share_mode == SM_EMPTY)
+  types.push_back("malloc-reserved");
+else
+  types.push_back("malloc-metadata");
+  }
+  if (m_data.user_tag == VM_MEMORY_MALLOC_NANO ||
+  m_data.user_tag == VM_MEMORY_MALLOC_TINY ||
+  m_data.user_tag == VM_MEMORY_MALLOC_SMALL ||
+  m_data.user_tag == VM_MEMORY_MALLOC_LARGE ||
+  m_data.user_tag == VM_MEMORY_MALLOC_LARGE_REUSED ||
+  m_data.user_tag == VM_MEMORY_MALLOC_LARGE_REUSABLE ||
+  m_data.user_tag == VM_MEMORY_MALLOC_HUGE ||
+  m_data.user_tag == VM_MEMORY_REALLOC ||
+  m_data.user_tag == VM_MEMORY_SBRK) {
+types.push_back("heap");
+if (m_data.user_tag == VM_MEMORY_MALLOC_TINY) {
+  types.push_back("malloc-tiny");
+}
+if (m_data.user_tag == VM_MEMORY_MALLOC_LARGE) {
+  types.push_back("malloc-large");
+}
+if (m_data.user_tag == VM_MEMORY_MALLOC_SMALL) {
+  types.push_back("malloc-small");
+}
+  }
+  return types;
+}
Index: lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
@@ -125,6 +125,7 @@
 region_info->permissions = vmRegion.GetDNBPermissions();
 region_info->dirty_pages =
 get_dirty_pages(task, vmRegion.StartAddress(), vmRegion.GetByteSize());
+region_info->vm_types = vmRegion.GetMemoryTypes();
   } else {
 region_info->addr = address;
 region_info->size = 0;
Index: lldb/tools/debugserver/source/DNBDefs.h
===
--- lldb/tools/debugserver/source/DNBDefs.h
+++ lldb/tools/debugserver/source/DNBDefs.h
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -318,11 +319,13 @@
 
 struct DNBRegionInfo {
 public:
-  DNBRegionInfo() : addr(0), size(0), permissions(0), dirty_pages() {}
+  DNBRegionInfo()
+  : 

[Lldb-commits] [PATCH] D107625: Add a stack-memory-only style for Darwin process save-core

2021-08-09 Thread Jason Molenda via Phabricator via lldb-commits
jasonmolenda updated this revision to Diff 365319.
jasonmolenda added a comment.

Have debugserver report malloc memory regions too, aka heap.  I don't know how 
to use this in lldb yet, but it was easy to add so I thought I'd add it.  Maybe 
we'll come up with an idea for it later.  On Darwin, there are multiple types 
of heap - malloc small, malloc large, malloc tiny, etc - so for these, 
debugserver will return "type:heap,malloc-small;" etc, so the generic "heap" 
word is there, but also the more darwin-specific type of heap is given.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107625/new/

https://reviews.llvm.org/D107625

Files:
  lldb/docs/lldb-gdb-remote.txt
  lldb/include/lldb/Target/MemoryRegionInfo.h
  lldb/include/lldb/lldb-enumerations.h
  lldb/source/Commands/CommandObjectProcess.cpp
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/test/API/macosx/skinny-corefile/TestSkinnyCorefile.py
  lldb/test/API/macosx/stack-corefile/Makefile
  lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
  lldb/test/API/macosx/stack-corefile/main.c
  lldb/tools/debugserver/source/DNBDefs.h
  lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
  lldb/tools/debugserver/source/RNBRemote.cpp

Index: lldb/tools/debugserver/source/RNBRemote.cpp
===
--- lldb/tools/debugserver/source/RNBRemote.cpp
+++ lldb/tools/debugserver/source/RNBRemote.cpp
@@ -4310,6 +4310,14 @@
   }
 }
 ostrm << ";";
+if (!region_info.vm_types.empty()) {
+  for (size_t i = 0; i < region_info.vm_types.size(); i++) {
+if (i)
+  ostrm << ",";
+ostrm << region_info.vm_types[i];
+  }
+  ostrm << ";";
+}
   }
   return SendPacket(ostrm.str());
 }
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
@@ -40,6 +40,7 @@
   vm_prot_t prot);
   bool RestoreProtections();
   bool GetRegionForAddress(nub_addr_t addr);
+  std::vector GetMemoryTypes() const;
 
   uint32_t GetDNBPermissions() const;
 
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
@@ -182,3 +182,43 @@
 dnb_permissions |= eMemoryPermissionsExecutable;
   return dnb_permissions;
 }
+
+std::vector MachVMRegion::GetMemoryTypes() const {
+  std::vector types;
+  if (m_data.user_tag == VM_MEMORY_STACK) {
+if (m_data.protection == VM_PROT_NONE) {
+  types.push_back("stack-guard");
+} else {
+  types.push_back("stack");
+}
+  }
+  if (m_data.user_tag == VM_MEMORY_MALLOC) {
+if (m_data.protection == VM_PROT_NONE)
+  types.push_back("malloc-guard");
+else if (m_data.share_mode == SM_EMPTY)
+  types.push_back("malloc-reserved");
+else
+  types.push_back("malloc-metadata");
+  }
+  if (m_data.user_tag == VM_MEMORY_MALLOC_NANO ||
+  m_data.user_tag == VM_MEMORY_MALLOC_TINY ||
+  m_data.user_tag == VM_MEMORY_MALLOC_SMALL ||
+  m_data.user_tag == VM_MEMORY_MALLOC_LARGE ||
+  m_data.user_tag == VM_MEMORY_MALLOC_LARGE_REUSED ||
+  m_data.user_tag == VM_MEMORY_MALLOC_LARGE_REUSABLE ||
+  m_data.user_tag == VM_MEMORY_MALLOC_HUGE ||
+  m_data.user_tag == VM_MEMORY_REALLOC ||
+  m_data.user_tag == VM_MEMORY_SBRK) {
+types.push_back("heap");
+if (m_data.user_tag == VM_MEMORY_MALLOC_TINY) {
+  types.push_back("malloc-tiny");
+}
+if (m_data.user_tag == VM_MEMORY_MALLOC_LARGE) {
+  types.push_back("malloc-large");
+}
+if (m_data.user_tag == VM_MEMORY_MALLOC_SMALL) {
+  types.push_back("malloc-small");
+}
+  }
+  return types;
+}
Index: lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
@@ -125,6 +125,7 @@
 region_info->permissions = vmRegion.GetDNBPermissions();
 region_info->dirty_pages =
 get_dirty_pages(task, vmRegion.StartAddress(), vmRegion.GetByteSize());
+region_info->vm_types = vmRegion.GetMemoryTypes();
   } else {
 region_info->addr = address;
 region_info->size = 0;
Index: lldb/tools/debugserver/source/DNBDefs.h
===
--- lldb/tools/debugserver/source/DNBDefs.h
+++ lldb/tools/debugserver/source/DNBDefs.h
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 

[Lldb-commits] [PATCH] D107625: Add a stack-memory-only style for Darwin process save-core

2021-08-06 Thread Jason Molenda via Phabricator via lldb-commits
jasonmolenda updated this revision to Diff 364731.
jasonmolenda added a comment.

Handle a bit of state tracking in ObjectFileMachO a little bit more readably.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107625/new/

https://reviews.llvm.org/D107625

Files:
  lldb/docs/lldb-gdb-remote.txt
  lldb/include/lldb/Target/MemoryRegionInfo.h
  lldb/include/lldb/lldb-enumerations.h
  lldb/source/Commands/CommandObjectProcess.cpp
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/test/API/macosx/skinny-corefile/TestSkinnyCorefile.py
  lldb/test/API/macosx/stack-corefile/Makefile
  lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
  lldb/test/API/macosx/stack-corefile/main.c
  lldb/tools/debugserver/source/DNBDefs.h
  lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
  lldb/tools/debugserver/source/RNBRemote.cpp

Index: lldb/tools/debugserver/source/RNBRemote.cpp
===
--- lldb/tools/debugserver/source/RNBRemote.cpp
+++ lldb/tools/debugserver/source/RNBRemote.cpp
@@ -4310,6 +4310,8 @@
   }
 }
 ostrm << ";";
+if (region_info.is_stack)
+  ostrm << "type:stack;";
   }
   return SendPacket(ostrm.str());
 }
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
@@ -40,6 +40,7 @@
   vm_prot_t prot);
   bool RestoreProtections();
   bool GetRegionForAddress(nub_addr_t addr);
+  bool GetIsStackMemory() const;
 
   uint32_t GetDNBPermissions() const;
 
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
@@ -182,3 +182,11 @@
 dnb_permissions |= eMemoryPermissionsExecutable;
   return dnb_permissions;
 }
+
+bool MachVMRegion::GetIsStackMemory() const {
+  // VM_MEMORY_STACK and VM_PROT_NONE is the STACK GUARD region.
+  if (m_data.user_tag == VM_MEMORY_STACK && m_data.protection != VM_PROT_NONE)
+return true;
+  else
+return false;
+}
Index: lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
@@ -125,6 +125,8 @@
 region_info->permissions = vmRegion.GetDNBPermissions();
 region_info->dirty_pages =
 get_dirty_pages(task, vmRegion.StartAddress(), vmRegion.GetByteSize());
+if (vmRegion.GetIsStackMemory())
+  region_info->is_stack = true;
   } else {
 region_info->addr = address;
 region_info->size = 0;
Index: lldb/tools/debugserver/source/DNBDefs.h
===
--- lldb/tools/debugserver/source/DNBDefs.h
+++ lldb/tools/debugserver/source/DNBDefs.h
@@ -318,11 +318,13 @@
 
 struct DNBRegionInfo {
 public:
-  DNBRegionInfo() : addr(0), size(0), permissions(0), dirty_pages() {}
+  DNBRegionInfo()
+  : addr(0), size(0), permissions(0), dirty_pages(), is_stack(false) {}
   nub_addr_t addr;
   nub_addr_t size;
   uint32_t permissions;
   std::vector dirty_pages;
+  bool is_stack;
 };
 
 enum DNBProfileDataScanType {
Index: lldb/test/API/macosx/stack-corefile/main.c
===
--- /dev/null
+++ lldb/test/API/macosx/stack-corefile/main.c
@@ -0,0 +1,15 @@
+#include 
+#include 
+#include 
+int main() {
+  int stack_int = 5;
+  int *heap_int = (int*) malloc(sizeof (int));
+  *heap_int = 10;
+
+  char stack_str[80];
+  strcpy (stack_str, "stack string");
+  char *heap_str = (char*) malloc(80);
+  strcpy (heap_str, "heap string");
+
+  return stack_int; // break here;
+}
Index: lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
===
--- /dev/null
+++ lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
@@ -0,0 +1,69 @@
+"""Test that lldb can create a stack-only corefile, and load the main binary."""
+
+import os
+import re
+import subprocess
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestStackCorefile(TestBase):
+
+mydir = TestBase.compute_mydir(__file__)
+
+@no_debug_info_test
+@skipUnlessDarwin
+def test(self):
+
+corefile = self.getBuildArtifact("process.core")
+self.build()
+(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+self, "// 

[Lldb-commits] [PATCH] D107625: Add a stack-memory-only style for Darwin process save-core

2021-08-06 Thread Jason Molenda via Phabricator via lldb-commits
jasonmolenda created this revision.
jasonmolenda added a project: LLDB.
Herald added a subscriber: JDevlieghere.
jasonmolenda requested review of this revision.

After adding the "dirty memory only" coredump style, I've been wondering how 
small a corefile I could get by only saving stack memory.  I took a little time 
today to find out.  A normal macOS corefile is a couple of GB, a dirty-memory 
corefile is around 440kb for a test binary.  A stack memory corefile is about 
20kb for that test binary.

I added a new "type" key-value pair to the qMemoryRegionInfo packet, and add 
"stack" to stack memory regions.  David added a "flags" k-v pair for MTE but 
that has a specially formatted string of MTE flags in it (space separated) so I 
didn't want to mix in with that.  It's straightforward to detect different 
memory types on Darwin systems, but I haven't thought of anything useful I 
could do by writing out heap dirty memory only or something.  Maybe someone 
will think of some interesting way to use the memory region types.

In the test case, I create a stack-memory-only corefile, then read it back into 
lldb and fetch some stack & heap objects.  SBValue has the unfortunate behavior 
(IMO) that it doesn't surface memory read errors in any way - so you can ask 
for a summary or a value of an SBValue object that couldn't read anything, and 
it will return 0/empty-string.  We need to surface memory read errors better in 
lldb in these cases, this is just one of the issues with that.

I'm not sure a stack-memory-only corefile is especially useful for real 
C++/ObjC/Swift programs where many objects live on the heap.  One thing I've 
thought about is trying to get a very tiny corefile showing interesting unwind 
states for writing tests against.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D107625

Files:
  lldb/docs/lldb-gdb-remote.txt
  lldb/include/lldb/Target/MemoryRegionInfo.h
  lldb/include/lldb/lldb-enumerations.h
  lldb/source/Commands/CommandObjectProcess.cpp
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
  lldb/test/API/macosx/skinny-corefile/TestSkinnyCorefile.py
  lldb/test/API/macosx/stack-corefile/Makefile
  lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
  lldb/test/API/macosx/stack-corefile/main.c
  lldb/tools/debugserver/source/DNBDefs.h
  lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
  lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
  lldb/tools/debugserver/source/RNBRemote.cpp

Index: lldb/tools/debugserver/source/RNBRemote.cpp
===
--- lldb/tools/debugserver/source/RNBRemote.cpp
+++ lldb/tools/debugserver/source/RNBRemote.cpp
@@ -4310,6 +4310,8 @@
   }
 }
 ostrm << ";";
+if (region_info.is_stack)
+  ostrm << "type:stack;";
   }
   return SendPacket(ostrm.str());
 }
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
@@ -40,6 +40,7 @@
   vm_prot_t prot);
   bool RestoreProtections();
   bool GetRegionForAddress(nub_addr_t addr);
+  bool GetIsStackMemory() const;
 
   uint32_t GetDNBPermissions() const;
 
Index: lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
@@ -182,3 +182,11 @@
 dnb_permissions |= eMemoryPermissionsExecutable;
   return dnb_permissions;
 }
+
+bool MachVMRegion::GetIsStackMemory() const {
+  // VM_MEMORY_STACK and VM_PROT_NONE is the STACK GUARD region.
+  if (m_data.user_tag == VM_MEMORY_STACK && m_data.protection != VM_PROT_NONE)
+return true;
+  else
+return false;
+}
Index: lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
===
--- lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
+++ lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
@@ -125,6 +125,8 @@
 region_info->permissions = vmRegion.GetDNBPermissions();
 region_info->dirty_pages =
 get_dirty_pages(task, vmRegion.StartAddress(), vmRegion.GetByteSize());
+if (vmRegion.GetIsStackMemory())
+  region_info->is_stack = true;
   } else {
 region_info->addr = address;
 region_info->size = 0;
Index: lldb/tools/debugserver/source/DNBDefs.h
===
--- lldb/tools/debugserver/source/DNBDefs.h
+++ lldb/tools/debugserver/source/DNBDefs.h
@@ -318,11 +318,13 @@
 
 struct DNBRegionInfo {
 public:
-  DNBRegionInfo() : addr(0), size(0), permissions(0), dirty_pages() {}
+  DNBRegionInfo()
+  : addr(0),