[Lldb-commits] [lldb] r166757 - in /lldb/trunk: include/lldb/Symbol/ source/Plugins/ABI/MacOSX-arm/ source/Plugins/ABI/MacOSX-i386/ source/Plugins/ABI/SysV-x86_64/ source/Plugins/Instruction/ARM/ source/Plugins/Process/Utility/ source/Plugins/UnwindAssembly/x86/ source/Symbol/

Jason Molenda jmolenda at apple.com
Thu Oct 25 23:08:59 PDT 2012


Author: jmolenda
Date: Fri Oct 26 01:08:58 2012
New Revision: 166757

URL: http://llvm.org/viewvc/llvm-project?rev=166757&view=rev
Log:
Add a new capability to RegisterContextLLDB:  To recognize when the
Full UnwindPlan is trying to do an impossible unwind; in that case
invalidate the Full UnwindPlan and replace it with the architecture
default unwind plan.

This is a scenario that happens occasionally with arm unwinds in
particular; the instruction analysis based full unwindplan can
mis-parse the functions and the stack walk stops prematurely.  Now
we can do a simpleminded frame-chain walk to find the caller frame
and continue the unwind.  It's not ideal but given the complicated
nature of analyzing the arm functions, and the lack of eh_frame
information on iOS, it is a distinct improvement and fixes some
long-standing problems with the unwinder on that platform.  

This is fixing <rdar://problem/12091421>.  I may re-use this
invalidate feature in the future if I can identify other cases where
the full unwindplan's unwind information is clearly incorrect.

This checkin also includes some cleanup for the volatile register
definition in the arm ABI plugin for <rdar://problem/10652166> 
although work remains to be done for that bug.


Modified:
    lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
    lldb/trunk/include/lldb/Symbol/UnwindPlan.h
    lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
    lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
    lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
    lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
    lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h
    lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
    lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp
    lldb/trunk/source/Symbol/FuncUnwinders.cpp
    lldb/trunk/source/Symbol/UnwindPlan.cpp

Modified: lldb/trunk/include/lldb/Symbol/FuncUnwinders.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/FuncUnwinders.h?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/FuncUnwinders.h (original)
+++ lldb/trunk/include/lldb/Symbol/FuncUnwinders.h Fri Oct 26 01:08:58 2012
@@ -70,6 +70,13 @@
         return m_range.ContainsFileAddress (addr);
     }
 
+    // When we're doing an unwind using the UnwindPlanAtNonCallSite and we find an
+    // impossible unwind condition, we know that the UnwindPlan is invalid.  Calling
+    // this method on the FuncUnwinder will tell it to replace that UnwindPlan with
+    // the architectural default UnwindPlan so hopefully our stack walk will get past
+    // this frame.
+    void
+    InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& Thread);
 
 private:
     UnwindTable& m_unwind_table;

Modified: lldb/trunk/include/lldb/Symbol/UnwindPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindPlan.h?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindPlan.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindPlan.h Fri Oct 26 01:08:58 2012
@@ -349,7 +349,9 @@
         m_plan_valid_address_range (), 
         m_register_kind (reg_kind), 
         m_return_addr_register (LLDB_INVALID_REGNUM),
-        m_source_name ()
+        m_source_name (),
+        m_plan_is_sourced_from_compiler (eLazyBoolCalculate),
+        m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate)
     {
     }
 
@@ -432,6 +434,36 @@
     void
     SetSourceName (const char *);
 
+    // Was this UnwindPlan emitted by a compiler?
+    lldb_private::LazyBool
+    GetSourcedFromCompiler () const
+    {
+        return m_plan_is_sourced_from_compiler;
+    }
+
+    // Was this UnwindPlan emitted by a compiler?
+    void
+    SetSourcedFromCompiler (lldb_private::LazyBool from_compiler)
+    {
+        m_plan_is_sourced_from_compiler = from_compiler;
+    }
+
+    // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
+    // e.g. for exception handling.
+    lldb_private::LazyBool
+    GetUnwindPlanValidAtAllInstructions () const
+    {
+        return m_plan_is_valid_at_all_instruction_locations;
+    }
+
+    // Is this UnwindPlan valid at all instructions?  If not, then it is assumed valid at call sites,
+    // e.g. for exception handling.
+    void
+    SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn)
+    {
+        m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
+    }
+
     int
     GetRowCount () const;
 
@@ -458,6 +490,8 @@
     uint32_t m_return_addr_register;      // The register that has the return address for the caller frame
                                           // e.g. the lr on arm
     lldb_private::ConstString m_source_name;  // for logging, where this UnwindPlan originated from
+    lldb_private::LazyBool m_plan_is_sourced_from_compiler;
+    lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
 }; // class UnwindPlan
 
 } // namespace lldb_private

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp Fri Oct 26 01:08:58 2012
@@ -628,6 +628,8 @@
     // All other registers are the same.
     
     unwind_plan.SetSourceName ("arm at-func-entry default");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
     return true;
 }
 
@@ -651,9 +653,30 @@
     
     unwind_plan.AppendRow (row);
     unwind_plan.SetSourceName ("arm-apple-ios default unwind plan");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+
     return true;
 }
 
