[Lldb-commits] [lldb] r253026 - Fix to solve Bug 23139 & Bug 23560

Abhishek Aggarwal via lldb-commits lldb-commits at lists.llvm.org
Fri Nov 13 02:47:50 PST 2015


Author: abhishek
Date: Fri Nov 13 04:47:49 2015
New Revision: 253026

URL: http://llvm.org/viewvc/llvm-project?rev=253026&view=rev
Log:
Fix to solve Bug 23139 & Bug 23560

Summary:
 - Reason of both bugs:

   1. For the very first frame, Unwinder doesn't check the validity
      of Full UnwindPlan before creating StackFrame from it:

        When 'process launch' command is run after setting a breakpoint
        in inferior, the Unwinder runs and saves only Frame 0 (the frame
        in which breakpoint was set) in thread's StackFrameList i.e.
        m_curr_frames_sp. However, it doesn't check the validity of the
        Full UnwindPlan for this frame by unwinding 2 more frames further.

   2. Unwinder doesn't update the CFA value of Cursor when Full UnwindPlan
      fails and FallBack UnwindPlan succeeds in providing valid CFA values
      for frames:

        Sometimes during unwinding of stack frames, the Full UnwindPlan
        inside the RegisterContextLLDB object may fail to provide valid
        CFA values for these frames. Then the Fallback UnwindPlan is used
        to unwind the frames.

        If the Fallback UnwindPlan succeeds, then it provides a valid new
        CFA value. The RegisterContextLLDB::m_cfa field of Cursor object
        is updated during the Fallback UnwindPlan execution. However,
        UnwindLLDB misses the implementation to update the 'cfa' field
        of this Cursor with this valid new CFA value.

 - This patch fixes both these issues.

 - Remove XFAIL in test files corresponding to these 2 Bugs

Change-Id: I932ea407545ceee2d628f946ecc61a4806d4cc86
Signed-off-by: Abhishek Aggarwal <abhishek.a.aggarwal at intel.com>

Reviewers: jingham, lldb-commits, jasonmolenda

Subscribers: lldb-commits, ovyalov, tberghammer

Differential Revision: http://reviews.llvm.org/D14226

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py
    lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h

