[Lldb-commits] [lldb] r146477 - in /lldb/trunk: docs/lldb-gdb-remote.txt include/lldb/Target/Process.h source/Plugins/Process/Utility/RegisterContextLLDB.cpp source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp

Jason Molenda jmolenda at apple.com
Mon Dec 12 21:39:38 PST 2011


Author: jmolenda
Date: Mon Dec 12 23:39:38 2011
New Revision: 146477

URL: http://llvm.org/viewvc/llvm-project?rev=146477&view=rev
Log:
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>


Modified:
    lldb/trunk/docs/lldb-gdb-remote.txt
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp

Modified: lldb/trunk/docs/lldb-gdb-remote.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/docs/lldb-gdb-remote.txt?rev=146477&r1=146476&r2=146477&view=diff
==============================================================================
--- lldb/trunk/docs/lldb-gdb-remote.txt (original)
+++ lldb/trunk/docs/lldb-gdb-remote.txt Mon Dec 12 23:39:38 2011
@@ -592,6 +592,18 @@
                                      // a hex encoded string value that 
                                      // contains an error string
                                     
+If the address requested is not in a mapped region (e.g. we've jumped through
+a NULL pointer and are at 0x0) currently lldb expects to get back the size 
+of the unmapped region -- that is, the distance to the next valid region.
+For instance, with a Mac OS X process which has nothing mapped in the first
+4GB of its address space, if we're asking about address 0x2,
+
+  qMemoryRegionInfo:2
+  start:2;size:fffffffe;
+
+The lack of 'permissions:' indicates that none of read/write/execute are valid
+for this region.
+
 //----------------------------------------------------------------------
 // Stop reply packet extensions
 //

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=146477&r1=146476&r2=146477&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Mon Dec 12 23:39:38 2011
@@ -1177,10 +1177,18 @@
 {
 public:
     typedef Range<lldb::addr_t, lldb::addr_t> RangeType;
-    
+
+    enum OptionalBool {
+        eDontKnow  = -1,
+        eNo         = 0,
+        eYes        = 1
+    };
+
     MemoryRegionInfo () :
         m_range (),
-        m_permissions (0)
+        m_read (eDontKnow),
+        m_write (eDontKnow),
+        m_execute (eDontKnow)
     {
     }
 
@@ -1198,7 +1206,7 @@
     Clear()
     {
         m_range.Clear();
-        m_permissions = 0;
+        m_read = m_write = m_execute = eDontKnow;
     }
 
     const RangeType &
@@ -1206,42 +1214,48 @@
     {
         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
+
+    OptionalBool
+    GetReadable () const
     {
-        return m_permissions.AllSet(permissions);
+        return m_read;
     }
-    
-    const Flags &
-    GetPermissions () const
+
+    OptionalBool
+    GetWritable () const
     {
-        return m_permissions;
+        return m_write;
+    }
+
+    OptionalBool
+    GetExecutable () const
+    {
+        return m_execute;
     }
 
     void
-    SetPermissions (uint32_t permissions)
+    SetReadable (OptionalBool val)
     {
-        m_permissions.Reset(permissions);
+        m_read = val;
     }
-    
+
     void
-    AddPermissions (uint32_t permissions)
+    SetWritable (OptionalBool val)
     {
-        m_permissions.Set (permissions);
+        m_write = val;
     }
 
     void
-    RemovePermissions (uint32_t permissions)
+    SetExecutable (OptionalBool val)
     {
-        m_permissions.Clear (permissions);
+        m_execute = val;
     }
 
 protected:
     RangeType m_range;
-    Flags m_permissions; // Uses lldb::Permissions enumeration values logical OR'ed together
+    OptionalBool m_read;
+    OptionalBool m_write;
+    OptionalBool m_execute;
 };
 
 //----------------------------------------------------------------------
@@ -2558,17 +2572,56 @@
         error.SetErrorString ("Process::GetMemoryRegionInfo() not supported");
         return error;
     }
-    
-    virtual uint32_t
-    GetLoadAddressPermissions (lldb::addr_t load_addr)
+
+    //------------------------------------------------------------------
+    /// Attempt to get the attributes for a region of memory in the process.
+    ///
+    /// It may be possible for the remote debug server to inspect attributes
+    /// for a region of memory in the process, such as whether there is a
+    /// valid page of memory at a given address or whether that page is 
+    /// readable/writable/executable by the process.
+    ///
+    /// @param[in] load_addr
+    ///     The address of interest in the process.
+    ///
+    /// @param[out] permissions
+    ///     If this call returns successfully, this bitmask will have
+    ///     its Permissions bits set to indicate whether the region is
+    ///     readable/writable/executable.  If this call fails, the
+    ///     bitmask values are undefined.
+    ///
+    /// @return
+    ///     Returns true if it was able to determine the attributes of the
+    ///     memory region.  False if not.
+    //------------------------------------------------------------------
+
+    virtual bool
+    GetLoadAddressPermissions (lldb::addr_t load_addr, uint32_t &permissions)
     {
         MemoryRegionInfo range_info;
+        permissions = 0;
         Error error (GetMemoryRegionInfo (load_addr, range_info));
-        if (error.Success())
-            return range_info.GetPermissions().Get();
-        return 0;
+        if (!error.Success())
+            return false;
+        if (range_info.GetReadable() == MemoryRegionInfo::eDontKnow 
+            || range_info.GetWritable() == MemoryRegionInfo::eDontKnow 
+            || range_info.GetExecutable() == MemoryRegionInfo::eDontKnow)
+        {
+            return false;
+        }
+
+        if (range_info.GetReadable() == MemoryRegionInfo::eYes)
+            permissions |= lldb::ePermissionsReadable;
+
+        if (range_info.GetWritable() == MemoryRegionInfo::eYes)
+            permissions |= lldb::ePermissionsWritable;
+
+        if (range_info.GetExecutable() == MemoryRegionInfo::eYes)
+            permissions |= lldb::ePermissionsExecutable;
+
+        return true;
     }
-                  
+
     //------------------------------------------------------------------
     /// Determines whether executing JIT-compiled code in this process 
     /// is possible.

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=146477&r1=146476&r2=146477&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Mon Dec 12 23:39:38 2011
@@ -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.

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=146477&r1=146476&r2=146477&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Mon Dec 12 23:39:38 2011
@@ -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
         {





More information about the lldb-commits mailing list