+// ARMv7 on iOS general purpose reg rules:
+//    r0-r3 not preserved  (used for argument passing)
+//    r4-r6 preserved
+//    r7    preserved (frame pointer)
+//    r8    preserved
+//    r9    not preserved (usable as volatile scratch register with iOS 3.x and later)
+//    r10-r11 preserved
+//    r12   not presrved
+//    r13   preserved (stack pointer)
+//    r14   not preserved (link register)
+//    r15   preserved (pc)
+//    cpsr  not preserved (different rules for different bits)
+
+// ARMv7 on iOS floating point rules:
+//    d0-d7   not preserved   (aka s0-s15, q0-q3)
+//    d8-d15  preserved       (aka s16-s31, q4-q7)
+//    d16-d31 not preserved   (aka q8-q15)
+
 bool
 ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
 {
@@ -691,28 +714,28 @@
             switch (name[1])
             {
                 case '0': 
-                    return name[2] == '\0'; // d0
+                    return name[2] == '\0'; // d0 is volatile
 
                 case '1':
                     switch (name[2])
                     {
                     case '\0':
-                        return true; // d1;
+                        return true; // d1 is volatile
                     case '6':
                     case '7':
                     case '8':
                     case '9':
-                        return name[3] == '\0'; // d16 - d19
+                        return name[3] == '\0'; // d16 - d19 are volatile
                     default:
                         break;
                     }
                     break;
-                    
+
                 case '2':
                     switch (name[2])
                     {
                     case '\0':
-                        return true; // d2;
+                        return true; // d2 is volatile
                     case '0':
                     case '1':
                     case '2':
@@ -723,7 +746,7 @@
                     case '7':
                     case '8':
                     case '9':
-                        return name[3] == '\0'; // d20 - d29
+                        return name[3] == '\0'; // d20 - d29 are volatile
                     default:
                         break;
                     }
@@ -733,10 +756,62 @@
                     switch (name[2])
                     {
                     case '\0':
-                        return true; // d3;
+                        return true; // d3 is volatile
+                    case '0':
+                    case '1':
+                        return name[3] == '\0'; // d30 - d31 are volatile
+                    default:
+                        break;
+                    }
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                    return name[2] == '\0'; // d4 - d7 are volatile
+
+                default:
+                    break;
+            }
+        }
+        else if (name[0] == 's')
+        {
+            switch (name[1])
+            {
+                case '0': 
+                    return name[2] == '\0'; // s0 is volatile
+
+                case '1':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // s1 is volatile
                     case '0':
                     case '1':
-                        return name[3] == '\0'; // d30 - d31
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                        return name[3] == '\0'; // s10 - s15 are volatile
+                    default:
+                        break;
+                    }
+                    break;
+
+                case '2':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // s2 is volatile
+                    default:
+                        break;
+                    }
+                    break;
+
+                case '3':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // s3 is volatile
                     default:
                         break;
                     }
@@ -744,7 +819,9 @@
                 case '5':
                 case '6':
                 case '7':
-                    return name[2] == '\0'; // d4 - d7
+                case '8':
+                case '9':
+                    return name[2] == '\0'; // s4 - s9 are volatile
 
                 default:
                     break;

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp Fri Oct 26 01:08:58 2012
@@ -894,6 +894,7 @@
     row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
     unwind_plan.AppendRow (row);
     unwind_plan.SetSourceName ("i386 at-func-entry default");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
     return true;
 }
 
@@ -919,6 +920,8 @@
 
     unwind_plan.AppendRow (row);
     unwind_plan.SetSourceName ("i386 default unwind plan");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
     return true;
 }
 

Modified: lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp Fri Oct 26 01:08:58 2012
@@ -1088,6 +1088,7 @@
     row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
     unwind_plan.AppendRow (row);
     unwind_plan.SetSourceName ("x86_64 at-func-entry default");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
     return true;
 }
 
@@ -1139,6 +1140,8 @@
 
     unwind_plan.AppendRow (row);
     unwind_plan.SetSourceName ("x86_64 default unwind plan");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
     return true;
 }
 

Modified: lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp (original)
+++ lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp Fri Oct 26 01:08:58 2012
@@ -13613,9 +13613,7 @@
     // All other registers are the same.
     
     unwind_plan.SetSourceName ("EmulateInstructionARM");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
     return true;
 }
-
-
-
-                                           

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=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Fri Oct 26 01:08:58 2012
@@ -35,24 +35,24 @@
 using namespace lldb;
 using namespace lldb_private;
 
-RegisterContextLLDB::RegisterContextLLDB 
+RegisterContextLLDB::RegisterContextLLDB
 (
-    Thread& thread, 
+    Thread& thread,
     const SharedPtr &next_frame,
     SymbolContext& sym_ctx,
     uint32_t frame_number,
     UnwindLLDB& unwind_lldb
 ) :
-    RegisterContext (thread, frame_number), 
-    m_thread(thread), 
+    RegisterContext (thread, frame_number),
+    m_thread(thread),
     m_fast_unwind_plan_sp (),
     m_full_unwind_plan_sp (),
     m_all_registers_available(false),
     m_frame_type (-1),
     m_cfa (LLDB_INVALID_ADDRESS),
-    m_start_pc (), 
-    m_current_pc (), 
-    m_current_offset (0), 
+    m_start_pc (),
+    m_current_pc (),
+    m_current_offset (0),
     m_current_offset_backed_up_one (0),
     m_sym_ctx(sym_ctx),
     m_sym_ctx_valid (false),
@@ -73,8 +73,8 @@
     }
 
     // This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
-    if (IsFrameZero() 
-        || next_frame->m_frame_type == eSigtrampFrame 
+    if (IsFrameZero()
+        || next_frame->m_frame_type == eSigtrampFrame
         || next_frame->m_frame_type == eDebuggerFrame)
     {
         m_all_registers_available = true;
@@ -90,8 +90,6 @@
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();
 
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
     if (reg_ctx_sp.get() == NULL)
     {
         m_frame_type = eNotAValidFrame;
@@ -124,11 +122,7 @@
     ModuleSP pc_module_sp (m_current_pc.GetModule());
     if (!m_current_pc.IsValid() || !pc_module_sp)
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u using architectural default unwind method",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
+        UnwindLogMsg ("using architectural default unwind method");
     }
 
     // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
@@ -140,7 +134,7 @@
 
     AddressRange addr_range;
     m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
-    
+
     static ConstString g_sigtramp_name ("_sigtramp");
     if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == g_sigtramp_name) ||
         (m_sym_ctx.symbol   && m_sym_ctx.symbol->GetName()   == g_sigtramp_name))
