[Lldb-commits] [lldb] r163867 - in /lldb/trunk: include/lldb/API/SBThread.h include/lldb/Target/RegisterContext.h include/lldb/Target/Thread.h scripts/Python/interface/SBThread.i source/API/SBThread.cpp source/Commands/CommandObjectThread.cpp source/Target/RegisterContext.cpp source/Target/Thread.cpp

Jim Ingham jingham at apple.com
Thu Sep 13 19:14:15 PDT 2012


Author: jingham
Date: Thu Sep 13 21:14:15 2012
New Revision: 163867

URL: http://llvm.org/viewvc/llvm-project?rev=163867&view=rev
Log:
Make the unwinding of the stack part of "thread return" work, and add the thread return command.

Modified:
    lldb/trunk/include/lldb/API/SBThread.h
    lldb/trunk/include/lldb/Target/RegisterContext.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/scripts/Python/interface/SBThread.i
    lldb/trunk/source/API/SBThread.cpp
    lldb/trunk/source/Commands/CommandObjectThread.cpp
    lldb/trunk/source/Target/RegisterContext.cpp
    lldb/trunk/source/Target/Thread.cpp

Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Thu Sep 13 21:14:15 2012
@@ -103,7 +103,7 @@
     RunToAddress (lldb::addr_t addr);
     
     SBError
-    ReturnToFrame (SBFrame &frame, SBValue &return_value);
+    ReturnFromFrame (SBFrame &frame, SBValue &return_value);
 
     //--------------------------------------------------------------------------
     /// LLDB currently supports process centric debugging which means when any

Modified: lldb/trunk/include/lldb/Target/RegisterContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/RegisterContext.h?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/RegisterContext.h (original)
+++ lldb/trunk/include/lldb/Target/RegisterContext.h Thu Sep 13 21:14:15 2012
@@ -72,6 +72,9 @@
     virtual bool
     WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0;
     
+    bool
+    CopyFromRegisterContext (lldb::RegisterContextSP context);
+    
     virtual uint32_t
     ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) = 0;
 

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Thu Sep 13 21:14:15 2012
@@ -286,10 +286,10 @@
     }
     
     Error
-    ReturnToFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp);
+    ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp);
     
     Error
-    ReturnToFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp);
+    ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp);
     
     virtual lldb::StackFrameSP
     GetFrameWithStackID (const StackID &stack_id)

Modified: lldb/trunk/scripts/Python/interface/SBThread.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBThread.i?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBThread.i (original)
+++ lldb/trunk/scripts/Python/interface/SBThread.i Thu Sep 13 21:14:15 2012
@@ -131,7 +131,7 @@
     RunToAddress (lldb::addr_t addr);
 
     SBError
-    ReturnToFrame (SBFrame &frame, SBValue &return_value);
+    ReturnFromFrame (SBFrame &frame, SBValue &return_value);
 
     %feature("docstring", "
     //--------------------------------------------------------------------------

Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Thu Sep 13 21:14:15 2012
@@ -878,7 +878,7 @@
 }
 
 SBError
-SBThread::ReturnToFrame (SBFrame &frame, SBValue &return_value)
+SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
 {
     SBError sb_error;
     
@@ -889,12 +889,12 @@
 
 
     if (log)
-        log->Printf ("SBThread(%p)::ReturnToFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID());
+        log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID());
     
     if (exe_ctx.HasThreadScope())
     {
         Thread *thread = exe_ctx.GetThreadPtr();
-        sb_error.SetError (thread->ReturnToFrame(frame.GetFrameSP(), return_value.GetSP()));
+        sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
     }
     
     return sb_error;

Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Thu Sep 13 21:14:15 2012
@@ -13,6 +13,7 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "lldb/lldb-private.h"
 #include "lldb/Core/State.h"
 #include "lldb/Core/SourceManager.h"
 #include "lldb/Host/Host.h"
@@ -1244,6 +1245,107 @@
     }
 };
 
