Handle the case where no eh_frame section is present.

RegisterContextLLDB holds a reference to the SymbolContext
in the vector of Cursors that UnwindLLDB maintains.  Switch
UnwindLLDB to hold a vector of shared pointers of Cursors
so this reference doesn't become invalid.

Correctly falling back from the "fast" UnwindPlan to the
"full" UnwindPlan when additional registers need to be
retrieved.

llvm-svn: 118218
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index d0b4eca..5b7ea72 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -33,9 +33,13 @@
                                           int frame_number) :
     RegisterContext (thread), m_thread(thread), m_next_frame(next_frame), 
     m_sym_ctx(sym_ctx), m_all_registers_available(false), m_registers(),
-    m_cfa (LLDB_INVALID_ADDRESS), m_start_pc (), m_current_pc (), m_frame_number (frame_number)
+    m_cfa (LLDB_INVALID_ADDRESS), m_start_pc (), m_current_pc (), m_frame_number (frame_number),
+    m_full_unwind_plan(NULL), m_fast_unwind_plan(NULL)
 {
+    m_sym_ctx.Clear();
+    m_sym_ctx_valid = false;
     m_base_reg_ctx = m_thread.GetRegisterContext();
+
     if (IsFrameZero ())
     {
         InitializeZerothFrame ();
@@ -77,13 +81,11 @@
         m_frame_type = eNotAValidFrame;
         return;
     }
-    m_sym_ctx = frame_sp->GetSymbolContext (eSymbolContextEverything);
-    const AddressRange *addr_range_ptr;
-    if (m_sym_ctx.function)
-        addr_range_ptr = &m_sym_ctx.function->GetAddressRange();
-    else if (m_sym_ctx.symbol)
-        addr_range_ptr = m_sym_ctx.symbol->GetAddressRangePtr();
-
+    m_sym_ctx = frame_sp->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol);
+    m_sym_ctx_valid = true;
+    AddressRange addr_range;
+    m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, addr_range);
+    
     m_current_pc = frame_sp->GetFrameCodeAddress();
 
     static ConstString sigtramp_name ("_sigtramp");
@@ -98,11 +100,11 @@
         m_frame_type = eNormalFrame;
     }
 
-    // If we were able to find a symbol/function, set addr_range_ptr to the bounds of that symbol/function.
+    // If we were able to find a symbol/function, set addr_range to the bounds of that symbol/function.
     // else treat the current pc value as the start_pc and record no offset.
-    if (addr_range_ptr)
+    if (addr_range.GetBaseAddress().IsValid())
     {
-        m_start_pc = addr_range_ptr->GetBaseAddress();
+        m_start_pc = addr_range.GetBaseAddress();
         m_current_offset = frame_sp->GetFrameCodeAddress().GetOffset() - m_start_pc.GetOffset();
     }
     else
@@ -261,14 +263,17 @@
         return;
     }
 
-    // set up our m_sym_ctx SymbolContext
-    m_current_pc.GetModule()->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction | eSymbolContextSymbol, m_sym_ctx);
+    // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
+    if ((m_current_pc.GetModule()->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+    {
+        m_sym_ctx_valid = true;
+    }
 
-    const AddressRange *addr_range_ptr;
-    if (m_sym_ctx.function)
-        addr_range_ptr = &m_sym_ctx.function->GetAddressRange();
-    else if (m_sym_ctx.symbol)
-        addr_range_ptr = m_sym_ctx.symbol->GetAddressRangePtr();
+    AddressRange addr_range;
+    if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, addr_range))
+    {
+        m_sym_ctx_valid = false;
+    }
 
     static ConstString sigtramp_name ("_sigtramp");
     if ((m_sym_ctx.function && m_sym_ctx.function->GetMangled().GetMangledName() == sigtramp_name)
@@ -284,9 +289,9 @@
 
     // If we were able to find a symbol/function, set addr_range_ptr to the bounds of that symbol/function.
     // else treat the current pc value as the start_pc and record no offset.
-    if (addr_range_ptr)
+    if (addr_range.GetBaseAddress().IsValid())
     {
-        m_start_pc = addr_range_ptr->GetBaseAddress();
+        m_start_pc = addr_range.GetBaseAddress();
         m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
     }
     else
@@ -458,6 +463,9 @@
     {
         behaves_like_zeroth_frame = true;
     }
+
+    // If this frame behaves like a 0th frame (currently executing or interrupted asynchronously), all registers
+    // can be retrieved.
     if (behaves_like_zeroth_frame)
     {
         m_all_registers_available = true;
@@ -471,7 +479,10 @@
     }
 
     FuncUnwindersSP fu;
-    fu = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+    if (m_sym_ctx_valid)
+    {
+        fu = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+    }
 
     // No FuncUnwinders available for this pc, try using architectural default unwind.
     if (fu.get() == NULL)
@@ -718,9 +729,9 @@
         {
             if (log)
             {
-                log->Printf("%*sFrame %d could not supply caller's reg %d location",
+                log->Printf("%*sFrame %d 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);
+                            lldb_regnum, (int) unwindplan_registerkind);
             }
             return false;
         }
@@ -735,9 +746,10 @@
             have_unwindplan_regloc = true;
         }
     }
