[Lldb-commits] [PATCH] D107625: Add a stack-memory-only style for Darwin process save-core
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
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
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
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),