1cfca06d7SDimitry Andric //===-- CommandObjectWatchpoint.cpp ---------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "CommandObjectWatchpoint.h"
10f034231aSEd Maste #include "CommandObjectWatchpointCommand.h"
11f034231aSEd Maste
127fa27ce4SDimitry Andric #include <memory>
13f3fbd1c0SDimitry Andric #include <vector>
14f3fbd1c0SDimitry Andric
15f3fbd1c0SDimitry Andric #include "llvm/ADT/StringRef.h"
16f3fbd1c0SDimitry Andric
17f034231aSEd Maste #include "lldb/Breakpoint/Watchpoint.h"
18f034231aSEd Maste #include "lldb/Breakpoint/WatchpointList.h"
19f034231aSEd Maste #include "lldb/Core/ValueObject.h"
2074a628f7SDimitry Andric #include "lldb/Host/OptionParser.h"
21f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
224b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
23f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
247fa27ce4SDimitry Andric #include "lldb/Symbol/Function.h"
25f034231aSEd Maste #include "lldb/Symbol/Variable.h"
26f034231aSEd Maste #include "lldb/Symbol/VariableList.h"
275e95aa85SEd Maste #include "lldb/Target/StackFrame.h"
28f034231aSEd Maste #include "lldb/Target/Target.h"
2974a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
30f034231aSEd Maste
31f034231aSEd Maste using namespace lldb;
32f034231aSEd Maste using namespace lldb_private;
33f034231aSEd Maste
AddWatchpointDescription(Stream & s,Watchpoint & wp,lldb::DescriptionLevel level)347fa27ce4SDimitry Andric static void AddWatchpointDescription(Stream &s, Watchpoint &wp,
3514f1b3e8SDimitry Andric lldb::DescriptionLevel level) {
367fa27ce4SDimitry Andric s.IndentMore();
377fa27ce4SDimitry Andric wp.GetDescription(&s, level);
387fa27ce4SDimitry Andric s.IndentLess();
397fa27ce4SDimitry Andric s.EOL();
40f034231aSEd Maste }
41f034231aSEd Maste
CheckTargetForWatchpointOperations(Target * target,CommandReturnObject & result)4214f1b3e8SDimitry Andric static bool CheckTargetForWatchpointOperations(Target *target,
4314f1b3e8SDimitry Andric CommandReturnObject &result) {
4414f1b3e8SDimitry Andric bool process_is_valid =
4514f1b3e8SDimitry Andric target->GetProcessSP() && target->GetProcessSP()->IsAlive();
4614f1b3e8SDimitry Andric if (!process_is_valid) {
47cfca06d7SDimitry Andric result.AppendError("There's no process or it is not alive.");
48f034231aSEd Maste return false;
49f034231aSEd Maste }
50f034231aSEd Maste // Target passes our checks, return true.
51f034231aSEd Maste return true;
52f034231aSEd Maste }
53f034231aSEd Maste
54f034231aSEd Maste // Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
55f034231aSEd Maste static const char *RSA[4] = {"-", "to", "To", "TO"};
56f034231aSEd Maste
57f034231aSEd Maste // Return the index to RSA if found; otherwise -1 is returned.
WithRSAIndex(llvm::StringRef Arg)5814f1b3e8SDimitry Andric static int32_t WithRSAIndex(llvm::StringRef Arg) {
59f034231aSEd Maste
60f034231aSEd Maste uint32_t i;
61f034231aSEd Maste for (i = 0; i < 4; ++i)
62c0981da4SDimitry Andric if (Arg.contains(RSA[i]))
63f034231aSEd Maste return i;
64f034231aSEd Maste return -1;
65f034231aSEd Maste }
66f034231aSEd Maste
67f73363f1SDimitry Andric // Return true if wp_ids is successfully populated with the watch ids. False
68f73363f1SDimitry Andric // otherwise.
VerifyWatchpointIDs(Target * target,Args & args,std::vector<uint32_t> & wp_ids)6914f1b3e8SDimitry Andric bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
7014f1b3e8SDimitry Andric Target *target, Args &args, std::vector<uint32_t> &wp_ids) {
71f034231aSEd Maste // Pre-condition: args.GetArgumentCount() > 0.
7214f1b3e8SDimitry Andric if (args.GetArgumentCount() == 0) {
73f3fbd1c0SDimitry Andric if (target == nullptr)
74f034231aSEd Maste return false;
75f034231aSEd Maste WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
7614f1b3e8SDimitry Andric if (watch_sp) {
77f034231aSEd Maste wp_ids.push_back(watch_sp->GetID());
78f034231aSEd Maste return true;
7914f1b3e8SDimitry Andric } else
80f034231aSEd Maste return false;
81f034231aSEd Maste }
82f034231aSEd Maste
83f034231aSEd Maste llvm::StringRef Minus("-");
84f034231aSEd Maste std::vector<llvm::StringRef> StrRefArgs;
8514f1b3e8SDimitry Andric llvm::StringRef first;
8614f1b3e8SDimitry Andric llvm::StringRef second;
87f034231aSEd Maste size_t i;
88f034231aSEd Maste int32_t idx;
89e81d9d49SDimitry Andric // Go through the arguments and make a canonical form of arg list containing
90f034231aSEd Maste // only numbers with possible "-" in between.
9114f1b3e8SDimitry Andric for (auto &entry : args.entries()) {
92ead24645SDimitry Andric if ((idx = WithRSAIndex(entry.ref())) == -1) {
93ead24645SDimitry Andric StrRefArgs.push_back(entry.ref());
94f034231aSEd Maste continue;
95f034231aSEd Maste }
96f034231aSEd Maste // The Arg contains the range specifier, split it, then.
97ead24645SDimitry Andric std::tie(first, second) = entry.ref().split(RSA[idx]);
9814f1b3e8SDimitry Andric if (!first.empty())
9914f1b3e8SDimitry Andric StrRefArgs.push_back(first);
100f034231aSEd Maste StrRefArgs.push_back(Minus);
10114f1b3e8SDimitry Andric if (!second.empty())
10214f1b3e8SDimitry Andric StrRefArgs.push_back(second);
103f034231aSEd Maste }
104f73363f1SDimitry Andric // Now process the canonical list and fill in the vector of uint32_t's. If
105f73363f1SDimitry Andric // there is any error, return false and the client should ignore wp_ids.
106f034231aSEd Maste uint32_t beg, end, id;
107f034231aSEd Maste size_t size = StrRefArgs.size();
108f034231aSEd Maste bool in_range = false;
109f034231aSEd Maste for (i = 0; i < size; ++i) {
110f034231aSEd Maste llvm::StringRef Arg = StrRefArgs[i];
111f034231aSEd Maste if (in_range) {
112f034231aSEd Maste // Look for the 'end' of the range. Note StringRef::getAsInteger()
113f034231aSEd Maste // returns true to signify error while parsing.
114f034231aSEd Maste if (Arg.getAsInteger(0, end))
115f034231aSEd Maste return false;
116f034231aSEd Maste // Found a range! Now append the elements.
117f034231aSEd Maste for (id = beg; id <= end; ++id)
118f034231aSEd Maste wp_ids.push_back(id);
119f034231aSEd Maste in_range = false;
120f034231aSEd Maste continue;
121f034231aSEd Maste }
122f034231aSEd Maste if (i < (size - 1) && StrRefArgs[i + 1] == Minus) {
123f034231aSEd Maste if (Arg.getAsInteger(0, beg))
124f034231aSEd Maste return false;
125f034231aSEd Maste // Turn on the in_range flag, we are looking for end of range next.
12614f1b3e8SDimitry Andric ++i;
12714f1b3e8SDimitry Andric in_range = true;
128f034231aSEd Maste continue;
129f034231aSEd Maste }
130f034231aSEd Maste // Otherwise, we have a simple ID. Just append it.
131f034231aSEd Maste if (Arg.getAsInteger(0, beg))
132f034231aSEd Maste return false;
133f034231aSEd Maste wp_ids.push_back(beg);
134f034231aSEd Maste }
135f034231aSEd Maste
13694994d37SDimitry Andric // It is an error if after the loop, we're still in_range.
13794994d37SDimitry Andric return !in_range;
138f034231aSEd Maste }
139f034231aSEd Maste
140f034231aSEd Maste // CommandObjectWatchpointList
14114f1b3e8SDimitry Andric
14214f1b3e8SDimitry Andric // CommandObjectWatchpointList::Options
14314f1b3e8SDimitry Andric #pragma mark List::CommandOptions
1445f29bb8aSDimitry Andric #define LLDB_OPTIONS_watchpoint_list
1455f29bb8aSDimitry Andric #include "CommandOptions.inc"
14614f1b3e8SDimitry Andric
147f034231aSEd Maste #pragma mark List
148f034231aSEd Maste
14914f1b3e8SDimitry Andric class CommandObjectWatchpointList : public CommandObjectParsed {
150f034231aSEd Maste public:
CommandObjectWatchpointList(CommandInterpreter & interpreter)15114f1b3e8SDimitry Andric CommandObjectWatchpointList(CommandInterpreter &interpreter)
15214f1b3e8SDimitry Andric : CommandObjectParsed(
15314f1b3e8SDimitry Andric interpreter, "watchpoint list",
154ead24645SDimitry Andric "List all watchpoints at configurable levels of detail.", nullptr,
1556f8fc217SDimitry Andric eCommandRequiresTarget) {
156ac9a064cSDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs);
157f034231aSEd Maste }
158f034231aSEd Maste
159f3fbd1c0SDimitry Andric ~CommandObjectWatchpointList() override = default;
160f034231aSEd Maste
GetOptions()16114f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
162f034231aSEd Maste
16314f1b3e8SDimitry Andric class CommandOptions : public Options {
164f034231aSEd Maste public:
165145449b1SDimitry Andric CommandOptions() = default;
166f034231aSEd Maste
167f3fbd1c0SDimitry Andric ~CommandOptions() override = default;
168f034231aSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)169b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
17014f1b3e8SDimitry Andric ExecutionContext *execution_context) override {
171b76161e4SDimitry Andric Status error;
172f034231aSEd Maste const int short_option = m_getopt_table[option_idx].val;
173f034231aSEd Maste
17414f1b3e8SDimitry Andric switch (short_option) {
175f034231aSEd Maste case 'b':
176f034231aSEd Maste m_level = lldb::eDescriptionLevelBrief;
177f034231aSEd Maste break;
178f034231aSEd Maste case 'f':
179f034231aSEd Maste m_level = lldb::eDescriptionLevelFull;
180f034231aSEd Maste break;
181f034231aSEd Maste case 'v':
182f034231aSEd Maste m_level = lldb::eDescriptionLevelVerbose;
183f034231aSEd Maste break;
184f034231aSEd Maste default:
185ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
186f034231aSEd Maste }
187f034231aSEd Maste
188f034231aSEd Maste return error;
189f034231aSEd Maste }
190f034231aSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)19114f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
192f034231aSEd Maste m_level = lldb::eDescriptionLevelFull;
193f034231aSEd Maste }
194f034231aSEd Maste
GetDefinitions()19514f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
196e3b55780SDimitry Andric return llvm::ArrayRef(g_watchpoint_list_options);
197f034231aSEd Maste }
198f034231aSEd Maste
199f034231aSEd Maste // Instance variables to hold the values for command options.
200f034231aSEd Maste
201344a3780SDimitry Andric lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
202f034231aSEd Maste };
203f034231aSEd Maste
204f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)205b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
206ead24645SDimitry Andric Target *target = &GetSelectedTarget();
207f034231aSEd Maste
20814f1b3e8SDimitry Andric if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
2097fa27ce4SDimitry Andric std::optional<uint32_t> num_supported_hardware_watchpoints =
2107fa27ce4SDimitry Andric target->GetProcessSP()->GetWatchpointSlotCount();
2117fa27ce4SDimitry Andric
2127fa27ce4SDimitry Andric if (num_supported_hardware_watchpoints)
21314f1b3e8SDimitry Andric result.AppendMessageWithFormat(
21414f1b3e8SDimitry Andric "Number of supported hardware watchpoints: %u\n",
2157fa27ce4SDimitry Andric *num_supported_hardware_watchpoints);
216f034231aSEd Maste }
217f034231aSEd Maste
218f034231aSEd Maste const WatchpointList &watchpoints = target->GetWatchpointList();
219f3fbd1c0SDimitry Andric
220f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
221f3fbd1c0SDimitry Andric target->GetWatchpointList().GetListMutex(lock);
222f034231aSEd Maste
223f034231aSEd Maste size_t num_watchpoints = watchpoints.GetSize();
224f034231aSEd Maste
22514f1b3e8SDimitry Andric if (num_watchpoints == 0) {
226f034231aSEd Maste result.AppendMessage("No watchpoints currently set.");
227f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
228b1c73532SDimitry Andric return;
229f034231aSEd Maste }
230f034231aSEd Maste
231f034231aSEd Maste Stream &output_stream = result.GetOutputStream();
232f034231aSEd Maste
23314f1b3e8SDimitry Andric if (command.GetArgumentCount() == 0) {
234f034231aSEd Maste // No watchpoint selected; show info about all currently set watchpoints.
235f034231aSEd Maste result.AppendMessage("Current watchpoints:");
23614f1b3e8SDimitry Andric for (size_t i = 0; i < num_watchpoints; ++i) {
2377fa27ce4SDimitry Andric WatchpointSP watch_sp = watchpoints.GetByIndex(i);
2387fa27ce4SDimitry Andric AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level);
239f034231aSEd Maste }
240f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
24114f1b3e8SDimitry Andric } else {
242f034231aSEd Maste // Particular watchpoints selected; enable them.
243f034231aSEd Maste std::vector<uint32_t> wp_ids;
24414f1b3e8SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
24514f1b3e8SDimitry Andric target, command, wp_ids)) {
246f034231aSEd Maste result.AppendError("Invalid watchpoints specification.");
247b1c73532SDimitry Andric return;
248f034231aSEd Maste }
249f034231aSEd Maste
250f034231aSEd Maste const size_t size = wp_ids.size();
25114f1b3e8SDimitry Andric for (size_t i = 0; i < size; ++i) {
2527fa27ce4SDimitry Andric WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]);
2537fa27ce4SDimitry Andric if (watch_sp)
2547fa27ce4SDimitry Andric AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level);
255f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
256f034231aSEd Maste }
257f034231aSEd Maste }
258f034231aSEd Maste }
259f034231aSEd Maste
260f034231aSEd Maste private:
261f034231aSEd Maste CommandOptions m_options;
262f034231aSEd Maste };
263f034231aSEd Maste
264f034231aSEd Maste // CommandObjectWatchpointEnable
265f034231aSEd Maste #pragma mark Enable
266f034231aSEd Maste
26714f1b3e8SDimitry Andric class CommandObjectWatchpointEnable : public CommandObjectParsed {
268f034231aSEd Maste public:
CommandObjectWatchpointEnable(CommandInterpreter & interpreter)26914f1b3e8SDimitry Andric CommandObjectWatchpointEnable(CommandInterpreter &interpreter)
27014f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "enable",
27114f1b3e8SDimitry Andric "Enable the specified disabled watchpoint(s). If "
27214f1b3e8SDimitry Andric "no watchpoints are specified, enable all of them.",
273ead24645SDimitry Andric nullptr, eCommandRequiresTarget) {
274ac9a064cSDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs);
275f034231aSEd Maste }
276f034231aSEd Maste
277f3fbd1c0SDimitry Andric ~CommandObjectWatchpointEnable() override = default;
278f034231aSEd Maste
279b60736ecSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)280b60736ecSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
281b60736ecSDimitry Andric OptionElementVector &opt_element_vector) override {
2827fa27ce4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2837fa27ce4SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
2847fa27ce4SDimitry Andric nullptr);
285b60736ecSDimitry Andric }
286b60736ecSDimitry Andric
287f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)288b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
289ead24645SDimitry Andric Target *target = &GetSelectedTarget();
290f034231aSEd Maste if (!CheckTargetForWatchpointOperations(target, result))
291b1c73532SDimitry Andric return;
292f034231aSEd Maste
293f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
294f3fbd1c0SDimitry Andric target->GetWatchpointList().GetListMutex(lock);
295f034231aSEd Maste
296f034231aSEd Maste const WatchpointList &watchpoints = target->GetWatchpointList();
297f034231aSEd Maste
298f034231aSEd Maste size_t num_watchpoints = watchpoints.GetSize();
299f034231aSEd Maste
30014f1b3e8SDimitry Andric if (num_watchpoints == 0) {
301f034231aSEd Maste result.AppendError("No watchpoints exist to be enabled.");
302b1c73532SDimitry Andric return;
303f034231aSEd Maste }
304f034231aSEd Maste
30514f1b3e8SDimitry Andric if (command.GetArgumentCount() == 0) {
306f034231aSEd Maste // No watchpoint selected; enable all currently set watchpoints.
307f034231aSEd Maste target->EnableAllWatchpoints();
30814f1b3e8SDimitry Andric result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
30914f1b3e8SDimitry Andric " watchpoints)\n",
31014f1b3e8SDimitry Andric (uint64_t)num_watchpoints);
311f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
31214f1b3e8SDimitry Andric } else {
313f034231aSEd Maste // Particular watchpoints selected; enable them.
314f034231aSEd Maste std::vector<uint32_t> wp_ids;
31514f1b3e8SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
31614f1b3e8SDimitry Andric target, command, wp_ids)) {
317f034231aSEd Maste result.AppendError("Invalid watchpoints specification.");
318b1c73532SDimitry Andric return;
319f034231aSEd Maste }
320f034231aSEd Maste
321f034231aSEd Maste int count = 0;
322f034231aSEd Maste const size_t size = wp_ids.size();
323f034231aSEd Maste for (size_t i = 0; i < size; ++i)
324f034231aSEd Maste if (target->EnableWatchpointByID(wp_ids[i]))
325f034231aSEd Maste ++count;
326f034231aSEd Maste result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
327f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
328f034231aSEd Maste }
329f034231aSEd Maste }
330f034231aSEd Maste };
331f034231aSEd Maste
332f034231aSEd Maste // CommandObjectWatchpointDisable
333f034231aSEd Maste #pragma mark Disable
334f034231aSEd Maste
33514f1b3e8SDimitry Andric class CommandObjectWatchpointDisable : public CommandObjectParsed {
336f034231aSEd Maste public:
CommandObjectWatchpointDisable(CommandInterpreter & interpreter)33714f1b3e8SDimitry Andric CommandObjectWatchpointDisable(CommandInterpreter &interpreter)
33814f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "watchpoint disable",
33914f1b3e8SDimitry Andric "Disable the specified watchpoint(s) without "
34014f1b3e8SDimitry Andric "removing it/them. If no watchpoints are "
34114f1b3e8SDimitry Andric "specified, disable them all.",
342ead24645SDimitry Andric nullptr, eCommandRequiresTarget) {
343ac9a064cSDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs);
344f034231aSEd Maste }
345f034231aSEd Maste
346f3fbd1c0SDimitry Andric ~CommandObjectWatchpointDisable() override = default;
347f034231aSEd Maste
348b60736ecSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)349b60736ecSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
350b60736ecSDimitry Andric OptionElementVector &opt_element_vector) override {
3517fa27ce4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
3527fa27ce4SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
3537fa27ce4SDimitry Andric nullptr);
354b60736ecSDimitry Andric }
355b60736ecSDimitry Andric
356f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)357b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
358ead24645SDimitry Andric Target *target = &GetSelectedTarget();
359f034231aSEd Maste if (!CheckTargetForWatchpointOperations(target, result))
360b1c73532SDimitry Andric return;
361f034231aSEd Maste
362f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
363f3fbd1c0SDimitry Andric target->GetWatchpointList().GetListMutex(lock);
364f034231aSEd Maste
365f034231aSEd Maste const WatchpointList &watchpoints = target->GetWatchpointList();
366f034231aSEd Maste size_t num_watchpoints = watchpoints.GetSize();
367f034231aSEd Maste
36814f1b3e8SDimitry Andric if (num_watchpoints == 0) {
369f034231aSEd Maste result.AppendError("No watchpoints exist to be disabled.");
370b1c73532SDimitry Andric return;
371f034231aSEd Maste }
372f034231aSEd Maste
37314f1b3e8SDimitry Andric if (command.GetArgumentCount() == 0) {
374f034231aSEd Maste // No watchpoint selected; disable all currently set watchpoints.
37514f1b3e8SDimitry Andric if (target->DisableAllWatchpoints()) {
37614f1b3e8SDimitry Andric result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
37714f1b3e8SDimitry Andric " watchpoints)\n",
37814f1b3e8SDimitry Andric (uint64_t)num_watchpoints);
379f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
38014f1b3e8SDimitry Andric } else {
381f034231aSEd Maste result.AppendError("Disable all watchpoints failed\n");
382f034231aSEd Maste }
38314f1b3e8SDimitry Andric } else {
384f034231aSEd Maste // Particular watchpoints selected; disable them.
385f034231aSEd Maste std::vector<uint32_t> wp_ids;
38614f1b3e8SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
38714f1b3e8SDimitry Andric target, command, wp_ids)) {
388f034231aSEd Maste result.AppendError("Invalid watchpoints specification.");
389b1c73532SDimitry Andric return;
390f034231aSEd Maste }
391f034231aSEd Maste
392f034231aSEd Maste int count = 0;
393f034231aSEd Maste const size_t size = wp_ids.size();
394f034231aSEd Maste for (size_t i = 0; i < size; ++i)
395f034231aSEd Maste if (target->DisableWatchpointByID(wp_ids[i]))
396f034231aSEd Maste ++count;
397f034231aSEd Maste result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
398f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
399f034231aSEd Maste }
400f034231aSEd Maste }
401f034231aSEd Maste };
402f034231aSEd Maste
403f034231aSEd Maste // CommandObjectWatchpointDelete
404706b4fc4SDimitry Andric #define LLDB_OPTIONS_watchpoint_delete
405706b4fc4SDimitry Andric #include "CommandOptions.inc"
406706b4fc4SDimitry Andric
407706b4fc4SDimitry Andric // CommandObjectWatchpointDelete
408f034231aSEd Maste #pragma mark Delete
409f034231aSEd Maste
41014f1b3e8SDimitry Andric class CommandObjectWatchpointDelete : public CommandObjectParsed {
411f034231aSEd Maste public:
CommandObjectWatchpointDelete(CommandInterpreter & interpreter)41214f1b3e8SDimitry Andric CommandObjectWatchpointDelete(CommandInterpreter &interpreter)
41314f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "watchpoint delete",
41414f1b3e8SDimitry Andric "Delete the specified watchpoint(s). If no "
41514f1b3e8SDimitry Andric "watchpoints are specified, delete them all.",
4166f8fc217SDimitry Andric nullptr, eCommandRequiresTarget) {
417ac9a064cSDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs);
418f034231aSEd Maste }
419f034231aSEd Maste
420f3fbd1c0SDimitry Andric ~CommandObjectWatchpointDelete() override = default;
421f034231aSEd Maste
422b60736ecSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)423b60736ecSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
424b60736ecSDimitry Andric OptionElementVector &opt_element_vector) override {
4257fa27ce4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
4267fa27ce4SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
4277fa27ce4SDimitry Andric nullptr);
428b60736ecSDimitry Andric }
429b60736ecSDimitry Andric
GetOptions()430706b4fc4SDimitry Andric Options *GetOptions() override { return &m_options; }
431706b4fc4SDimitry Andric
432706b4fc4SDimitry Andric class CommandOptions : public Options {
433706b4fc4SDimitry Andric public:
434145449b1SDimitry Andric CommandOptions() = default;
435706b4fc4SDimitry Andric
436706b4fc4SDimitry Andric ~CommandOptions() override = default;
437706b4fc4SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)438706b4fc4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
439706b4fc4SDimitry Andric ExecutionContext *execution_context) override {
440706b4fc4SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
441706b4fc4SDimitry Andric
442706b4fc4SDimitry Andric switch (short_option) {
443706b4fc4SDimitry Andric case 'f':
444706b4fc4SDimitry Andric m_force = true;
445706b4fc4SDimitry Andric break;
446706b4fc4SDimitry Andric default:
447706b4fc4SDimitry Andric llvm_unreachable("Unimplemented option");
448706b4fc4SDimitry Andric }
449706b4fc4SDimitry Andric
450706b4fc4SDimitry Andric return {};
451706b4fc4SDimitry Andric }
452706b4fc4SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)453706b4fc4SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
454706b4fc4SDimitry Andric m_force = false;
455706b4fc4SDimitry Andric }
456706b4fc4SDimitry Andric
GetDefinitions()457706b4fc4SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
458e3b55780SDimitry Andric return llvm::ArrayRef(g_watchpoint_delete_options);
459706b4fc4SDimitry Andric }
460706b4fc4SDimitry Andric
461706b4fc4SDimitry Andric // Instance variables to hold the values for command options.
462344a3780SDimitry Andric bool m_force = false;
463706b4fc4SDimitry Andric };
464706b4fc4SDimitry Andric
465f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)466b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
467ead24645SDimitry Andric Target *target = &GetSelectedTarget();
468f034231aSEd Maste if (!CheckTargetForWatchpointOperations(target, result))
469b1c73532SDimitry Andric return;
470f034231aSEd Maste
471f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
472f3fbd1c0SDimitry Andric target->GetWatchpointList().GetListMutex(lock);
473f034231aSEd Maste
474f034231aSEd Maste const WatchpointList &watchpoints = target->GetWatchpointList();
475f034231aSEd Maste
476f034231aSEd Maste size_t num_watchpoints = watchpoints.GetSize();
477f034231aSEd Maste
47814f1b3e8SDimitry Andric if (num_watchpoints == 0) {
479f034231aSEd Maste result.AppendError("No watchpoints exist to be deleted.");
480b1c73532SDimitry Andric return;
481f034231aSEd Maste }
482f034231aSEd Maste
483706b4fc4SDimitry Andric if (command.empty()) {
484706b4fc4SDimitry Andric if (!m_options.m_force &&
485706b4fc4SDimitry Andric !m_interpreter.Confirm(
48614f1b3e8SDimitry Andric "About to delete all watchpoints, do you want to do that?",
48714f1b3e8SDimitry Andric true)) {
488f034231aSEd Maste result.AppendMessage("Operation cancelled...");
48914f1b3e8SDimitry Andric } else {
490f034231aSEd Maste target->RemoveAllWatchpoints();
49114f1b3e8SDimitry Andric result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
49214f1b3e8SDimitry Andric " watchpoints)\n",
49314f1b3e8SDimitry Andric (uint64_t)num_watchpoints);
494f034231aSEd Maste }
495f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
496b1c73532SDimitry Andric return;
497706b4fc4SDimitry Andric }
498706b4fc4SDimitry Andric
499f034231aSEd Maste // Particular watchpoints selected; delete them.
500f034231aSEd Maste std::vector<uint32_t> wp_ids;
501706b4fc4SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command,
502706b4fc4SDimitry Andric wp_ids)) {
503f034231aSEd Maste result.AppendError("Invalid watchpoints specification.");
504b1c73532SDimitry Andric return;
505f034231aSEd Maste }
506f034231aSEd Maste
507f034231aSEd Maste int count = 0;
508f034231aSEd Maste const size_t size = wp_ids.size();
509f034231aSEd Maste for (size_t i = 0; i < size; ++i)
510f034231aSEd Maste if (target->RemoveWatchpointByID(wp_ids[i]))
511f034231aSEd Maste ++count;
512f034231aSEd Maste result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
513f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
514f034231aSEd Maste }
515706b4fc4SDimitry Andric
516706b4fc4SDimitry Andric private:
517706b4fc4SDimitry Andric CommandOptions m_options;
518f034231aSEd Maste };
519f034231aSEd Maste
520f034231aSEd Maste // CommandObjectWatchpointIgnore
521f034231aSEd Maste
52214f1b3e8SDimitry Andric #pragma mark Ignore::CommandOptions
5235f29bb8aSDimitry Andric #define LLDB_OPTIONS_watchpoint_ignore
5245f29bb8aSDimitry Andric #include "CommandOptions.inc"
52514f1b3e8SDimitry Andric
52614f1b3e8SDimitry Andric class CommandObjectWatchpointIgnore : public CommandObjectParsed {
527f034231aSEd Maste public:
CommandObjectWatchpointIgnore(CommandInterpreter & interpreter)52814f1b3e8SDimitry Andric CommandObjectWatchpointIgnore(CommandInterpreter &interpreter)
52914f1b3e8SDimitry Andric : CommandObjectParsed(interpreter, "watchpoint ignore",
53014f1b3e8SDimitry Andric "Set ignore count on the specified watchpoint(s). "
53114f1b3e8SDimitry Andric "If no watchpoints are specified, set them all.",
5326f8fc217SDimitry Andric nullptr, eCommandRequiresTarget) {
533ac9a064cSDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs);
534f034231aSEd Maste }
535f034231aSEd Maste
536f3fbd1c0SDimitry Andric ~CommandObjectWatchpointIgnore() override = default;
537f034231aSEd Maste
538b60736ecSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)539b60736ecSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
540b60736ecSDimitry Andric OptionElementVector &opt_element_vector) override {
5417fa27ce4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
5427fa27ce4SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
5437fa27ce4SDimitry Andric nullptr);
544b60736ecSDimitry Andric }
545b60736ecSDimitry Andric
GetOptions()54614f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
547f034231aSEd Maste
54814f1b3e8SDimitry Andric class CommandOptions : public Options {
549f034231aSEd Maste public:
550145449b1SDimitry Andric CommandOptions() = default;
551f034231aSEd Maste
552f3fbd1c0SDimitry Andric ~CommandOptions() override = default;
553f034231aSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)554b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
55514f1b3e8SDimitry Andric ExecutionContext *execution_context) override {
556b76161e4SDimitry Andric Status error;
557f034231aSEd Maste const int short_option = m_getopt_table[option_idx].val;
558f034231aSEd Maste
55914f1b3e8SDimitry Andric switch (short_option) {
560f034231aSEd Maste case 'i':
56114f1b3e8SDimitry Andric if (option_arg.getAsInteger(0, m_ignore_count))
56214f1b3e8SDimitry Andric error.SetErrorStringWithFormat("invalid ignore count '%s'",
56314f1b3e8SDimitry Andric option_arg.str().c_str());
564f034231aSEd Maste break;
565f034231aSEd Maste default:
566ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
567f034231aSEd Maste }
568f034231aSEd Maste
569f034231aSEd Maste return error;
570f034231aSEd Maste }
571f034231aSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)57214f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
573f034231aSEd Maste m_ignore_count = 0;
574f034231aSEd Maste }
575f034231aSEd Maste
GetDefinitions()57614f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
577e3b55780SDimitry Andric return llvm::ArrayRef(g_watchpoint_ignore_options);
578f034231aSEd Maste }
579f034231aSEd Maste
580f034231aSEd Maste // Instance variables to hold the values for command options.
581f034231aSEd Maste
582344a3780SDimitry Andric uint32_t m_ignore_count = 0;
583f034231aSEd Maste };
584f034231aSEd Maste
585f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)586b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
587ead24645SDimitry Andric Target *target = &GetSelectedTarget();
588f034231aSEd Maste if (!CheckTargetForWatchpointOperations(target, result))
589b1c73532SDimitry Andric return;
590f034231aSEd Maste
591f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
592f3fbd1c0SDimitry Andric target->GetWatchpointList().GetListMutex(lock);
593f034231aSEd Maste
594f034231aSEd Maste const WatchpointList &watchpoints = target->GetWatchpointList();
595f034231aSEd Maste
596f034231aSEd Maste size_t num_watchpoints = watchpoints.GetSize();
597f034231aSEd Maste
59814f1b3e8SDimitry Andric if (num_watchpoints == 0) {
599f034231aSEd Maste result.AppendError("No watchpoints exist to be ignored.");
600b1c73532SDimitry Andric return;
601f034231aSEd Maste }
602f034231aSEd Maste
60314f1b3e8SDimitry Andric if (command.GetArgumentCount() == 0) {
604f034231aSEd Maste target->IgnoreAllWatchpoints(m_options.m_ignore_count);
60514f1b3e8SDimitry Andric result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
60614f1b3e8SDimitry Andric " watchpoints)\n",
60714f1b3e8SDimitry Andric (uint64_t)num_watchpoints);
608f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
60914f1b3e8SDimitry Andric } else {
610f034231aSEd Maste // Particular watchpoints selected; ignore them.
611f034231aSEd Maste std::vector<uint32_t> wp_ids;
61214f1b3e8SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
61314f1b3e8SDimitry Andric target, command, wp_ids)) {
614f034231aSEd Maste result.AppendError("Invalid watchpoints specification.");
615b1c73532SDimitry Andric return;
616f034231aSEd Maste }
617f034231aSEd Maste
618f034231aSEd Maste int count = 0;
619f034231aSEd Maste const size_t size = wp_ids.size();
620f034231aSEd Maste for (size_t i = 0; i < size; ++i)
621f034231aSEd Maste if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
622f034231aSEd Maste ++count;
623f034231aSEd Maste result.AppendMessageWithFormat("%d watchpoints ignored.\n", count);
624f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
625f034231aSEd Maste }
626f034231aSEd Maste }
627f034231aSEd Maste
628f034231aSEd Maste private:
629f034231aSEd Maste CommandOptions m_options;
630f034231aSEd Maste };
631f034231aSEd Maste
632f034231aSEd Maste // CommandObjectWatchpointModify
63314f1b3e8SDimitry Andric
63414f1b3e8SDimitry Andric #pragma mark Modify::CommandOptions
6355f29bb8aSDimitry Andric #define LLDB_OPTIONS_watchpoint_modify
6365f29bb8aSDimitry Andric #include "CommandOptions.inc"
63714f1b3e8SDimitry Andric
638f034231aSEd Maste #pragma mark Modify
639f034231aSEd Maste
64014f1b3e8SDimitry Andric class CommandObjectWatchpointModify : public CommandObjectParsed {
641f034231aSEd Maste public:
CommandObjectWatchpointModify(CommandInterpreter & interpreter)64214f1b3e8SDimitry Andric CommandObjectWatchpointModify(CommandInterpreter &interpreter)
64314f1b3e8SDimitry Andric : CommandObjectParsed(
64414f1b3e8SDimitry Andric interpreter, "watchpoint modify",
64514f1b3e8SDimitry Andric "Modify the options on a watchpoint or set of watchpoints in the "
64614f1b3e8SDimitry Andric "executable. "
64714f1b3e8SDimitry Andric "If no watchpoint is specified, act on the last created "
64814f1b3e8SDimitry Andric "watchpoint. "
649f034231aSEd Maste "Passing an empty argument clears the modification.",
6506f8fc217SDimitry Andric nullptr, eCommandRequiresTarget) {
651ac9a064cSDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs);
652f034231aSEd Maste }
653f034231aSEd Maste
654f3fbd1c0SDimitry Andric ~CommandObjectWatchpointModify() override = default;
655f034231aSEd Maste
656b60736ecSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)657b60736ecSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
658b60736ecSDimitry Andric OptionElementVector &opt_element_vector) override {
6597fa27ce4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
6607fa27ce4SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
6617fa27ce4SDimitry Andric nullptr);
662b60736ecSDimitry Andric }
663b60736ecSDimitry Andric
GetOptions()66414f1b3e8SDimitry Andric Options *GetOptions() override { return &m_options; }
665f034231aSEd Maste
66614f1b3e8SDimitry Andric class CommandOptions : public Options {
667f034231aSEd Maste public:
668145449b1SDimitry Andric CommandOptions() = default;
669f034231aSEd Maste
670f3fbd1c0SDimitry Andric ~CommandOptions() override = default;
671f034231aSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)672b76161e4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
67314f1b3e8SDimitry Andric ExecutionContext *execution_context) override {
674b76161e4SDimitry Andric Status error;
675f034231aSEd Maste const int short_option = m_getopt_table[option_idx].val;
676f034231aSEd Maste
67714f1b3e8SDimitry Andric switch (short_option) {
678f034231aSEd Maste case 'c':
679cfca06d7SDimitry Andric m_condition = std::string(option_arg);
680f034231aSEd Maste m_condition_passed = true;
681f034231aSEd Maste break;
682f034231aSEd Maste default:
683ead24645SDimitry Andric llvm_unreachable("Unimplemented option");
684f034231aSEd Maste }
685f034231aSEd Maste
686f034231aSEd Maste return error;
687f034231aSEd Maste }
688f034231aSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)68914f1b3e8SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
690f034231aSEd Maste m_condition.clear();
691f034231aSEd Maste m_condition_passed = false;
692f034231aSEd Maste }
693f034231aSEd Maste
GetDefinitions()69414f1b3e8SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
695e3b55780SDimitry Andric return llvm::ArrayRef(g_watchpoint_modify_options);
696f034231aSEd Maste }
697f034231aSEd Maste
698f034231aSEd Maste // Instance variables to hold the values for command options.
699f034231aSEd Maste
700f034231aSEd Maste std::string m_condition;
701344a3780SDimitry Andric bool m_condition_passed = false;
702f034231aSEd Maste };
703f034231aSEd Maste
704f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)705b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
706ead24645SDimitry Andric Target *target = &GetSelectedTarget();
707f034231aSEd Maste if (!CheckTargetForWatchpointOperations(target, result))
708b1c73532SDimitry Andric return;
709f034231aSEd Maste
710f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
711f3fbd1c0SDimitry Andric target->GetWatchpointList().GetListMutex(lock);
712f034231aSEd Maste
713f034231aSEd Maste const WatchpointList &watchpoints = target->GetWatchpointList();
714f034231aSEd Maste
715f034231aSEd Maste size_t num_watchpoints = watchpoints.GetSize();
716f034231aSEd Maste
71714f1b3e8SDimitry Andric if (num_watchpoints == 0) {
718f034231aSEd Maste result.AppendError("No watchpoints exist to be modified.");
719b1c73532SDimitry Andric return;
720f034231aSEd Maste }
721f034231aSEd Maste
72214f1b3e8SDimitry Andric if (command.GetArgumentCount() == 0) {
7237fa27ce4SDimitry Andric WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
7247fa27ce4SDimitry Andric watch_sp->SetCondition(m_options.m_condition.c_str());
725f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
72614f1b3e8SDimitry Andric } else {
727f034231aSEd Maste // Particular watchpoints selected; set condition on them.
728f034231aSEd Maste std::vector<uint32_t> wp_ids;
72914f1b3e8SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
73014f1b3e8SDimitry Andric target, command, wp_ids)) {
731f034231aSEd Maste result.AppendError("Invalid watchpoints specification.");
732b1c73532SDimitry Andric return;
733f034231aSEd Maste }
734f034231aSEd Maste
735f034231aSEd Maste int count = 0;
736f034231aSEd Maste const size_t size = wp_ids.size();
73714f1b3e8SDimitry Andric for (size_t i = 0; i < size; ++i) {
7387fa27ce4SDimitry Andric WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]);
7397fa27ce4SDimitry Andric if (watch_sp) {
7407fa27ce4SDimitry Andric watch_sp->SetCondition(m_options.m_condition.c_str());
741f034231aSEd Maste ++count;
742f034231aSEd Maste }
743f034231aSEd Maste }
744f034231aSEd Maste result.AppendMessageWithFormat("%d watchpoints modified.\n", count);
745f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
746f034231aSEd Maste }
747f034231aSEd Maste }
748f034231aSEd Maste
749f034231aSEd Maste private:
750f034231aSEd Maste CommandOptions m_options;
751f034231aSEd Maste };
752f034231aSEd Maste
753f034231aSEd Maste // CommandObjectWatchpointSetVariable
754f034231aSEd Maste #pragma mark SetVariable
755f034231aSEd Maste
75614f1b3e8SDimitry Andric class CommandObjectWatchpointSetVariable : public CommandObjectParsed {
757f034231aSEd Maste public:
CommandObjectWatchpointSetVariable(CommandInterpreter & interpreter)75814f1b3e8SDimitry Andric CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter)
75914f1b3e8SDimitry Andric : CommandObjectParsed(
76014f1b3e8SDimitry Andric interpreter, "watchpoint set variable",
761f034231aSEd Maste "Set a watchpoint on a variable. "
762f034231aSEd Maste "Use the '-w' option to specify the type of watchpoint and "
763f3fbd1c0SDimitry Andric "the '-s' option to specify the byte size to watch for. "
764b1c73532SDimitry Andric "If no '-w' option is specified, it defaults to modify. "
765f3fbd1c0SDimitry Andric "If no '-s' option is specified, it defaults to the variable's "
766f034231aSEd Maste "byte size. "
767f034231aSEd Maste "Note that there are limited hardware resources for watchpoints. "
76814f1b3e8SDimitry Andric "If watchpoint setting fails, consider disable/delete existing "
76914f1b3e8SDimitry Andric "ones "
770f034231aSEd Maste "to free up resources.",
771f3fbd1c0SDimitry Andric nullptr,
77214f1b3e8SDimitry Andric eCommandRequiresFrame | eCommandTryTargetAPILock |
7736f8fc217SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
774f034231aSEd Maste SetHelpLong(
775027f1c96SDimitry Andric R"(
776027f1c96SDimitry Andric Examples:
777027f1c96SDimitry Andric
778027f1c96SDimitry Andric (lldb) watchpoint set variable -w read_write my_global_var
779027f1c96SDimitry Andric
78014f1b3e8SDimitry Andric )"
78114f1b3e8SDimitry Andric " Watches my_global_var for read/write access, with the region to watch \
78214f1b3e8SDimitry Andric corresponding to the byte size of the data type.");
783f034231aSEd Maste
784ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypeVarName);
785f034231aSEd Maste
786f3fbd1c0SDimitry Andric // Absorb the '-w' and '-s' options into our option group.
7877fa27ce4SDimitry Andric m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_1, LLDB_OPT_SET_1);
788f034231aSEd Maste m_option_group.Finalize();
789f034231aSEd Maste }
790f034231aSEd Maste
791f3fbd1c0SDimitry Andric ~CommandObjectWatchpointSetVariable() override = default;
792f034231aSEd Maste
GetOptions()79314f1b3e8SDimitry Andric Options *GetOptions() override { return &m_option_group; }
794f034231aSEd Maste
795f034231aSEd Maste protected:
GetVariableCallback(void * baton,const char * name,VariableList & variable_list)79614f1b3e8SDimitry Andric static size_t GetVariableCallback(void *baton, const char *name,
79714f1b3e8SDimitry Andric VariableList &variable_list) {
798ead24645SDimitry Andric size_t old_size = variable_list.GetSize();
799f034231aSEd Maste Target *target = static_cast<Target *>(baton);
800ead24645SDimitry Andric if (target)
801ead24645SDimitry Andric target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX,
802ead24645SDimitry Andric variable_list);
803ead24645SDimitry Andric return variable_list.GetSize() - old_size;
804f034231aSEd Maste }
805f034231aSEd Maste
DoExecute(Args & command,CommandReturnObject & result)806b1c73532SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
8075f29bb8aSDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
808f034231aSEd Maste StackFrame *frame = m_exe_ctx.GetFramePtr();
809f034231aSEd Maste
810f73363f1SDimitry Andric // If no argument is present, issue an error message. There's no way to
811f73363f1SDimitry Andric // set a watchpoint.
81214f1b3e8SDimitry Andric if (command.GetArgumentCount() <= 0) {
813344a3780SDimitry Andric result.AppendError("required argument missing; "
814344a3780SDimitry Andric "specify your program variable to watch for");
815b1c73532SDimitry Andric return;
816f034231aSEd Maste }
817f034231aSEd Maste
818b1c73532SDimitry Andric // If no '-w' is specified, default to '-w modify'.
81914f1b3e8SDimitry Andric if (!m_option_watchpoint.watch_type_specified) {
820b1c73532SDimitry Andric m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify;
821f034231aSEd Maste }
822f034231aSEd Maste
823f73363f1SDimitry Andric // We passed the sanity check for the command. Proceed to set the
824f73363f1SDimitry Andric // watchpoint now.
825f034231aSEd Maste lldb::addr_t addr = 0;
826f034231aSEd Maste size_t size = 0;
827f034231aSEd Maste
828f034231aSEd Maste VariableSP var_sp;
829f034231aSEd Maste ValueObjectSP valobj_sp;
830f034231aSEd Maste Stream &output_stream = result.GetOutputStream();
831f034231aSEd Maste
832f034231aSEd Maste // A simple watch variable gesture allows only one argument.
83314f1b3e8SDimitry Andric if (command.GetArgumentCount() != 1) {
834344a3780SDimitry Andric result.AppendError("specify exactly one variable to watch for");
835b1c73532SDimitry Andric return;
836f034231aSEd Maste }
837f034231aSEd Maste
838f034231aSEd Maste // Things have checked out ok...
839b76161e4SDimitry Andric Status error;
84014f1b3e8SDimitry Andric uint32_t expr_path_options =
84114f1b3e8SDimitry Andric StackFrame::eExpressionPathOptionCheckPtrVsMember |
842f034231aSEd Maste StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
84314f1b3e8SDimitry Andric valobj_sp = frame->GetValueForVariableExpressionPath(
84414f1b3e8SDimitry Andric command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
84514f1b3e8SDimitry Andric var_sp, error);
846f034231aSEd Maste
84714f1b3e8SDimitry Andric if (!valobj_sp) {
848f034231aSEd Maste // Not in the frame; let's check the globals.
849f034231aSEd Maste
850f034231aSEd Maste VariableList variable_list;
851f034231aSEd Maste ValueObjectList valobj_list;
852f034231aSEd Maste
853b76161e4SDimitry Andric Status error(Variable::GetValuesForVariableExpressionPath(
85414f1b3e8SDimitry Andric command.GetArgumentAtIndex(0),
85514f1b3e8SDimitry Andric m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target,
85614f1b3e8SDimitry Andric variable_list, valobj_list));
857f034231aSEd Maste
858f034231aSEd Maste if (valobj_list.GetSize())
859f034231aSEd Maste valobj_sp = valobj_list.GetValueObjectAtIndex(0);
860f034231aSEd Maste }
861f034231aSEd Maste
862e81d9d49SDimitry Andric CompilerType compiler_type;
863f034231aSEd Maste
86414f1b3e8SDimitry Andric if (valobj_sp) {
865f034231aSEd Maste AddressType addr_type;
866f034231aSEd Maste addr = valobj_sp->GetAddressOf(false, &addr_type);
86714f1b3e8SDimitry Andric if (addr_type == eAddressTypeLoad) {
868f034231aSEd Maste // We're in business.
869f034231aSEd Maste // Find out the size of this variable.
870b1c73532SDimitry Andric size = m_option_watchpoint.watch_size.GetCurrentValue() == 0
871145449b1SDimitry Andric ? valobj_sp->GetByteSize().value_or(0)
872b1c73532SDimitry Andric : m_option_watchpoint.watch_size.GetCurrentValue();
873f034231aSEd Maste }
874e81d9d49SDimitry Andric compiler_type = valobj_sp->GetCompilerType();
87514f1b3e8SDimitry Andric } else {
876f3fbd1c0SDimitry Andric const char *error_cstr = error.AsCString(nullptr);
877f034231aSEd Maste if (error_cstr)
878344a3780SDimitry Andric result.AppendError(error_cstr);
879f034231aSEd Maste else
880344a3780SDimitry Andric result.AppendErrorWithFormat("unable to find any variable "
881344a3780SDimitry Andric "expression path that matches '%s'",
882f034231aSEd Maste command.GetArgumentAtIndex(0));
883b1c73532SDimitry Andric return;
884f034231aSEd Maste }
885f034231aSEd Maste
886f034231aSEd Maste // Now it's time to create the watchpoint.
887b1c73532SDimitry Andric uint32_t watch_type = 0;
888b1c73532SDimitry Andric switch (m_option_watchpoint.watch_type) {
889b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchModify:
890b1c73532SDimitry Andric watch_type |= LLDB_WATCH_TYPE_MODIFY;
891b1c73532SDimitry Andric break;
892b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchRead:
893b1c73532SDimitry Andric watch_type |= LLDB_WATCH_TYPE_READ;
894b1c73532SDimitry Andric break;
895b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchReadWrite:
896b1c73532SDimitry Andric watch_type |= LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE;
897b1c73532SDimitry Andric break;
898b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchWrite:
899b1c73532SDimitry Andric watch_type |= LLDB_WATCH_TYPE_WRITE;
900b1c73532SDimitry Andric break;
901b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchInvalid:
902b1c73532SDimitry Andric break;
903b1c73532SDimitry Andric };
904f034231aSEd Maste
905f034231aSEd Maste error.Clear();
9067fa27ce4SDimitry Andric WatchpointSP watch_sp =
9077fa27ce4SDimitry Andric target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
9087fa27ce4SDimitry Andric if (!watch_sp) {
90914f1b3e8SDimitry Andric result.AppendErrorWithFormat(
91014f1b3e8SDimitry Andric "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64
91114f1b3e8SDimitry Andric ", variable expression='%s').\n",
9127fa27ce4SDimitry Andric addr, static_cast<uint64_t>(size), command.GetArgumentAtIndex(0));
9137fa27ce4SDimitry Andric if (const char *error_message = error.AsCString(nullptr))
9147fa27ce4SDimitry Andric result.AppendError(error_message);
915b1c73532SDimitry Andric return;
916f034231aSEd Maste }
917f034231aSEd Maste
9187fa27ce4SDimitry Andric watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0));
9197fa27ce4SDimitry Andric watch_sp->SetWatchVariable(true);
9207fa27ce4SDimitry Andric if (var_sp) {
9217fa27ce4SDimitry Andric if (var_sp->GetDeclaration().GetFile()) {
9227fa27ce4SDimitry Andric StreamString ss;
9237fa27ce4SDimitry Andric // True to show fullpath for declaration file.
9247fa27ce4SDimitry Andric var_sp->GetDeclaration().DumpStopContext(&ss, true);
9257fa27ce4SDimitry Andric watch_sp->SetDeclInfo(std::string(ss.GetString()));
9267fa27ce4SDimitry Andric }
9277fa27ce4SDimitry Andric if (var_sp->GetScope() == eValueTypeVariableLocal)
9287fa27ce4SDimitry Andric watch_sp->SetupVariableWatchpointDisabler(m_exe_ctx.GetFrameSP());
9297fa27ce4SDimitry Andric }
9307fa27ce4SDimitry Andric output_stream.Printf("Watchpoint created: ");
9317fa27ce4SDimitry Andric watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
9327fa27ce4SDimitry Andric output_stream.EOL();
9337fa27ce4SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
934f034231aSEd Maste }
935f034231aSEd Maste
936f034231aSEd Maste private:
937f034231aSEd Maste OptionGroupOptions m_option_group;
938f034231aSEd Maste OptionGroupWatchpoint m_option_watchpoint;
939f034231aSEd Maste };
940f034231aSEd Maste
941f034231aSEd Maste // CommandObjectWatchpointSetExpression
942f034231aSEd Maste #pragma mark Set
943f034231aSEd Maste
94414f1b3e8SDimitry Andric class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
945f034231aSEd Maste public:
CommandObjectWatchpointSetExpression(CommandInterpreter & interpreter)94614f1b3e8SDimitry Andric CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter)
94714f1b3e8SDimitry Andric : CommandObjectRaw(
94814f1b3e8SDimitry Andric interpreter, "watchpoint set expression",
949f034231aSEd Maste "Set a watchpoint on an address by supplying an expression. "
9507fa27ce4SDimitry Andric "Use the '-l' option to specify the language of the expression. "
951f034231aSEd Maste "Use the '-w' option to specify the type of watchpoint and "
952f3fbd1c0SDimitry Andric "the '-s' option to specify the byte size to watch for. "
953b1c73532SDimitry Andric "If no '-w' option is specified, it defaults to modify. "
954f3fbd1c0SDimitry Andric "If no '-s' option is specified, it defaults to the target's "
955f034231aSEd Maste "pointer byte size. "
956f034231aSEd Maste "Note that there are limited hardware resources for watchpoints. "
95714f1b3e8SDimitry Andric "If watchpoint setting fails, consider disable/delete existing "
95814f1b3e8SDimitry Andric "ones "
959f034231aSEd Maste "to free up resources.",
96014f1b3e8SDimitry Andric "",
96114f1b3e8SDimitry Andric eCommandRequiresFrame | eCommandTryTargetAPILock |
9626f8fc217SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
963f034231aSEd Maste SetHelpLong(
964027f1c96SDimitry Andric R"(
965027f1c96SDimitry Andric Examples:
966027f1c96SDimitry Andric
967b1c73532SDimitry Andric (lldb) watchpoint set expression -w modify -s 1 -- foo + 32
968027f1c96SDimitry Andric
96914f1b3e8SDimitry Andric Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
970f034231aSEd Maste
971ac9a064cSDimitry Andric AddSimpleArgumentList(eArgTypeExpression);
972f034231aSEd Maste
973f3fbd1c0SDimitry Andric // Absorb the '-w' and '-s' options into our option group.
97414f1b3e8SDimitry Andric m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
97514f1b3e8SDimitry Andric LLDB_OPT_SET_1);
976f034231aSEd Maste m_option_group.Finalize();
977f034231aSEd Maste }
978f034231aSEd Maste
979f3fbd1c0SDimitry Andric ~CommandObjectWatchpointSetExpression() override = default;
980f034231aSEd Maste
98114f1b3e8SDimitry Andric // Overrides base class's behavior where WantsCompletion =
98214f1b3e8SDimitry Andric // !WantsRawCommandString.
WantsCompletion()98314f1b3e8SDimitry Andric bool WantsCompletion() override { return true; }
984f034231aSEd Maste
GetOptions()98514f1b3e8SDimitry Andric Options *GetOptions() override { return &m_option_group; }
986f034231aSEd Maste
987f034231aSEd Maste protected:
DoExecute(llvm::StringRef raw_command,CommandReturnObject & result)988b1c73532SDimitry Andric void DoExecute(llvm::StringRef raw_command,
98914f1b3e8SDimitry Andric CommandReturnObject &result) override {
99014f1b3e8SDimitry Andric auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
99114f1b3e8SDimitry Andric m_option_group.NotifyOptionParsingStarting(
99214f1b3e8SDimitry Andric &exe_ctx); // This is a raw command, so notify the option group
993f034231aSEd Maste
9945f29bb8aSDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
995f034231aSEd Maste StackFrame *frame = m_exe_ctx.GetFramePtr();
996f034231aSEd Maste
997f73363f1SDimitry Andric OptionsWithRaw args(raw_command);
998f034231aSEd Maste
999f73363f1SDimitry Andric llvm::StringRef expr = args.GetRawPart();
1000f73363f1SDimitry Andric
1001f73363f1SDimitry Andric if (args.HasArgs())
1002f73363f1SDimitry Andric if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
1003f73363f1SDimitry Andric exe_ctx))
1004b1c73532SDimitry Andric return;
1005f034231aSEd Maste
1006f73363f1SDimitry Andric // If no argument is present, issue an error message. There's no way to
1007f73363f1SDimitry Andric // set a watchpoint.
1008f73363f1SDimitry Andric if (raw_command.trim().empty()) {
1009344a3780SDimitry Andric result.AppendError("required argument missing; specify an expression "
1010344a3780SDimitry Andric "to evaluate into the address to watch for");
1011b1c73532SDimitry Andric return;
1012f034231aSEd Maste }
1013f034231aSEd Maste
1014f034231aSEd Maste // If no '-w' is specified, default to '-w write'.
101514f1b3e8SDimitry Andric if (!m_option_watchpoint.watch_type_specified) {
1016b1c73532SDimitry Andric m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify;
1017f034231aSEd Maste }
1018f034231aSEd Maste
1019f73363f1SDimitry Andric // We passed the sanity check for the command. Proceed to set the
1020f73363f1SDimitry Andric // watchpoint now.
1021f034231aSEd Maste lldb::addr_t addr = 0;
1022f034231aSEd Maste size_t size = 0;
1023f034231aSEd Maste
1024f034231aSEd Maste ValueObjectSP valobj_sp;
1025f034231aSEd Maste
1026f034231aSEd Maste // Use expression evaluation to arrive at the address to watch.
1027f034231aSEd Maste EvaluateExpressionOptions options;
102886758c71SEd Maste options.SetCoerceToId(false);
102986758c71SEd Maste options.SetUnwindOnError(true);
103086758c71SEd Maste options.SetKeepInMemory(false);
103186758c71SEd Maste options.SetTryAllThreads(true);
1032e3b55780SDimitry Andric options.SetTimeout(std::nullopt);
10337fa27ce4SDimitry Andric if (m_option_watchpoint.language_type != eLanguageTypeUnknown)
10347fa27ce4SDimitry Andric options.SetLanguage(m_option_watchpoint.language_type);
1035f034231aSEd Maste
103614f1b3e8SDimitry Andric ExpressionResults expr_result =
103714f1b3e8SDimitry Andric target->EvaluateExpression(expr, frame, valobj_sp, options);
103814f1b3e8SDimitry Andric if (expr_result != eExpressionCompleted) {
1039344a3780SDimitry Andric result.AppendError("expression evaluation of address to watch failed");
1040344a3780SDimitry Andric result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data());
1041cfca06d7SDimitry Andric if (valobj_sp && !valobj_sp->GetError().Success())
1042344a3780SDimitry Andric result.AppendError(valobj_sp->GetError().AsCString());
1043b1c73532SDimitry Andric return;
1044f034231aSEd Maste }
1045f034231aSEd Maste
1046f034231aSEd Maste // Get the address to watch.
1047f034231aSEd Maste bool success = false;
1048f034231aSEd Maste addr = valobj_sp->GetValueAsUnsigned(0, &success);
104914f1b3e8SDimitry Andric if (!success) {
1050344a3780SDimitry Andric result.AppendError("expression did not evaluate to an address");
1051b1c73532SDimitry Andric return;
1052f034231aSEd Maste }
1053f034231aSEd Maste
1054b1c73532SDimitry Andric if (m_option_watchpoint.watch_size.GetCurrentValue() != 0)
1055b1c73532SDimitry Andric size = m_option_watchpoint.watch_size.GetCurrentValue();
1056f034231aSEd Maste else
1057f034231aSEd Maste size = target->GetArchitecture().GetAddressByteSize();
1058f034231aSEd Maste
1059f034231aSEd Maste // Now it's time to create the watchpoint.
1060b1c73532SDimitry Andric uint32_t watch_type;
1061b1c73532SDimitry Andric switch (m_option_watchpoint.watch_type) {
1062b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchRead:
1063b1c73532SDimitry Andric watch_type = LLDB_WATCH_TYPE_READ;
1064b1c73532SDimitry Andric break;
1065b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchWrite:
1066b1c73532SDimitry Andric watch_type = LLDB_WATCH_TYPE_WRITE;
1067b1c73532SDimitry Andric break;
1068b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchModify:
1069b1c73532SDimitry Andric watch_type = LLDB_WATCH_TYPE_MODIFY;
1070b1c73532SDimitry Andric break;
1071b1c73532SDimitry Andric case OptionGroupWatchpoint::eWatchReadWrite:
1072b1c73532SDimitry Andric watch_type = LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE;
1073b1c73532SDimitry Andric break;
1074b1c73532SDimitry Andric default:
1075b1c73532SDimitry Andric watch_type = LLDB_WATCH_TYPE_MODIFY;
1076b1c73532SDimitry Andric }
1077f034231aSEd Maste
107814f1b3e8SDimitry Andric // Fetch the type from the value object, the type of the watched object is
107914f1b3e8SDimitry Andric // the pointee type
1080f034231aSEd Maste /// of the expression, so convert to that if we found a valid type.
1081e81d9d49SDimitry Andric CompilerType compiler_type(valobj_sp->GetCompilerType());
1082f034231aSEd Maste
1083ac9a064cSDimitry Andric std::optional<uint64_t> valobj_size = valobj_sp->GetByteSize();
1084ac9a064cSDimitry Andric // Set the type as a uint8_t array if the size being watched is
1085ac9a064cSDimitry Andric // larger than the ValueObject's size (which is probably the size
1086ac9a064cSDimitry Andric // of a pointer).
1087ac9a064cSDimitry Andric if (valobj_size && size > *valobj_size) {
1088ac9a064cSDimitry Andric auto type_system = compiler_type.GetTypeSystem();
1089ac9a064cSDimitry Andric if (type_system) {
1090ac9a064cSDimitry Andric CompilerType clang_uint8_type =
1091ac9a064cSDimitry Andric type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
1092ac9a064cSDimitry Andric compiler_type = clang_uint8_type.GetArrayType(size);
1093ac9a064cSDimitry Andric }
1094ac9a064cSDimitry Andric }
1095ac9a064cSDimitry Andric
1096b76161e4SDimitry Andric Status error;
10977fa27ce4SDimitry Andric WatchpointSP watch_sp =
10987fa27ce4SDimitry Andric target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
10997fa27ce4SDimitry Andric if (watch_sp) {
11007fa27ce4SDimitry Andric watch_sp->SetWatchSpec(std::string(expr));
1101f034231aSEd Maste Stream &output_stream = result.GetOutputStream();
1102f034231aSEd Maste output_stream.Printf("Watchpoint created: ");
11037fa27ce4SDimitry Andric watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1104f034231aSEd Maste output_stream.EOL();
1105f034231aSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
110614f1b3e8SDimitry Andric } else {
110714f1b3e8SDimitry Andric result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
110814f1b3e8SDimitry Andric ", size=%" PRIu64 ").\n",
11090cac4ca3SEd Maste addr, (uint64_t)size);
1110f3fbd1c0SDimitry Andric if (error.AsCString(nullptr))
1111f034231aSEd Maste result.AppendError(error.AsCString());
1112f034231aSEd Maste }
1113f034231aSEd Maste }
1114f034231aSEd Maste
1115f034231aSEd Maste private:
1116f034231aSEd Maste OptionGroupOptions m_option_group;
1117f034231aSEd Maste OptionGroupWatchpoint m_option_watchpoint;
1118f034231aSEd Maste };
1119f034231aSEd Maste
1120f034231aSEd Maste // CommandObjectWatchpointSet
1121f034231aSEd Maste #pragma mark Set
1122f034231aSEd Maste
112314f1b3e8SDimitry Andric class CommandObjectWatchpointSet : public CommandObjectMultiword {
1124f034231aSEd Maste public:
CommandObjectWatchpointSet(CommandInterpreter & interpreter)1125f3fbd1c0SDimitry Andric CommandObjectWatchpointSet(CommandInterpreter &interpreter)
112614f1b3e8SDimitry Andric : CommandObjectMultiword(
112714f1b3e8SDimitry Andric interpreter, "watchpoint set", "Commands for setting a watchpoint.",
112814f1b3e8SDimitry Andric "watchpoint set <subcommand> [<subcommand-options>]") {
1129f034231aSEd Maste
113014f1b3e8SDimitry Andric LoadSubCommand(
113114f1b3e8SDimitry Andric "variable",
113214f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter)));
113314f1b3e8SDimitry Andric LoadSubCommand(
113414f1b3e8SDimitry Andric "expression",
113514f1b3e8SDimitry Andric CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter)));
1136f034231aSEd Maste }
1137f034231aSEd Maste
1138f3fbd1c0SDimitry Andric ~CommandObjectWatchpointSet() override = default;
1139f034231aSEd Maste };
1140f034231aSEd Maste
1141f034231aSEd Maste // CommandObjectMultiwordWatchpoint
1142f034231aSEd Maste #pragma mark MultiwordWatchpoint
1143f034231aSEd Maste
CommandObjectMultiwordWatchpoint(CommandInterpreter & interpreter)114414f1b3e8SDimitry Andric CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(
114514f1b3e8SDimitry Andric CommandInterpreter &interpreter)
114614f1b3e8SDimitry Andric : CommandObjectMultiword(interpreter, "watchpoint",
114714f1b3e8SDimitry Andric "Commands for operating on watchpoints.",
114814f1b3e8SDimitry Andric "watchpoint <subcommand> [<command-options>]") {
114914f1b3e8SDimitry Andric CommandObjectSP list_command_object(
115014f1b3e8SDimitry Andric new CommandObjectWatchpointList(interpreter));
115114f1b3e8SDimitry Andric CommandObjectSP enable_command_object(
115214f1b3e8SDimitry Andric new CommandObjectWatchpointEnable(interpreter));
115314f1b3e8SDimitry Andric CommandObjectSP disable_command_object(
115414f1b3e8SDimitry Andric new CommandObjectWatchpointDisable(interpreter));
115514f1b3e8SDimitry Andric CommandObjectSP delete_command_object(
115614f1b3e8SDimitry Andric new CommandObjectWatchpointDelete(interpreter));
115714f1b3e8SDimitry Andric CommandObjectSP ignore_command_object(
115814f1b3e8SDimitry Andric new CommandObjectWatchpointIgnore(interpreter));
115914f1b3e8SDimitry Andric CommandObjectSP command_command_object(
116014f1b3e8SDimitry Andric new CommandObjectWatchpointCommand(interpreter));
116114f1b3e8SDimitry Andric CommandObjectSP modify_command_object(
116214f1b3e8SDimitry Andric new CommandObjectWatchpointModify(interpreter));
116314f1b3e8SDimitry Andric CommandObjectSP set_command_object(
116414f1b3e8SDimitry Andric new CommandObjectWatchpointSet(interpreter));
1165f034231aSEd Maste
1166f034231aSEd Maste list_command_object->SetCommandName("watchpoint list");
1167f034231aSEd Maste enable_command_object->SetCommandName("watchpoint enable");
1168f034231aSEd Maste disable_command_object->SetCommandName("watchpoint disable");
1169f034231aSEd Maste delete_command_object->SetCommandName("watchpoint delete");
1170f034231aSEd Maste ignore_command_object->SetCommandName("watchpoint ignore");
1171f034231aSEd Maste command_command_object->SetCommandName("watchpoint command");
1172f034231aSEd Maste modify_command_object->SetCommandName("watchpoint modify");
1173f034231aSEd Maste set_command_object->SetCommandName("watchpoint set");
1174f034231aSEd Maste
1175f034231aSEd Maste LoadSubCommand("list", list_command_object);
1176f034231aSEd Maste LoadSubCommand("enable", enable_command_object);
1177f034231aSEd Maste LoadSubCommand("disable", disable_command_object);
1178f034231aSEd Maste LoadSubCommand("delete", delete_command_object);
1179f034231aSEd Maste LoadSubCommand("ignore", ignore_command_object);
1180f034231aSEd Maste LoadSubCommand("command", command_command_object);
1181f034231aSEd Maste LoadSubCommand("modify", modify_command_object);
1182f034231aSEd Maste LoadSubCommand("set", set_command_object);
1183f034231aSEd Maste }
1184f034231aSEd Maste
1185f3fbd1c0SDimitry Andric CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default;
1186