1ac7ddfbfSEd Maste //===-- CommandObjectWatchpoint.cpp -----------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "CommandObjectWatchpoint.h"
11ac7ddfbfSEd Maste #include "CommandObjectWatchpointCommand.h"
12ac7ddfbfSEd Maste 
134bb0738eSEd Maste #include <vector>
144bb0738eSEd Maste 
154bb0738eSEd Maste #include "llvm/ADT/StringRef.h"
164bb0738eSEd Maste 
17ac7ddfbfSEd Maste #include "lldb/Breakpoint/Watchpoint.h"
18ac7ddfbfSEd Maste #include "lldb/Breakpoint/WatchpointList.h"
19ac7ddfbfSEd Maste #include "lldb/Core/ValueObject.h"
20ac7ddfbfSEd Maste #include "lldb/Core/ValueObjectVariable.h"
21f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
22435933ddSDimitry Andric #include "lldb/Interpreter/CommandCompletions.h"
23ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
25ac7ddfbfSEd Maste #include "lldb/Symbol/Variable.h"
26ac7ddfbfSEd Maste #include "lldb/Symbol/VariableList.h"
271c3bbb01SEd Maste #include "lldb/Target/StackFrame.h"
28ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
29f678e45dSDimitry Andric #include "lldb/Utility/StreamString.h"
30ac7ddfbfSEd Maste 
31ac7ddfbfSEd Maste using namespace lldb;
32ac7ddfbfSEd Maste using namespace lldb_private;
33ac7ddfbfSEd Maste 
AddWatchpointDescription(Stream * s,Watchpoint * wp,lldb::DescriptionLevel level)34435933ddSDimitry Andric static void AddWatchpointDescription(Stream *s, Watchpoint *wp,
35435933ddSDimitry Andric                                      lldb::DescriptionLevel level) {
36ac7ddfbfSEd Maste   s->IndentMore();
37ac7ddfbfSEd Maste   wp->GetDescription(s, level);
38ac7ddfbfSEd Maste   s->IndentLess();
39ac7ddfbfSEd Maste   s->EOL();
40ac7ddfbfSEd Maste }
41ac7ddfbfSEd Maste 
CheckTargetForWatchpointOperations(Target * target,CommandReturnObject & result)42435933ddSDimitry Andric static bool CheckTargetForWatchpointOperations(Target *target,
43435933ddSDimitry Andric                                                CommandReturnObject &result) {
44435933ddSDimitry Andric   if (target == nullptr) {
45ac7ddfbfSEd Maste     result.AppendError("Invalid target.  No existing target or watchpoints.");
46ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusFailed);
47ac7ddfbfSEd Maste     return false;
48ac7ddfbfSEd Maste   }
49435933ddSDimitry Andric   bool process_is_valid =
50435933ddSDimitry Andric       target->GetProcessSP() && target->GetProcessSP()->IsAlive();
51435933ddSDimitry Andric   if (!process_is_valid) {
52ac7ddfbfSEd Maste     result.AppendError("Thre's no process or it is not alive.");
53ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusFailed);
54ac7ddfbfSEd Maste     return false;
55ac7ddfbfSEd Maste   }
56ac7ddfbfSEd Maste   // Target passes our checks, return true.
57ac7ddfbfSEd Maste   return true;
58ac7ddfbfSEd Maste }
59ac7ddfbfSEd Maste 
60ac7ddfbfSEd Maste // Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
61ac7ddfbfSEd Maste static const char *RSA[4] = {"-", "to", "To", "TO"};
62ac7ddfbfSEd Maste 
63ac7ddfbfSEd Maste // Return the index to RSA if found; otherwise -1 is returned.
WithRSAIndex(llvm::StringRef Arg)64435933ddSDimitry Andric static int32_t WithRSAIndex(llvm::StringRef Arg) {
65ac7ddfbfSEd Maste 
66ac7ddfbfSEd Maste   uint32_t i;
67ac7ddfbfSEd Maste   for (i = 0; i < 4; ++i)
68ac7ddfbfSEd Maste     if (Arg.find(RSA[i]) != llvm::StringRef::npos)
69ac7ddfbfSEd Maste       return i;
70ac7ddfbfSEd Maste   return -1;
71ac7ddfbfSEd Maste }
72ac7ddfbfSEd Maste 
734ba319b5SDimitry Andric // Return true if wp_ids is successfully populated with the watch ids. False
744ba319b5SDimitry Andric // otherwise.
VerifyWatchpointIDs(Target * target,Args & args,std::vector<uint32_t> & wp_ids)75435933ddSDimitry Andric bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
76435933ddSDimitry Andric     Target *target, Args &args, std::vector<uint32_t> &wp_ids) {
77ac7ddfbfSEd Maste   // Pre-condition: args.GetArgumentCount() > 0.
78435933ddSDimitry Andric   if (args.GetArgumentCount() == 0) {
794bb0738eSEd Maste     if (target == nullptr)
80ac7ddfbfSEd Maste       return false;
81ac7ddfbfSEd Maste     WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
82435933ddSDimitry Andric     if (watch_sp) {
83ac7ddfbfSEd Maste       wp_ids.push_back(watch_sp->GetID());
84ac7ddfbfSEd Maste       return true;
85435933ddSDimitry Andric     } else
86ac7ddfbfSEd Maste       return false;
87ac7ddfbfSEd Maste   }
88ac7ddfbfSEd Maste 
89ac7ddfbfSEd Maste   llvm::StringRef Minus("-");
90ac7ddfbfSEd Maste   std::vector<llvm::StringRef> StrRefArgs;
91435933ddSDimitry Andric   llvm::StringRef first;
92435933ddSDimitry Andric   llvm::StringRef second;
93ac7ddfbfSEd Maste   size_t i;
94ac7ddfbfSEd Maste   int32_t idx;
959f2f44ceSEd Maste   // Go through the arguments and make a canonical form of arg list containing
96ac7ddfbfSEd Maste   // only numbers with possible "-" in between.
97435933ddSDimitry Andric   for (auto &entry : args.entries()) {
98435933ddSDimitry Andric     if ((idx = WithRSAIndex(entry.ref)) == -1) {
99435933ddSDimitry Andric       StrRefArgs.push_back(entry.ref);
100ac7ddfbfSEd Maste       continue;
101ac7ddfbfSEd Maste     }
102ac7ddfbfSEd Maste     // The Arg contains the range specifier, split it, then.
103435933ddSDimitry Andric     std::tie(first, second) = entry.ref.split(RSA[idx]);
104435933ddSDimitry Andric     if (!first.empty())
105435933ddSDimitry Andric       StrRefArgs.push_back(first);
106ac7ddfbfSEd Maste     StrRefArgs.push_back(Minus);
107435933ddSDimitry Andric     if (!second.empty())
108435933ddSDimitry Andric       StrRefArgs.push_back(second);
109ac7ddfbfSEd Maste   }
1104ba319b5SDimitry Andric   // Now process the canonical list and fill in the vector of uint32_t's. If
1114ba319b5SDimitry Andric   // there is any error, return false and the client should ignore wp_ids.
112ac7ddfbfSEd Maste   uint32_t beg, end, id;
113ac7ddfbfSEd Maste   size_t size = StrRefArgs.size();
114ac7ddfbfSEd Maste   bool in_range = false;
115ac7ddfbfSEd Maste   for (i = 0; i < size; ++i) {
116ac7ddfbfSEd Maste     llvm::StringRef Arg = StrRefArgs[i];
117ac7ddfbfSEd Maste     if (in_range) {
118ac7ddfbfSEd Maste       // Look for the 'end' of the range.  Note StringRef::getAsInteger()
119ac7ddfbfSEd Maste       // returns true to signify error while parsing.
120ac7ddfbfSEd Maste       if (Arg.getAsInteger(0, end))
121ac7ddfbfSEd Maste         return false;
122ac7ddfbfSEd Maste       // Found a range!  Now append the elements.
123ac7ddfbfSEd Maste       for (id = beg; id <= end; ++id)
124ac7ddfbfSEd Maste         wp_ids.push_back(id);
125ac7ddfbfSEd Maste       in_range = false;
126ac7ddfbfSEd Maste       continue;
127ac7ddfbfSEd Maste     }
128ac7ddfbfSEd Maste     if (i < (size - 1) && StrRefArgs[i + 1] == Minus) {
129ac7ddfbfSEd Maste       if (Arg.getAsInteger(0, beg))
130ac7ddfbfSEd Maste         return false;
131ac7ddfbfSEd Maste       // Turn on the in_range flag, we are looking for end of range next.
132435933ddSDimitry Andric       ++i;
133435933ddSDimitry Andric       in_range = true;
134ac7ddfbfSEd Maste       continue;
135ac7ddfbfSEd Maste     }
136ac7ddfbfSEd Maste     // Otherwise, we have a simple ID.  Just append it.
137ac7ddfbfSEd Maste     if (Arg.getAsInteger(0, beg))
138ac7ddfbfSEd Maste       return false;
139ac7ddfbfSEd Maste     wp_ids.push_back(beg);
140ac7ddfbfSEd Maste   }
141ac7ddfbfSEd Maste 
142*b5893f02SDimitry Andric   // It is an error if after the loop, we're still in_range.
143*b5893f02SDimitry Andric   return !in_range;
144ac7ddfbfSEd Maste }
145ac7ddfbfSEd Maste 
146ac7ddfbfSEd Maste //-------------------------------------------------------------------------
147ac7ddfbfSEd Maste // CommandObjectWatchpointList
148ac7ddfbfSEd Maste //-------------------------------------------------------------------------
149435933ddSDimitry Andric 
150435933ddSDimitry Andric //-------------------------------------------------------------------------
151435933ddSDimitry Andric // CommandObjectWatchpointList::Options
152435933ddSDimitry Andric //-------------------------------------------------------------------------
153435933ddSDimitry Andric #pragma mark List::CommandOptions
154435933ddSDimitry Andric 
155*b5893f02SDimitry Andric static constexpr OptionDefinition g_watchpoint_list_options[] = {
156435933ddSDimitry Andric     // clang-format off
157*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "brief",   'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." },
158*b5893f02SDimitry Andric   { LLDB_OPT_SET_2, false, "full",    'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." },
159*b5893f02SDimitry Andric   { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." }
160435933ddSDimitry Andric     // clang-format on
161435933ddSDimitry Andric };
162435933ddSDimitry Andric 
163ac7ddfbfSEd Maste #pragma mark List
164ac7ddfbfSEd Maste 
165435933ddSDimitry Andric class CommandObjectWatchpointList : public CommandObjectParsed {
166ac7ddfbfSEd Maste public:
CommandObjectWatchpointList(CommandInterpreter & interpreter)167435933ddSDimitry Andric   CommandObjectWatchpointList(CommandInterpreter &interpreter)
168435933ddSDimitry Andric       : CommandObjectParsed(
169435933ddSDimitry Andric             interpreter, "watchpoint list",
170435933ddSDimitry Andric             "List all watchpoints at configurable levels of detail.", nullptr),
171435933ddSDimitry Andric         m_options() {
172ac7ddfbfSEd Maste     CommandArgumentEntry arg;
173435933ddSDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
174435933ddSDimitry Andric                                       eArgTypeWatchpointIDRange);
175435933ddSDimitry Andric     // Add the entry for the first argument for this command to the object's
176435933ddSDimitry Andric     // arguments vector.
177ac7ddfbfSEd Maste     m_arguments.push_back(arg);
178ac7ddfbfSEd Maste   }
179ac7ddfbfSEd Maste 
1804bb0738eSEd Maste   ~CommandObjectWatchpointList() override = default;
181ac7ddfbfSEd Maste 
GetOptions()182435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
183ac7ddfbfSEd Maste 
184435933ddSDimitry Andric   class CommandOptions : public Options {
185ac7ddfbfSEd Maste   public:
CommandOptions()186435933ddSDimitry Andric     CommandOptions()
187435933ddSDimitry Andric         : Options(),
188435933ddSDimitry Andric           m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to
189435933ddSDimitry Andric                                                 // brief descriptions
190435933ddSDimitry Andric     {}
191ac7ddfbfSEd Maste 
1924bb0738eSEd Maste     ~CommandOptions() override = default;
193ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1945517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
195435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
1965517e702SDimitry Andric       Status error;
197ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
198ac7ddfbfSEd Maste 
199435933ddSDimitry Andric       switch (short_option) {
200ac7ddfbfSEd Maste       case 'b':
201ac7ddfbfSEd Maste         m_level = lldb::eDescriptionLevelBrief;
202ac7ddfbfSEd Maste         break;
203ac7ddfbfSEd Maste       case 'f':
204ac7ddfbfSEd Maste         m_level = lldb::eDescriptionLevelFull;
205ac7ddfbfSEd Maste         break;
206ac7ddfbfSEd Maste       case 'v':
207ac7ddfbfSEd Maste         m_level = lldb::eDescriptionLevelVerbose;
208ac7ddfbfSEd Maste         break;
209ac7ddfbfSEd Maste       default:
210435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
211435933ddSDimitry Andric                                        short_option);
212ac7ddfbfSEd Maste         break;
213ac7ddfbfSEd Maste       }
214ac7ddfbfSEd Maste 
215ac7ddfbfSEd Maste       return error;
216ac7ddfbfSEd Maste     }
217ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)218435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
219ac7ddfbfSEd Maste       m_level = lldb::eDescriptionLevelFull;
220ac7ddfbfSEd Maste     }
221ac7ddfbfSEd Maste 
GetDefinitions()222435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
223435933ddSDimitry Andric       return llvm::makeArrayRef(g_watchpoint_list_options);
224ac7ddfbfSEd Maste     }
225ac7ddfbfSEd Maste 
226ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
227ac7ddfbfSEd Maste 
228ac7ddfbfSEd Maste     lldb::DescriptionLevel m_level;
229ac7ddfbfSEd Maste   };
230ac7ddfbfSEd Maste 
231ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)232435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
233ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
234435933ddSDimitry Andric     if (target == nullptr) {
235ac7ddfbfSEd Maste       result.AppendError("Invalid target. No current target or watchpoints.");
236ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
237ac7ddfbfSEd Maste       return true;
238ac7ddfbfSEd Maste     }
239ac7ddfbfSEd Maste 
240435933ddSDimitry Andric     if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
241ac7ddfbfSEd Maste       uint32_t num_supported_hardware_watchpoints;
2425517e702SDimitry Andric       Status error = target->GetProcessSP()->GetWatchpointSupportInfo(
243435933ddSDimitry Andric           num_supported_hardware_watchpoints);
244ac7ddfbfSEd Maste       if (error.Success())
245435933ddSDimitry Andric         result.AppendMessageWithFormat(
246435933ddSDimitry Andric             "Number of supported hardware watchpoints: %u\n",
247ac7ddfbfSEd Maste             num_supported_hardware_watchpoints);
248ac7ddfbfSEd Maste     }
249ac7ddfbfSEd Maste 
250ac7ddfbfSEd Maste     const WatchpointList &watchpoints = target->GetWatchpointList();
2514bb0738eSEd Maste 
2524bb0738eSEd Maste     std::unique_lock<std::recursive_mutex> lock;
2534bb0738eSEd Maste     target->GetWatchpointList().GetListMutex(lock);
254ac7ddfbfSEd Maste 
255ac7ddfbfSEd Maste     size_t num_watchpoints = watchpoints.GetSize();
256ac7ddfbfSEd Maste 
257435933ddSDimitry Andric     if (num_watchpoints == 0) {
258ac7ddfbfSEd Maste       result.AppendMessage("No watchpoints currently set.");
259ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
260ac7ddfbfSEd Maste       return true;
261ac7ddfbfSEd Maste     }
262ac7ddfbfSEd Maste 
263ac7ddfbfSEd Maste     Stream &output_stream = result.GetOutputStream();
264ac7ddfbfSEd Maste 
265435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
266ac7ddfbfSEd Maste       // No watchpoint selected; show info about all currently set watchpoints.
267ac7ddfbfSEd Maste       result.AppendMessage("Current watchpoints:");
268435933ddSDimitry Andric       for (size_t i = 0; i < num_watchpoints; ++i) {
269ac7ddfbfSEd Maste         Watchpoint *wp = watchpoints.GetByIndex(i).get();
270ac7ddfbfSEd Maste         AddWatchpointDescription(&output_stream, wp, m_options.m_level);
271ac7ddfbfSEd Maste       }
272ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
273435933ddSDimitry Andric     } else {
274ac7ddfbfSEd Maste       // Particular watchpoints selected; enable them.
275ac7ddfbfSEd Maste       std::vector<uint32_t> wp_ids;
276435933ddSDimitry Andric       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
277435933ddSDimitry Andric               target, command, wp_ids)) {
278ac7ddfbfSEd Maste         result.AppendError("Invalid watchpoints specification.");
279ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
280ac7ddfbfSEd Maste         return false;
281ac7ddfbfSEd Maste       }
282ac7ddfbfSEd Maste 
283ac7ddfbfSEd Maste       const size_t size = wp_ids.size();
284435933ddSDimitry Andric       for (size_t i = 0; i < size; ++i) {
285ac7ddfbfSEd Maste         Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get();
286ac7ddfbfSEd Maste         if (wp)
287ac7ddfbfSEd Maste           AddWatchpointDescription(&output_stream, wp, m_options.m_level);
288ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
289ac7ddfbfSEd Maste       }
290ac7ddfbfSEd Maste     }
291ac7ddfbfSEd Maste 
292ac7ddfbfSEd Maste     return result.Succeeded();
293ac7ddfbfSEd Maste   }
294ac7ddfbfSEd Maste 
295ac7ddfbfSEd Maste private:
296ac7ddfbfSEd Maste   CommandOptions m_options;
297ac7ddfbfSEd Maste };
298ac7ddfbfSEd Maste 
299ac7ddfbfSEd Maste //-------------------------------------------------------------------------
300ac7ddfbfSEd Maste // CommandObjectWatchpointEnable
301ac7ddfbfSEd Maste //-------------------------------------------------------------------------
302ac7ddfbfSEd Maste #pragma mark Enable
303ac7ddfbfSEd Maste 
304435933ddSDimitry Andric class CommandObjectWatchpointEnable : public CommandObjectParsed {
305ac7ddfbfSEd Maste public:
CommandObjectWatchpointEnable(CommandInterpreter & interpreter)306435933ddSDimitry Andric   CommandObjectWatchpointEnable(CommandInterpreter &interpreter)
307435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "enable",
308435933ddSDimitry Andric                             "Enable the specified disabled watchpoint(s). If "
309435933ddSDimitry Andric                             "no watchpoints are specified, enable all of them.",
310435933ddSDimitry Andric                             nullptr) {
311ac7ddfbfSEd Maste     CommandArgumentEntry arg;
312435933ddSDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
313435933ddSDimitry Andric                                       eArgTypeWatchpointIDRange);
314435933ddSDimitry Andric     // Add the entry for the first argument for this command to the object's
315435933ddSDimitry Andric     // arguments vector.
316ac7ddfbfSEd Maste     m_arguments.push_back(arg);
317ac7ddfbfSEd Maste   }
318ac7ddfbfSEd Maste 
3194bb0738eSEd Maste   ~CommandObjectWatchpointEnable() override = default;
320ac7ddfbfSEd Maste 
321ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)322435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
323ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
324ac7ddfbfSEd Maste     if (!CheckTargetForWatchpointOperations(target, result))
325ac7ddfbfSEd Maste       return false;
326ac7ddfbfSEd Maste 
3274bb0738eSEd Maste     std::unique_lock<std::recursive_mutex> lock;
3284bb0738eSEd Maste     target->GetWatchpointList().GetListMutex(lock);
329ac7ddfbfSEd Maste 
330ac7ddfbfSEd Maste     const WatchpointList &watchpoints = target->GetWatchpointList();
331ac7ddfbfSEd Maste 
332ac7ddfbfSEd Maste     size_t num_watchpoints = watchpoints.GetSize();
333ac7ddfbfSEd Maste 
334435933ddSDimitry Andric     if (num_watchpoints == 0) {
335ac7ddfbfSEd Maste       result.AppendError("No watchpoints exist to be enabled.");
336ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
337ac7ddfbfSEd Maste       return false;
338ac7ddfbfSEd Maste     }
339ac7ddfbfSEd Maste 
340435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
341ac7ddfbfSEd Maste       // No watchpoint selected; enable all currently set watchpoints.
342ac7ddfbfSEd Maste       target->EnableAllWatchpoints();
343435933ddSDimitry Andric       result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
344435933ddSDimitry Andric                                      " watchpoints)\n",
345435933ddSDimitry Andric                                      (uint64_t)num_watchpoints);
346ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
347435933ddSDimitry Andric     } else {
348ac7ddfbfSEd Maste       // Particular watchpoints selected; enable them.
349ac7ddfbfSEd Maste       std::vector<uint32_t> wp_ids;
350435933ddSDimitry Andric       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
351435933ddSDimitry Andric               target, command, wp_ids)) {
352ac7ddfbfSEd Maste         result.AppendError("Invalid watchpoints specification.");
353ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
354ac7ddfbfSEd Maste         return false;
355ac7ddfbfSEd Maste       }
356ac7ddfbfSEd Maste 
357ac7ddfbfSEd Maste       int count = 0;
358ac7ddfbfSEd Maste       const size_t size = wp_ids.size();
359ac7ddfbfSEd Maste       for (size_t i = 0; i < size; ++i)
360ac7ddfbfSEd Maste         if (target->EnableWatchpointByID(wp_ids[i]))
361ac7ddfbfSEd Maste           ++count;
362ac7ddfbfSEd Maste       result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
363ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
364ac7ddfbfSEd Maste     }
365ac7ddfbfSEd Maste 
366ac7ddfbfSEd Maste     return result.Succeeded();
367ac7ddfbfSEd Maste   }
368ac7ddfbfSEd Maste };
369ac7ddfbfSEd Maste 
370ac7ddfbfSEd Maste //-------------------------------------------------------------------------
371ac7ddfbfSEd Maste // CommandObjectWatchpointDisable
372ac7ddfbfSEd Maste //-------------------------------------------------------------------------
373ac7ddfbfSEd Maste #pragma mark Disable
374ac7ddfbfSEd Maste 
375435933ddSDimitry Andric class CommandObjectWatchpointDisable : public CommandObjectParsed {
376ac7ddfbfSEd Maste public:
CommandObjectWatchpointDisable(CommandInterpreter & interpreter)377435933ddSDimitry Andric   CommandObjectWatchpointDisable(CommandInterpreter &interpreter)
378435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "watchpoint disable",
379435933ddSDimitry Andric                             "Disable the specified watchpoint(s) without "
380435933ddSDimitry Andric                             "removing it/them.  If no watchpoints are "
381435933ddSDimitry Andric                             "specified, disable them all.",
382435933ddSDimitry Andric                             nullptr) {
383ac7ddfbfSEd Maste     CommandArgumentEntry arg;
384435933ddSDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
385435933ddSDimitry Andric                                       eArgTypeWatchpointIDRange);
386435933ddSDimitry Andric     // Add the entry for the first argument for this command to the object's
387435933ddSDimitry Andric     // arguments vector.
388ac7ddfbfSEd Maste     m_arguments.push_back(arg);
389ac7ddfbfSEd Maste   }
390ac7ddfbfSEd Maste 
3914bb0738eSEd Maste   ~CommandObjectWatchpointDisable() override = default;
392ac7ddfbfSEd Maste 
393ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)394435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
395ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
396ac7ddfbfSEd Maste     if (!CheckTargetForWatchpointOperations(target, result))
397ac7ddfbfSEd Maste       return false;
398ac7ddfbfSEd Maste 
3994bb0738eSEd Maste     std::unique_lock<std::recursive_mutex> lock;
4004bb0738eSEd Maste     target->GetWatchpointList().GetListMutex(lock);
401ac7ddfbfSEd Maste 
402ac7ddfbfSEd Maste     const WatchpointList &watchpoints = target->GetWatchpointList();
403ac7ddfbfSEd Maste     size_t num_watchpoints = watchpoints.GetSize();
404ac7ddfbfSEd Maste 
405435933ddSDimitry Andric     if (num_watchpoints == 0) {
406ac7ddfbfSEd Maste       result.AppendError("No watchpoints exist to be disabled.");
407ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
408ac7ddfbfSEd Maste       return false;
409ac7ddfbfSEd Maste     }
410ac7ddfbfSEd Maste 
411435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
412ac7ddfbfSEd Maste       // No watchpoint selected; disable all currently set watchpoints.
413435933ddSDimitry Andric       if (target->DisableAllWatchpoints()) {
414435933ddSDimitry Andric         result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
415435933ddSDimitry Andric                                        " watchpoints)\n",
416435933ddSDimitry Andric                                        (uint64_t)num_watchpoints);
417ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
418435933ddSDimitry Andric       } else {
419ac7ddfbfSEd Maste         result.AppendError("Disable all watchpoints failed\n");
420ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
421ac7ddfbfSEd Maste       }
422435933ddSDimitry Andric     } else {
423ac7ddfbfSEd Maste       // Particular watchpoints selected; disable them.
424ac7ddfbfSEd Maste       std::vector<uint32_t> wp_ids;
425435933ddSDimitry Andric       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
426435933ddSDimitry Andric               target, command, wp_ids)) {
427ac7ddfbfSEd Maste         result.AppendError("Invalid watchpoints specification.");
428ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
429ac7ddfbfSEd Maste         return false;
430ac7ddfbfSEd Maste       }
431ac7ddfbfSEd Maste 
432ac7ddfbfSEd Maste       int count = 0;
433ac7ddfbfSEd Maste       const size_t size = wp_ids.size();
434ac7ddfbfSEd Maste       for (size_t i = 0; i < size; ++i)
435ac7ddfbfSEd Maste         if (target->DisableWatchpointByID(wp_ids[i]))
436ac7ddfbfSEd Maste           ++count;
437ac7ddfbfSEd Maste       result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
438ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
439ac7ddfbfSEd Maste     }
440ac7ddfbfSEd Maste 
441ac7ddfbfSEd Maste     return result.Succeeded();
442ac7ddfbfSEd Maste   }
443ac7ddfbfSEd Maste };
444ac7ddfbfSEd Maste 
445ac7ddfbfSEd Maste //-------------------------------------------------------------------------
446ac7ddfbfSEd Maste // CommandObjectWatchpointDelete
447ac7ddfbfSEd Maste //-------------------------------------------------------------------------
448ac7ddfbfSEd Maste #pragma mark Delete
449ac7ddfbfSEd Maste 
450435933ddSDimitry Andric class CommandObjectWatchpointDelete : public CommandObjectParsed {
451ac7ddfbfSEd Maste public:
CommandObjectWatchpointDelete(CommandInterpreter & interpreter)452435933ddSDimitry Andric   CommandObjectWatchpointDelete(CommandInterpreter &interpreter)
453435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "watchpoint delete",
454435933ddSDimitry Andric                             "Delete the specified watchpoint(s).  If no "
455435933ddSDimitry Andric                             "watchpoints are specified, delete them all.",
456435933ddSDimitry Andric                             nullptr) {
457ac7ddfbfSEd Maste     CommandArgumentEntry arg;
458435933ddSDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
459435933ddSDimitry Andric                                       eArgTypeWatchpointIDRange);
460435933ddSDimitry Andric     // Add the entry for the first argument for this command to the object's
461435933ddSDimitry Andric     // arguments vector.
462ac7ddfbfSEd Maste     m_arguments.push_back(arg);
463ac7ddfbfSEd Maste   }
464ac7ddfbfSEd Maste 
4654bb0738eSEd Maste   ~CommandObjectWatchpointDelete() override = default;
466ac7ddfbfSEd Maste 
467ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)468435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
469ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
470ac7ddfbfSEd Maste     if (!CheckTargetForWatchpointOperations(target, result))
471ac7ddfbfSEd Maste       return false;
472ac7ddfbfSEd Maste 
4734bb0738eSEd Maste     std::unique_lock<std::recursive_mutex> lock;
4744bb0738eSEd Maste     target->GetWatchpointList().GetListMutex(lock);
475ac7ddfbfSEd Maste 
476ac7ddfbfSEd Maste     const WatchpointList &watchpoints = target->GetWatchpointList();
477ac7ddfbfSEd Maste 
478ac7ddfbfSEd Maste     size_t num_watchpoints = watchpoints.GetSize();
479ac7ddfbfSEd Maste 
480435933ddSDimitry Andric     if (num_watchpoints == 0) {
481ac7ddfbfSEd Maste       result.AppendError("No watchpoints exist to be deleted.");
482ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
483ac7ddfbfSEd Maste       return false;
484ac7ddfbfSEd Maste     }
485ac7ddfbfSEd Maste 
486435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
487435933ddSDimitry Andric       if (!m_interpreter.Confirm(
488435933ddSDimitry Andric               "About to delete all watchpoints, do you want to do that?",
489435933ddSDimitry Andric               true)) {
490ac7ddfbfSEd Maste         result.AppendMessage("Operation cancelled...");
491435933ddSDimitry Andric       } else {
492ac7ddfbfSEd Maste         target->RemoveAllWatchpoints();
493435933ddSDimitry Andric         result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
494435933ddSDimitry Andric                                        " watchpoints)\n",
495435933ddSDimitry Andric                                        (uint64_t)num_watchpoints);
496ac7ddfbfSEd Maste       }
497ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
498435933ddSDimitry Andric     } else {
499ac7ddfbfSEd Maste       // Particular watchpoints selected; delete them.
500ac7ddfbfSEd Maste       std::vector<uint32_t> wp_ids;
501435933ddSDimitry Andric       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
502435933ddSDimitry Andric               target, command, wp_ids)) {
503ac7ddfbfSEd Maste         result.AppendError("Invalid watchpoints specification.");
504ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
505ac7ddfbfSEd Maste         return false;
506ac7ddfbfSEd Maste       }
507ac7ddfbfSEd Maste 
508ac7ddfbfSEd Maste       int count = 0;
509ac7ddfbfSEd Maste       const size_t size = wp_ids.size();
510ac7ddfbfSEd Maste       for (size_t i = 0; i < size; ++i)
511ac7ddfbfSEd Maste         if (target->RemoveWatchpointByID(wp_ids[i]))
512ac7ddfbfSEd Maste           ++count;
513ac7ddfbfSEd Maste       result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
514ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
515ac7ddfbfSEd Maste     }
516ac7ddfbfSEd Maste 
517ac7ddfbfSEd Maste     return result.Succeeded();
518ac7ddfbfSEd Maste   }
519ac7ddfbfSEd Maste };
520ac7ddfbfSEd Maste 
521ac7ddfbfSEd Maste //-------------------------------------------------------------------------
522ac7ddfbfSEd Maste // CommandObjectWatchpointIgnore
523ac7ddfbfSEd Maste //-------------------------------------------------------------------------
524ac7ddfbfSEd Maste 
525435933ddSDimitry Andric #pragma mark Ignore::CommandOptions
526*b5893f02SDimitry Andric static constexpr OptionDefinition g_watchpoint_ignore_options[] = {
527435933ddSDimitry Andric     // clang-format off
528*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }
529435933ddSDimitry Andric     // clang-format on
530435933ddSDimitry Andric };
531435933ddSDimitry Andric 
532435933ddSDimitry Andric class CommandObjectWatchpointIgnore : public CommandObjectParsed {
533ac7ddfbfSEd Maste public:
CommandObjectWatchpointIgnore(CommandInterpreter & interpreter)534435933ddSDimitry Andric   CommandObjectWatchpointIgnore(CommandInterpreter &interpreter)
535435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "watchpoint ignore",
536435933ddSDimitry Andric                             "Set ignore count on the specified watchpoint(s).  "
537435933ddSDimitry Andric                             "If no watchpoints are specified, set them all.",
5384bb0738eSEd Maste                             nullptr),
539435933ddSDimitry Andric         m_options() {
540ac7ddfbfSEd Maste     CommandArgumentEntry arg;
541435933ddSDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
542435933ddSDimitry Andric                                       eArgTypeWatchpointIDRange);
543435933ddSDimitry Andric     // Add the entry for the first argument for this command to the object's
544435933ddSDimitry Andric     // arguments vector.
545ac7ddfbfSEd Maste     m_arguments.push_back(arg);
546ac7ddfbfSEd Maste   }
547ac7ddfbfSEd Maste 
5484bb0738eSEd Maste   ~CommandObjectWatchpointIgnore() override = default;
549ac7ddfbfSEd Maste 
GetOptions()550435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
551ac7ddfbfSEd Maste 
552435933ddSDimitry Andric   class CommandOptions : public Options {
553ac7ddfbfSEd Maste   public:
CommandOptions()554435933ddSDimitry Andric     CommandOptions() : Options(), m_ignore_count(0) {}
555ac7ddfbfSEd Maste 
5564bb0738eSEd Maste     ~CommandOptions() override = default;
557ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)5585517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
559435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
5605517e702SDimitry Andric       Status error;
561ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
562ac7ddfbfSEd Maste 
563435933ddSDimitry Andric       switch (short_option) {
564ac7ddfbfSEd Maste       case 'i':
565435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_ignore_count))
566435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid ignore count '%s'",
567435933ddSDimitry Andric                                          option_arg.str().c_str());
568ac7ddfbfSEd Maste         break;
569ac7ddfbfSEd Maste       default:
570435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
571435933ddSDimitry Andric                                        short_option);
572ac7ddfbfSEd Maste         break;
573ac7ddfbfSEd Maste       }
574ac7ddfbfSEd Maste 
575ac7ddfbfSEd Maste       return error;
576ac7ddfbfSEd Maste     }
577ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)578435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
579ac7ddfbfSEd Maste       m_ignore_count = 0;
580ac7ddfbfSEd Maste     }
581ac7ddfbfSEd Maste 
GetDefinitions()582435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
583435933ddSDimitry Andric       return llvm::makeArrayRef(g_watchpoint_ignore_options);
584ac7ddfbfSEd Maste     }
585ac7ddfbfSEd Maste 
586ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
587ac7ddfbfSEd Maste 
588ac7ddfbfSEd Maste     uint32_t m_ignore_count;
589ac7ddfbfSEd Maste   };
590ac7ddfbfSEd Maste 
591ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)592435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
593ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
594ac7ddfbfSEd Maste     if (!CheckTargetForWatchpointOperations(target, result))
595ac7ddfbfSEd Maste       return false;
596ac7ddfbfSEd Maste 
5974bb0738eSEd Maste     std::unique_lock<std::recursive_mutex> lock;
5984bb0738eSEd Maste     target->GetWatchpointList().GetListMutex(lock);
599ac7ddfbfSEd Maste 
600ac7ddfbfSEd Maste     const WatchpointList &watchpoints = target->GetWatchpointList();
601ac7ddfbfSEd Maste 
602ac7ddfbfSEd Maste     size_t num_watchpoints = watchpoints.GetSize();
603ac7ddfbfSEd Maste 
604435933ddSDimitry Andric     if (num_watchpoints == 0) {
605ac7ddfbfSEd Maste       result.AppendError("No watchpoints exist to be ignored.");
606ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
607ac7ddfbfSEd Maste       return false;
608ac7ddfbfSEd Maste     }
609ac7ddfbfSEd Maste 
610435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
611ac7ddfbfSEd Maste       target->IgnoreAllWatchpoints(m_options.m_ignore_count);
612435933ddSDimitry Andric       result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
613435933ddSDimitry Andric                                      " watchpoints)\n",
614435933ddSDimitry Andric                                      (uint64_t)num_watchpoints);
615ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
616435933ddSDimitry Andric     } else {
617ac7ddfbfSEd Maste       // Particular watchpoints selected; ignore them.
618ac7ddfbfSEd Maste       std::vector<uint32_t> wp_ids;
619435933ddSDimitry Andric       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
620435933ddSDimitry Andric               target, command, wp_ids)) {
621ac7ddfbfSEd Maste         result.AppendError("Invalid watchpoints specification.");
622ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
623ac7ddfbfSEd Maste         return false;
624ac7ddfbfSEd Maste       }
625ac7ddfbfSEd Maste 
626ac7ddfbfSEd Maste       int count = 0;
627ac7ddfbfSEd Maste       const size_t size = wp_ids.size();
628ac7ddfbfSEd Maste       for (size_t i = 0; i < size; ++i)
629ac7ddfbfSEd Maste         if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
630ac7ddfbfSEd Maste           ++count;
631ac7ddfbfSEd Maste       result.AppendMessageWithFormat("%d watchpoints ignored.\n", count);
632ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
633ac7ddfbfSEd Maste     }
634ac7ddfbfSEd Maste 
635ac7ddfbfSEd Maste     return result.Succeeded();
636ac7ddfbfSEd Maste   }
637ac7ddfbfSEd Maste 
638ac7ddfbfSEd Maste private:
639ac7ddfbfSEd Maste   CommandOptions m_options;
640ac7ddfbfSEd Maste };
641ac7ddfbfSEd Maste 
642ac7ddfbfSEd Maste //-------------------------------------------------------------------------
643ac7ddfbfSEd Maste // CommandObjectWatchpointModify
644ac7ddfbfSEd Maste //-------------------------------------------------------------------------
645435933ddSDimitry Andric 
646435933ddSDimitry Andric #pragma mark Modify::CommandOptions
647435933ddSDimitry Andric 
648*b5893f02SDimitry Andric static constexpr OptionDefinition g_watchpoint_modify_options[] = {
649435933ddSDimitry Andric     // clang-format off
650*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." }
651435933ddSDimitry Andric     // clang-format on
652435933ddSDimitry Andric };
653435933ddSDimitry Andric 
654ac7ddfbfSEd Maste #pragma mark Modify
655ac7ddfbfSEd Maste 
656435933ddSDimitry Andric class CommandObjectWatchpointModify : public CommandObjectParsed {
657ac7ddfbfSEd Maste public:
CommandObjectWatchpointModify(CommandInterpreter & interpreter)658435933ddSDimitry Andric   CommandObjectWatchpointModify(CommandInterpreter &interpreter)
659435933ddSDimitry Andric       : CommandObjectParsed(
660435933ddSDimitry Andric             interpreter, "watchpoint modify",
661435933ddSDimitry Andric             "Modify the options on a watchpoint or set of watchpoints in the "
662435933ddSDimitry Andric             "executable.  "
663435933ddSDimitry Andric             "If no watchpoint is specified, act on the last created "
664435933ddSDimitry Andric             "watchpoint.  "
665ac7ddfbfSEd Maste             "Passing an empty argument clears the modification.",
6664bb0738eSEd Maste             nullptr),
667435933ddSDimitry Andric         m_options() {
668ac7ddfbfSEd Maste     CommandArgumentEntry arg;
669435933ddSDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
670435933ddSDimitry Andric                                       eArgTypeWatchpointIDRange);
671435933ddSDimitry Andric     // Add the entry for the first argument for this command to the object's
672435933ddSDimitry Andric     // arguments vector.
673ac7ddfbfSEd Maste     m_arguments.push_back(arg);
674ac7ddfbfSEd Maste   }
675ac7ddfbfSEd Maste 
6764bb0738eSEd Maste   ~CommandObjectWatchpointModify() override = default;
677ac7ddfbfSEd Maste 
GetOptions()678435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
679ac7ddfbfSEd Maste 
680435933ddSDimitry Andric   class CommandOptions : public Options {
681ac7ddfbfSEd Maste   public:
CommandOptions()682435933ddSDimitry Andric     CommandOptions() : Options(), m_condition(), m_condition_passed(false) {}
683ac7ddfbfSEd Maste 
6844bb0738eSEd Maste     ~CommandOptions() override = default;
685ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)6865517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
687435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
6885517e702SDimitry Andric       Status error;
689ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
690ac7ddfbfSEd Maste 
691435933ddSDimitry Andric       switch (short_option) {
692ac7ddfbfSEd Maste       case 'c':
693435933ddSDimitry Andric         m_condition = option_arg;
694ac7ddfbfSEd Maste         m_condition_passed = true;
695ac7ddfbfSEd Maste         break;
696ac7ddfbfSEd Maste       default:
697435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
698435933ddSDimitry Andric                                        short_option);
699ac7ddfbfSEd Maste         break;
700ac7ddfbfSEd Maste       }
701ac7ddfbfSEd Maste 
702ac7ddfbfSEd Maste       return error;
703ac7ddfbfSEd Maste     }
704ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)705435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
706ac7ddfbfSEd Maste       m_condition.clear();
707ac7ddfbfSEd Maste       m_condition_passed = false;
708ac7ddfbfSEd Maste     }
709ac7ddfbfSEd Maste 
GetDefinitions()710435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
711435933ddSDimitry Andric       return llvm::makeArrayRef(g_watchpoint_modify_options);
712ac7ddfbfSEd Maste     }
713ac7ddfbfSEd Maste 
714ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
715ac7ddfbfSEd Maste 
716ac7ddfbfSEd Maste     std::string m_condition;
717ac7ddfbfSEd Maste     bool m_condition_passed;
718ac7ddfbfSEd Maste   };
719ac7ddfbfSEd Maste 
720ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)721435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
722ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
723ac7ddfbfSEd Maste     if (!CheckTargetForWatchpointOperations(target, result))
724ac7ddfbfSEd Maste       return false;
725ac7ddfbfSEd Maste 
7264bb0738eSEd Maste     std::unique_lock<std::recursive_mutex> lock;
7274bb0738eSEd Maste     target->GetWatchpointList().GetListMutex(lock);
728ac7ddfbfSEd Maste 
729ac7ddfbfSEd Maste     const WatchpointList &watchpoints = target->GetWatchpointList();
730ac7ddfbfSEd Maste 
731ac7ddfbfSEd Maste     size_t num_watchpoints = watchpoints.GetSize();
732ac7ddfbfSEd Maste 
733435933ddSDimitry Andric     if (num_watchpoints == 0) {
734ac7ddfbfSEd Maste       result.AppendError("No watchpoints exist to be modified.");
735ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
736ac7ddfbfSEd Maste       return false;
737ac7ddfbfSEd Maste     }
738ac7ddfbfSEd Maste 
739435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
740ac7ddfbfSEd Maste       WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
741ac7ddfbfSEd Maste       wp_sp->SetCondition(m_options.m_condition.c_str());
742ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
743435933ddSDimitry Andric     } else {
744ac7ddfbfSEd Maste       // Particular watchpoints selected; set condition on them.
745ac7ddfbfSEd Maste       std::vector<uint32_t> wp_ids;
746435933ddSDimitry Andric       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
747435933ddSDimitry Andric               target, command, wp_ids)) {
748ac7ddfbfSEd Maste         result.AppendError("Invalid watchpoints specification.");
749ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
750ac7ddfbfSEd Maste         return false;
751ac7ddfbfSEd Maste       }
752ac7ddfbfSEd Maste 
753ac7ddfbfSEd Maste       int count = 0;
754ac7ddfbfSEd Maste       const size_t size = wp_ids.size();
755435933ddSDimitry Andric       for (size_t i = 0; i < size; ++i) {
756ac7ddfbfSEd Maste         WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
757435933ddSDimitry Andric         if (wp_sp) {
758ac7ddfbfSEd Maste           wp_sp->SetCondition(m_options.m_condition.c_str());
759ac7ddfbfSEd Maste           ++count;
760ac7ddfbfSEd Maste         }
761ac7ddfbfSEd Maste       }
762ac7ddfbfSEd Maste       result.AppendMessageWithFormat("%d watchpoints modified.\n", count);
763ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
764ac7ddfbfSEd Maste     }
765ac7ddfbfSEd Maste 
766ac7ddfbfSEd Maste     return result.Succeeded();
767ac7ddfbfSEd Maste   }
768ac7ddfbfSEd Maste 
769ac7ddfbfSEd Maste private:
770ac7ddfbfSEd Maste   CommandOptions m_options;
771ac7ddfbfSEd Maste };
772ac7ddfbfSEd Maste 
773ac7ddfbfSEd Maste //-------------------------------------------------------------------------
774ac7ddfbfSEd Maste // CommandObjectWatchpointSetVariable
775ac7ddfbfSEd Maste //-------------------------------------------------------------------------
776ac7ddfbfSEd Maste #pragma mark SetVariable
777ac7ddfbfSEd Maste 
778435933ddSDimitry Andric class CommandObjectWatchpointSetVariable : public CommandObjectParsed {
779ac7ddfbfSEd Maste public:
CommandObjectWatchpointSetVariable(CommandInterpreter & interpreter)780435933ddSDimitry Andric   CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter)
781435933ddSDimitry Andric       : CommandObjectParsed(
782435933ddSDimitry Andric             interpreter, "watchpoint set variable",
783ac7ddfbfSEd Maste             "Set a watchpoint on a variable. "
784ac7ddfbfSEd Maste             "Use the '-w' option to specify the type of watchpoint and "
7854bb0738eSEd Maste             "the '-s' option to specify the byte size to watch for. "
786ac7ddfbfSEd Maste             "If no '-w' option is specified, it defaults to write. "
7874bb0738eSEd Maste             "If no '-s' option is specified, it defaults to the variable's "
788ac7ddfbfSEd Maste             "byte size. "
789ac7ddfbfSEd Maste             "Note that there are limited hardware resources for watchpoints. "
790435933ddSDimitry Andric             "If watchpoint setting fails, consider disable/delete existing "
791435933ddSDimitry Andric             "ones "
792ac7ddfbfSEd Maste             "to free up resources.",
7934bb0738eSEd Maste             nullptr,
794435933ddSDimitry Andric             eCommandRequiresFrame | eCommandTryTargetAPILock |
795435933ddSDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
796435933ddSDimitry Andric         m_option_group(), m_option_watchpoint() {
797ac7ddfbfSEd Maste     SetHelpLong(
798b91a7dfcSDimitry Andric         R"(
799b91a7dfcSDimitry Andric Examples:
800b91a7dfcSDimitry Andric 
801b91a7dfcSDimitry Andric (lldb) watchpoint set variable -w read_write my_global_var
802b91a7dfcSDimitry Andric 
803435933ddSDimitry Andric )"
804435933ddSDimitry Andric         "    Watches my_global_var for read/write access, with the region to watch \
805435933ddSDimitry Andric corresponding to the byte size of the data type.");
806ac7ddfbfSEd Maste 
807ac7ddfbfSEd Maste     CommandArgumentEntry arg;
808ac7ddfbfSEd Maste     CommandArgumentData var_name_arg;
809ac7ddfbfSEd Maste 
810ac7ddfbfSEd Maste     // Define the only variant of this arg.
811ac7ddfbfSEd Maste     var_name_arg.arg_type = eArgTypeVarName;
812ac7ddfbfSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlain;
813ac7ddfbfSEd Maste 
814ac7ddfbfSEd Maste     // Push the variant into the argument entry.
815ac7ddfbfSEd Maste     arg.push_back(var_name_arg);
816ac7ddfbfSEd Maste 
817ac7ddfbfSEd Maste     // Push the data for the only argument into the m_arguments vector.
818ac7ddfbfSEd Maste     m_arguments.push_back(arg);
819ac7ddfbfSEd Maste 
8204bb0738eSEd Maste     // Absorb the '-w' and '-s' options into our option group.
821435933ddSDimitry Andric     m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
822435933ddSDimitry Andric                           LLDB_OPT_SET_1);
823ac7ddfbfSEd Maste     m_option_group.Finalize();
824ac7ddfbfSEd Maste   }
825ac7ddfbfSEd Maste 
8264bb0738eSEd Maste   ~CommandObjectWatchpointSetVariable() override = default;
827ac7ddfbfSEd Maste 
GetOptions()828435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
829ac7ddfbfSEd Maste 
830ac7ddfbfSEd Maste protected:
GetVariableCallback(void * baton,const char * name,VariableList & variable_list)831435933ddSDimitry Andric   static size_t GetVariableCallback(void *baton, const char *name,
832435933ddSDimitry Andric                                     VariableList &variable_list) {
833ac7ddfbfSEd Maste     Target *target = static_cast<Target *>(baton);
834435933ddSDimitry Andric     if (target) {
8354ba319b5SDimitry Andric       return target->GetImages().FindGlobalVariables(ConstString(name),
836435933ddSDimitry Andric                                                      UINT32_MAX, variable_list);
837ac7ddfbfSEd Maste     }
838ac7ddfbfSEd Maste     return 0;
839ac7ddfbfSEd Maste   }
840ac7ddfbfSEd Maste 
DoExecute(Args & command,CommandReturnObject & result)841435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
842ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
843ac7ddfbfSEd Maste     StackFrame *frame = m_exe_ctx.GetFramePtr();
844ac7ddfbfSEd Maste 
8454ba319b5SDimitry Andric     // If no argument is present, issue an error message.  There's no way to
8464ba319b5SDimitry Andric     // set a watchpoint.
847435933ddSDimitry Andric     if (command.GetArgumentCount() <= 0) {
848435933ddSDimitry Andric       result.GetErrorStream().Printf("error: required argument missing; "
849435933ddSDimitry Andric                                      "specify your program variable to watch "
850435933ddSDimitry Andric                                      "for\n");
851ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
852ac7ddfbfSEd Maste       return false;
853ac7ddfbfSEd Maste     }
854ac7ddfbfSEd Maste 
855ac7ddfbfSEd Maste     // If no '-w' is specified, default to '-w write'.
856435933ddSDimitry Andric     if (!m_option_watchpoint.watch_type_specified) {
857ac7ddfbfSEd Maste       m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
858ac7ddfbfSEd Maste     }
859ac7ddfbfSEd Maste 
8604ba319b5SDimitry Andric     // We passed the sanity check for the command. Proceed to set the
8614ba319b5SDimitry Andric     // watchpoint now.
862ac7ddfbfSEd Maste     lldb::addr_t addr = 0;
863ac7ddfbfSEd Maste     size_t size = 0;
864ac7ddfbfSEd Maste 
865ac7ddfbfSEd Maste     VariableSP var_sp;
866ac7ddfbfSEd Maste     ValueObjectSP valobj_sp;
867ac7ddfbfSEd Maste     Stream &output_stream = result.GetOutputStream();
868ac7ddfbfSEd Maste 
869ac7ddfbfSEd Maste     // A simple watch variable gesture allows only one argument.
870435933ddSDimitry Andric     if (command.GetArgumentCount() != 1) {
871435933ddSDimitry Andric       result.GetErrorStream().Printf(
872435933ddSDimitry Andric           "error: specify exactly one variable to watch for\n");
873ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
874ac7ddfbfSEd Maste       return false;
875ac7ddfbfSEd Maste     }
876ac7ddfbfSEd Maste 
877ac7ddfbfSEd Maste     // Things have checked out ok...
8785517e702SDimitry Andric     Status error;
879435933ddSDimitry Andric     uint32_t expr_path_options =
880435933ddSDimitry Andric         StackFrame::eExpressionPathOptionCheckPtrVsMember |
881ac7ddfbfSEd Maste         StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
882435933ddSDimitry Andric     valobj_sp = frame->GetValueForVariableExpressionPath(
883435933ddSDimitry Andric         command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
884435933ddSDimitry Andric         var_sp, error);
885ac7ddfbfSEd Maste 
886435933ddSDimitry Andric     if (!valobj_sp) {
887ac7ddfbfSEd Maste       // Not in the frame; let's check the globals.
888ac7ddfbfSEd Maste 
889ac7ddfbfSEd Maste       VariableList variable_list;
890ac7ddfbfSEd Maste       ValueObjectList valobj_list;
891ac7ddfbfSEd Maste 
8925517e702SDimitry Andric       Status error(Variable::GetValuesForVariableExpressionPath(
893435933ddSDimitry Andric           command.GetArgumentAtIndex(0),
894435933ddSDimitry Andric           m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target,
895435933ddSDimitry Andric           variable_list, valobj_list));
896ac7ddfbfSEd Maste 
897ac7ddfbfSEd Maste       if (valobj_list.GetSize())
898ac7ddfbfSEd Maste         valobj_sp = valobj_list.GetValueObjectAtIndex(0);
899ac7ddfbfSEd Maste     }
900ac7ddfbfSEd Maste 
9019f2f44ceSEd Maste     CompilerType compiler_type;
902ac7ddfbfSEd Maste 
903435933ddSDimitry Andric     if (valobj_sp) {
904ac7ddfbfSEd Maste       AddressType addr_type;
905ac7ddfbfSEd Maste       addr = valobj_sp->GetAddressOf(false, &addr_type);
906435933ddSDimitry Andric       if (addr_type == eAddressTypeLoad) {
907ac7ddfbfSEd Maste         // We're in business.
908ac7ddfbfSEd Maste         // Find out the size of this variable.
909435933ddSDimitry Andric         size = m_option_watchpoint.watch_size == 0
910435933ddSDimitry Andric                    ? valobj_sp->GetByteSize()
911ac7ddfbfSEd Maste                    : m_option_watchpoint.watch_size;
912ac7ddfbfSEd Maste       }
9139f2f44ceSEd Maste       compiler_type = valobj_sp->GetCompilerType();
914435933ddSDimitry Andric     } else {
9154bb0738eSEd Maste       const char *error_cstr = error.AsCString(nullptr);
916ac7ddfbfSEd Maste       if (error_cstr)
917ac7ddfbfSEd Maste         result.GetErrorStream().Printf("error: %s\n", error_cstr);
918ac7ddfbfSEd Maste       else
919435933ddSDimitry Andric         result.GetErrorStream().Printf("error: unable to find any variable "
920435933ddSDimitry Andric                                        "expression path that matches '%s'\n",
921ac7ddfbfSEd Maste                                        command.GetArgumentAtIndex(0));
922ac7ddfbfSEd Maste       return false;
923ac7ddfbfSEd Maste     }
924ac7ddfbfSEd Maste 
925ac7ddfbfSEd Maste     // Now it's time to create the watchpoint.
926ac7ddfbfSEd Maste     uint32_t watch_type = m_option_watchpoint.watch_type;
927ac7ddfbfSEd Maste 
928ac7ddfbfSEd Maste     error.Clear();
929435933ddSDimitry Andric     Watchpoint *wp =
930435933ddSDimitry Andric         target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
931435933ddSDimitry Andric             .get();
932435933ddSDimitry Andric     if (wp) {
933ac7ddfbfSEd Maste       wp->SetWatchSpec(command.GetArgumentAtIndex(0));
934ac7ddfbfSEd Maste       wp->SetWatchVariable(true);
935435933ddSDimitry Andric       if (var_sp && var_sp->GetDeclaration().GetFile()) {
936ac7ddfbfSEd Maste         StreamString ss;
937ac7ddfbfSEd Maste         // True to show fullpath for declaration file.
938ac7ddfbfSEd Maste         var_sp->GetDeclaration().DumpStopContext(&ss, true);
939ac7ddfbfSEd Maste         wp->SetDeclInfo(ss.GetString());
940ac7ddfbfSEd Maste       }
941ac7ddfbfSEd Maste       output_stream.Printf("Watchpoint created: ");
942ac7ddfbfSEd Maste       wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
943ac7ddfbfSEd Maste       output_stream.EOL();
944ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
945435933ddSDimitry Andric     } else {
946435933ddSDimitry Andric       result.AppendErrorWithFormat(
947435933ddSDimitry Andric           "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64
948435933ddSDimitry Andric           ", variable expression='%s').\n",
9490127ef0fSEd Maste           addr, (uint64_t)size, command.GetArgumentAtIndex(0));
9504bb0738eSEd Maste       if (error.AsCString(nullptr))
951ac7ddfbfSEd Maste         result.AppendError(error.AsCString());
952ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
953ac7ddfbfSEd Maste     }
954ac7ddfbfSEd Maste 
955ac7ddfbfSEd Maste     return result.Succeeded();
956ac7ddfbfSEd Maste   }
957ac7ddfbfSEd Maste 
958ac7ddfbfSEd Maste private:
959ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
960ac7ddfbfSEd Maste   OptionGroupWatchpoint m_option_watchpoint;
961ac7ddfbfSEd Maste };
962ac7ddfbfSEd Maste 
963ac7ddfbfSEd Maste //-------------------------------------------------------------------------
964ac7ddfbfSEd Maste // CommandObjectWatchpointSetExpression
965ac7ddfbfSEd Maste //-------------------------------------------------------------------------
966ac7ddfbfSEd Maste #pragma mark Set
967ac7ddfbfSEd Maste 
968435933ddSDimitry Andric class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
969ac7ddfbfSEd Maste public:
CommandObjectWatchpointSetExpression(CommandInterpreter & interpreter)970435933ddSDimitry Andric   CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter)
971435933ddSDimitry Andric       : CommandObjectRaw(
972435933ddSDimitry Andric             interpreter, "watchpoint set expression",
973ac7ddfbfSEd Maste             "Set a watchpoint on an address by supplying an expression. "
974ac7ddfbfSEd Maste             "Use the '-w' option to specify the type of watchpoint and "
9754bb0738eSEd Maste             "the '-s' option to specify the byte size to watch for. "
976ac7ddfbfSEd Maste             "If no '-w' option is specified, it defaults to write. "
9774bb0738eSEd Maste             "If no '-s' option is specified, it defaults to the target's "
978ac7ddfbfSEd Maste             "pointer byte size. "
979ac7ddfbfSEd Maste             "Note that there are limited hardware resources for watchpoints. "
980435933ddSDimitry Andric             "If watchpoint setting fails, consider disable/delete existing "
981435933ddSDimitry Andric             "ones "
982ac7ddfbfSEd Maste             "to free up resources.",
983435933ddSDimitry Andric             "",
984435933ddSDimitry Andric             eCommandRequiresFrame | eCommandTryTargetAPILock |
985435933ddSDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
986435933ddSDimitry Andric         m_option_group(), m_option_watchpoint() {
987ac7ddfbfSEd Maste     SetHelpLong(
988b91a7dfcSDimitry Andric         R"(
989b91a7dfcSDimitry Andric Examples:
990b91a7dfcSDimitry Andric 
9914bb0738eSEd Maste (lldb) watchpoint set expression -w write -s 1 -- foo + 32
992b91a7dfcSDimitry Andric 
993435933ddSDimitry Andric     Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
994ac7ddfbfSEd Maste 
995ac7ddfbfSEd Maste     CommandArgumentEntry arg;
996ac7ddfbfSEd Maste     CommandArgumentData expression_arg;
997ac7ddfbfSEd Maste 
998ac7ddfbfSEd Maste     // Define the only variant of this arg.
999ac7ddfbfSEd Maste     expression_arg.arg_type = eArgTypeExpression;
1000ac7ddfbfSEd Maste     expression_arg.arg_repetition = eArgRepeatPlain;
1001ac7ddfbfSEd Maste 
1002ac7ddfbfSEd Maste     // Push the only variant into the argument entry.
1003ac7ddfbfSEd Maste     arg.push_back(expression_arg);
1004ac7ddfbfSEd Maste 
1005ac7ddfbfSEd Maste     // Push the data for the only argument into the m_arguments vector.
1006ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1007ac7ddfbfSEd Maste 
10084bb0738eSEd Maste     // Absorb the '-w' and '-s' options into our option group.
1009435933ddSDimitry Andric     m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
1010435933ddSDimitry Andric                           LLDB_OPT_SET_1);
1011ac7ddfbfSEd Maste     m_option_group.Finalize();
1012ac7ddfbfSEd Maste   }
1013ac7ddfbfSEd Maste 
10144bb0738eSEd Maste   ~CommandObjectWatchpointSetExpression() override = default;
1015ac7ddfbfSEd Maste 
1016435933ddSDimitry Andric   // Overrides base class's behavior where WantsCompletion =
1017435933ddSDimitry Andric   // !WantsRawCommandString.
WantsCompletion()1018435933ddSDimitry Andric   bool WantsCompletion() override { return true; }
1019ac7ddfbfSEd Maste 
GetOptions()1020435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
1021ac7ddfbfSEd Maste 
1022ac7ddfbfSEd Maste protected:
DoExecute(llvm::StringRef raw_command,CommandReturnObject & result)10234ba319b5SDimitry Andric   bool DoExecute(llvm::StringRef raw_command,
1024435933ddSDimitry Andric                  CommandReturnObject &result) override {
1025435933ddSDimitry Andric     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
1026435933ddSDimitry Andric     m_option_group.NotifyOptionParsingStarting(
1027435933ddSDimitry Andric         &exe_ctx); // This is a raw command, so notify the option group
1028ac7ddfbfSEd Maste 
1029ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1030ac7ddfbfSEd Maste     StackFrame *frame = m_exe_ctx.GetFramePtr();
1031ac7ddfbfSEd Maste 
10324ba319b5SDimitry Andric     OptionsWithRaw args(raw_command);
1033ac7ddfbfSEd Maste 
10344ba319b5SDimitry Andric     llvm::StringRef expr = args.GetRawPart();
10354ba319b5SDimitry Andric 
10364ba319b5SDimitry Andric     if (args.HasArgs())
10374ba319b5SDimitry Andric       if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
10384ba319b5SDimitry Andric                                  exe_ctx))
1039ac7ddfbfSEd Maste         return false;
1040ac7ddfbfSEd Maste 
10414ba319b5SDimitry Andric     // If no argument is present, issue an error message.  There's no way to
10424ba319b5SDimitry Andric     // set a watchpoint.
10434ba319b5SDimitry Andric     if (raw_command.trim().empty()) {
1044435933ddSDimitry Andric       result.GetErrorStream().Printf("error: required argument missing; "
1045435933ddSDimitry Andric                                      "specify an expression to evaulate into "
1046435933ddSDimitry Andric                                      "the address to watch for\n");
1047ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1048ac7ddfbfSEd Maste       return false;
1049ac7ddfbfSEd Maste     }
1050ac7ddfbfSEd Maste 
1051ac7ddfbfSEd Maste     // If no '-w' is specified, default to '-w write'.
1052435933ddSDimitry Andric     if (!m_option_watchpoint.watch_type_specified) {
1053ac7ddfbfSEd Maste       m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
1054ac7ddfbfSEd Maste     }
1055ac7ddfbfSEd Maste 
10564ba319b5SDimitry Andric     // We passed the sanity check for the command. Proceed to set the
10574ba319b5SDimitry Andric     // watchpoint now.
1058ac7ddfbfSEd Maste     lldb::addr_t addr = 0;
1059ac7ddfbfSEd Maste     size_t size = 0;
1060ac7ddfbfSEd Maste 
1061ac7ddfbfSEd Maste     ValueObjectSP valobj_sp;
1062ac7ddfbfSEd Maste 
1063ac7ddfbfSEd Maste     // Use expression evaluation to arrive at the address to watch.
1064ac7ddfbfSEd Maste     EvaluateExpressionOptions options;
1065b952cd58SEd Maste     options.SetCoerceToId(false);
1066b952cd58SEd Maste     options.SetUnwindOnError(true);
1067b952cd58SEd Maste     options.SetKeepInMemory(false);
1068b952cd58SEd Maste     options.SetTryAllThreads(true);
1069435933ddSDimitry Andric     options.SetTimeout(llvm::None);
1070ac7ddfbfSEd Maste 
1071435933ddSDimitry Andric     ExpressionResults expr_result =
1072435933ddSDimitry Andric         target->EvaluateExpression(expr, frame, valobj_sp, options);
1073435933ddSDimitry Andric     if (expr_result != eExpressionCompleted) {
1074435933ddSDimitry Andric       result.GetErrorStream().Printf(
1075435933ddSDimitry Andric           "error: expression evaluation of address to watch failed\n");
10764ba319b5SDimitry Andric       result.GetErrorStream() << "expression evaluated: \n" << expr << "\n";
1077ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1078ac7ddfbfSEd Maste       return false;
1079ac7ddfbfSEd Maste     }
1080ac7ddfbfSEd Maste 
1081ac7ddfbfSEd Maste     // Get the address to watch.
1082ac7ddfbfSEd Maste     bool success = false;
1083ac7ddfbfSEd Maste     addr = valobj_sp->GetValueAsUnsigned(0, &success);
1084435933ddSDimitry Andric     if (!success) {
1085435933ddSDimitry Andric       result.GetErrorStream().Printf(
1086435933ddSDimitry Andric           "error: expression did not evaluate to an address\n");
1087ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1088ac7ddfbfSEd Maste       return false;
1089ac7ddfbfSEd Maste     }
1090ac7ddfbfSEd Maste 
1091ac7ddfbfSEd Maste     if (m_option_watchpoint.watch_size != 0)
1092ac7ddfbfSEd Maste       size = m_option_watchpoint.watch_size;
1093ac7ddfbfSEd Maste     else
1094ac7ddfbfSEd Maste       size = target->GetArchitecture().GetAddressByteSize();
1095ac7ddfbfSEd Maste 
1096ac7ddfbfSEd Maste     // Now it's time to create the watchpoint.
1097ac7ddfbfSEd Maste     uint32_t watch_type = m_option_watchpoint.watch_type;
1098ac7ddfbfSEd Maste 
1099435933ddSDimitry Andric     // Fetch the type from the value object, the type of the watched object is
1100435933ddSDimitry Andric     // the pointee type
1101ac7ddfbfSEd Maste     /// of the expression, so convert to that if we  found a valid type.
11029f2f44ceSEd Maste     CompilerType compiler_type(valobj_sp->GetCompilerType());
1103ac7ddfbfSEd Maste 
11045517e702SDimitry Andric     Status error;
1105435933ddSDimitry Andric     Watchpoint *wp =
1106435933ddSDimitry Andric         target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
1107435933ddSDimitry Andric             .get();
1108435933ddSDimitry Andric     if (wp) {
1109ac7ddfbfSEd Maste       Stream &output_stream = result.GetOutputStream();
1110ac7ddfbfSEd Maste       output_stream.Printf("Watchpoint created: ");
1111ac7ddfbfSEd Maste       wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1112ac7ddfbfSEd Maste       output_stream.EOL();
1113ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
1114435933ddSDimitry Andric     } else {
1115435933ddSDimitry Andric       result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1116435933ddSDimitry Andric                                    ", size=%" PRIu64 ").\n",
11170127ef0fSEd Maste                                    addr, (uint64_t)size);
11184bb0738eSEd Maste       if (error.AsCString(nullptr))
1119ac7ddfbfSEd Maste         result.AppendError(error.AsCString());
1120ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1121ac7ddfbfSEd Maste     }
1122ac7ddfbfSEd Maste 
1123ac7ddfbfSEd Maste     return result.Succeeded();
1124ac7ddfbfSEd Maste   }
1125ac7ddfbfSEd Maste 
1126ac7ddfbfSEd Maste private:
1127ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
1128ac7ddfbfSEd Maste   OptionGroupWatchpoint m_option_watchpoint;
1129ac7ddfbfSEd Maste };
1130ac7ddfbfSEd Maste 
1131ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1132ac7ddfbfSEd Maste // CommandObjectWatchpointSet
1133ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1134ac7ddfbfSEd Maste #pragma mark Set
1135ac7ddfbfSEd Maste 
1136435933ddSDimitry Andric class CommandObjectWatchpointSet : public CommandObjectMultiword {
1137ac7ddfbfSEd Maste public:
CommandObjectWatchpointSet(CommandInterpreter & interpreter)11384bb0738eSEd Maste   CommandObjectWatchpointSet(CommandInterpreter &interpreter)
1139435933ddSDimitry Andric       : CommandObjectMultiword(
1140435933ddSDimitry Andric             interpreter, "watchpoint set", "Commands for setting a watchpoint.",
1141435933ddSDimitry Andric             "watchpoint set <subcommand> [<subcommand-options>]") {
1142ac7ddfbfSEd Maste 
1143435933ddSDimitry Andric     LoadSubCommand(
1144435933ddSDimitry Andric         "variable",
1145435933ddSDimitry Andric         CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter)));
1146435933ddSDimitry Andric     LoadSubCommand(
1147435933ddSDimitry Andric         "expression",
1148435933ddSDimitry Andric         CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter)));
1149ac7ddfbfSEd Maste   }
1150ac7ddfbfSEd Maste 
11514bb0738eSEd Maste   ~CommandObjectWatchpointSet() override = default;
1152ac7ddfbfSEd Maste };
1153ac7ddfbfSEd Maste 
1154ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1155ac7ddfbfSEd Maste // CommandObjectMultiwordWatchpoint
1156ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1157ac7ddfbfSEd Maste #pragma mark MultiwordWatchpoint
1158ac7ddfbfSEd Maste 
CommandObjectMultiwordWatchpoint(CommandInterpreter & interpreter)1159435933ddSDimitry Andric CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(
1160435933ddSDimitry Andric     CommandInterpreter &interpreter)
1161435933ddSDimitry Andric     : CommandObjectMultiword(interpreter, "watchpoint",
1162435933ddSDimitry Andric                              "Commands for operating on watchpoints.",
1163435933ddSDimitry Andric                              "watchpoint <subcommand> [<command-options>]") {
1164435933ddSDimitry Andric   CommandObjectSP list_command_object(
1165435933ddSDimitry Andric       new CommandObjectWatchpointList(interpreter));
1166435933ddSDimitry Andric   CommandObjectSP enable_command_object(
1167435933ddSDimitry Andric       new CommandObjectWatchpointEnable(interpreter));
1168435933ddSDimitry Andric   CommandObjectSP disable_command_object(
1169435933ddSDimitry Andric       new CommandObjectWatchpointDisable(interpreter));
1170435933ddSDimitry Andric   CommandObjectSP delete_command_object(
1171435933ddSDimitry Andric       new CommandObjectWatchpointDelete(interpreter));
1172435933ddSDimitry Andric   CommandObjectSP ignore_command_object(
1173435933ddSDimitry Andric       new CommandObjectWatchpointIgnore(interpreter));
1174435933ddSDimitry Andric   CommandObjectSP command_command_object(
1175435933ddSDimitry Andric       new CommandObjectWatchpointCommand(interpreter));
1176435933ddSDimitry Andric   CommandObjectSP modify_command_object(
1177435933ddSDimitry Andric       new CommandObjectWatchpointModify(interpreter));
1178435933ddSDimitry Andric   CommandObjectSP set_command_object(
1179435933ddSDimitry Andric       new CommandObjectWatchpointSet(interpreter));
1180ac7ddfbfSEd Maste 
1181ac7ddfbfSEd Maste   list_command_object->SetCommandName("watchpoint list");
1182ac7ddfbfSEd Maste   enable_command_object->SetCommandName("watchpoint enable");
1183ac7ddfbfSEd Maste   disable_command_object->SetCommandName("watchpoint disable");
1184ac7ddfbfSEd Maste   delete_command_object->SetCommandName("watchpoint delete");
1185ac7ddfbfSEd Maste   ignore_command_object->SetCommandName("watchpoint ignore");
1186ac7ddfbfSEd Maste   command_command_object->SetCommandName("watchpoint command");
1187ac7ddfbfSEd Maste   modify_command_object->SetCommandName("watchpoint modify");
1188ac7ddfbfSEd Maste   set_command_object->SetCommandName("watchpoint set");
1189ac7ddfbfSEd Maste 
1190ac7ddfbfSEd Maste   LoadSubCommand("list", list_command_object);
1191ac7ddfbfSEd Maste   LoadSubCommand("enable", enable_command_object);
1192ac7ddfbfSEd Maste   LoadSubCommand("disable", disable_command_object);
1193ac7ddfbfSEd Maste   LoadSubCommand("delete", delete_command_object);
1194ac7ddfbfSEd Maste   LoadSubCommand("ignore", ignore_command_object);
1195ac7ddfbfSEd Maste   LoadSubCommand("command", command_command_object);
1196ac7ddfbfSEd Maste   LoadSubCommand("modify", modify_command_object);
1197ac7ddfbfSEd Maste   LoadSubCommand("set", set_command_object);
1198ac7ddfbfSEd Maste }
1199ac7ddfbfSEd Maste 
12004bb0738eSEd Maste CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default;
1201