@@ -182,8 +176,8 @@
     // We've set m_frame_type and m_sym_ctx before these calls.
 
     m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
-    m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); 
-    
+    m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
+
     UnwindPlan::RowSP active_row;
     int cfa_offset = 0;
     int row_register_kind = -1;
@@ -195,8 +189,7 @@
         {
             StreamString active_row_strm;
             active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
-            log->Printf("%*sFrame %u active row: %s",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+            UnwindLogMsg ("%s", active_row_strm.GetString().c_str());
         }
     }
 
@@ -206,7 +199,7 @@
         return;
     }
 
-    
+
     addr_t cfa_regval;
     if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
     {
@@ -220,23 +213,11 @@
 
     m_cfa = cfa_regval + cfa_offset;
 
-    if (log)
-    {
-        log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    m_cfa, cfa_regval, cfa_offset);
-    }
-    
-    if (log)
-    {
-        log->Printf("%*sThread %d Frame %u initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan", 
-                    m_frame_number < 100 ? m_frame_number : 100, "", 
-                    m_thread.GetIndexID(), 
-                    m_frame_number,
-                    (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), 
-                    (uint64_t) m_cfa,
-                    m_full_unwind_plan_sp->GetSourceName().GetCString());
-    }
+    UnwindLogMsg ("cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+    UnwindLogMsg ("initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan",
+            (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
+            (uint64_t) m_cfa,
+            m_full_unwind_plan_sp->GetSourceName().GetCString());
 }
 
 // Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the RegisterContextLLDB "below" it
