2013-08-23 13:46:38 -04:00
//===-- CommandObjectWatchpoint.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "CommandObjectWatchpoint.h"
# include "CommandObjectWatchpointCommand.h"
// C Includes
// C++ Includes
2016-07-23 16:50:09 -04:00
# include <vector>
2013-08-23 13:46:38 -04:00
// Other libraries and framework includes
2016-07-23 16:50:09 -04:00
# include "llvm/ADT/StringRef.h"
2013-08-23 13:46:38 -04:00
// Project includes
# include "lldb/Breakpoint/Watchpoint.h"
# include "lldb/Breakpoint/WatchpointList.h"
# include "lldb/Core/ValueObject.h"
# include "lldb/Core/ValueObjectVariable.h"
2017-04-16 12:04:10 -04:00
# include "lldb/Host/OptionParser.h"
2017-01-02 14:26:05 -05:00
# include "lldb/Interpreter/CommandCompletions.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Symbol/Variable.h"
# include "lldb/Symbol/VariableList.h"
2015-07-03 12:57:06 -04:00
# include "lldb/Target/StackFrame.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Target/Target.h"
2017-04-16 12:04:10 -04:00
# include "lldb/Utility/StreamString.h"
2013-08-23 13:46:38 -04:00
using namespace lldb ;
using namespace lldb_private ;
2017-01-02 14:26:05 -05:00
static void AddWatchpointDescription ( Stream * s , Watchpoint * wp ,
lldb : : DescriptionLevel level ) {
s - > IndentMore ( ) ;
wp - > GetDescription ( s , level ) ;
s - > IndentLess ( ) ;
s - > EOL ( ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
static bool CheckTargetForWatchpointOperations ( Target * target ,
CommandReturnObject & result ) {
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No existing target or watchpoints. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
bool process_is_valid =
target - > GetProcessSP ( ) & & target - > GetProcessSP ( ) - > IsAlive ( ) ;
if ( ! process_is_valid ) {
result . AppendError ( " Thre's no process or it is not alive. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
// Target passes our checks, return true.
return true ;
2013-08-23 13:46:38 -04:00
}
// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
2017-01-02 14:26:05 -05:00
static const char * RSA [ 4 ] = { " - " , " to " , " To " , " TO " } ;
2013-08-23 13:46:38 -04:00
// Return the index to RSA if found; otherwise -1 is returned.
2017-01-02 14:26:05 -05:00
static int32_t WithRSAIndex ( llvm : : StringRef Arg ) {
uint32_t i ;
for ( i = 0 ; i < 4 ; + + i )
if ( Arg . find ( RSA [ i ] ) ! = llvm : : StringRef : : npos )
return i ;
return - 1 ;
2013-08-23 13:46:38 -04:00
}
// Return true if wp_ids is successfully populated with the watch ids.
// False otherwise.
2017-01-02 14:26:05 -05:00
bool CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs (
Target * target , Args & args , std : : vector < uint32_t > & wp_ids ) {
// Pre-condition: args.GetArgumentCount() > 0.
if ( args . GetArgumentCount ( ) = = 0 ) {
if ( target = = nullptr )
return false ;
WatchpointSP watch_sp = target - > GetLastCreatedWatchpoint ( ) ;
if ( watch_sp ) {
wp_ids . push_back ( watch_sp - > GetID ( ) ) ;
return true ;
} else
return false ;
}
llvm : : StringRef Minus ( " - " ) ;
std : : vector < llvm : : StringRef > StrRefArgs ;
llvm : : StringRef first ;
llvm : : StringRef second ;
size_t i ;
int32_t idx ;
// Go through the arguments and make a canonical form of arg list containing
// only numbers with possible "-" in between.
for ( auto & entry : args . entries ( ) ) {
if ( ( idx = WithRSAIndex ( entry . ref ) ) = = - 1 ) {
StrRefArgs . push_back ( entry . ref ) ;
continue ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
// The Arg contains the range specifier, split it, then.
std : : tie ( first , second ) = entry . ref . split ( RSA [ idx ] ) ;
if ( ! first . empty ( ) )
StrRefArgs . push_back ( first ) ;
StrRefArgs . push_back ( Minus ) ;
if ( ! second . empty ( ) )
StrRefArgs . push_back ( second ) ;
}
// Now process the canonical list and fill in the vector of uint32_t's.
// If there is any error, return false and the client should ignore wp_ids.
uint32_t beg , end , id ;
size_t size = StrRefArgs . size ( ) ;
bool in_range = false ;
for ( i = 0 ; i < size ; + + i ) {
llvm : : StringRef Arg = StrRefArgs [ i ] ;
if ( in_range ) {
// Look for the 'end' of the range. Note StringRef::getAsInteger()
// returns true to signify error while parsing.
if ( Arg . getAsInteger ( 0 , end ) )
return false ;
// Found a range! Now append the elements.
for ( id = beg ; id < = end ; + + id )
wp_ids . push_back ( id ) ;
in_range = false ;
continue ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( i < ( size - 1 ) & & StrRefArgs [ i + 1 ] = = Minus ) {
if ( Arg . getAsInteger ( 0 , beg ) )
2013-08-23 13:46:38 -04:00
return false ;
2017-01-02 14:26:05 -05:00
// Turn on the in_range flag, we are looking for end of range next.
+ + i ;
in_range = true ;
continue ;
}
// Otherwise, we have a simple ID. Just append it.
if ( Arg . getAsInteger ( 0 , beg ) )
return false ;
wp_ids . push_back ( beg ) ;
}
// It is an error if after the loop, we're still in_range.
if ( in_range )
return false ;
return true ; // Success!
2013-08-23 13:46:38 -04:00
}
//-------------------------------------------------------------------------
// CommandObjectWatchpointList
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
//-------------------------------------------------------------------------
// CommandObjectWatchpointList::Options
//-------------------------------------------------------------------------
# pragma mark List::CommandOptions
static OptionDefinition g_watchpoint_list_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_1 , false , " brief " , ' b ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Give a brief description of the watchpoint (no location info). " } ,
{ LLDB_OPT_SET_2 , false , " full " , ' f ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Give a full description of the watchpoint and its locations. " } ,
{ LLDB_OPT_SET_3 , false , " verbose " , ' v ' , OptionParser : : eNoArgument , nullptr , nullptr , 0 , eArgTypeNone , " Explain everything we know about the watchpoint (for debugging debugger bugs). " }
// clang-format on
} ;
2013-08-23 13:46:38 -04:00
# pragma mark List
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointList : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointList ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " watchpoint list " ,
" List all watchpoints at configurable levels of detail. " , nullptr ) ,
m_options ( ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeWatchpointID ,
eArgTypeWatchpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectWatchpointList ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( )
: Options ( ) ,
m_level ( lldb : : eDescriptionLevelBrief ) // Watchpoint List defaults to
// brief descriptions
{ }
~ CommandOptions ( ) override = default ;
2017-05-16 15:47:58 -04:00
Status SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Status error ;
2017-01-02 14:26:05 -05:00
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' b ' :
m_level = lldb : : eDescriptionLevelBrief ;
break ;
case ' f ' :
m_level = lldb : : eDescriptionLevelFull ;
break ;
case ' v ' :
m_level = lldb : : eDescriptionLevelVerbose ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_level = lldb : : eDescriptionLevelFull ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_watchpoint_list_options ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
lldb : : DescriptionLevel m_level ;
} ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = nullptr ) {
result . AppendError ( " Invalid target. No current target or watchpoints. " ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
if ( target - > GetProcessSP ( ) & & target - > GetProcessSP ( ) - > IsAlive ( ) ) {
uint32_t num_supported_hardware_watchpoints ;
2017-05-16 15:47:58 -04:00
Status error = target - > GetProcessSP ( ) - > GetWatchpointSupportInfo (
2017-01-02 14:26:05 -05:00
num_supported_hardware_watchpoints ) ;
if ( error . Success ( ) )
result . AppendMessageWithFormat (
" Number of supported hardware watchpoints: %u \n " ,
num_supported_hardware_watchpoints ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetWatchpointList ( ) . GetListMutex ( lock ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
size_t num_watchpoints = watchpoints . GetSize ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( num_watchpoints = = 0 ) {
result . AppendMessage ( " No watchpoints currently set. " ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
Stream & output_stream = result . GetOutputStream ( ) ;
if ( command . GetArgumentCount ( ) = = 0 ) {
// No watchpoint selected; show info about all currently set watchpoints.
result . AppendMessage ( " Current watchpoints: " ) ;
for ( size_t i = 0 ; i < num_watchpoints ; + + i ) {
Watchpoint * wp = watchpoints . GetByIndex ( i ) . get ( ) ;
AddWatchpointDescription ( & output_stream , wp , m_options . m_level ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular watchpoints selected; enable them.
std : : vector < uint32_t > wp_ids ;
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs (
target , command , wp_ids ) ) {
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
const size_t size = wp_ids . size ( ) ;
for ( size_t i = 0 ; i < size ; + + i ) {
Watchpoint * wp = watchpoints . FindByID ( wp_ids [ i ] ) . get ( ) ;
if ( wp )
AddWatchpointDescription ( & output_stream , wp , m_options . m_level ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
private :
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointEnable
//-------------------------------------------------------------------------
# pragma mark Enable
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointEnable : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointEnable ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " enable " ,
" Enable the specified disabled watchpoint(s). If "
" no watchpoints are specified, enable all of them. " ,
nullptr ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeWatchpointID ,
eArgTypeWatchpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectWatchpointEnable ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetWatchpointList ( ) . GetListMutex ( lock ) ;
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
size_t num_watchpoints = watchpoints . GetSize ( ) ;
if ( num_watchpoints = = 0 ) {
result . AppendError ( " No watchpoints exist to be enabled. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( command . GetArgumentCount ( ) = = 0 ) {
// No watchpoint selected; enable all currently set watchpoints.
target - > EnableAllWatchpoints ( ) ;
result . AppendMessageWithFormat ( " All watchpoints enabled. (% " PRIu64
" watchpoints) \n " ,
( uint64_t ) num_watchpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular watchpoints selected; enable them.
std : : vector < uint32_t > wp_ids ;
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs (
target , command , wp_ids ) ) {
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
int count = 0 ;
const size_t size = wp_ids . size ( ) ;
for ( size_t i = 0 ; i < size ; + + i )
if ( target - > EnableWatchpointByID ( wp_ids [ i ] ) )
+ + count ;
result . AppendMessageWithFormat ( " %d watchpoints enabled. \n " , count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointDisable
//-------------------------------------------------------------------------
# pragma mark Disable
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointDisable : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointDisable ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " watchpoint disable " ,
" Disable the specified watchpoint(s) without "
" removing it/them. If no watchpoints are "
" specified, disable them all. " ,
nullptr ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeWatchpointID ,
eArgTypeWatchpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectWatchpointDisable ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetWatchpointList ( ) . GetListMutex ( lock ) ;
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
size_t num_watchpoints = watchpoints . GetSize ( ) ;
if ( num_watchpoints = = 0 ) {
result . AppendError ( " No watchpoints exist to be disabled. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( command . GetArgumentCount ( ) = = 0 ) {
// No watchpoint selected; disable all currently set watchpoints.
if ( target - > DisableAllWatchpoints ( ) ) {
result . AppendMessageWithFormat ( " All watchpoints disabled. (% " PRIu64
" watchpoints) \n " ,
( uint64_t ) num_watchpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
result . AppendError ( " Disable all watchpoints failed \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
} else {
// Particular watchpoints selected; disable them.
std : : vector < uint32_t > wp_ids ;
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs (
target , command , wp_ids ) ) {
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
int count = 0 ;
const size_t size = wp_ids . size ( ) ;
for ( size_t i = 0 ; i < size ; + + i )
if ( target - > DisableWatchpointByID ( wp_ids [ i ] ) )
+ + count ;
result . AppendMessageWithFormat ( " %d watchpoints disabled. \n " , count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointDelete
//-------------------------------------------------------------------------
# pragma mark Delete
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointDelete : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointDelete ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " watchpoint delete " ,
" Delete the specified watchpoint(s). If no "
" watchpoints are specified, delete them all. " ,
nullptr ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeWatchpointID ,
eArgTypeWatchpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectWatchpointDelete ( ) override = default ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetWatchpointList ( ) . GetListMutex ( lock ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
size_t num_watchpoints = watchpoints . GetSize ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( num_watchpoints = = 0 ) {
result . AppendError ( " No watchpoints exist to be deleted. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( command . GetArgumentCount ( ) = = 0 ) {
if ( ! m_interpreter . Confirm (
" About to delete all watchpoints, do you want to do that? " ,
true ) ) {
result . AppendMessage ( " Operation cancelled... " ) ;
} else {
target - > RemoveAllWatchpoints ( ) ;
result . AppendMessageWithFormat ( " All watchpoints removed. (% " PRIu64
" watchpoints) \n " ,
( uint64_t ) num_watchpoints ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular watchpoints selected; delete them.
std : : vector < uint32_t > wp_ids ;
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs (
target , command , wp_ids ) ) {
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
int count = 0 ;
const size_t size = wp_ids . size ( ) ;
for ( size_t i = 0 ; i < size ; + + i )
if ( target - > RemoveWatchpointByID ( wp_ids [ i ] ) )
+ + count ;
result . AppendMessageWithFormat ( " %d watchpoints deleted. \n " , count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointIgnore
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
# pragma mark Ignore::CommandOptions
static OptionDefinition g_watchpoint_ignore_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , true , " ignore-count " , ' i ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeCount , " Set the number of times this watchpoint is skipped before stopping. " }
// clang-format on
} ;
class CommandObjectWatchpointIgnore : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointIgnore ( CommandInterpreter & interpreter )
: CommandObjectParsed ( interpreter , " watchpoint ignore " ,
" Set ignore count on the specified watchpoint(s). "
" If no watchpoints are specified, set them all. " ,
2016-07-23 16:50:09 -04:00
nullptr ) ,
2017-01-02 14:26:05 -05:00
m_options ( ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeWatchpointID ,
eArgTypeWatchpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectWatchpointIgnore ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) , m_ignore_count ( 0 ) { }
~ CommandOptions ( ) override = default ;
2017-05-16 15:47:58 -04:00
Status SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Status error ;
2017-01-02 14:26:05 -05:00
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' i ' :
if ( option_arg . getAsInteger ( 0 , m_ignore_count ) )
error . SetErrorStringWithFormat ( " invalid ignore count '%s' " ,
option_arg . str ( ) . c_str ( ) ) ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_ignore_count = 0 ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_watchpoint_ignore_options ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
uint32_t m_ignore_count ;
} ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
protected :
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetWatchpointList ( ) . GetListMutex ( lock ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
size_t num_watchpoints = watchpoints . GetSize ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( num_watchpoints = = 0 ) {
result . AppendError ( " No watchpoints exist to be ignored. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
if ( command . GetArgumentCount ( ) = = 0 ) {
target - > IgnoreAllWatchpoints ( m_options . m_ignore_count ) ;
result . AppendMessageWithFormat ( " All watchpoints ignored. (% " PRIu64
" watchpoints) \n " ,
( uint64_t ) num_watchpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular watchpoints selected; ignore them.
std : : vector < uint32_t > wp_ids ;
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs (
target , command , wp_ids ) ) {
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
int count = 0 ;
const size_t size = wp_ids . size ( ) ;
for ( size_t i = 0 ; i < size ; + + i )
if ( target - > IgnoreWatchpointByID ( wp_ids [ i ] , m_options . m_ignore_count ) )
+ + count ;
result . AppendMessageWithFormat ( " %d watchpoints ignored. \n " , count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
private :
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointModify
//-------------------------------------------------------------------------
2017-01-02 14:26:05 -05:00
# pragma mark Modify::CommandOptions
static OptionDefinition g_watchpoint_modify_options [ ] = {
// clang-format off
{ LLDB_OPT_SET_ALL , false , " condition " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeExpression , " The watchpoint stops only if this condition expression evaluates to true. " }
// clang-format on
} ;
2013-08-23 13:46:38 -04:00
# pragma mark Modify
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointModify : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointModify ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " watchpoint modify " ,
" Modify the options on a watchpoint or set of watchpoints in the "
" executable. "
" If no watchpoint is specified, act on the last created "
" watchpoint. "
" Passing an empty argument clears the modification. " ,
nullptr ) ,
m_options ( ) {
CommandArgumentEntry arg ;
CommandObject : : AddIDsArgumentData ( arg , eArgTypeWatchpointID ,
eArgTypeWatchpointIDRange ) ;
// Add the entry for the first argument for this command to the object's
// arguments vector.
m_arguments . push_back ( arg ) ;
}
~ CommandObjectWatchpointModify ( ) override = default ;
Options * GetOptions ( ) override { return & m_options ; }
class CommandOptions : public Options {
public :
CommandOptions ( ) : Options ( ) , m_condition ( ) , m_condition_passed ( false ) { }
~ CommandOptions ( ) override = default ;
2017-05-16 15:47:58 -04:00
Status SetOptionValue ( uint32_t option_idx , llvm : : StringRef option_arg ,
ExecutionContext * execution_context ) override {
Status error ;
2017-01-02 14:26:05 -05:00
const int short_option = m_getopt_table [ option_idx ] . val ;
switch ( short_option ) {
case ' c ' :
m_condition = option_arg ;
m_condition_passed = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " ,
short_option ) ;
break ;
}
return error ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
void OptionParsingStarting ( ExecutionContext * execution_context ) override {
m_condition . clear ( ) ;
m_condition_passed = false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
llvm : : ArrayRef < OptionDefinition > GetDefinitions ( ) override {
return llvm : : makeArrayRef ( g_watchpoint_modify_options ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Instance variables to hold the values for command options.
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
std : : string m_condition ;
bool m_condition_passed ;
} ;
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
std : : unique_lock < std : : recursive_mutex > lock ;
target - > GetWatchpointList ( ) . GetListMutex ( lock ) ;
2016-07-23 16:50:09 -04:00
2017-01-02 14:26:05 -05:00
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
size_t num_watchpoints = watchpoints . GetSize ( ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( num_watchpoints = = 0 ) {
result . AppendError ( " No watchpoints exist to be modified. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( command . GetArgumentCount ( ) = = 0 ) {
WatchpointSP wp_sp = target - > GetLastCreatedWatchpoint ( ) ;
wp_sp - > SetCondition ( m_options . m_condition . c_str ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
} else {
// Particular watchpoints selected; set condition on them.
std : : vector < uint32_t > wp_ids ;
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs (
target , command , wp_ids ) ) {
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
int count = 0 ;
const size_t size = wp_ids . size ( ) ;
for ( size_t i = 0 ; i < size ; + + i ) {
WatchpointSP wp_sp = watchpoints . FindByID ( wp_ids [ i ] ) ;
if ( wp_sp ) {
wp_sp - > SetCondition ( m_options . m_condition . c_str ( ) ) ;
+ + count ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
result . AppendMessageWithFormat ( " %d watchpoints modified. \n " , count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
private :
CommandOptions m_options ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointSetVariable
//-------------------------------------------------------------------------
# pragma mark SetVariable
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointSetVariable : public CommandObjectParsed {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointSetVariable ( CommandInterpreter & interpreter )
: CommandObjectParsed (
interpreter , " watchpoint set variable " ,
" Set a watchpoint on a variable. "
" Use the '-w' option to specify the type of watchpoint and "
" the '-s' option to specify the byte size to watch for. "
" If no '-w' option is specified, it defaults to write. "
" If no '-s' option is specified, it defaults to the variable's "
" byte size. "
" Note that there are limited hardware resources for watchpoints. "
" If watchpoint setting fails, consider disable/delete existing "
" ones "
" to free up resources. " ,
nullptr ,
eCommandRequiresFrame | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched | eCommandProcessMustBePaused ) ,
m_option_group ( ) , m_option_watchpoint ( ) {
SetHelpLong (
R " (
2015-09-06 10:32:30 -04:00
Examples :
( lldb ) watchpoint set variable - w read_write my_global_var
2017-01-02 14:26:05 -05:00
) "
" Watches my_global_var for read/write access, with the region to watch \
corresponding to the byte size of the data type . " );
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
CommandArgumentEntry arg ;
CommandArgumentData var_name_arg ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Define the only variant of this arg.
var_name_arg . arg_type = eArgTypeVarName ;
var_name_arg . arg_repetition = eArgRepeatPlain ;
// Push the variant into the argument entry.
arg . push_back ( var_name_arg ) ;
// Push the data for the only argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
// Absorb the '-w' and '-s' options into our option group.
m_option_group . Append ( & m_option_watchpoint , LLDB_OPT_SET_ALL ,
LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
~ CommandObjectWatchpointSetVariable ( ) override = default ;
Options * GetOptions ( ) override { return & m_option_group ; }
2013-08-23 13:46:38 -04:00
protected :
2017-01-02 14:26:05 -05:00
static size_t GetVariableCallback ( void * baton , const char * name ,
VariableList & variable_list ) {
Target * target = static_cast < Target * > ( baton ) ;
if ( target ) {
return target - > GetImages ( ) . FindGlobalVariables ( ConstString ( name ) , true ,
UINT32_MAX , variable_list ) ;
}
return 0 ;
}
bool DoExecute ( Args & command , CommandReturnObject & result ) override {
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
StackFrame * frame = m_exe_ctx . GetFramePtr ( ) ;
// If no argument is present, issue an error message. There's no way to set
// a watchpoint.
if ( command . GetArgumentCount ( ) < = 0 ) {
result . GetErrorStream ( ) . Printf ( " error: required argument missing; "
" specify your program variable to watch "
" for \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
// If no '-w' is specified, default to '-w write'.
if ( ! m_option_watchpoint . watch_type_specified ) {
m_option_watchpoint . watch_type = OptionGroupWatchpoint : : eWatchWrite ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// We passed the sanity check for the command.
// Proceed to set the watchpoint now.
lldb : : addr_t addr = 0 ;
size_t size = 0 ;
VariableSP var_sp ;
ValueObjectSP valobj_sp ;
Stream & output_stream = result . GetOutputStream ( ) ;
// A simple watch variable gesture allows only one argument.
if ( command . GetArgumentCount ( ) ! = 1 ) {
result . GetErrorStream ( ) . Printf (
" error: specify exactly one variable to watch for \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Things have checked out ok...
2017-05-16 15:47:58 -04:00
Status error ;
2017-01-02 14:26:05 -05:00
uint32_t expr_path_options =
StackFrame : : eExpressionPathOptionCheckPtrVsMember |
StackFrame : : eExpressionPathOptionsAllowDirectIVarAccess ;
valobj_sp = frame - > GetValueForVariableExpressionPath (
command . GetArgumentAtIndex ( 0 ) , eNoDynamicValues , expr_path_options ,
var_sp , error ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( ! valobj_sp ) {
// Not in the frame; let's check the globals.
VariableList variable_list ;
ValueObjectList valobj_list ;
2017-05-16 15:47:58 -04:00
Status error ( Variable : : GetValuesForVariableExpressionPath (
2017-01-02 14:26:05 -05:00
command . GetArgumentAtIndex ( 0 ) ,
m_exe_ctx . GetBestExecutionContextScope ( ) , GetVariableCallback , target ,
variable_list , valobj_list ) ) ;
if ( valobj_list . GetSize ( ) )
valobj_sp = valobj_list . GetValueObjectAtIndex ( 0 ) ;
}
CompilerType compiler_type ;
if ( valobj_sp ) {
AddressType addr_type ;
addr = valobj_sp - > GetAddressOf ( false , & addr_type ) ;
if ( addr_type = = eAddressTypeLoad ) {
// We're in business.
// Find out the size of this variable.
size = m_option_watchpoint . watch_size = = 0
? valobj_sp - > GetByteSize ( )
: m_option_watchpoint . watch_size ;
}
compiler_type = valobj_sp - > GetCompilerType ( ) ;
} else {
const char * error_cstr = error . AsCString ( nullptr ) ;
if ( error_cstr )
result . GetErrorStream ( ) . Printf ( " error: %s \n " , error_cstr ) ;
else
result . GetErrorStream ( ) . Printf ( " error: unable to find any variable "
" expression path that matches '%s' \n " ,
command . GetArgumentAtIndex ( 0 ) ) ;
return false ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Now it's time to create the watchpoint.
uint32_t watch_type = m_option_watchpoint . watch_type ;
error . Clear ( ) ;
Watchpoint * wp =
target - > CreateWatchpoint ( addr , size , & compiler_type , watch_type , error )
. get ( ) ;
if ( wp ) {
wp - > SetWatchSpec ( command . GetArgumentAtIndex ( 0 ) ) ;
wp - > SetWatchVariable ( true ) ;
if ( var_sp & & var_sp - > GetDeclaration ( ) . GetFile ( ) ) {
StreamString ss ;
// True to show fullpath for declaration file.
var_sp - > GetDeclaration ( ) . DumpStopContext ( & ss , true ) ;
wp - > SetDeclInfo ( ss . GetString ( ) ) ;
}
output_stream . Printf ( " Watchpoint created: " ) ;
wp - > GetDescription ( & output_stream , lldb : : eDescriptionLevelFull ) ;
output_stream . EOL ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendErrorWithFormat (
" Watchpoint creation failed (addr=0x% " PRIx64 " , size=% " PRIu64
" , variable expression='%s'). \n " ,
addr , ( uint64_t ) size , command . GetArgumentAtIndex ( 0 ) ) ;
if ( error . AsCString ( nullptr ) )
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupWatchpoint m_option_watchpoint ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointSetExpression
//-------------------------------------------------------------------------
# pragma mark Set
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointSetExpression ( CommandInterpreter & interpreter )
: CommandObjectRaw (
interpreter , " watchpoint set expression " ,
" Set a watchpoint on an address by supplying an expression. "
" Use the '-w' option to specify the type of watchpoint and "
" the '-s' option to specify the byte size to watch for. "
" If no '-w' option is specified, it defaults to write. "
" If no '-s' option is specified, it defaults to the target's "
" pointer byte size. "
" Note that there are limited hardware resources for watchpoints. "
" If watchpoint setting fails, consider disable/delete existing "
" ones "
" to free up resources. " ,
" " ,
eCommandRequiresFrame | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched | eCommandProcessMustBePaused ) ,
m_option_group ( ) , m_option_watchpoint ( ) {
SetHelpLong (
R " (
2015-09-06 10:32:30 -04:00
Examples :
2016-07-23 16:50:09 -04:00
( lldb ) watchpoint set expression - w write - s 1 - - foo + 32
2015-09-06 10:32:30 -04:00
2017-01-02 14:26:05 -05:00
Watches write access for the 1 - byte region pointed to by the address ' foo + 32 ' ) " );
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
CommandArgumentEntry arg ;
CommandArgumentData expression_arg ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Define the only variant of this arg.
expression_arg . arg_type = eArgTypeExpression ;
expression_arg . arg_repetition = eArgRepeatPlain ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Push the only variant into the argument entry.
arg . push_back ( expression_arg ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Push the data for the only argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Absorb the '-w' and '-s' options into our option group.
m_option_group . Append ( & m_option_watchpoint , LLDB_OPT_SET_ALL ,
LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
~ CommandObjectWatchpointSetExpression ( ) override = default ;
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
// Overrides base class's behavior where WantsCompletion =
// !WantsRawCommandString.
bool WantsCompletion ( ) override { return true ; }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
Options * GetOptions ( ) override { return & m_option_group ; }
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
protected :
bool DoExecute ( const char * raw_command ,
CommandReturnObject & result ) override {
auto exe_ctx = GetCommandInterpreter ( ) . GetExecutionContext ( ) ;
m_option_group . NotifyOptionParsingStarting (
& exe_ctx ) ; // This is a raw command, so notify the option group
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
StackFrame * frame = m_exe_ctx . GetFramePtr ( ) ;
Args command ( raw_command ) ;
const char * expr = nullptr ;
if ( raw_command [ 0 ] = = ' - ' ) {
// We have some options and these options MUST end with --.
const char * end_options = nullptr ;
const char * s = raw_command ;
while ( s & & s [ 0 ] ) {
end_options = : : strstr ( s , " -- " ) ;
if ( end_options ) {
end_options + = 2 ; // Get past the "--"
if ( : : isspace ( end_options [ 0 ] ) ) {
expr = end_options ;
while ( : : isspace ( * expr ) )
+ + expr ;
break ;
}
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
s = end_options ;
}
if ( end_options ) {
Args args ( llvm : : StringRef ( raw_command , end_options - raw_command ) ) ;
if ( ! ParseOptions ( args , result ) )
return false ;
2017-05-16 15:47:58 -04:00
Status error ( m_option_group . NotifyOptionParsingFinished ( & exe_ctx ) ) ;
2017-01-02 14:26:05 -05:00
if ( error . Fail ( ) ) {
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
}
}
2013-08-23 13:46:38 -04:00
2017-01-02 14:26:05 -05:00
if ( expr = = nullptr )
expr = raw_command ;
// If no argument is present, issue an error message. There's no way to set
// a watchpoint.
if ( command . GetArgumentCount ( ) = = 0 ) {
result . GetErrorStream ( ) . Printf ( " error: required argument missing; "
" specify an expression to evaulate into "
" the address to watch for \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2013-08-23 13:46:38 -04:00
}
2017-01-02 14:26:05 -05:00
// If no '-w' is specified, default to '-w write'.
if ( ! m_option_watchpoint . watch_type_specified ) {
m_option_watchpoint . watch_type = OptionGroupWatchpoint : : eWatchWrite ;
}
// We passed the sanity check for the command.
// Proceed to set the watchpoint now.
lldb : : addr_t addr = 0 ;
size_t size = 0 ;
ValueObjectSP valobj_sp ;
// Use expression evaluation to arrive at the address to watch.
EvaluateExpressionOptions options ;
options . SetCoerceToId ( false ) ;
options . SetUnwindOnError ( true ) ;
options . SetKeepInMemory ( false ) ;
options . SetTryAllThreads ( true ) ;
options . SetTimeout ( llvm : : None ) ;
ExpressionResults expr_result =
target - > EvaluateExpression ( expr , frame , valobj_sp , options ) ;
if ( expr_result ! = eExpressionCompleted ) {
result . GetErrorStream ( ) . Printf (
" error: expression evaluation of address to watch failed \n " ) ;
result . GetErrorStream ( ) . Printf ( " expression evaluated: %s \n " , expr ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
// Get the address to watch.
bool success = false ;
addr = valobj_sp - > GetValueAsUnsigned ( 0 , & success ) ;
if ( ! success ) {
result . GetErrorStream ( ) . Printf (
" error: expression did not evaluate to an address \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
if ( m_option_watchpoint . watch_size ! = 0 )
size = m_option_watchpoint . watch_size ;
else
size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
// Now it's time to create the watchpoint.
uint32_t watch_type = m_option_watchpoint . watch_type ;
// Fetch the type from the value object, the type of the watched object is
// the pointee type
/// of the expression, so convert to that if we found a valid type.
CompilerType compiler_type ( valobj_sp - > GetCompilerType ( ) ) ;
2017-05-16 15:47:58 -04:00
Status error ;
2017-01-02 14:26:05 -05:00
Watchpoint * wp =
target - > CreateWatchpoint ( addr , size , & compiler_type , watch_type , error )
. get ( ) ;
if ( wp ) {
Stream & output_stream = result . GetOutputStream ( ) ;
output_stream . Printf ( " Watchpoint created: " ) ;
wp - > GetDescription ( & output_stream , lldb : : eDescriptionLevelFull ) ;
output_stream . EOL ( ) ;
result . SetStatus ( eReturnStatusSuccessFinishResult ) ;
} else {
result . AppendErrorWithFormat ( " Watchpoint creation failed (addr=0x% " PRIx64
" , size=% " PRIu64 " ). \n " ,
addr , ( uint64_t ) size ) ;
if ( error . AsCString ( nullptr ) )
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
2013-08-23 13:46:38 -04:00
private :
2017-01-02 14:26:05 -05:00
OptionGroupOptions m_option_group ;
OptionGroupWatchpoint m_option_watchpoint ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectWatchpointSet
//-------------------------------------------------------------------------
# pragma mark Set
2017-01-02 14:26:05 -05:00
class CommandObjectWatchpointSet : public CommandObjectMultiword {
2013-08-23 13:46:38 -04:00
public :
2017-01-02 14:26:05 -05:00
CommandObjectWatchpointSet ( CommandInterpreter & interpreter )
: CommandObjectMultiword (
interpreter , " watchpoint set " , " Commands for setting a watchpoint. " ,
" watchpoint set <subcommand> [<subcommand-options>] " ) {
LoadSubCommand (
" variable " ,
CommandObjectSP ( new CommandObjectWatchpointSetVariable ( interpreter ) ) ) ;
LoadSubCommand (
" expression " ,
CommandObjectSP ( new CommandObjectWatchpointSetExpression ( interpreter ) ) ) ;
}
~ CommandObjectWatchpointSet ( ) override = default ;
2013-08-23 13:46:38 -04:00
} ;
//-------------------------------------------------------------------------
// CommandObjectMultiwordWatchpoint
//-------------------------------------------------------------------------
# pragma mark MultiwordWatchpoint
2017-01-02 14:26:05 -05:00
CommandObjectMultiwordWatchpoint : : CommandObjectMultiwordWatchpoint (
CommandInterpreter & interpreter )
: CommandObjectMultiword ( interpreter , " watchpoint " ,
" Commands for operating on watchpoints. " ,
" watchpoint <subcommand> [<command-options>] " ) {
CommandObjectSP list_command_object (
new CommandObjectWatchpointList ( interpreter ) ) ;
CommandObjectSP enable_command_object (
new CommandObjectWatchpointEnable ( interpreter ) ) ;
CommandObjectSP disable_command_object (
new CommandObjectWatchpointDisable ( interpreter ) ) ;
CommandObjectSP delete_command_object (
new CommandObjectWatchpointDelete ( interpreter ) ) ;
CommandObjectSP ignore_command_object (
new CommandObjectWatchpointIgnore ( interpreter ) ) ;
CommandObjectSP command_command_object (
new CommandObjectWatchpointCommand ( interpreter ) ) ;
CommandObjectSP modify_command_object (
new CommandObjectWatchpointModify ( interpreter ) ) ;
CommandObjectSP set_command_object (
new CommandObjectWatchpointSet ( interpreter ) ) ;
list_command_object - > SetCommandName ( " watchpoint list " ) ;
enable_command_object - > SetCommandName ( " watchpoint enable " ) ;
disable_command_object - > SetCommandName ( " watchpoint disable " ) ;
delete_command_object - > SetCommandName ( " watchpoint delete " ) ;
ignore_command_object - > SetCommandName ( " watchpoint ignore " ) ;
command_command_object - > SetCommandName ( " watchpoint command " ) ;
modify_command_object - > SetCommandName ( " watchpoint modify " ) ;
set_command_object - > SetCommandName ( " watchpoint set " ) ;
LoadSubCommand ( " list " , list_command_object ) ;
LoadSubCommand ( " enable " , enable_command_object ) ;
LoadSubCommand ( " disable " , disable_command_object ) ;
LoadSubCommand ( " delete " , delete_command_object ) ;
LoadSubCommand ( " ignore " , ignore_command_object ) ;
LoadSubCommand ( " command " , command_command_object ) ;
LoadSubCommand ( " modify " , modify_command_object ) ;
LoadSubCommand ( " set " , set_command_object ) ;
2013-08-23 13:46:38 -04:00
}
2016-07-23 16:50:09 -04:00
CommandObjectMultiwordWatchpoint : : ~ CommandObjectMultiwordWatchpoint ( ) = default ;