summaryrefslogtreecommitdiff
path: root/lldb/source/Target/ThreadPlanCallFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Target/ThreadPlanCallFunction.cpp')
-rw-r--r--lldb/source/Target/ThreadPlanCallFunction.cpp509
1 files changed, 0 insertions, 509 deletions
diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp
deleted file mode 100644
index fa89b412b3ca..000000000000
--- a/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ /dev/null
@@ -1,509 +0,0 @@
-//===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Target/ThreadPlanCallFunction.h"
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "llvm/Support/MachO.h"
-// Project includes
-#include "lldb/lldb-private-log.h"
-#include "lldb/Breakpoint/Breakpoint.h"
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/Address.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Target/LanguageRuntime.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Target/ThreadPlanRunToAddress.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-//----------------------------------------------------------------------
-// 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::GetLogIfAnyCategoriesSet (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 ("ThreadPlanCallFunction(%p): Trying to put the stack in unreadable memory at: 0x%llx.", this, m_function_sp);
- return false;
- }
-
- Module *exe_module = target_sp->GetExecutableModulePointer();
-
- if (exe_module == NULL)
- {
- if (log)
- log->Printf ("ThreadPlanCallFunction(%p): Can't execute code without an executable module.", this);
- return false;
- }
- else
- {
- ObjectFile *objectFile = exe_module->GetObjectFile();
- if (!objectFile)
- {
- if (log)
- log->Printf ("ThreadPlanCallFunction(%p): Could not find object file for module \"%s\".",
- this, exe_module->GetFileSpec().GetFilename().AsCString());
- return false;
- }
- m_start_addr = objectFile->GetEntryPointAddress();
- if (!m_start_addr.IsValid())
- {
- if (log)
- log->Printf ("ThreadPlanCallFunction(%p): Could not find entry point address for executable module \"%s\".",
- this, 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 ("ThreadPlanCallFunction(%p): Setting up ThreadPlanCallFunction, failed to checkpoint thread state.", this);
- 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,
- const ClangASTType &return_type,
- addr_t arg,
- bool stop_other_threads,
- bool discard_on_error,
- addr_t *this_arg,
- addr_t *cmd_arg) :
- ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
- m_valid (false),
- m_stop_other_threads (stop_other_threads),
- m_function_addr (function),
- m_function_sp (NULL),
- m_return_type (return_type),
- m_takedown_done (false),
- m_stop_address (LLDB_INVALID_ADDRESS)
-{
- 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;
-
- if (this_arg && cmd_arg)
- {
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- this_arg,
- cmd_arg,
- &arg))
- return;
- }
- else if (this_arg)
- {
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- this_arg,
- &arg))
- return;
- }
- else
- {
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- &arg))
- return;
- }
-
- ReportRegisterState ("Function call was set up. Register state was:");
-
- m_valid = true;
-}
-
-
-ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
- Address &function,
- const ClangASTType &return_type,
- bool stop_other_threads,
- bool discard_on_error,
- addr_t *arg1_ptr,
- addr_t *arg2_ptr,
- addr_t *arg3_ptr,
- addr_t *arg4_ptr,
- addr_t *arg5_ptr,
- addr_t *arg6_ptr) :
- ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
- m_valid (false),
- m_stop_other_threads (stop_other_threads),
- m_function_addr (function),
- m_function_sp(NULL),
- m_return_type (return_type),
- m_takedown_done (false),
- m_stop_address (LLDB_INVALID_ADDRESS)
-{
- 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;
-
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- arg1_ptr,
- arg2_ptr,
- arg3_ptr,
- arg4_ptr,
- arg5_ptr,
- arg6_ptr))
- {
- return;
- }
-
- ReportRegisterState ("Function call was set up. Register state was:");
-
- m_valid = true;
-}
-
-ThreadPlanCallFunction::~ThreadPlanCallFunction ()
-{
- DoTakedown();
-}
-
-void
-ThreadPlanCallFunction::ReportRegisterState (const char *message)
-{
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_VERBOSE));
- if (log)
- {
- StreamString strm;
- RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
-
- log->PutCString(message);
-
- RegisterValue reg_value;
-
- for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();
- reg_idx < num_registers;
- ++reg_idx)
- {
- const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_idx);
- if (reg_ctx->ReadRegister(reg_info, reg_value))
- {
- reg_value.Dump(&strm, reg_info, true, false, eFormatDefault);
- strm.EOL();
- }
- }
- log->PutCString(strm.GetData());
- }
-}
-
-void
-ThreadPlanCallFunction::DoTakedown ()
-{
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
-
- if (!m_valid)
- {
- //Don't call DoTakedown if we were never valid to begin with.
- if (log)
- log->Printf ("ThreadPlanCallFunction(%p): Log called on ThreadPlanCallFunction that was never valid.", this);
- return;
- }
-
- if (!m_takedown_done)
- {
- ProcessSP process_sp (m_thread.GetProcess());
- const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
- if (abi && m_return_type.IsValid())
- {
- const bool persistent = false;
- m_return_valobj_sp = abi->GetReturnValueObject (m_thread, m_return_type, persistent);
- }
-
- if (log)
- log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4llx, m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
- m_takedown_done = true;
- m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
- m_real_stop_info_sp = GetPrivateStopReason();
- m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state);
- SetPlanComplete();
- ClearBreakpoints();
- if (log && log->GetVerbose())
- ReportRegisterState ("Restoring thread state after function call. Restored register state:");
-
- }
- else
- {
- if (log)
- log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called as no-op for thread 0x%4.4llx, m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
- }
-}
-
-void
-ThreadPlanCallFunction::WillPop ()
-{
- DoTakedown();
-}
-
-void
-ThreadPlanCallFunction::GetDescription (Stream *s, DescriptionLevel level)
-{
- if (level == eDescriptionLevelBrief)
- {
- s->Printf("Function call thread plan");
- }
- else
- {
- TargetSP target_sp (m_thread.CalculateTarget());
- s->Printf("Thread plan to call 0x%llx", m_function_addr.GetLoadAddress(target_sp.get()));
- }
-}
-
-bool
-ThreadPlanCallFunction::ValidatePlan (Stream *error)
-{
- if (!m_valid)
- return false;
-
- return true;
-}
-
-bool
-ThreadPlanCallFunction::PlanExplainsStop ()
-{
- m_real_stop_info_sp = GetPrivateStopReason();
-
- // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
- // we answer yes.
- if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
- return true;
-
- // Check if the breakpoint is one of ours.
-
- if (BreakpointsExplainStop())
- return true;
-
- // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
- if (!OkayToDiscard())
- return false;
-
- // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
- // If it is not an internal breakpoint, consult OkayToDiscard.
-
- if (m_real_stop_info_sp && m_real_stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
- {
- ProcessSP process_sp (m_thread.CalculateProcess());
- uint64_t break_site_id = m_real_stop_info_sp->GetValue();
- BreakpointSiteSP bp_site_sp;
- if (process_sp)
- bp_site_sp = process_sp->GetBreakpointSiteList().FindByID(break_site_id);
- if (bp_site_sp)
- {
- uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
- bool is_internal = true;
- for (uint32_t i = 0; i < num_owners; i++)
- {
- Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
-
- if (!bp.IsInternal())
- {
- is_internal = false;
- break;
- }
- }
- if (is_internal)
- return false;
- }
-
- return OkayToDiscard();
- }
- else
- {
- // If the subplan is running, any crashes are attributable to us.
- // If we want to discard the plan, then we say we explain the stop
- // but if we are going to be discarded, let whoever is above us
- // explain the stop.
- return ((m_subplan_sp.get() != NULL) && !OkayToDiscard());
- }
-}
-
-bool
-ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
-{
- if (PlanExplainsStop())
- {
- ReportRegisterState ("Function completed. Register state was:");
-
- DoTakedown();
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-bool
-ThreadPlanCallFunction::StopOthers ()
-{
- return m_stop_other_threads;
-}
-
-void
-ThreadPlanCallFunction::SetStopOthers (bool new_value)
-{
- if (m_subplan_sp)
- {
- ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get());
- address_plan->SetStopOthers(new_value);
- }
- m_stop_other_threads = new_value;
-}
-
-StateType
-ThreadPlanCallFunction::GetPlanRunState ()
-{
- return eStateRunning;
-}
-
-void
-ThreadPlanCallFunction::DidPush ()
-{
-//#define SINGLE_STEP_EXPRESSIONS
-
-#ifndef SINGLE_STEP_EXPRESSIONS
- m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
-
- m_thread.QueueThreadPlan(m_subplan_sp, false);
- m_subplan_sp->SetPrivate (true);
-#endif
-}
-
-bool
-ThreadPlanCallFunction::WillStop ()
-{
- return true;
-}
-
-bool
-ThreadPlanCallFunction::MischiefManaged ()
-{
- if (IsPlanComplete())
- {
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-
- if (log)
- log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", this);
-
- ThreadPlan::MischiefManaged ();
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void
-ThreadPlanCallFunction::SetBreakpoints ()
-{
- ProcessSP process_sp (m_thread.CalculateProcess());
- if (process_sp)
- {
- m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus);
- m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC);
-
- if (m_cxx_language_runtime)
- m_cxx_language_runtime->SetExceptionBreakpoints();
- if (m_objc_language_runtime)
- m_objc_language_runtime->SetExceptionBreakpoints();
- }
-}
-
-void
-ThreadPlanCallFunction::ClearBreakpoints ()
-{
- if (m_cxx_language_runtime)
- m_cxx_language_runtime->ClearExceptionBreakpoints();
- if (m_objc_language_runtime)
- m_objc_language_runtime->ClearExceptionBreakpoints();
-}
-
-bool
-ThreadPlanCallFunction::BreakpointsExplainStop()
-{
- StopInfoSP stop_info_sp = GetPrivateStopReason();
-
- if (m_cxx_language_runtime &&
- m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
- return true;
-
- if (m_objc_language_runtime &&
- m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
- return true;
-
- return false;
-}