@@ -246,13 +227,12 @@
 RegisterContextLLDB::InitializeNonZerothFrame()
 {
     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
     if (IsFrameZero ())
     {
         m_frame_type = eNotAValidFrame;
         return;
     }
-    
+
     if (!GetNextFrame().get() || !GetNextFrame()->IsValid())
     {
         m_frame_type = eNotAValidFrame;
@@ -267,27 +247,19 @@
     addr_t pc;
     if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not get pc value",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
+        UnwindLogMsg ("could not get pc value");
         m_frame_type = eNotAValidFrame;
         return;
     }
-    
+
     if (log)
     {
-        log->Printf("%*sFrame %u pc = 0x%16.16llx",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, pc);
+        UnwindLogMsg ("pc = 0x%16.16llx", pc);
         addr_t reg_val;
         if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
-            log->Printf("%*sFrame %u fp = 0x%16.16llx",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
-
+            UnwindLogMsg ("fp = 0x%16.16llx", reg_val);
         if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
-            log->Printf("%*sFrame %u sp = 0x%16.16llx",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val);
+            UnwindLogMsg ("sp = 0x%16.16llx", reg_val);
     }
 
     // A pc of 0x0 means it's the end of the stack crawl
@@ -296,11 +268,11 @@
         m_frame_type = eNotAValidFrame;
         return;
     }
-    
+
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     Process *process = exe_ctx.GetProcessPtr();
     // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
-    // this will strip bit zero in case we read a PC from memory or from the LR.   
+    // this will strip bit zero in case we read a PC from memory or from the LR.
     ABI *abi = process->GetABI().get();
     if (abi)
         pc = abi->FixCodeAddress(pc);
@@ -312,12 +284,8 @@
     ModuleSP pc_module_sp (m_current_pc.GetModule());
     if (!m_current_pc.IsValid() || !pc_module_sp)
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u using architectural default unwind method",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
-        
+        UnwindLogMsg ("using architectural default unwind method");
+
         // Test the pc value to see if we know it's in an unmapped/non-executable region of memory.
         uint32_t permissions;
         if (process->GetLoadAddressPermissions(pc, permissions)
@@ -329,11 +297,8 @@
             // pc and see if we can get any further.
             if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsFrameZero())
             {
-                if (log)
-                {
-                    log->Printf("%*sFrame %u had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, (uint64_t) pc);
-                }
+                UnwindLogMsg ("had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.",
+                         (uint64_t) pc);
                 m_frame_type = eSkipFrame;
             }
             else
@@ -365,11 +330,7 @@
                 int cfa_offset = row->GetCFAOffset();
                 if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
                 {
-                    if (log)
-                    {
-                        log->Printf("%*sFrame %u failed to get cfa value",
-                                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-                    }
+                    UnwindLogMsg ("failed to get cfa value");
                     if (m_frame_type != eSkipFrame)   // don't override eSkipFrame
                     {
                         m_frame_type = eNormalFrame;
@@ -381,11 +342,7 @@
                 // A couple of sanity checks..
                 if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
                 {
-                    if (log)
-                    {
-                        log->Printf("%*sFrame %u could not find a valid cfa address",
-                                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-                    }
+                    UnwindLogMsg ("could not find a valid cfa address");
                     m_frame_type = eNotAValidFrame;
                     return;
                 }
@@ -401,21 +358,12 @@
             }
             else
             {
-                if (log)
-                {
-                    log->Printf("%*sFrame %u could not find a row for function offset zero",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-                }
+                UnwindLogMsg ("could not find a row for function offset zero");
                 m_frame_type = eNotAValidFrame;
                 return;
             }
 
-            if (log)
-            {
-                log->Printf("%*sFrame %u initialized frame cfa is 0x%llx",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            (uint64_t) m_cfa);
-            }
+            UnwindLogMsg ("initialized frame cfa is 0x%llx", (uint64_t) m_cfa);
             return;
         }
         m_frame_type = eNotAValidFrame;
@@ -456,7 +404,7 @@
     // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
     // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
     // to the ABI plugin and consult that.
-    if (decr_pc_and_recompute_addr_range) 
+    if (decr_pc_and_recompute_addr_range)
     {
         Address temporary_pc(m_current_pc);
         temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
@@ -522,11 +470,10 @@
         {
             StreamString active_row_strm;
             active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
-            log->Printf("%*sFrame %u active row: %s",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+            UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
         }
     }
-    else 
+    else
     {
         m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
         if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
@@ -537,8 +484,7 @@
             {
                 StreamString active_row_strm;
                 active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
-                log->Printf("%*sFrame %u active row: %s",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str());
+                UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
             }
         }
     }
@@ -552,12 +498,7 @@
     addr_t cfa_regval;
     if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
     {
-        if (log)
-        {
-            log->Printf("%*sFrame %u failed to get cfa reg %d/%d",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        row_register_kind, active_row->GetCFARegister());
-        }
+        UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
         m_frame_type = eNotAValidFrame;
         return;
     }
@@ -565,21 +506,12 @@
 
     m_cfa = cfa_regval + cfa_offset;
 
-    if (log)
-    {
-        log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    m_cfa, cfa_regval, cfa_offset);
-    }
+    UnwindLogMsg ("cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
 
     // A couple of sanity checks..
     if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
-    { 
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not find a valid cfa address",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-        }
+    {
+        UnwindLogMsg ("could not find a valid cfa address");
         m_frame_type = eNotAValidFrame;
         return;
     }
@@ -606,22 +538,14 @@
         }
         if (repeating_frames && abi->FunctionCallsChangeCFA())
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u same CFA address as next frame, assuming the unwind is looping - stopping",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
-            }
+            UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
             m_frame_type = eNotAValidFrame;
             return;
         }
     }
 
-    if (log)
-    {
-        log->Printf("%*sFrame %u initialized frame current pc is 0x%llx cfa is 0x%llx", 
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
-    }
+    UnwindLogMsg ("initialized frame current pc is 0x%llx cfa is 0x%llx",
+            (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
 }
 
 
@@ -634,9 +558,9 @@
 
 // Find a fast unwind plan for this frame, if possible.
 //
-// On entry to this method, 
+// On entry to this method,
 //
-//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, 
+//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
 //   2. m_sym_ctx should already be filled in, and
 //   3. m_current_pc should have the current pc value for this frame
 //   4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -657,7 +581,7 @@
     if (!func_unwinders_sp)
         return unwind_plan_sp;
 
-    // If we're in _sigtramp(), unwinding past this frame requires special knowledge.  
+    // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
     if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
         return unwind_plan_sp;
 
@@ -669,16 +593,15 @@
             LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
             if (log && log->GetVerbose())
             {
-                const char *has_fast = "";
                 if (m_fast_unwind_plan_sp)
-                    has_fast = ", and has a fast UnwindPlan";
-                log->Printf("%*sFrame %u frame%s",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, has_fast);
+                    UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan");
+                else
+                    UnwindLogMsgVerbose ("frame");
             }
             m_frame_type = eNormalFrame;
             return unwind_plan_sp;
         }
-        else 
+        else
         {
             unwind_plan_sp.reset();
         }
@@ -686,9 +609,9 @@
     return unwind_plan_sp;
 }
 
-// On entry to this method, 
+// On entry to this method,
 //
-//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, 
+//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
 //   2. m_sym_ctx should already be filled in, and
 //   3. m_current_pc should have the current pc value for this frame
 //   4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -697,7 +620,6 @@
 RegisterContextLLDB::GetFullUnwindPlanForFrame ()
 {
     UnwindPlanSP unwind_plan_sp;
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     UnwindPlanSP arch_default_unwind_plan_sp;
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     Process *process = exe_ctx.GetProcessPtr();
@@ -709,12 +631,12 @@
     }
 
     bool behaves_like_zeroth_frame = false;
-    if (IsFrameZero () 
+    if (IsFrameZero ()
         || GetNextFrame()->m_frame_type == eSigtrampFrame
         || GetNextFrame()->m_frame_type == eDebuggerFrame)
     {
         behaves_like_zeroth_frame = true;
-        // If this frame behaves like a 0th frame (currently executing or 
+        // If this frame behaves like a 0th frame (currently executing or
         // interrupted asynchronously), all registers can be retrieved.
         m_all_registers_available = true;
     }
@@ -723,7 +645,7 @@
     // in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
     // 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.
-    // Note, if the symbol context has a function for the symbol, then we don't need to do this check. 
+    // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
 
     if ((!m_sym_ctx_valid  || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
     {
@@ -784,12 +706,8 @@
         unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
         if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
         {
-            if (log && log->GetVerbose())
-            {
-                log->Printf("%*sFrame %u frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            unwind_plan_sp->GetSourceName().GetCString());
-            }
+            UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
+                           unwind_plan_sp->GetSourceName().GetCString());
             return unwind_plan_sp;
         }
     }
@@ -800,12 +718,7 @@
         unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
         if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
         {
-            if (log && log->GetVerbose())
-            {
-                log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            unwind_plan_sp->GetSourceName().GetCString());
-            }
+            UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
             return unwind_plan_sp;
         }
     }
@@ -814,36 +727,21 @@
     unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
     if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
     {
-        if (log && log->GetVerbose())
-        {
-            log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        unwind_plan_sp->GetSourceName().GetCString());
-        }
+        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
         return unwind_plan_sp;
     }
-    
+
     // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
     // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
     unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
     if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
     {
-        if (log && log->GetVerbose())
-        {
-            log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        unwind_plan_sp->GetSourceName().GetCString());
-        }
+        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
         return unwind_plan_sp;
     }
 
     // If nothing else, use the architectural default UnwindPlan and hope that does the job.
-    if (log && log->GetVerbose())
-    {
-        log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    arch_default_unwind_plan_sp->GetSourceName().GetCString());
-    }
+    UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
     return arch_default_unwind_plan_sp;
 }
 
