[Lldb-commits] [lldb] r222601 - When a RegisterContext produces an invalid CFA address, change

Jason Molenda jmolenda at apple.com
Fri Nov 21 17:52:03 PST 2014


Author: jmolenda
Date: Fri Nov 21 19:52:03 2014
New Revision: 222601

URL: http://llvm.org/viewvc/llvm-project?rev=222601&view=rev
Log:
When a RegisterContext produces an invalid CFA address, change
UnwindLLDB::AddOneMoreFrame to try the fallback unwind plan on
that same stack frame before it tries the fallback unwind plan
on the "next" or callee frame.

In RegisterContextLLDB::TryFallbackUnwindPlan, when we're
trying the fallback unwind plan to see if it is valid, make
sure we change all of the object ivars that might be used in
the process of fetching the CFA & caller's saved pc value 
and restore those if we decide not to use the fallback 
unwindplan.

<rdar://problem/19035079> 

Modified:
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp

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=222601&r1=222600&r2=222601&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Fri Nov 21 19:52:03 2014
@@ -1528,7 +1528,17 @@ RegisterContextLLDB::TryFallbackUnwindPl
     if (m_fallback_unwind_plan_sp.get() == nullptr)
         return true;
 
+
+    // Switch the full UnwindPlan to be the fallback UnwindPlan.  If we decide this isn't
+    // working, we need to restore.
+    // We'll also need to save & restore the value of the m_cfa ivar.  Save is down below a bit in 'old_cfa'.
     UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+    addr_t old_cfa = m_cfa;
+
+    m_registers.clear();
+
+    m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
+
     UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
     
     if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
@@ -1539,11 +1549,12 @@ RegisterContextLLDB::TryFallbackUnwindPl
         {
             UnwindLogMsg ("failed to get cfa with fallback unwindplan");
             m_fallback_unwind_plan_sp.reset();
+            m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+            m_cfa = old_cfa;
             return false;
         }
+        m_cfa = new_cfa;
 
-        m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
-        m_registers.clear();
         if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound)
         {
             const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB));
@@ -1557,12 +1568,13 @@ RegisterContextLLDB::TryFallbackUnwindPl
             }
         }
 
-        m_full_unwind_plan_sp = original_full_unwind_plan_sp;
 
         if (new_caller_pc_value == LLDB_INVALID_ADDRESS)
         {
             UnwindLogMsg ("failed to get a pc value for the caller frame with the fallback unwind plan");
             m_fallback_unwind_plan_sp.reset();
+            m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+            m_cfa = old_cfa;
             return false;
         }
 
@@ -1572,14 +1584,12 @@ RegisterContextLLDB::TryFallbackUnwindPl
             {
                 UnwindLogMsg ("fallback unwind plan got the same values for this frame CFA and caller frame pc, not using");
                 m_fallback_unwind_plan_sp.reset();
+                m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+                m_cfa = old_cfa;
                 return false;
             }
         }
 
-        m_registers.clear();
-        m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
-        m_cfa = new_cfa;
-
         UnwindLogMsg ("trying to unwind from this function with the UnwindPlan '%s' because UnwindPlan '%s' failed.", 
                       m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
                       original_full_unwind_plan_sp->GetSourceName().GetCString());

Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp?rev=222601&r1=222600&r2=222601&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp Fri Nov 21 19:52:03 2014
@@ -208,18 +208,35 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
         // these.
         if (reg_ctx_sp->IsTrapHandlerFrame() == false)
         {
-            // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
-            // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.
-            if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+            // See if we can find a fallback unwind plan for THIS frame.  It may be
+            // that the UnwindPlan we're using for THIS frame was bad and gave us a
+            // bad CFA.  
+            // If that's not it, then see if we can change the UnwindPlan for the frame
+            // below us ("NEXT") -- see if using that other UnwindPlan gets us a better
+            // unwind state.
+            if (reg_ctx_sp->TryFallbackUnwindPlan() == false
+                || reg_ctx_sp->GetCFA (cursor_sp->cfa) == false
+                || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)
             {
-                return AddOneMoreFrame (abi);
+                if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+                {
+                    return AddOneMoreFrame (abi);
+                }
+                if (log)
+                {
+                    log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
+                                cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+                }
+                goto unwind_done;
             }
-            if (log)
+            else
             {
-                log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
-                            cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+                if (log)
+                {
+                    log->Printf("%*sFrame %d had a bad CFA value but we switched the UnwindPlan being used and got one that looks more realistic.",
+                                cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+                }
             }
-            goto unwind_done;
         }
     }
     if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc))





More information about the lldb-commits mailing list