+class CommandObjectThreadReturn : public CommandObjectRaw
+{
+public:
+    CommandObjectThreadReturn (CommandInterpreter &interpreter) :
+        CommandObjectRaw (interpreter,
+                          "thread return",
+                          "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value.",
+                          "thread return",
+                          eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+    {
+        CommandArgumentEntry arg;
+        CommandArgumentData expression_arg;
+
+        // Define the first (and only) variant of this arg.
+        expression_arg.arg_type = eArgTypeExpression;
+        expression_arg.arg_repetition = eArgRepeatPlain;
+
+        // There is only one variant this argument could be; put it into the argument entry.
+        arg.push_back (expression_arg);
+
+        // Push the data for the first argument into the m_arguments vector.
+        m_arguments.push_back (arg);
+        
+        
+    }
+    
+    ~CommandObjectThreadReturn()
+    {
+    }
+    
+protected:
+
+    bool DoExecute
+    (
+        const char *command,
+        CommandReturnObject &result
+    )
+    {
+        // If there is a command string, pass it to the expression parser:
+        ExecutionContext exe_ctx = m_interpreter.GetExecutionContext();
+        if (!(exe_ctx.HasProcessScope() && exe_ctx.HasThreadScope() && exe_ctx.HasFrameScope()))
+        {
+            result.AppendError("Must have selected process, thread and frame for thread return.");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        
+        ValueObjectSP return_valobj_sp;
+        
+        StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+        uint32_t frame_idx = frame_sp->GetFrameIndex();
+        
+        if (frame_sp->IsInlined())
+        {
+            result.AppendError("Don't know how to return from inlined frames.");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        
+        if (command && command[0] != '\0')
+        {
+            Target *target = exe_ctx.GetTargetPtr();
+            Target::EvaluateExpressionOptions options;
+
+            options.SetUnwindOnError(true);
+            options.SetUseDynamic(eNoDynamicValues);
+            
+            ExecutionResults exe_results = eExecutionSetupError;
+            exe_results = target->EvaluateExpression (command,
+                                                      frame_sp.get(),
+                                                      return_valobj_sp,
+                                                      options);
+            if (exe_results != eExecutionCompleted)
+            {
+                if (return_valobj_sp)
+                    result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
+                else
+                    result.AppendErrorWithFormat("Unknown error evaluating result expression.");
+                result.SetStatus (eReturnStatusFailed);
+                return false;
+            
+            }
+        }
+                
+        Error error;
+        ThreadSP thread_sp = exe_ctx.GetThreadSP();
+        error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp);
+        if (!error.Success())
+        {
+            result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        thread_sp->GetStatus(result.GetOutputStream(), 0, 1, 1);
+        result.SetStatus (eReturnStatusSuccessFinishResult);
+        return true;
+    }
+
+};
+
 //-------------------------------------------------------------------------
 // CommandObjectMultiwordThread
 //-------------------------------------------------------------------------
@@ -1257,6 +1359,7 @@
     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
+    LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (

Modified: lldb/trunk/source/Target/RegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/RegisterContext.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/Target/RegisterContext.cpp (original)
+++ lldb/trunk/source/Target/RegisterContext.cpp Thu Sep 13 21:14:15 2012
@@ -196,6 +196,47 @@
     return false;
 }
 
+bool
+RegisterContext::CopyFromRegisterContext (lldb::RegisterContextSP context)
+{
+    uint32_t num_register_sets = context->GetRegisterSetCount();
+    // We don't know that two threads have the same register context, so require the threads to be the same.
+    if (context->GetThreadID() != GetThreadID())
+        return false;
+    
+    if (num_register_sets != GetRegisterSetCount())
+        return false;
+    
+    RegisterContextSP frame_zero_context = m_thread.GetRegisterContext();
+    
+    for (uint32_t set_idx = 0; set_idx < num_register_sets; ++set_idx)
+    {
+        const RegisterSet * const reg_set = GetRegisterSet(set_idx);
+        
+        const uint32_t num_registers = reg_set->num_registers;
+        for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
+        {
+            const uint32_t reg = reg_set->registers[reg_idx];
+            const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+            if (!reg_info || reg_info->value_regs)
+                continue;
+            RegisterValue reg_value;
+            
+            // If we can reconstruct the register from the frame we are copying from, then do so, otherwise
+            // use the value from frame 0.
+            if (context->ReadRegister(reg_info, reg_value))
+            {
+                WriteRegister(reg_info, reg_value);
+            }
+            else if (frame_zero_context->ReadRegister(reg_info, reg_value))
+            {
+                WriteRegister(reg_info, reg_value);
+            }
+        }
+    }
+    return true;
+}
+
 lldb::tid_t
 RegisterContext::GetThreadID() const
 {

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Thu Sep 13 21:14:15 2012
@@ -1273,7 +1273,7 @@
 
 
 Error
-Thread::ReturnToFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp)
+Thread::ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp)
 {
     StackFrameSP frame_sp = GetStackFrameAtIndex (frame_idx);
     Error return_error;
@@ -1283,11 +1283,11 @@
         return_error.SetErrorStringWithFormat("Could not find frame with index %d in thread 0x%llx.", frame_idx, GetID());
     }
     
-    return ReturnToFrame(frame_sp, return_value_sp);
+    return ReturnFromFrame(frame_sp, return_value_sp);
 }
 
 Error
-Thread::ReturnToFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp)
+Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp)
 {
     Error return_error;
     
@@ -1298,32 +1298,37 @@
     }
     
     Thread *thread = frame_sp->GetThread().get();
+    uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1;
+    StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx);
     
     if (return_value_sp)
     {
+        // TODO: coerce the return_value_sp to the type of the function in frame_sp.
+    
         lldb::ABISP abi = thread->GetProcess()->GetABI();
         if (!abi)
         {
             return_error.SetErrorString("Could not find ABI to set return value.");
         }
-        return_error = abi->SetReturnValueObject(frame_sp, return_value_sp);
+        return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
         if (!return_error.Success())
             return return_error;
     }
     
     // Now write the return registers for the chosen frame:
-    lldb::DataBufferSP register_values_sp;
-    frame_sp->GetRegisterContext()->ReadAllRegisterValues (register_values_sp);
-    if (thread->ResetFrameZeroRegisters(register_values_sp))
+    // Note, we can't use ReadAllRegisterValues->WriteAllRegisterValues, since the read & write
+    // cook their data 
+    bool copy_success = thread->GetStackFrameAtIndex(0)->GetRegisterContext()->CopyFromRegisterContext(older_frame_sp->GetRegisterContext());
+    if (copy_success)
     {
         thread->DiscardThreadPlans(true);
+        thread->ClearStackFrames();
         return return_error;
     }
     else
     {
         return_error.SetErrorString("Could not reset register values.");
         return return_error;
-    
     }
 }
 





More information about the lldb-commits mailing list