forked from OSchip/llvm-project
After discussions with Jim and Greg, modify the 'watchpoint set' command to become a mutiword command
with subcommand 'expression' and 'variable'. The first subcommand is for supplying an expression to be evaluated into an address to watch for, while the second is for watching a variable. 'watchpoint set expression' is a raw command, which means that you need to use the "--" option terminator to end the '-w' or '-x' option processing and to start typing your expression. Also update several test cases to comply and add a couple of test cases into TestCompletion.py, in particular, test that 'watchpoint set ex' completes to 'watchpoint set expression ' and that 'watchpoint set var' completes to 'watchpoint set variable '. llvm-svn: 150109
This commit is contained in:
parent
8610a59de1
commit
2ffa754a6f
|
@ -57,7 +57,7 @@ namespace lldb_private {
|
|||
|
||||
WatchType watch_type;
|
||||
uint32_t watch_size;
|
||||
bool watch_variable;
|
||||
bool watch_type_specified;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(OptionGroupWatchpoint);
|
||||
|
|
|
@ -433,7 +433,7 @@ public:
|
|||
if (variable_list)
|
||||
{
|
||||
// If watching a variable, there are certain restrictions to be followed.
|
||||
if (m_option_watchpoint.watch_variable)
|
||||
if (m_option_watchpoint.watch_type_specified)
|
||||
{
|
||||
if (command.GetArgumentCount() != 1) {
|
||||
result.GetErrorStream().Printf("error: specify exactly one variable when using the '-w' option\n");
|
||||
|
@ -544,7 +544,7 @@ public:
|
|||
options,
|
||||
format);
|
||||
// Process watchpoint if necessary.
|
||||
if (m_option_watchpoint.watch_variable)
|
||||
if (m_option_watchpoint.watch_type_specified)
|
||||
{
|
||||
AddressType addr_type;
|
||||
lldb::addr_t addr = 0;
|
||||
|
|
|
@ -852,146 +852,86 @@ CommandObjectWatchpointModify::Execute
|
|||
return result.Succeeded();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointSet::CommandOptions
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark Set::CommandOptions
|
||||
|
||||
CommandObjectWatchpointSet::CommandOptions::CommandOptions() :
|
||||
OptionGroup()
|
||||
{
|
||||
}
|
||||
|
||||
CommandObjectWatchpointSet::CommandOptions::~CommandOptions ()
|
||||
{
|
||||
}
|
||||
|
||||
OptionDefinition
|
||||
CommandObjectWatchpointSet::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_1, true, "expression", 'e', no_argument, NULL, NULL, eArgTypeNone, "Watch an address with an expression specified at the end."},
|
||||
{ LLDB_OPT_SET_2, true, "variable", 'v', no_argument, NULL, NULL, eArgTypeNone, "Watch a variable name specified at the end."}
|
||||
};
|
||||
|
||||
uint32_t
|
||||
CommandObjectWatchpointSet::CommandOptions::GetNumDefinitions ()
|
||||
{
|
||||
return sizeof(g_option_table)/sizeof(OptionDefinition);
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
CommandObjectWatchpointSet::CommandOptions::GetDefinitions ()
|
||||
{
|
||||
return g_option_table;
|
||||
}
|
||||
|
||||
Error
|
||||
CommandObjectWatchpointSet::CommandOptions::SetOptionValue (CommandInterpreter &interpreter,
|
||||
uint32_t option_idx,
|
||||
const char *option_arg)
|
||||
{
|
||||
Error error;
|
||||
char short_option = (char) g_option_table[option_idx].short_option;
|
||||
|
||||
switch (short_option)
|
||||
{
|
||||
case 'e':
|
||||
m_do_expression = true;
|
||||
break;
|
||||
case 'v':
|
||||
m_do_variable = true;
|
||||
break;
|
||||
default:
|
||||
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
CommandObjectWatchpointSet::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
|
||||
{
|
||||
m_do_expression = false;
|
||||
m_do_variable = false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointSet
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark Set
|
||||
|
||||
CommandObjectWatchpointSet::CommandObjectWatchpointSet (CommandInterpreter &interpreter) :
|
||||
CommandObject (interpreter,
|
||||
"watchpoint set",
|
||||
"Set a watchpoint. "
|
||||
"You can choose to watch a variable in scope with the '-v' option "
|
||||
"or to watch an address with the '-e' option 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. "
|
||||
"If no '-w' option is specified, it defaults to read_write. "
|
||||
"Note that hardware resources for watching are often limited.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
m_option_group (interpreter),
|
||||
m_option_watchpoint (),
|
||||
m_command_options ()
|
||||
CommandObjectMultiword (interpreter,
|
||||
"watchpoint set",
|
||||
"A set of commands for setting a watchpoint.",
|
||||
"watchpoint set <subcommand> [<subcommand-options>]")
|
||||
{
|
||||
SetHelpLong(
|
||||
"Examples: \n\
|
||||
\n\
|
||||
watchpoint set -w read_wriate -v 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\
|
||||
\n\
|
||||
watchpoint set -w write -x 1 -e foo + 32\n\
|
||||
# Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n\
|
||||
# If no '-x' option is specified, byte size defaults to 4.\n");
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData var_name_arg, expression_arg;
|
||||
|
||||
// Define the first variant of this arg.
|
||||
expression_arg.arg_type = eArgTypeExpression;
|
||||
expression_arg.arg_repetition = eArgRepeatPlain;
|
||||
expression_arg.arg_opt_set_association = LLDB_OPT_SET_1;
|
||||
|
||||
// Define the second variant of this arg.
|
||||
var_name_arg.arg_type = eArgTypeVarName;
|
||||
var_name_arg.arg_repetition = eArgRepeatPlain;
|
||||
var_name_arg.arg_opt_set_association = LLDB_OPT_SET_2;
|
||||
|
||||
// Push the two variants into the argument entry.
|
||||
arg.push_back (expression_arg);
|
||||
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 the '-e' (LLDB_OPT_SET_1) set as
|
||||
// well as the '-v' (LLDB_OPT_SET_2) set.
|
||||
m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_1, LLDB_OPT_SET_1|LLDB_OPT_SET_2);
|
||||
m_option_group.Append (&m_command_options);
|
||||
m_option_group.Finalize();
|
||||
|
||||
LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter)));
|
||||
LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter)));
|
||||
}
|
||||
|
||||
CommandObjectWatchpointSet::~CommandObjectWatchpointSet ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointSetVariable
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark Set
|
||||
|
||||
CommandObjectWatchpointSetVariable::CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter) :
|
||||
CommandObject (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. "
|
||||
"If no '-w' option is specified, it defaults to read_write. "
|
||||
"If no '-x' option is specified, it defaults to the variable's "
|
||||
"byte size. "
|
||||
"Note that hardware resources for watching are often limited.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
m_option_group (interpreter),
|
||||
m_option_watchpoint ()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
CommandObjectWatchpointSetVariable::~CommandObjectWatchpointSetVariable ()
|
||||
{
|
||||
}
|
||||
|
||||
Options *
|
||||
CommandObjectWatchpointSet::GetOptions ()
|
||||
CommandObjectWatchpointSetVariable::GetOptions ()
|
||||
{
|
||||
return &m_option_group;
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObjectWatchpointSet::Execute
|
||||
CommandObjectWatchpointSetVariable::Execute
|
||||
(
|
||||
Args& command,
|
||||
CommandReturnObject &result
|
||||
)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
if (frame == NULL)
|
||||
|
@ -1004,18 +944,14 @@ CommandObjectWatchpointSet::Execute
|
|||
// 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 ('-v') or an address ('-e') to watch for\n");
|
||||
result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
// It's either '-e' to watch an address with expression' or '-v' to watch a variable.
|
||||
bool watch_address = m_command_options.m_do_expression;
|
||||
|
||||
// If no '-w' is specified, default to '-w read_write'.
|
||||
if (!m_option_watchpoint.watch_variable)
|
||||
if (!m_option_watchpoint.watch_type_specified)
|
||||
{
|
||||
m_option_watchpoint.watch_variable = true;
|
||||
m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite;
|
||||
}
|
||||
|
||||
|
@ -1028,70 +964,38 @@ CommandObjectWatchpointSet::Execute
|
|||
ValueObjectSP valobj_sp;
|
||||
Stream &output_stream = result.GetOutputStream();
|
||||
|
||||
if (watch_address) {
|
||||
// Use expression evaluation to arrive at the address to watch.
|
||||
std::string expr_str;
|
||||
command.GetQuotedCommandString(expr_str);
|
||||
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,
|
||||
valobj_sp);
|
||||
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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Get the address to watch.
|
||||
addr = valobj_sp->GetValueAsUnsigned(0);
|
||||
if (!addr) {
|
||||
result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
// Things have checked out ok...
|
||||
Error error;
|
||||
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
|
||||
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;
|
||||
}
|
||||
size = m_option_watchpoint.watch_size == 0 ? 4 /* Could use a better default size? */
|
||||
: m_option_watchpoint.watch_size;
|
||||
} else {
|
||||
// A simple watch variable gesture allows only one argument.
|
||||
if (command.GetArgumentCount() != 1) {
|
||||
result.GetErrorStream().Printf("error: specify exactly one variable with the '-v' option\n");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Things have checked out ok...
|
||||
Error error;
|
||||
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// Now it's time to create the watchpoint.
|
||||
|
@ -1117,3 +1021,184 @@ CommandObjectWatchpointSet::Execute
|
|||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointSetExpression
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark Set
|
||||
|
||||
CommandObjectWatchpointSetExpression::CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) :
|
||||
CommandObject (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. "
|
||||
"If no '-w' option is specified, it defaults to read_write. "
|
||||
"If no '-x' option is specified, it defaults to the target's "
|
||||
"pointer byte size. "
|
||||
"Note that hardware resources for watching are often limited.",
|
||||
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();
|
||||
}
|
||||
|
||||
CommandObjectWatchpointSetExpression::~CommandObjectWatchpointSetExpression ()
|
||||
{
|
||||
}
|
||||
|
||||
Options *
|
||||
CommandObjectWatchpointSetExpression::GetOptions ()
|
||||
{
|
||||
return &m_option_group;
|
||||
}
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
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;
|
||||
}
|
||||
bool
|
||||
CommandObjectWatchpointSetExpression::ExecuteRawCommandString
|
||||
(
|
||||
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;
|
||||
}
|
||||
|
||||
Args command(raw_command);
|
||||
|
||||
// Process possible options.
|
||||
if (!ParseOptions (command, result))
|
||||
return false;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
bool no_dash_w = !m_option_watchpoint.watch_type_specified;
|
||||
bool no_dash_x = (m_option_watchpoint.watch_size == 0);
|
||||
|
||||
// If no '-w' is specified, default to '-w read_write'.
|
||||
if (no_dash_w)
|
||||
{
|
||||
m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// 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, !no_dash_w, !no_dash_x).str();
|
||||
|
||||
// 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,
|
||||
valobj_sp);
|
||||
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);
|
||||
}
|
||||
|
||||
// Get the address to watch.
|
||||
addr = valobj_sp->GetValueAsUnsigned(0);
|
||||
if (!addr) {
|
||||
result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
size = no_dash_x ? target->GetArchitecture().GetAddressByteSize()
|
||||
: m_option_watchpoint.watch_size;
|
||||
|
||||
// Now it's time to create the watchpoint.
|
||||
uint32_t watch_type = m_option_watchpoint.watch_type;
|
||||
Watchpoint *wp = exe_ctx.GetTargetRef().CreateWatchpoint(addr, size, watch_type).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);
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
|
|
@ -247,45 +247,27 @@ private:
|
|||
// CommandObjectWatchpointSet
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class CommandObjectWatchpointSet : public CommandObject
|
||||
class CommandObjectWatchpointSet : public CommandObjectMultiword
|
||||
{
|
||||
public:
|
||||
|
||||
class CommandOptions : public OptionGroup
|
||||
{
|
||||
public:
|
||||
|
||||
CommandOptions ();
|
||||
|
||||
virtual
|
||||
~CommandOptions ();
|
||||
|
||||
virtual uint32_t
|
||||
GetNumDefinitions ();
|
||||
|
||||
virtual const OptionDefinition*
|
||||
GetDefinitions ();
|
||||
|
||||
virtual Error
|
||||
SetOptionValue (CommandInterpreter &interpreter,
|
||||
uint32_t option_idx,
|
||||
const char *option_value);
|
||||
|
||||
virtual void
|
||||
OptionParsingStarting (CommandInterpreter &interpreter);
|
||||
|
||||
// Options table: Required for subclasses of Options.
|
||||
|
||||
static OptionDefinition g_option_table[];
|
||||
bool m_do_expression;
|
||||
bool m_do_variable;
|
||||
};
|
||||
|
||||
CommandObjectWatchpointSet (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectWatchpointSet ();
|
||||
|
||||
|
||||
};
|
||||
|
||||
class CommandObjectWatchpointSetVariable : public CommandObject
|
||||
{
|
||||
public:
|
||||
|
||||
CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectWatchpointSetVariable ();
|
||||
|
||||
virtual bool
|
||||
Execute (Args& command,
|
||||
CommandReturnObject &result);
|
||||
|
@ -296,7 +278,39 @@ public:
|
|||
private:
|
||||
OptionGroupOptions m_option_group;
|
||||
OptionGroupWatchpoint m_option_watchpoint;
|
||||
CommandOptions m_command_options;
|
||||
};
|
||||
|
||||
class CommandObjectWatchpointSetExpression : public CommandObject
|
||||
{
|
||||
public:
|
||||
|
||||
CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectWatchpointSetExpression ();
|
||||
|
||||
virtual bool
|
||||
Execute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{ return false; }
|
||||
|
||||
virtual bool
|
||||
WantsRawCommandString() { return true; }
|
||||
|
||||
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
|
||||
virtual bool
|
||||
WantsCompletion() { return true; }
|
||||
|
||||
virtual bool
|
||||
ExecuteRawCommandString (const char *raw_command,
|
||||
CommandReturnObject &result);
|
||||
|
||||
virtual Options *
|
||||
GetOptions ();
|
||||
|
||||
private:
|
||||
OptionGroupOptions m_option_group;
|
||||
OptionGroupWatchpoint m_option_watchpoint;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -66,7 +66,7 @@ OptionGroupWatchpoint::SetOptionValue (CommandInterpreter &interpreter,
|
|||
case 'w':
|
||||
watch_type = (WatchType) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
|
||||
if (error.Success())
|
||||
watch_variable = true;
|
||||
watch_type_specified = true;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
|
@ -84,7 +84,7 @@ OptionGroupWatchpoint::SetOptionValue (CommandInterpreter &interpreter,
|
|||
void
|
||||
OptionGroupWatchpoint::OptionParsingStarting (CommandInterpreter &interpreter)
|
||||
{
|
||||
watch_variable = false;
|
||||
watch_type_specified = false;
|
||||
watch_type = eWatchInvalid;
|
||||
watch_size = 0;
|
||||
}
|
||||
|
|
|
@ -26,13 +26,17 @@ class CommandLineCompletionTestCase(TestBase):
|
|||
"""Test that 'frame variable -w ' completes to ['Available completions:', 'read', 'write', 'read_write']."""
|
||||
self.complete_from_to('frame variable -w ', ['Available completions:', 'read', 'write', 'read_write'])
|
||||
|
||||
def test_watchpoint_set_dash_x(self):
|
||||
"""Test that 'watchpoint set -x' completes to 'watchpoint set -x '."""
|
||||
self.complete_from_to('watchpoint set -x', 'watchpoint set -x ')
|
||||
def test_watchpoint_set_ex(self):
|
||||
"""Test that 'watchpoint set ex' completes to 'watchpoint set expression '."""
|
||||
self.complete_from_to('watchpoint set ex', 'watchpoint set expression ')
|
||||
|
||||
def test_watchpoint_set_dash_w_read_underbar(self):
|
||||
"""Test that 'watchpoint set -w read_' completes to 'watchpoint set -w read_write'."""
|
||||
self.complete_from_to('watchpoint set -w read_', 'watchpoint set -w read_write')
|
||||
def test_watchpoint_set_var(self):
|
||||
"""Test that 'watchpoint set var' completes to 'watchpoint set variable '."""
|
||||
self.complete_from_to('watchpoint set var', 'watchpoint set variable ')
|
||||
|
||||
def test_watchpoint_set_variable_dash_w_read_underbar(self):
|
||||
"""Test that 'watchpoint set variable -w read_' completes to 'watchpoint set variable -w read_write'."""
|
||||
self.complete_from_to('watchpoint set variable -w read_', 'watchpoint set variable -w read_write')
|
||||
|
||||
def test_help_fi(self):
|
||||
"""Test that 'help fi' completes to ['Available completions:', 'file', 'finish']."""
|
||||
|
|
|
@ -75,7 +75,7 @@ class HelloWatchpointTestCase(TestBase):
|
|||
substrs = ['Watchpoint created', 'size = 4', 'type = w',
|
||||
'%s:%d' % (self.source, self.decl)])
|
||||
else:
|
||||
self.expect("watchpoint set -w write -v global", WATCHPOINT_CREATED,
|
||||
self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED,
|
||||
substrs = ['Watchpoint created', 'size = 4', 'type = w',
|
||||
'%s:%d' % (self.source, self.decl)])
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ class WatchLocationUsingWatchpointSetTestCase(TestBase):
|
|||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
def test_watchlocation_with_dsym_using_watchpoint_set(self):
|
||||
"""Test watching a location with 'watchpoint set -w write -x size' option."""
|
||||
"""Test watching a location with 'watchpoint set expression -w write -x size' option."""
|
||||
self.buildDsym(dictionary=self.d)
|
||||
self.setTearDownCleanup(dictionary=self.d)
|
||||
self.watchlocation_using_watchpoint_set()
|
||||
|
||||
def test_watchlocation_with_dwarf_using_watchpoint_set(self):
|
||||
"""Test watching a location with 'watchpoint set -w write -x size' option."""
|
||||
"""Test watching a location with 'watchpoint set expression -w write -x size' option."""
|
||||
self.buildDwarf(dictionary=self.d)
|
||||
self.setTearDownCleanup(dictionary=self.d)
|
||||
self.watchlocation_using_watchpoint_set()
|
||||
|
@ -60,7 +60,7 @@ class WatchLocationUsingWatchpointSetTestCase(TestBase):
|
|||
# with offset as 7.
|
||||
# The main.cpp, by design, misbehaves by not following the agreed upon
|
||||
# protocol of only accessing the allowable index range of [0, 6].
|
||||
self.expect("watchpoint set -w write -x 1 -e g_char_ptr + 7", WATCHPOINT_CREATED,
|
||||
self.expect("watchpoint set expression -w write -x 1 -- g_char_ptr + 7", WATCHPOINT_CREATED,
|
||||
substrs = ['Watchpoint created', 'size = 1', 'type = w'])
|
||||
self.runCmd("expr unsigned val = g_char_ptr[7]; val")
|
||||
self.expect(self.res.GetOutput().splitlines()[0], exe=False,
|
||||
|
|
|
@ -49,18 +49,20 @@ class WatchpointSetErrorTestCase(TestBase):
|
|||
|
||||
# Try some error conditions:
|
||||
|
||||
# No argument is an error.
|
||||
self.expect("watchpoint set", error=True,
|
||||
startstr = 'error: invalid combination of options for the given command')
|
||||
self.runCmd("watchpoint set -v -w read_write", check=False)
|
||||
# 'watchpoint set' is now a multiword command.
|
||||
self.expect("watchpoint set",
|
||||
substrs = ['The following subcommands are supported:',
|
||||
'expression',
|
||||
'variable'])
|
||||
self.runCmd("watchpoint set variable -w read_write", check=False)
|
||||
|
||||
# 'watchpoint set' now takes a mandatory '-v' or '-e' option to
|
||||
# indicate watching for either variable or address.
|
||||
self.expect("watchpoint set -w write global", error=True,
|
||||
startstr = 'error: invalid combination of options for the given command')
|
||||
# 'watchpoint set expression' with '-w' or '-x' specified now needs
|
||||
# an option terminator and a raw expression after that.
|
||||
self.expect("watchpoint set expression -w write --", error=True,
|
||||
startstr = 'error: required argument missing; specify an expression to evaulate into the addres to watch for')
|
||||
|
||||
# Wrong size parameter is an error.
|
||||
self.expect("watchpoint set -x -128", error=True,
|
||||
self.expect("watchpoint set variable -x -128", error=True,
|
||||
substrs = ['invalid enumeration value'])
|
||||
|
||||
|
||||
|
|
|
@ -122,11 +122,12 @@ class HelpCommandTestCase(TestBase):
|
|||
substrs = ['<watchpt-id-list>'])
|
||||
|
||||
def test_help_watchpoint_set(self):
|
||||
"""Test that 'help watchpoint set' prints out <expr> for the '-e' option
|
||||
and <variable-name> for the '-v' option."""
|
||||
"""Test that 'help watchpoint set' prints out 'expression' and 'variable'
|
||||
as the possible subcommands."""
|
||||
self.expect("help watchpoint set",
|
||||
patterns = ['watchpoint set -e.*<expr>',
|
||||
'watchpoint set -v.*<variable-name>'])
|
||||
substrs = ['The following subcommands are supported:'],
|
||||
patterns = ['expression +--',
|
||||
'variable +--'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in New Issue