When unwinding from the first frame, try to ask the remote debugserver
if this is a mapped/executable region of memory.  If it isn't, we've jumped
through a bad pointer and we know how to unwind the stack correctly based
on the ABI.  

Previously I had 0x0 special cased but if you jumped to 0x2 on x86_64 one
frame would be skipped because the unwinder would try using the x86_64 
ArchDefaultUnwindPlan which relied on the rbp.

Fixes <rdar://problem/10508291>

llvm-svn: 146477
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 8eefb5e..fe14269 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -562,8 +562,7 @@
     UnwindPlanSP unwind_plan_sp;
     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     UnwindPlanSP arch_default_unwind_plan_sp;
-    
-    
+
     ABI *abi = m_thread.GetProcess().GetABI().get();
     if (abi)
     {
@@ -584,14 +583,22 @@
 
     // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer) so the pc is 0x0
     // in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
-    if (behaves_like_zeroth_frame 
-        && m_current_pc.IsValid() 
-        && m_current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()) == 0)
+    // Also, if this Process can report on memory region attributes, any non-executable region means
+    // we jumped through a bad function pointer - handle the same way as 0x0.
+
+    if (behaves_like_zeroth_frame && m_current_pc.IsValid())
     {
-        unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
-        abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp);
-        m_frame_type = eNormalFrame;
-        return unwind_plan_sp;
+        uint32_t permissions;
+        addr_t current_pc_addr = m_current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget());
+        if (current_pc_addr == 0
+            || (m_thread.GetProcess().GetLoadAddressPermissions(current_pc_addr, permissions)
+                && (permissions & ePermissionsExecutable) == 0))
+        {
+            unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp);
+            m_frame_type = eNormalFrame;
+            return unwind_plan_sp;
+        }
     }
 
     // No Module fm_current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()or the current pc, try using the architecture default unwind.
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 60234ac..eaa0398 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -1108,6 +1108,7 @@
             std::string value;
             addr_t addr_value;
             bool success = true;
+            bool saw_permissions = false;
             while (success && response.GetNameColonValue(name, value))
             {
                 if (name.compare ("start") == 0)
@@ -1122,14 +1123,33 @@
                     if (success)
                         region_info.GetRange().SetByteSize (addr_value);
                 }
-                else if (name.compare ("permissions") == 0)
+                else if (name.compare ("permissions") == 0 && region_info.GetRange().IsValid())
                 {
-                    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);
+                    saw_permissions = true;
+                    if (region_info.GetRange().Contains (addr))
+                    {
+                        if (value.find('r') != std::string::npos)
+                            region_info.SetReadable (MemoryRegionInfo::eYes);
+                        else
+                            region_info.SetReadable (MemoryRegionInfo::eNo);
+
+                        if (value.find('w') != std::string::npos)
+                            region_info.SetWritable (MemoryRegionInfo::eYes);
+                        else
+                            region_info.SetWritable (MemoryRegionInfo::eNo);
+
+                        if (value.find('x') != std::string::npos)
+                            region_info.SetExecutable (MemoryRegionInfo::eYes);
+                        else
+                            region_info.SetExecutable (MemoryRegionInfo::eNo);
+                    }
+                    else
+                    {
+                        // The reported region does not contain this address -- we're looking at an unmapped page
+                        region_info.SetReadable (MemoryRegionInfo::eNo);
+                        region_info.SetWritable (MemoryRegionInfo::eNo);
+                        region_info.SetExecutable (MemoryRegionInfo::eNo);
+                    }
                 }
                 else if (name.compare ("error") == 0)
                 {
@@ -1141,6 +1161,14 @@
                     error.SetErrorString(value.c_str());
                 }
             }
+
+            // We got a valid address range back but no permissions -- which means this is an unmapped page
+            if (region_info.GetRange().IsValid() && saw_permissions == false)
+            {
+                region_info.SetReadable (MemoryRegionInfo::eNo);
+                region_info.SetWritable (MemoryRegionInfo::eNo);
+                region_info.SetExecutable (MemoryRegionInfo::eNo);
+            }
         }
         else
         {