Add the ability to process save-core stack-memory-only corefiles
Add a field to the qMemoryRegionInfo packet where the remote stub can describe the type of memory -- heap, stack. Keep track of memory regions that are stack memory in lldb. Add a new "--style stack" to process save-core to request that only stack memory be included in the corefile. Differential Revision: https://reviews.llvm.org/D107625
This commit is contained in:
parent
7f3c3d7aa4
commit
8c31efeed6
|
@ -1206,6 +1206,9 @@ tuples to return are:
|
||||||
// is "mt" for AArch64 memory tagging. lldb will
|
// is "mt" for AArch64 memory tagging. lldb will
|
||||||
// ignore any other flags in this field.
|
// ignore any other flags in this field.
|
||||||
|
|
||||||
|
type:[<type>][,<type>]; // memory types that apply to this region, e.g.
|
||||||
|
// "stack" for stack memory.
|
||||||
|
|
||||||
error:<ascii-byte-error-string>; // where <ascii-byte-error-string> is
|
error:<ascii-byte-error-string>; // where <ascii-byte-error-string> is
|
||||||
// a hex encoded string value that
|
// a hex encoded string value that
|
||||||
// contains an error string
|
// contains an error string
|
||||||
|
|
|
@ -28,10 +28,10 @@ public:
|
||||||
MemoryRegionInfo(RangeType range, OptionalBool read, OptionalBool write,
|
MemoryRegionInfo(RangeType range, OptionalBool read, OptionalBool write,
|
||||||
OptionalBool execute, OptionalBool mapped, ConstString name,
|
OptionalBool execute, OptionalBool mapped, ConstString name,
|
||||||
OptionalBool flash, lldb::offset_t blocksize,
|
OptionalBool flash, lldb::offset_t blocksize,
|
||||||
OptionalBool memory_tagged)
|
OptionalBool memory_tagged, OptionalBool stack_memory)
|
||||||
: m_range(range), m_read(read), m_write(write), m_execute(execute),
|
: m_range(range), m_read(read), m_write(write), m_execute(execute),
|
||||||
m_mapped(mapped), m_name(name), m_flash(flash), m_blocksize(blocksize),
|
m_mapped(mapped), m_name(name), m_flash(flash), m_blocksize(blocksize),
|
||||||
m_memory_tagged(memory_tagged) {}
|
m_memory_tagged(memory_tagged), m_is_stack_memory(stack_memory) {}
|
||||||
|
|
||||||
RangeType &GetRange() { return m_range; }
|
RangeType &GetRange() { return m_range; }
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@ public:
|
||||||
m_mapped == rhs.m_mapped && m_name == rhs.m_name &&
|
m_mapped == rhs.m_mapped && m_name == rhs.m_name &&
|
||||||
m_flash == rhs.m_flash && m_blocksize == rhs.m_blocksize &&
|
m_flash == rhs.m_flash && m_blocksize == rhs.m_blocksize &&
|
||||||
m_memory_tagged == rhs.m_memory_tagged &&
|
m_memory_tagged == rhs.m_memory_tagged &&
|
||||||
m_pagesize == rhs.m_pagesize;
|
m_pagesize == rhs.m_pagesize &&
|
||||||
|
m_is_stack_memory == rhs.m_is_stack_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs); }
|
bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs); }
|
||||||
|
@ -116,6 +117,10 @@ public:
|
||||||
return m_dirty_pages;
|
return m_dirty_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptionalBool IsStackMemory() const { return m_is_stack_memory; }
|
||||||
|
|
||||||
|
void SetIsStackMemory(OptionalBool val) { m_is_stack_memory = val; }
|
||||||
|
|
||||||
void SetPageSize(int pagesize) { m_pagesize = pagesize; }
|
void SetPageSize(int pagesize) { m_pagesize = pagesize; }
|
||||||
|
|
||||||
void SetDirtyPageList(std::vector<lldb::addr_t> pagelist) {
|
void SetDirtyPageList(std::vector<lldb::addr_t> pagelist) {
|
||||||
|
@ -134,6 +139,7 @@ protected:
|
||||||
OptionalBool m_flash = eDontKnow;
|
OptionalBool m_flash = eDontKnow;
|
||||||
lldb::offset_t m_blocksize = 0;
|
lldb::offset_t m_blocksize = 0;
|
||||||
OptionalBool m_memory_tagged = eDontKnow;
|
OptionalBool m_memory_tagged = eDontKnow;
|
||||||
|
OptionalBool m_is_stack_memory = eDontKnow;
|
||||||
int m_pagesize = 0;
|
int m_pagesize = 0;
|
||||||
llvm::Optional<std::vector<lldb::addr_t>> m_dirty_pages;
|
llvm::Optional<std::vector<lldb::addr_t>> m_dirty_pages;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1137,6 +1137,7 @@ enum SaveCoreStyle {
|
||||||
eSaveCoreUnspecified = 0,
|
eSaveCoreUnspecified = 0,
|
||||||
eSaveCoreFull = 1,
|
eSaveCoreFull = 1,
|
||||||
eSaveCoreDirtyOnly = 2,
|
eSaveCoreDirtyOnly = 2,
|
||||||
|
eSaveCoreStackOnly = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lldb
|
} // namespace lldb
|
||||||
|
|
|
@ -1166,7 +1166,9 @@ protected:
|
||||||
static constexpr OptionEnumValueElement g_corefile_save_style[] = {
|
static constexpr OptionEnumValueElement g_corefile_save_style[] = {
|
||||||
{eSaveCoreFull, "full", "Create a core file with all memory saved"},
|
{eSaveCoreFull, "full", "Create a core file with all memory saved"},
|
||||||
{eSaveCoreDirtyOnly, "modified-memory",
|
{eSaveCoreDirtyOnly, "modified-memory",
|
||||||
"Create a corefile with only modified memory saved"}};
|
"Create a corefile with only modified memory saved"},
|
||||||
|
{eSaveCoreStackOnly, "stack",
|
||||||
|
"Create a corefile with only stack memory saved"}};
|
||||||
|
|
||||||
static constexpr OptionEnumValues SaveCoreStyles() {
|
static constexpr OptionEnumValues SaveCoreStyles() {
|
||||||
return OptionEnumValues(g_corefile_save_style);
|
return OptionEnumValues(g_corefile_save_style);
|
||||||
|
@ -1237,11 +1239,12 @@ protected:
|
||||||
Status error =
|
Status error =
|
||||||
PluginManager::SaveCore(process_sp, output_file, corefile_style);
|
PluginManager::SaveCore(process_sp, output_file, corefile_style);
|
||||||
if (error.Success()) {
|
if (error.Success()) {
|
||||||
if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) {
|
if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly ||
|
||||||
|
corefile_style == SaveCoreStyle::eSaveCoreStackOnly) {
|
||||||
result.AppendMessageWithFormat(
|
result.AppendMessageWithFormat(
|
||||||
"\nModified-memory only corefile "
|
"\nModified-memory or stack-memory only corefile "
|
||||||
"created. This corefile may not show \n"
|
"created. This corefile may \n"
|
||||||
"library/framework/app binaries "
|
"not show library/framework/app binaries "
|
||||||
"on a different system, or when \n"
|
"on a different system, or when \n"
|
||||||
"those binaries have "
|
"those binaries have "
|
||||||
"been updated/modified. Copies are not included\n"
|
"been updated/modified. Copies are not included\n"
|
||||||
|
|
|
@ -6342,13 +6342,17 @@ struct segment_vmaddr {
|
||||||
// are some multiple passes over the image list while calculating
|
// are some multiple passes over the image list while calculating
|
||||||
// everything.
|
// everything.
|
||||||
|
|
||||||
static offset_t
|
static offset_t CreateAllImageInfosPayload(
|
||||||
CreateAllImageInfosPayload(const lldb::ProcessSP &process_sp,
|
const lldb::ProcessSP &process_sp, offset_t initial_file_offset,
|
||||||
offset_t initial_file_offset,
|
StreamString &all_image_infos_payload, SaveCoreStyle core_style) {
|
||||||
StreamString &all_image_infos_payload) {
|
|
||||||
Target &target = process_sp->GetTarget();
|
Target &target = process_sp->GetTarget();
|
||||||
const ModuleList &modules = target.GetImages();
|
ModuleList modules = target.GetImages();
|
||||||
size_t modules_count = modules.GetSize();
|
|
||||||
|
// stack-only corefiles have no reason to include binaries that
|
||||||
|
// are not executing; we're trying to make the smallest corefile
|
||||||
|
// we can, so leave the rest out.
|
||||||
|
if (core_style == SaveCoreStyle::eSaveCoreStackOnly)
|
||||||
|
modules.Clear();
|
||||||
|
|
||||||
std::set<std::string> executing_uuids;
|
std::set<std::string> executing_uuids;
|
||||||
ThreadList &thread_list(process_sp->GetThreadList());
|
ThreadList &thread_list(process_sp->GetThreadList());
|
||||||
|
@ -6363,10 +6367,12 @@ CreateAllImageInfosPayload(const lldb::ProcessSP &process_sp,
|
||||||
UUID uuid = module_sp->GetUUID();
|
UUID uuid = module_sp->GetUUID();
|
||||||
if (uuid.IsValid()) {
|
if (uuid.IsValid()) {
|
||||||
executing_uuids.insert(uuid.GetAsString());
|
executing_uuids.insert(uuid.GetAsString());
|
||||||
|
modules.AppendIfNeeded(module_sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
size_t modules_count = modules.GetSize();
|
||||||
|
|
||||||
struct all_image_infos_header infos;
|
struct all_image_infos_header infos;
|
||||||
infos.version = 1;
|
infos.version = 1;
|
||||||
|
@ -6508,12 +6514,9 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
|
||||||
if (!process_sp)
|
if (!process_sp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// For Mach-O, we can only create full corefiles or dirty-page-only
|
// Default on macOS is to create a dirty-memory-only corefile.
|
||||||
// corefiles. The default is dirty-page-only.
|
if (core_style == SaveCoreStyle::eSaveCoreUnspecified) {
|
||||||
if (core_style != SaveCoreStyle::eSaveCoreFull) {
|
|
||||||
core_style = SaveCoreStyle::eSaveCoreDirtyOnly;
|
core_style = SaveCoreStyle::eSaveCoreDirtyOnly;
|
||||||
} else {
|
|
||||||
core_style = SaveCoreStyle::eSaveCoreFull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Target &target = process_sp->GetTarget();
|
Target &target = process_sp->GetTarget();
|
||||||
|
@ -6568,13 +6571,23 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (prot != 0) {
|
bool include_this_region = true;
|
||||||
|
bool dirty_pages_only = false;
|
||||||
|
if (core_style == SaveCoreStyle::eSaveCoreStackOnly) {
|
||||||
|
dirty_pages_only = true;
|
||||||
|
if (range_info.IsStackMemory() != MemoryRegionInfo::eYes) {
|
||||||
|
include_this_region = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (core_style == SaveCoreStyle::eSaveCoreDirtyOnly) {
|
||||||
|
dirty_pages_only = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot != 0 && include_this_region) {
|
||||||
addr_t pagesize = range_info.GetPageSize();
|
addr_t pagesize = range_info.GetPageSize();
|
||||||
const llvm::Optional<std::vector<addr_t>> &dirty_page_list =
|
const llvm::Optional<std::vector<addr_t>> &dirty_page_list =
|
||||||
range_info.GetDirtyPageList();
|
range_info.GetDirtyPageList();
|
||||||
if (core_style == SaveCoreStyle::eSaveCoreDirtyOnly &&
|
if (dirty_pages_only && dirty_page_list.hasValue()) {
|
||||||
dirty_page_list.hasValue()) {
|
|
||||||
core_style = SaveCoreStyle::eSaveCoreDirtyOnly;
|
|
||||||
for (addr_t dirtypage : dirty_page_list.getValue()) {
|
for (addr_t dirtypage : dirty_page_list.getValue()) {
|
||||||
page_object obj;
|
page_object obj;
|
||||||
obj.addr = dirtypage;
|
obj.addr = dirtypage;
|
||||||
|
@ -6617,6 +6630,12 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
|
||||||
last_obj = obj;
|
last_obj = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we only ended up with one contiguous memory segment
|
||||||
|
if (combined_page_objects.size() == 0 &&
|
||||||
|
last_obj.addr != LLDB_INVALID_ADDRESS) {
|
||||||
|
combined_page_objects.push_back(last_obj);
|
||||||
|
}
|
||||||
|
|
||||||
for (page_object obj : combined_page_objects) {
|
for (page_object obj : combined_page_objects) {
|
||||||
uint32_t cmd_type = LC_SEGMENT_64;
|
uint32_t cmd_type = LC_SEGMENT_64;
|
||||||
uint32_t segment_size = sizeof(llvm::MachO::segment_command_64);
|
uint32_t segment_size = sizeof(llvm::MachO::segment_command_64);
|
||||||
|
@ -6767,7 +6786,8 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
|
||||||
all_image_infos_lcnote_up->name = "all image infos";
|
all_image_infos_lcnote_up->name = "all image infos";
|
||||||
all_image_infos_lcnote_up->payload_file_offset = file_offset;
|
all_image_infos_lcnote_up->payload_file_offset = file_offset;
|
||||||
file_offset = CreateAllImageInfosPayload(
|
file_offset = CreateAllImageInfosPayload(
|
||||||
process_sp, file_offset, all_image_infos_lcnote_up->payload);
|
process_sp, file_offset, all_image_infos_lcnote_up->payload,
|
||||||
|
core_style);
|
||||||
lc_notes.push_back(std::move(all_image_infos_lcnote_up));
|
lc_notes.push_back(std::move(all_image_infos_lcnote_up));
|
||||||
|
|
||||||
// Add LC_NOTE load commands
|
// Add LC_NOTE load commands
|
||||||
|
|
|
@ -1572,6 +1572,19 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (name.equals("type")) {
|
||||||
|
std::string comma_sep_str = value.str();
|
||||||
|
size_t comma_pos;
|
||||||
|
while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) {
|
||||||
|
comma_sep_str[comma_pos] = '\0';
|
||||||
|
if (comma_sep_str == "stack") {
|
||||||
|
region_info.SetIsStackMemory(MemoryRegionInfo::eYes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle final (or only) type of "stack"
|
||||||
|
if (comma_sep_str == "stack") {
|
||||||
|
region_info.SetIsStackMemory(MemoryRegionInfo::eYes);
|
||||||
|
}
|
||||||
} else if (name.equals("error")) {
|
} else if (name.equals("error")) {
|
||||||
StringExtractorGDBRemote error_extractor(value);
|
StringExtractorGDBRemote error_extractor(value);
|
||||||
std::string error_string;
|
std::string error_string;
|
||||||
|
|
|
@ -12,7 +12,7 @@ from lldbsuite.test.lldbtest import *
|
||||||
from lldbsuite.test import lldbutil
|
from lldbsuite.test import lldbutil
|
||||||
|
|
||||||
|
|
||||||
class TestFirmwareCorefiles(TestBase):
|
class TestSkinnyCorefile(TestBase):
|
||||||
|
|
||||||
mydir = TestBase.compute_mydir(__file__)
|
mydir = TestBase.compute_mydir(__file__)
|
||||||
|
|
||||||
|
|
3
lldb/test/API/macosx/stack-corefile/Makefile
Normal file
3
lldb/test/API/macosx/stack-corefile/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
C_SOURCES = main.c
|
||||||
|
|
||||||
|
include Makefile.rules
|
69
lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
Normal file
69
lldb/test/API/macosx/stack-corefile/TestStackCorefile.py
Normal file
|
@ -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, "// break here", lldb.SBFileSpec("main.c"))
|
||||||
|
|
||||||
|
frame = thread.GetFrameAtIndex(0)
|
||||||
|
stack_int = frame.GetValueForVariablePath("stack_int")
|
||||||
|
heap_int = frame.GetValueForVariablePath("*heap_int")
|
||||||
|
stack_str = frame.GetValueForVariablePath("stack_str")
|
||||||
|
heap_str = frame.GetValueForVariablePath("heap_str")
|
||||||
|
self.assertEqual(stack_int.GetValueAsUnsigned(), 5)
|
||||||
|
self.assertEqual(heap_int.GetValueAsUnsigned(), 10)
|
||||||
|
self.assertEqual(stack_str.summary, '"stack string"')
|
||||||
|
self.assertEqual(heap_str.summary, '"heap string"')
|
||||||
|
|
||||||
|
self.runCmd("process save-core -s stack " + corefile)
|
||||||
|
process.Kill()
|
||||||
|
self.dbg.DeleteTarget(target)
|
||||||
|
|
||||||
|
# Now load the corefile
|
||||||
|
target = self.dbg.CreateTarget('')
|
||||||
|
process = target.LoadCore(corefile)
|
||||||
|
thread = process.GetSelectedThread()
|
||||||
|
self.assertTrue(process.IsValid())
|
||||||
|
self.assertTrue(process.GetSelectedThread().IsValid())
|
||||||
|
if self.TraceOn():
|
||||||
|
self.runCmd("image list")
|
||||||
|
self.runCmd("bt")
|
||||||
|
self.runCmd("fr v")
|
||||||
|
num_modules = target.GetNumModules()
|
||||||
|
# We should only have the a.out binary and possibly
|
||||||
|
# the libdyld.dylib. Extra libraries loaded means
|
||||||
|
# extra LC_NOTE and unnecessarily large corefile.
|
||||||
|
self.assertTrue(num_modules == 1 or num_modules == 2)
|
||||||
|
|
||||||
|
# The heap variables should be unavailable now.
|
||||||
|
frame = thread.GetFrameAtIndex(0)
|
||||||
|
stack_int = frame.GetValueForVariablePath("stack_int")
|
||||||
|
heap_int = frame.GetValueForVariablePath("*heap_int")
|
||||||
|
stack_str = frame.GetValueForVariablePath("stack_str")
|
||||||
|
heap_str = frame.GetValueForVariablePath("heap_str")
|
||||||
|
|
||||||
|
## The heap SBValues both come back as IsValid()==true,
|
||||||
|
## which I'm not so sure is a great/correct thing --
|
||||||
|
## it hides the memory read error that actually happened,
|
||||||
|
## and we don't have a real value.
|
||||||
|
self.assertEqual(stack_int.GetValueAsUnsigned(), 5)
|
||||||
|
self.assertEqual(heap_int.GetValueAsUnsigned(), 0)
|
||||||
|
self.assertEqual(stack_str.summary, '"stack string"')
|
||||||
|
self.assertEqual(heap_str.summary, '""')
|
15
lldb/test/API/macosx/stack-corefile/main.c
Normal file
15
lldb/test/API/macosx/stack-corefile/main.c
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
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;
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
#include <sys/syslimits.h>
|
#include <sys/syslimits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -318,11 +319,13 @@ struct DNBExecutableImageInfo {
|
||||||
|
|
||||||
struct DNBRegionInfo {
|
struct DNBRegionInfo {
|
||||||
public:
|
public:
|
||||||
DNBRegionInfo() : addr(0), size(0), permissions(0), dirty_pages() {}
|
DNBRegionInfo()
|
||||||
|
: addr(0), size(0), permissions(0), dirty_pages(), vm_types() {}
|
||||||
nub_addr_t addr;
|
nub_addr_t addr;
|
||||||
nub_addr_t size;
|
nub_addr_t size;
|
||||||
uint32_t permissions;
|
uint32_t permissions;
|
||||||
std::vector<nub_addr_t> dirty_pages;
|
std::vector<nub_addr_t> dirty_pages;
|
||||||
|
std::vector<std::string> vm_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DNBProfileDataScanType {
|
enum DNBProfileDataScanType {
|
||||||
|
|
|
@ -125,6 +125,7 @@ nub_bool_t MachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address,
|
||||||
region_info->permissions = vmRegion.GetDNBPermissions();
|
region_info->permissions = vmRegion.GetDNBPermissions();
|
||||||
region_info->dirty_pages =
|
region_info->dirty_pages =
|
||||||
get_dirty_pages(task, vmRegion.StartAddress(), vmRegion.GetByteSize());
|
get_dirty_pages(task, vmRegion.StartAddress(), vmRegion.GetByteSize());
|
||||||
|
region_info->vm_types = vmRegion.GetMemoryTypes();
|
||||||
} else {
|
} else {
|
||||||
region_info->addr = address;
|
region_info->addr = address;
|
||||||
region_info->size = 0;
|
region_info->size = 0;
|
||||||
|
|
|
@ -182,3 +182,43 @@ uint32_t MachVMRegion::GetDNBPermissions() const {
|
||||||
dnb_permissions |= eMemoryPermissionsExecutable;
|
dnb_permissions |= eMemoryPermissionsExecutable;
|
||||||
return dnb_permissions;
|
return dnb_permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MachVMRegion::GetMemoryTypes() const {
|
||||||
|
std::vector<std::string> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
vm_prot_t prot);
|
vm_prot_t prot);
|
||||||
bool RestoreProtections();
|
bool RestoreProtections();
|
||||||
bool GetRegionForAddress(nub_addr_t addr);
|
bool GetRegionForAddress(nub_addr_t addr);
|
||||||
|
std::vector<std::string> GetMemoryTypes() const;
|
||||||
|
|
||||||
uint32_t GetDNBPermissions() const;
|
uint32_t GetDNBPermissions() const;
|
||||||
|
|
||||||
|
|
|
@ -4310,6 +4310,14 @@ rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ostrm << ";";
|
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());
|
return SendPacket(ostrm.str());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue