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