xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectWatchpoint.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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