From 46fb558df13ad41638408734014a89baef592f51 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Fri, 18 Nov 2011 07:03:08 +0000 Subject: [PATCH] Added optional calls to lldb_private::Process for getting memory region info from a process and hooked it up to the new packet that was recently added to our GDB remote executable named debugserver. Now Process has the following new calls: virtual Error Process::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info); virtual uint32_t GetLoadAddressPermissions (lldb::addr_t load_addr); Only the first one needs to be implemented by subclasses that can add this support. Cleaned up the way the new packet was implemented in debugserver to be more useful as an API inside debugserver. Also found an error where finding a region for an address actually will pick up the next region that follows the address in the query so we also need ot make sure that the address we requested the region for falls into the region that gets returned. llvm-svn: 144976 --- lldb/include/lldb/Target/Process.h | 91 +++++++++++++++++++ .../GDBRemoteCommunicationClient.cpp | 73 +++++++++++++++ .../gdb-remote/GDBRemoteCommunicationClient.h | 6 ++ .../Process/gdb-remote/ProcessGDBRemote.cpp | 9 ++ .../Process/gdb-remote/ProcessGDBRemote.h | 4 + lldb/tools/debugserver/source/DNB.cpp | 7 +- lldb/tools/debugserver/source/DNB.h | 2 +- lldb/tools/debugserver/source/DNBDefs.h | 7 ++ .../debugserver/source/MacOSX/MachProcess.cpp | 6 -- .../debugserver/source/MacOSX/MachProcess.h | 1 - .../debugserver/source/MacOSX/MachTask.cpp | 11 ++- .../debugserver/source/MacOSX/MachTask.h | 2 +- .../source/MacOSX/MachVMMemory.cpp | 16 +++- .../debugserver/source/MacOSX/MachVMMemory.h | 2 +- .../source/MacOSX/MachVMRegion.cpp | 52 ++++++----- .../debugserver/source/MacOSX/MachVMRegion.h | 4 +- lldb/tools/debugserver/source/RNBRemote.cpp | 53 +++++++++-- 17 files changed, 291 insertions(+), 55 deletions(-) diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index df07491ece56..a921c7718243 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -27,6 +27,7 @@ #include "lldb/Core/Communication.h" #include "lldb/Core/Error.h" #include "lldb/Core/Event.h" +#include "lldb/Core/RangeMap.h" #include "lldb/Core/StringList.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Core/PluginInterface.h" @@ -1171,6 +1172,77 @@ inline bool operator!= (const ProcessModID &lhs, const ProcessModID &rhs) else return false; } + +class MemoryRegionInfo +{ +public: + typedef Range RangeType; + + MemoryRegionInfo () : + m_range (), + m_permissions (0) + { + } + + ~MemoryRegionInfo () + { + } + + RangeType & + GetRange() + { + return m_range; + } + + void + Clear() + { + m_range.Clear(); + m_permissions = 0; + } + + const RangeType & + GetRange() const + { + return m_range; + } + + // Pass in a uint32_t permissions with one or more lldb::Permissions + // enumeration values logical OR'ed together. + bool + TestPermissions (uint32_t permissions) const + { + return m_permissions.AllSet(permissions); + } + + const Flags & + GetPermissions () const + { + return m_permissions; + } + + void + SetPermissions (uint32_t permissions) + { + m_permissions.Reset(permissions); + } + + void + AddPermissions (uint32_t permissions) + { + m_permissions.Set (permissions); + } + + void + RemovePermissions (uint32_t permissions) + { + m_permissions.Clear (permissions); + } + +protected: + RangeType m_range; + Flags m_permissions; // Uses lldb::Permissions enumeration values logical OR'ed together +}; //---------------------------------------------------------------------- /// @class Process Process.h "lldb/Target/Process.h" @@ -2478,6 +2550,25 @@ public: lldb::addr_t AllocateMemory (size_t size, uint32_t permissions, Error &error); + virtual Error + GetMemoryRegionInfo (lldb::addr_t load_addr, + MemoryRegionInfo &range_info) + { + Error error; + error.SetErrorString ("Process::GetMemoryRegionInfo() not supported"); + return error; + } + + virtual uint32_t + GetLoadAddressPermissions (lldb::addr_t load_addr) + { + MemoryRegionInfo range_info; + Error error (GetMemoryRegionInfo (load_addr, range_info)); + if (error.Success()) + return range_info.GetPermissions().Get(); + return 0; + } + //------------------------------------------------------------------ /// Determines whether executing JIT-compiled code in this process /// is possible. diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 5dd4dc680277..13b1abe796de 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -46,6 +46,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_supports_vCont_S (eLazyBoolCalculate), m_qHostInfo_is_valid (eLazyBoolCalculate), m_supports_alloc_dealloc_memory (eLazyBoolCalculate), + m_supports_memory_region_info (eLazyBoolCalculate), m_supports_qProcessInfoPID (true), m_supports_qfProcessInfo (true), m_supports_qUserName (true), @@ -123,6 +124,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_vCont_S = eLazyBoolCalculate; m_qHostInfo_is_valid = eLazyBoolCalculate; m_supports_alloc_dealloc_memory = eLazyBoolCalculate; + m_supports_memory_region_info = eLazyBoolCalculate; m_supports_qProcessInfoPID = true; m_supports_qfProcessInfo = true; @@ -1086,6 +1088,77 @@ GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr) return false; } +Error +GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, + lldb_private::MemoryRegionInfo ®ion_info) +{ + Error error; + region_info.Clear(); + + if (m_supports_memory_region_info != eLazyBoolNo) + { + m_supports_memory_region_info = eLazyBoolYes; + char packet[64]; + const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%llx", (uint64_t)addr); + assert (packet_len < sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + { + std::string name; + std::string value; + addr_t addr_value; + bool success = true; + while (success && response.GetNameColonValue(name, value)) + { + if (name.compare ("start") == 0) + { + addr_value = Args::StringToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); + if (success) + region_info.GetRange().SetRangeBase(addr_value); + } + else if (name.compare ("size") == 0) + { + addr_value = Args::StringToUInt64(value.c_str(), 0, 16, &success); + if (success) + region_info.GetRange().SetByteSize (addr_value); + } + else if (name.compare ("permissions") == 0) + { + if (value.find('r') != std::string::npos) + region_info.AddPermissions (ePermissionsReadable); + if (value.find('w') != std::string::npos) + region_info.AddPermissions (ePermissionsWritable); + if (value.find('x') != std::string::npos) + region_info.AddPermissions (ePermissionsExecutable); + } + else if (name.compare ("error") == 0) + { + StringExtractorGDBRemote name_extractor; + // Swap "value" over into "name_extractor" + name_extractor.GetStringRef().swap(value); + // Now convert the HEX bytes into a string value + name_extractor.GetHexByteString (value); + error.SetErrorString(value.c_str()); + } + } + } + else + { + m_supports_memory_region_info = eLazyBoolNo; + } + } + + if (m_supports_memory_region_info == eLazyBoolNo) + { + error.SetErrorString("qMemoryRegionInfo is not supported"); + } + if (error.Fail()) + region_info.Clear(); + return error; + +} + + int GDBRemoteCommunicationClient::SetSTDIN (char const *path) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 0f980fe102b6..30d6fb0707ef 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -17,6 +17,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/ArchSpec.h" +#include "lldb/Target/Process.h" #include "GDBRemoteCommunication.h" @@ -196,6 +197,10 @@ public: bool DeallocateMemory (lldb::addr_t addr); + lldb_private::Error + GetMemoryRegionInfo (lldb::addr_t addr, + lldb_private::MemoryRegionInfo &range_info); + const lldb_private::ArchSpec & GetHostArchitecture (); @@ -332,6 +337,7 @@ protected: lldb_private::LazyBool m_supports_vCont_S; lldb_private::LazyBool m_qHostInfo_is_valid; lldb_private::LazyBool m_supports_alloc_dealloc_memory; + lldb_private::LazyBool m_supports_memory_region_info; bool m_supports_qProcessInfoPID:1, diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index ba6431291ad7..6aa89fadaa9b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1703,6 +1703,15 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er return allocated_addr; } +Error +ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr, + MemoryRegionInfo ®ion_info) +{ + + Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info)); + return error; +} + Error ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr) { diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 2b298ffe2b19..15ccb34ef3a3 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -166,6 +166,10 @@ public: virtual lldb::addr_t DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error); + virtual lldb_private::Error + GetMemoryRegionInfo (lldb::addr_t load_addr, + lldb_private::MemoryRegionInfo ®ion_info); + virtual lldb_private::Error DoDeallocateMemory (lldb::addr_t ptr); diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index c6dc313cd316..12950102edd5 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -1139,13 +1139,12 @@ DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) // //---------------------------------------------------------------------- int -DNBMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, char *outbuf, nub_size_t outbufsize) +DNBMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info) { MachProcessSP procSP; if (GetProcessSP (pid, procSP)) - { - return procSP->MemoryRegionInfo(addr, outbuf, outbufsize); - } + return procSP->Task().GetMemoryRegionInfo (addr, region_info); + return -1; } diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h index 3b6009a82215..2e791f41e218 100644 --- a/lldb/tools/debugserver/source/DNB.h +++ b/lldb/tools/debugserver/source/DNB.h @@ -66,7 +66,7 @@ nub_size_t DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub nub_size_t DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf) DNB_EXPORT; nub_addr_t DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions) DNB_EXPORT; nub_bool_t DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; -int DNBMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, char *outbuf, nub_size_t outbufsize); +int DNBMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info) DNB_EXPORT; //---------------------------------------------------------------------- // Process status diff --git a/lldb/tools/debugserver/source/DNBDefs.h b/lldb/tools/debugserver/source/DNBDefs.h index 4b4729307d57..87926327504a 100644 --- a/lldb/tools/debugserver/source/DNBDefs.h +++ b/lldb/tools/debugserver/source/DNBDefs.h @@ -333,6 +333,13 @@ struct DNBExecutableImageInfo DNBSegment *segments; // Array of contiguous memory segments in executable }; +struct DNBRegionInfo +{ + nub_addr_t addr; + nub_addr_t size; + uint32_t permissions; +}; + typedef nub_bool_t (*DNBCallbackBreakpointHit)(nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton); typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid, const char *name, const char *shlib_regex, void *baton); typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton); diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp index 4cf8fd335da6..264c7362e617 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp @@ -603,12 +603,6 @@ MachProcess::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf) return bytes_written; } -int -MachProcess::MemoryRegionInfo(nub_addr_t address, char *outbuf, nub_size_t outbufsize) -{ - return m_task.MemoryRegionInfo (address, outbuf, outbufsize); -} - void MachProcess::ReplyToAllExceptions () { diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h index 732d50d69dbc..d52735adba71 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -99,7 +99,6 @@ public: bool Detach (); nub_size_t ReadMemory (nub_addr_t addr, nub_size_t size, void *buf); nub_size_t WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf); - int MemoryRegionInfo(nub_addr_t address, char *outbuf, nub_size_t outbufsize); //---------------------------------------------------------------------- // Path and arg accessors diff --git a/lldb/tools/debugserver/source/MacOSX/MachTask.cpp b/lldb/tools/debugserver/source/MacOSX/MachTask.cpp index b6368fc89569..88f3f46b45ee 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachTask.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachTask.cpp @@ -208,14 +208,19 @@ MachTask::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf) // MachTask::MemoryRegionInfo //---------------------------------------------------------------------- int -MachTask::MemoryRegionInfo (nub_addr_t addr, char *outbuf, nub_size_t outbufsize) +MachTask::GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info) { task_t task = TaskPort(); if (task == TASK_NULL) return -1; - int ret = m_vm_memory.MemoryRegionInfo(task, addr, outbuf, outbufsize); - DNBLogThreadedIf(LOG_MEMORY, "MachTask::MemoryRegionInfo ( addr = 0x%8.8llx ) => %d", (uint64_t)addr, ret); + int ret = m_vm_memory.GetMemoryRegionInfo(task, addr, region_info); + DNBLogThreadedIf(LOG_MEMORY, "MachTask::MemoryRegionInfo ( addr = 0x%8.8llx ) => %i (start = 0x%8.8llx, size = 0x%8.8llx, permissions = %u)", + (uint64_t)addr, + ret, + (uint64_t)region_info->addr, + (uint64_t)region_info->size, + region_info->permissions); return ret; } diff --git a/lldb/tools/debugserver/source/MacOSX/MachTask.h b/lldb/tools/debugserver/source/MacOSX/MachTask.h index f0cfd0e56e82..b0eaa8d60ded 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachTask.h +++ b/lldb/tools/debugserver/source/MacOSX/MachTask.h @@ -64,7 +64,7 @@ public: nub_size_t ReadMemory (nub_addr_t addr, nub_size_t size, void *buf); nub_size_t WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf); - int MemoryRegionInfo (nub_addr_t addr, char *outbuf, nub_size_t outbufsize); + int GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info); nub_addr_t AllocateMemory (nub_size_t size, uint32_t permissions); nub_bool_t DeallocateMemory (nub_addr_t addr); diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp index 69e50d546cfd..d0eb3e753685 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp @@ -53,15 +53,21 @@ MachVMMemory::MaxBytesLeftInPage(nub_addr_t addr, nub_size_t count) } int -MachVMMemory::MemoryRegionInfo(task_t task, nub_addr_t address, char *outbuf, nub_size_t outbufsize) +MachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info) { MachVMRegion vmRegion(task); - outbuf[0] = '\0'; - if (vmRegion.GetRegionForAddress(address) && vmRegion.GetRegionDescription(outbuf, outbufsize)) + if (vmRegion.GetRegionForAddress(address)) + { + region_info->addr = vmRegion.StartAddress(); + region_info->size = vmRegion.GetByteSize(); + region_info->permissions = vmRegion.GetDNBPermissions(); return 1; - else - return 0; + } + region_info->addr = 0; + region_info->size = 0; + region_info->permissions = 0; + return 0; } nub_size_t diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h index fa5583383bf0..e32fa4f4c447 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h +++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h @@ -27,7 +27,7 @@ public: nub_size_t Read(task_t task, nub_addr_t address, void *data, nub_size_t data_count); nub_size_t Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count); nub_size_t PageSize(); - int MemoryRegionInfo(task_t task, nub_addr_t address, char *outbuf, nub_size_t outbufsize); + int GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info); protected: nub_size_t MaxBytesLeftInPage(nub_addr_t addr, nub_size_t count); diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp index f12f2b927033..e1667f0c196d 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp @@ -134,7 +134,21 @@ MachVMRegion::GetRegionForAddress(nub_addr_t addr) mach_msg_type_number_t info_size = kRegionInfoSize; assert(sizeof(info_size) == 4); m_err = ::mach_vm_region_recurse (m_task, &m_start, &m_size, &m_depth, (vm_region_recurse_info_t)&m_data, &info_size); - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS) || m_err.Fail()) + const bool log_protections = DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS); + if (m_err.Success()) + { + if ((addr < m_start) || (addr >= (m_start + m_size))) + { + m_err.SetErrorString("no region for address"); + m_err.SetError(-1, DNBError::Generic); + if (log_protections) + m_err.LogThreaded("::mach_vm_region_recurse ( task = 0x%4.4x, address => 0x%8.8llx, size => %llu, nesting_depth => %d, info => %p, infoCnt => %d) addr = 0x%8.8llx not in range [0x%8.8llx - 0x%8.8llx)", + m_task, (uint64_t)m_start, (uint64_t)m_size, m_depth, &m_data, info_size, (uint64_t)addr, (uint64_t)m_start, (uint64_t)m_start + m_size); + return false; + } + } + + if (log_protections || m_err.Fail()) m_err.LogThreaded("::mach_vm_region_recurse ( task = 0x%4.4x, address => 0x%8.8llx, size => %llu, nesting_depth => %d, info => %p, infoCnt => %d) addr = 0x%8.8llx ", m_task, (uint64_t)m_start, (uint64_t)m_size, m_depth, &m_data, info_size, (uint64_t)addr); if (m_err.Fail()) { @@ -142,7 +156,7 @@ MachVMRegion::GetRegionForAddress(nub_addr_t addr) } else { - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS)) + if (log_protections) { DNBLogThreaded("info = { prot = %u, " "max_prot = %u, " @@ -178,26 +192,18 @@ MachVMRegion::GetRegionForAddress(nub_addr_t addr) return true; } -bool -MachVMRegion::GetRegionDescription (char *outbuf, nub_size_t outbufsize) +uint32_t +MachVMRegion::GetDNBPermissions () const { - if (m_addr == INVALID_NUB_ADDRESS || m_start == INVALID_NUB_ADDRESS || m_size == 0) - return false; - snprintf (outbuf, outbufsize, "start:%llx,size:%llx", m_start, m_size); - outbuf[outbufsize - 1] = '\0'; - - char tmpbuf[128]; - strcpy (tmpbuf, ",permissions:"); - if ((m_data.protection & VM_PROT_READ) == VM_PROT_READ) - strcat (tmpbuf, "r"); - if ((m_data.protection & VM_PROT_WRITE) == VM_PROT_WRITE) - strcat (tmpbuf, "w"); - if ((m_data.protection & VM_PROT_EXECUTE) == VM_PROT_EXECUTE) - strcat (tmpbuf, "x"); - strlcat (outbuf, tmpbuf, outbufsize); - - // It would be nice if we could figure out whether the memory region is stack memory or jitted code memory as well - - outbuf[outbufsize - 1] = '\0'; - return true; + if (m_addr == INVALID_NUB_ADDRESS || m_start == INVALID_NUB_ADDRESS || m_size == 0) + return 0; + uint32_t dnb_permissions = 0; + + if ((m_data.protection & VM_PROT_READ) == VM_PROT_READ) + dnb_permissions |= eMemoryPermissionsReadable; + if ((m_data.protection & VM_PROT_WRITE) == VM_PROT_WRITE) + dnb_permissions |= eMemoryPermissionsWritable; + if ((m_data.protection & VM_PROT_EXECUTE) == VM_PROT_EXECUTE) + dnb_permissions |= eMemoryPermissionsExecutable; + return dnb_permissions; } diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h index 7a3bd5866002..e856f0b24140 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h +++ b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h @@ -27,6 +27,7 @@ public: void Clear(); mach_vm_address_t StartAddress() const { return m_start; } mach_vm_address_t EndAddress() const { return m_start + m_size; } + mach_vm_size_t GetByteSize () const { return m_size; } mach_vm_address_t BytesRemaining(mach_vm_address_t addr) const { if (ContainsAddress(addr)) @@ -43,7 +44,8 @@ public: bool RestoreProtections(); bool GetRegionForAddress(nub_addr_t addr); - bool GetRegionDescription (char *outbuf, nub_size_t outbufsize); + uint32_t + GetDNBPermissions () const; protected: #if defined (VM_REGION_SUBMAP_SHORT_INFO_COUNT_64) diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 6cb251a682af..c640023b21ee 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -3282,16 +3282,51 @@ RNBRemote::HandlePacket_MemoryRegionInfo (const char *p) return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet"); } - char retbuf[1024]; + DNBRegionInfo region_info = { 0, 0, 0 }; + int ret = DNBMemoryRegionInfo (m_ctx.ProcessID(), address, ®ion_info); + std::ostringstream ostrm; - int ret = DNBMemoryRegionInfo (m_ctx.ProcessID(), address, retbuf, sizeof (retbuf)); - retbuf[sizeof (retbuf) - 1] = '\0'; - if (ret == 1) - return SendPacket (retbuf); - if (ret == 0) - return SendPacket ("error:address in unmapped region"); - if (ret == -1) - return SendPacket ("error:region lookup cannot be performed"); + if (ret == 1 && region_info.size > 0) + { + // start:3a50000,size:100000,permissions:rwx + ostrm << "start:" << std::hex << region_info.addr << ';' + << "size:" << std::hex << region_info.size << ';'; + + if (region_info.permissions) + { + ostrm << "permissions:"; + + if (region_info.permissions & eMemoryPermissionsReadable) + ostrm << 'r'; + if (region_info.permissions & eMemoryPermissionsWritable) + ostrm << 'w'; + if (region_info.permissions & eMemoryPermissionsExecutable) + ostrm << 'x'; + ostrm << ';'; + } + return SendPacket (ostrm.str()); + } + else + { + ostrm << std::hex << "error:"; + const char *error_message = NULL; + if (ret == -1) + { + error_message = "region lookup cannot be performed"; + } + else + { + error_message = "address in unmapped region"; + } + // hex encode the error message so we can send any characters we want in + // the future since this is text + const int error_message_len = strlen (error_message); + const uint8_t *u_error_message = (const uint8_t *)error_message; + for (int i = 0; i < error_message_len; i++) + ostrm << RAWHEX8(u_error_message[i]); + ostrm << ';'; + return SendPacket (ostrm.str()); + } return SendPacket ("E68"); }