]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Commands / CommandObjectWatchpoint.cpp
1 //===-- CommandObjectWatchpoint.cpp -----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "CommandObjectWatchpoint.h"
11 #include "CommandObjectWatchpointCommand.h"
12
13 #include <vector>
14
15 #include "llvm/ADT/StringRef.h"
16
17 #include "lldb/Breakpoint/Watchpoint.h"
18 #include "lldb/Breakpoint/WatchpointList.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Core/ValueObjectVariable.h"
21 #include "lldb/Host/OptionParser.h"
22 #include "lldb/Interpreter/CommandCompletions.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Symbol/Variable.h"
26 #include "lldb/Symbol/VariableList.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Utility/StreamString.h"
30
31 using namespace lldb;
32 using namespace lldb_private;
33
34 static void AddWatchpointDescription(Stream *s, Watchpoint *wp,
35                                      lldb::DescriptionLevel level) {
36   s->IndentMore();
37   wp->GetDescription(s, level);
38   s->IndentLess();
39   s->EOL();
40 }
41
42 static bool CheckTargetForWatchpointOperations(Target *target,
43                                                CommandReturnObject &result) {
44   if (target == nullptr) {
45     result.AppendError("Invalid target.  No existing target or watchpoints.");
46     result.SetStatus(eReturnStatusFailed);
47     return false;
48   }
49   bool process_is_valid =
50       target->GetProcessSP() && target->GetProcessSP()->IsAlive();
51   if (!process_is_valid) {
52     result.AppendError("Thre's no process or it is not alive.");
53     result.SetStatus(eReturnStatusFailed);
54     return false;
55   }
56   // Target passes our checks, return true.
57   return true;
58 }
59
60 // Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
61 static const char *RSA[4] = {"-", "to", "To", "TO"};
62
63 // Return the index to RSA if found; otherwise -1 is returned.
64 static int32_t WithRSAIndex(llvm::StringRef Arg) {
65
66   uint32_t i;
67   for (i = 0; i < 4; ++i)
68     if (Arg.find(RSA[i]) != llvm::StringRef::npos)
69       return i;
70   return -1;
71 }
72
73 // Return true if wp_ids is successfully populated with the watch ids. False
74 // otherwise.
75 bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
76     Target *target, Args &args, std::vector<uint32_t> &wp_ids) {
77   // Pre-condition: args.GetArgumentCount() > 0.
78   if (args.GetArgumentCount() == 0) {
79     if (target == nullptr)
80       return false;
81     WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
82     if (watch_sp) {
83       wp_ids.push_back(watch_sp->GetID());
84       return true;
85     } else
86       return false;
87   }
88
89   llvm::StringRef Minus("-");
90   std::vector<llvm::StringRef> StrRefArgs;
91   llvm::StringRef first;
92   llvm::StringRef second;
93   size_t i;
94   int32_t idx;
95   // Go through the arguments and make a canonical form of arg list containing
96   // only numbers with possible "-" in between.
97   for (auto &entry : args.entries()) {
98     if ((idx = WithRSAIndex(entry.ref)) == -1) {
99       StrRefArgs.push_back(entry.ref);
100       continue;
101     }
102     // The Arg contains the range specifier, split it, then.
103     std::tie(first, second) = entry.ref.split(RSA[idx]);
104     if (!first.empty())
105       StrRefArgs.push_back(first);
106     StrRefArgs.push_back(Minus);
107     if (!second.empty())
108       StrRefArgs.push_back(second);
109   }
110   // Now process the canonical list and fill in the vector of uint32_t's. If
111   // there is any error, return false and the client should ignore wp_ids.
112   uint32_t beg, end, id;
113   size_t size = StrRefArgs.size();
114   bool in_range = false;
115   for (i = 0; i < size; ++i) {
116     llvm::StringRef Arg = StrRefArgs[i];
117     if (in_range) {
118       // Look for the 'end' of the range.  Note StringRef::getAsInteger()
119       // returns true to signify error while parsing.
120       if (Arg.getAsInteger(0, end))
121         return false;
122       // Found a range!  Now append the elements.
123       for (id = beg; id <= end; ++id)
124         wp_ids.push_back(id);
125       in_range = false;
126       continue;
127     }
128     if (i < (size - 1) && StrRefArgs[i + 1] == Minus) {
129       if (Arg.getAsInteger(0, beg))
130         return false;
131       // Turn on the in_range flag, we are looking for end of range next.
132       ++i;
133       in_range = true;
134       continue;
135     }
136     // Otherwise, we have a simple ID.  Just append it.
137     if (Arg.getAsInteger(0, beg))
138       return false;
139     wp_ids.push_back(beg);
140   }
141
142   // It is an error if after the loop, we're still in_range.
143   return !in_range;
144 }
145
146 //-------------------------------------------------------------------------
147 // CommandObjectWatchpointList
148 //-------------------------------------------------------------------------
149
150 //-------------------------------------------------------------------------
151 // CommandObjectWatchpointList::Options
152 //-------------------------------------------------------------------------
153 #pragma mark List::CommandOptions
154
155 static constexpr OptionDefinition g_watchpoint_list_options[] = {
156     // clang-format off
157   { LLDB_OPT_SET_1, false, "brief",   'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." },
158   { LLDB_OPT_SET_2, false, "full",    'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." },
159   { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." }
160     // clang-format on
161 };
162
163 #pragma mark List
164
165 class CommandObjectWatchpointList : public CommandObjectParsed {
166 public:
167   CommandObjectWatchpointList(CommandInterpreter &interpreter)
168       : CommandObjectParsed(
169             interpreter, "watchpoint list",
170             "List all watchpoints at configurable levels of detail.", nullptr),
171         m_options() {
172     CommandArgumentEntry arg;
173     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
174                                       eArgTypeWatchpointIDRange);
175     // Add the entry for the first argument for this command to the object's
176     // arguments vector.
177     m_arguments.push_back(arg);
178   }
179
180   ~CommandObjectWatchpointList() override = default;
181
182   Options *GetOptions() override { return &m_options; }
183
184   class CommandOptions : public Options {
185   public:
186     CommandOptions()
187         : Options(),
188           m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to
189                                                 // brief descriptions
190     {}
191
192     ~CommandOptions() override = default;
193
194     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
195                           ExecutionContext *execution_context) override {
196       Status error;
197       const int short_option = m_getopt_table[option_idx].val;
198
199       switch (short_option) {
200       case 'b':
201         m_level = lldb::eDescriptionLevelBrief;
202         break;
203       case 'f':
204         m_level = lldb::eDescriptionLevelFull;
205         break;
206       case 'v':
207         m_level = lldb::eDescriptionLevelVerbose;
208         break;
209       default:
210         error.SetErrorStringWithFormat("unrecognized option '%c'",
211                                        short_option);
212         break;
213       }
214
215       return error;
216     }
217
218     void OptionParsingStarting(ExecutionContext *execution_context) override {
219       m_level = lldb::eDescriptionLevelFull;
220     }
221
222     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
223       return llvm::makeArrayRef(g_watchpoint_list_options);
224     }
225
226     // Instance variables to hold the values for command options.
227
228     lldb::DescriptionLevel m_level;
229   };
230
231 protected:
232   bool DoExecute(Args &command, CommandReturnObject &result) override {
233     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
234     if (target == nullptr) {
235       result.AppendError("Invalid target. No current target or watchpoints.");
236       result.SetStatus(eReturnStatusSuccessFinishNoResult);
237       return true;
238     }
239
240     if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
241       uint32_t num_supported_hardware_watchpoints;
242       Status error = target->GetProcessSP()->GetWatchpointSupportInfo(
243           num_supported_hardware_watchpoints);
244       if (error.Success())
245         result.AppendMessageWithFormat(
246             "Number of supported hardware watchpoints: %u\n",
247             num_supported_hardware_watchpoints);
248     }
249
250     const WatchpointList &watchpoints = target->GetWatchpointList();
251
252     std::unique_lock<std::recursive_mutex> lock;
253     target->GetWatchpointList().GetListMutex(lock);
254
255     size_t num_watchpoints = watchpoints.GetSize();
256
257     if (num_watchpoints == 0) {
258       result.AppendMessage("No watchpoints currently set.");
259       result.SetStatus(eReturnStatusSuccessFinishNoResult);
260       return true;
261     }
262
263     Stream &output_stream = result.GetOutputStream();
264
265     if (command.GetArgumentCount() == 0) {
266       // No watchpoint selected; show info about all currently set watchpoints.
267       result.AppendMessage("Current watchpoints:");
268       for (size_t i = 0; i < num_watchpoints; ++i) {
269         Watchpoint *wp = watchpoints.GetByIndex(i).get();
270         AddWatchpointDescription(&output_stream, wp, m_options.m_level);
271       }
272       result.SetStatus(eReturnStatusSuccessFinishNoResult);
273     } else {
274       // Particular watchpoints selected; enable them.
275       std::vector<uint32_t> wp_ids;
276       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
277               target, command, wp_ids)) {
278         result.AppendError("Invalid watchpoints specification.");
279         result.SetStatus(eReturnStatusFailed);
280         return false;
281       }
282
283       const size_t size = wp_ids.size();
284       for (size_t i = 0; i < size; ++i) {
285         Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get();
286         if (wp)
287           AddWatchpointDescription(&output_stream, wp, m_options.m_level);
288         result.SetStatus(eReturnStatusSuccessFinishNoResult);
289       }
290     }
291
292     return result.Succeeded();
293   }
294
295 private:
296   CommandOptions m_options;
297 };
298
299 //-------------------------------------------------------------------------
300 // CommandObjectWatchpointEnable
301 //-------------------------------------------------------------------------
302 #pragma mark Enable
303
304 class CommandObjectWatchpointEnable : public CommandObjectParsed {
305 public:
306   CommandObjectWatchpointEnable(CommandInterpreter &interpreter)
307       : CommandObjectParsed(interpreter, "enable",
308                             "Enable the specified disabled watchpoint(s). If "
309                             "no watchpoints are specified, enable all of them.",
310                             nullptr) {
311     CommandArgumentEntry arg;
312     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
313                                       eArgTypeWatchpointIDRange);
314     // Add the entry for the first argument for this command to the object's
315     // arguments vector.
316     m_arguments.push_back(arg);
317   }
318
319   ~CommandObjectWatchpointEnable() override = default;
320
321 protected:
322   bool DoExecute(Args &command, CommandReturnObject &result) override {
323     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
324     if (!CheckTargetForWatchpointOperations(target, result))
325       return false;
326
327     std::unique_lock<std::recursive_mutex> lock;
328     target->GetWatchpointList().GetListMutex(lock);
329
330     const WatchpointList &watchpoints = target->GetWatchpointList();
331
332     size_t num_watchpoints = watchpoints.GetSize();
333
334     if (num_watchpoints == 0) {
335       result.AppendError("No watchpoints exist to be enabled.");
336       result.SetStatus(eReturnStatusFailed);
337       return false;
338     }
339
340     if (command.GetArgumentCount() == 0) {
341       // No watchpoint selected; enable all currently set watchpoints.
342       target->EnableAllWatchpoints();
343       result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
344                                      " watchpoints)\n",
345                                      (uint64_t)num_watchpoints);
346       result.SetStatus(eReturnStatusSuccessFinishNoResult);
347     } else {
348       // Particular watchpoints selected; enable them.
349       std::vector<uint32_t> wp_ids;
350       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
351               target, command, wp_ids)) {
352         result.AppendError("Invalid watchpoints specification.");
353         result.SetStatus(eReturnStatusFailed);
354         return false;
355       }
356
357       int count = 0;
358       const size_t size = wp_ids.size();
359       for (size_t i = 0; i < size; ++i)
360         if (target->EnableWatchpointByID(wp_ids[i]))
361           ++count;
362       result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
363       result.SetStatus(eReturnStatusSuccessFinishNoResult);
364     }
365
366     return result.Succeeded();
367   }
368 };
369
370 //-------------------------------------------------------------------------
371 // CommandObjectWatchpointDisable
372 //-------------------------------------------------------------------------
373 #pragma mark Disable
374
375 class CommandObjectWatchpointDisable : public CommandObjectParsed {
376 public:
377   CommandObjectWatchpointDisable(CommandInterpreter &interpreter)
378       : CommandObjectParsed(interpreter, "watchpoint disable",
379                             "Disable the specified watchpoint(s) without "
380                             "removing it/them.  If no watchpoints are "
381                             "specified, disable them all.",
382                             nullptr) {
383     CommandArgumentEntry arg;
384     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
385                                       eArgTypeWatchpointIDRange);
386     // Add the entry for the first argument for this command to the object's
387     // arguments vector.
388     m_arguments.push_back(arg);
389   }
390
391   ~CommandObjectWatchpointDisable() override = default;
392
393 protected:
394   bool DoExecute(Args &command, CommandReturnObject &result) override {
395     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
396     if (!CheckTargetForWatchpointOperations(target, result))
397       return false;
398
399     std::unique_lock<std::recursive_mutex> lock;
400     target->GetWatchpointList().GetListMutex(lock);
401
402     const WatchpointList &watchpoints = target->GetWatchpointList();
403     size_t num_watchpoints = watchpoints.GetSize();
404
405     if (num_watchpoints == 0) {
406       result.AppendError("No watchpoints exist to be disabled.");
407       result.SetStatus(eReturnStatusFailed);
408       return false;
409     }
410
411     if (command.GetArgumentCount() == 0) {
412       // No watchpoint selected; disable all currently set watchpoints.
413       if (target->DisableAllWatchpoints()) {
414         result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
415                                        " watchpoints)\n",
416                                        (uint64_t)num_watchpoints);
417         result.SetStatus(eReturnStatusSuccessFinishNoResult);
418       } else {
419         result.AppendError("Disable all watchpoints failed\n");
420         result.SetStatus(eReturnStatusFailed);
421       }
422     } else {
423       // Particular watchpoints selected; disable them.
424       std::vector<uint32_t> wp_ids;
425       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
426               target, command, wp_ids)) {
427         result.AppendError("Invalid watchpoints specification.");
428         result.SetStatus(eReturnStatusFailed);
429         return false;
430       }
431
432       int count = 0;
433       const size_t size = wp_ids.size();
434       for (size_t i = 0; i < size; ++i)
435         if (target->DisableWatchpointByID(wp_ids[i]))
436           ++count;
437       result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
438       result.SetStatus(eReturnStatusSuccessFinishNoResult);
439     }
440
441     return result.Succeeded();
442   }
443 };
444
445 //-------------------------------------------------------------------------
446 // CommandObjectWatchpointDelete
447 //-------------------------------------------------------------------------
448 #pragma mark Delete
449
450 class CommandObjectWatchpointDelete : public CommandObjectParsed {
451 public:
452   CommandObjectWatchpointDelete(CommandInterpreter &interpreter)
453       : CommandObjectParsed(interpreter, "watchpoint delete",
454                             "Delete the specified watchpoint(s).  If no "
455                             "watchpoints are specified, delete them all.",
456                             nullptr) {
457     CommandArgumentEntry arg;
458     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
459                                       eArgTypeWatchpointIDRange);
460     // Add the entry for the first argument for this command to the object's
461     // arguments vector.
462     m_arguments.push_back(arg);
463   }
464
465   ~CommandObjectWatchpointDelete() override = default;
466
467 protected:
468   bool DoExecute(Args &command, CommandReturnObject &result) override {
469     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
470     if (!CheckTargetForWatchpointOperations(target, result))
471       return false;
472
473     std::unique_lock<std::recursive_mutex> lock;
474     target->GetWatchpointList().GetListMutex(lock);
475
476     const WatchpointList &watchpoints = target->GetWatchpointList();
477
478     size_t num_watchpoints = watchpoints.GetSize();
479
480     if (num_watchpoints == 0) {
481       result.AppendError("No watchpoints exist to be deleted.");
482       result.SetStatus(eReturnStatusFailed);
483       return false;
484     }
485
486     if (command.GetArgumentCount() == 0) {
487       if (!m_interpreter.Confirm(
488               "About to delete all watchpoints, do you want to do that?",
489               true)) {
490         result.AppendMessage("Operation cancelled...");
491       } else {
492         target->RemoveAllWatchpoints();
493         result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
494                                        " watchpoints)\n",
495                                        (uint64_t)num_watchpoints);
496       }
497       result.SetStatus(eReturnStatusSuccessFinishNoResult);
498     } else {
499       // Particular watchpoints selected; delete them.
500       std::vector<uint32_t> wp_ids;
501       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
502               target, command, wp_ids)) {
503         result.AppendError("Invalid watchpoints specification.");
504         result.SetStatus(eReturnStatusFailed);
505         return false;
506       }
507
508       int count = 0;
509       const size_t size = wp_ids.size();
510       for (size_t i = 0; i < size; ++i)
511         if (target->RemoveWatchpointByID(wp_ids[i]))
512           ++count;
513       result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
514       result.SetStatus(eReturnStatusSuccessFinishNoResult);
515     }
516
517     return result.Succeeded();
518   }
519 };
520
521 //-------------------------------------------------------------------------
522 // CommandObjectWatchpointIgnore
523 //-------------------------------------------------------------------------
524
525 #pragma mark Ignore::CommandOptions
526 static constexpr OptionDefinition g_watchpoint_ignore_options[] = {
527     // clang-format off
528   { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }
529     // clang-format on
530 };
531
532 class CommandObjectWatchpointIgnore : public CommandObjectParsed {
533 public:
534   CommandObjectWatchpointIgnore(CommandInterpreter &interpreter)
535       : CommandObjectParsed(interpreter, "watchpoint ignore",
536                             "Set ignore count on the specified watchpoint(s).  "
537                             "If no watchpoints are specified, set them all.",
538                             nullptr),
539         m_options() {
540     CommandArgumentEntry arg;
541     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
542                                       eArgTypeWatchpointIDRange);
543     // Add the entry for the first argument for this command to the object's
544     // arguments vector.
545     m_arguments.push_back(arg);
546   }
547
548   ~CommandObjectWatchpointIgnore() override = default;
549
550   Options *GetOptions() override { return &m_options; }
551
552   class CommandOptions : public Options {
553   public:
554     CommandOptions() : Options(), m_ignore_count(0) {}
555
556     ~CommandOptions() override = default;
557
558     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
559                           ExecutionContext *execution_context) override {
560       Status error;
561       const int short_option = m_getopt_table[option_idx].val;
562
563       switch (short_option) {
564       case 'i':
565         if (option_arg.getAsInteger(0, m_ignore_count))
566           error.SetErrorStringWithFormat("invalid ignore count '%s'",
567                                          option_arg.str().c_str());
568         break;
569       default:
570         error.SetErrorStringWithFormat("unrecognized option '%c'",
571                                        short_option);
572         break;
573       }
574
575       return error;
576     }
577
578     void OptionParsingStarting(ExecutionContext *execution_context) override {
579       m_ignore_count = 0;
580     }
581
582     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
583       return llvm::makeArrayRef(g_watchpoint_ignore_options);
584     }
585
586     // Instance variables to hold the values for command options.
587
588     uint32_t m_ignore_count;
589   };
590
591 protected:
592   bool DoExecute(Args &command, CommandReturnObject &result) override {
593     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
594     if (!CheckTargetForWatchpointOperations(target, result))
595       return false;
596
597     std::unique_lock<std::recursive_mutex> lock;
598     target->GetWatchpointList().GetListMutex(lock);
599
600     const WatchpointList &watchpoints = target->GetWatchpointList();
601
602     size_t num_watchpoints = watchpoints.GetSize();
603
604     if (num_watchpoints == 0) {
605       result.AppendError("No watchpoints exist to be ignored.");
606       result.SetStatus(eReturnStatusFailed);
607       return false;
608     }
609
610     if (command.GetArgumentCount() == 0) {
611       target->IgnoreAllWatchpoints(m_options.m_ignore_count);
612       result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
613                                      " watchpoints)\n",
614                                      (uint64_t)num_watchpoints);
615       result.SetStatus(eReturnStatusSuccessFinishNoResult);
616     } else {
617       // Particular watchpoints selected; ignore them.
618       std::vector<uint32_t> wp_ids;
619       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
620               target, command, wp_ids)) {
621         result.AppendError("Invalid watchpoints specification.");
622         result.SetStatus(eReturnStatusFailed);
623         return false;
624       }
625
626       int count = 0;
627       const size_t size = wp_ids.size();
628       for (size_t i = 0; i < size; ++i)
629         if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
630           ++count;
631       result.AppendMessageWithFormat("%d watchpoints ignored.\n", count);
632       result.SetStatus(eReturnStatusSuccessFinishNoResult);
633     }
634
635     return result.Succeeded();
636   }
637
638 private:
639   CommandOptions m_options;
640 };
641
642 //-------------------------------------------------------------------------
643 // CommandObjectWatchpointModify
644 //-------------------------------------------------------------------------
645
646 #pragma mark Modify::CommandOptions
647
648 static constexpr OptionDefinition g_watchpoint_modify_options[] = {
649     // clang-format off
650   { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." }
651     // clang-format on
652 };
653
654 #pragma mark Modify
655
656 class CommandObjectWatchpointModify : public CommandObjectParsed {
657 public:
658   CommandObjectWatchpointModify(CommandInterpreter &interpreter)
659       : CommandObjectParsed(
660             interpreter, "watchpoint modify",
661             "Modify the options on a watchpoint or set of watchpoints in the "
662             "executable.  "
663             "If no watchpoint is specified, act on the last created "
664             "watchpoint.  "
665             "Passing an empty argument clears the modification.",
666             nullptr),
667         m_options() {
668     CommandArgumentEntry arg;
669     CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
670                                       eArgTypeWatchpointIDRange);
671     // Add the entry for the first argument for this command to the object's
672     // arguments vector.
673     m_arguments.push_back(arg);
674   }
675
676   ~CommandObjectWatchpointModify() override = default;
677
678   Options *GetOptions() override { return &m_options; }
679
680   class CommandOptions : public Options {
681   public:
682     CommandOptions() : Options(), m_condition(), m_condition_passed(false) {}
683
684     ~CommandOptions() override = default;
685
686     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
687                           ExecutionContext *execution_context) override {
688       Status error;
689       const int short_option = m_getopt_table[option_idx].val;
690
691       switch (short_option) {
692       case 'c':
693         m_condition = option_arg;
694         m_condition_passed = true;
695         break;
696       default:
697         error.SetErrorStringWithFormat("unrecognized option '%c'",
698                                        short_option);
699         break;
700       }
701
702       return error;
703     }
704
705     void OptionParsingStarting(ExecutionContext *execution_context) override {
706       m_condition.clear();
707       m_condition_passed = false;
708     }
709
710     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
711       return llvm::makeArrayRef(g_watchpoint_modify_options);
712     }
713
714     // Instance variables to hold the values for command options.
715
716     std::string m_condition;
717     bool m_condition_passed;
718   };
719
720 protected:
721   bool DoExecute(Args &command, CommandReturnObject &result) override {
722     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
723     if (!CheckTargetForWatchpointOperations(target, result))
724       return false;
725
726     std::unique_lock<std::recursive_mutex> lock;
727     target->GetWatchpointList().GetListMutex(lock);
728
729     const WatchpointList &watchpoints = target->GetWatchpointList();
730
731     size_t num_watchpoints = watchpoints.GetSize();
732
733     if (num_watchpoints == 0) {
734       result.AppendError("No watchpoints exist to be modified.");
735       result.SetStatus(eReturnStatusFailed);
736       return false;
737     }
738
739     if (command.GetArgumentCount() == 0) {
740       WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
741       wp_sp->SetCondition(m_options.m_condition.c_str());
742       result.SetStatus(eReturnStatusSuccessFinishNoResult);
743     } else {
744       // Particular watchpoints selected; set condition on them.
745       std::vector<uint32_t> wp_ids;
746       if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
747               target, command, wp_ids)) {
748         result.AppendError("Invalid watchpoints specification.");
749         result.SetStatus(eReturnStatusFailed);
750         return false;
751       }
752
753       int count = 0;
754       const size_t size = wp_ids.size();
755       for (size_t i = 0; i < size; ++i) {
756         WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
757         if (wp_sp) {
758           wp_sp->SetCondition(m_options.m_condition.c_str());
759           ++count;
760         }
761       }
762       result.AppendMessageWithFormat("%d watchpoints modified.\n", count);
763       result.SetStatus(eReturnStatusSuccessFinishNoResult);
764     }
765
766     return result.Succeeded();
767   }
768
769 private:
770   CommandOptions m_options;
771 };
772
773 //-------------------------------------------------------------------------
774 // CommandObjectWatchpointSetVariable
775 //-------------------------------------------------------------------------
776 #pragma mark SetVariable
777
778 class CommandObjectWatchpointSetVariable : public CommandObjectParsed {
779 public:
780   CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter)
781       : CommandObjectParsed(
782             interpreter, "watchpoint set variable",
783             "Set a watchpoint on a variable. "
784             "Use the '-w' option to specify the type of watchpoint and "
785             "the '-s' option to specify the byte size to watch for. "
786             "If no '-w' option is specified, it defaults to write. "
787             "If no '-s' option is specified, it defaults to the variable's "
788             "byte size. "
789             "Note that there are limited hardware resources for watchpoints. "
790             "If watchpoint setting fails, consider disable/delete existing "
791             "ones "
792             "to free up resources.",
793             nullptr,
794             eCommandRequiresFrame | eCommandTryTargetAPILock |
795                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
796         m_option_group(), m_option_watchpoint() {
797     SetHelpLong(
798         R"(
799 Examples:
800
801 (lldb) watchpoint set variable -w read_write my_global_var
802
803 )"
804         "    Watches my_global_var for read/write access, with the region to watch \
805 corresponding to the byte size of the data type.");
806
807     CommandArgumentEntry arg;
808     CommandArgumentData var_name_arg;
809
810     // Define the only variant of this arg.
811     var_name_arg.arg_type = eArgTypeVarName;
812     var_name_arg.arg_repetition = eArgRepeatPlain;
813
814     // Push the variant into the argument entry.
815     arg.push_back(var_name_arg);
816
817     // Push the data for the only argument into the m_arguments vector.
818     m_arguments.push_back(arg);
819
820     // Absorb the '-w' and '-s' options into our option group.
821     m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
822                           LLDB_OPT_SET_1);
823     m_option_group.Finalize();
824   }
825
826   ~CommandObjectWatchpointSetVariable() override = default;
827
828   Options *GetOptions() override { return &m_option_group; }
829
830 protected:
831   static size_t GetVariableCallback(void *baton, const char *name,
832                                     VariableList &variable_list) {
833     Target *target = static_cast<Target *>(baton);
834     if (target) {
835       return target->GetImages().FindGlobalVariables(ConstString(name),
836                                                      UINT32_MAX, variable_list);
837     }
838     return 0;
839   }
840
841   bool DoExecute(Args &command, CommandReturnObject &result) override {
842     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
843     StackFrame *frame = m_exe_ctx.GetFramePtr();
844
845     // If no argument is present, issue an error message.  There's no way to
846     // set a watchpoint.
847     if (command.GetArgumentCount() <= 0) {
848       result.GetErrorStream().Printf("error: required argument missing; "
849                                      "specify your program variable to watch "
850                                      "for\n");
851       result.SetStatus(eReturnStatusFailed);
852       return false;
853     }
854
855     // If no '-w' is specified, default to '-w write'.
856     if (!m_option_watchpoint.watch_type_specified) {
857       m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
858     }
859
860     // We passed the sanity check for the command. Proceed to set the
861     // watchpoint now.
862     lldb::addr_t addr = 0;
863     size_t size = 0;
864
865     VariableSP var_sp;
866     ValueObjectSP valobj_sp;
867     Stream &output_stream = result.GetOutputStream();
868
869     // A simple watch variable gesture allows only one argument.
870     if (command.GetArgumentCount() != 1) {
871       result.GetErrorStream().Printf(
872           "error: specify exactly one variable to watch for\n");
873       result.SetStatus(eReturnStatusFailed);
874       return false;
875     }
876
877     // Things have checked out ok...
878     Status error;
879     uint32_t expr_path_options =
880         StackFrame::eExpressionPathOptionCheckPtrVsMember |
881         StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
882     valobj_sp = frame->GetValueForVariableExpressionPath(
883         command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
884         var_sp, error);
885
886     if (!valobj_sp) {
887       // Not in the frame; let's check the globals.
888
889       VariableList variable_list;
890       ValueObjectList valobj_list;
891
892       Status error(Variable::GetValuesForVariableExpressionPath(
893           command.GetArgumentAtIndex(0),
894           m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target,
895           variable_list, valobj_list));
896
897       if (valobj_list.GetSize())
898         valobj_sp = valobj_list.GetValueObjectAtIndex(0);
899     }
900
901     CompilerType compiler_type;
902
903     if (valobj_sp) {
904       AddressType addr_type;
905       addr = valobj_sp->GetAddressOf(false, &addr_type);
906       if (addr_type == eAddressTypeLoad) {
907         // We're in business.
908         // Find out the size of this variable.
909         size = m_option_watchpoint.watch_size == 0
910                    ? valobj_sp->GetByteSize()
911                    : m_option_watchpoint.watch_size;
912       }
913       compiler_type = valobj_sp->GetCompilerType();
914     } else {
915       const char *error_cstr = error.AsCString(nullptr);
916       if (error_cstr)
917         result.GetErrorStream().Printf("error: %s\n", error_cstr);
918       else
919         result.GetErrorStream().Printf("error: unable to find any variable "
920                                        "expression path that matches '%s'\n",
921                                        command.GetArgumentAtIndex(0));
922       return false;
923     }
924
925     // Now it's time to create the watchpoint.
926     uint32_t watch_type = m_option_watchpoint.watch_type;
927
928     error.Clear();
929     Watchpoint *wp =
930         target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
931             .get();
932     if (wp) {
933       wp->SetWatchSpec(command.GetArgumentAtIndex(0));
934       wp->SetWatchVariable(true);
935       if (var_sp && var_sp->GetDeclaration().GetFile()) {
936         StreamString ss;
937         // True to show fullpath for declaration file.
938         var_sp->GetDeclaration().DumpStopContext(&ss, true);
939         wp->SetDeclInfo(ss.GetString());
940       }
941       output_stream.Printf("Watchpoint created: ");
942       wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
943       output_stream.EOL();
944       result.SetStatus(eReturnStatusSuccessFinishResult);
945     } else {
946       result.AppendErrorWithFormat(
947           "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64
948           ", variable expression='%s').\n",
949           addr, (uint64_t)size, command.GetArgumentAtIndex(0));
950       if (error.AsCString(nullptr))
951         result.AppendError(error.AsCString());
952       result.SetStatus(eReturnStatusFailed);
953     }
954
955     return result.Succeeded();
956   }
957
958 private:
959   OptionGroupOptions m_option_group;
960   OptionGroupWatchpoint m_option_watchpoint;
961 };
962
963 //-------------------------------------------------------------------------
964 // CommandObjectWatchpointSetExpression
965 //-------------------------------------------------------------------------
966 #pragma mark Set
967
968 class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
969 public:
970   CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter)
971       : CommandObjectRaw(
972             interpreter, "watchpoint set expression",
973             "Set a watchpoint on an address by supplying an expression. "
974             "Use the '-w' option to specify the type of watchpoint and "
975             "the '-s' option to specify the byte size to watch for. "
976             "If no '-w' option is specified, it defaults to write. "
977             "If no '-s' option is specified, it defaults to the target's "
978             "pointer byte size. "
979             "Note that there are limited hardware resources for watchpoints. "
980             "If watchpoint setting fails, consider disable/delete existing "
981             "ones "
982             "to free up resources.",
983             "",
984             eCommandRequiresFrame | eCommandTryTargetAPILock |
985                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
986         m_option_group(), m_option_watchpoint() {
987     SetHelpLong(
988         R"(
989 Examples:
990
991 (lldb) watchpoint set expression -w write -s 1 -- foo + 32
992
993     Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
994
995     CommandArgumentEntry arg;
996     CommandArgumentData expression_arg;
997
998     // Define the only variant of this arg.
999     expression_arg.arg_type = eArgTypeExpression;
1000     expression_arg.arg_repetition = eArgRepeatPlain;
1001
1002     // Push the only variant into the argument entry.
1003     arg.push_back(expression_arg);
1004
1005     // Push the data for the only argument into the m_arguments vector.
1006     m_arguments.push_back(arg);
1007
1008     // Absorb the '-w' and '-s' options into our option group.
1009     m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
1010                           LLDB_OPT_SET_1);
1011     m_option_group.Finalize();
1012   }
1013
1014   ~CommandObjectWatchpointSetExpression() override = default;
1015
1016   // Overrides base class's behavior where WantsCompletion =
1017   // !WantsRawCommandString.
1018   bool WantsCompletion() override { return true; }
1019
1020   Options *GetOptions() override { return &m_option_group; }
1021
1022 protected:
1023   bool DoExecute(llvm::StringRef raw_command,
1024                  CommandReturnObject &result) override {
1025     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
1026     m_option_group.NotifyOptionParsingStarting(
1027         &exe_ctx); // This is a raw command, so notify the option group
1028
1029     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1030     StackFrame *frame = m_exe_ctx.GetFramePtr();
1031
1032     OptionsWithRaw args(raw_command);
1033
1034     llvm::StringRef expr = args.GetRawPart();
1035
1036     if (args.HasArgs())
1037       if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
1038                                  exe_ctx))
1039         return false;
1040
1041     // If no argument is present, issue an error message.  There's no way to
1042     // set a watchpoint.
1043     if (raw_command.trim().empty()) {
1044       result.GetErrorStream().Printf("error: required argument missing; "
1045                                      "specify an expression to evaulate into "
1046                                      "the address to watch for\n");
1047       result.SetStatus(eReturnStatusFailed);
1048       return false;
1049     }
1050
1051     // If no '-w' is specified, default to '-w write'.
1052     if (!m_option_watchpoint.watch_type_specified) {
1053       m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
1054     }
1055
1056     // We passed the sanity check for the command. Proceed to set the
1057     // watchpoint now.
1058     lldb::addr_t addr = 0;
1059     size_t size = 0;
1060
1061     ValueObjectSP valobj_sp;
1062
1063     // Use expression evaluation to arrive at the address to watch.
1064     EvaluateExpressionOptions options;
1065     options.SetCoerceToId(false);
1066     options.SetUnwindOnError(true);
1067     options.SetKeepInMemory(false);
1068     options.SetTryAllThreads(true);
1069     options.SetTimeout(llvm::None);
1070
1071     ExpressionResults expr_result =
1072         target->EvaluateExpression(expr, frame, valobj_sp, options);
1073     if (expr_result != eExpressionCompleted) {
1074       result.GetErrorStream().Printf(
1075           "error: expression evaluation of address to watch failed\n");
1076       result.GetErrorStream() << "expression evaluated: \n" << expr << "\n";
1077       result.SetStatus(eReturnStatusFailed);
1078       return false;
1079     }
1080
1081     // Get the address to watch.
1082     bool success = false;
1083     addr = valobj_sp->GetValueAsUnsigned(0, &success);
1084     if (!success) {
1085       result.GetErrorStream().Printf(
1086           "error: expression did not evaluate to an address\n");
1087       result.SetStatus(eReturnStatusFailed);
1088       return false;
1089     }
1090
1091     if (m_option_watchpoint.watch_size != 0)
1092       size = m_option_watchpoint.watch_size;
1093     else
1094       size = target->GetArchitecture().GetAddressByteSize();
1095
1096     // Now it's time to create the watchpoint.
1097     uint32_t watch_type = m_option_watchpoint.watch_type;
1098
1099     // Fetch the type from the value object, the type of the watched object is
1100     // the pointee type
1101     /// of the expression, so convert to that if we  found a valid type.
1102     CompilerType compiler_type(valobj_sp->GetCompilerType());
1103
1104     Status error;
1105     Watchpoint *wp =
1106         target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
1107             .get();
1108     if (wp) {
1109       Stream &output_stream = result.GetOutputStream();
1110       output_stream.Printf("Watchpoint created: ");
1111       wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1112       output_stream.EOL();
1113       result.SetStatus(eReturnStatusSuccessFinishResult);
1114     } else {
1115       result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1116                                    ", size=%" PRIu64 ").\n",
1117                                    addr, (uint64_t)size);
1118       if (error.AsCString(nullptr))
1119         result.AppendError(error.AsCString());
1120       result.SetStatus(eReturnStatusFailed);
1121     }
1122
1123     return result.Succeeded();
1124   }
1125
1126 private:
1127   OptionGroupOptions m_option_group;
1128   OptionGroupWatchpoint m_option_watchpoint;
1129 };
1130
1131 //-------------------------------------------------------------------------
1132 // CommandObjectWatchpointSet
1133 //-------------------------------------------------------------------------
1134 #pragma mark Set
1135
1136 class CommandObjectWatchpointSet : public CommandObjectMultiword {
1137 public:
1138   CommandObjectWatchpointSet(CommandInterpreter &interpreter)
1139       : CommandObjectMultiword(
1140             interpreter, "watchpoint set", "Commands for setting a watchpoint.",
1141             "watchpoint set <subcommand> [<subcommand-options>]") {
1142
1143     LoadSubCommand(
1144         "variable",
1145         CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter)));
1146     LoadSubCommand(
1147         "expression",
1148         CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter)));
1149   }
1150
1151   ~CommandObjectWatchpointSet() override = default;
1152 };
1153
1154 //-------------------------------------------------------------------------
1155 // CommandObjectMultiwordWatchpoint
1156 //-------------------------------------------------------------------------
1157 #pragma mark MultiwordWatchpoint
1158
1159 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(
1160     CommandInterpreter &interpreter)
1161     : CommandObjectMultiword(interpreter, "watchpoint",
1162                              "Commands for operating on watchpoints.",
1163                              "watchpoint <subcommand> [<command-options>]") {
1164   CommandObjectSP list_command_object(
1165       new CommandObjectWatchpointList(interpreter));
1166   CommandObjectSP enable_command_object(
1167       new CommandObjectWatchpointEnable(interpreter));
1168   CommandObjectSP disable_command_object(
1169       new CommandObjectWatchpointDisable(interpreter));
1170   CommandObjectSP delete_command_object(
1171       new CommandObjectWatchpointDelete(interpreter));
1172   CommandObjectSP ignore_command_object(
1173       new CommandObjectWatchpointIgnore(interpreter));
1174   CommandObjectSP command_command_object(
1175       new CommandObjectWatchpointCommand(interpreter));
1176   CommandObjectSP modify_command_object(
1177       new CommandObjectWatchpointModify(interpreter));
1178   CommandObjectSP set_command_object(
1179       new CommandObjectWatchpointSet(interpreter));
1180
1181   list_command_object->SetCommandName("watchpoint list");
1182   enable_command_object->SetCommandName("watchpoint enable");
1183   disable_command_object->SetCommandName("watchpoint disable");
1184   delete_command_object->SetCommandName("watchpoint delete");
1185   ignore_command_object->SetCommandName("watchpoint ignore");
1186   command_command_object->SetCommandName("watchpoint command");
1187   modify_command_object->SetCommandName("watchpoint modify");
1188   set_command_object->SetCommandName("watchpoint set");
1189
1190   LoadSubCommand("list", list_command_object);
1191   LoadSubCommand("enable", enable_command_object);
1192   LoadSubCommand("disable", disable_command_object);
1193   LoadSubCommand("delete", delete_command_object);
1194   LoadSubCommand("ignore", ignore_command_object);
1195   LoadSubCommand("command", command_command_object);
1196   LoadSubCommand("modify", modify_command_object);
1197   LoadSubCommand("set", set_command_object);
1198 }
1199
1200 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default;