@@ -885,7 +783,7 @@
 }
 
 bool
-RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                                             const RegisterInfo *reg_info,
                                                             RegisterValue &value)
 {
@@ -898,11 +796,11 @@
     case UnwindLLDB::RegisterLocation::eRegisterInRegister:
         {
             const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
-            
+
             if (!other_reg_info)
                 return false;
-            
-            if (IsFrameZero ()) 
+
+            if (IsFrameZero ())
             {
                 success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value);
             }
@@ -915,7 +813,7 @@
     case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
         success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size);
         break;
-            
+
     case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
         break;
     case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
@@ -923,9 +821,9 @@
         break;
     case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
         {
-            Error error (ReadRegisterValueFromMemory(reg_info, 
-                                                     regloc.location.target_memory_location, 
-                                                     reg_info->byte_size, 
+            Error error (ReadRegisterValueFromMemory(reg_info,
+                                                     regloc.location.target_memory_location,
+                                                     reg_info->byte_size,
                                                      value));
             success = error.Success();
         }
@@ -938,7 +836,7 @@
 }
 
 bool
-RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                                            const RegisterInfo *reg_info,
                                                            const RegisterValue &value)
 {
@@ -946,13 +844,13 @@
         return false;
 
     bool success = false;
-    
+
     switch (regloc.type)
     {
         case UnwindLLDB::RegisterLocation::eRegisterInRegister:
             {
                 const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
-                if (IsFrameZero ()) 
+                if (IsFrameZero ())
                 {
                     success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value);
                 }
@@ -970,9 +868,9 @@
             break;
         case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
             {
-                Error error (WriteRegisterValueToMemory (reg_info, 
-                                                         regloc.location.target_memory_location, 
-                                                         reg_info->byte_size, 
+                Error error (WriteRegisterValueToMemory (reg_info,
+                                                         regloc.location.target_memory_location,
+                                                         reg_info->byte_size,
                                                          value));
                 success = error.Success();
             }
@@ -994,7 +892,7 @@
 // A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther
 // up the stack if we keep looking.  It's always the second frame in an unwind (i.e. the first frame after
 // frame zero) where unwinding can be the trickiest.  Ideally we'll mark up this frame in some way so the
-// user knows we're displaying bad data and we may have skipped one frame of their real program in the 
+// user knows we're displaying bad data and we may have skipped one frame of their real program in the
 // process of getting back on track.
 
 bool
@@ -1006,10 +904,8 @@
 // Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
 
 bool
-RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, bool check_next_frame)
+RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc)
 {
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
-
     // Have we already found this register location?
     if (!m_registers.empty())
     {
@@ -1022,11 +918,19 @@
         }
     }
 
+    static uint32_t sp_regnum = LLDB_INVALID_REGNUM;
+    static uint32_t pc_regnum = LLDB_INVALID_REGNUM;
+    static bool generic_registers_initialized = false;
+    if (!generic_registers_initialized)
+    {
+        m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum);
+        m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum);
+        generic_registers_initialized = true;
+    }
+
     // Are we looking for the CALLER's stack pointer?  The stack pointer is defined to be the same as THIS frame's
     // CFA so just return the CFA value.  This is true on x86-32/x86-64 at least.
-    uint32_t sp_regnum;
-    if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum)
-        && sp_regnum == lldb_regnum)
+    if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum)
     {
         // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
         assert (sizeof (addr_t) <= sizeof (uint64_t));
@@ -1036,12 +940,6 @@
         return true;
     }
 
-    uint32_t pc_regnum;
-    if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum))
-    {
-        pc_regnum = LLDB_INVALID_REGNUM;
-    }
-
     // Look through the available UnwindPlans for the register location.
 
     UnwindPlan::Row::RegisterLocation unwindplan_regloc;
@@ -1055,22 +953,13 @@
         uint32_t row_regnum;
         if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum, (int) unwindplan_registerkind);
-            }
+            UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+                    lldb_regnum, (int) unwindplan_registerkind);
             return false;
         }
         if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u supplying caller's saved reg %d's location using FastUnwindPlan",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum);
-            }
+            UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum);
             have_unwindplan_regloc = true;
         }
     }
@@ -1092,27 +981,18 @@
             if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
             {
                row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister();
-               if (log)
-               {
-                   log->Printf("%*sFrame %u requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
-                               m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, row_regnum);
-               }
+               UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
+                       row_regnum);
             }
             else
             {
                 if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
                 {
-                    if (log)
-                    {
-                        if (unwindplan_registerkind == eRegisterKindGeneric)
-                            log->Printf("%*sFrame %u could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme",
-                                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                        lldb_regnum);
-                        else
-                            log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
-                                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                        lldb_regnum, (int) unwindplan_registerkind);
-                    }
+                    if (unwindplan_registerkind == eRegisterKindGeneric)
+                        UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum);
+                    else
+                        UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+                                lldb_regnum, (int) unwindplan_registerkind);
                     return false;
                 }
             }
