Factor out a bunch of common code in the two ThreadPlanCallFunction constructors.  Also add a sanity check - try reading the frame, and if we fail bag out.

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@154698 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
index a01b5b7..8e1d018 100644
--- a/source/Target/ThreadPlanCallFunction.cpp
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -34,6 +34,92 @@
 //----------------------------------------------------------------------
 // ThreadPlanCallFunction: Plan to call a single function
 //----------------------------------------------------------------------
+bool
+ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
+                                          bool discard_on_error,
+                                          ABI *& abi,
+                                          lldb::addr_t &start_load_addr,
+                                          lldb::addr_t &function_load_addr)
+{
+    // Call function thread plans need to be master plans so that they can potentially stay on the stack when
+    // a breakpoint is hit during the function call.
+    SetIsMasterPlan (true);
+    SetOkayToDiscard (discard_on_error);
+
+    ProcessSP process_sp (thread.GetProcess());
+    if (!process_sp)
+        return false;
+    
+    abi = process_sp->GetABI().get();
+    
+    if (!abi)
+        return false;
+    
+    TargetSP target_sp (thread.CalculateTarget());
+
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    
+    SetBreakpoints();
+    
+    m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
+    // If we can't read memory at the point of the process where we are planning to put our function, we're
+    // not going to get any further...
+    Error error;
+    process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);
+    if (!error.Success())
+    {
+        if (log)
+            log->Printf ("Trying to put the stack in unreadable memory at: 0x%llx.", m_function_sp);
+        return false;
+    }
+    
+    Module *exe_module = target_sp->GetExecutableModulePointer();
+
+    if (exe_module == NULL)
+    {
+        if (log)
+            log->Printf ("Can't execute code without an executable module.");
+        return false;
+    }
+    else
+    {
+        ObjectFile *objectFile = exe_module->GetObjectFile();
+        if (!objectFile)
+        {
+            if (log)
+                log->Printf ("Could not find object file for module \"%s\".", 
+                             exe_module->GetFileSpec().GetFilename().AsCString());
+            return false;
+        }
+        m_start_addr = objectFile->GetEntryPointAddress();
+        if (!m_start_addr.IsValid())
+        {
+            if (log)
+                log->Printf ("Could not find entry point address for executable module \"%s\".", 
+                             exe_module->GetFileSpec().GetFilename().AsCString());
+            return false;
+        }
+    }
+    
+    start_load_addr = m_start_addr.GetLoadAddress (target_sp.get());
+    
+    // Checkpoint the thread state so we can restore it later.
+    if (log && log->GetVerbose())
+        ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
+
+    if (!thread.CheckpointThreadState (m_stored_thread_state))
+    {
+        if (log)
+            log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
+        return false;
+    }
+    // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
+    thread.SetStopInfoToNothing();
+    
+    function_load_addr = m_function_addr.GetLoadAddress (target_sp.get());
+    
+    return true;
+}
 
 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
                                                 Address &function,
