forked from OSchip/llvm-project
[lldb/Command] Add --force option for `watchpoint delete` command
Currently, there is no option to delete all the watchpoint without LLDB asking for a confirmation. Besides making the watchpoint delete command homogeneous with the breakpoint delete command, this option could also become handy to trigger automated watchpoint deletion i.e. using breakpoint actions. rdar://42560586 Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
This commit is contained in:
parent
b63bc648a4
commit
3620e5f28a
|
@ -155,6 +155,56 @@ class WatchpointCommandsTestCase(TestBase):
|
|||
self.expect("process status",
|
||||
substrs=['exited'])
|
||||
|
||||
# Read-write watchpoints not supported on SystemZ
|
||||
@expectedFailureAll(archs=['s390x'])
|
||||
def test_rw_watchpoint_delete(self):
|
||||
"""Test delete watchpoint and expect not to stop for watchpoint."""
|
||||
self.build(dictionary=self.d)
|
||||
self.setTearDownCleanup(dictionary=self.d)
|
||||
|
||||
exe = self.getBuildArtifact(self.exe_name)
|
||||
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
|
||||
|
||||
# Add a breakpoint to set a watchpoint when stopped on the breakpoint.
|
||||
lldbutil.run_break_set_by_file_and_line(
|
||||
self, None, self.line, num_expected_locations=1)
|
||||
|
||||
# Run the program.
|
||||
self.runCmd("run", RUN_SUCCEEDED)
|
||||
|
||||
# We should be stopped again due to the breakpoint.
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs=['stopped',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# Now let's set a read_write-type watchpoint for 'global'.
|
||||
# There should be two watchpoint hits (see main.c).
|
||||
self.expect(
|
||||
"watchpoint set variable -w read_write global",
|
||||
WATCHPOINT_CREATED,
|
||||
substrs=[
|
||||
'Watchpoint created',
|
||||
'size = 4',
|
||||
'type = rw',
|
||||
'%s:%d' %
|
||||
(self.source,
|
||||
self.decl)])
|
||||
|
||||
# Delete the watchpoint immediately using the force option.
|
||||
self.expect("watchpoint delete --force",
|
||||
substrs=['All watchpoints removed.'])
|
||||
|
||||
# Use the '-v' option to do verbose listing of the watchpoint.
|
||||
self.runCmd("watchpoint list -v")
|
||||
|
||||
self.runCmd("process continue")
|
||||
|
||||
# There should be no more watchpoint hit and the process status should
|
||||
# be 'exited'.
|
||||
self.expect("process status",
|
||||
substrs=['exited'])
|
||||
|
||||
# Read-write watchpoints not supported on SystemZ
|
||||
@expectedFailureAll(archs=['s390x'])
|
||||
def test_rw_watchpoint_set_ignore_count(self):
|
||||
|
|
|
@ -414,6 +414,10 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
// CommandObjectWatchpointDelete
|
||||
#define LLDB_OPTIONS_watchpoint_delete
|
||||
#include "CommandOptions.inc"
|
||||
|
||||
// CommandObjectWatchpointDelete
|
||||
#pragma mark Delete
|
||||
|
||||
|
@ -423,7 +427,8 @@ public:
|
|||
: CommandObjectParsed(interpreter, "watchpoint delete",
|
||||
"Delete the specified watchpoint(s). If no "
|
||||
"watchpoints are specified, delete them all.",
|
||||
nullptr, eCommandRequiresTarget) {
|
||||
nullptr, eCommandRequiresTarget),
|
||||
m_options() {
|
||||
CommandArgumentEntry arg;
|
||||
CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
|
||||
eArgTypeWatchpointIDRange);
|
||||
|
@ -434,6 +439,41 @@ public:
|
|||
|
||||
~CommandObjectWatchpointDelete() override = default;
|
||||
|
||||
Options *GetOptions() override { return &m_options; }
|
||||
|
||||
class CommandOptions : public Options {
|
||||
public:
|
||||
CommandOptions() : Options(), m_force(false) {}
|
||||
|
||||
~CommandOptions() override = default;
|
||||
|
||||
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
|
||||
ExecutionContext *execution_context) override {
|
||||
const int short_option = m_getopt_table[option_idx].val;
|
||||
|
||||
switch (short_option) {
|
||||
case 'f':
|
||||
m_force = true;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unimplemented option");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void OptionParsingStarting(ExecutionContext *execution_context) override {
|
||||
m_force = false;
|
||||
}
|
||||
|
||||
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
|
||||
return llvm::makeArrayRef(g_watchpoint_delete_options);
|
||||
}
|
||||
|
||||
// Instance variables to hold the values for command options.
|
||||
bool m_force;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
||||
Target *target = &GetSelectedTarget();
|
||||
|
@ -453,8 +493,9 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
if (command.GetArgumentCount() == 0) {
|
||||
if (!m_interpreter.Confirm(
|
||||
if (command.empty()) {
|
||||
if (!m_options.m_force &&
|
||||
!m_interpreter.Confirm(
|
||||
"About to delete all watchpoints, do you want to do that?",
|
||||
true)) {
|
||||
result.AppendMessage("Operation cancelled...");
|
||||
|
@ -465,27 +506,31 @@ protected:
|
|||
(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);
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
private:
|
||||
CommandOptions m_options;
|
||||
};
|
||||
|
||||
// CommandObjectWatchpointIgnore
|
||||
|
|
|
@ -1126,3 +1126,8 @@ let Command = "watchpoint command add" in {
|
|||
"to run as command for this watchpoint. Be sure to give a module name if "
|
||||
"appropriate.">;
|
||||
}
|
||||
|
||||
let Command = "watchpoint delete" in {
|
||||
def watchpoint_delete_force : Option<"force", "f">, Group<1>,
|
||||
Desc<"Delete all watchpoints without querying for confirmation.">;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue