blob: 96ae18b35743f96c54649de626055fbdb6f2e75e [file] [log] [blame]
Johnny Chenf04ee932011-09-22 18:04:58 +00001//===-- 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"
Johnny Chene9a56272012-08-09 23:09:42 +000011#include "CommandObjectWatchpointCommand.h"
Johnny Chenf04ee932011-09-22 18:04:58 +000012
13// C Includes
14// C++ Includes
Eugene Zelenko3f18ea02016-02-24 02:05:55 +000015#include <vector>
16
Johnny Chenf04ee932011-09-22 18:04:58 +000017// Other libraries and framework includes
Eugene Zelenko3f18ea02016-02-24 02:05:55 +000018#include "llvm/ADT/StringRef.h"
19
Johnny Chenf04ee932011-09-22 18:04:58 +000020// Project includes
Johnny Chen01a67862011-10-14 00:42:25 +000021#include "lldb/Breakpoint/Watchpoint.h"
22#include "lldb/Breakpoint/WatchpointList.h"
Johnny Chendedb67a2012-01-30 21:46:17 +000023#include "lldb/Core/ValueObject.h"
24#include "lldb/Core/ValueObjectVariable.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000025#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000026#include "lldb/Interpreter/CommandCompletions.h"
Johnny Chenf04ee932011-09-22 18:04:58 +000027#include "lldb/Interpreter/CommandInterpreter.h"
28#include "lldb/Interpreter/CommandReturnObject.h"
Johnny Chendedb67a2012-01-30 21:46:17 +000029#include "lldb/Symbol/Variable.h"
30#include "lldb/Symbol/VariableList.h"
Zachary Turnera78bd7f2015-03-03 23:11:11 +000031#include "lldb/Target/StackFrame.h"
Johnny Chendedb67a2012-01-30 21:46:17 +000032#include "lldb/Target/Target.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000033#include "lldb/Utility/StreamString.h"
Johnny Chenf04ee932011-09-22 18:04:58 +000034
Johnny Chenf04ee932011-09-22 18:04:58 +000035using namespace lldb;
36using namespace lldb_private;
37
Kate Stoneb9c1b512016-09-06 20:57:50 +000038static void AddWatchpointDescription(Stream *s, Watchpoint *wp,
39 lldb::DescriptionLevel level) {
40 s->IndentMore();
41 wp->GetDescription(s, level);
42 s->IndentLess();
43 s->EOL();
Johnny Chenf04ee932011-09-22 18:04:58 +000044}
45
Kate Stoneb9c1b512016-09-06 20:57:50 +000046static bool CheckTargetForWatchpointOperations(Target *target,
47 CommandReturnObject &result) {
48 if (target == nullptr) {
49 result.AppendError("Invalid target. No existing target or watchpoints.");
50 result.SetStatus(eReturnStatusFailed);
51 return false;
52 }
53 bool process_is_valid =
54 target->GetProcessSP() && target->GetProcessSP()->IsAlive();
55 if (!process_is_valid) {
56 result.AppendError("Thre's no process or it is not alive.");
57 result.SetStatus(eReturnStatusFailed);
58 return false;
59 }
60 // Target passes our checks, return true.
61 return true;
Johnny Chenf04ee932011-09-22 18:04:58 +000062}
63
Johnny Chenf04ee932011-09-22 18:04:58 +000064// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
Kate Stoneb9c1b512016-09-06 20:57:50 +000065static const char *RSA[4] = {"-", "to", "To", "TO"};
Johnny Chenf04ee932011-09-22 18:04:58 +000066
67// Return the index to RSA if found; otherwise -1 is returned.
Zachary Turner97d2c402016-10-05 23:40:23 +000068static int32_t WithRSAIndex(llvm::StringRef Arg) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000069
70 uint32_t i;
71 for (i = 0; i < 4; ++i)
72 if (Arg.find(RSA[i]) != llvm::StringRef::npos)
73 return i;
74 return -1;
Johnny Chenf04ee932011-09-22 18:04:58 +000075}
76
Adrian Prantl05097242018-04-30 16:49:04 +000077// Return true if wp_ids is successfully populated with the watch ids. False
78// otherwise.
Kate Stoneb9c1b512016-09-06 20:57:50 +000079bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
80 Target *target, Args &args, std::vector<uint32_t> &wp_ids) {
81 // Pre-condition: args.GetArgumentCount() > 0.
82 if (args.GetArgumentCount() == 0) {
83 if (target == nullptr)
84 return false;
85 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
86 if (watch_sp) {
87 wp_ids.push_back(watch_sp->GetID());
88 return true;
89 } else
90 return false;
91 }
Johnny Chenf04ee932011-09-22 18:04:58 +000092
Kate Stoneb9c1b512016-09-06 20:57:50 +000093 llvm::StringRef Minus("-");
94 std::vector<llvm::StringRef> StrRefArgs;
Zachary Turner97d2c402016-10-05 23:40:23 +000095 llvm::StringRef first;
96 llvm::StringRef second;
Kate Stoneb9c1b512016-09-06 20:57:50 +000097 size_t i;
98 int32_t idx;
99 // Go through the arguments and make a canonical form of arg list containing
100 // only numbers with possible "-" in between.
Zachary Turner97d2c402016-10-05 23:40:23 +0000101 for (auto &entry : args.entries()) {
102 if ((idx = WithRSAIndex(entry.ref)) == -1) {
103 StrRefArgs.push_back(entry.ref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 continue;
Johnny Chenf04ee932011-09-22 18:04:58 +0000105 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 // The Arg contains the range specifier, split it, then.
Zachary Turner97d2c402016-10-05 23:40:23 +0000107 std::tie(first, second) = entry.ref.split(RSA[idx]);
108 if (!first.empty())
109 StrRefArgs.push_back(first);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 StrRefArgs.push_back(Minus);
Zachary Turner97d2c402016-10-05 23:40:23 +0000111 if (!second.empty())
112 StrRefArgs.push_back(second);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113 }
Adrian Prantl05097242018-04-30 16:49:04 +0000114 // Now process the canonical list and fill in the vector of uint32_t's. If
115 // there is any error, return false and the client should ignore wp_ids.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 uint32_t beg, end, id;
117 size_t size = StrRefArgs.size();
118 bool in_range = false;
119 for (i = 0; i < size; ++i) {
120 llvm::StringRef Arg = StrRefArgs[i];
121 if (in_range) {
122 // Look for the 'end' of the range. Note StringRef::getAsInteger()
123 // returns true to signify error while parsing.
124 if (Arg.getAsInteger(0, end))
Johnny Chenf04ee932011-09-22 18:04:58 +0000125 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 // Found a range! Now append the elements.
127 for (id = beg; id <= end; ++id)
128 wp_ids.push_back(id);
129 in_range = false;
130 continue;
131 }
132 if (i < (size - 1) && StrRefArgs[i + 1] == Minus) {
133 if (Arg.getAsInteger(0, beg))
134 return false;
135 // Turn on the in_range flag, we are looking for end of range next.
136 ++i;
137 in_range = true;
138 continue;
139 }
140 // Otherwise, we have a simple ID. Just append it.
141 if (Arg.getAsInteger(0, beg))
142 return false;
143 wp_ids.push_back(beg);
144 }
145 // It is an error if after the loop, we're still in_range.
146 if (in_range)
147 return false;
Johnny Chenf04ee932011-09-22 18:04:58 +0000148
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 return true; // Success!
Johnny Chenf04ee932011-09-22 18:04:58 +0000150}
151
152//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000153// CommandObjectWatchpointList
154//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000155
156//-------------------------------------------------------------------------
157// CommandObjectWatchpointList::Options
158//-------------------------------------------------------------------------
159#pragma mark List::CommandOptions
160
161static OptionDefinition g_watchpoint_list_options[] = {
162 // clang-format off
163 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." },
164 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." },
165 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." }
166 // clang-format on
167};
168
Jim Ingham5a988412012-06-08 21:56:10 +0000169#pragma mark List
170
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171class CommandObjectWatchpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000172public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173 CommandObjectWatchpointList(CommandInterpreter &interpreter)
174 : CommandObjectParsed(
175 interpreter, "watchpoint list",
176 "List all watchpoints at configurable levels of detail.", nullptr),
177 m_options() {
178 CommandArgumentEntry arg;
179 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
180 eArgTypeWatchpointIDRange);
181 // Add the entry for the first argument for this command to the object's
182 // arguments vector.
183 m_arguments.push_back(arg);
184 }
185
186 ~CommandObjectWatchpointList() override = default;
187
188 Options *GetOptions() override { return &m_options; }
189
190 class CommandOptions : public Options {
191 public:
192 CommandOptions()
193 : Options(),
194 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to
195 // brief descriptions
196 {}
197
198 ~CommandOptions() override = default;
199
Zachary Turner97206d52017-05-12 04:51:55 +0000200 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
201 ExecutionContext *execution_context) override {
202 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203 const int short_option = m_getopt_table[option_idx].val;
204
205 switch (short_option) {
206 case 'b':
207 m_level = lldb::eDescriptionLevelBrief;
208 break;
209 case 'f':
210 m_level = lldb::eDescriptionLevelFull;
211 break;
212 case 'v':
213 m_level = lldb::eDescriptionLevelVerbose;
214 break;
215 default:
216 error.SetErrorStringWithFormat("unrecognized option '%c'",
217 short_option);
218 break;
219 }
220
221 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000222 }
223
Kate Stoneb9c1b512016-09-06 20:57:50 +0000224 void OptionParsingStarting(ExecutionContext *execution_context) override {
225 m_level = lldb::eDescriptionLevelFull;
Jim Ingham5a988412012-06-08 21:56:10 +0000226 }
227
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000228 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000229 return llvm::makeArrayRef(g_watchpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000230 }
Jim Ingham5a988412012-06-08 21:56:10 +0000231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000233
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234 lldb::DescriptionLevel m_level;
235 };
Jim Ingham5a988412012-06-08 21:56:10 +0000236
237protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238 bool DoExecute(Args &command, CommandReturnObject &result) override {
239 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
240 if (target == nullptr) {
241 result.AppendError("Invalid target. No current target or watchpoints.");
242 result.SetStatus(eReturnStatusSuccessFinishNoResult);
243 return true;
Jim Ingham5a988412012-06-08 21:56:10 +0000244 }
245
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246 if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
247 uint32_t num_supported_hardware_watchpoints;
Zachary Turner97206d52017-05-12 04:51:55 +0000248 Status error = target->GetProcessSP()->GetWatchpointSupportInfo(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 num_supported_hardware_watchpoints);
250 if (error.Success())
251 result.AppendMessageWithFormat(
252 "Number of supported hardware watchpoints: %u\n",
253 num_supported_hardware_watchpoints);
254 }
255
256 const WatchpointList &watchpoints = target->GetWatchpointList();
257
258 std::unique_lock<std::recursive_mutex> lock;
259 target->GetWatchpointList().GetListMutex(lock);
260
261 size_t num_watchpoints = watchpoints.GetSize();
262
263 if (num_watchpoints == 0) {
264 result.AppendMessage("No watchpoints currently set.");
265 result.SetStatus(eReturnStatusSuccessFinishNoResult);
266 return true;
267 }
268
269 Stream &output_stream = result.GetOutputStream();
270
271 if (command.GetArgumentCount() == 0) {
272 // No watchpoint selected; show info about all currently set watchpoints.
273 result.AppendMessage("Current watchpoints:");
274 for (size_t i = 0; i < num_watchpoints; ++i) {
275 Watchpoint *wp = watchpoints.GetByIndex(i).get();
276 AddWatchpointDescription(&output_stream, wp, m_options.m_level);
277 }
278 result.SetStatus(eReturnStatusSuccessFinishNoResult);
279 } else {
280 // Particular watchpoints selected; enable them.
281 std::vector<uint32_t> wp_ids;
282 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
283 target, command, wp_ids)) {
284 result.AppendError("Invalid watchpoints specification.");
285 result.SetStatus(eReturnStatusFailed);
286 return false;
287 }
288
289 const size_t size = wp_ids.size();
290 for (size_t i = 0; i < size; ++i) {
291 Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get();
292 if (wp)
293 AddWatchpointDescription(&output_stream, wp, m_options.m_level);
294 result.SetStatus(eReturnStatusSuccessFinishNoResult);
295 }
296 }
297
298 return result.Succeeded();
299 }
300
Jim Ingham5a988412012-06-08 21:56:10 +0000301private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000303};
304
305//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000306// CommandObjectWatchpointEnable
307//-------------------------------------------------------------------------
308#pragma mark Enable
309
Kate Stoneb9c1b512016-09-06 20:57:50 +0000310class CommandObjectWatchpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000311public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312 CommandObjectWatchpointEnable(CommandInterpreter &interpreter)
313 : CommandObjectParsed(interpreter, "enable",
314 "Enable the specified disabled watchpoint(s). If "
315 "no watchpoints are specified, enable all of them.",
316 nullptr) {
317 CommandArgumentEntry arg;
318 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
319 eArgTypeWatchpointIDRange);
320 // Add the entry for the first argument for this command to the object's
321 // arguments vector.
322 m_arguments.push_back(arg);
323 }
Jim Ingham5a988412012-06-08 21:56:10 +0000324
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325 ~CommandObjectWatchpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +0000326
327protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000328 bool DoExecute(Args &command, CommandReturnObject &result) override {
329 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
330 if (!CheckTargetForWatchpointOperations(target, result))
331 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000332
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333 std::unique_lock<std::recursive_mutex> lock;
334 target->GetWatchpointList().GetListMutex(lock);
Jim Ingham5a988412012-06-08 21:56:10 +0000335
Kate Stoneb9c1b512016-09-06 20:57:50 +0000336 const WatchpointList &watchpoints = target->GetWatchpointList();
Jim Ingham5a988412012-06-08 21:56:10 +0000337
Kate Stoneb9c1b512016-09-06 20:57:50 +0000338 size_t num_watchpoints = watchpoints.GetSize();
Jim Ingham5a988412012-06-08 21:56:10 +0000339
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 if (num_watchpoints == 0) {
341 result.AppendError("No watchpoints exist to be enabled.");
342 result.SetStatus(eReturnStatusFailed);
343 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000344 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000345
346 if (command.GetArgumentCount() == 0) {
347 // No watchpoint selected; enable all currently set watchpoints.
348 target->EnableAllWatchpoints();
349 result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
350 " watchpoints)\n",
351 (uint64_t)num_watchpoints);
352 result.SetStatus(eReturnStatusSuccessFinishNoResult);
353 } else {
354 // Particular watchpoints selected; enable them.
355 std::vector<uint32_t> wp_ids;
356 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
357 target, command, wp_ids)) {
358 result.AppendError("Invalid watchpoints specification.");
359 result.SetStatus(eReturnStatusFailed);
360 return false;
361 }
362
363 int count = 0;
364 const size_t size = wp_ids.size();
365 for (size_t i = 0; i < size; ++i)
366 if (target->EnableWatchpointByID(wp_ids[i]))
367 ++count;
368 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
369 result.SetStatus(eReturnStatusSuccessFinishNoResult);
370 }
371
372 return result.Succeeded();
373 }
Jim Ingham5a988412012-06-08 21:56:10 +0000374};
375
376//-------------------------------------------------------------------------
377// CommandObjectWatchpointDisable
378//-------------------------------------------------------------------------
379#pragma mark Disable
380
Kate Stoneb9c1b512016-09-06 20:57:50 +0000381class CommandObjectWatchpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000382public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383 CommandObjectWatchpointDisable(CommandInterpreter &interpreter)
384 : CommandObjectParsed(interpreter, "watchpoint disable",
385 "Disable the specified watchpoint(s) without "
386 "removing it/them. If no watchpoints are "
387 "specified, disable them all.",
388 nullptr) {
389 CommandArgumentEntry arg;
390 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
391 eArgTypeWatchpointIDRange);
392 // Add the entry for the first argument for this command to the object's
393 // arguments vector.
394 m_arguments.push_back(arg);
395 }
Jim Ingham5a988412012-06-08 21:56:10 +0000396
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 ~CommandObjectWatchpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +0000398
399protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400 bool DoExecute(Args &command, CommandReturnObject &result) override {
401 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
402 if (!CheckTargetForWatchpointOperations(target, result))
403 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000404
Kate Stoneb9c1b512016-09-06 20:57:50 +0000405 std::unique_lock<std::recursive_mutex> lock;
406 target->GetWatchpointList().GetListMutex(lock);
Jim Ingham5a988412012-06-08 21:56:10 +0000407
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408 const WatchpointList &watchpoints = target->GetWatchpointList();
409 size_t num_watchpoints = watchpoints.GetSize();
Jim Ingham5a988412012-06-08 21:56:10 +0000410
Kate Stoneb9c1b512016-09-06 20:57:50 +0000411 if (num_watchpoints == 0) {
412 result.AppendError("No watchpoints exist to be disabled.");
413 result.SetStatus(eReturnStatusFailed);
414 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000415 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000416
417 if (command.GetArgumentCount() == 0) {
418 // No watchpoint selected; disable all currently set watchpoints.
419 if (target->DisableAllWatchpoints()) {
420 result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
421 " watchpoints)\n",
422 (uint64_t)num_watchpoints);
423 result.SetStatus(eReturnStatusSuccessFinishNoResult);
424 } else {
425 result.AppendError("Disable all watchpoints failed\n");
426 result.SetStatus(eReturnStatusFailed);
427 }
428 } else {
429 // Particular watchpoints selected; disable them.
430 std::vector<uint32_t> wp_ids;
431 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
432 target, command, wp_ids)) {
433 result.AppendError("Invalid watchpoints specification.");
434 result.SetStatus(eReturnStatusFailed);
435 return false;
436 }
437
438 int count = 0;
439 const size_t size = wp_ids.size();
440 for (size_t i = 0; i < size; ++i)
441 if (target->DisableWatchpointByID(wp_ids[i]))
442 ++count;
443 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
444 result.SetStatus(eReturnStatusSuccessFinishNoResult);
445 }
446
447 return result.Succeeded();
448 }
Jim Ingham5a988412012-06-08 21:56:10 +0000449};
450
451//-------------------------------------------------------------------------
452// CommandObjectWatchpointDelete
453//-------------------------------------------------------------------------
454#pragma mark Delete
455
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456class CommandObjectWatchpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000457public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000458 CommandObjectWatchpointDelete(CommandInterpreter &interpreter)
459 : CommandObjectParsed(interpreter, "watchpoint delete",
460 "Delete the specified watchpoint(s). If no "
461 "watchpoints are specified, delete them all.",
462 nullptr) {
463 CommandArgumentEntry arg;
464 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
465 eArgTypeWatchpointIDRange);
466 // Add the entry for the first argument for this command to the object's
467 // arguments vector.
468 m_arguments.push_back(arg);
469 }
Jim Ingham5a988412012-06-08 21:56:10 +0000470
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471 ~CommandObjectWatchpointDelete() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +0000472
473protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474 bool DoExecute(Args &command, CommandReturnObject &result) override {
475 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
476 if (!CheckTargetForWatchpointOperations(target, result))
477 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000478
Kate Stoneb9c1b512016-09-06 20:57:50 +0000479 std::unique_lock<std::recursive_mutex> lock;
480 target->GetWatchpointList().GetListMutex(lock);
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000481
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482 const WatchpointList &watchpoints = target->GetWatchpointList();
Jim Ingham5a988412012-06-08 21:56:10 +0000483
Kate Stoneb9c1b512016-09-06 20:57:50 +0000484 size_t num_watchpoints = watchpoints.GetSize();
Jim Ingham5a988412012-06-08 21:56:10 +0000485
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486 if (num_watchpoints == 0) {
487 result.AppendError("No watchpoints exist to be deleted.");
488 result.SetStatus(eReturnStatusFailed);
489 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000490 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000491
492 if (command.GetArgumentCount() == 0) {
493 if (!m_interpreter.Confirm(
494 "About to delete all watchpoints, do you want to do that?",
495 true)) {
496 result.AppendMessage("Operation cancelled...");
497 } else {
498 target->RemoveAllWatchpoints();
499 result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
500 " watchpoints)\n",
501 (uint64_t)num_watchpoints);
502 }
503 result.SetStatus(eReturnStatusSuccessFinishNoResult);
504 } else {
505 // Particular watchpoints selected; delete them.
506 std::vector<uint32_t> wp_ids;
507 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
508 target, command, wp_ids)) {
509 result.AppendError("Invalid watchpoints specification.");
510 result.SetStatus(eReturnStatusFailed);
511 return false;
512 }
513
514 int count = 0;
515 const size_t size = wp_ids.size();
516 for (size_t i = 0; i < size; ++i)
517 if (target->RemoveWatchpointByID(wp_ids[i]))
518 ++count;
519 result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
520 result.SetStatus(eReturnStatusSuccessFinishNoResult);
521 }
522
523 return result.Succeeded();
524 }
Jim Ingham5a988412012-06-08 21:56:10 +0000525};
526
527//-------------------------------------------------------------------------
528// CommandObjectWatchpointIgnore
529//-------------------------------------------------------------------------
530
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000531#pragma mark Ignore::CommandOptions
532static OptionDefinition g_watchpoint_ignore_options[] = {
533 // clang-format off
534 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }
535 // clang-format on
536};
537
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538class CommandObjectWatchpointIgnore : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000539public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540 CommandObjectWatchpointIgnore(CommandInterpreter &interpreter)
541 : CommandObjectParsed(interpreter, "watchpoint ignore",
542 "Set ignore count on the specified watchpoint(s). "
543 "If no watchpoints are specified, set them all.",
Eugene Zelenko3f18ea02016-02-24 02:05:55 +0000544 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000545 m_options() {
546 CommandArgumentEntry arg;
547 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
548 eArgTypeWatchpointIDRange);
549 // Add the entry for the first argument for this command to the object's
550 // arguments vector.
551 m_arguments.push_back(arg);
552 }
553
554 ~CommandObjectWatchpointIgnore() override = default;
555
556 Options *GetOptions() override { return &m_options; }
557
558 class CommandOptions : public Options {
559 public:
560 CommandOptions() : Options(), m_ignore_count(0) {}
561
562 ~CommandOptions() override = default;
563
Zachary Turner97206d52017-05-12 04:51:55 +0000564 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
565 ExecutionContext *execution_context) override {
566 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000567 const int short_option = m_getopt_table[option_idx].val;
568
569 switch (short_option) {
570 case 'i':
Zachary Turnerfe114832016-11-12 16:56:47 +0000571 if (option_arg.getAsInteger(0, m_ignore_count))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000572 error.SetErrorStringWithFormat("invalid ignore count '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000573 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000574 break;
575 default:
576 error.SetErrorStringWithFormat("unrecognized option '%c'",
577 short_option);
578 break;
579 }
580
581 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000582 }
583
Kate Stoneb9c1b512016-09-06 20:57:50 +0000584 void OptionParsingStarting(ExecutionContext *execution_context) override {
585 m_ignore_count = 0;
Jim Ingham5a988412012-06-08 21:56:10 +0000586 }
587
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000588 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000589 return llvm::makeArrayRef(g_watchpoint_ignore_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000590 }
Jim Ingham5a988412012-06-08 21:56:10 +0000591
Kate Stoneb9c1b512016-09-06 20:57:50 +0000592 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000593
Kate Stoneb9c1b512016-09-06 20:57:50 +0000594 uint32_t m_ignore_count;
595 };
Jim Ingham5a988412012-06-08 21:56:10 +0000596
597protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000598 bool DoExecute(Args &command, CommandReturnObject &result) override {
599 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
600 if (!CheckTargetForWatchpointOperations(target, result))
601 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000602
Kate Stoneb9c1b512016-09-06 20:57:50 +0000603 std::unique_lock<std::recursive_mutex> lock;
604 target->GetWatchpointList().GetListMutex(lock);
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000605
Kate Stoneb9c1b512016-09-06 20:57:50 +0000606 const WatchpointList &watchpoints = target->GetWatchpointList();
Jim Ingham5a988412012-06-08 21:56:10 +0000607
Kate Stoneb9c1b512016-09-06 20:57:50 +0000608 size_t num_watchpoints = watchpoints.GetSize();
Jim Ingham5a988412012-06-08 21:56:10 +0000609
Kate Stoneb9c1b512016-09-06 20:57:50 +0000610 if (num_watchpoints == 0) {
611 result.AppendError("No watchpoints exist to be ignored.");
612 result.SetStatus(eReturnStatusFailed);
613 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000614 }
615
Kate Stoneb9c1b512016-09-06 20:57:50 +0000616 if (command.GetArgumentCount() == 0) {
617 target->IgnoreAllWatchpoints(m_options.m_ignore_count);
618 result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
619 " watchpoints)\n",
620 (uint64_t)num_watchpoints);
621 result.SetStatus(eReturnStatusSuccessFinishNoResult);
622 } else {
623 // Particular watchpoints selected; ignore them.
624 std::vector<uint32_t> wp_ids;
625 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
626 target, command, wp_ids)) {
627 result.AppendError("Invalid watchpoints specification.");
628 result.SetStatus(eReturnStatusFailed);
629 return false;
630 }
631
632 int count = 0;
633 const size_t size = wp_ids.size();
634 for (size_t i = 0; i < size; ++i)
635 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
636 ++count;
637 result.AppendMessageWithFormat("%d watchpoints ignored.\n", count);
638 result.SetStatus(eReturnStatusSuccessFinishNoResult);
639 }
640
641 return result.Succeeded();
642 }
643
Jim Ingham5a988412012-06-08 21:56:10 +0000644private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000645 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000646};
647
Jim Ingham5a988412012-06-08 21:56:10 +0000648//-------------------------------------------------------------------------
649// CommandObjectWatchpointModify
650//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000651
652#pragma mark Modify::CommandOptions
653
654static OptionDefinition g_watchpoint_modify_options[] = {
655 // clang-format off
656 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." }
657 // clang-format on
658};
659
Jim Ingham5a988412012-06-08 21:56:10 +0000660#pragma mark Modify
661
Kate Stoneb9c1b512016-09-06 20:57:50 +0000662class CommandObjectWatchpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000663public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000664 CommandObjectWatchpointModify(CommandInterpreter &interpreter)
665 : CommandObjectParsed(
666 interpreter, "watchpoint modify",
667 "Modify the options on a watchpoint or set of watchpoints in the "
668 "executable. "
669 "If no watchpoint is specified, act on the last created "
670 "watchpoint. "
671 "Passing an empty argument clears the modification.",
672 nullptr),
673 m_options() {
674 CommandArgumentEntry arg;
675 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
676 eArgTypeWatchpointIDRange);
677 // Add the entry for the first argument for this command to the object's
678 // arguments vector.
679 m_arguments.push_back(arg);
680 }
681
682 ~CommandObjectWatchpointModify() override = default;
683
684 Options *GetOptions() override { return &m_options; }
685
686 class CommandOptions : public Options {
687 public:
688 CommandOptions() : Options(), m_condition(), m_condition_passed(false) {}
689
690 ~CommandOptions() override = default;
691
Zachary Turner97206d52017-05-12 04:51:55 +0000692 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
693 ExecutionContext *execution_context) override {
694 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000695 const int short_option = m_getopt_table[option_idx].val;
696
697 switch (short_option) {
698 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +0000699 m_condition = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000700 m_condition_passed = true;
701 break;
702 default:
703 error.SetErrorStringWithFormat("unrecognized option '%c'",
704 short_option);
705 break;
706 }
707
708 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000709 }
710
Kate Stoneb9c1b512016-09-06 20:57:50 +0000711 void OptionParsingStarting(ExecutionContext *execution_context) override {
712 m_condition.clear();
713 m_condition_passed = false;
Jim Ingham5a988412012-06-08 21:56:10 +0000714 }
715
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000716 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000717 return llvm::makeArrayRef(g_watchpoint_modify_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000718 }
Jim Ingham5a988412012-06-08 21:56:10 +0000719
Kate Stoneb9c1b512016-09-06 20:57:50 +0000720 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000721
Kate Stoneb9c1b512016-09-06 20:57:50 +0000722 std::string m_condition;
723 bool m_condition_passed;
724 };
Jim Ingham5a988412012-06-08 21:56:10 +0000725
726protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000727 bool DoExecute(Args &command, CommandReturnObject &result) override {
728 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
729 if (!CheckTargetForWatchpointOperations(target, result))
730 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000731
Kate Stoneb9c1b512016-09-06 20:57:50 +0000732 std::unique_lock<std::recursive_mutex> lock;
733 target->GetWatchpointList().GetListMutex(lock);
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000734
Kate Stoneb9c1b512016-09-06 20:57:50 +0000735 const WatchpointList &watchpoints = target->GetWatchpointList();
Jim Ingham5a988412012-06-08 21:56:10 +0000736
Kate Stoneb9c1b512016-09-06 20:57:50 +0000737 size_t num_watchpoints = watchpoints.GetSize();
Jim Ingham5a988412012-06-08 21:56:10 +0000738
Kate Stoneb9c1b512016-09-06 20:57:50 +0000739 if (num_watchpoints == 0) {
740 result.AppendError("No watchpoints exist to be modified.");
741 result.SetStatus(eReturnStatusFailed);
742 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000743 }
744
Kate Stoneb9c1b512016-09-06 20:57:50 +0000745 if (command.GetArgumentCount() == 0) {
746 WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
747 wp_sp->SetCondition(m_options.m_condition.c_str());
748 result.SetStatus(eReturnStatusSuccessFinishNoResult);
749 } else {
750 // Particular watchpoints selected; set condition on them.
751 std::vector<uint32_t> wp_ids;
752 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
753 target, command, wp_ids)) {
754 result.AppendError("Invalid watchpoints specification.");
755 result.SetStatus(eReturnStatusFailed);
756 return false;
757 }
758
759 int count = 0;
760 const size_t size = wp_ids.size();
761 for (size_t i = 0; i < size; ++i) {
762 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
763 if (wp_sp) {
764 wp_sp->SetCondition(m_options.m_condition.c_str());
765 ++count;
766 }
767 }
768 result.AppendMessageWithFormat("%d watchpoints modified.\n", count);
769 result.SetStatus(eReturnStatusSuccessFinishNoResult);
770 }
771
772 return result.Succeeded();
773 }
774
Jim Ingham5a988412012-06-08 21:56:10 +0000775private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000776 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000777};
778
Jim Ingham5a988412012-06-08 21:56:10 +0000779//-------------------------------------------------------------------------
780// CommandObjectWatchpointSetVariable
781//-------------------------------------------------------------------------
782#pragma mark SetVariable
783
Kate Stoneb9c1b512016-09-06 20:57:50 +0000784class CommandObjectWatchpointSetVariable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000785public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000786 CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter)
787 : CommandObjectParsed(
788 interpreter, "watchpoint set variable",
789 "Set a watchpoint on a variable. "
790 "Use the '-w' option to specify the type of watchpoint and "
791 "the '-s' option to specify the byte size to watch for. "
792 "If no '-w' option is specified, it defaults to write. "
793 "If no '-s' option is specified, it defaults to the variable's "
794 "byte size. "
795 "Note that there are limited hardware resources for watchpoints. "
796 "If watchpoint setting fails, consider disable/delete existing "
797 "ones "
798 "to free up resources.",
799 nullptr,
800 eCommandRequiresFrame | eCommandTryTargetAPILock |
801 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
802 m_option_group(), m_option_watchpoint() {
803 SetHelpLong(
804 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000805Examples:
806
807(lldb) watchpoint set variable -w read_write my_global_var
808
Kate Stoneb9c1b512016-09-06 20:57:50 +0000809)"
810 " Watches my_global_var for read/write access, with the region to watch \
811corresponding to the byte size of the data type.");
Jim Ingham5a988412012-06-08 21:56:10 +0000812
Kate Stoneb9c1b512016-09-06 20:57:50 +0000813 CommandArgumentEntry arg;
814 CommandArgumentData var_name_arg;
Jim Ingham5a988412012-06-08 21:56:10 +0000815
Kate Stoneb9c1b512016-09-06 20:57:50 +0000816 // Define the only variant of this arg.
817 var_name_arg.arg_type = eArgTypeVarName;
818 var_name_arg.arg_repetition = eArgRepeatPlain;
Jim Ingham5a988412012-06-08 21:56:10 +0000819
Kate Stoneb9c1b512016-09-06 20:57:50 +0000820 // Push the variant into the argument entry.
821 arg.push_back(var_name_arg);
Jim Ingham5a988412012-06-08 21:56:10 +0000822
Kate Stoneb9c1b512016-09-06 20:57:50 +0000823 // Push the data for the only argument into the m_arguments vector.
824 m_arguments.push_back(arg);
Jim Ingham5a988412012-06-08 21:56:10 +0000825
Kate Stoneb9c1b512016-09-06 20:57:50 +0000826 // Absorb the '-w' and '-s' options into our option group.
827 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
828 LLDB_OPT_SET_1);
829 m_option_group.Finalize();
830 }
831
832 ~CommandObjectWatchpointSetVariable() override = default;
833
834 Options *GetOptions() override { return &m_option_group; }
Jim Ingham5a988412012-06-08 21:56:10 +0000835
836protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000837 static size_t GetVariableCallback(void *baton, const char *name,
838 VariableList &variable_list) {
839 Target *target = static_cast<Target *>(baton);
840 if (target) {
Pavel Labath34cda142018-05-31 09:46:26 +0000841 return target->GetImages().FindGlobalVariables(ConstString(name),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000842 UINT32_MAX, variable_list);
Sean Callanan903259f2012-09-14 17:20:18 +0000843 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000844 return 0;
845 }
Jim Ingham5a988412012-06-08 21:56:10 +0000846
Kate Stoneb9c1b512016-09-06 20:57:50 +0000847 bool DoExecute(Args &command, CommandReturnObject &result) override {
848 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
849 StackFrame *frame = m_exe_ctx.GetFramePtr();
Jim Ingham5a988412012-06-08 21:56:10 +0000850
Adrian Prantl05097242018-04-30 16:49:04 +0000851 // If no argument is present, issue an error message. There's no way to
852 // set a watchpoint.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000853 if (command.GetArgumentCount() <= 0) {
854 result.GetErrorStream().Printf("error: required argument missing; "
855 "specify your program variable to watch "
856 "for\n");
857 result.SetStatus(eReturnStatusFailed);
858 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000859 }
860
Kate Stoneb9c1b512016-09-06 20:57:50 +0000861 // If no '-w' is specified, default to '-w write'.
862 if (!m_option_watchpoint.watch_type_specified) {
863 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
864 }
865
Adrian Prantl05097242018-04-30 16:49:04 +0000866 // We passed the sanity check for the command. Proceed to set the
867 // watchpoint now.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000868 lldb::addr_t addr = 0;
869 size_t size = 0;
870
871 VariableSP var_sp;
872 ValueObjectSP valobj_sp;
873 Stream &output_stream = result.GetOutputStream();
874
875 // A simple watch variable gesture allows only one argument.
876 if (command.GetArgumentCount() != 1) {
877 result.GetErrorStream().Printf(
878 "error: specify exactly one variable to watch for\n");
879 result.SetStatus(eReturnStatusFailed);
880 return false;
881 }
882
883 // Things have checked out ok...
Zachary Turner97206d52017-05-12 04:51:55 +0000884 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000885 uint32_t expr_path_options =
886 StackFrame::eExpressionPathOptionCheckPtrVsMember |
887 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
888 valobj_sp = frame->GetValueForVariableExpressionPath(
889 command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
890 var_sp, error);
891
892 if (!valobj_sp) {
893 // Not in the frame; let's check the globals.
894
895 VariableList variable_list;
896 ValueObjectList valobj_list;
897
Zachary Turner97206d52017-05-12 04:51:55 +0000898 Status error(Variable::GetValuesForVariableExpressionPath(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000899 command.GetArgumentAtIndex(0),
900 m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target,
901 variable_list, valobj_list));
902
903 if (valobj_list.GetSize())
904 valobj_sp = valobj_list.GetValueObjectAtIndex(0);
905 }
906
907 CompilerType compiler_type;
908
909 if (valobj_sp) {
910 AddressType addr_type;
911 addr = valobj_sp->GetAddressOf(false, &addr_type);
912 if (addr_type == eAddressTypeLoad) {
913 // We're in business.
914 // Find out the size of this variable.
915 size = m_option_watchpoint.watch_size == 0
916 ? valobj_sp->GetByteSize()
917 : m_option_watchpoint.watch_size;
918 }
919 compiler_type = valobj_sp->GetCompilerType();
920 } else {
921 const char *error_cstr = error.AsCString(nullptr);
922 if (error_cstr)
923 result.GetErrorStream().Printf("error: %s\n", error_cstr);
924 else
925 result.GetErrorStream().Printf("error: unable to find any variable "
926 "expression path that matches '%s'\n",
927 command.GetArgumentAtIndex(0));
928 return false;
929 }
930
931 // Now it's time to create the watchpoint.
932 uint32_t watch_type = m_option_watchpoint.watch_type;
933
934 error.Clear();
935 Watchpoint *wp =
936 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
937 .get();
938 if (wp) {
939 wp->SetWatchSpec(command.GetArgumentAtIndex(0));
940 wp->SetWatchVariable(true);
941 if (var_sp && var_sp->GetDeclaration().GetFile()) {
942 StreamString ss;
943 // True to show fullpath for declaration file.
944 var_sp->GetDeclaration().DumpStopContext(&ss, true);
945 wp->SetDeclInfo(ss.GetString());
946 }
947 output_stream.Printf("Watchpoint created: ");
948 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
949 output_stream.EOL();
950 result.SetStatus(eReturnStatusSuccessFinishResult);
951 } else {
952 result.AppendErrorWithFormat(
953 "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64
954 ", variable expression='%s').\n",
955 addr, (uint64_t)size, command.GetArgumentAtIndex(0));
956 if (error.AsCString(nullptr))
957 result.AppendError(error.AsCString());
958 result.SetStatus(eReturnStatusFailed);
959 }
960
961 return result.Succeeded();
962 }
963
Jim Ingham5a988412012-06-08 21:56:10 +0000964private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000965 OptionGroupOptions m_option_group;
966 OptionGroupWatchpoint m_option_watchpoint;
Jim Ingham5a988412012-06-08 21:56:10 +0000967};
968
969//-------------------------------------------------------------------------
970// CommandObjectWatchpointSetExpression
971//-------------------------------------------------------------------------
972#pragma mark Set
973
Kate Stoneb9c1b512016-09-06 20:57:50 +0000974class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
Jim Ingham5a988412012-06-08 21:56:10 +0000975public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000976 CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter)
977 : CommandObjectRaw(
978 interpreter, "watchpoint set expression",
979 "Set a watchpoint on an address by supplying an expression. "
980 "Use the '-w' option to specify the type of watchpoint and "
981 "the '-s' option to specify the byte size to watch for. "
982 "If no '-w' option is specified, it defaults to write. "
983 "If no '-s' option is specified, it defaults to the target's "
984 "pointer byte size. "
985 "Note that there are limited hardware resources for watchpoints. "
986 "If watchpoint setting fails, consider disable/delete existing "
987 "ones "
988 "to free up resources.",
Zachary Turnera4496982016-10-05 21:14:38 +0000989 "",
Kate Stoneb9c1b512016-09-06 20:57:50 +0000990 eCommandRequiresFrame | eCommandTryTargetAPILock |
991 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
992 m_option_group(), m_option_watchpoint() {
993 SetHelpLong(
994 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000995Examples:
996
Stephane Sezer6944f0e2016-04-05 17:30:31 +0000997(lldb) watchpoint set expression -w write -s 1 -- foo + 32
Kate Stoneea671fb2015-07-14 05:48:36 +0000998
Kate Stoneb9c1b512016-09-06 20:57:50 +0000999 Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
Jim Ingham5a988412012-06-08 21:56:10 +00001000
Kate Stoneb9c1b512016-09-06 20:57:50 +00001001 CommandArgumentEntry arg;
1002 CommandArgumentData expression_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001003
Kate Stoneb9c1b512016-09-06 20:57:50 +00001004 // Define the only variant of this arg.
1005 expression_arg.arg_type = eArgTypeExpression;
1006 expression_arg.arg_repetition = eArgRepeatPlain;
Jim Ingham5a988412012-06-08 21:56:10 +00001007
Kate Stoneb9c1b512016-09-06 20:57:50 +00001008 // Push the only variant into the argument entry.
1009 arg.push_back(expression_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001010
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011 // Push the data for the only argument into the m_arguments vector.
1012 m_arguments.push_back(arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001013
Kate Stoneb9c1b512016-09-06 20:57:50 +00001014 // Absorb the '-w' and '-s' options into our option group.
1015 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
1016 LLDB_OPT_SET_1);
1017 m_option_group.Finalize();
1018 }
Jim Ingham5a988412012-06-08 21:56:10 +00001019
Kate Stoneb9c1b512016-09-06 20:57:50 +00001020 ~CommandObjectWatchpointSetExpression() override = default;
1021
1022 // Overrides base class's behavior where WantsCompletion =
1023 // !WantsRawCommandString.
1024 bool WantsCompletion() override { return true; }
1025
1026 Options *GetOptions() override { return &m_option_group; }
Jim Ingham5a988412012-06-08 21:56:10 +00001027
1028protected:
Raphael Isemann4d51a902018-07-12 22:28:52 +00001029 bool DoExecute(llvm::StringRef raw_command,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001030 CommandReturnObject &result) override {
1031 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
1032 m_option_group.NotifyOptionParsingStarting(
1033 &exe_ctx); // This is a raw command, so notify the option group
Jim Ingham5a988412012-06-08 21:56:10 +00001034
Kate Stoneb9c1b512016-09-06 20:57:50 +00001035 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1036 StackFrame *frame = m_exe_ctx.GetFramePtr();
1037
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001038 OptionsWithRaw args(raw_command);
Jim Ingham5a988412012-06-08 21:56:10 +00001039
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001040 llvm::StringRef expr = args.GetRawPart();
Jim Ingham5a988412012-06-08 21:56:10 +00001041
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001042 if (args.HasArgs())
1043 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
1044 exe_ctx))
1045 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046
Adrian Prantl05097242018-04-30 16:49:04 +00001047 // If no argument is present, issue an error message. There's no way to
1048 // set a watchpoint.
Raphael Isemann4d51a902018-07-12 22:28:52 +00001049 if (raw_command.trim().empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001050 result.GetErrorStream().Printf("error: required argument missing; "
1051 "specify an expression to evaulate into "
1052 "the address to watch for\n");
1053 result.SetStatus(eReturnStatusFailed);
1054 return false;
1055 }
1056
1057 // If no '-w' is specified, default to '-w write'.
1058 if (!m_option_watchpoint.watch_type_specified) {
1059 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
1060 }
1061
Adrian Prantl05097242018-04-30 16:49:04 +00001062 // We passed the sanity check for the command. Proceed to set the
1063 // watchpoint now.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001064 lldb::addr_t addr = 0;
1065 size_t size = 0;
1066
1067 ValueObjectSP valobj_sp;
1068
1069 // Use expression evaluation to arrive at the address to watch.
1070 EvaluateExpressionOptions options;
1071 options.SetCoerceToId(false);
1072 options.SetUnwindOnError(true);
1073 options.SetKeepInMemory(false);
1074 options.SetTryAllThreads(true);
Pavel Labath43d35412016-12-06 11:24:51 +00001075 options.SetTimeout(llvm::None);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001076
1077 ExpressionResults expr_result =
1078 target->EvaluateExpression(expr, frame, valobj_sp, options);
1079 if (expr_result != eExpressionCompleted) {
1080 result.GetErrorStream().Printf(
1081 "error: expression evaluation of address to watch failed\n");
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001082 result.GetErrorStream() << "expression evaluated: \n" << expr << "\n";
Kate Stoneb9c1b512016-09-06 20:57:50 +00001083 result.SetStatus(eReturnStatusFailed);
1084 return false;
1085 }
1086
1087 // Get the address to watch.
1088 bool success = false;
1089 addr = valobj_sp->GetValueAsUnsigned(0, &success);
1090 if (!success) {
1091 result.GetErrorStream().Printf(
1092 "error: expression did not evaluate to an address\n");
1093 result.SetStatus(eReturnStatusFailed);
1094 return false;
1095 }
1096
1097 if (m_option_watchpoint.watch_size != 0)
1098 size = m_option_watchpoint.watch_size;
1099 else
1100 size = target->GetArchitecture().GetAddressByteSize();
1101
1102 // Now it's time to create the watchpoint.
1103 uint32_t watch_type = m_option_watchpoint.watch_type;
1104
1105 // Fetch the type from the value object, the type of the watched object is
1106 // the pointee type
1107 /// of the expression, so convert to that if we found a valid type.
1108 CompilerType compiler_type(valobj_sp->GetCompilerType());
1109
Zachary Turner97206d52017-05-12 04:51:55 +00001110 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001111 Watchpoint *wp =
1112 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
1113 .get();
1114 if (wp) {
1115 Stream &output_stream = result.GetOutputStream();
1116 output_stream.Printf("Watchpoint created: ");
1117 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1118 output_stream.EOL();
1119 result.SetStatus(eReturnStatusSuccessFinishResult);
1120 } else {
1121 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1122 ", size=%" PRIu64 ").\n",
1123 addr, (uint64_t)size);
1124 if (error.AsCString(nullptr))
1125 result.AppendError(error.AsCString());
1126 result.SetStatus(eReturnStatusFailed);
1127 }
1128
1129 return result.Succeeded();
1130 }
1131
Jim Ingham5a988412012-06-08 21:56:10 +00001132private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001133 OptionGroupOptions m_option_group;
1134 OptionGroupWatchpoint m_option_watchpoint;
Jim Ingham5a988412012-06-08 21:56:10 +00001135};
1136
1137//-------------------------------------------------------------------------
1138// CommandObjectWatchpointSet
1139//-------------------------------------------------------------------------
1140#pragma mark Set
1141
Kate Stoneb9c1b512016-09-06 20:57:50 +00001142class CommandObjectWatchpointSet : public CommandObjectMultiword {
Jim Ingham5a988412012-06-08 21:56:10 +00001143public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001144 CommandObjectWatchpointSet(CommandInterpreter &interpreter)
1145 : CommandObjectMultiword(
1146 interpreter, "watchpoint set", "Commands for setting a watchpoint.",
1147 "watchpoint set <subcommand> [<subcommand-options>]") {
Jim Ingham5a988412012-06-08 21:56:10 +00001148
Kate Stoneb9c1b512016-09-06 20:57:50 +00001149 LoadSubCommand(
1150 "variable",
1151 CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter)));
1152 LoadSubCommand(
1153 "expression",
1154 CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter)));
1155 }
1156
1157 ~CommandObjectWatchpointSet() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001158};
1159
1160//-------------------------------------------------------------------------
Johnny Chenf04ee932011-09-22 18:04:58 +00001161// CommandObjectMultiwordWatchpoint
1162//-------------------------------------------------------------------------
1163#pragma mark MultiwordWatchpoint
1164
Kate Stoneb9c1b512016-09-06 20:57:50 +00001165CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(
1166 CommandInterpreter &interpreter)
1167 : CommandObjectMultiword(interpreter, "watchpoint",
1168 "Commands for operating on watchpoints.",
1169 "watchpoint <subcommand> [<command-options>]") {
1170 CommandObjectSP list_command_object(
1171 new CommandObjectWatchpointList(interpreter));
1172 CommandObjectSP enable_command_object(
1173 new CommandObjectWatchpointEnable(interpreter));
1174 CommandObjectSP disable_command_object(
1175 new CommandObjectWatchpointDisable(interpreter));
1176 CommandObjectSP delete_command_object(
1177 new CommandObjectWatchpointDelete(interpreter));
1178 CommandObjectSP ignore_command_object(
1179 new CommandObjectWatchpointIgnore(interpreter));
1180 CommandObjectSP command_command_object(
1181 new CommandObjectWatchpointCommand(interpreter));
1182 CommandObjectSP modify_command_object(
1183 new CommandObjectWatchpointModify(interpreter));
1184 CommandObjectSP set_command_object(
1185 new CommandObjectWatchpointSet(interpreter));
Johnny Chenf04ee932011-09-22 18:04:58 +00001186
Kate Stoneb9c1b512016-09-06 20:57:50 +00001187 list_command_object->SetCommandName("watchpoint list");
1188 enable_command_object->SetCommandName("watchpoint enable");
1189 disable_command_object->SetCommandName("watchpoint disable");
1190 delete_command_object->SetCommandName("watchpoint delete");
1191 ignore_command_object->SetCommandName("watchpoint ignore");
1192 command_command_object->SetCommandName("watchpoint command");
1193 modify_command_object->SetCommandName("watchpoint modify");
1194 set_command_object->SetCommandName("watchpoint set");
Johnny Chenf04ee932011-09-22 18:04:58 +00001195
Kate Stoneb9c1b512016-09-06 20:57:50 +00001196 LoadSubCommand("list", list_command_object);
1197 LoadSubCommand("enable", enable_command_object);
1198 LoadSubCommand("disable", disable_command_object);
1199 LoadSubCommand("delete", delete_command_object);
1200 LoadSubCommand("ignore", ignore_command_object);
1201 LoadSubCommand("command", command_command_object);
1202 LoadSubCommand("modify", modify_command_object);
1203 LoadSubCommand("set", set_command_object);
Johnny Chenf04ee932011-09-22 18:04:58 +00001204}
1205
Eugene Zelenko3f18ea02016-02-24 02:05:55 +00001206CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default;