2011-09-23 02:04:58 +08: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"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
2011-10-14 08:42:25 +08:00
# include "lldb/Breakpoint/Watchpoint.h"
# include "lldb/Breakpoint/WatchpointList.h"
2011-09-23 02:04:58 +08:00
# include "lldb/Core/StreamString.h"
2012-01-31 05:46:17 +08:00
# include "lldb/Core/ValueObject.h"
# include "lldb/Core/ValueObjectVariable.h"
2011-09-23 02:04:58 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Interpreter/CommandReturnObject.h"
# include "lldb/Interpreter/CommandCompletions.h"
2012-01-31 05:46:17 +08:00
# include "lldb/Symbol/Variable.h"
# include "lldb/Symbol/VariableList.h"
# include "lldb/Target/Target.h"
2011-09-23 02:04:58 +08:00
# include <vector>
using namespace lldb ;
using namespace lldb_private ;
static void
2011-10-14 08:42:25 +08:00
AddWatchpointDescription ( Stream * s , Watchpoint * wp , lldb : : DescriptionLevel level )
2011-09-23 02:04:58 +08:00
{
s - > IndentMore ( ) ;
2011-10-14 08:42:25 +08:00
wp - > GetDescription ( s , level ) ;
2011-09-23 02:04:58 +08:00
s - > IndentLess ( ) ;
s - > EOL ( ) ;
}
static bool
CheckTargetForWatchpointOperations ( Target * target , CommandReturnObject & result )
{
if ( target = = NULL )
{
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 ;
}
2012-06-09 05:56:10 +08:00
// FIXME: This doesn't seem to be the right place for this functionality.
2011-09-23 02:04:58 +08:00
# include "llvm/ADT/StringRef.h"
2012-06-09 05:56:10 +08:00
static inline void StripLeadingSpaces ( llvm : : StringRef & Str )
{
while ( ! Str . empty ( ) & & isspace ( Str [ 0 ] ) )
Str = Str . substr ( 1 ) ;
}
static inline llvm : : StringRef StripOptionTerminator ( llvm : : StringRef & Str , bool with_dash_w , bool with_dash_x )
{
llvm : : StringRef ExprStr = Str ;
// Get rid of the leading spaces first.
StripLeadingSpaces ( ExprStr ) ;
// If there's no '-w' and no '-x', we can just return.
if ( ! with_dash_w & & ! with_dash_x )
return ExprStr ;
// Otherwise, split on the "--" option terminator string, and return the rest of the string.
ExprStr = ExprStr . split ( " -- " ) . second ;
StripLeadingSpaces ( ExprStr ) ;
return ExprStr ;
}
2011-09-23 02:04:58 +08:00
// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
static const char * RSA [ 4 ] = { " - " , " to " , " To " , " TO " } ;
// Return the index to RSA if found; otherwise -1 is returned.
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 ;
}
// Return true if wp_ids is successfully populated with the watch ids.
// False otherwise.
2012-06-20 06:12:58 +08:00
bool
CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs ( Args & args , std : : vector < uint32_t > & wp_ids )
2011-09-23 02:04:58 +08:00
{
// Pre-condition: args.GetArgumentCount() > 0.
assert ( args . GetArgumentCount ( ) > 0 ) ;
llvm : : StringRef Minus ( " - " ) ;
std : : vector < llvm : : StringRef > StrRefArgs ;
std : : pair < llvm : : StringRef , llvm : : StringRef > Pair ;
size_t i ;
int32_t idx ;
// Go through the argments and make a canonical form of arg list containing
// only numbers with possible "-" in between.
for ( i = 0 ; i < args . GetArgumentCount ( ) ; + + i ) {
llvm : : StringRef Arg ( args . GetArgumentAtIndex ( i ) ) ;
if ( ( idx = WithRSAIndex ( Arg ) ) = = - 1 ) {
StrRefArgs . push_back ( Arg ) ;
continue ;
}
// The Arg contains the range specifier, split it, then.
Pair = Arg . split ( RSA [ idx ] ) ;
if ( ! Pair . first . empty ( ) )
StrRefArgs . push_back ( Pair . first ) ;
StrRefArgs . push_back ( Minus ) ;
if ( ! Pair . second . empty ( ) )
StrRefArgs . push_back ( Pair . 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 ;
}
if ( i < ( size - 1 ) & & StrRefArgs [ i + 1 ] = = Minus ) {
if ( Arg . getAsInteger ( 0 , beg ) )
return false ;
// 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!
}
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
// CommandObjectWatchpointList
2011-09-23 02:04:58 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
# pragma mark List
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointList : public CommandObjectParsed
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
public :
CommandObjectWatchpointList ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" watchpoint list " ,
" List all watchpoints at configurable levels of detail. " ,
NULL ) ,
m_options ( interpreter )
{
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 ) ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointList ( ) { }
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
virtual Options *
GetOptions ( )
{
return & m_options ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
class CommandOptions : public Options
{
public :
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
m_level ( lldb : : eDescriptionLevelBrief ) // Watchpoint List defaults to brief descriptions
{
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandOptions ( ) { }
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
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 ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
return error ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
void
OptionParsingStarting ( )
{
2011-09-23 02:04:58 +08:00
m_level = lldb : : eDescriptionLevelFull ;
2012-06-09 05:56:10 +08:00
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
// Options table: Required for subclasses of Options.
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
static OptionDefinition g_option_table [ ] ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
// Instance variables to hold the values for command options.
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
lldb : : DescriptionLevel m_level ;
} ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
protected :
virtual bool
DoExecute ( Args & command , CommandReturnObject & result )
2012-05-24 05:09:52 +08:00
{
2012-06-09 05:56:10 +08:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( target = = NULL )
{
result . AppendError ( " Invalid target. No current target or watchpoints. " ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
if ( target - > GetProcessSP ( ) & & target - > GetProcessSP ( ) - > IsAlive ( ) )
{
uint32_t num_supported_hardware_watchpoints ;
Error error = target - > GetProcessSP ( ) - > GetWatchpointSupportInfo ( num_supported_hardware_watchpoints ) ;
if ( error . Success ( ) )
result . AppendMessageWithFormat ( " Number of supported hardware watchpoints: %u \n " ,
num_supported_hardware_watchpoints ) ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
Mutex : : Locker locker ;
target - > GetWatchpointList ( ) . GetListMutex ( locker ) ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
size_t num_watchpoints = watchpoints . GetSize ( ) ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
if ( num_watchpoints = = 0 )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
result . AppendMessage ( " No watchpoints currently set. " ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
return true ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
Stream & output_stream = result . GetOutputStream ( ) ;
if ( command . GetArgumentCount ( ) = = 0 )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
// 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 ( ) ;
2011-10-14 08:42:25 +08:00
AddWatchpointDescription ( & output_stream , wp , m_options . m_level ) ;
2012-06-09 05:56:10 +08:00
}
2011-09-23 02:04:58 +08:00
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
2012-06-09 05:56:10 +08:00
else
{
// Particular watchpoints selected; enable them.
std : : vector < uint32_t > wp_ids ;
2012-06-20 06:12:58 +08:00
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs ( command , wp_ids ) )
2012-06-09 05:56:10 +08:00
{
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
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 ) ;
}
}
return result . Succeeded ( ) ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
private :
CommandOptions m_options ;
} ;
2011-09-23 02:04:58 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
// CommandObjectWatchpointList::Options
2011-09-23 02:04:58 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
# pragma mark List::CommandOptions
OptionDefinition
CommandObjectWatchpointList : : CommandOptions : : g_option_table [ ] =
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
{ LLDB_OPT_SET_1 , false , " brief " , ' b ' , no_argument , NULL , 0 , eArgTypeNone ,
" Give a brief description of the watchpoint (no location info). " } ,
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
{ LLDB_OPT_SET_2 , false , " full " , ' f ' , no_argument , NULL , 0 , eArgTypeNone ,
" Give a full description of the watchpoint and its locations. " } ,
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
{ LLDB_OPT_SET_3 , false , " verbose " , ' v ' , no_argument , NULL , 0 , eArgTypeNone ,
" Explain everything we know about the watchpoint (for debugging debugger bugs). " } ,
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
//-------------------------------------------------------------------------
// CommandObjectWatchpointEnable
//-------------------------------------------------------------------------
# pragma mark Enable
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointEnable : public CommandObjectParsed
{
public :
CommandObjectWatchpointEnable ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" enable " ,
" Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them. " ,
NULL )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
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 ) ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointEnable ( ) { }
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
Mutex : : Locker locker ;
target - > GetWatchpointList ( ) . GetListMutex ( locker ) ;
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
size_t num_watchpoints = watchpoints . GetSize ( ) ;
if ( num_watchpoints = = 0 )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
result . AppendError ( " No watchpoints exist to be enabled. " ) ;
2011-09-23 02:04:58 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-06-09 05:56:10 +08:00
if ( command . GetArgumentCount ( ) = = 0 )
{
// No watchpoint selected; enable all currently set watchpoints.
target - > EnableAllWatchpoints ( ) ;
result . AppendMessageWithFormat ( " All watchpoints enabled. (%lu watchpoints) \n " , num_watchpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
// Particular watchpoints selected; enable them.
std : : vector < uint32_t > wp_ids ;
2012-06-20 06:12:58 +08:00
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs ( command , wp_ids ) )
2012-06-09 05:56:10 +08:00
{
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 ) ;
}
return result . Succeeded ( ) ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
private :
} ;
2011-09-23 02:04:58 +08:00
//-------------------------------------------------------------------------
// CommandObjectWatchpointDisable
//-------------------------------------------------------------------------
# pragma mark Disable
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointDisable : public CommandObjectParsed
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
public :
CommandObjectWatchpointDisable ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" watchpoint disable " ,
" Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all. " ,
NULL )
{
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 ) ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointDisable ( ) { }
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
protected :
virtual bool
DoExecute ( Args & command , CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
Mutex : : Locker locker ;
target - > GetWatchpointList ( ) . GetListMutex ( locker ) ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
size_t num_watchpoints = watchpoints . GetSize ( ) ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
if ( num_watchpoints = = 0 )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
result . AppendError ( " No watchpoints exist to be disabled. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
if ( command . GetArgumentCount ( ) = = 0 )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
// No watchpoint selected; disable all currently set watchpoints.
if ( target - > DisableAllWatchpoints ( ) )
{
result . AppendMessageWithFormat ( " All watchpoints disabled. (%lu watchpoints) \n " , num_watchpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
result . AppendError ( " Disable all watchpoints failed \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
else
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
// Particular watchpoints selected; disable them.
std : : vector < uint32_t > wp_ids ;
2012-06-20 06:12:58 +08:00
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs ( command , wp_ids ) )
2012-06-09 05:56:10 +08:00
{
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 ) ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
return result . Succeeded ( ) ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
} ;
2011-09-23 02:04:58 +08:00
//-------------------------------------------------------------------------
// CommandObjectWatchpointDelete
//-------------------------------------------------------------------------
# pragma mark Delete
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointDelete : public CommandObjectParsed
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
public :
CommandObjectWatchpointDelete ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" watchpoint delete " ,
" Delete the specified watchpoint(s). If no watchpoints are specified, delete them all. " ,
NULL )
{
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 ) ;
}
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointDelete ( ) { }
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
protected :
virtual bool
DoExecute ( Args & command , CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
Mutex : : Locker locker ;
target - > GetWatchpointList ( ) . GetListMutex ( locker ) ;
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
size_t num_watchpoints = watchpoints . GetSize ( ) ;
2011-09-23 02:04:58 +08:00
2012-06-09 05:56:10 +08:00
if ( num_watchpoints = = 0 )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
result . AppendError ( " No watchpoints exist to be deleted. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
if ( command . GetArgumentCount ( ) = = 0 )
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
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. (%lu watchpoints) \n " , num_watchpoints ) ;
}
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
2011-09-23 02:04:58 +08:00
{
2012-06-09 05:56:10 +08:00
// Particular watchpoints selected; delete them.
std : : vector < uint32_t > wp_ids ;
2012-06-20 06:12:58 +08:00
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs ( command , wp_ids ) )
2012-06-09 05:56:10 +08:00
{
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 ) ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
return result . Succeeded ( ) ;
2011-09-23 02:04:58 +08:00
}
2012-06-09 05:56:10 +08:00
} ;
2011-09-23 02:04:58 +08:00
2011-10-06 05:35:46 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
// CommandObjectWatchpointIgnore
2011-10-06 05:35:46 +08:00
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointIgnore : public CommandObjectParsed
2011-10-06 05:35:46 +08:00
{
2012-06-09 05:56:10 +08:00
public :
CommandObjectWatchpointIgnore ( CommandInterpreter & interpreter ) :
CommandObjectParsed ( interpreter ,
" watchpoint ignore " ,
" Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all. " ,
NULL ) ,
m_options ( interpreter )
{
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 ) ;
}
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointIgnore ( ) { }
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
virtual Options *
GetOptions ( )
{
return & m_options ;
}
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
class CommandOptions : public Options
2011-10-06 05:35:46 +08:00
{
2012-06-09 05:56:10 +08:00
public :
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
m_ignore_count ( 0 )
2011-10-06 05:35:46 +08:00
{
}
2012-06-09 05:56:10 +08:00
virtual
~ CommandOptions ( ) { }
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
switch ( short_option )
{
case ' i ' :
{
m_ignore_count = Args : : StringToUInt32 ( option_arg , UINT32_MAX , 0 ) ;
if ( m_ignore_count = = UINT32_MAX )
error . SetErrorStringWithFormat ( " invalid ignore count '%s' " , option_arg ) ;
}
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " , short_option ) ;
break ;
}
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
return error ;
}
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
void
OptionParsingStarting ( )
{
m_ignore_count = 0 ;
}
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
// Options table: Required for subclasses of Options.
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
static OptionDefinition g_option_table [ ] ;
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
// Instance variables to hold the values for command options.
uint32_t m_ignore_count ;
} ;
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
2011-10-06 05:35:46 +08:00
{
2012-06-09 05:56:10 +08:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
Mutex : : Locker locker ;
target - > GetWatchpointList ( ) . GetListMutex ( locker ) ;
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
size_t num_watchpoints = watchpoints . GetSize ( ) ;
if ( num_watchpoints = = 0 )
2011-10-06 05:35:46 +08:00
{
2012-06-09 05:56:10 +08:00
result . AppendError ( " No watchpoints exist to be ignored. " ) ;
2011-10-06 05:35:46 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-06-09 05:56:10 +08:00
if ( command . GetArgumentCount ( ) = = 0 )
{
target - > IgnoreAllWatchpoints ( m_options . m_ignore_count ) ;
result . AppendMessageWithFormat ( " All watchpoints ignored. (%lu watchpoints) \n " , num_watchpoints ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
// Particular watchpoints selected; ignore them.
std : : vector < uint32_t > wp_ids ;
2012-06-20 06:12:58 +08:00
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs ( command , wp_ids ) )
2012-06-09 05:56:10 +08:00
{
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2011-10-06 05:35:46 +08:00
2012-06-09 05:56:10 +08:00
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 ) ;
}
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
return result . Succeeded ( ) ;
}
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
private :
CommandOptions m_options ;
} ;
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
# pragma mark Ignore::CommandOptions
2011-10-18 02:58:00 +08:00
OptionDefinition
2012-06-09 05:56:10 +08:00
CommandObjectWatchpointIgnore : : CommandOptions : : g_option_table [ ] =
2011-10-18 02:58:00 +08:00
{
2012-06-09 05:56:10 +08:00
{ LLDB_OPT_SET_ALL , true , " ignore-count " , ' i ' , required_argument , NULL , NULL , eArgTypeCount , " Set the number of times this watchpoint is skipped before stopping. " } ,
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
2011-10-18 02:58:00 +08:00
} ;
2012-06-09 05:56:10 +08:00
//-------------------------------------------------------------------------
// CommandObjectWatchpointModify
//-------------------------------------------------------------------------
# pragma mark Modify
class CommandObjectWatchpointModify : public CommandObjectParsed
2011-10-18 02:58:00 +08:00
{
2012-06-09 05:56:10 +08:00
public :
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. " ,
NULL ) ,
m_options ( interpreter )
{
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 ) ;
}
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointModify ( ) { }
virtual Options *
GetOptions ( )
2011-10-18 02:58:00 +08:00
{
2012-06-09 05:56:10 +08:00
return & m_options ;
2011-10-18 02:58:00 +08:00
}
2012-06-09 05:56:10 +08:00
class CommandOptions : public Options
{
public :
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
CommandOptions ( CommandInterpreter & interpreter ) :
Options ( interpreter ) ,
m_condition ( ) ,
m_condition_passed ( false )
{
}
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandOptions ( ) { }
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
virtual Error
SetOptionValue ( uint32_t option_idx , const char * option_arg )
{
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
switch ( short_option )
{
case ' c ' :
if ( option_arg ! = NULL )
m_condition . assign ( option_arg ) ;
else
m_condition . clear ( ) ;
m_condition_passed = true ;
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " , short_option ) ;
break ;
}
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
return error ;
}
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
void
OptionParsingStarting ( )
{
m_condition . clear ( ) ;
m_condition_passed = false ;
}
const OptionDefinition *
GetDefinitions ( )
{
return g_option_table ;
}
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
// Options table: Required for subclasses of Options.
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
static OptionDefinition g_option_table [ ] ;
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
// Instance variables to hold the values for command options.
2011-10-18 02:58:00 +08:00
2012-06-09 05:56:10 +08:00
std : : string m_condition ;
bool m_condition_passed ;
} ;
protected :
virtual bool
DoExecute ( Args & command , CommandReturnObject & result )
2011-10-18 02:58:00 +08:00
{
2012-06-09 05:56:10 +08:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
if ( ! CheckTargetForWatchpointOperations ( target , result ) )
return false ;
Mutex : : Locker locker ;
target - > GetWatchpointList ( ) . GetListMutex ( locker ) ;
const WatchpointList & watchpoints = target - > GetWatchpointList ( ) ;
size_t num_watchpoints = watchpoints . GetSize ( ) ;
if ( num_watchpoints = = 0 )
2011-10-18 02:58:00 +08:00
{
2012-06-09 05:56:10 +08:00
result . AppendError ( " No watchpoints exist to be modified. " ) ;
2011-10-18 02:58:00 +08:00
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-06-09 05:56:10 +08:00
if ( command . GetArgumentCount ( ) = = 0 )
{
WatchpointSP wp_sp = target - > GetLastCreatedWatchpoint ( ) ;
wp_sp - > SetCondition ( m_options . m_condition . c_str ( ) ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
2011-10-18 02:58:00 +08:00
{
2012-06-09 05:56:10 +08:00
// Particular watchpoints selected; set condition on them.
std : : vector < uint32_t > wp_ids ;
2012-06-20 06:12:58 +08:00
if ( ! CommandObjectMultiwordWatchpoint : : VerifyWatchpointIDs ( command , wp_ids ) )
2011-10-18 02:58:00 +08:00
{
2012-06-09 05:56:10 +08:00
result . AppendError ( " Invalid watchpoints specification. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2011-10-18 02:58:00 +08:00
}
2012-06-09 05:56:10 +08:00
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 ;
}
}
result . AppendMessageWithFormat ( " %d watchpoints modified. \n " , count ) ;
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
return result . Succeeded ( ) ;
}
2012-02-08 09:13:31 +08:00
2012-06-09 05:56:10 +08:00
private :
CommandOptions m_options ;
} ;
2012-02-08 09:13:31 +08:00
2012-06-09 05:56:10 +08:00
# pragma mark Modify::CommandOptions
OptionDefinition
CommandObjectWatchpointModify : : CommandOptions : : g_option_table [ ] =
2012-02-08 09:13:31 +08:00
{
2012-06-09 05:56:10 +08:00
{ LLDB_OPT_SET_ALL , false , " condition " , ' c ' , required_argument , NULL , NULL , eArgTypeExpression , " The watchpoint stops only if this condition expression evaluates to true. " } ,
{ 0 , false , NULL , 0 , 0 , NULL , 0 , eArgTypeNone , NULL }
} ;
2012-02-08 09:13:31 +08:00
2012-02-09 06:37:48 +08:00
//-------------------------------------------------------------------------
// CommandObjectWatchpointSetVariable
//-------------------------------------------------------------------------
2012-06-09 05:56:10 +08:00
# pragma mark SetVariable
2012-02-08 09:13:31 +08:00
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointSetVariable : public CommandObjectParsed
2012-02-08 09:13:31 +08:00
{
2012-06-09 05:56:10 +08:00
public :
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 '-x' option to specify the byte size to watch for. "
2012-06-30 03:35:01 +08:00
" If no '-w' option is specified, it defaults to write. "
2012-06-09 05:56:10 +08:00
" If no '-x' 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. " ,
NULL ,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused ) ,
m_option_group ( interpreter ) ,
m_option_watchpoint ( )
2012-02-09 06:37:48 +08:00
{
2012-06-09 05:56:10 +08:00
SetHelpLong (
" Examples: \n \
\ n \
watchpoint set variable - w read_wriate my_global_var \ n \
# Watch my_global_var for read / write access, with the region to watch corresponding to the byte size of the data type.\n");
CommandArgumentEntry arg ;
CommandArgumentData var_name_arg ;
// 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 '-x' options into our option group.
m_option_group . Append ( & m_option_watchpoint , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
2012-02-09 06:37:48 +08:00
}
2012-02-08 09:13:31 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointSetVariable ( ) { }
virtual Options *
GetOptions ( )
2012-02-08 09:13:31 +08:00
{
2012-06-09 05:56:10 +08:00
return & m_option_group ;
2012-02-08 09:13:31 +08:00
}
2012-06-09 05:56:10 +08:00
protected :
virtual bool
DoExecute ( Args & command ,
CommandReturnObject & result )
2012-02-09 06:37:48 +08:00
{
2012-06-09 05:56:10 +08:00
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
StackFrame * frame = exe_ctx . GetFramePtr ( ) ;
if ( frame = = NULL )
{
result . AppendError ( " you must be stopped in a valid stack frame to set a watchpoint. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-02-08 09:13:31 +08:00
2012-06-09 05:56:10 +08:00
// 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 ;
}
2012-02-09 06:37:48 +08:00
2012-06-30 03:35:01 +08:00
// If no '-w' is specified, default to '-w write'.
2012-06-09 05:56:10 +08:00
if ( ! m_option_watchpoint . watch_type_specified )
{
2012-06-30 03:35:01 +08:00
m_option_watchpoint . watch_type = OptionGroupWatchpoint : : eWatchWrite ;
2012-06-09 05:56:10 +08:00
}
2012-02-09 06:37:48 +08:00
2012-06-09 05:56:10 +08: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 ;
}
2012-02-09 06:37:48 +08:00
2012-06-09 05:56:10 +08:00
// Things have checked out ok...
Error error ;
2012-07-14 08:53:55 +08:00
uint32_t expr_path_options = StackFrame : : eExpressionPathOptionCheckPtrVsMember |
StackFrame : : eExpressionPathOptionsAllowDirectIVarAccess ;
2012-06-09 05:56:10 +08:00
valobj_sp = frame - > GetValueForVariableExpressionPath ( command . GetArgumentAtIndex ( 0 ) ,
eNoDynamicValues ,
expr_path_options ,
var_sp ,
error ) ;
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 ;
}
} else {
const char * error_cstr = error . AsCString ( NULL ) ;
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 ;
2012-02-09 06:37:48 +08:00
}
2012-06-09 05:56:10 +08: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 , watch_type , error ) . get ( ) ;
if ( wp ) {
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 ( ) ) ;
}
2012-02-09 06:37:48 +08:00
StreamString ss ;
2012-06-09 05:56:10 +08:00
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%llx, size=%lu). \n " ,
addr , size ) ;
if ( error . AsCString ( NULL ) )
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
2012-02-09 06:37:48 +08:00
}
2012-06-09 05:56:10 +08:00
return result . Succeeded ( ) ;
2012-02-09 06:37:48 +08:00
}
2012-06-09 05:56:10 +08:00
private :
OptionGroupOptions m_option_group ;
OptionGroupWatchpoint m_option_watchpoint ;
} ;
2012-02-08 09:13:31 +08:00
2012-01-31 05:46:17 +08:00
//-------------------------------------------------------------------------
2012-02-09 06:37:48 +08:00
// CommandObjectWatchpointSetExpression
2012-01-31 05:46:17 +08:00
//-------------------------------------------------------------------------
# pragma mark Set
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointSetExpression : public CommandObjectRaw
2012-01-31 05:46:17 +08:00
{
2012-06-09 05:56:10 +08:00
public :
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 '-x' option to specify the byte size to watch for. "
2012-06-30 03:35:01 +08:00
" If no '-w' option is specified, it defaults to write. "
2012-06-09 05:56:10 +08:00
" If no '-x' 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. " ,
NULL ,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused ) ,
m_option_group ( interpreter ) ,
m_option_watchpoint ( )
{
SetHelpLong (
" Examples: \n \
\ n \
watchpoint set expression - w write - x 1 - - foo + 32 \ n \
# Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n");
CommandArgumentEntry arg ;
CommandArgumentData expression_arg ;
// Define the only variant of this arg.
expression_arg . arg_type = eArgTypeExpression ;
expression_arg . arg_repetition = eArgRepeatPlain ;
// Push the only variant into the argument entry.
arg . push_back ( expression_arg ) ;
// Push the data for the only argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
// Absorb the '-w' and '-x' options into our option group.
m_option_group . Append ( & m_option_watchpoint , LLDB_OPT_SET_ALL , LLDB_OPT_SET_1 ) ;
m_option_group . Finalize ( ) ;
}
2012-02-08 09:13:31 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointSetExpression ( ) { }
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
virtual bool
WantsCompletion ( ) { return true ; }
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
virtual Options *
GetOptions ( )
{
return & m_option_group ;
}
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
protected :
virtual bool
DoExecute ( const char * raw_command , CommandReturnObject & result )
{
Target * target = m_interpreter . GetDebugger ( ) . GetSelectedTarget ( ) . get ( ) ;
ExecutionContext exe_ctx ( m_interpreter . GetExecutionContext ( ) ) ;
StackFrame * frame = exe_ctx . GetFramePtr ( ) ;
if ( frame = = NULL )
{
result . AppendError ( " you must be stopped in a valid stack frame to set a watchpoint. " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-02-09 06:37:48 +08:00
2012-06-09 05:56:10 +08:00
Args command ( raw_command ) ;
2012-02-09 06:37:48 +08:00
2012-06-09 05:56:10 +08:00
// Process possible options.
if ( ! ParseOptions ( command , result ) )
return false ;
2012-02-09 06:37:48 +08:00
2012-06-09 05:56:10 +08:00
// 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 addres to watch for \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
bool with_dash_w = m_option_watchpoint . watch_type_specified ;
bool with_dash_x = ( m_option_watchpoint . watch_size ! = 0 ) ;
2012-02-09 06:37:48 +08:00
2012-06-30 03:35:01 +08:00
// If no '-w' is specified, default to '-w write'.
2012-06-09 05:56:10 +08:00
if ( ! with_dash_w )
{
2012-06-30 03:35:01 +08:00
m_option_watchpoint . watch_type = OptionGroupWatchpoint : : eWatchWrite ;
2012-06-09 05:56:10 +08:00
}
2012-02-09 06:37:48 +08:00
2012-06-09 05:56:10 +08:00
// We passed the sanity check for the command.
// Proceed to set the watchpoint now.
lldb : : addr_t addr = 0 ;
size_t size = 0 ;
2012-02-08 09:13:31 +08:00
2012-06-09 05:56:10 +08:00
VariableSP var_sp ;
ValueObjectSP valobj_sp ;
Stream & output_stream = result . GetOutputStream ( ) ;
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
// We will process the raw command string to rid of the '-w', '-x', or '--'
llvm : : StringRef raw_expr_str ( raw_command ) ;
std : : string expr_str = StripOptionTerminator ( raw_expr_str , with_dash_w , with_dash_x ) . str ( ) ;
// Sanity check for when the user forgets to terminate the option strings with a '--'.
if ( ( with_dash_w | | with_dash_w ) & & expr_str . empty ( ) )
{
result . GetErrorStream ( ) . Printf ( " error: did you forget to enter the option terminator string \" -- \" ? \n " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
// Use expression evaluation to arrive at the address to watch.
const bool coerce_to_id = true ;
const bool unwind_on_error = true ;
const bool keep_in_memory = false ;
ExecutionResults expr_result = target - > EvaluateExpression ( expr_str . c_str ( ) ,
frame ,
eExecutionPolicyOnlyWhenNeeded ,
coerce_to_id ,
unwind_on_error ,
keep_in_memory ,
eNoDynamicValues ,
2012-07-17 07:10:35 +08:00
valobj_sp ,
0 /* no timeout */ ) ;
2012-06-09 05:56:10 +08:00
if ( expr_result ! = eExecutionCompleted ) {
result . GetErrorStream ( ) . Printf ( " error: expression evaluation of address to watch failed \n " ) ;
result . GetErrorStream ( ) . Printf ( " expression evaluated: %s \n " , expr_str . c_str ( ) ) ;
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 ;
}
size = with_dash_x ? m_option_watchpoint . watch_size
: target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
// Now it's time to create the watchpoint.
uint32_t watch_type = m_option_watchpoint . watch_type ;
Error error ;
Watchpoint * wp = target - > CreateWatchpoint ( addr , size , watch_type , error ) . get ( ) ;
if ( wp ) {
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 ( ) ) ;
}
StreamString ss ;
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%llx, size=%lu). \n " ,
addr , size ) ;
if ( error . AsCString ( NULL ) )
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
2012-01-31 05:46:17 +08:00
}
2012-06-09 05:56:10 +08:00
private :
OptionGroupOptions m_option_group ;
OptionGroupWatchpoint m_option_watchpoint ;
} ;
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
//-------------------------------------------------------------------------
// CommandObjectWatchpointSet
//-------------------------------------------------------------------------
# pragma mark Set
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
class CommandObjectWatchpointSet : public CommandObjectMultiword
{
public :
2012-02-10 02:44:27 +08:00
2012-06-09 05:56:10 +08:00
CommandObjectWatchpointSet ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" watchpoint set " ,
" A set of commands for setting a watchpoint. " ,
" watchpoint set <subcommand> [<subcommand-options>] " )
2012-02-10 02:44:27 +08:00
{
2012-06-09 05:56:10 +08:00
LoadSubCommand ( " variable " , CommandObjectSP ( new CommandObjectWatchpointSetVariable ( interpreter ) ) ) ;
LoadSubCommand ( " expression " , CommandObjectSP ( new CommandObjectWatchpointSetExpression ( interpreter ) ) ) ;
2012-02-10 02:44:27 +08:00
}
2012-02-09 06:37:48 +08:00
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
virtual
~ CommandObjectWatchpointSet ( ) { }
2012-01-31 05:46:17 +08:00
2012-06-09 05:56:10 +08:00
} ;
//-------------------------------------------------------------------------
// CommandObjectMultiwordWatchpoint
//-------------------------------------------------------------------------
# pragma mark MultiwordWatchpoint
CommandObjectMultiwordWatchpoint : : CommandObjectMultiwordWatchpoint ( CommandInterpreter & interpreter ) :
CommandObjectMultiword ( interpreter ,
" watchpoint " ,
" A set of commands for operating on watchpoints. " ,
" watchpoint <command> [<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 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 " ) ;
modify_command_object - > SetCommandName ( " watchpoint modify " ) ;
set_command_object - > SetCommandName ( " watchpoint set " ) ;
2012-07-17 11:23:13 +08:00
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 ( " modify " , modify_command_object ) ;
LoadSubCommand ( " set " , set_command_object ) ;
2012-01-31 05:46:17 +08:00
}
2012-06-09 05:56:10 +08:00
CommandObjectMultiwordWatchpoint : : ~ CommandObjectMultiwordWatchpoint ( )
{
}