@@ -1120,22 +1000,62 @@
             if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
             {
                 have_unwindplan_regloc = true;
-                if (log)
-                {                
-                    log->Printf("%*sFrame %u supplying caller's saved reg %d's location using %s UnwindPlan",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                lldb_regnum, m_full_unwind_plan_sp->GetSourceName().GetCString());
+                UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum,
+                              m_full_unwind_plan_sp->GetSourceName().GetCString());
+            }
+
+            // If this architecture stores the return address in a register (it defines a Return Address register)
+            // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the
+            // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this
+            // is an impossible situation and the instruction emulation code has likely been misled.  
+            // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the 
+            // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so
+            // the stack walk can get past this point.
+
+            // Special note:  If the Full UnwindPlan was generated from the compiler, don't second-guess it 
+            // when we're at a call site location.
+
+            // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering
+            uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM; 
+            if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum)
+                && arch_default_ra_regnum != LLDB_INVALID_REGNUM
+                && pc_regnum != LLDB_INVALID_REGNUM
+                && pc_regnum == lldb_regnum
+                && unwindplan_regloc.IsInOtherRegister()
+                && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum
+                && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes
+                && !m_all_registers_available)
+            {
+                UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame",
+                              m_full_unwind_plan_sp->GetSourceName().GetCString());
+
+                // Throw away the full unwindplan; install the arch default unwindplan
+                InvalidateFullUnwindPlan();
+
+                // Now re-fetch the pc value we're searching for
+                uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM;
+                UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+                if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg)
+                    && arch_default_pc_reg != LLDB_INVALID_REGNUM
+                    && active_row
+                    && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc))
+                {
+                    have_unwindplan_regloc = true;
+                }
+                else
+                {
+                    have_unwindplan_regloc = false;
                 }
             }
         }
     }
-    
-    
+
+
     ExecutionContext exe_ctx(m_thread.shared_from_this());
     Process *process = exe_ctx.GetProcessPtr();
     if (have_unwindplan_regloc == false)
     {
-        // If a volatile register is being requested, we don't want to forward the next frame's register contents 
+        // If a volatile register is being requested, we don't want to forward the next frame's register contents
         // up the stack -- the register is not retrievable at this frame.
         ABI *abi = process ? process->GetABI().get() : NULL;
         if (abi)
@@ -1143,14 +1063,9 @@
             const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
             if (reg_info && abi->RegisterIsVolatile (reg_info))
             {
-                if (log && log->GetVerbose ())
-                {
-                    log->Printf("%*sFrame %u did not supply reg location for %d because it is volatile",
-                                m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                                lldb_regnum);
-                }
+                UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
                 return false;
-            }  
+            }
         }
 
         if (IsFrameZero ())
@@ -1164,16 +1079,7 @@
             return true;
         }
         else
-        {
-            if (check_next_frame)
-                return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
-        }
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
+        UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
         return false;
     }
 
@@ -1183,12 +1089,7 @@
         lldb_private::UnwindLLDB::RegisterLocation new_regloc;
         new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
         m_registers[lldb_regnum] = new_regloc;
-        if (log)
-        {
-            log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
+        UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
         return false;
     }
 
@@ -1196,20 +1097,12 @@
     {
         if (IsFrameZero ())
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum);
-            }
+            UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
             return false;
         }
         else
         {
-            if (check_next_frame)
-                return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1);
-            else
-                return false;
+            return false;
         }
     }
 
@@ -1237,12 +1130,7 @@
         uint32_t row_regnum_in_lldb;
         if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
         {
-            if (log)
-            {
-                log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                            m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                            lldb_regnum);
-            }
+            UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
             return false;
         }
         regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
@@ -1253,8 +1141,8 @@
 
     if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
     {
-        DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(), 
-                                 unwindplan_regloc.GetDWARFExpressionLength(), 
+        DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
+                                 unwindplan_regloc.GetDWARFExpressionLength(),
                                  process->GetByteOrder(), process->GetAddressByteSize());
         DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
         dwarfexpr.SetRegisterKind (unwindplan_registerkind);
@@ -1279,28 +1167,69 @@
                return true;
             }
         }
-        if (log)
-        {
-            log->Printf("%*sFrame %u tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
+        UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
         return false;
     }
 
-    if (log)
-    {
-        log->Printf("%*sFrame %u could not supply caller's reg %d location",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    lldb_regnum);
-    }
+    UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+
+    // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
 
-    
-    // assert ("UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.");
     return false;
 }
 
-// Retrieve a general purpose register value for THIS from, as saved by the NEXT frame, i.e. the frame that
+// If the Full unwindplan has been determined to be incorrect, this method will
+// replace it with the architecture's default unwindplna, if one is defined.
+// It will also find the FuncUnwinders object for this function and replace the
+// Full unwind method for the function there so we don't use the errant Full unwindplan
+// again in the future of this debug session.
+// We're most likely doing this because the Full unwindplan was generated by assembly
+// instruction profiling and the profiler got something wrong.
+
+void
+RegisterContextLLDB::InvalidateFullUnwindPlan ()
+{
+    UnwindPlan::Row::RegisterLocation unwindplan_regloc;
+    ExecutionContext exe_ctx (m_thread.shared_from_this());
+    Process *process = exe_ctx.GetProcessPtr();
+    ABI *abi = process ? process->GetABI().get() : NULL;
+    if (abi)
+    {
+        UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+        UnwindPlanSP arch_default_unwind_plan_sp;
+        arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+        abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
+        if (arch_default_unwind_plan_sp)
+        {
+            UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+        
+            if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
+            {
+                FuncUnwindersSP func_unwinders_sp;
+                if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule())
+                {
+                    func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+                    if (func_unwinders_sp)
+                    {
+                        func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread);
+                    }
+                }
+                m_registers.clear();
+                m_full_unwind_plan_sp = arch_default_unwind_plan_sp;
+                addr_t cfa_regval;
+                if (ReadGPRValue (arch_default_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
+                {
+                    m_cfa = cfa_regval + active_row->GetCFAOffset ();
+                }
+
+                UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.",
+                              original_full_unwind_plan_sp->GetSourceName().GetCString(), arch_default_unwind_plan_sp->GetSourceName().GetCString());
+            }
+        }
+    }
+}
+
+// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
 // this frame called.  e.g.
 //
 //  foo () { }