-    else
+
+    if (!have_unwindplan_regloc)
     {
-        // m_full_unwind_plan being NULL probably means that we haven't tried to find a full UnwindPlan yet
+        // m_full_unwind_plan being NULL means that we haven't tried to find a full UnwindPlan yet
         if (m_full_unwind_plan == NULL)
         {
             m_full_unwind_plan = GetFullUnwindPlanForFrame ();
@@ -751,9 +763,9 @@
             {
                 if (log)
                 {
-                    log->Printf("%*sFrame %d could not supply caller's reg %d location",
+                    log->Printf("%*sFrame %d 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);
+                                lldb_regnum, (int) unwindplan_registerkind);
                 }
                 return false;
             }
@@ -770,6 +782,7 @@
             }
         }
     }
+
     if (have_unwindplan_regloc == false)
     {
         // If a volatile register is being requested, we don't want to forward m_next_frame's register contents 
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
index d0611061..9acad0f 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -163,14 +163,15 @@
     // i.e. where THIS frame saved them
     ///
 
-    lldb_private::UnwindPlan *m_fast_unwind_plan;    // may be NULL
+    lldb_private::UnwindPlan *m_fast_unwind_plan;  // may be NULL
     lldb_private::UnwindPlan *m_full_unwind_plan;
-    bool m_all_registers_available;                  // Can we retrieve all regs or just nonvolatile regs?
-    int m_frame_type;                                // enum FrameType
-    int m_current_offset;                            // how far into the function we've executed; -1 if unknown
+    bool m_all_registers_available;               // Can we retrieve all regs or just nonvolatile regs?
+    int m_frame_type;                             // enum FrameType
+    int m_current_offset;                         // how far into the function we've executed; -1 if unknown
     lldb_private::SymbolContext& m_sym_ctx;
+    bool m_sym_ctx_valid;                         // if ResolveSymbolContextForAddress fails, don't try to use m_sym_ctx
 
-    int m_frame_number;                              // What stack frame level this frame is - used for debug logging
+    int m_frame_number;                           // What stack frame level this frame is - used for debug logging
 
     lldb::addr_t m_cfa;
     lldb_private::Address m_start_pc;
diff --git a/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp b/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp
index 58b2ee0..e0f99d9 100644
--- a/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp
+++ b/lldb/source/Plugins/Process/Utility/UnwindAssemblyProfiler-x86.cpp
@@ -478,6 +478,10 @@
 AssemblyParse_x86::instruction_length (Address addr, int &length)
 {
     const char *triple;
+
+    if (!addr.IsValid())
+        return false;
+
     // FIXME should probably pass down the ArchSpec and work from that to make a portable triple
     if (m_cpu == k_i386)
         triple = "i386-unknown-unknown";
@@ -512,11 +516,16 @@
     UnwindPlan up;
     UnwindPlan::Row row;
     int non_prologue_insn_count = 0;
-    Address m_cur_insn = m_func_bounds.GetBaseAddress ();
+    m_cur_insn = m_func_bounds.GetBaseAddress ();
     int current_func_text_offset = 0;
     int current_sp_bytes_offset_from_cfa = 0;
     UnwindPlan::Row::RegisterLocation regloc;
 
+    if (!m_cur_insn.IsValid())
+    {
+        return false;
+    }
+
     unwind_plan.SetPlanValidAddressRange (m_func_bounds);
     unwind_plan.SetRegisterKind (eRegisterKindLLDB);
 
@@ -725,6 +734,11 @@
 AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
 {
     m_cur_insn = m_func_bounds.GetBaseAddress ();
+    if (!m_cur_insn.IsValid())
+    {
+        return false;
+    }
+
     while (m_func_bounds.ContainsFileAddress (m_cur_insn))
     {
         Error error;
diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
index d7d0a10..9fdd05d 100644
--- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -35,20 +35,20 @@
     if (m_frames.empty())
     {
         // First, set up the 0th (initial) frame
-        Cursor first_cursor;
+        CursorSP first_cursor_sp(new Cursor);
         RegisterContextSP no_frame; // an empty shared pointer
-        RegisterContextLLDB *first_register_ctx = new RegisterContextLLDB(m_thread, no_frame, first_cursor.sctx, 0);
+        RegisterContextLLDB *first_register_ctx = new RegisterContextLLDB(m_thread, no_frame, first_cursor_sp->sctx, 0);
         if (!first_register_ctx->IsValid())
         {
             delete first_register_ctx;
             return 0;
         }
-        if (!first_register_ctx->GetCFA (first_cursor.cfa))
+        if (!first_register_ctx->GetCFA (first_cursor_sp->cfa))
         {
             delete first_register_ctx;
             return 0;
         }
-        if (!first_register_ctx->GetPC (first_cursor.start_pc))
+        if (!first_register_ctx->GetPC (first_cursor_sp->start_pc))
         {
             delete first_register_ctx;
             return 0;
@@ -56,16 +56,16 @@
         // Reuse the StackFrame provided by the processor native machine context for the first frame
         first_register_ctx->SetStackFrame (m_thread.GetStackFrameAtIndex(0).get());
         RegisterContextSP temp_rcs(first_register_ctx);
-        first_cursor.reg_ctx = temp_rcs;
-        m_frames.push_back (first_cursor);
+        first_cursor_sp->reg_ctx = temp_rcs;
+        m_frames.push_back (first_cursor_sp);
 
         // Now walk up the rest of the stack
         while (1)
         {
-            Cursor cursor;
+            CursorSP cursor_sp(new Cursor);
             RegisterContextLLDB *register_ctx;
             int cur_idx = m_frames.size ();
-            register_ctx = new RegisterContextLLDB (m_thread, m_frames[cur_idx - 1].reg_ctx, cursor.sctx, cur_idx);
+            register_ctx = new RegisterContextLLDB (m_thread, m_frames[cur_idx - 1]->reg_ctx, cursor_sp->sctx, cur_idx);
             if (!register_ctx->IsValid())
             {
                 delete register_ctx;
@@ -76,7 +76,7 @@
                 }
                 break;
             }
-            if (!register_ctx->GetCFA (cursor.cfa))
+            if (!register_ctx->GetCFA (cursor_sp->cfa))
             {
                 delete register_ctx;
                 if (log)
@@ -86,7 +86,7 @@
                 }
                 break;
             }
-            if (cursor.cfa == (addr_t) -1 || cursor.cfa == 1 || cursor.cfa == 0)
+            if (cursor_sp->cfa == (addr_t) -1 || cursor_sp->cfa == 1 || cursor_sp->cfa == 0)
             {
                 delete register_ctx;
                 if (log)
@@ -96,7 +96,7 @@
                 }
                 break;
             }
-            if (!register_ctx->GetPC (cursor.start_pc))
+            if (!register_ctx->GetPC (cursor_sp->start_pc))
             {
                 delete register_ctx;
                 if (log)
@@ -107,10 +107,10 @@
                 break;
             }
             RegisterContextSP temp_rcs(register_ctx);
-            StackFrame *frame = new StackFrame(cur_idx, cur_idx, m_thread, temp_rcs, cursor.cfa, cursor.start_pc, &cursor.sctx);
+            StackFrame *frame = new StackFrame(cur_idx, cur_idx, m_thread, temp_rcs, cursor_sp->cfa, cursor_sp->start_pc, &(cursor_sp->sctx));
             register_ctx->SetStackFrame (frame);
-            cursor.reg_ctx = temp_rcs;
-            m_frames.push_back (cursor);
+            cursor_sp->reg_ctx = temp_rcs;
+            m_frames.push_back (cursor_sp);
         }
     }
     return m_frames.size ();
@@ -125,8 +125,8 @@
 
     if (idx < m_frames.size ())
     {
-        cfa = m_frames[idx].cfa;
-        pc = m_frames[idx].start_pc;
+        cfa = m_frames[idx]->cfa;
+        pc = m_frames[idx]->start_pc;
         return true;
     }
     return false;
@@ -146,6 +146,6 @@
         return m_thread.GetRegisterContext();
     }
     if (idx < m_frames.size ())
-        return m_frames[idx].reg_ctx.get();
+        return m_frames[idx]->reg_ctx.get();
     return NULL;
 }
diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
index 5c12117..f281269 100644
--- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -11,6 +11,7 @@
 #define lldb_UnwindLLDB_h_
 
 #include "lldb/lldb-private.h"
+#include "lldb/lldb-types.h"
 #include "lldb/Target/Unwind.h"
 #include "lldb/Symbol/FuncUnwinders.h"
 #include "lldb/Symbol/UnwindPlan.h"
@@ -57,7 +58,8 @@
         Cursor () : start_pc (LLDB_INVALID_ADDRESS), cfa (LLDB_INVALID_ADDRESS), sctx(), reg_ctx() { }
     };
 
-    std::vector<Cursor> m_frames;
+    typedef lldb::SharedPtr<Cursor>::Type CursorSP;
+    std::vector<CursorSP> m_frames;
 
     //------------------------------------------------------------------
     // For UnwindLLDB only
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
index 6f370de..809ae9e 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -287,6 +287,9 @@
     if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
         return true;
 
+    if (!addr.IsValid())
+        return true;
+
     if (m_plan_valid_address_range.ContainsFileAddress (addr))
         return true;
 
diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp
index 183e231..7738cba 100644
--- a/lldb/source/Symbol/UnwindTable.cpp
+++ b/lldb/source/Symbol/UnwindTable.cpp
@@ -77,6 +77,11 @@
 
     initialize();
 
