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