2010-06-09 00:52:24 +08:00
//===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
2016-02-20 03:33:46 +08:00
// Other libraries and framework includes
// Project includes
2010-06-09 00:52:24 +08:00
# include "CommandObjectBreakpointCommand.h"
# include "CommandObjectBreakpoint.h"
2016-09-07 04:57:50 +08:00
# include "lldb/Breakpoint/Breakpoint.h"
# include "lldb/Breakpoint/BreakpointIDList.h"
# include "lldb/Breakpoint/BreakpointLocation.h"
# include "lldb/Breakpoint/StoppointCallbackContext.h"
2014-01-28 07:43:24 +08:00
# include "lldb/Core/IOHandler.h"
2016-09-07 04:57:50 +08:00
# include "lldb/Core/State.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/Thread.h"
2016-09-14 01:53:38 +08:00
# include "llvm/ADT/STLExtras.h"
2010-06-09 00:52:24 +08:00
using namespace lldb ;
using namespace lldb_private ;
//-------------------------------------------------------------------------
// CommandObjectBreakpointCommandAdd
//-------------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointCommandAdd : public CommandObjectParsed ,
public IOHandlerDelegateMultiline {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointCommandAdd ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " add " ,
" Add LLDB commands to a breakpoint, to be executed "
" whenever the breakpoint is hit. "
" If no breakpoint is specified, adds the "
" commands to the last created breakpoint. " ,
nullptr ) ,
IOHandlerDelegateMultiline ( " DONE " ,
IOHandlerDelegate : : Completion : : LLDBCommand ) ,
m_options ( ) {
SetHelpLong (
R " (
2015-07-14 13:48:36 +08:00
General information about entering breakpoint commands
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-09-07 04:57:50 +08:00
) "
" This command will prompt for commands to be executed when the specified \
2015-07-14 13:48:36 +08:00
breakpoint is hit . Each command is typed on its own line following the ' > ' \
2016-09-07 04:57:50 +08:00
prompt until ' DONE ' is entered . "
R " (
2015-07-14 13:48:36 +08:00
2016-09-07 04:57:50 +08:00
) "
" Syntactic errors may not be detected when initially entered, and many \
2015-07-14 13:48:36 +08:00
malformed commands can silently fail when executed . If your breakpoint commands \
2016-09-07 04:57:50 +08:00
do not appear to be executing , double - check the command syntax . "
R " (
2015-07-14 13:48:36 +08:00
2016-09-07 04:57:50 +08:00
) "
" Note: You may enter any debugger command exactly as you would at the debugger \
2015-07-14 13:48:36 +08:00
prompt . There is no limit to the number of commands supplied , but do NOT enter \
2016-09-07 04:57:50 +08:00
more than one command per line . "
R " (
2015-07-14 13:48:36 +08:00
Special information about PYTHON breakpoint commands
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-09-07 04:57:50 +08:00
) "
" You may enter either one or more lines of Python, including function \
2015-07-14 13:48:36 +08:00
definitions or calls to functions that will have been imported by the time \
the code executes . Single line breakpoint commands will be interpreted ' as is ' \
when the breakpoint is hit . Multiple lines of Python will be wrapped in a \
2016-09-07 04:57:50 +08:00
generated function , and a call to the function will be attached to the breakpoint . "
R " (
2015-07-14 13:48:36 +08:00
This auto - generated function is passed in three arguments :
frame : an lldb . SBFrame object for the frame which hit breakpoint .
bp_loc : an lldb . SBBreakpointLocation object that represents the breakpoint location that was hit .
dict : the python session dictionary hit .
2016-09-07 04:57:50 +08:00
) "
" When specifying a python function with the --python-function option, you need \
to supply the function name prepended by the module name : "
R " (
2015-07-14 13:48:36 +08:00
- - python - function myutils . breakpoint_callback
The function itself must have the following prototype :
def breakpoint_callback ( frame , bp_loc , dict ) :
# Your code goes here
2016-09-07 04:57:50 +08:00
) "
" The arguments are the same as the arguments passed to generated functions as \
2015-07-14 13:48:36 +08:00
described above . Note that the global variable ' lldb . frame ' will NOT be updated when \
this function is called , so be sure to use the ' frame ' argument . The ' frame ' argument \
can get you to the thread via frame . GetThread ( ) , the thread can get you to the \
process via thread . GetProcess ( ) , and the process can get you back to the target \
2016-09-07 04:57:50 +08:00
via process . GetTarget ( ) . "
R " (
2015-07-14 13:48:36 +08:00
2016-09-07 04:57:50 +08:00
) "
" Important Note: As Python code gets collected into functions, access to global \
2015-07-14 13:48:36 +08:00
variables requires explicit scoping using the ' global ' keyword . Be sure to use correct \
2016-09-07 04:57:50 +08:00
Python syntax , including indentation , when entering Python breakpoint commands . "
R " (
2015-07-14 13:48:36 +08:00
Example Python one - line breakpoint command :
( lldb ) breakpoint command add - s python 1
Enter your Python command ( s ) . Type ' DONE ' to end .
> print " Hit this breakpoint! "
> DONE
As a convenience , this also works for a short Python one - liner :
( lldb ) breakpoint command add - s python 1 - o ' import time ; print time . asctime ( ) '
( lldb ) run
Launching ' . . . / a . out ' ( x86_64 )
( lldb ) Fri Sep 10 12 : 17 : 45 2010
Process 21778 Stopped
* thread # 1 : tid = 0x2e03 , 0x0000000100000de8 a . out ` c + 7 at main . c : 39 , stop reason = breakpoint 1.1 , queue = com . apple . main - thread
36
37 int c ( int val )
38 {
39 - > return val + 3 ;
40 }
41
42 int main ( int argc , char const * argv [ ] )
Example multiple line Python breakpoint command :
( lldb ) breakpoint command add - s p 1
Enter your Python command ( s ) . Type ' DONE ' to end .
> global bp_count
> bp_count = bp_count + 1
> print " Hit this breakpoint " + repr ( bp_count ) + " times! "
> DONE
Example multiple line Python breakpoint command , using function definition :
( lldb ) breakpoint command add - s python 1
Enter your Python command ( s ) . Type ' DONE ' to end .
> def breakpoint_output ( bp_no ) :
> out_string = " Hit breakpoint number " + repr ( bp_no )
> print out_string
> return True
> breakpoint_output ( 1 )
> DONE
2016-09-07 04:57:50 +08:00
) "
" In this case, since there is a reference to a global variable, \
2015-07-14 13:48:36 +08:00
' bp_count ' , you will also need to make sure ' bp_count ' exists and is \
2016-09-07 04:57:50 +08:00
initialized : "
R " (
2015-07-14 13:48:36 +08:00
( lldb ) script
> > > bp_count = 0
> > > quit ( )
2016-09-07 04:57:50 +08:00
) "
" Your Python code, however organized, can optionally return a value. \
2015-07-14 13:48:36 +08:00
If the returned value is False , that tells LLDB not to stop at the breakpoint \
to which the code is associated . Returning anything other than False , or even \
returning None , or even omitting a return statement entirely , will cause \
2016-09-07 04:57:50 +08:00
LLDB to stop . "
R " (
2015-07-14 13:48:36 +08:00
2016-09-07 04:57:50 +08:00
) "
" Final Note: A warning that no breakpoint command was generated when there \
are no syntax errors may indicate that a function was declared but never called . " );
2010-10-05 06:28:36 +08:00
2016-09-07 04:57:50 +08:00
CommandArgumentEntry arg ;
CommandArgumentData bp_id_arg ;
2010-10-05 06:28:36 +08:00
2016-09-07 04:57:50 +08:00
// Define the first (and only) variant of this arg.
bp_id_arg . arg_type = eArgTypeBreakpointID ;
bp_id_arg . arg_repetition = eArgRepeatOptional ;
2010-10-05 06:28:36 +08:00
2016-09-07 04:57:50 +08:00
// There is only one variant this argument could be; put it into the
// argument entry.
arg . push_back ( bp_id_arg ) ;
2010-10-05 06:28:36 +08:00
2016-09-07 04:57:50 +08:00
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
~ CommandObjectBreakpointCommandAdd ( ) override = default ;
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
Options * GetOptions ( ) override { return & m_options ; }
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
void IOHandlerActivated ( IOHandler & io_handler ) override {
StreamFileSP output_sp ( io_handler . GetOutputStreamFile ( ) ) ;
if ( output_sp ) {
output_sp - > PutCString ( g_reader_instructions ) ;
output_sp - > Flush ( ) ;
2014-01-28 07:43:24 +08:00
}
2016-09-07 04:57:50 +08:00
}
void IOHandlerInputComplete ( IOHandler & io_handler ,
std : : string & line ) override {
io_handler . SetIsDone ( true ) ;
std : : vector < BreakpointOptions * > * bp_options_vec =
( std : : vector < BreakpointOptions * > * ) io_handler . GetUserData ( ) ;
for ( BreakpointOptions * bp_options : * bp_options_vec ) {
if ( ! bp_options )
continue ;
2016-09-14 01:53:38 +08:00
auto cmd_data = llvm : : make_unique < BreakpointOptions : : CommandData > ( ) ;
2016-09-13 07:10:56 +08:00
cmd_data - > user_source . SplitIntoLines ( line . c_str ( ) , line . size ( ) ) ;
2016-09-21 06:54:49 +08:00
bp_options - > SetCommandDataCallback ( cmd_data ) ;
2012-04-05 01:30:31 +08:00
}
2016-09-07 04:57:50 +08:00
}
void CollectDataForBreakpointCommandCallback (
std : : vector < BreakpointOptions * > & bp_options_vec ,
CommandReturnObject & result ) {
m_interpreter . GetLLDBCommandsFromIOHandler (
" > " , // Prompt
* this , // IOHandlerDelegate
true , // Run IOHandler in async mode
& bp_options_vec ) ; // Baton for the "io_handler" that will be passed back
// into our IOHandlerDelegate functions
}
/// Set a one-liner as the callback for the breakpoint.
void
SetBreakpointCommandCallback ( std : : vector < BreakpointOptions * > & bp_options_vec ,
const char * oneliner ) {
for ( auto bp_options : bp_options_vec ) {
2016-09-14 01:53:38 +08:00
auto cmd_data = llvm : : make_unique < BreakpointOptions : : CommandData > ( ) ;
2016-09-07 04:57:50 +08:00
// It's necessary to set both user_source and script_source to the
// oneliner.
// The former is used to generate callback description (as in breakpoint
// command list)
// while the latter is used for Python to interpret during the actual
// callback.
2016-09-13 07:10:56 +08:00
cmd_data - > user_source . AppendString ( oneliner ) ;
cmd_data - > script_source . assign ( oneliner ) ;
cmd_data - > stop_on_error = m_options . m_stop_on_error ;
2016-09-07 04:57:50 +08:00
2016-09-21 06:54:49 +08:00
bp_options - > SetCommandDataCallback ( cmd_data ) ;
2014-01-28 07:43:24 +08:00
}
2016-09-07 04:57:50 +08:00
}
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_use_commands ( false ) , m_use_script_language ( false ) ,
m_script_language ( eScriptLanguageNone ) , m_use_one_liner ( false ) ,
m_one_liner ( ) , m_function_name ( ) { }
~ CommandOptions ( ) override = default ;
Error SetOptionValue ( uint32_t option_idx , const char * option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
2016-09-20 01:54:06 +08:00
auto option_strref = llvm : : StringRef : : withNullAsEmpty ( option_arg ) ;
2016-09-07 04:57:50 +08:00
switch ( short_option ) {
case ' o ' :
m_use_one_liner = true ;
m_one_liner = option_arg ;
break ;
case ' s ' :
m_script_language = ( lldb : : ScriptLanguage ) Args : : StringToOptionEnum (
option_arg , g_option_table [ option_idx ] . enum_values ,
eScriptLanguageNone , error ) ;
if ( m_script_language = = eScriptLanguagePython | |
m_script_language = = eScriptLanguageDefault ) {
m_use_script_language = true ;
} else {
m_use_script_language = false ;
2012-06-09 05:56:10 +08:00
}
2016-09-07 04:57:50 +08:00
break ;
case ' e ' : {
bool success = false ;
2016-09-20 01:54:06 +08:00
m_stop_on_error = Args : : StringToBoolean ( option_strref , false , & success ) ;
2016-09-07 04:57:50 +08:00
if ( ! success )
error . SetErrorStringWithFormat (
" invalid value for stop-on-error: \" %s \" " , option_arg ) ;
} break ;
case ' F ' :
m_use_one_liner = false ;
m_use_script_language = true ;
m_function_name . assign ( option_arg ) ;
break ;
case ' D ' :
m_use_dummy = true ;
break ;
default :
break ;
}
return error ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_use_commands = true ;
m_use_script_language = false ;
m_script_language = eScriptLanguageNone ;
2016-02-20 03:33:46 +08:00
2016-09-07 04:57:50 +08:00
m_use_one_liner = false ;
m_stop_on_error = true ;
m_one_liner . clear ( ) ;
m_function_name . clear ( ) ;
m_use_dummy = false ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
const OptionDefinition * GetDefinitions ( ) override { return g_option_table ; }
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
// Options table: Required for subclasses of Options.
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
static OptionDefinition g_option_table [ ] ;
2010-09-11 08:18:09 +08:00
2016-09-07 04:57:50 +08:00
// Instance variables to hold the values for command options.
2010-09-11 08:18:09 +08:00
2016-09-07 04:57:50 +08:00
bool m_use_commands ;
bool m_use_script_language ;
lldb : : ScriptLanguage m_script_language ;
2010-09-11 08:18:09 +08:00
2016-09-07 04:57:50 +08:00
// Instance variables to hold the values for one_liner options.
bool m_use_one_liner ;
std : : string m_one_liner ;
bool m_stop_on_error ;
std : : string m_function_name ;
bool m_use_dummy ;
} ;
2010-09-11 08:18:09 +08:00
2012-06-09 05:56:10 +08:00
protected :
2016-09-07 04:57:50 +08:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( m_options . m_use_dummy ) ;
if ( target = = nullptr ) {
result . AppendError ( " There is not a current executable; there are no "
" breakpoints to which to add commands " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
size_t num_breakpoints = breakpoints . GetSize ( ) ;
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
if ( num_breakpoints = = 0 ) {
result . AppendError ( " No breakpoints exist to have commands added " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
if ( ! m_options . m_use_script_language & &
! m_options . m_function_name . empty ( ) ) {
result . AppendError ( " need to enable scripting to have a function run as a "
" breakpoint command " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointOrLocationIDs (
command , target , result , & valid_bp_ids ) ;
m_bp_options_vec . clear ( ) ;
if ( result . Succeeded ( ) ) {
const size_t count = valid_bp_ids . GetSize ( ) ;
for ( size_t i = 0 ; i < count ; + + i ) {
BreakpointID cur_bp_id = valid_bp_ids . GetBreakpointIDAtIndex ( i ) ;
if ( cur_bp_id . GetBreakpointID ( ) ! = LLDB_INVALID_BREAK_ID ) {
Breakpoint * bp =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
BreakpointOptions * bp_options = nullptr ;
if ( cur_bp_id . GetLocationID ( ) = = LLDB_INVALID_BREAK_ID ) {
// This breakpoint does not have an associated location.
bp_options = bp - > GetOptions ( ) ;
} else {
BreakpointLocationSP bp_loc_sp (
bp - > FindLocationByID ( cur_bp_id . GetLocationID ( ) ) ) ;
// This breakpoint does have an associated location.
// Get its breakpoint options.
if ( bp_loc_sp )
bp_options = bp_loc_sp - > GetLocationOptions ( ) ;
}
if ( bp_options )
m_bp_options_vec . push_back ( bp_options ) ;
2010-11-20 04:47:54 +08:00
}
2016-09-07 04:57:50 +08:00
}
// If we are using script language, get the script interpreter
// in order to set or collect command callback. Otherwise, call
// the methods associated with this object.
if ( m_options . m_use_script_language ) {
ScriptInterpreter * script_interp = m_interpreter . GetScriptInterpreter ( ) ;
// Special handling for one-liner specified inline.
if ( m_options . m_use_one_liner ) {
script_interp - > SetBreakpointCommandCallback (
m_bp_options_vec , m_options . m_one_liner . c_str ( ) ) ;
} else if ( ! m_options . m_function_name . empty ( ) ) {
script_interp - > SetBreakpointCommandCallbackFunction (
m_bp_options_vec , m_options . m_function_name . c_str ( ) ) ;
} else {
script_interp - > CollectDataForBreakpointCommandCallback (
m_bp_options_vec , result ) ;
}
} else {
// Special handling for one-liner specified inline.
if ( m_options . m_use_one_liner )
SetBreakpointCommandCallback ( m_bp_options_vec ,
m_options . m_one_liner . c_str ( ) ) ;
else
CollectDataForBreakpointCommandCallback ( m_bp_options_vec , result ) ;
}
2010-06-09 00:52:24 +08:00
}
2016-09-07 04:57:50 +08:00
return result . Succeeded ( ) ;
}
2012-06-09 05:56:10 +08:00
private :
2016-09-07 04:57:50 +08:00
CommandOptions m_options ;
std : : vector < BreakpointOptions * > m_bp_options_vec ; // This stores the
// breakpoint options that
// we are currently
// collecting commands for. In the CollectData... calls we need
// to hand this off to the IOHandler, which may run asynchronously.
// So we have to have some way to keep it alive, and not leak it.
// Making it an ivar of the command object, which never goes away
// achieves this. Note that if we were able to run
// the same command concurrently in one interpreter we'd have to
// make this "per invocation". But there are many more reasons
// why it is not in general safe to do that in lldb at present,
// so it isn't worthwhile to come up with a more complex mechanism
// to address this particular weakness right now.
static const char * g_reader_instructions ;
2012-06-09 05:56:10 +08:00
} ;
2016-09-07 04:57:50 +08:00
const char * CommandObjectBreakpointCommandAdd : : g_reader_instructions =
" Enter your debugger command(s). Type 'DONE' to end. \n " ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
// FIXME: "script-type" needs to have its contents determined dynamically, so
// somebody can add a new scripting
// language to lldb and have it pickable here without having to change this
// enumeration by hand and rebuild lldb proper.
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
static OptionEnumValueElement g_script_option_enumeration [ 4 ] = {
{ eScriptLanguageNone , " command " ,
" Commands are in the lldb command interpreter language " } ,
{ eScriptLanguagePython , " python " , " Commands are in the Python language. " } ,
{ eSortOrderByName , " default-script " ,
" Commands are in the default scripting language. " } ,
{ 0 , nullptr , nullptr } } ;
2012-06-09 05:56:10 +08:00
OptionDefinition
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointCommandAdd : : CommandOptions : : g_option_table [ ] = {
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_1 , false , " one-liner " , ' o ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeOneLiner , " Specify a one-line breakpoint command inline. Be sure to surround it with quotes. " } ,
{ LLDB_OPT_SET_ALL , false , " stop-on-error " , ' e ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Specify whether breakpoint command execution should terminate on error. " } ,
{ LLDB_OPT_SET_ALL , false , " script-type " , ' s ' , OptionParser : : eRequiredArgument , nullptr , g_script_option_enumeration , 0 , eArgTypeNone , " Specify the language for the commands - if none is specified, the lldb command interpreter will be used. " } ,
{ LLDB_OPT_SET_2 , false , " python-function " , ' F ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypePythonFunction , " Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate. " } ,
{ LLDB_OPT_SET_ALL , false , " dummy-breakpoints " , ' D ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2016-09-07 04:57:50 +08:00
// clang-format on
2012-06-09 05:56:10 +08:00
} ;
2010-06-09 00:52:24 +08:00
//-------------------------------------------------------------------------
2011-05-22 15:14:46 +08:00
// CommandObjectBreakpointCommandDelete
2010-06-09 00:52:24 +08:00
//-------------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointCommandDelete : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointCommandDelete ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " delete " ,
2016-02-20 03:33:46 +08:00
" Delete the set of commands from a breakpoint. " ,
nullptr ) ,
2016-09-07 04:57:50 +08:00
m_options ( ) {
CommandArgumentEntry arg ;
CommandArgumentData bp_id_arg ;
2010-10-05 06:28:36 +08:00
2016-09-07 04:57:50 +08:00
// Define the first (and only) variant of this arg.
bp_id_arg . arg_type = eArgTypeBreakpointID ;
bp_id_arg . arg_repetition = eArgRepeatPlain ;
2010-10-05 06:28:36 +08:00
2016-09-07 04:57:50 +08:00
// There is only one variant this argument could be; put it into the
// argument entry.
arg . push_back ( bp_id_arg ) ;
2010-10-05 06:28:36 +08:00
2016-09-07 04:57:50 +08:00
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
~ CommandObjectBreakpointCommandDelete ( ) override = default ;
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
Options * GetOptions ( ) override { return & m_options ; }
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) , m_use_dummy ( false ) { }
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
~ CommandOptions ( ) override = default ;
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
Error SetOptionValue ( uint32_t option_idx , const char * option_arg ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = m_getopt_table [ option_idx ] . val ;
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
switch ( short_option ) {
case ' D ' :
m_use_dummy = true ;
break ;
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
return error ;
}
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_use_dummy = false ;
}
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
const OptionDefinition * GetDefinitions ( ) override { return g_option_table ; }
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
// Options table: Required for subclasses of Options.
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
static OptionDefinition g_option_table [ ] ;
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
// Instance variables to hold the values for command options.
bool m_use_dummy ;
} ;
2014-12-06 09:28:03 +08:00
2012-06-09 05:56:10 +08:00
protected :
2016-09-07 04:57:50 +08:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( m_options . m_use_dummy ) ;
if ( target = = nullptr ) {
result . AppendError ( " There is not a current executable; there are no "
" breakpoints from which to delete commands " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
size_t num_breakpoints = breakpoints . GetSize ( ) ;
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
if ( num_breakpoints = = 0 ) {
result . AppendError ( " No breakpoints exist to have commands deleted " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
if ( command . GetArgumentCount ( ) = = 0 ) {
result . AppendError (
" No breakpoint specified from which to delete the commands " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointOrLocationIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
const size_t count = valid_bp_ids . GetSize ( ) ;
for ( size_t i = 0 ; i < count ; + + i ) {
BreakpointID cur_bp_id = valid_bp_ids . GetBreakpointIDAtIndex ( i ) ;
if ( cur_bp_id . GetBreakpointID ( ) ! = LLDB_INVALID_BREAK_ID ) {
Breakpoint * bp =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
if ( cur_bp_id . GetLocationID ( ) ! = LLDB_INVALID_BREAK_ID ) {
BreakpointLocationSP bp_loc_sp (
bp - > FindLocationByID ( cur_bp_id . GetLocationID ( ) ) ) ;
if ( bp_loc_sp )
bp_loc_sp - > ClearCallback ( ) ;
else {
result . AppendErrorWithFormat ( " Invalid breakpoint ID: %u.%u. \n " ,
cur_bp_id . GetBreakpointID ( ) ,
cur_bp_id . GetLocationID ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2010-06-09 00:52:24 +08:00
}
2016-09-07 04:57:50 +08:00
} else {
bp - > ClearCallback ( ) ;
}
2010-06-09 00:52:24 +08:00
}
2016-09-07 04:57:50 +08:00
}
2010-06-09 00:52:24 +08:00
}
2016-09-07 04:57:50 +08:00
return result . Succeeded ( ) ;
}
2016-02-20 03:33:46 +08:00
2014-12-06 09:28:03 +08:00
private :
2016-09-07 04:57:50 +08:00
CommandOptions m_options ;
2014-12-06 09:28:03 +08:00
} ;
OptionDefinition
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointCommandDelete : : CommandOptions : : g_option_table [ ] = {
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_1 , false , " dummy-breakpoints " , ' D ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2016-09-07 04:57:50 +08:00
// clang-format on
2012-06-09 05:56:10 +08:00
} ;
2010-06-09 00:52:24 +08:00
//-------------------------------------------------------------------------
// CommandObjectBreakpointCommandList
//-------------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointCommandList : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointCommandList ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " list " , " List the script or set of "
" commands to be executed when "
" the breakpoint is hit. " ,
nullptr ) {
CommandArgumentEntry arg ;
CommandArgumentData bp_id_arg ;
// Define the first (and only) variant of this arg.
bp_id_arg . arg_type = eArgTypeBreakpointID ;
bp_id_arg . arg_repetition = eArgRepeatPlain ;
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
// There is only one variant this argument could be; put it into the
// argument entry.
arg . push_back ( bp_id_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectBreakpointCommandList ( ) override = default ;
2010-06-09 00:52:24 +08:00
2012-06-09 05:56:10 +08:00
protected :
2016-09-07 04:57:50 +08:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " There is not a current executable; there are no "
" breakpoints for which to list commands " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
size_t num_breakpoints = breakpoints . GetSize ( ) ;
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
if ( num_breakpoints = = 0 ) {
result . AppendError ( " No breakpoints exist for which to list commands " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
if ( command . GetArgumentCount ( ) = = 0 ) {
result . AppendError (
" No breakpoint specified for which to list the commands " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointOrLocationIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
const size_t count = valid_bp_ids . GetSize ( ) ;
for ( size_t i = 0 ; i < count ; + + i ) {
BreakpointID cur_bp_id = valid_bp_ids . GetBreakpointIDAtIndex ( i ) ;
if ( cur_bp_id . GetBreakpointID ( ) ! = LLDB_INVALID_BREAK_ID ) {
Breakpoint * bp =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
if ( bp ) {
const BreakpointOptions * bp_options = nullptr ;
if ( cur_bp_id . GetLocationID ( ) ! = LLDB_INVALID_BREAK_ID ) {
BreakpointLocationSP bp_loc_sp (
bp - > FindLocationByID ( cur_bp_id . GetLocationID ( ) ) ) ;
if ( bp_loc_sp )
bp_options = bp_loc_sp - > GetOptionsNoCreate ( ) ;
else {
result . AppendErrorWithFormat ( " Invalid breakpoint ID: %u.%u. \n " ,
cur_bp_id . GetBreakpointID ( ) ,
cur_bp_id . GetLocationID ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else {
bp_options = bp - > GetOptions ( ) ;
2010-06-09 00:52:24 +08:00
}
2016-09-07 04:57:50 +08:00
if ( bp_options ) {
StreamString id_str ;
BreakpointID : : GetCanonicalReference ( & id_str ,
cur_bp_id . GetBreakpointID ( ) ,
cur_bp_id . GetLocationID ( ) ) ;
const Baton * baton = bp_options - > GetBaton ( ) ;
if ( baton ) {
result . GetOutputStream ( ) . Printf ( " Breakpoint %s: \n " ,
id_str . GetData ( ) ) ;
result . GetOutputStream ( ) . IndentMore ( ) ;
baton - > GetDescription ( & result . GetOutputStream ( ) ,
eDescriptionLevelFull ) ;
result . GetOutputStream ( ) . IndentLess ( ) ;
} else {
result . AppendMessageWithFormat (
" Breakpoint %s does not have an associated command. \n " ,
id_str . GetData ( ) ) ;
}
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendErrorWithFormat ( " Invalid breakpoint ID: %u. \n " ,
cur_bp_id . GetBreakpointID ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
}
2012-06-09 05:56:10 +08:00
}
2016-09-07 04:57:50 +08:00
return result . Succeeded ( ) ;
}
2012-06-09 05:56:10 +08:00
} ;
2010-06-09 00:52:24 +08:00
//-------------------------------------------------------------------------
// CommandObjectBreakpointCommand
//-------------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointCommand : : CommandObjectBreakpointCommand (
CommandInterpreter & interpreter )
2016-07-15 06:03:10 +08:00
: CommandObjectMultiword (
2016-09-07 04:57:50 +08:00
interpreter , " command " , " Commands for adding, removing and listing "
" LLDB commands executed when a breakpoint is "
" hit. " ,
" command <sub-command> [<sub-command-options>] <breakpoint-id> " ) {
CommandObjectSP add_command_object (
new CommandObjectBreakpointCommandAdd ( interpreter ) ) ;
CommandObjectSP delete_command_object (
new CommandObjectBreakpointCommandDelete ( interpreter ) ) ;
CommandObjectSP list_command_object (
new CommandObjectBreakpointCommandList ( interpreter ) ) ;
add_command_object - > SetCommandName ( " breakpoint command add " ) ;
delete_command_object - > SetCommandName ( " breakpoint command delete " ) ;
list_command_object - > SetCommandName ( " breakpoint command list " ) ;
LoadSubCommand ( " add " , add_command_object ) ;
LoadSubCommand ( " delete " , delete_command_object ) ;
LoadSubCommand ( " list " , list_command_object ) ;
2010-06-09 00:52:24 +08:00
}
2016-02-20 03:33:46 +08:00
CommandObjectBreakpointCommand : : ~ CommandObjectBreakpointCommand ( ) = default ;