Modified: lldb/trunk/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py Fri Nov 13 04:47:49 2015
@@ -17,7 +17,6 @@ class SBBreakpointCallbackCase(TestBase)
     @skipIfRemote
     @skipIfNoSBHeaders
     @skipIfWindows # clang-cl does not support throw or catch (llvm.org/pr24538)
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["x86_64"])
     def test_breakpoint_callback(self):
         """Test the that SBBreakpoint callback is invoked when a breakpoint is hit. """
         self.build_and_test('driver.cpp test_breakpoint_callback.cpp',
@@ -27,7 +26,6 @@ class SBBreakpointCallbackCase(TestBase)
     @skipIfNoSBHeaders
     @skipIfWindows # clang-cl does not support throw or catch (llvm.org/pr24538)
     @expectedFlakeyFreeBSD
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["x86_64"])
     def test_sb_api_listener_event_description(self):
         """ Test the description of an SBListener breakpoint event is valid."""
         self.build_and_test('driver.cpp listener_test.cpp test_listener_event_description.cpp',
@@ -39,7 +37,6 @@ class SBBreakpointCallbackCase(TestBase)
     @skipIfWindows # clang-cl does not support throw or catch (llvm.org/pr24538)
     @expectedFlakeyFreeBSD
     @expectedFlakeyLinux # Driver occasionally returns '1' as exit status
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["x86_64"])
     def test_sb_api_listener_event_process_state(self):
         """ Test that a registered SBListener receives events when a process
             changes state.

Modified: lldb/trunk/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py Fri Nov 13 04:47:49 2015
@@ -56,7 +56,6 @@ class BasicExprCommandsTestCase(TestBase
             patterns = ["\(float\) \$.* = 2\.234"])
         # (float) $2 = 2.234
 
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     @expectedFailureWindows("llvm.org/pr21765")
     def test_many_expr_commands(self):
         self.build_and_run()
@@ -99,7 +98,6 @@ class BasicExprCommandsTestCase(TestBase
         # (const char *) $8 = 0x... "/Volumes/data/lldb/svn/trunk/test/expression_command/test/a.out"
 
     @add_test_categories(['pyapi'])
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     @expectedFailureWindows # Test crashes
     def test_evaluate_expression_python(self):
         """Test SBFrame.EvaluateExpression() API for evaluating an expression."""

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py Fri Nov 13 04:47:49 2015
@@ -21,7 +21,6 @@ class SynthDataFormatterTestCase(TestBas
         # Find the line number to break at.
         self.line = line_number('main.cpp', '// Set break point at this line.')
 
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["x86_64","i386"])
     def test_with_run_command(self):
         """Test that that file and class static variables display correctly."""
         self.build()

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py Fri Nov 13 04:47:49 2015
@@ -20,7 +20,6 @@ class ConvenienceVariablesCase(TestBase)
 
     @skipIfFreeBSD # llvm.org/pr17228
     @skipIfRemote
-    @expectedFailureAll("llvm.org/pr23560", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
     def test_with_run_commands(self):
         """Test convenience variables lldb.debugger, lldb.target, lldb.process, lldb.thread, and lldb.frame."""

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py Fri Nov 13 04:47:49 2015
@@ -40,7 +40,6 @@ class CrashingInferiorTestCase(TestBase)
         self.build()
         self.inferior_crashing_expr()
 
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     @expectedFailureWindows("llvm.org/pr24778")
     def test_inferior_crashing_step(self):
         """Test that stepping after a crash behaves correctly."""

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py Fri Nov 13 04:47:49 2015
@@ -16,7 +16,6 @@ class TestInlineStepping(TestBase):
     @add_test_categories(['pyapi'])
     @expectedFailureFreeBSD('llvm.org/pr17214')
     @expectedFailureIcc # Not really a bug.  ICC combines two inlined functions.
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     @expectedFailureWindows("llvm.org/pr24778")
     # failed 1/365 dosep runs, (i386-clang), TestInlineStepping.py:237 failed to stop at first breakpoint in main
     @expectedFailureAll(oslist=["linux"], archs=["i386"])
@@ -26,7 +25,6 @@ class TestInlineStepping(TestBase):
         self.inline_stepping()
 
     @add_test_categories(['pyapi'])
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_step_over_with_python_api(self):
         """Test stepping over and into inlined functions."""
         self.build()

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/memory/read/TestMemoryRead.py Fri Nov 13 04:47:49 2015
@@ -22,7 +22,6 @@ class MemoryReadTestCase(TestBase):
         # Find the line number to break inside main().
         self.line = line_number('main.cpp', '// Set break point at this line.')
 
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_memory_read(self):
         """Test the 'memory read' command with plain and vector formats."""
         self.build()

Modified: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py Fri Nov 13 04:47:49 2015
@@ -34,7 +34,6 @@ class MiExecTestCase(lldbmi_testcase.MiT
 
     @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
     @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_lldbmi_exec_abort(self):
         """Test that 'lldb-mi --interpreter' works for -exec-abort."""
 
@@ -84,7 +83,6 @@ class MiExecTestCase(lldbmi_testcase.MiT
 
     @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
     @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_lldbmi_exec_arguments_set(self):
         """Test that 'lldb-mi --interpreter' can pass args using -exec-arguments."""
 
@@ -127,7 +125,6 @@ class MiExecTestCase(lldbmi_testcase.MiT
 
     @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
     @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_lldbmi_exec_arguments_reset(self):
         """Test that 'lldb-mi --interpreter' can reset previously set args using -exec-arguments."""
 
@@ -208,7 +205,6 @@ class MiExecTestCase(lldbmi_testcase.MiT
     @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
     @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
     @expectedFailurei386 #xfail to get buildbot green, failing config: i386 binary running on ubuntu 14.04 x86_64
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_lldbmi_exec_next_instruction(self):
         """Test that 'lldb-mi --interpreter' works for instruction stepping."""
 
@@ -391,7 +387,6 @@ class MiExecTestCase(lldbmi_testcase.MiT
 
     @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
     @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
-    @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_lldbmi_exec_finish(self):
         """Test that 'lldb-mi --interpreter' works for -exec-finish."""
 

Modified: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py?rev=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py Fri Nov 13 04:47:49 2015
@@ -15,7 +15,6 @@ class MiVarTestCase(lldbmi_testcase.MiTe
 
     @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
     @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
-    @expectedFailureAll("llvm.org/pr23560", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["i386"])
     def test_lldbmi_eval(self):
         """Test that 'lldb-mi --interpreter' works for evaluating."""
 

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=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp Fri Nov 13 04:47:49 2015
@@ -86,6 +86,9 @@ UnwindLLDB::AddFirstFrame ()
     if (m_frames.size() > 0)
         return true;
         
+    ProcessSP process_sp (m_thread.GetProcess());
+    ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+
     // First, set up the 0th (initial) frame
     CursorSP first_cursor_sp(new Cursor ());
     RegisterContextLLDBSP reg_ctx_sp (new RegisterContextLLDB (m_thread, 
@@ -108,6 +111,10 @@ UnwindLLDB::AddFirstFrame ()
     // cursor own it in its shared pointer
     first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
     m_frames.push_back (first_cursor_sp);
+
+    // Update the Full Unwind Plan for this frame if not valid
+    UpdateUnwindPlanForFirstFrameIfInvalid(abi);
+
     return true;
 
 unwind_done:
@@ -161,7 +168,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
         // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
         // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.
         if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+        {
+            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+                return nullptr;
+
             return GetOneMoreFrame (abi);
+        }
 
         if (log)
             log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.",
@@ -175,7 +189,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
         // See if the regctx below this on the stack has a fallback unwind plan it can use.
         // Subsequent calls to TryFallbackUnwindPlan() will return false.
         if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+        {
+            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+                return nullptr;
+
             return GetOneMoreFrame (abi);
+        }
 
         if (log)
             log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk", 
@@ -187,7 +208,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
         // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
         // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.
         if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+        {
+            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+                return nullptr;
+
             return GetOneMoreFrame (abi);
+        }
 
         if (log)
             log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
@@ -212,7 +240,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
                 || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)
             {
                 if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+                {
+                    // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+                    // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+                    if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+                        return nullptr;
+
                     return GetOneMoreFrame (abi);
+                }
 
                 if (log)
                     log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
@@ -232,7 +267,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
         // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
         // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.
         if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+        {
+            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+                return nullptr;
+
             return GetOneMoreFrame (abi);
+        }
 
         if (log)
             log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
@@ -244,7 +286,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
         // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
         // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.
         if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+        {
+            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+                return nullptr;
+
             return GetOneMoreFrame (abi);
+        }
 
         if (log)
             log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk",
@@ -263,6 +312,33 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
     return cursor_sp;
 }
 
+void
+UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid (ABI *abi)
+{
+    // This function is called for First Frame only.
+    assert (m_frames.size() == 1 && "No. of cursor frames are not 1");
+
+    bool old_m_unwind_complete = m_unwind_complete;
+    CursorSP old_m_candidate_frame = m_candidate_frame;
+
+    // Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan
+    // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also
+    // update the cfa of Frame 0 (if required).
+    AddOneMoreFrame(abi);
+
+    // Remove all the frames added by above function as the purpose of
+    // using above function was just to check whether Unwinder of Frame 0
+    // works or not.
+    for(uint32_t i=1; i<m_frames.size(); i++)
+        m_frames.pop_back();
+
+    // Restore status after calling AddOneMoreFrame
+    m_unwind_complete = old_m_unwind_complete;
+    m_candidate_frame = old_m_candidate_frame;
+    return;
+}
+
+
 bool
 UnwindLLDB::AddOneMoreFrame (ABI *abi)
 {
@@ -321,9 +397,17 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
     m_frames.push_back(new_frame_v2);
     m_candidate_frame = GetOneMoreFrame(abi);
     if (m_candidate_frame)
+    {
+        // If control reached here then TryFallbackUnwindPlan had succeeded for Cursor::m_frames[m_frames.size() - 2].
+        // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that.
+        // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already updated during TryFallbackUnwindPlan
+        // call above. However, cfa field still needs to be updated. Hence updating it here and then returning.
+        if ( !(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(m_frames[m_frames.size() - 2]->cfa)))
+            return false;
         return true;
+    }
 
-    // The new frame isn't helped in unwinding. Fall back to the original one as the default unwind
+    // The new frame hasn't helped in unwinding. Fall back to the original one as the default unwind
     // plan is usually more reliable then the fallback one.
     m_frames.pop_back();
     m_frames.push_back(new_frame);

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=253026&r1=253025&r2=253026&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h Fri Nov 13 04:47:49 2015
@@ -136,6 +136,15 @@ private:
  
     std::vector<ConstString> m_user_supplied_trap_handler_functions;
 
+    //-----------------------------------------------------------------
+    // Check if Full UnwindPlan of First frame is valid or not.
+    // If not then try Fallback UnwindPlan of the frame. If Fallback
+    // UnwindPlan succeeds then update the Full UnwindPlan with the
+    // Fallback UnwindPlan.
+    //-----------------------------------------------------------------
+    void
+    UpdateUnwindPlanForFirstFrameIfInvalid (ABI* abi);
+
     CursorSP
     GetOneMoreFrame (ABI* abi);
 




More information about the lldb-commits mailing list