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
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
index 4cf8fd3..264c736 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
@@ -603,12 +603,6 @@
     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 732d50d..d52735a 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
@@ -99,7 +99,6 @@
     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 b6368fc..88f3f46 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
@@ -208,14 +208,19 @@
 // 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 f0cfd0e..b0eaa8d 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachTask.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachTask.h
@@ -64,7 +64,7 @@
 
             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 69e50d5..d0eb3e7 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp
@@ -53,15 +53,21 @@
 }
 
 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 fa55833..e32fa4f 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h
@@ -27,7 +27,7 @@
     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 f12f2b92..e1667f0 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp
@@ -134,7 +134,21 @@
     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 @@
     }
     else
     {
-        if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS))
+        if (log_protections)
         {
             DNBLogThreaded("info = { prot = %u, "
                              "max_prot = %u, "
@@ -178,26 +192,18 @@
     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 7a3bd58..e856f0b 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h
@@ -27,6 +27,7 @@
     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 @@
     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)