@@ -1343,8 +1272,21 @@
         return false;
     }
 
+    bool pc_or_return_address = false;
+    uint32_t generic_regnum;
+    if (register_kind == eRegisterKindGeneric
+        && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA))
+    {
+        pc_or_return_address = true;
+    }
+    else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum)
+             && (generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_RA))
+    {
+        pc_or_return_address = true;
+    }
+
     lldb_private::UnwindLLDB::RegisterLocation regloc;
-    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_or_return_address))
     {
         return false;
     }
@@ -1361,33 +1303,22 @@
 bool
 RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
 {
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     if (!IsValid())
         return false;
 
     const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
-    if (log && log->GetVerbose ())
-    {
-        log->Printf("%*sFrame %u looking for register saved location for reg %d",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    lldb_regnum);
-    }
+    UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
 
     // If this is the 0th frame, hand this over to the live register context
     if (IsFrameZero ())
     {
-        if (log && log->GetVerbose ())
-        {
-            log->Printf("%*sFrame %u passing along to the live register context for reg %d",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
+        UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
         return m_thread.GetRegisterContext()->ReadRegister (reg_info, value);
     }
 
     lldb_private::UnwindLLDB::RegisterLocation regloc;
     // Find out where the NEXT frame saved THIS frame's register contents
-    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
         return false;
 
     return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value);
@@ -1396,33 +1327,22 @@
 bool
 RegisterContextLLDB::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value)
 {
-    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
     if (!IsValid())
         return false;
 
     const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
-    if (log && log->GetVerbose ())
-    {
-        log->Printf("%*sFrame %u looking for register saved location for reg %d",
-                    m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                    lldb_regnum);
-    }
+    UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
 
     // If this is the 0th frame, hand this over to the live register context
     if (IsFrameZero ())
     {
-        if (log && log->GetVerbose ())
-        {
-            log->Printf("%*sFrame %u passing along to the live register context for reg %d",
-                        m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
-                        lldb_regnum);
-        }
+        UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
         return m_thread.GetRegisterContext()->WriteRegister (reg_info, value);
     }
 
     lldb_private::UnwindLLDB::RegisterLocation regloc;
     // Find out where the NEXT frame saved THIS frame's register contents
-    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1))
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
         return false;
 
     return WriteRegisterValueToRegisterLocation (regloc, reg_info, value);
@@ -1486,7 +1406,7 @@
 
     if (!m_start_pc.IsValid())
     {
-        return ReadPC (start_pc); 
+        return ReadPC (start_pc);
     }
     start_pc = m_start_pc.GetLoadAddress (CalculateTarget().get());
     return true;
@@ -1507,12 +1427,12 @@
         // occur if code has jumped through a NULL pointer -- we want to be able to unwind past that frame to help
         // find the bug.
 
-        if (m_all_registers_available == false 
+        if (m_all_registers_available == false
             && (pc == 0 || pc == 1))
         {
             return false;
         }
-        else 
+        else
         {
             return true;
         }
@@ -1522,3 +1442,57 @@
         return false;
     }
 }
+
+
+void
+RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...)
+{
+    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (log)
+    {
+        va_list args;
+        va_start (args, fmt);
+
+        char *logmsg;
+        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+        {
+            if (logmsg)
+                free (logmsg);
+            va_end (args);
+            return;
+        }
+        va_end (args);
+
+        log->Printf ("%*sth%d/fr%u %s",
+                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+                      logmsg);
+        free (logmsg);
+    }
+}
+
+void
+RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
+{
+    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (log && log->GetVerbose())
+    {
+        va_list args;
+        va_start (args, fmt);
+
+        char *logmsg;
+        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+        {
+            if (logmsg)
+                free (logmsg);
+            va_end (args);
+            return;
+        }
+        va_end (args);
+
+        log->Printf ("%*sth%d/fr%u %s",
+                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+                      logmsg);
+        free (logmsg);
+    }
+}
+

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h Fri Oct 26 01:08:58 2012
@@ -59,7 +59,7 @@
 
     virtual bool
     WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
-    
+
     virtual bool
     ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
 
@@ -96,14 +96,14 @@
     friend class UnwindLLDB;
 
     // Indicates whether this frame is frame zero -- the currently
-    // executing frame -- or not.  
+    // executing frame -- or not.
     bool
     IsFrameZero () const;
 
-    void 
+    void
     InitializeZerothFrame ();
 
-    void 
+    void
     InitializeNonZerothFrame();
 
     SharedPtr
@@ -112,7 +112,7 @@
     SharedPtr
     GetPrevFrame () const;
 
-    // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1.  
+    // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1.
     // There is a good chance we'll get back on track if we follow the frame pointer chain (or whatever is appropriate
     // on this ABI) so we allow one invalid frame to be in the stack.  Ideally we'll mark this frame specially at some
     // point and indicate to the user that the unwinder had a hiccup.  Often when this happens we will miss a frame of
@@ -124,32 +124,30 @@
     // Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
     // function didn't modify/use.
     //
