2010-06-08 16:52:24 +00:00
//===-- 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
2010-11-03 01:37:52 +00:00
# include "llvm/Support/MachO.h"
2010-06-08 16:52:24 +00:00
// Project includes
# include "lldb/lldb-private-log.h"
2010-10-26 00:27:45 +00:00
# include "lldb/Breakpoint/Breakpoint.h"
# include "lldb/Breakpoint/BreakpointLocation.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/Address.h"
# include "lldb/Core/Log.h"
# include "lldb/Core/Stream.h"
2010-11-03 22:19:38 +00:00
# include "lldb/Target/LanguageRuntime.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Target/Process.h"
# include "lldb/Target/RegisterContext.h"
2010-10-26 00:27:45 +00:00
# include "lldb/Target/StopInfo.h"
2010-06-08 16:52:24 +00:00
# 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
//----------------------------------------------------------------------
2012-04-13 20:38:13 +00:00
bool
ThreadPlanCallFunction : : ConstructorSetup ( Thread & thread ,
ABI * & abi ,
lldb : : addr_t & start_load_addr ,
lldb : : addr_t & function_load_addr )
2010-06-08 16:52:24 +00:00
{
2012-04-09 22:37:39 +00:00
SetIsMasterPlan ( true ) ;
2012-05-11 18:43:38 +00:00
SetOkayToDiscard ( false ) ;
2010-06-08 16:52:24 +00:00
2012-02-21 00:09:25 +00:00
ProcessSP process_sp ( thread . GetProcess ( ) ) ;
if ( ! process_sp )
2012-04-13 20:38:13 +00:00
return false ;
2012-02-21 00:09:25 +00:00
2012-04-13 20:38:13 +00:00
abi = process_sp - > GetABI ( ) . get ( ) ;
2010-11-03 01:37:52 +00:00
2010-06-08 16:52:24 +00:00
if ( ! abi )
2012-04-13 20:38:13 +00:00
return false ;
2010-11-03 01:37:52 +00:00
2012-02-21 00:09:25 +00:00
TargetSP target_sp ( thread . CalculateTarget ( ) ) ;
2012-04-13 23:11:52 +00:00
LogSP log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_STEP ) ) ;
2011-01-20 02:03:18 +00:00
2010-11-03 01:37:52 +00:00
SetBreakpoints ( ) ;
2011-05-09 22:04:36 +00:00
m_function_sp = thread . GetRegisterContext ( ) - > GetSP ( ) - abi - > GetRedZoneSize ( ) ;
2012-04-13 20:38:13 +00:00
// 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 )
2012-04-13 23:11:52 +00:00
log - > Printf ( " ThreadPlanCallFunction(%p): Trying to put the stack in unreadable memory at: 0x%llx. " , this , m_function_sp ) ;
2012-04-13 20:38:13 +00:00
return false ;
}
2010-06-08 16:52:24 +00:00
2012-02-21 00:09:25 +00:00
Module * exe_module = target_sp - > GetExecutableModulePointer ( ) ;
2010-06-08 16:52:24 +00:00
2011-08-11 02:48:45 +00:00
if ( exe_module = = NULL )
2011-03-07 23:44:08 +00:00
{
2011-08-10 17:58:11 +00:00
if ( log )
2012-04-13 23:11:52 +00:00
log - > Printf ( " ThreadPlanCallFunction(%p): Can't execute code without an executable module. " , this ) ;
2012-04-13 20:38:13 +00:00
return false ;
2011-03-07 23:44:08 +00:00
}
else
{
2011-08-11 02:48:45 +00:00
ObjectFile * objectFile = exe_module - > GetObjectFile ( ) ;
2011-03-07 23:44:08 +00:00
if ( ! objectFile )
{
2011-08-10 17:58:11 +00:00
if ( log )
2012-04-13 23:11:52 +00:00
log - > Printf ( " ThreadPlanCallFunction(%p): Could not find object file for module \" %s \" . " ,
this , exe_module - > GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
2012-04-13 20:38:13 +00:00
return false ;
2011-03-07 23:44:08 +00:00
}
m_start_addr = objectFile - > GetEntryPointAddress ( ) ;
if ( ! m_start_addr . IsValid ( ) )
{
2011-08-10 17:58:11 +00:00
if ( log )
2012-04-13 23:11:52 +00:00
log - > Printf ( " ThreadPlanCallFunction(%p): Could not find entry point address for executable module \" %s \" . " ,
this , exe_module - > GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
2012-04-13 20:38:13 +00:00
return false ;
2011-03-07 23:44:08 +00:00
}
}
2010-06-08 16:52:24 +00:00
2012-04-13 20:38:13 +00:00
start_load_addr = m_start_addr . GetLoadAddress ( target_sp . get ( ) ) ;
2011-03-07 23:44:08 +00:00
2011-01-20 02:03:18 +00:00
// Checkpoint the thread state so we can restore it later.
2011-01-22 01:27:23 +00:00
if ( log & & log - > GetVerbose ( ) )
ReportRegisterState ( " About to checkpoint thread before function call. Original register state was: " ) ;
2011-01-20 02:03:18 +00:00
if ( ! thread . CheckpointThreadState ( m_stored_thread_state ) )
{
if ( log )
2012-04-13 23:11:52 +00:00
log - > Printf ( " ThreadPlanCallFunction(%p): Setting up ThreadPlanCallFunction, failed to checkpoint thread state. " , this ) ;
2012-04-13 20:38:13 +00:00
return false ;
2011-01-20 02:03:18 +00:00
}
// Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
thread . SetStopInfoToNothing ( ) ;
2012-04-13 20:38:13 +00:00
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 ) ,
2012-05-11 18:43:38 +00:00
m_stop_address ( LLDB_INVALID_ADDRESS ) ,
m_discard_on_error ( discard_on_error )
2012-04-13 20:38:13 +00:00
{
lldb : : addr_t start_load_addr ;
ABI * abi ;
lldb : : addr_t function_load_addr ;
2012-05-11 18:43:38 +00:00
if ( ! ConstructorSetup ( thread , abi , start_load_addr , function_load_addr ) )
2012-04-13 20:38:13 +00:00
return ;
2010-06-08 16:52:24 +00:00
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 02:14:56 +00:00
if ( this_arg & & cmd_arg )
{
if ( ! abi - > PrepareTrivialCall ( thread ,
m_function_sp ,
2012-04-13 20:38:13 +00:00
function_load_addr ,
2011-05-14 01:50:35 +00:00
start_load_addr ,
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 02:14:56 +00:00
this_arg ,
cmd_arg ,
2011-05-14 01:50:35 +00:00
& arg ) )
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 02:14:56 +00:00
return ;
}
else if ( this_arg )
{
if ( ! abi - > PrepareTrivialCall ( thread ,
m_function_sp ,
2012-04-13 20:38:13 +00:00
function_load_addr ,
2011-05-14 01:50:35 +00:00
start_load_addr ,
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 02:14:56 +00:00
this_arg ,
2011-05-14 01:50:35 +00:00
& arg ) )
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 02:14:56 +00:00
return ;
}
else
{
if ( ! abi - > PrepareTrivialCall ( thread ,
m_function_sp ,
2012-04-13 20:38:13 +00:00
function_load_addr ,
2011-05-14 01:50:35 +00:00
start_load_addr ,
& arg ) )
return ;
}
ReportRegisterState ( " Function call was set up. Register state was: " ) ;
m_valid = true ;
}
ThreadPlanCallFunction : : ThreadPlanCallFunction ( Thread & thread ,
Address & function ,
2011-12-22 19:12:40 +00:00
const ClangASTType & return_type ,
2011-05-14 01:50:35 +00:00
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 ) ,
2011-08-12 23:34:31 +00:00
m_function_addr ( function ) ,
2011-06-03 20:41:09 +00:00
m_function_sp ( NULL ) ,
2011-12-22 19:12:40 +00:00
m_return_type ( return_type ) ,
2012-04-13 20:38:13 +00:00
m_takedown_done ( false ) ,
m_stop_address ( LLDB_INVALID_ADDRESS )
2011-05-14 01:50:35 +00:00
{
2012-04-13 20:38:13 +00:00
lldb : : addr_t start_load_addr ;
ABI * abi ;
lldb : : addr_t function_load_addr ;
2012-05-11 18:43:38 +00:00
if ( ! ConstructorSetup ( thread , abi , start_load_addr , function_load_addr ) )
2012-02-21 00:09:25 +00:00
return ;
2011-05-14 01:50:35 +00:00
if ( ! abi - > PrepareTrivialCall ( thread ,
2012-04-13 20:38:13 +00:00
m_function_sp ,
function_load_addr ,
2011-05-14 01:50:35 +00:00
start_load_addr ,
arg1_ptr ,
arg2_ptr ,
arg3_ptr ,
arg4_ptr ,
arg5_ptr ,
arg6_ptr ) )
{
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 02:14:56 +00:00
return ;
}
2010-06-08 16:52:24 +00:00
2011-01-22 01:27:23 +00:00
ReportRegisterState ( " Function call was set up. Register state was: " ) ;
m_valid = true ;
}
ThreadPlanCallFunction : : ~ ThreadPlanCallFunction ( )
{
2012-05-10 01:35:39 +00:00
DoTakedown ( true ) ;
2011-01-22 01:27:23 +00:00
}
void
ThreadPlanCallFunction : : ReportRegisterState ( const char * message )
{
2011-05-19 03:54:16 +00:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_STEP | LIBLLDB_LOG_VERBOSE ) ) ;
2010-11-08 03:49:50 +00:00
if ( log )
{
2011-05-19 03:54:16 +00:00
StreamString strm ;
2011-01-06 22:15:06 +00:00
RegisterContext * reg_ctx = m_thread . GetRegisterContext ( ) . get ( ) ;
2011-01-22 01:27:23 +00:00
log - > PutCString ( message ) ;
2011-05-19 03:54:16 +00:00
RegisterValue reg_value ;
for ( uint32_t reg_idx = 0 , num_registers = reg_ctx - > GetRegisterCount ( ) ;
reg_idx < num_registers ;
+ + reg_idx )
2010-11-08 03:49:50 +00:00
{
2011-05-19 03:54:16 +00:00
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 ( ) ;
}
2010-11-08 03:49:50 +00:00
}
2011-05-19 03:54:16 +00:00
log - > PutCString ( strm . GetData ( ) ) ;
2010-11-08 03:49:50 +00:00
}
2010-11-04 01:51:38 +00:00
}
void
2012-05-10 01:35:39 +00:00
ThreadPlanCallFunction : : DoTakedown ( bool success )
2010-11-04 01:51:38 +00:00
{
2012-04-13 23:11:52 +00:00
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 ;
}
2011-01-22 01:27:23 +00:00
if ( ! m_takedown_done )
2011-01-20 02:03:18 +00:00
{
2012-05-10 01:35:39 +00:00
if ( success )
2011-05-15 01:25:55 +00:00
{
2012-05-10 01:35:39 +00:00
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 ) ;
}
2011-05-15 01:25:55 +00:00
}
2011-01-22 01:27:23 +00:00
if ( log )
2012-04-13 23:11:52 +00:00
log - > Printf ( " ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4llx, m_valid: %d complete: %d. \n " , this , m_thread . GetID ( ) , m_valid , IsPlanComplete ( ) ) ;
2011-01-22 01:27:23 +00:00
m_takedown_done = true ;
2011-11-01 02:46:54 +00:00
m_stop_address = m_thread . GetStackFrameAtIndex ( 0 ) - > GetRegisterContext ( ) - > GetPC ( ) ;
2011-05-17 01:10:11 +00:00
m_real_stop_info_sp = GetPrivateStopReason ( ) ;
2011-01-20 02:03:18 +00:00
m_thread . RestoreThreadStateFromCheckpoint ( m_stored_thread_state ) ;
2012-05-10 01:35:39 +00:00
SetPlanComplete ( success ) ;
2011-01-20 02:03:18 +00:00
ClearBreakpoints ( ) ;
2011-01-22 01:27:23 +00:00
if ( log & & log - > GetVerbose ( ) )
ReportRegisterState ( " Restoring thread state after function call. Restored register state: " ) ;
2011-01-26 19:13:09 +00:00
2011-01-22 01:27:23 +00:00
}
else
{
if ( log )
2012-04-13 23:11:52 +00:00
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 ( ) ) ;
2011-01-20 02:03:18 +00:00
}
2010-06-08 16:52:24 +00:00
}
2011-01-18 01:58:06 +00:00
void
ThreadPlanCallFunction : : WillPop ( )
{
2012-05-10 01:35:39 +00:00
DoTakedown ( true ) ;
2011-01-18 01:58:06 +00:00
}
2010-06-08 16:52:24 +00:00
void
2011-05-14 01:50:35 +00:00
ThreadPlanCallFunction : : GetDescription ( Stream * s , DescriptionLevel level )
2010-06-08 16:52:24 +00:00
{
2011-05-14 01:50:35 +00:00
if ( level = = eDescriptionLevelBrief )
2010-06-08 16:52:24 +00:00
{
s - > Printf ( " Function call thread plan " ) ;
}
else
{
2012-02-21 00:09:25 +00:00
TargetSP target_sp ( m_thread . CalculateTarget ( ) ) ;
s - > Printf ( " Thread plan to call 0x%llx " , m_function_addr . GetLoadAddress ( target_sp . get ( ) ) ) ;
2010-06-08 16:52:24 +00:00
}
}
bool
ThreadPlanCallFunction : : ValidatePlan ( Stream * error )
{
if ( ! m_valid )
return false ;
return true ;
}
bool
ThreadPlanCallFunction : : PlanExplainsStop ( )
2010-11-03 01:37:52 +00:00
{
2011-05-17 01:10:11 +00:00
m_real_stop_info_sp = GetPrivateStopReason ( ) ;
2010-10-26 00:27:45 +00:00
// If our subplan knows why we stopped, even if it's done (which would forward the question to us)
// we answer yes.
The implementation of categories is now synchronization safe
Code cleanup:
- The Format Manager implementation is now split between two files: FormatClasses.{h|cpp} where the
actual formatter classes (ValueFormat, SummaryFormat, ...) are implemented and
FormatManager.{h|cpp} where the infrastructure classes (FormatNavigator, FormatManager, ...)
are contained. The wrapper code always remains in Debugger.{h|cpp}
- Several leftover fields, methods and comments from previous design choices have been removed
type category subcommands (enable, disable, delete) now can take a list of category names as input
- for type category enable, saying "enable A B C" is the same as saying
enable C
enable B
enable A
(the ordering is relevant in enabling categories, and it is expected that a user typing
enable A B C wants to look into category A, then into B, then into C and not the other
way round)
- for the other two commands, the order is not really relevant (however, the same inverted ordering
is used for consistency)
llvm-svn: 135494
2011-07-19 18:03:25 +00:00
if ( m_subplan_sp . get ( ) ! = NULL & & m_subplan_sp - > PlanExplainsStop ( ) )
2010-10-26 00:27:45 +00:00
return true ;
2010-10-19 22:24:06 +00:00
2010-11-03 19:36:28 +00:00
// Check if the breakpoint is one of ours.
2012-05-10 01:35:39 +00:00
StopReason stop_reason ;
if ( ! m_real_stop_info_sp )
stop_reason = eStopReasonNone ;
else
stop_reason = m_real_stop_info_sp - > GetStopReason ( ) ;
if ( stop_reason = = eStopReasonBreakpoint & & BreakpointsExplainStop ( ) )
2010-11-03 19:36:28 +00:00
return true ;
2010-10-26 00:27:45 +00:00
// If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
2012-05-11 18:43:38 +00:00
if ( ! m_discard_on_error )
2010-10-26 00:27:45 +00:00
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.
2010-11-03 01:37:52 +00:00
2012-05-10 01:35:39 +00:00
if ( stop_reason = = eStopReasonBreakpoint )
2010-10-26 00:27:45 +00:00
{
2012-02-21 00:09:25 +00:00
ProcessSP process_sp ( m_thread . CalculateProcess ( ) ) ;
2011-05-17 01:10:11 +00:00
uint64_t break_site_id = m_real_stop_info_sp - > GetValue ( ) ;
2012-02-21 00:09:25 +00:00
BreakpointSiteSP bp_site_sp ;
if ( process_sp )
bp_site_sp = process_sp - > GetBreakpointSiteList ( ) . FindByID ( break_site_id ) ;
2010-10-26 00:27:45 +00:00
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 + + )
{
2010-11-03 01:37:52 +00:00
Breakpoint & bp = bp_site_sp - > GetOwnerAtIndex ( i ) - > GetBreakpoint ( ) ;
if ( ! bp . IsInternal ( ) )
2010-10-26 00:27:45 +00:00
{
is_internal = false ;
break ;
}
}
if ( is_internal )
return false ;
}
2012-05-11 18:43:38 +00:00
if ( m_discard_on_error )
{
DoTakedown ( false ) ;
return true ;
}
else
return false ;
2010-10-26 00:27:45 +00:00
}
else
{
// If the subplan is running, any crashes are attributable to us.
2011-01-26 19:13:09 +00:00
// 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.
2012-05-10 01:35:39 +00:00
if ( m_subplan_sp ! = NULL )
{
2012-05-11 18:43:38 +00:00
if ( m_discard_on_error )
2012-05-10 01:35:39 +00:00
{
DoTakedown ( false ) ;
return true ;
}
else
return false ;
}
else
return false ;
2010-10-26 00:27:45 +00:00
}
2010-06-08 16:52:24 +00:00
}
bool
ThreadPlanCallFunction : : ShouldStop ( Event * event_ptr )
{
2012-05-11 23:47:32 +00:00
if ( IsPlanComplete ( ) | | PlanExplainsStop ( ) )
2010-06-08 16:52:24 +00:00
{
2011-01-22 01:27:23 +00:00
ReportRegisterState ( " Function completed. Register state was: " ) ;
2010-07-31 01:32:05 +00:00
2012-05-10 01:35:39 +00:00
DoTakedown ( true ) ;
2010-11-03 01:37:52 +00:00
2010-06-08 16:52:24 +00:00
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
2010-11-11 19:26:09 +00:00
ThreadPlanCallFunction : : GetPlanRunState ( )
2010-06-08 16:52:24 +00:00
{
return eStateRunning ;
}
void
ThreadPlanCallFunction : : DidPush ( )
{
2010-10-26 00:31:56 +00:00
//#define SINGLE_STEP_EXPRESSIONS
# ifndef SINGLE_STEP_EXPRESSIONS
2010-06-08 16:52:24 +00:00
m_subplan_sp . reset ( new ThreadPlanRunToAddress ( m_thread , m_start_addr , m_stop_other_threads ) ) ;
m_thread . QueueThreadPlan ( m_subplan_sp , false ) ;
2011-01-20 02:03:18 +00:00
m_subplan_sp - > SetPrivate ( true ) ;
2010-10-26 00:31:56 +00:00
# endif
2010-06-08 16:52:24 +00:00
}
bool
ThreadPlanCallFunction : : WillStop ( )
{
return true ;
}
bool
ThreadPlanCallFunction : : MischiefManaged ( )
{
if ( IsPlanComplete ( ) )
{
2010-11-06 01:53:30 +00:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_STEP ) ) ;
2010-06-08 16:52:24 +00:00
if ( log )
2012-04-13 23:11:52 +00:00
log - > Printf ( " ThreadPlanCallFunction(%p): Completed call function plan. " , this ) ;
2010-06-08 16:52:24 +00:00
ThreadPlan : : MischiefManaged ( ) ;
return true ;
}
else
{
return false ;
}
}
2010-11-03 01:37:52 +00:00
void
ThreadPlanCallFunction : : SetBreakpoints ( )
{
2012-02-21 00:09:25 +00:00
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 ) ;
2010-11-03 01:37:52 +00:00
2012-02-21 00:09:25 +00:00
if ( m_cxx_language_runtime )
m_cxx_language_runtime - > SetExceptionBreakpoints ( ) ;
if ( m_objc_language_runtime )
m_objc_language_runtime - > SetExceptionBreakpoints ( ) ;
}
2010-11-03 01:37:52 +00:00
}
void
ThreadPlanCallFunction : : ClearBreakpoints ( )
{
2010-11-03 22:19:38 +00:00
if ( m_cxx_language_runtime )
m_cxx_language_runtime - > ClearExceptionBreakpoints ( ) ;
if ( m_objc_language_runtime )
m_objc_language_runtime - > ClearExceptionBreakpoints ( ) ;
2010-11-03 01:37:52 +00:00
}
2010-11-03 19:36:28 +00:00
bool
ThreadPlanCallFunction : : BreakpointsExplainStop ( )
{
2011-05-14 01:50:35 +00:00
StopInfoSP stop_info_sp = GetPrivateStopReason ( ) ;
2010-11-03 19:36:28 +00:00
2010-11-03 22:19:38 +00:00
if ( m_cxx_language_runtime & &
m_cxx_language_runtime - > ExceptionBreakpointsExplainStop ( stop_info_sp ) )
return true ;
2010-11-03 19:36:28 +00:00
2010-11-03 22:19:38 +00:00
if ( m_objc_language_runtime & &
m_objc_language_runtime - > ExceptionBreakpointsExplainStop ( stop_info_sp ) )
return true ;
2010-11-03 19:36:28 +00:00
return false ;
}