+    if (m_eh_frame == NULL)
+    {
+        return no_unwind_found;
+    }
+
     // Create a FuncUnwinders object for the binary search below
     AddressRange search_range(addr, 1);
     FuncUnwindersSP search_unwind(new FuncUnwinders (*this, NULL, search_range));
@@ -103,26 +108,19 @@
     }
 
     AddressRange range;
-    if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
+    if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range) || !range.GetBaseAddress().IsValid())
     {
-        FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
-        m_unwinds.push_back (unw);
-        std::sort (m_unwinds.begin(), m_unwinds.end());
-        return unw;
-    }
-    else
-    {
-        // Does the eh_frame unwind info has a function bounds defined for this addr?
-        if (m_eh_frame->GetAddressRange (addr, range))
+        // Does the eh_frame unwind info has a function bounds for this addr?
+        if (!m_eh_frame->GetAddressRange (addr, range))
         {
-            FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
-            m_unwinds.push_back (unw);
-            std::sort (m_unwinds.begin(), m_unwinds.end());
-            return unw;
-            // FIXME we should create a syntheic Symbol based on the address range with a synthesized symbol name
+            return no_unwind_found;
         }
     }
-    return no_unwind_found;
+
+    FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
+    m_unwinds.push_back (unw);
+    std::sort (m_unwinds.begin(), m_unwinds.end());
+    return unw;
 }
 
 DWARFCallFrameInfo *