2010-06-09 00:52:24 +08:00
//===-- CommandObjectBreakpoint.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-19 06:39:14 +08:00
# include <vector>
2010-06-09 00:52:24 +08:00
// Other libraries and framework includes
// Project includes
2016-02-19 06:39:14 +08:00
# include "CommandObjectBreakpoint.h"
# include "CommandObjectBreakpointCommand.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Breakpoint/Breakpoint.h"
# include "lldb/Breakpoint/BreakpointIDList.h"
# include "lldb/Breakpoint/BreakpointLocation.h"
# include "lldb/Core/RegularExpression.h"
# include "lldb/Core/StreamString.h"
2016-09-07 04:57:50 +08:00
# include "lldb/Host/StringConvert.h"
# include "lldb/Interpreter/CommandCompletions.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
2016-09-07 04:57:50 +08:00
# include "lldb/Interpreter/OptionValueBoolean.h"
# include "lldb/Interpreter/OptionValueString.h"
# include "lldb/Interpreter/OptionValueUInt64.h"
# include "lldb/Interpreter/Options.h"
2015-09-02 09:06:46 +08:00
# include "lldb/Target/Language.h"
2013-11-04 17:33:30 +08:00
# include "lldb/Target/StackFrame.h"
2016-09-07 04:57:50 +08:00
# include "lldb/Target/Target.h"
2010-06-16 10:00:15 +08:00
# include "lldb/Target/Thread.h"
# include "lldb/Target/ThreadSpec.h"
2010-06-09 00:52:24 +08:00
using namespace lldb ;
using namespace lldb_private ;
2016-09-07 04:57:50 +08:00
static void AddBreakpointDescription ( Stream * s , Breakpoint * bp ,
lldb : : DescriptionLevel level ) {
s - > IndentMore ( ) ;
bp - > GetDescription ( s , level , true ) ;
s - > IndentLess ( ) ;
s - > EOL ( ) ;
2010-06-09 00:52:24 +08:00
}
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
// CommandObjectBreakpointSet
2010-06-09 00:52:24 +08:00
//-------------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointSet : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
typedef enum BreakpointSetType {
eSetTypeInvalid ,
eSetTypeFileAndLine ,
eSetTypeAddress ,
eSetTypeFunctionName ,
eSetTypeFunctionRegexp ,
eSetTypeSourceRegexp ,
eSetTypeException
} BreakpointSetType ;
CommandObjectBreakpointSet ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " breakpoint set " ,
" Sets a breakpoint or set of breakpoints in the executable. " ,
" breakpoint set <cmd-options> " ) ,
m_options ( ) { }
~ CommandObjectBreakpointSet ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_condition ( ) , m_filenames ( ) , m_line_num ( 0 ) , m_column ( 0 ) ,
m_func_names ( ) , m_func_name_type_mask ( eFunctionNameTypeNone ) ,
m_func_regexp ( ) , m_source_text_regexp ( ) , m_modules ( ) , m_load_addr ( ) ,
m_ignore_count ( 0 ) , m_thread_id ( LLDB_INVALID_THREAD_ID ) ,
m_thread_index ( UINT32_MAX ) , m_thread_name ( ) , m_queue_name ( ) ,
m_catch_bp ( false ) , m_throw_bp ( true ) , m_hardware ( false ) ,
m_exception_language ( eLanguageTypeUnknown ) ,
m_language ( lldb : : eLanguageTypeUnknown ) ,
m_skip_prologue ( eLazyBoolCalculate ) , m_one_shot ( false ) ,
m_all_files ( false ) , m_move_to_nearest_code ( eLazyBoolCalculate ) { }
~ 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-17 10:00:02 +08:00
llvm : : StringRef option_strref ( option_arg ? option_arg : " " ) ;
2016-09-07 04:57:50 +08:00
switch ( short_option ) {
case ' a ' : {
m_load_addr = Args : : StringToAddress ( execution_context , option_arg ,
LLDB_INVALID_ADDRESS , & error ) ;
} break ;
case ' A ' :
m_all_files = true ;
break ;
case ' b ' :
m_func_names . push_back ( option_arg ) ;
m_func_name_type_mask | = eFunctionNameTypeBase ;
break ;
case ' C ' : {
bool success ;
m_column = StringConvert : : ToUInt32 ( option_arg , 0 , 0 , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid column number: %s " ,
option_arg ) ;
break ;
}
case ' c ' :
m_condition . assign ( option_arg ) ;
break ;
case ' D ' :
m_use_dummy = true ;
break ;
case ' E ' : {
LanguageType language = Language : : GetLanguageTypeFromString ( option_arg ) ;
switch ( language ) {
case eLanguageTypeC89 :
case eLanguageTypeC :
case eLanguageTypeC99 :
case eLanguageTypeC11 :
m_exception_language = eLanguageTypeC ;
break ;
case eLanguageTypeC_plus_plus :
case eLanguageTypeC_plus_plus_03 :
case eLanguageTypeC_plus_plus_11 :
case eLanguageTypeC_plus_plus_14 :
m_exception_language = eLanguageTypeC_plus_plus ;
break ;
case eLanguageTypeObjC :
m_exception_language = eLanguageTypeObjC ;
break ;
case eLanguageTypeObjC_plus_plus :
error . SetErrorStringWithFormat (
" Set exception breakpoints separately for c++ and objective-c " ) ;
break ;
case eLanguageTypeUnknown :
error . SetErrorStringWithFormat (
" Unknown language type: '%s' for exception breakpoint " ,
option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat (
" Unsupported language type: '%s' for exception breakpoint " ,
option_arg ) ;
}
} break ;
case ' f ' :
m_filenames . AppendIfUnique ( FileSpec ( option_arg , false ) ) ;
break ;
case ' F ' :
m_func_names . push_back ( option_arg ) ;
m_func_name_type_mask | = eFunctionNameTypeFull ;
break ;
case ' h ' : {
bool success ;
2016-09-20 01:54:06 +08:00
m_catch_bp = Args : : StringToBoolean ( option_strref , true , & success ) ;
2016-09-07 04:57:50 +08:00
if ( ! success )
error . SetErrorStringWithFormat (
" Invalid boolean value for on-catch option: '%s' " , option_arg ) ;
} break ;
case ' H ' :
m_hardware = true ;
break ;
case ' i ' :
m_ignore_count = StringConvert : : ToUInt32 ( option_arg , UINT32_MAX , 0 ) ;
if ( m_ignore_count = = UINT32_MAX )
error . SetErrorStringWithFormat ( " invalid ignore count '%s' " ,
option_arg ) ;
break ;
case ' K ' : {
bool success ;
bool value ;
2016-09-20 01:54:06 +08:00
value = Args : : StringToBoolean ( option_strref , true , & success ) ;
2016-09-07 04:57:50 +08:00
if ( value )
m_skip_prologue = eLazyBoolYes ;
else
m_skip_prologue = eLazyBoolNo ;
if ( ! success )
error . SetErrorStringWithFormat (
" Invalid boolean value for skip prologue option: '%s' " ,
option_arg ) ;
} break ;
case ' l ' : {
bool success ;
m_line_num = StringConvert : : ToUInt32 ( option_arg , 0 , 0 , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " invalid line number: %s. " ,
option_arg ) ;
break ;
}
case ' L ' :
m_language = Language : : GetLanguageTypeFromString ( option_arg ) ;
if ( m_language = = eLanguageTypeUnknown )
error . SetErrorStringWithFormat (
" Unknown language type: '%s' for breakpoint " , option_arg ) ;
break ;
case ' m ' : {
bool success ;
bool value ;
2016-09-20 01:54:06 +08:00
value = Args : : StringToBoolean ( option_strref , true , & success ) ;
2016-09-07 04:57:50 +08:00
if ( value )
m_move_to_nearest_code = eLazyBoolYes ;
else
m_move_to_nearest_code = eLazyBoolNo ;
if ( ! success )
error . SetErrorStringWithFormat (
" Invalid boolean value for move-to-nearest-code option: '%s' " ,
option_arg ) ;
break ;
}
case ' M ' :
m_func_names . push_back ( option_arg ) ;
m_func_name_type_mask | = eFunctionNameTypeMethod ;
break ;
case ' n ' :
m_func_names . push_back ( option_arg ) ;
m_func_name_type_mask | = eFunctionNameTypeAuto ;
break ;
2016-09-17 10:00:02 +08:00
case ' N ' : {
if ( BreakpointID : : StringIsBreakpointName ( option_strref , error ) )
2016-09-07 04:57:50 +08:00
m_breakpoint_names . push_back ( option_arg ) ;
break ;
2016-09-17 10:00:02 +08:00
}
2016-09-07 04:57:50 +08:00
case ' R ' : {
lldb : : addr_t tmp_offset_addr ;
tmp_offset_addr =
Args : : StringToAddress ( execution_context , option_arg , 0 , & error ) ;
if ( error . Success ( ) )
m_offset_addr = tmp_offset_addr ;
} break ;
case ' o ' :
m_one_shot = true ;
break ;
case ' O ' :
2016-09-20 01:54:06 +08:00
m_exception_extra_args . AppendArgument ( llvm : : StringRef ( " -O " ) ) ;
m_exception_extra_args . AppendArgument ( option_strref ) ;
2016-09-07 04:57:50 +08:00
break ;
case ' p ' :
m_source_text_regexp . assign ( option_arg ) ;
break ;
case ' q ' :
m_queue_name . assign ( option_arg ) ;
break ;
case ' r ' :
m_func_regexp . assign ( option_arg ) ;
break ;
case ' s ' :
m_modules . AppendIfUnique ( FileSpec ( option_arg , false ) ) ;
break ;
case ' S ' :
m_func_names . push_back ( option_arg ) ;
m_func_name_type_mask | = eFunctionNameTypeSelector ;
break ;
case ' t ' :
m_thread_id =
StringConvert : : ToUInt64 ( option_arg , LLDB_INVALID_THREAD_ID , 0 ) ;
if ( m_thread_id = = LLDB_INVALID_THREAD_ID )
error . SetErrorStringWithFormat ( " invalid thread id string '%s' " ,
option_arg ) ;
break ;
case ' T ' :
m_thread_name . assign ( option_arg ) ;
break ;
case ' w ' : {
bool success ;
2016-09-20 01:54:06 +08:00
m_throw_bp = Args : : StringToBoolean ( option_strref , true , & success ) ;
2016-09-07 04:57:50 +08:00
if ( ! success )
error . SetErrorStringWithFormat (
" Invalid boolean value for on-throw option: '%s' " , option_arg ) ;
} break ;
case ' x ' :
m_thread_index = StringConvert : : ToUInt32 ( option_arg , UINT32_MAX , 0 ) ;
if ( m_thread_id = = UINT32_MAX )
error . SetErrorStringWithFormat ( " invalid thread index string '%s' " ,
option_arg ) ;
break ;
case ' X ' :
m_source_regex_func_names . insert ( option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2012-06-09 05:56:10 +08:00
}
2016-09-07 04:57:50 +08:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_condition . clear ( ) ;
m_filenames . Clear ( ) ;
m_line_num = 0 ;
m_column = 0 ;
m_func_names . clear ( ) ;
m_func_name_type_mask = eFunctionNameTypeNone ;
m_func_regexp . clear ( ) ;
m_source_text_regexp . clear ( ) ;
m_modules . Clear ( ) ;
m_load_addr = LLDB_INVALID_ADDRESS ;
m_offset_addr = 0 ;
m_ignore_count = 0 ;
m_thread_id = LLDB_INVALID_THREAD_ID ;
m_thread_index = UINT32_MAX ;
m_thread_name . clear ( ) ;
m_queue_name . clear ( ) ;
m_catch_bp = false ;
m_throw_bp = true ;
m_hardware = false ;
m_exception_language = eLanguageTypeUnknown ;
m_language = lldb : : eLanguageTypeUnknown ;
m_skip_prologue = eLazyBoolCalculate ;
m_one_shot = false ;
m_use_dummy = false ;
m_breakpoint_names . clear ( ) ;
m_all_files = false ;
m_exception_extra_args . Clear ( ) ;
m_move_to_nearest_code = eLazyBoolCalculate ;
m_source_regex_func_names . clear ( ) ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
const OptionDefinition * GetDefinitions ( ) override { return g_option_table ; }
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
std : : string m_condition ;
FileSpecList m_filenames ;
uint32_t m_line_num ;
uint32_t m_column ;
std : : vector < std : : string > m_func_names ;
std : : vector < std : : string > m_breakpoint_names ;
uint32_t m_func_name_type_mask ;
std : : string m_func_regexp ;
std : : string m_source_text_regexp ;
FileSpecList m_modules ;
lldb : : addr_t m_load_addr ;
lldb : : addr_t m_offset_addr ;
uint32_t m_ignore_count ;
lldb : : tid_t m_thread_id ;
uint32_t m_thread_index ;
std : : string m_thread_name ;
std : : string m_queue_name ;
bool m_catch_bp ;
bool m_throw_bp ;
bool m_hardware ; // Request to use hardware breakpoints
lldb : : LanguageType m_exception_language ;
lldb : : LanguageType m_language ;
LazyBool m_skip_prologue ;
bool m_one_shot ;
bool m_use_dummy ;
bool m_all_files ;
Args m_exception_extra_args ;
LazyBool m_move_to_nearest_code ;
std : : unordered_set < std : : string > m_source_regex_func_names ;
} ;
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( m_options . m_use_dummy ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. Must set target before setting "
" breakpoints (see 'target create' command). " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2012-06-09 05:56:10 +08:00
}
2016-09-07 04:57:50 +08:00
// The following are the various types of breakpoints that could be set:
// 1). -f -l -p [-s -g] (setting breakpoint by source location)
// 2). -a [-s -g] (setting breakpoint by address)
// 3). -n [-s -g] (setting breakpoint by function name)
// 4). -r [-s -g] (setting breakpoint by function name regular
// expression)
// 5). -p -f (setting a breakpoint by comparing a reg-exp
// to source text)
// 6). -E [-w -h] (setting a breakpoint for exceptions for a
// given language.)
BreakpointSetType break_type = eSetTypeInvalid ;
if ( m_options . m_line_num ! = 0 )
break_type = eSetTypeFileAndLine ;
else if ( m_options . m_load_addr ! = LLDB_INVALID_ADDRESS )
break_type = eSetTypeAddress ;
else if ( ! m_options . m_func_names . empty ( ) )
break_type = eSetTypeFunctionName ;
else if ( ! m_options . m_func_regexp . empty ( ) )
break_type = eSetTypeFunctionRegexp ;
else if ( ! m_options . m_source_text_regexp . empty ( ) )
break_type = eSetTypeSourceRegexp ;
else if ( m_options . m_exception_language ! = eLanguageTypeUnknown )
break_type = eSetTypeException ;
Breakpoint * bp = nullptr ;
FileSpec module_spec ;
const bool internal = false ;
// If the user didn't specify skip-prologue, having an offset should turn
// that off.
if ( m_options . m_offset_addr ! = 0 & &
m_options . m_skip_prologue = = eLazyBoolCalculate )
m_options . m_skip_prologue = eLazyBoolNo ;
switch ( break_type ) {
case eSetTypeFileAndLine : // Breakpoint by source position
2012-06-09 05:56:10 +08:00
{
2016-09-07 04:57:50 +08:00
FileSpec file ;
const size_t num_files = m_options . m_filenames . GetSize ( ) ;
if ( num_files = = 0 ) {
if ( ! GetDefaultFile ( target , file , result ) ) {
result . AppendError ( " No file supplied and no default file available. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else if ( num_files > 1 ) {
result . AppendError ( " Only one file at a time is allowed for file and "
" line breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
} else
file = m_options . m_filenames . GetFileSpecAtIndex ( 0 ) ;
// Only check for inline functions if
LazyBool check_inlines = eLazyBoolCalculate ;
bp = target
- > CreateBreakpoint ( & ( m_options . m_modules ) , file ,
m_options . m_line_num , m_options . m_offset_addr ,
check_inlines , m_options . m_skip_prologue ,
internal , m_options . m_hardware ,
m_options . m_move_to_nearest_code )
. get ( ) ;
} break ;
case eSetTypeAddress : // Breakpoint by address
{
// If a shared library has been specified, make an lldb_private::Address
// with the library, and
// use that. That way the address breakpoint will track the load location
// of the library.
size_t num_modules_specified = m_options . m_modules . GetSize ( ) ;
if ( num_modules_specified = = 1 ) {
const FileSpec * file_spec =
m_options . m_modules . GetFileSpecPointerAtIndex ( 0 ) ;
bp = target
- > CreateAddressInModuleBreakpoint ( m_options . m_load_addr ,
internal , file_spec ,
m_options . m_hardware )
. get ( ) ;
} else if ( num_modules_specified = = 0 ) {
bp = target
- > CreateBreakpoint ( m_options . m_load_addr , internal ,
m_options . m_hardware )
. get ( ) ;
} else {
result . AppendError ( " Only one shared library can be specified for "
" address breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
break ;
}
case eSetTypeFunctionName : // Breakpoint by function name
{
uint32_t name_type_mask = m_options . m_func_name_type_mask ;
if ( name_type_mask = = 0 )
name_type_mask = eFunctionNameTypeAuto ;
bp = target
- > CreateBreakpoint (
& ( m_options . m_modules ) , & ( m_options . m_filenames ) ,
m_options . m_func_names , name_type_mask , m_options . m_language ,
m_options . m_offset_addr , m_options . m_skip_prologue , internal ,
m_options . m_hardware )
. get ( ) ;
} break ;
case eSetTypeFunctionRegexp : // Breakpoint by regular expression function
// name
2016-09-13 07:10:56 +08:00
{
RegularExpression regexp ( m_options . m_func_regexp . c_str ( ) ) ;
if ( ! regexp . IsValid ( ) ) {
char err_str [ 1024 ] ;
regexp . GetErrorAsCString ( err_str , sizeof ( err_str ) ) ;
result . AppendErrorWithFormat (
" Function name regular expression could not be compiled: \" %s \" " ,
err_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2016-09-07 04:57:50 +08:00
2016-09-13 07:10:56 +08:00
bp = target
- > CreateFuncRegexBreakpoint (
& ( m_options . m_modules ) , & ( m_options . m_filenames ) , regexp ,
m_options . m_language , m_options . m_skip_prologue , internal ,
m_options . m_hardware )
. get ( ) ;
}
break ;
2016-09-07 04:57:50 +08:00
case eSetTypeSourceRegexp : // Breakpoint by regexp on source text.
{
const size_t num_files = m_options . m_filenames . GetSize ( ) ;
if ( num_files = = 0 & & ! m_options . m_all_files ) {
FileSpec file ;
if ( ! GetDefaultFile ( target , file , result ) ) {
result . AppendError (
" No files provided and could not find default file. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
} else {
m_options . m_filenames . Append ( file ) ;
}
}
RegularExpression regexp ( m_options . m_source_text_regexp . c_str ( ) ) ;
if ( ! regexp . IsValid ( ) ) {
char err_str [ 1024 ] ;
regexp . GetErrorAsCString ( err_str , sizeof ( err_str ) ) ;
result . AppendErrorWithFormat (
" Source text regular expression could not be compiled: \" %s \" " ,
err_str ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
bp = target
- > CreateSourceRegexBreakpoint (
& ( m_options . m_modules ) , & ( m_options . m_filenames ) ,
m_options . m_source_regex_func_names , regexp , internal ,
m_options . m_hardware , m_options . m_move_to_nearest_code )
. get ( ) ;
} break ;
case eSetTypeException : {
Error precond_error ;
bp = target
- > CreateExceptionBreakpoint (
m_options . m_exception_language , m_options . m_catch_bp ,
m_options . m_throw_bp , internal ,
& m_options . m_exception_extra_args , & precond_error )
. get ( ) ;
if ( precond_error . Fail ( ) ) {
result . AppendErrorWithFormat (
" Error setting extra exception arguments: %s " ,
precond_error . AsCString ( ) ) ;
target - > RemoveBreakpointByID ( bp - > GetID ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} break ;
default :
break ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
// Now set the various options that were passed in:
if ( bp ) {
if ( m_options . m_thread_id ! = LLDB_INVALID_THREAD_ID )
bp - > SetThreadID ( m_options . m_thread_id ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( m_options . m_thread_index ! = UINT32_MAX )
bp - > GetOptions ( ) - > GetThreadSpec ( ) - > SetIndex ( m_options . m_thread_index ) ;
2016-02-19 06:39:14 +08:00
2016-09-07 04:57:50 +08:00
if ( ! m_options . m_thread_name . empty ( ) )
bp - > GetOptions ( ) - > GetThreadSpec ( ) - > SetName (
m_options . m_thread_name . c_str ( ) ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( ! m_options . m_queue_name . empty ( ) )
bp - > GetOptions ( ) - > GetThreadSpec ( ) - > SetQueueName (
m_options . m_queue_name . c_str ( ) ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( m_options . m_ignore_count ! = 0 )
bp - > GetOptions ( ) - > SetIgnoreCount ( m_options . m_ignore_count ) ;
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
if ( ! m_options . m_condition . empty ( ) )
bp - > GetOptions ( ) - > SetCondition ( m_options . m_condition . c_str ( ) ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( ! m_options . m_breakpoint_names . empty ( ) ) {
Error error ; // We don't need to check the error here, since the option
// parser checked it...
for ( auto name : m_options . m_breakpoint_names )
bp - > AddName ( name . c_str ( ) , error ) ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
bp - > SetOneShot ( m_options . m_one_shot ) ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( bp ) {
Stream & output_stream = result . GetOutputStream ( ) ;
const bool show_locations = false ;
bp - > GetDescription ( & output_stream , lldb : : eDescriptionLevelInitial ,
show_locations ) ;
if ( target = = m_interpreter . GetDebugger ( ) . GetDummyTarget ( ) )
output_stream . Printf ( " Breakpoint set in dummy target, will get copied "
" into future targets. \n " ) ;
else {
// Don't print out this warning for exception breakpoints. They can get
// set before the target
// is set, but we won't know how to actually set the breakpoint till we
// run.
if ( bp - > GetNumLocations ( ) = = 0 & & break_type ! = eSetTypeException ) {
output_stream . Printf ( " WARNING: Unable to resolve breakpoint to any "
" actual locations. \n " ) ;
}
}
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else if ( ! bp ) {
result . AppendError ( " Breakpoint creation failed: No breakpoint created. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2012-06-09 05:56:10 +08:00
}
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
bool GetDefaultFile ( Target * target , FileSpec & file ,
CommandReturnObject & result ) {
uint32_t default_line ;
// First use the Source Manager's default file.
// Then use the current stack frame's file.
if ( ! target - > GetSourceManager ( ) . GetDefaultFileAndLine ( file , default_line ) ) {
StackFrame * cur_frame = m_exe_ctx . GetFramePtr ( ) ;
if ( cur_frame = = nullptr ) {
result . AppendError (
" No selected frame to use to find the default file. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
} else if ( ! cur_frame - > HasDebugInformation ( ) ) {
result . AppendError ( " Cannot use the selected frame to find the default "
" file, it has no debug info. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
} else {
const SymbolContext & sc =
cur_frame - > GetSymbolContext ( eSymbolContextLineEntry ) ;
if ( sc . line_entry . file ) {
file = sc . line_entry . file ;
} else {
result . AppendError ( " Can't find the file for the selected frame to "
" use as the default file. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
}
2012-06-09 05:56:10 +08:00
}
2016-09-07 04:57:50 +08:00
return true ;
}
CommandOptions m_options ;
2012-06-09 05:56:10 +08:00
} ;
2016-02-19 06:39:14 +08:00
2012-05-08 08:43:20 +08:00
// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
2016-09-07 04:57:50 +08:00
# define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
# define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
# define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
# define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
# define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
# define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
OptionDefinition CommandObjectBreakpointSet : : CommandOptions : : g_option_table [ ] =
{
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_NOT_10 , false , " shlib " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eModuleCompletion , eArgTypeShlibName , " Set the breakpoint only in this shared library. Can repeat this option "
" multiple times to specify multiple shared libraries. " } ,
{ LLDB_OPT_SET_ALL , false , " ignore-count " , ' i ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeCount , " Set the number of times this breakpoint is skipped before stopping. " } ,
{ LLDB_OPT_SET_ALL , false , " one-shot " , ' o ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " The breakpoint is deleted the first time it causes a stop. " } ,
{ LLDB_OPT_SET_ALL , false , " condition " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeExpression , " The breakpoint stops only if this condition expression evaluates to true. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-index " , ' x ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadIndex , " The breakpoint stops only for the thread whose indeX matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-id " , ' t ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadID , " The breakpoint stops only for the thread whose TID matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-name " , ' T ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadName , " The breakpoint stops only for the thread whose thread name matches this "
" argument. " } ,
{ LLDB_OPT_SET_ALL , false , " hardware " , ' H ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Require the breakpoint to use hardware breakpoints. " } ,
{ LLDB_OPT_SET_ALL , false , " queue-name " , ' q ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeQueueName , " The breakpoint stops only for threads in the queue whose name is given by "
" this argument. " } ,
{ LLDB_OPT_FILE , false , " file " , ' f ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSourceFileCompletion , eArgTypeFilename , " Specifies the source file in which to set this breakpoint. Note, by default "
" lldb only looks for files that are #included if they use the standard include "
" file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
" #included, set target.inline-breakpoint-strategy to \" always \" . " } ,
{ LLDB_OPT_SET_1 , true , " line " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLineNum , " Specifies the line number on which to set this breakpoint. " } ,
2010-06-09 00:52:24 +08:00
// Comment out this option for the moment, as we don't actually use it, but will in the future.
// This way users won't see it, but the infrastructure is left in place.
2016-02-19 06:39:14 +08:00
// { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
2010-06-09 00:52:24 +08:00
// "Set the breakpoint by source location at this particular column."},
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_2 , true , " address " , ' a ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeAddressOrExpression , " Set the breakpoint at the specified address. If the address maps uniquely to "
" a particular binary, then the address will be converted to a \" file \" "
" address, so that the breakpoint will track that binary+offset no matter where "
" the binary eventually loads. Alternately, if you also specify the module - "
" with the -s option - then the address will be treated as a file address in "
" that module, and resolved accordingly. Again, this will allow lldb to track "
" that offset on subsequent reloads. The module need not have been loaded at "
" the time you specify this breakpoint, and will get resolved when the module "
" is loaded. " } ,
{ LLDB_OPT_SET_3 , true , " name " , ' n ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSymbolCompletion , eArgTypeFunctionName , " Set the breakpoint by function name. Can be repeated multiple times to make "
" one breakpoint for multiple names " } ,
{ LLDB_OPT_SET_9 , false , " source-regexp-function " , ' X ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSymbolCompletion , eArgTypeFunctionName , " When used with '-p' limits the source regex to source contained in the named "
" functions. Can be repeated multiple times. " } ,
{ LLDB_OPT_SET_4 , true , " fullname " , ' F ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSymbolCompletion , eArgTypeFullName , " Set the breakpoint by fully qualified function names. For C++ this means "
" namespaces and all arguments, and for Objective C this means a full function "
" prototype with class and selector. Can be repeated multiple times to make "
" one breakpoint for multiple names. " } ,
{ LLDB_OPT_SET_5 , true , " selector " , ' S ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeSelector , " Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
" make one breakpoint for multiple Selectors. " } ,
{ LLDB_OPT_SET_6 , true , " method " , ' M ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeMethod , " Set the breakpoint by C++ method names. Can be repeated multiple times to "
" make one breakpoint for multiple methods. " } ,
{ LLDB_OPT_SET_7 , true , " func-regex " , ' r ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeRegularExpression , " Set the breakpoint by function name, evaluating a regular-expression to find "
" the function name(s). " } ,
{ LLDB_OPT_SET_8 , true , " basename " , ' b ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSymbolCompletion , eArgTypeFunctionName , " Set the breakpoint by function basename (C++ namespaces and arguments will be "
" ignored). Can be repeated multiple times to make one breakpoint for multiple "
" symbols. " } ,
{ LLDB_OPT_SET_9 , true , " source-pattern-regexp " , ' p ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeRegularExpression , " Set the breakpoint by specifying a regular expression which is matched "
" against the source text in a source file or files specified with the -f "
" option. The -f option can be specified more than once. If no source files "
" are specified, uses the current \" default source file \" . If you want to "
" match against all source files, pass the \" --all-files \" option. " } ,
{ LLDB_OPT_SET_9 , false , " all-files " , ' A ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " All files are searched for source pattern matches. " } ,
{ LLDB_OPT_SET_10 , true , " language-exception " , ' E ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Set the breakpoint on exceptions thrown by the specified language (without "
" options, on throw but not catch.) " } ,
{ LLDB_OPT_SET_10 , false , " on-throw " , ' w ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Set the breakpoint on exception throW. " } ,
{ LLDB_OPT_SET_10 , false , " on-catch " , ' h ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Set the breakpoint on exception catcH. " } ,
2011-09-21 09:17:13 +08:00
2015-04-23 03:42:18 +08:00
// Don't add this option till it actually does something useful...
2016-02-19 06:39:14 +08:00
// { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
2015-04-23 03:42:18 +08:00
// "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" },
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_EXPR_LANGUAGE , false , " language " , ' L ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLanguage , " Specifies the Language to use when interpreting the breakpoint's expression "
" (note: currently only implemented for setting breakpoints on identifiers). "
" If not set the target.language setting is used. " } ,
{ LLDB_OPT_SKIP_PROLOGUE , false , " skip-prologue " , ' K ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " sKip the prologue if the breakpoint is at the beginning of a function. "
" If not set the target.skip-prologue setting is used. " } ,
{ 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. " } ,
{ LLDB_OPT_SET_ALL , false , " breakpoint-name " , ' N ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBreakpointName , " Adds this to the list of names for this breakpoint. " } ,
{ LLDB_OPT_OFFSET_APPLIES , false , " address-slide " , ' R ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeAddress , " Add the specified offset to whatever address(es) the breakpoint resolves to. "
2016-03-10 02:59:13 +08:00
" At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries. " } ,
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_MOVE_TO_NEAREST_CODE , false , " move-to-nearest-code " , ' m ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
" setting is used. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2016-09-07 04:57:50 +08:00
// clang-format on
2010-06-09 00:52:24 +08:00
} ;
2012-06-09 05:56:10 +08:00
//-------------------------------------------------------------------------
// CommandObjectBreakpointModify
//-------------------------------------------------------------------------
# pragma mark Modify
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointModify : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointModify ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " breakpoint modify " ,
" Modify the options on a breakpoint or set of "
" breakpoints in the executable. "
" If no breakpoint is specified, acts on the last "
" created breakpoint. "
" With the exception of -e, -d and -i, passing an "
" empty argument clears the modification. " ,
2016-02-19 06:39:14 +08:00
nullptr ) ,
2016-09-07 04:57:50 +08:00
m_options ( ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeBreakpointID ,
eArgTypeBreakpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectBreakpointModify ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_ignore_count ( 0 ) , m_thread_id ( LLDB_INVALID_THREAD_ID ) ,
m_thread_id_passed ( false ) , m_thread_index ( UINT32_MAX ) ,
m_thread_index_passed ( false ) , m_thread_name ( ) , m_queue_name ( ) ,
m_condition ( ) , m_one_shot ( false ) , m_enable_passed ( false ) ,
m_enable_value ( false ) , m_name_passed ( false ) , m_queue_passed ( false ) ,
m_condition_passed ( false ) , m_one_shot_passed ( false ) ,
m_use_dummy ( false ) { }
~ 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 ;
switch ( short_option ) {
case ' c ' :
if ( option_arg ! = nullptr )
m_condition . assign ( option_arg ) ;
else
m_condition . clear ( ) ;
m_condition_passed = true ;
break ;
case ' d ' :
m_enable_passed = true ;
m_enable_value = false ;
break ;
case ' D ' :
m_use_dummy = true ;
break ;
case ' e ' :
m_enable_passed = true ;
m_enable_value = true ;
break ;
case ' i ' :
m_ignore_count = StringConvert : : ToUInt32 ( option_arg , UINT32_MAX , 0 ) ;
if ( m_ignore_count = = UINT32_MAX )
error . SetErrorStringWithFormat ( " invalid ignore count '%s' " ,
option_arg ) ;
break ;
case ' o ' : {
bool value , success ;
2016-09-20 01:54:06 +08:00
value = Args : : StringToBoolean (
llvm : : StringRef : : withNullAsEmpty ( option_arg ) , false , & success ) ;
2016-09-07 04:57:50 +08:00
if ( success ) {
m_one_shot_passed = true ;
m_one_shot = value ;
} else
error . SetErrorStringWithFormat (
" invalid boolean value '%s' passed for -o option " , option_arg ) ;
} break ;
case ' t ' :
if ( option_arg [ 0 ] = = ' \0 ' ) {
m_thread_id = LLDB_INVALID_THREAD_ID ;
m_thread_id_passed = true ;
} else {
m_thread_id =
StringConvert : : ToUInt64 ( option_arg , LLDB_INVALID_THREAD_ID , 0 ) ;
if ( m_thread_id = = LLDB_INVALID_THREAD_ID )
error . SetErrorStringWithFormat ( " invalid thread id string '%s' " ,
option_arg ) ;
else
m_thread_id_passed = true ;
}
break ;
case ' T ' :
if ( option_arg ! = nullptr )
m_thread_name . assign ( option_arg ) ;
else
m_thread_name . clear ( ) ;
m_name_passed = true ;
break ;
case ' q ' :
if ( option_arg ! = nullptr )
m_queue_name . assign ( option_arg ) ;
else
m_queue_name . clear ( ) ;
m_queue_passed = true ;
break ;
case ' x ' :
if ( option_arg [ 0 ] = = ' \n ' ) {
m_thread_index = UINT32_MAX ;
m_thread_index_passed = true ;
} else {
m_thread_index = StringConvert : : ToUInt32 ( option_arg , UINT32_MAX , 0 ) ;
if ( m_thread_id = = UINT32_MAX )
error . SetErrorStringWithFormat ( " invalid thread index string '%s' " ,
option_arg ) ;
else
m_thread_index_passed = true ;
}
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2012-06-09 05:56:10 +08:00
}
2016-09-07 04:57:50 +08:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_ignore_count = 0 ;
m_thread_id = LLDB_INVALID_THREAD_ID ;
m_thread_id_passed = false ;
m_thread_index = UINT32_MAX ;
m_thread_index_passed = false ;
m_thread_name . clear ( ) ;
m_queue_name . clear ( ) ;
m_condition . clear ( ) ;
m_one_shot = false ;
m_enable_passed = false ;
m_queue_passed = false ;
m_name_passed = false ;
m_condition_passed = false ;
m_one_shot_passed = false ;
m_use_dummy = false ;
2012-06-09 05:56:10 +08:00
}
2010-06-29 05:30:43 +08:00
2016-09-07 04:57:50 +08:00
const OptionDefinition * GetDefinitions ( ) override { return g_option_table ; }
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
// Options table: Required for subclasses of Options.
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
static OptionDefinition g_option_table [ ] ;
2016-02-19 06:39:14 +08:00
2016-09-07 04:57:50 +08:00
// Instance variables to hold the values for command options.
uint32_t m_ignore_count ;
lldb : : tid_t m_thread_id ;
bool m_thread_id_passed ;
uint32_t m_thread_index ;
bool m_thread_index_passed ;
std : : string m_thread_name ;
std : : string m_queue_name ;
std : : string m_condition ;
bool m_one_shot ;
bool m_enable_passed ;
bool m_enable_value ;
bool m_name_passed ;
bool m_queue_passed ;
bool m_condition_passed ;
bool m_one_shot_passed ;
bool m_use_dummy ;
} ;
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 = GetSelectedOrDummyTarget ( m_options . m_use_dummy ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
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 ) {
BreakpointLocation * location =
bp - > FindLocationByID ( cur_bp_id . GetLocationID ( ) ) . get ( ) ;
if ( location ) {
if ( m_options . m_thread_id_passed )
location - > SetThreadID ( m_options . m_thread_id ) ;
if ( m_options . m_thread_index_passed )
location - > SetThreadIndex ( m_options . m_thread_index ) ;
if ( m_options . m_name_passed )
location - > SetThreadName ( m_options . m_thread_name . c_str ( ) ) ;
2011-09-21 09:17:13 +08:00
2016-09-07 04:57:50 +08:00
if ( m_options . m_queue_passed )
location - > SetQueueName ( m_options . m_queue_name . c_str ( ) ) ;
if ( m_options . m_ignore_count ! = 0 )
location - > SetIgnoreCount ( m_options . m_ignore_count ) ;
if ( m_options . m_enable_passed )
location - > SetEnabled ( m_options . m_enable_value ) ;
if ( m_options . m_condition_passed )
location - > SetCondition ( m_options . m_condition . c_str ( ) ) ;
2010-06-09 00:52:24 +08:00
}
2016-09-07 04:57:50 +08:00
} else {
if ( m_options . m_thread_id_passed )
bp - > SetThreadID ( m_options . m_thread_id ) ;
if ( m_options . m_thread_index_passed )
bp - > SetThreadIndex ( m_options . m_thread_index ) ;
if ( m_options . m_name_passed )
bp - > SetThreadName ( m_options . m_thread_name . c_str ( ) ) ;
if ( m_options . m_queue_passed )
bp - > SetQueueName ( m_options . m_queue_name . c_str ( ) ) ;
if ( m_options . m_ignore_count ! = 0 )
bp - > SetIgnoreCount ( m_options . m_ignore_count ) ;
if ( m_options . m_enable_passed )
bp - > SetEnabled ( m_options . m_enable_value ) ;
if ( m_options . m_condition_passed )
bp - > SetCondition ( m_options . m_condition . c_str ( ) ) ;
}
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 ( ) ;
}
2012-06-09 05:56:10 +08:00
private :
2016-09-07 04:57:50 +08:00
CommandOptions m_options ;
2010-06-09 00:52:24 +08:00
} ;
2012-06-09 05:56:10 +08:00
# pragma mark Modify::CommandOptions
OptionDefinition
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointModify : : CommandOptions : : g_option_table [ ] = {
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_ALL , false , " ignore-count " , ' i ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeCount , " Set the number of times this breakpoint is skipped before stopping. " } ,
{ LLDB_OPT_SET_ALL , false , " one-shot " , ' o ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBoolean , " The breakpoint is deleted the first time it stop causes a stop. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-index " , ' x ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadIndex , " The breakpoint stops only for the thread whose index matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-id " , ' t ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadID , " The breakpoint stops only for the thread whose TID matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " thread-name " , ' T ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeThreadName , " The breakpoint stops only for the thread whose thread name matches this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " queue-name " , ' q ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeQueueName , " The breakpoint stops only for threads in the queue whose name is given by this argument. " } ,
{ LLDB_OPT_SET_ALL , false , " condition " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeExpression , " The breakpoint stops only if this condition expression evaluates to true. " } ,
{ LLDB_OPT_SET_1 , false , " enable " , ' e ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Enable the breakpoint. " } ,
{ LLDB_OPT_SET_2 , false , " disable " , ' d ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Disable the breakpoint. " } ,
{ 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
//-------------------------------------------------------------------------
// CommandObjectBreakpointEnable
//-------------------------------------------------------------------------
2010-06-18 08:58:52 +08:00
# pragma mark Enable
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointEnable : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointEnable ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " enable " ,
" Enable the specified disabled breakpoint(s). If "
" no breakpoints are specified, enable all of them. " ,
nullptr ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeBreakpointID ,
eArgTypeBreakpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectBreakpointEnable ( ) 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 = GetSelectedOrDummyTarget ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-16 10:00:15 +08:00
2016-09-07 04:57:50 +08:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
2010-06-16 10:00:15 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
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 be enabled. " ) ;
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 ) {
// No breakpoint selected; enable all currently set breakpoints.
target - > EnableAllBreakpoints ( ) ;
result . AppendMessageWithFormat ( " All breakpoints enabled. (% " PRIu64
" breakpoints) \n " ,
( uint64_t ) num_breakpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular breakpoint selected; enable that breakpoint.
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointOrLocationIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
int enable_count = 0 ;
int loc_count = 0 ;
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 * breakpoint =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
if ( cur_bp_id . GetLocationID ( ) ! = LLDB_INVALID_BREAK_ID ) {
BreakpointLocation * location =
breakpoint - > FindLocationByID ( cur_bp_id . GetLocationID ( ) ) . get ( ) ;
if ( location ) {
location - > SetEnabled ( true ) ;
+ + loc_count ;
}
} else {
breakpoint - > SetEnabled ( true ) ;
+ + enable_count ;
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
result . AppendMessageWithFormat ( " %d breakpoints enabled. \n " ,
enable_count + loc_count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
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
//-------------------------------------------------------------------------
// CommandObjectBreakpointDisable
//-------------------------------------------------------------------------
2010-06-18 08:58:52 +08:00
# pragma mark Disable
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointDisable : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointDisable ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " breakpoint disable " ,
" Disable the specified breakpoint(s) without deleting "
" them. If none are specified, disable all "
" breakpoints. " ,
nullptr ) {
SetHelpLong (
" Disable the specified breakpoint(s) without deleting them. \
2016-07-15 06:03:10 +08:00
If none are specified , disable all breakpoints . "
2016-09-07 04:57:50 +08:00
R " (
2015-07-14 13:48:36 +08:00
2016-07-15 06:03:10 +08:00
) "
2016-09-07 04:57:50 +08:00
" Note: disabling a breakpoint will cause none of its locations to be hit \
2016-07-15 06:03:10 +08:00
regardless of whether individual locations are enabled or disabled . After the sequence : "
2016-09-07 04:57:50 +08:00
R " (
2015-07-14 13:48:36 +08:00
( lldb ) break disable 1
( lldb ) break enable 1.1
execution will NOT stop at location 1.1 . To achieve that , type :
( lldb ) break disable 1. *
( lldb ) break enable 1.1
2016-07-15 06:03:10 +08:00
) "
2016-09-07 04:57:50 +08:00
" The first command disables all locations for breakpoint 1, \
2016-07-15 06:03:10 +08:00
the second re - enables the first location . " );
2016-09-07 04:57:50 +08:00
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeBreakpointID ,
eArgTypeBreakpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
~ CommandObjectBreakpointDisable ( ) 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 = GetSelectedOrDummyTarget ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
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 be disabled. " ) ;
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 ) {
// No breakpoint selected; disable all currently set breakpoints.
target - > DisableAllBreakpoints ( ) ;
result . AppendMessageWithFormat ( " All breakpoints disabled. (% " PRIu64
" breakpoints) \n " ,
( uint64_t ) num_breakpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointOrLocationIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
int disable_count = 0 ;
int loc_count = 0 ;
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 * breakpoint =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
if ( cur_bp_id . GetLocationID ( ) ! = LLDB_INVALID_BREAK_ID ) {
BreakpointLocation * location =
breakpoint - > FindLocationByID ( cur_bp_id . GetLocationID ( ) ) . get ( ) ;
if ( location ) {
location - > SetEnabled ( false ) ;
+ + loc_count ;
}
} else {
breakpoint - > SetEnabled ( false ) ;
+ + disable_count ;
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
result . AppendMessageWithFormat ( " %d breakpoints disabled. \n " ,
disable_count + loc_count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
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
} ;
2010-06-09 00:52:24 +08:00
2010-10-29 01:27:46 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
// CommandObjectBreakpointList
2010-10-29 01:27:46 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
# pragma mark List
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointList : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointList ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " breakpoint list " ,
" List some or all breakpoints at configurable levels of detail. " ,
nullptr ) ,
m_options ( ) {
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 = eArgRepeatOptional ;
// 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 ) ;
}
~ CommandObjectBreakpointList ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) , m_level ( lldb : : eDescriptionLevelBrief ) , m_use_dummy ( false ) {
2012-06-09 05:56:10 +08:00
}
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
~ 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 ;
switch ( short_option ) {
case ' b ' :
m_level = lldb : : eDescriptionLevelBrief ;
break ;
case ' D ' :
m_use_dummy = true ;
break ;
case ' f ' :
m_level = lldb : : eDescriptionLevelFull ;
break ;
case ' v ' :
m_level = lldb : : eDescriptionLevelVerbose ;
break ;
case ' i ' :
m_internal = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2010-10-29 01:27:46 +08:00
}
2016-09-07 04:57:50 +08:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_level = lldb : : eDescriptionLevelFull ;
m_internal = false ;
m_use_dummy = false ;
}
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
const OptionDefinition * GetDefinitions ( ) override { return g_option_table ; }
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
// Options table: Required for subclasses of Options.
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
static OptionDefinition g_option_table [ ] ;
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
// Instance variables to hold the values for command options.
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
lldb : : DescriptionLevel m_level ;
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
bool m_internal ;
bool m_use_dummy ;
} ;
2010-10-29 01:27:46 +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 ) ;
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No current target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
}
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints =
target - > GetBreakpointList ( m_options . m_internal ) ;
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( m_options . m_internal ) . GetListMutex ( lock ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
size_t num_breakpoints = breakpoints . GetSize ( ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( num_breakpoints = = 0 ) {
result . AppendMessage ( " No breakpoints currently set. " ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
}
2010-10-29 01:27:46 +08:00
2016-09-07 04:57:50 +08:00
Stream & output_stream = result . GetOutputStream ( ) ;
if ( command . GetArgumentCount ( ) = = 0 ) {
// No breakpoint selected; show info about all currently set breakpoints.
result . AppendMessage ( " Current breakpoints: " ) ;
for ( size_t i = 0 ; i < num_breakpoints ; + + i ) {
Breakpoint * breakpoint = breakpoints . GetBreakpointAtIndex ( i ) . get ( ) ;
AddBreakpointDescription ( & output_stream , breakpoint , m_options . m_level ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular breakpoints selected; show info about that breakpoint.
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointOrLocationIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
for ( size_t i = 0 ; i < valid_bp_ids . GetSize ( ) ; + + i ) {
BreakpointID cur_bp_id = valid_bp_ids . GetBreakpointIDAtIndex ( i ) ;
Breakpoint * breakpoint =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
AddBreakpointDescription ( & output_stream , breakpoint ,
m_options . m_level ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError ( " Invalid breakpoint ID. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2010-10-29 01:27:46 +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 ;
2012-06-09 05:56:10 +08:00
} ;
# pragma mark List::CommandOptions
2016-09-07 04:57:50 +08:00
OptionDefinition CommandObjectBreakpointList : : CommandOptions : : g_option_table [ ] =
{
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_ALL , false , " internal " , ' i ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Show debugger internal breakpoints " } ,
{ LLDB_OPT_SET_1 , false , " brief " , ' b ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Give a brief description of the breakpoint (no location info). " } ,
2012-06-09 05:56:10 +08:00
// FIXME: We need to add an "internal" command, and then add this sort of thing to it.
// But I need to see it for now, and don't want to wait.
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_2 , false , " full " , ' f ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Give a full description of the breakpoint and its locations. " } ,
{ LLDB_OPT_SET_3 , false , " verbose " , ' v ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Explain everything we know about the breakpoint (for debugging debugger bugs). " } ,
{ LLDB_OPT_SET_ALL , false , " dummy-breakpoints " , ' D ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " List 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
} ;
//-------------------------------------------------------------------------
// CommandObjectBreakpointClear
//-------------------------------------------------------------------------
# pragma mark Clear
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointClear : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
typedef enum BreakpointClearType {
eClearTypeInvalid ,
eClearTypeFileAndLine
} BreakpointClearType ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointClear ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " breakpoint clear " ,
" Delete or disable breakpoints matching the "
" specified source file and line. " ,
" breakpoint clear <cmd-options> " ) ,
m_options ( ) { }
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
~ CommandObjectBreakpointClear ( ) override = default ;
2010-10-29 01:27:46 +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
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) , m_filename ( ) , m_line_num ( 0 ) { }
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
~ CommandOptions ( ) override = default ;
2012-06-09 05:56:10 +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 ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
switch ( short_option ) {
case ' f ' :
m_filename . assign ( option_arg ) ;
break ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
case ' l ' :
m_line_num = StringConvert : : ToUInt32 ( option_arg , 0 ) ;
break ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
return error ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_filename . clear ( ) ;
m_line_num = 0 ;
}
2010-06-09 00:52:24 +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-06-16 10:00:15 +08:00
2016-09-07 04:57:50 +08:00
// Instance variables to hold the values for command options.
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
std : : string m_filename ;
uint32_t m_line_num ;
} ;
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 = GetSelectedOrDummyTarget ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
// The following are the various types of breakpoints that could be cleared:
// 1). -f -l (clearing breakpoint by source location)
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
BreakpointClearType break_type = eClearTypeInvalid ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( m_options . m_line_num ! = 0 )
break_type = eClearTypeFileAndLine ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
size_t num_breakpoints = breakpoints . GetSize ( ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
// Early return if there's no breakpoint at all.
if ( num_breakpoints = = 0 ) {
result . AppendError ( " Breakpoint clear: No breakpoint cleared. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return result . Succeeded ( ) ;
}
2010-06-09 00:52:24 +08:00
2016-09-07 04:57:50 +08:00
// Find matching breakpoints and delete them.
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
// First create a copy of all the IDs.
std : : vector < break_id_t > BreakIDs ;
for ( size_t i = 0 ; i < num_breakpoints ; + + i )
BreakIDs . push_back ( breakpoints . GetBreakpointAtIndex ( i ) - > GetID ( ) ) ;
int num_cleared = 0 ;
StreamString ss ;
switch ( break_type ) {
case eClearTypeFileAndLine : // Breakpoint by source position
{
const ConstString filename ( m_options . m_filename . c_str ( ) ) ;
BreakpointLocationCollection loc_coll ;
for ( size_t i = 0 ; i < num_breakpoints ; + + i ) {
Breakpoint * bp = breakpoints . FindBreakpointByID ( BreakIDs [ i ] ) . get ( ) ;
if ( bp - > GetMatchingFileLine ( filename , m_options . m_line_num , loc_coll ) ) {
// If the collection size is 0, it's a full match and we can just
// remove the breakpoint.
if ( loc_coll . GetSize ( ) = = 0 ) {
bp - > GetDescription ( & ss , lldb : : eDescriptionLevelBrief ) ;
ss . EOL ( ) ;
target - > RemoveBreakpointByID ( bp - > GetID ( ) ) ;
+ + num_cleared ;
}
}
}
} break ;
default :
break ;
}
2010-06-16 10:00:15 +08:00
2016-09-07 04:57:50 +08:00
if ( num_cleared > 0 ) {
Stream & output_stream = result . GetOutputStream ( ) ;
output_stream . Printf ( " %d breakpoints cleared: \n " , num_cleared ) ;
output_stream < < ss . GetData ( ) ;
output_stream . EOL ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError ( " Breakpoint clear: No breakpoint cleared. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2012-06-09 05:56:10 +08:00
}
2010-06-16 10:00:15 +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 ;
2012-06-09 05:56:10 +08:00
} ;
2010-06-16 10:00:15 +08:00
2012-06-09 05:56:10 +08:00
# pragma mark Clear::CommandOptions
2010-06-16 10:00:15 +08:00
2011-03-25 05:19:54 +08:00
OptionDefinition
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointClear : : CommandOptions : : g_option_table [ ] = {
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_1 , false , " file " , ' f ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eSourceFileCompletion , eArgTypeFilename , " Specify the breakpoint by source location in this particular file. " } ,
{ LLDB_OPT_SET_1 , true , " line " , ' l ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeLineNum , " Specify the breakpoint by source location at this particular line. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
2016-09-07 04:57:50 +08:00
// clang-format on
2010-06-16 10:00:15 +08:00
} ;
2012-06-09 05:56:10 +08:00
//-------------------------------------------------------------------------
// CommandObjectBreakpointDelete
//-------------------------------------------------------------------------
# pragma mark Delete
2010-06-16 10:00:15 +08:00
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointDelete : public CommandObjectParsed {
2012-06-09 05:56:10 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointDelete ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " breakpoint delete " ,
" Delete the specified breakpoint(s). If no "
" breakpoints are specified, delete them all. " ,
2016-02-19 06:39:14 +08:00
nullptr ) ,
2016-09-07 04:57:50 +08:00
m_options ( ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeBreakpointID ,
eArgTypeBreakpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectBreakpointDelete ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) , m_use_dummy ( false ) , m_force ( false ) { }
~ 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 ;
switch ( short_option ) {
case ' f ' :
m_force = true ;
break ;
case ' D ' :
m_use_dummy = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2012-06-09 05:56:10 +08:00
}
2016-09-07 04:57:50 +08:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_use_dummy = false ;
m_force = 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 ;
bool m_force ;
} ;
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 ) ;
2014-12-06 09:28:03 +08:00
2016-09-07 04:57:50 +08:00
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
2016-05-19 13:13:57 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
size_t num_breakpoints = breakpoints . GetSize ( ) ;
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( num_breakpoints = = 0 ) {
result . AppendError ( " No breakpoints exist to be deleted. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-06-09 05:56:10 +08:00
2016-09-07 04:57:50 +08:00
if ( command . GetArgumentCount ( ) = = 0 ) {
if ( ! m_options . m_force & &
! m_interpreter . Confirm (
" About to delete all breakpoints, do you want to do that? " ,
true ) ) {
result . AppendMessage ( " Operation cancelled... " ) ;
} else {
target - > RemoveAllBreakpoints ( ) ;
result . AppendMessageWithFormat (
" All breakpoints removed. (% " PRIu64 " breakpoint%s) \n " ,
( uint64_t ) num_breakpoints , num_breakpoints > 1 ? " s " : " " ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointOrLocationIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
int delete_count = 0 ;
int disable_count = 0 ;
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 ) {
if ( cur_bp_id . GetLocationID ( ) ! = LLDB_INVALID_BREAK_ID ) {
Breakpoint * breakpoint =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
BreakpointLocation * location =
breakpoint - > FindLocationByID ( cur_bp_id . GetLocationID ( ) ) . get ( ) ;
// It makes no sense to try to delete individual locations, so we
// disable them instead.
if ( location ) {
location - > SetEnabled ( false ) ;
+ + disable_count ;
}
} else {
target - > RemoveBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) ;
+ + delete_count ;
2010-12-04 07:04:19 +08:00
}
2016-09-07 04:57:50 +08:00
}
2010-06-16 10:00:15 +08:00
}
2016-09-07 04:57:50 +08:00
result . AppendMessageWithFormat (
" %d breakpoints deleted; %d breakpoint locations disabled. \n " ,
delete_count , disable_count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
2010-06-16 10:00:15 +08:00
}
2016-09-07 04:57:50 +08:00
return result . Succeeded ( ) ;
}
2016-02-19 06:39:14 +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
CommandObjectBreakpointDelete : : CommandOptions : : g_option_table [ ] = {
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_1 , false , " force " , ' f ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Delete all breakpoints without querying for confirmation. " } ,
{ LLDB_OPT_SET_1 , false , " dummy-breakpoints " , ' D ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Delete 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-16 10:00:15 +08:00
2014-12-17 07:40:14 +08:00
//-------------------------------------------------------------------------
// CommandObjectBreakpointName
//-------------------------------------------------------------------------
2016-07-15 06:03:10 +08:00
static OptionDefinition g_breakpoint_name_options [ ] = {
2016-09-07 04:57:50 +08:00
// clang-format off
2016-08-27 07:28:47 +08:00
{ LLDB_OPT_SET_1 , false , " name " , ' N ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBreakpointName , " Specifies a breakpoint name to use. " } ,
{ LLDB_OPT_SET_2 , false , " breakpoint-id " , ' B ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeBreakpointID , " Specify a breakpoint ID to use. " } ,
{ LLDB_OPT_SET_ALL , false , " dummy-breakpoints " , ' D ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets. " } ,
2016-09-07 04:57:50 +08:00
// clang-format on
2014-12-17 07:40:14 +08:00
} ;
2016-09-07 04:57:50 +08:00
class BreakpointNameOptionGroup : public OptionGroup {
2014-12-17 07:40:14 +08:00
public :
2016-09-07 04:57:50 +08:00
BreakpointNameOptionGroup ( )
: OptionGroup ( ) , m_breakpoint ( LLDB_INVALID_BREAK_ID ) , m_use_dummy ( false ) {
}
~ BreakpointNameOptionGroup ( ) override = default ;
uint32_t GetNumDefinitions ( ) override {
return sizeof ( g_breakpoint_name_options ) / sizeof ( OptionDefinition ) ;
}
const OptionDefinition * GetDefinitions ( ) override {
return g_breakpoint_name_options ;
}
Error SetOptionValue ( uint32_t option_idx , const char * option_value ,
ExecutionContext * execution_context ) override {
Error error ;
const int short_option = g_breakpoint_name_options [ option_idx ] . short_option ;
2016-09-17 10:00:02 +08:00
llvm : : StringRef option_strref ( option_value ? option_value : " " ) ;
2016-09-07 04:57:50 +08:00
switch ( short_option ) {
case ' N ' :
2016-09-17 10:00:02 +08:00
if ( BreakpointID : : StringIsBreakpointName ( option_strref , error ) & &
2016-09-07 04:57:50 +08:00
error . Success ( ) )
2016-09-17 10:00:02 +08:00
m_name . SetValueFromString ( option_strref ) ;
2016-09-07 04:57:50 +08:00
break ;
case ' B ' :
if ( m_breakpoint . SetValueFromString ( option_value ) . Fail ( ) )
error . SetErrorStringWithFormat (
" unrecognized value \" %s \" for breakpoint " , option_value ) ;
break ;
case ' D ' :
if ( m_use_dummy . SetValueFromString ( option_value ) . Fail ( ) )
error . SetErrorStringWithFormat (
" unrecognized value \" %s \" for use-dummy " , option_value ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized short option '%c' " ,
short_option ) ;
break ;
2014-12-17 07:40:14 +08:00
}
2016-09-07 04:57:50 +08:00
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_name . Clear ( ) ;
m_breakpoint . Clear ( ) ;
m_use_dummy . Clear ( ) ;
m_use_dummy . SetDefaultValue ( false ) ;
}
OptionValueString m_name ;
OptionValueUInt64 m_breakpoint ;
OptionValueBoolean m_use_dummy ;
2014-12-17 07:40:14 +08:00
} ;
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
2014-12-17 07:40:14 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointNameAdd ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " add " , " Add a name to the breakpoints provided. " ,
" breakpoint name add <command-options> <breakpoint-id-list> " ) ,
m_name_options ( ) , m_option_group ( ) {
// Create the first variant for the first (and only) argument for this
// command.
CommandArgumentEntry arg1 ;
CommandArgumentData id_arg ;
id_arg . arg_type = eArgTypeBreakpointID ;
id_arg . arg_repetition = eArgRepeatOptional ;
arg1 . push_back ( id_arg ) ;
m_arguments . push_back ( arg1 ) ;
m_option_group . Append ( & m_name_options , LLDB_OPT_SET_1 , LLDB_OPT_SET_ALL ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectBreakpointNameAdd ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
2014-12-17 07:40:14 +08:00
protected :
2016-09-07 04:57:50 +08:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
if ( ! m_name_options . m_name . OptionWasSet ( ) ) {
result . SetError ( " No name option provided. " ) ;
return false ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
Target * target =
GetSelectedOrDummyTarget ( m_name_options . m_use_dummy . GetCurrentValue ( ) ) ;
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
2016-05-19 13:13:57 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
size_t num_breakpoints = breakpoints . GetSize ( ) ;
if ( num_breakpoints = = 0 ) {
result . SetError ( " No breakpoints, cannot add names. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
if ( valid_bp_ids . GetSize ( ) = = 0 ) {
result . SetError ( " No breakpoints specified, cannot add names. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
size_t num_valid_ids = valid_bp_ids . GetSize ( ) ;
for ( size_t index = 0 ; index < num_valid_ids ; index + + ) {
lldb : : break_id_t bp_id =
valid_bp_ids . GetBreakpointIDAtIndex ( index ) . GetBreakpointID ( ) ;
BreakpointSP bp_sp = breakpoints . FindBreakpointByID ( bp_id ) ;
Error error ; // We don't need to check the error here, since the option
// parser checked it...
bp_sp - > AddName ( m_name_options . m_name . GetCurrentValue ( ) , error ) ;
}
2014-12-17 07:40:14 +08:00
}
2016-09-07 04:57:50 +08:00
return true ;
}
2014-12-17 07:40:14 +08:00
private :
2016-09-07 04:57:50 +08:00
BreakpointNameOptionGroup m_name_options ;
OptionGroupOptions m_option_group ;
2014-12-17 07:40:14 +08:00
} ;
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
2014-12-17 07:40:14 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointNameDelete ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " delete " ,
" Delete a name from the breakpoints provided. " ,
" breakpoint name delete <command-options> <breakpoint-id-list> " ) ,
m_name_options ( ) , m_option_group ( ) {
// Create the first variant for the first (and only) argument for this
// command.
CommandArgumentEntry arg1 ;
CommandArgumentData id_arg ;
id_arg . arg_type = eArgTypeBreakpointID ;
id_arg . arg_repetition = eArgRepeatOptional ;
arg1 . push_back ( id_arg ) ;
m_arguments . push_back ( arg1 ) ;
m_option_group . Append ( & m_name_options , LLDB_OPT_SET_1 , LLDB_OPT_SET_ALL ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectBreakpointNameDelete ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
2014-12-17 07:40:14 +08:00
protected :
2016-09-07 04:57:50 +08:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
if ( ! m_name_options . m_name . OptionWasSet ( ) ) {
result . SetError ( " No name option provided. " ) ;
return false ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
Target * target =
GetSelectedOrDummyTarget ( m_name_options . m_use_dummy . GetCurrentValue ( ) ) ;
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2016-05-19 13:13:57 +08:00
2016-09-07 04:57:50 +08:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
const BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
size_t num_breakpoints = breakpoints . GetSize ( ) ;
if ( num_breakpoints = = 0 ) {
result . SetError ( " No breakpoints, cannot delete names. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
// Particular breakpoint selected; disable that breakpoint.
BreakpointIDList valid_bp_ids ;
CommandObjectMultiwordBreakpoint : : VerifyBreakpointIDs (
command , target , result , & valid_bp_ids ) ;
if ( result . Succeeded ( ) ) {
if ( valid_bp_ids . GetSize ( ) = = 0 ) {
result . SetError ( " No breakpoints specified, cannot delete names. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
size_t num_valid_ids = valid_bp_ids . GetSize ( ) ;
for ( size_t index = 0 ; index < num_valid_ids ; index + + ) {
lldb : : break_id_t bp_id =
valid_bp_ids . GetBreakpointIDAtIndex ( index ) . GetBreakpointID ( ) ;
BreakpointSP bp_sp = breakpoints . FindBreakpointByID ( bp_id ) ;
bp_sp - > RemoveName ( m_name_options . m_name . GetCurrentValue ( ) ) ;
}
2014-12-17 07:40:14 +08:00
}
2016-09-07 04:57:50 +08:00
return true ;
}
2014-12-17 07:40:14 +08:00
private :
2016-09-07 04:57:50 +08:00
BreakpointNameOptionGroup m_name_options ;
OptionGroupOptions m_option_group ;
2014-12-17 07:40:14 +08:00
} ;
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointNameList : public CommandObjectParsed {
2014-12-17 07:40:14 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointNameList ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " list " ,
" List either the names for a breakpoint or the "
" breakpoints for a given name. " ,
" breakpoint name list <command-options> " ) ,
m_name_options ( ) , m_option_group ( ) {
m_option_group . Append ( & m_name_options ) ;
m_option_group . Finalize ( ) ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
~ CommandObjectBreakpointNameList ( ) override = default ;
2016-02-19 06:39:14 +08:00
2016-09-07 04:57:50 +08:00
Options * GetOptions ( ) override { return & m_option_group ; }
2014-12-17 07:40:14 +08:00
protected :
2016-09-07 04:57:50 +08:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target =
GetSelectedOrDummyTarget ( m_name_options . m_use_dummy . GetCurrentValue ( ) ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2014-12-17 07:40:14 +08:00
2016-09-07 04:57:50 +08:00
if ( m_name_options . m_name . OptionWasSet ( ) ) {
const char * name = m_name_options . m_name . GetCurrentValue ( ) ;
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
BreakpointList & breakpoints = target - > GetBreakpointList ( ) ;
for ( BreakpointSP bp_sp : breakpoints . Breakpoints ( ) ) {
if ( bp_sp - > MatchesName ( name ) ) {
StreamString s ;
bp_sp - > GetDescription ( & s , eDescriptionLevelBrief ) ;
s . EOL ( ) ;
result . AppendMessage ( s . GetData ( ) ) ;
}
}
} else if ( m_name_options . m_breakpoint . OptionWasSet ( ) ) {
BreakpointSP bp_sp = target - > GetBreakpointList ( ) . FindBreakpointByID (
m_name_options . m_breakpoint . GetCurrentValue ( ) ) ;
if ( bp_sp ) {
std : : vector < std : : string > names ;
bp_sp - > GetNames ( names ) ;
result . AppendMessage ( " Names: " ) ;
for ( auto name : names )
result . AppendMessageWithFormat ( " %s \n " , name . c_str ( ) ) ;
} else {
result . AppendErrorWithFormat (
" Could not find breakpoint % " PRId64 " . \n " ,
m_name_options . m_breakpoint . GetCurrentValue ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
} else {
result . SetError ( " Must specify -N or -B option to list. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2014-12-17 07:40:14 +08:00
}
2016-09-07 04:57:50 +08:00
return true ;
}
2014-12-17 07:40:14 +08:00
private :
2016-09-07 04:57:50 +08:00
BreakpointNameOptionGroup m_name_options ;
OptionGroupOptions m_option_group ;
2014-12-17 07:40:14 +08:00
} ;
//-------------------------------------------------------------------------
2016-09-13 07:10:56 +08:00
// CommandObjectBreakpointName
2014-12-17 07:40:14 +08:00
//-------------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
class CommandObjectBreakpointName : public CommandObjectMultiword {
2014-12-17 07:40:14 +08:00
public :
2016-09-07 04:57:50 +08:00
CommandObjectBreakpointName ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " name " , " Commands to manage name tags for breakpoints " ,
" breakpoint name <subcommand> [<command-options>] " ) {
CommandObjectSP add_command_object (
new CommandObjectBreakpointNameAdd ( interpreter ) ) ;
CommandObjectSP delete_command_object (
new CommandObjectBreakpointNameDelete ( interpreter ) ) ;
CommandObjectSP list_command_object (
new CommandObjectBreakpointNameList ( interpreter ) ) ;
LoadSubCommand ( " add " , add_command_object ) ;
LoadSubCommand ( " delete " , delete_command_object ) ;
LoadSubCommand ( " list " , list_command_object ) ;
}
~ CommandObjectBreakpointName ( ) override = default ;
2014-12-17 07:40:14 +08:00
} ;
2016-09-13 07:10:56 +08:00
//-------------------------------------------------------------------------
// CommandObjectBreakpointRead
//-------------------------------------------------------------------------
# pragma mark Restore
class CommandObjectBreakpointRead : public CommandObjectParsed {
public :
CommandObjectBreakpointRead ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " breakpoint read " ,
" Read and set the breakpoints previously saved to "
" a file with \" breakpoint write \" . " ,
nullptr ) ,
m_options ( ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeBreakpointID ,
eArgTypeBreakpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectBreakpointRead ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
~ 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 ;
switch ( short_option ) {
case ' f ' :
m_filename . assign ( option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_filename . clear ( ) ;
}
const OptionDefinition * GetDefinitions ( ) override { return g_option_table ; }
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
std : : string m_filename ;
} ;
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
FileSpec input_spec ( m_options . m_filename , true ) ;
2016-09-15 03:07:35 +08:00
BreakpointIDList new_bps ;
Error error = target - > CreateBreakpointsFromFile ( input_spec , new_bps ) ;
2016-09-13 07:10:56 +08:00
2016-09-15 03:07:35 +08:00
if ( ! error . Success ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
2016-09-13 07:10:56 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2016-09-15 03:07:35 +08:00
// FIXME: Report the newly created breakpoints.
2016-09-13 07:10:56 +08:00
return result . Succeeded ( ) ;
}
private :
CommandOptions m_options ;
} ;
# pragma mark Modify::CommandOptions
OptionDefinition CommandObjectBreakpointRead : : CommandOptions : : g_option_table [ ] =
{
// clang-format off
{ LLDB_OPT_SET_ALL , true , " file " , ' f ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eDiskFileCompletion , eArgTypeFilename , " The file from which to read the breakpoints. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
// clang-format on
} ;
//-------------------------------------------------------------------------
// CommandObjectBreakpointWrite
//-------------------------------------------------------------------------
# pragma mark Save
class CommandObjectBreakpointWrite : public CommandObjectParsed {
public :
CommandObjectBreakpointWrite ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " breakpoint write " ,
" Write the breakpoints listed to a file that can "
" be read in with \" breakpoint read \" . "
" If given no arguments, writes all breakpoints. " ,
nullptr ) ,
m_options ( ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeBreakpointID ,
eArgTypeBreakpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectBreakpointWrite ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) { }
~ 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 ;
switch ( short_option ) {
case ' f ' :
m_filename . assign ( option_arg ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
}
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_filename . clear ( ) ;
}
const OptionDefinition * GetDefinitions ( ) override { return g_option_table ; }
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table [ ] ;
// Instance variables to hold the values for command options.
std : : string m_filename ;
} ;
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = GetSelectedOrDummyTarget ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or breakpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetBreakpointList ( ) . GetListMutex ( lock ) ;
2016-09-15 03:07:35 +08:00
BreakpointIDList valid_bp_ids ;
if ( command . GetArgumentCount ( ) > 0 ) {
2016-09-13 07:10:56 +08:00
CommandObjectMultiwordBreakpoint : : VerifyBreakpointIDs (
command , target , result , & valid_bp_ids ) ;
2016-09-15 03:07:35 +08:00
if ( ! result . Succeeded ( ) ) {
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2016-09-13 07:10:56 +08:00
}
}
2016-09-15 03:07:35 +08:00
Error error = target - > SerializeBreakpointsToFile (
FileSpec ( m_options . m_filename . c_str ( ) , true ) , valid_bp_ids ) ;
if ( ! error . Success ( ) ) {
result . AppendErrorWithFormat ( " error serializing breakpoints: %s. " ,
error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2016-09-13 07:10:56 +08:00
return result . Succeeded ( ) ;
}
private :
CommandOptions m_options ;
} ;
# pragma mark Modify::CommandOptions
OptionDefinition
CommandObjectBreakpointWrite : : CommandOptions : : g_option_table [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , true , " file " , ' f ' , OptionParser : : eRequiredArgument , nullptr , nullptr , CommandCompletions : : eDiskFileCompletion , eArgTypeFilename , " The file into which to write the breakpoints. " } ,
{ 0 , false , nullptr , 0 , 0 , nullptr , nullptr , 0 , eArgTypeNone , nullptr }
// clang-format on
} ;
2010-06-16 10:00:15 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
// CommandObjectMultiwordBreakpoint
2010-06-16 10:00:15 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
# pragma mark MultiwordBreakpoint
2010-06-16 10:00:15 +08:00
2016-09-07 04:57:50 +08:00
CommandObjectMultiwordBreakpoint : : CommandObjectMultiwordBreakpoint (
CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " breakpoint " ,
" Commands for operating on breakpoints (see 'help b' for shorthand.) " ,
" breakpoint <subcommand> [<command-options>] " ) {
CommandObjectSP list_command_object (
new CommandObjectBreakpointList ( interpreter ) ) ;
CommandObjectSP enable_command_object (
new CommandObjectBreakpointEnable ( interpreter ) ) ;
CommandObjectSP disable_command_object (
new CommandObjectBreakpointDisable ( interpreter ) ) ;
CommandObjectSP clear_command_object (
new CommandObjectBreakpointClear ( interpreter ) ) ;
CommandObjectSP delete_command_object (
new CommandObjectBreakpointDelete ( interpreter ) ) ;
CommandObjectSP set_command_object (
new CommandObjectBreakpointSet ( interpreter ) ) ;
CommandObjectSP command_command_object (
new CommandObjectBreakpointCommand ( interpreter ) ) ;
CommandObjectSP modify_command_object (
new CommandObjectBreakpointModify ( interpreter ) ) ;
CommandObjectSP name_command_object (
new CommandObjectBreakpointName ( interpreter ) ) ;
2016-09-13 07:10:56 +08:00
CommandObjectSP write_command_object (
new CommandObjectBreakpointWrite ( interpreter ) ) ;
CommandObjectSP read_command_object (
new CommandObjectBreakpointRead ( interpreter ) ) ;
2016-09-07 04:57:50 +08:00
list_command_object - > SetCommandName ( " breakpoint list " ) ;
enable_command_object - > SetCommandName ( " breakpoint enable " ) ;
disable_command_object - > SetCommandName ( " breakpoint disable " ) ;
clear_command_object - > SetCommandName ( " breakpoint clear " ) ;
delete_command_object - > SetCommandName ( " breakpoint delete " ) ;
set_command_object - > SetCommandName ( " breakpoint set " ) ;
command_command_object - > SetCommandName ( " breakpoint command " ) ;
modify_command_object - > SetCommandName ( " breakpoint modify " ) ;
name_command_object - > SetCommandName ( " breakpoint name " ) ;
2016-09-13 07:10:56 +08:00
write_command_object - > SetCommandName ( " breakpoint write " ) ;
read_command_object - > SetCommandName ( " breakpoint read " ) ;
2016-09-07 04:57:50 +08:00
LoadSubCommand ( " list " , list_command_object ) ;
LoadSubCommand ( " enable " , enable_command_object ) ;
LoadSubCommand ( " disable " , disable_command_object ) ;
LoadSubCommand ( " clear " , clear_command_object ) ;
LoadSubCommand ( " delete " , delete_command_object ) ;
LoadSubCommand ( " set " , set_command_object ) ;
LoadSubCommand ( " command " , command_command_object ) ;
LoadSubCommand ( " modify " , modify_command_object ) ;
LoadSubCommand ( " name " , name_command_object ) ;
2016-09-13 07:10:56 +08:00
LoadSubCommand ( " write " , write_command_object ) ;
LoadSubCommand ( " read " , read_command_object ) ;
2010-06-16 10:00:15 +08:00
}
2016-02-19 06:39:14 +08:00
CommandObjectMultiwordBreakpoint : : ~ CommandObjectMultiwordBreakpoint ( ) = default ;
2010-06-16 10:00:15 +08:00
2016-09-07 04:57:50 +08:00
void CommandObjectMultiwordBreakpoint : : VerifyIDs ( Args & args , Target * target ,
bool allow_locations ,
CommandReturnObject & result ,
BreakpointIDList * valid_ids ) {
// args can be strings representing 1). integers (for breakpoint ids)
// 2). the full breakpoint & location
// canonical representation
// 3). the word "to" or a hyphen,
// representing a range (in which case there
// had *better* be an entry both before &
// after of one of the first two types.
// 4). A breakpoint name
// If args is empty, we will use the last created breakpoint (if there is
// one.)
Args temp_args ;
if ( args . GetArgumentCount ( ) = = 0 ) {
if ( target - > GetLastCreatedBreakpoint ( ) ) {
valid_ids - > AddBreakpointID ( BreakpointID (
target - > GetLastCreatedBreakpoint ( ) - > GetID ( ) , LLDB_INVALID_BREAK_ID ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError (
" No breakpoint specified and no last created breakpoint. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2010-06-16 10:00:15 +08:00
}
2016-09-07 04:57:50 +08:00
return ;
}
// Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
// directly from the old ARGS to
// the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead
// generate a list of strings for
// all the breakpoint ids in the range, and shove all of those breakpoint id
// strings into TEMP_ARGS.
BreakpointIDList : : FindAndReplaceIDRanges ( args , target , allow_locations ,
result , temp_args ) ;
// NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
// BreakpointIDList:
valid_ids - > InsertStringArray ( temp_args . GetConstArgumentVector ( ) ,
temp_args . GetArgumentCount ( ) , result ) ;
// At this point, all of the breakpoint ids that the user passed in have been
// converted to breakpoint IDs
// and put into valid_ids.
if ( result . Succeeded ( ) ) {
// Now that we've converted everything from args into a list of breakpoint
// ids, go through our tentative list
// of breakpoint id's and verify that they correspond to valid/currently set
// breakpoints.
const size_t count = valid_ids - > GetSize ( ) ;
for ( size_t i = 0 ; i < count ; + + i ) {
BreakpointID cur_bp_id = valid_ids - > GetBreakpointIDAtIndex ( i ) ;
Breakpoint * breakpoint =
target - > GetBreakpointByID ( cur_bp_id . GetBreakpointID ( ) ) . get ( ) ;
if ( breakpoint ! = nullptr ) {
const size_t num_locations = breakpoint - > GetNumLocations ( ) ;
if ( static_cast < size_t > ( cur_bp_id . GetLocationID ( ) ) > num_locations ) {
StreamString id_str ;
BreakpointID : : GetCanonicalReference (
& id_str , cur_bp_id . GetBreakpointID ( ) , cur_bp_id . GetLocationID ( ) ) ;
i = valid_ids - > GetSize ( ) + 1 ;
result . AppendErrorWithFormat (
" '%s' is not a currently valid breakpoint/location id. \n " ,
id_str . GetData ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
i = valid_ids - > GetSize ( ) + 1 ;
result . AppendErrorWithFormat (
" '%d' is not a currently valid breakpoint ID. \n " ,
cur_bp_id . GetBreakpointID ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2010-06-16 10:00:15 +08:00
}
2016-09-07 04:57:50 +08:00
}
2010-06-16 10:00:15 +08:00
}