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))


_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to