@@ -52,78 +138,17 @@
     m_takedown_done (false),
     m_stop_address (LLDB_INVALID_ADDRESS)
 {
-    // Call function thread plans need to be master plans so that they can potentially stay on the stack when
-    // a breakpoint is hit during the function call.
-    SetIsMasterPlan (true);
-    SetOkayToDiscard (discard_on_error);
-
-    ProcessSP process_sp (thread.GetProcess());
-    if (!process_sp)
+    lldb::addr_t start_load_addr;
+    ABI *abi;
+    lldb::addr_t function_load_addr;
+    if (!ConstructorSetup (thread, discard_on_error, abi, start_load_addr, function_load_addr))
         return;
-    
-    const ABI *abi = process_sp->GetABI().get();
-    
-    if (!abi)
-        return;
-    
-    TargetSP target_sp (thread.CalculateTarget());
-
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-    
-    SetBreakpoints();
-    
-    m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
-    
-    Module *exe_module = target_sp->GetExecutableModulePointer();
-
-    if (exe_module == NULL)
-    {
-        if (log)
-            log->Printf ("Can't execute code without an executable module.");
-        return;
-    }
-    else
-    {
-        ObjectFile *objectFile = exe_module->GetObjectFile();
-        if (!objectFile)
-        {
-            if (log)
-                log->Printf ("Could not find object file for module \"%s\".", 
-                             exe_module->GetFileSpec().GetFilename().AsCString());
-            return;
-        }
-        m_start_addr = objectFile->GetEntryPointAddress();
-        if (!m_start_addr.IsValid())
-        {
-            if (log)
-                log->Printf ("Could not find entry point address for executable module \"%s\".", 
-                             exe_module->GetFileSpec().GetFilename().AsCString());
-            return;
-        }
-    }
-    
-    addr_t start_load_addr = m_start_addr.GetLoadAddress (target_sp.get());
-    
-    // Checkpoint the thread state so we can restore it later.
-    if (log && log->GetVerbose())
-        ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
-
-    if (!thread.CheckpointThreadState (m_stored_thread_state))
-    {
-        if (log)
-            log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
-        return;
-    }
-    // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
-    thread.SetStopInfoToNothing();
-    
-    addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress (target_sp.get());
         
     if (this_arg && cmd_arg)
     {
         if (!abi->PrepareTrivialCall (thread, 
                                       m_function_sp, 
-                                      FunctionLoadAddr, 
+                                      function_load_addr, 
                                       start_load_addr, 
                                       this_arg,
                                       cmd_arg,
@@ -134,7 +159,7 @@
     {
         if (!abi->PrepareTrivialCall (thread, 
                                       m_function_sp, 
-                                      FunctionLoadAddr, 
+                                      function_load_addr, 
                                       start_load_addr, 
                                       this_arg,
                                       &arg))
@@ -144,7 +169,7 @@
     {
         if (!abi->PrepareTrivialCall (thread, 
                                       m_function_sp, 
-                                      FunctionLoadAddr, 
+                                      function_load_addr, 
                                       start_load_addr, 
                                       &arg))
             return;
@@ -173,78 +198,18 @@
     m_function_addr (function),
     m_function_sp(NULL),
     m_return_type (return_type),
-    m_takedown_done (false)
+    m_takedown_done (false),
+    m_stop_address (LLDB_INVALID_ADDRESS)
 {
-    // Call function thread plans need to be master plans so that they can potentially stay on the stack when
-    // a breakpoint is hit during the function call.
-    SetIsMasterPlan (true);
-    SetOkayToDiscard (discard_on_error);
-    
-    ProcessSP process_sp (thread.GetProcess());
-    if (!process_sp)
+    lldb::addr_t start_load_addr;
+    ABI *abi;
+    lldb::addr_t function_load_addr;
+    if (!ConstructorSetup (thread, discard_on_error, abi, start_load_addr, function_load_addr))
         return;
     
-    const ABI *abi = process_sp->GetABI().get();
-    
-    if (!abi)
-        return;
-
-    TargetSP target_sp (thread.CalculateTarget());
-
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-    
-    SetBreakpoints();
-    
-    m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
-    
-    Module *exe_module = target_sp->GetExecutableModulePointer();
-    
-    if (exe_module == NULL)
-    {
-        if (log)
-            log->Printf ("Can't execute code without an executable module.");
-        return;
-    }
-    else
-    {
-        ObjectFile *objectFile = exe_module->GetObjectFile();
-        if (!objectFile)
-        {
-            if (log)
-                log->Printf ("Could not find object file for module \"%s\".", 
-                             exe_module->GetFileSpec().GetFilename().AsCString());
-            return;
-        }
-        m_start_addr = objectFile->GetEntryPointAddress();
-        if (!m_start_addr.IsValid())
-        {
-            if (log)
-                log->Printf ("Could not find entry point address for executable module \"%s\".", 
-                             exe_module->GetFileSpec().GetFilename().AsCString());
-            return;
-        }
-    }
-    
-    addr_t start_load_addr = m_start_addr.GetLoadAddress(target_sp.get());
-    
-    // Checkpoint the thread state so we can restore it later.
-    if (log && log->GetVerbose())
-        ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");
-    
-    if (!thread.CheckpointThreadState (m_stored_thread_state))
-    {
-        if (log)
-            log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
-        return;
-    }
-    // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
-    thread.SetStopInfoToNothing();
-    
-    addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(target_sp.get());
-    
     if (!abi->PrepareTrivialCall (thread, 
-                                  m_function_sp, 
-                                  FunctionLoadAddr, 
+                                  m_function_sp,
+                                  function_load_addr, 
                                   start_load_addr, 
                                   arg1_ptr,
                                   arg2_ptr,