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