-    // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register 
+    // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register
     // being queried mid-stack.  Instead of floating frame 0's contents of that register up the stack (which may
     // or may not be the value of that reg when the function was executing), we won't return any value.
     //
     // If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested
     // stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same
     // as the requesting frame's.
-    //
-    // NB this function takes a "check_next_frame" boolean which indicates whether it should call back to the
-    // containing UnwindLLDB object to iterate the search down the stack (true) or if this call should look for
-    // a register save for that reg in the current frame only (false).  Allows UnwindLLDB to iterate through the
-    // RegisterContextLLDB's instead of using recursion to find saved register values.
     bool
-    SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, bool check_next_frame);
+    SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc);
 
     bool
-    ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+    ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                            const lldb_private::RegisterInfo *reg_info,
                                            lldb_private::RegisterValue &value);
 
     bool
-    WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, 
+    WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
                                           const lldb_private::RegisterInfo *reg_info,
                                           const lldb_private::RegisterValue &value);
 
-    // Get the contents of a general purpose (address-size) register for this frame 
+    void
+    InvalidateFullUnwindPlan ();
+
+    // Get the contents of a general purpose (address-size) register for this frame
     // (usually retrieved from the next frame)
     bool
     ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);
@@ -160,8 +158,14 @@
     lldb::UnwindPlanSP
     GetFullUnwindPlanForFrame ();
 
+    void
+    UnwindLogMsg (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+    void
+    UnwindLogMsgVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
     lldb_private::Thread& m_thread;
-    
+
     ///
     // The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above)
     // i.e. where THIS frame saved them
@@ -182,7 +186,7 @@
     int m_current_offset_backed_up_one;           // how far into the function we've executed; -1 if unknown
                                                   // 0 if no instructions have been executed yet.
                                                   // On architectures where the return address on the stack points
-                                                  // to the instruction after the CALL, this value will have 1 
+                                                  // to the instruction after the CALL, this value will have 1
                                                   // subtracted from it.  Else a function that ends in a CALL will
                                                   // have an offset pointing into the next function's address range.
                                                   // m_current_pc has the actual address of the "current" pc.

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=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp Fri Oct 26 01:08:58 2012
@@ -262,14 +262,24 @@
 }
 
 bool
-UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num)
+UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_or_return_address_reg)
 {
     int64_t frame_num = starting_frame_num;
     if (frame_num >= m_frames.size())
         return false;
+
+    // Never interrogate more than one level while looking for the saved pc value.  If the value
+    // isn't saved by frame_num, none of the frames lower on the stack will have a useful value.
+    if (pc_or_return_address_reg)
+    {
+        if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc))
+          return true;
+        else
+          return false;
+    }
     while (frame_num >= 0)
     {
-        if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc, false))
+        if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc))
             return true;
         frame_num--;
     }

Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h Fri Oct 26 01:08:58 2012
@@ -80,7 +80,7 @@
     // Iterate over the RegisterContextLLDB's in our m_frames vector, look for the first one that
     // has a saved location for this reg.
     bool
-    SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num);
+    SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_or_return_address_reg);
 
 
 private:

Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp Fri Oct 26 01:08:58 2012
@@ -738,6 +738,8 @@
     }
     
     unwind_plan.SetSourceName ("assembly insn profiling");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
 
     return true;
 }
@@ -822,6 +824,9 @@
     row.reset(newrow);
 
     unwind_plan.SetPlanValidAddressRange (func);
+    unwind_plan.SetSourceName ("fast unwind assembly profiling");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
     return true;
 }
 

Modified: lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp (original)
+++ lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp Fri Oct 26 01:08:58 2012
@@ -371,11 +371,18 @@
     {
         unwind_plan.SetSourceName ("eh_frame CFI");
         cie_offset = current_entry + 4 - cie_offset;
+        unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
     }
     else
     {
         unwind_plan.SetSourceName ("DWARF CFI");
+        // In theory the debug_frame info should be valid at all call sites
+        // ("asynchronous unwind info" as it is sometimes called) but in practice
+        // gcc et al all emit call frame info for the prologue and call sites, but
+        // not for the epilogue or all the other locations during the function reliably.
+        unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
     }
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
 
     const CIE *cie = GetCIE (cie_offset);
     assert (cie != NULL);

Modified: lldb/trunk/source/Symbol/FuncUnwinders.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/FuncUnwinders.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/FuncUnwinders.cpp (original)
+++ lldb/trunk/source/Symbol/FuncUnwinders.cpp Fri Oct 26 01:08:58 2012
@@ -236,3 +236,12 @@
     return m_range.GetBaseAddress();
 }
 
+void
+FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread)
+{
+    UnwindPlanSP arch_default = GetUnwindPlanArchitectureDefault (thread);
+    if (arch_default && m_tried_unwind_at_call_site)
+    {
+        m_unwind_plan_call_site_sp = arch_default;
+    }
+}

Modified: lldb/trunk/source/Symbol/UnwindPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindPlan.cpp?rev=166757&r1=166756&r2=166757&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindPlan.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindPlan.cpp Fri Oct 26 01:08:58 2012
@@ -153,7 +153,7 @@
 UnwindPlan::Row::Clear ()
 {
     m_offset = 0;
-    m_cfa_reg_num = 0;
+    m_cfa_reg_num = LLDB_INVALID_REGNUM;
     m_cfa_offset = 0;
     m_register_locations.clear();
 }
@@ -189,7 +189,7 @@
 
 UnwindPlan::Row::Row() :
     m_offset(0),
-    m_cfa_reg_num(0),
+    m_cfa_reg_num(LLDB_INVALID_REGNUM),
     m_cfa_offset(0),
     m_register_locations()
 {





More information about the lldb-commits mailing list