blob: 82b3fc34feeeac6b2958a60e689532d5a967b853 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:24 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00009#include "CommandObjectBreakpoint.h"
10#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include "lldb/Breakpoint/Breakpoint.h"
12#include "lldb/Breakpoint/BreakpointIDList.h"
13#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000014#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000015#include "lldb/Interpreter/CommandCompletions.h"
16#include "lldb/Interpreter/CommandInterpreter.h"
17#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000018#include "lldb/Interpreter/OptionArgParser.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000019#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000020#include "lldb/Interpreter/OptionValueString.h"
21#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000022#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000023#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000024#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000025#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000026#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadSpec.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000028#include "lldb/Utility/RegularExpression.h"
29#include "lldb/Utility/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030
Jonas Devlieghere796ac802019-02-11 23:13:08 +000031#include <memory>
32#include <vector>
33
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034using namespace lldb;
35using namespace lldb_private;
36
Kate Stoneb9c1b512016-09-06 20:57:50 +000037static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38 lldb::DescriptionLevel level) {
39 s->IndentMore();
40 bp->GetDescription(s, level, true);
41 s->IndentLess();
42 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
Jim Inghamb842f2e2017-09-14 20:22:49 +000045// Modifiable Breakpoint Options
Jim Inghamb842f2e2017-09-14 20:22:49 +000046#pragma mark Modify::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000047static constexpr OptionDefinition g_breakpoint_modify_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +000048 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000049 { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
50 { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
51 { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
52 { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
53 { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
54 { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
55 { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
56 { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
57 { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
58 { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
59 { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." },
Jim Inghamb842f2e2017-09-14 20:22:49 +000060 // clang-format on
61};
62class lldb_private::BreakpointOptionGroup : public OptionGroup
63{
64public:
65 BreakpointOptionGroup() :
66 OptionGroup(),
67 m_bp_opts(false) {}
68
69 ~BreakpointOptionGroup() override = default;
70
71 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
72 return llvm::makeArrayRef(g_breakpoint_modify_options);
73 }
74
75 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
76 ExecutionContext *execution_context) override {
77 Status error;
78 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
79
80 switch (short_option) {
81 case 'c':
Adrian Prantl05097242018-04-30 16:49:04 +000082 // Normally an empty breakpoint condition marks is as unset. But we need
83 // to say it was passed in.
Jim Inghamb842f2e2017-09-14 20:22:49 +000084 m_bp_opts.SetCondition(option_arg.str().c_str());
85 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
86 break;
87 case 'C':
88 m_commands.push_back(option_arg);
89 break;
90 case 'd':
91 m_bp_opts.SetEnabled(false);
92 break;
93 case 'e':
94 m_bp_opts.SetEnabled(true);
95 break;
96 case 'G': {
97 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +000098 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +000099 if (success) {
100 m_bp_opts.SetAutoContinue(value);
101 } else
102 error.SetErrorStringWithFormat(
103 "invalid boolean value '%s' passed for -G option",
104 option_arg.str().c_str());
105 }
106 break;
107 case 'i':
108 {
109 uint32_t ignore_count;
110 if (option_arg.getAsInteger(0, ignore_count))
111 error.SetErrorStringWithFormat("invalid ignore count '%s'",
112 option_arg.str().c_str());
113 else
114 m_bp_opts.SetIgnoreCount(ignore_count);
115 }
116 break;
117 case 'o': {
118 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000119 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000120 if (success) {
121 m_bp_opts.SetOneShot(value);
122 } else
123 error.SetErrorStringWithFormat(
124 "invalid boolean value '%s' passed for -o option",
125 option_arg.str().c_str());
126 } break;
127 case 't':
128 {
129 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
130 if (option_arg[0] != '\0') {
131 if (option_arg.getAsInteger(0, thread_id))
132 error.SetErrorStringWithFormat("invalid thread id string '%s'",
133 option_arg.str().c_str());
134 }
135 m_bp_opts.SetThreadID(thread_id);
136 }
137 break;
138 case 'T':
139 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
140 break;
141 case 'q':
142 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
143 break;
144 case 'x':
145 {
146 uint32_t thread_index = UINT32_MAX;
147 if (option_arg[0] != '\n') {
148 if (option_arg.getAsInteger(0, thread_index))
149 error.SetErrorStringWithFormat("invalid thread index string '%s'",
150 option_arg.str().c_str());
151 }
152 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
153 }
154 break;
155 default:
156 error.SetErrorStringWithFormat("unrecognized option '%c'",
157 short_option);
158 break;
159 }
160
161 return error;
162 }
163
164 void OptionParsingStarting(ExecutionContext *execution_context) override {
165 m_bp_opts.Clear();
166 m_commands.clear();
167 }
168
169 Status OptionParsingFinished(ExecutionContext *execution_context) override {
170 if (!m_commands.empty())
171 {
172 if (!m_commands.empty())
173 {
174 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
175
176 for (std::string &str : m_commands)
177 cmd_data->user_source.AppendString(str);
178
179 cmd_data->stop_on_error = true;
180 m_bp_opts.SetCommandDataCallback(cmd_data);
181 }
182 }
183 return Status();
184 }
185
186 const BreakpointOptions &GetBreakpointOptions()
187 {
188 return m_bp_opts;
189 }
190
191 std::vector<std::string> m_commands;
192 BreakpointOptions m_bp_opts;
193
194};
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000195static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000196 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000197 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, "
Jim Inghamb842f2e2017-09-14 20:22:49 +0000198 "which prime new targets." },
199 // clang-format on
200};
201
202class BreakpointDummyOptionGroup : public OptionGroup
203{
204public:
205 BreakpointDummyOptionGroup() :
206 OptionGroup() {}
207
208 ~BreakpointDummyOptionGroup() override = default;
209
210 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
211 return llvm::makeArrayRef(g_breakpoint_dummy_options);
212 }
213
214 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
215 ExecutionContext *execution_context) override {
216 Status error;
217 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
218
219 switch (short_option) {
220 case 'D':
221 m_use_dummy = true;
222 break;
223 default:
224 error.SetErrorStringWithFormat("unrecognized option '%c'",
225 short_option);
226 break;
227 }
228
229 return error;
230 }
231
232 void OptionParsingStarting(ExecutionContext *execution_context) override {
233 m_use_dummy = false;
234 }
235
236 bool m_use_dummy;
237
238};
239
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000240// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
241// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
Jim Ingham3815e702018-09-13 21:35:32 +0000242#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000243#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
Jim Ingham3815e702018-09-13 21:35:32 +0000244#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
245#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000246#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
247#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
248
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000249static constexpr OptionDefinition g_breakpoint_set_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000250 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000251 { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000252 "multiple times to specify multiple shared libraries." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000253 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
254 { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000255 "lldb only looks for files that are #included if they use the standard include "
256 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
257 "#included, set target.inline-breakpoint-strategy to \"always\"." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000258 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000259
Adrian Prantl05097242018-04-30 16:49:04 +0000260 // Comment out this option for the moment, as we don't actually use it, but
261 // will in the future. This way users won't see it, but the infrastructure is
262 // left in place.
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000263 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
264 // "Set the breakpoint by source location at this particular column."},
265
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000266 { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000267 "a particular binary, then the address will be converted to a \"file\" "
268 "address, so that the breakpoint will track that binary+offset no matter where "
269 "the binary eventually loads. Alternately, if you also specify the module - "
270 "with the -s option - then the address will be treated as a file address in "
271 "that module, and resolved accordingly. Again, this will allow lldb to track "
272 "that offset on subsequent reloads. The module need not have been loaded at "
273 "the time you specify this breakpoint, and will get resolved when the module "
274 "is loaded." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000275 { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000276 "one breakpoint for multiple names" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000277 { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000278 "functions. Can be repeated multiple times." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000279 { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
Adrian Prantl4e8be2c2018-06-13 16:21:24 +0000280 "namespaces and all arguments, and for Objective-C this means a full function "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000281 "prototype with class and selector. Can be repeated multiple times to make "
282 "one breakpoint for multiple names." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000283 { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000284 "make one breakpoint for multiple Selectors." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000285 { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000286 "make one breakpoint for multiple methods." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000287 { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000288 "the function name(s)." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000289 { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000290 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
291 "symbols." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000292 { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000293 "against the source text in a source file or files specified with the -f "
294 "option. The -f option can be specified more than once. If no source files "
295 "are specified, uses the current \"default source file\". If you want to "
296 "match against all source files, pass the \"--all-files\" option." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000297 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
298 { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
299 { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
300 { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
301 { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000302 "options, on throw but not catch.)" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000303 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
304 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000305
306 // Don't add this option till it actually does something useful...
307 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
308 // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" },
309
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000310 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000311 "(note: currently only implemented for setting breakpoints on identifiers). "
312 "If not set the target.language setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000313 { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000314 "If not set the target.skip-prologue setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000315 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
316 { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000317 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000318 { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000319 "setting is used." },
320 // clang-format on
321};
322
Jim Ingham5a988412012-06-08 21:56:10 +0000323// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000326public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000327 typedef enum BreakpointSetType {
328 eSetTypeInvalid,
329 eSetTypeFileAndLine,
330 eSetTypeAddress,
331 eSetTypeFunctionName,
332 eSetTypeFunctionRegexp,
333 eSetTypeSourceRegexp,
Jim Ingham3815e702018-09-13 21:35:32 +0000334 eSetTypeException,
335 eSetTypeScripted,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000336 } BreakpointSetType;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000337
Kate Stoneb9c1b512016-09-06 20:57:50 +0000338 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
339 : CommandObjectParsed(
340 interpreter, "breakpoint set",
341 "Sets a breakpoint or set of breakpoints in the executable.",
342 "breakpoint set <cmd-options>"),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000343 m_bp_opts(), m_options() {
344 // We're picking up all the normal options, commands and disable.
345 m_all_options.Append(&m_bp_opts,
346 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
347 LLDB_OPT_SET_ALL);
348 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
349 m_all_options.Append(&m_options);
350 m_all_options.Finalize();
351 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000352
353 ~CommandObjectBreakpointSet() override = default;
354
Jim Inghamb842f2e2017-09-14 20:22:49 +0000355 Options *GetOptions() override { return &m_all_options; }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356
Jim Inghamb842f2e2017-09-14 20:22:49 +0000357 class CommandOptions : public OptionGroup {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358 public:
359 CommandOptions()
Jim Inghamb842f2e2017-09-14 20:22:49 +0000360 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000361 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
362 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
364 m_exception_language(eLanguageTypeUnknown),
365 m_language(lldb::eLanguageTypeUnknown),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000366 m_skip_prologue(eLazyBoolCalculate),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
368
369 ~CommandOptions() override = default;
370
Zachary Turner97206d52017-05-12 04:51:55 +0000371 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
372 ExecutionContext *execution_context) override {
373 Status error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000374 const int short_option = g_breakpoint_set_options[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375
376 switch (short_option) {
377 case 'a': {
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000378 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
379 LLDB_INVALID_ADDRESS, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380 } break;
381
382 case 'A':
383 m_all_files = true;
384 break;
385
386 case 'b':
387 m_func_names.push_back(option_arg);
388 m_func_name_type_mask |= eFunctionNameTypeBase;
389 break;
390
Zachary Turnerfe114832016-11-12 16:56:47 +0000391 case 'C':
392 if (option_arg.getAsInteger(0, m_column))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000393 error.SetErrorStringWithFormat("invalid column number: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000394 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000395 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 case 'E': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000398 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000399
400 switch (language) {
401 case eLanguageTypeC89:
402 case eLanguageTypeC:
403 case eLanguageTypeC99:
404 case eLanguageTypeC11:
405 m_exception_language = eLanguageTypeC;
406 break;
407 case eLanguageTypeC_plus_plus:
408 case eLanguageTypeC_plus_plus_03:
409 case eLanguageTypeC_plus_plus_11:
410 case eLanguageTypeC_plus_plus_14:
411 m_exception_language = eLanguageTypeC_plus_plus;
412 break;
413 case eLanguageTypeObjC:
414 m_exception_language = eLanguageTypeObjC;
415 break;
416 case eLanguageTypeObjC_plus_plus:
417 error.SetErrorStringWithFormat(
418 "Set exception breakpoints separately for c++ and objective-c");
419 break;
420 case eLanguageTypeUnknown:
421 error.SetErrorStringWithFormat(
422 "Unknown language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000423 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 break;
425 default:
426 error.SetErrorStringWithFormat(
427 "Unsupported language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000428 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000429 }
430 } break;
431
432 case 'f':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000433 m_filenames.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434 break;
435
436 case 'F':
437 m_func_names.push_back(option_arg);
438 m_func_name_type_mask |= eFunctionNameTypeFull;
439 break;
Jim Inghamf08f5c92017-08-03 18:13:24 +0000440
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441 case 'h': {
442 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000443 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000444 if (!success)
445 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000446 "Invalid boolean value for on-catch option: '%s'",
447 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 } break;
449
450 case 'H':
451 m_hardware = true;
452 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000453
454 case 'k': {
455 if (m_current_key.empty())
456 m_current_key.assign(option_arg);
457 else
458 error.SetErrorStringWithFormat("Key: %s missing value.",
459 m_current_key.c_str());
460
461 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 case 'K': {
463 bool success;
464 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000465 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466 if (value)
467 m_skip_prologue = eLazyBoolYes;
468 else
469 m_skip_prologue = eLazyBoolNo;
470
471 if (!success)
472 error.SetErrorStringWithFormat(
473 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000474 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000475 } break;
476
Zachary Turnerfe114832016-11-12 16:56:47 +0000477 case 'l':
478 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000479 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000480 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482
483 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000484 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485 if (m_language == eLanguageTypeUnknown)
486 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000487 "Unknown language type: '%s' for breakpoint",
488 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000489 break;
490
491 case 'm': {
492 bool success;
493 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000494 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495 if (value)
496 m_move_to_nearest_code = eLazyBoolYes;
497 else
498 m_move_to_nearest_code = eLazyBoolNo;
499
500 if (!success)
501 error.SetErrorStringWithFormat(
502 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000503 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000504 break;
505 }
506
507 case 'M':
508 m_func_names.push_back(option_arg);
509 m_func_name_type_mask |= eFunctionNameTypeMethod;
510 break;
511
512 case 'n':
513 m_func_names.push_back(option_arg);
514 m_func_name_type_mask |= eFunctionNameTypeAuto;
515 break;
516
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000517 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000518 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000520 else
521 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000522 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000524 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525
526 case 'R': {
527 lldb::addr_t tmp_offset_addr;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000528 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
529 option_arg, 0, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530 if (error.Success())
531 m_offset_addr = tmp_offset_addr;
532 } break;
533
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000535 m_exception_extra_args.AppendArgument("-O");
536 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000537 break;
538
539 case 'p':
540 m_source_text_regexp.assign(option_arg);
541 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000542
543 case 'P':
544 m_python_class.assign(option_arg);
545 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547 case 'r':
548 m_func_regexp.assign(option_arg);
549 break;
550
551 case 's':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000552 m_modules.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000553 break;
554
555 case 'S':
556 m_func_names.push_back(option_arg);
557 m_func_name_type_mask |= eFunctionNameTypeSelector;
558 break;
559
Jim Ingham3815e702018-09-13 21:35:32 +0000560 case 'v': {
561 if (!m_current_key.empty()) {
562 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
563 m_current_key.clear();
564 }
565 else
566 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
567 option_arg.str().c_str());
568 } break;
569
Kate Stoneb9c1b512016-09-06 20:57:50 +0000570 case 'w': {
571 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000572 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000573 if (!success)
574 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000575 "Invalid boolean value for on-throw option: '%s'",
576 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000577 } break;
578
Kate Stoneb9c1b512016-09-06 20:57:50 +0000579 case 'X':
580 m_source_regex_func_names.insert(option_arg);
581 break;
582
583 default:
584 error.SetErrorStringWithFormat("unrecognized option '%c'",
585 short_option);
586 break;
587 }
588
589 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000590 }
591
Kate Stoneb9c1b512016-09-06 20:57:50 +0000592 void OptionParsingStarting(ExecutionContext *execution_context) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000593 m_filenames.Clear();
594 m_line_num = 0;
595 m_column = 0;
596 m_func_names.clear();
597 m_func_name_type_mask = eFunctionNameTypeNone;
598 m_func_regexp.clear();
599 m_source_text_regexp.clear();
600 m_modules.Clear();
601 m_load_addr = LLDB_INVALID_ADDRESS;
602 m_offset_addr = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000603 m_catch_bp = false;
604 m_throw_bp = true;
605 m_hardware = false;
606 m_exception_language = eLanguageTypeUnknown;
607 m_language = lldb::eLanguageTypeUnknown;
608 m_skip_prologue = eLazyBoolCalculate;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000609 m_breakpoint_names.clear();
610 m_all_files = false;
611 m_exception_extra_args.Clear();
612 m_move_to_nearest_code = eLazyBoolCalculate;
613 m_source_regex_func_names.clear();
Jim Ingham3815e702018-09-13 21:35:32 +0000614 m_python_class.clear();
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000615 m_extra_args_sp = std::make_shared<StructuredData::Dictionary>();
Jim Ingham3815e702018-09-13 21:35:32 +0000616 m_current_key.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000617 }
618
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000619 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000620 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000621 }
Jim Ingham5a988412012-06-08 21:56:10 +0000622
Kate Stoneb9c1b512016-09-06 20:57:50 +0000623 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000624
Kate Stoneb9c1b512016-09-06 20:57:50 +0000625 std::string m_condition;
626 FileSpecList m_filenames;
627 uint32_t m_line_num;
628 uint32_t m_column;
629 std::vector<std::string> m_func_names;
630 std::vector<std::string> m_breakpoint_names;
Zachary Turner117b1fa2018-10-25 20:45:40 +0000631 lldb::FunctionNameType m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000632 std::string m_func_regexp;
633 std::string m_source_text_regexp;
634 FileSpecList m_modules;
635 lldb::addr_t m_load_addr;
636 lldb::addr_t m_offset_addr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000637 bool m_catch_bp;
638 bool m_throw_bp;
639 bool m_hardware; // Request to use hardware breakpoints
640 lldb::LanguageType m_exception_language;
641 lldb::LanguageType m_language;
642 LazyBool m_skip_prologue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000643 bool m_all_files;
644 Args m_exception_extra_args;
645 LazyBool m_move_to_nearest_code;
646 std::unordered_set<std::string> m_source_regex_func_names;
Jim Ingham3815e702018-09-13 21:35:32 +0000647 std::string m_python_class;
648 StructuredData::DictionarySP m_extra_args_sp;
649 std::string m_current_key;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000650 };
Jim Ingham5a988412012-06-08 21:56:10 +0000651
652protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000653 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000654 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000655
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 if (target == nullptr) {
657 result.AppendError("Invalid target. Must set target before setting "
658 "breakpoints (see 'target create' command).");
659 result.SetStatus(eReturnStatusFailed);
660 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000661 }
662
Kate Stoneb9c1b512016-09-06 20:57:50 +0000663 // The following are the various types of breakpoints that could be set:
664 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
665 // 2). -a [-s -g] (setting breakpoint by address)
666 // 3). -n [-s -g] (setting breakpoint by function name)
667 // 4). -r [-s -g] (setting breakpoint by function name regular
668 // expression)
669 // 5). -p -f (setting a breakpoint by comparing a reg-exp
670 // to source text)
671 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
672 // given language.)
673
674 BreakpointSetType break_type = eSetTypeInvalid;
675
Jim Ingham3815e702018-09-13 21:35:32 +0000676 if (!m_options.m_python_class.empty())
677 break_type = eSetTypeScripted;
678 else if (m_options.m_line_num != 0)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000679 break_type = eSetTypeFileAndLine;
680 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
681 break_type = eSetTypeAddress;
682 else if (!m_options.m_func_names.empty())
683 break_type = eSetTypeFunctionName;
684 else if (!m_options.m_func_regexp.empty())
685 break_type = eSetTypeFunctionRegexp;
686 else if (!m_options.m_source_text_regexp.empty())
687 break_type = eSetTypeSourceRegexp;
688 else if (m_options.m_exception_language != eLanguageTypeUnknown)
689 break_type = eSetTypeException;
690
Jim Inghamb842f2e2017-09-14 20:22:49 +0000691 BreakpointSP bp_sp = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000692 FileSpec module_spec;
693 const bool internal = false;
694
695 // If the user didn't specify skip-prologue, having an offset should turn
696 // that off.
697 if (m_options.m_offset_addr != 0 &&
698 m_options.m_skip_prologue == eLazyBoolCalculate)
699 m_options.m_skip_prologue = eLazyBoolNo;
700
701 switch (break_type) {
702 case eSetTypeFileAndLine: // Breakpoint by source position
703 {
704 FileSpec file;
705 const size_t num_files = m_options.m_filenames.GetSize();
706 if (num_files == 0) {
707 if (!GetDefaultFile(target, file, result)) {
708 result.AppendError("No file supplied and no default file available.");
709 result.SetStatus(eReturnStatusFailed);
710 return false;
711 }
712 } else if (num_files > 1) {
713 result.AppendError("Only one file at a time is allowed for file and "
714 "line breakpoints.");
715 result.SetStatus(eReturnStatusFailed);
716 return false;
717 } else
718 file = m_options.m_filenames.GetFileSpecAtIndex(0);
719
720 // Only check for inline functions if
721 LazyBool check_inlines = eLazyBoolCalculate;
722
Jim Inghamb842f2e2017-09-14 20:22:49 +0000723 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
724 file,
Adrian Prantl431b1582018-08-30 15:11:00 +0000725 m_options.m_line_num,
726 m_options.m_column,
Jim Inghamb842f2e2017-09-14 20:22:49 +0000727 m_options.m_offset_addr,
728 check_inlines,
729 m_options.m_skip_prologue,
730 internal,
731 m_options.m_hardware,
732 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000733 } break;
734
735 case eSetTypeAddress: // Breakpoint by address
736 {
737 // If a shared library has been specified, make an lldb_private::Address
Jim Inghamb842f2e2017-09-14 20:22:49 +0000738 // with the library, and use that. That way the address breakpoint
739 // will track the load location of the library.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000740 size_t num_modules_specified = m_options.m_modules.GetSize();
741 if (num_modules_specified == 1) {
742 const FileSpec *file_spec =
743 m_options.m_modules.GetFileSpecPointerAtIndex(0);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000744 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
745 internal, file_spec,
746 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000747 } else if (num_modules_specified == 0) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000748 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
749 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000750 } else {
751 result.AppendError("Only one shared library can be specified for "
752 "address breakpoints.");
753 result.SetStatus(eReturnStatusFailed);
754 return false;
755 }
756 break;
757 }
758 case eSetTypeFunctionName: // Breakpoint by function name
759 {
Zachary Turner117b1fa2018-10-25 20:45:40 +0000760 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000761
762 if (name_type_mask == 0)
763 name_type_mask = eFunctionNameTypeAuto;
764
Jim Inghamb842f2e2017-09-14 20:22:49 +0000765 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
766 &(m_options.m_filenames),
767 m_options.m_func_names,
768 name_type_mask,
769 m_options.m_language,
770 m_options.m_offset_addr,
771 m_options.m_skip_prologue,
772 internal,
773 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000774 } break;
775
776 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
777 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000778 {
Zachary Turner95eae422016-09-21 16:01:28 +0000779 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000780 if (!regexp.IsValid()) {
781 char err_str[1024];
782 regexp.GetErrorAsCString(err_str, sizeof(err_str));
783 result.AppendErrorWithFormat(
784 "Function name regular expression could not be compiled: \"%s\"",
785 err_str);
786 result.SetStatus(eReturnStatusFailed);
787 return false;
788 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000789
Jim Inghamb842f2e2017-09-14 20:22:49 +0000790 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
791 &(m_options.m_filenames),
792 regexp,
793 m_options.m_language,
794 m_options.m_skip_prologue,
795 internal,
796 m_options.m_hardware);
Jim Inghame14dc262016-09-12 23:10:56 +0000797 }
798 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000799 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
800 {
801 const size_t num_files = m_options.m_filenames.GetSize();
802
803 if (num_files == 0 && !m_options.m_all_files) {
804 FileSpec file;
805 if (!GetDefaultFile(target, file, result)) {
806 result.AppendError(
807 "No files provided and could not find default file.");
808 result.SetStatus(eReturnStatusFailed);
809 return false;
810 } else {
811 m_options.m_filenames.Append(file);
812 }
813 }
814
Zachary Turner95eae422016-09-21 16:01:28 +0000815 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000816 if (!regexp.IsValid()) {
817 char err_str[1024];
818 regexp.GetErrorAsCString(err_str, sizeof(err_str));
819 result.AppendErrorWithFormat(
820 "Source text regular expression could not be compiled: \"%s\"",
821 err_str);
822 result.SetStatus(eReturnStatusFailed);
823 return false;
824 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000825 bp_sp =
826 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
827 &(m_options.m_filenames),
828 m_options
829 .m_source_regex_func_names,
830 regexp,
831 internal,
832 m_options.m_hardware,
833 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000834 } break;
835 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000836 Status precond_error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000837 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
838 m_options.m_catch_bp,
839 m_options.m_throw_bp,
840 internal,
841 &m_options
842 .m_exception_extra_args,
843 &precond_error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000844 if (precond_error.Fail()) {
845 result.AppendErrorWithFormat(
846 "Error setting extra exception arguments: %s",
847 precond_error.AsCString());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000848 target->RemoveBreakpointByID(bp_sp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000849 result.SetStatus(eReturnStatusFailed);
850 return false;
851 }
852 } break;
Jim Ingham3815e702018-09-13 21:35:32 +0000853 case eSetTypeScripted: {
854
855 Status error;
856 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
857 &(m_options.m_modules),
858 &(m_options.m_filenames),
859 false,
860 m_options.m_hardware,
861 m_options.m_extra_args_sp,
862 &error);
863 if (error.Fail()) {
864 result.AppendErrorWithFormat(
865 "Error setting extra exception arguments: %s",
866 error.AsCString());
867 target->RemoveBreakpointByID(bp_sp->GetID());
868 result.SetStatus(eReturnStatusFailed);
869 return false;
870 }
871 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000872 default:
873 break;
874 }
875
876 // Now set the various options that were passed in:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000877 if (bp_sp) {
878 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000879
880 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000881 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000882 for (auto name : m_options.m_breakpoint_names) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000883 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000884 if (name_error.Fail()) {
885 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
886 name.c_str());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000887 target->RemoveBreakpointByID(bp_sp->GetID());
Jim Inghamff9a91e2016-09-21 01:21:19 +0000888 result.SetStatus(eReturnStatusFailed);
889 return false;
890 }
891 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000892 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000893 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000894
895 if (bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000896 Stream &output_stream = result.GetOutputStream();
897 const bool show_locations = false;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000898 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000899 show_locations);
900 if (target == m_interpreter.GetDebugger().GetDummyTarget())
901 output_stream.Printf("Breakpoint set in dummy target, will get copied "
902 "into future targets.\n");
903 else {
Adrian Prantl05097242018-04-30 16:49:04 +0000904 // Don't print out this warning for exception breakpoints. They can
905 // get set before the target is set, but we won't know how to actually
906 // set the breakpoint till we run.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000907 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000908 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
909 "actual locations.\n");
910 }
911 }
912 result.SetStatus(eReturnStatusSuccessFinishResult);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000913 } else if (!bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000914 result.AppendError("Breakpoint creation failed: No breakpoint created.");
915 result.SetStatus(eReturnStatusFailed);
916 }
917
918 return result.Succeeded();
919 }
920
Jim Ingham5a988412012-06-08 21:56:10 +0000921private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000922 bool GetDefaultFile(Target *target, FileSpec &file,
923 CommandReturnObject &result) {
924 uint32_t default_line;
Adrian Prantl05097242018-04-30 16:49:04 +0000925 // First use the Source Manager's default file. Then use the current stack
926 // frame's file.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000927 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
928 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
929 if (cur_frame == nullptr) {
930 result.AppendError(
931 "No selected frame to use to find the default file.");
932 result.SetStatus(eReturnStatusFailed);
933 return false;
934 } else if (!cur_frame->HasDebugInformation()) {
935 result.AppendError("Cannot use the selected frame to find the default "
936 "file, it has no debug info.");
937 result.SetStatus(eReturnStatusFailed);
938 return false;
939 } else {
940 const SymbolContext &sc =
941 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
942 if (sc.line_entry.file) {
943 file = sc.line_entry.file;
944 } else {
945 result.AppendError("Can't find the file for the selected frame to "
946 "use as the default file.");
947 result.SetStatus(eReturnStatusFailed);
948 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000949 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000950 }
Jim Ingham5a988412012-06-08 21:56:10 +0000951 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000952 return true;
953 }
954
Jim Inghamb842f2e2017-09-14 20:22:49 +0000955 BreakpointOptionGroup m_bp_opts;
956 BreakpointDummyOptionGroup m_dummy_options;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000957 CommandOptions m_options;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000958 OptionGroupOptions m_all_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000959};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000960
Jim Ingham5a988412012-06-08 21:56:10 +0000961// CommandObjectBreakpointModify
Jim Ingham5a988412012-06-08 21:56:10 +0000962#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000963
Kate Stoneb9c1b512016-09-06 20:57:50 +0000964class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000965public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000966 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
967 : CommandObjectParsed(interpreter, "breakpoint modify",
968 "Modify the options on a breakpoint or set of "
969 "breakpoints in the executable. "
970 "If no breakpoint is specified, acts on the last "
971 "created breakpoint. "
972 "With the exception of -e, -d and -i, passing an "
973 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000974 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000975 m_options() {
976 CommandArgumentEntry arg;
977 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
978 eArgTypeBreakpointIDRange);
979 // Add the entry for the first argument for this command to the object's
980 // arguments vector.
981 m_arguments.push_back(arg);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000982
983 m_options.Append(&m_bp_opts,
984 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
985 LLDB_OPT_SET_ALL);
986 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
987 m_options.Finalize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000988 }
989
990 ~CommandObjectBreakpointModify() override = default;
991
992 Options *GetOptions() override { return &m_options; }
993
Jim Ingham5a988412012-06-08 21:56:10 +0000994protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000995 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000996 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997 if (target == nullptr) {
998 result.AppendError("Invalid target. No existing target or breakpoints.");
999 result.SetStatus(eReturnStatusFailed);
1000 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001001 }
1002
Kate Stoneb9c1b512016-09-06 20:57:50 +00001003 std::unique_lock<std::recursive_mutex> lock;
1004 target->GetBreakpointList().GetListMutex(lock);
1005
1006 BreakpointIDList valid_bp_ids;
1007
1008 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001009 command, target, result, &valid_bp_ids,
1010 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011
1012 if (result.Succeeded()) {
1013 const size_t count = valid_bp_ids.GetSize();
1014 for (size_t i = 0; i < count; ++i) {
1015 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1016
1017 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1018 Breakpoint *bp =
1019 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1020 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1021 BreakpointLocation *location =
1022 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001023 if (location)
1024 location->GetLocationOptions()
1025 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001026 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001027 bp->GetOptions()
1028 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001029 }
1030 }
1031 }
1032 }
1033
1034 return result.Succeeded();
1035 }
1036
Jim Ingham5a988412012-06-08 21:56:10 +00001037private:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001038 BreakpointOptionGroup m_bp_opts;
1039 BreakpointDummyOptionGroup m_dummy_opts;
1040 OptionGroupOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001041};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001042
Jim Ingham5a988412012-06-08 21:56:10 +00001043// CommandObjectBreakpointEnable
Jim Ingham5a988412012-06-08 21:56:10 +00001044#pragma mark Enable
1045
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001047public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001048 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1049 : CommandObjectParsed(interpreter, "enable",
1050 "Enable the specified disabled breakpoint(s). If "
1051 "no breakpoints are specified, enable all of them.",
1052 nullptr) {
1053 CommandArgumentEntry arg;
1054 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1055 eArgTypeBreakpointIDRange);
1056 // Add the entry for the first argument for this command to the object's
1057 // arguments vector.
1058 m_arguments.push_back(arg);
1059 }
Jim Ingham5a988412012-06-08 21:56:10 +00001060
Kate Stoneb9c1b512016-09-06 20:57:50 +00001061 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001062
1063protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001064 bool DoExecute(Args &command, CommandReturnObject &result) override {
1065 Target *target = GetSelectedOrDummyTarget();
1066 if (target == nullptr) {
1067 result.AppendError("Invalid target. No existing target or breakpoints.");
1068 result.SetStatus(eReturnStatusFailed);
1069 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001070 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001071
1072 std::unique_lock<std::recursive_mutex> lock;
1073 target->GetBreakpointList().GetListMutex(lock);
1074
1075 const BreakpointList &breakpoints = target->GetBreakpointList();
1076
1077 size_t num_breakpoints = breakpoints.GetSize();
1078
1079 if (num_breakpoints == 0) {
1080 result.AppendError("No breakpoints exist to be enabled.");
1081 result.SetStatus(eReturnStatusFailed);
1082 return false;
1083 }
1084
Zachary Turner11eb9c62016-10-05 20:03:37 +00001085 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001086 // No breakpoint selected; enable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001087 target->EnableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001088 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1089 " breakpoints)\n",
1090 (uint64_t)num_breakpoints);
1091 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1092 } else {
1093 // Particular breakpoint selected; enable that breakpoint.
1094 BreakpointIDList valid_bp_ids;
1095 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001096 command, target, result, &valid_bp_ids,
1097 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001098
1099 if (result.Succeeded()) {
1100 int enable_count = 0;
1101 int loc_count = 0;
1102 const size_t count = valid_bp_ids.GetSize();
1103 for (size_t i = 0; i < count; ++i) {
1104 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1105
1106 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1107 Breakpoint *breakpoint =
1108 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1109 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1110 BreakpointLocation *location =
1111 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1112 if (location) {
1113 location->SetEnabled(true);
1114 ++loc_count;
1115 }
1116 } else {
1117 breakpoint->SetEnabled(true);
1118 ++enable_count;
1119 }
1120 }
1121 }
1122 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1123 enable_count + loc_count);
1124 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1125 }
1126 }
1127
1128 return result.Succeeded();
1129 }
Jim Ingham5a988412012-06-08 21:56:10 +00001130};
1131
Jim Ingham5a988412012-06-08 21:56:10 +00001132// CommandObjectBreakpointDisable
Jim Ingham5a988412012-06-08 21:56:10 +00001133#pragma mark Disable
1134
Kate Stoneb9c1b512016-09-06 20:57:50 +00001135class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001136public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001137 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1138 : CommandObjectParsed(
1139 interpreter, "breakpoint disable",
1140 "Disable the specified breakpoint(s) without deleting "
1141 "them. If none are specified, disable all "
1142 "breakpoints.",
1143 nullptr) {
1144 SetHelpLong(
1145 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001146If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001147 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001148
Kate Stone7428a182016-07-14 22:03:10 +00001149)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001150 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001151regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001152 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001153
1154 (lldb) break disable 1
1155 (lldb) break enable 1.1
1156
1157execution will NOT stop at location 1.1. To achieve that, type:
1158
1159 (lldb) break disable 1.*
1160 (lldb) break enable 1.1
1161
Kate Stone7428a182016-07-14 22:03:10 +00001162)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001163 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001164the second re-enables the first location.");
1165
Kate Stoneb9c1b512016-09-06 20:57:50 +00001166 CommandArgumentEntry arg;
1167 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1168 eArgTypeBreakpointIDRange);
1169 // Add the entry for the first argument for this command to the object's
1170 // arguments vector.
1171 m_arguments.push_back(arg);
1172 }
Jim Ingham5a988412012-06-08 21:56:10 +00001173
Kate Stoneb9c1b512016-09-06 20:57:50 +00001174 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001175
1176protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001177 bool DoExecute(Args &command, CommandReturnObject &result) override {
1178 Target *target = GetSelectedOrDummyTarget();
1179 if (target == nullptr) {
1180 result.AppendError("Invalid target. No existing target or breakpoints.");
1181 result.SetStatus(eReturnStatusFailed);
1182 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001183 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001184
1185 std::unique_lock<std::recursive_mutex> lock;
1186 target->GetBreakpointList().GetListMutex(lock);
1187
1188 const BreakpointList &breakpoints = target->GetBreakpointList();
1189 size_t num_breakpoints = breakpoints.GetSize();
1190
1191 if (num_breakpoints == 0) {
1192 result.AppendError("No breakpoints exist to be disabled.");
1193 result.SetStatus(eReturnStatusFailed);
1194 return false;
1195 }
1196
Zachary Turner11eb9c62016-10-05 20:03:37 +00001197 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001198 // No breakpoint selected; disable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001199 target->DisableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001200 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1201 " breakpoints)\n",
1202 (uint64_t)num_breakpoints);
1203 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1204 } else {
1205 // Particular breakpoint selected; disable that breakpoint.
1206 BreakpointIDList valid_bp_ids;
1207
1208 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001209 command, target, result, &valid_bp_ids,
1210 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001211
1212 if (result.Succeeded()) {
1213 int disable_count = 0;
1214 int loc_count = 0;
1215 const size_t count = valid_bp_ids.GetSize();
1216 for (size_t i = 0; i < count; ++i) {
1217 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1218
1219 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1220 Breakpoint *breakpoint =
1221 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1222 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1223 BreakpointLocation *location =
1224 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1225 if (location) {
1226 location->SetEnabled(false);
1227 ++loc_count;
1228 }
1229 } else {
1230 breakpoint->SetEnabled(false);
1231 ++disable_count;
1232 }
1233 }
1234 }
1235 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1236 disable_count + loc_count);
1237 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1238 }
1239 }
1240
1241 return result.Succeeded();
1242 }
Jim Ingham5a988412012-06-08 21:56:10 +00001243};
1244
Jim Ingham5a988412012-06-08 21:56:10 +00001245// CommandObjectBreakpointList
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001246
1247#pragma mark List::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001248static constexpr OptionDefinition g_breakpoint_list_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001249 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001250 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1251 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001252 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1253 // But I need to see it for now, and don't want to wait.
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001254 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1255 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1256 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001257 // clang-format on
1258};
1259
Jim Ingham5a988412012-06-08 21:56:10 +00001260#pragma mark List
1261
Kate Stoneb9c1b512016-09-06 20:57:50 +00001262class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001263public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001264 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1265 : CommandObjectParsed(
1266 interpreter, "breakpoint list",
1267 "List some or all breakpoints at configurable levels of detail.",
1268 nullptr),
1269 m_options() {
1270 CommandArgumentEntry arg;
1271 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001272
Kate Stoneb9c1b512016-09-06 20:57:50 +00001273 // Define the first (and only) variant of this arg.
1274 bp_id_arg.arg_type = eArgTypeBreakpointID;
1275 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001276
Kate Stoneb9c1b512016-09-06 20:57:50 +00001277 // There is only one variant this argument could be; put it into the
1278 // argument entry.
1279 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001280
Kate Stoneb9c1b512016-09-06 20:57:50 +00001281 // Push the data for the first argument into the m_arguments vector.
1282 m_arguments.push_back(arg);
1283 }
1284
1285 ~CommandObjectBreakpointList() override = default;
1286
1287 Options *GetOptions() override { return &m_options; }
1288
1289 class CommandOptions : public Options {
1290 public:
1291 CommandOptions()
1292 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001293 }
1294
Kate Stoneb9c1b512016-09-06 20:57:50 +00001295 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001296
Zachary Turner97206d52017-05-12 04:51:55 +00001297 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1298 ExecutionContext *execution_context) override {
1299 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001300 const int short_option = m_getopt_table[option_idx].val;
1301
1302 switch (short_option) {
1303 case 'b':
1304 m_level = lldb::eDescriptionLevelBrief;
1305 break;
1306 case 'D':
1307 m_use_dummy = true;
1308 break;
1309 case 'f':
1310 m_level = lldb::eDescriptionLevelFull;
1311 break;
1312 case 'v':
1313 m_level = lldb::eDescriptionLevelVerbose;
1314 break;
1315 case 'i':
1316 m_internal = true;
1317 break;
1318 default:
1319 error.SetErrorStringWithFormat("unrecognized option '%c'",
1320 short_option);
1321 break;
1322 }
1323
1324 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001325 }
Jim Ingham5a988412012-06-08 21:56:10 +00001326
Kate Stoneb9c1b512016-09-06 20:57:50 +00001327 void OptionParsingStarting(ExecutionContext *execution_context) override {
1328 m_level = lldb::eDescriptionLevelFull;
1329 m_internal = false;
1330 m_use_dummy = false;
1331 }
Jim Ingham5a988412012-06-08 21:56:10 +00001332
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001333 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001334 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001335 }
Jim Ingham5a988412012-06-08 21:56:10 +00001336
Kate Stoneb9c1b512016-09-06 20:57:50 +00001337 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001338
Kate Stoneb9c1b512016-09-06 20:57:50 +00001339 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001340
Kate Stoneb9c1b512016-09-06 20:57:50 +00001341 bool m_internal;
1342 bool m_use_dummy;
1343 };
Jim Ingham5a988412012-06-08 21:56:10 +00001344
1345protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001346 bool DoExecute(Args &command, CommandReturnObject &result) override {
1347 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001348
Kate Stoneb9c1b512016-09-06 20:57:50 +00001349 if (target == nullptr) {
1350 result.AppendError("Invalid target. No current target or breakpoints.");
1351 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1352 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001353 }
1354
Kate Stoneb9c1b512016-09-06 20:57:50 +00001355 const BreakpointList &breakpoints =
1356 target->GetBreakpointList(m_options.m_internal);
1357 std::unique_lock<std::recursive_mutex> lock;
1358 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1359
1360 size_t num_breakpoints = breakpoints.GetSize();
1361
1362 if (num_breakpoints == 0) {
1363 result.AppendMessage("No breakpoints currently set.");
1364 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1365 return true;
1366 }
1367
1368 Stream &output_stream = result.GetOutputStream();
1369
Zachary Turner11eb9c62016-10-05 20:03:37 +00001370 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001371 // No breakpoint selected; show info about all currently set breakpoints.
1372 result.AppendMessage("Current breakpoints:");
1373 for (size_t i = 0; i < num_breakpoints; ++i) {
1374 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001375 if (breakpoint->AllowList())
1376 AddBreakpointDescription(&output_stream, breakpoint,
1377 m_options.m_level);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001378 }
1379 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1380 } else {
1381 // Particular breakpoints selected; show info about that breakpoint.
1382 BreakpointIDList valid_bp_ids;
1383 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001384 command, target, result, &valid_bp_ids,
1385 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001386
1387 if (result.Succeeded()) {
1388 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1389 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1390 Breakpoint *breakpoint =
1391 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1392 AddBreakpointDescription(&output_stream, breakpoint,
1393 m_options.m_level);
1394 }
1395 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1396 } else {
1397 result.AppendError("Invalid breakpoint ID.");
1398 result.SetStatus(eReturnStatusFailed);
1399 }
1400 }
1401
1402 return result.Succeeded();
1403 }
1404
Jim Ingham5a988412012-06-08 21:56:10 +00001405private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001406 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001407};
1408
Jim Ingham5a988412012-06-08 21:56:10 +00001409// CommandObjectBreakpointClear
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001410#pragma mark Clear::CommandOptions
1411
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001412static constexpr OptionDefinition g_breakpoint_clear_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001413 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001414 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1415 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001416 // clang-format on
1417};
1418
Jim Ingham5a988412012-06-08 21:56:10 +00001419#pragma mark Clear
1420
Kate Stoneb9c1b512016-09-06 20:57:50 +00001421class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001422public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001423 typedef enum BreakpointClearType {
1424 eClearTypeInvalid,
1425 eClearTypeFileAndLine
1426 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001427
Kate Stoneb9c1b512016-09-06 20:57:50 +00001428 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1429 : CommandObjectParsed(interpreter, "breakpoint clear",
1430 "Delete or disable breakpoints matching the "
1431 "specified source file and line.",
1432 "breakpoint clear <cmd-options>"),
1433 m_options() {}
1434
1435 ~CommandObjectBreakpointClear() override = default;
1436
1437 Options *GetOptions() override { return &m_options; }
1438
1439 class CommandOptions : public Options {
1440 public:
1441 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1442
1443 ~CommandOptions() override = default;
1444
Zachary Turner97206d52017-05-12 04:51:55 +00001445 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1446 ExecutionContext *execution_context) override {
1447 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001448 const int short_option = m_getopt_table[option_idx].val;
1449
1450 switch (short_option) {
1451 case 'f':
1452 m_filename.assign(option_arg);
1453 break;
1454
1455 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001456 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001457 break;
1458
1459 default:
1460 error.SetErrorStringWithFormat("unrecognized option '%c'",
1461 short_option);
1462 break;
1463 }
1464
1465 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001466 }
1467
Kate Stoneb9c1b512016-09-06 20:57:50 +00001468 void OptionParsingStarting(ExecutionContext *execution_context) override {
1469 m_filename.clear();
1470 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001471 }
1472
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001473 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001474 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001475 }
Jim Ingham5a988412012-06-08 21:56:10 +00001476
Kate Stoneb9c1b512016-09-06 20:57:50 +00001477 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001478
Kate Stoneb9c1b512016-09-06 20:57:50 +00001479 std::string m_filename;
1480 uint32_t m_line_num;
1481 };
Jim Ingham5a988412012-06-08 21:56:10 +00001482
1483protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001484 bool DoExecute(Args &command, CommandReturnObject &result) override {
1485 Target *target = GetSelectedOrDummyTarget();
1486 if (target == nullptr) {
1487 result.AppendError("Invalid target. No existing target or breakpoints.");
1488 result.SetStatus(eReturnStatusFailed);
1489 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001490 }
1491
Adrian Prantl05097242018-04-30 16:49:04 +00001492 // The following are the various types of breakpoints that could be
1493 // cleared:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001494 // 1). -f -l (clearing breakpoint by source location)
1495
1496 BreakpointClearType break_type = eClearTypeInvalid;
1497
1498 if (m_options.m_line_num != 0)
1499 break_type = eClearTypeFileAndLine;
1500
1501 std::unique_lock<std::recursive_mutex> lock;
1502 target->GetBreakpointList().GetListMutex(lock);
1503
1504 BreakpointList &breakpoints = target->GetBreakpointList();
1505 size_t num_breakpoints = breakpoints.GetSize();
1506
1507 // Early return if there's no breakpoint at all.
1508 if (num_breakpoints == 0) {
1509 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1510 result.SetStatus(eReturnStatusFailed);
1511 return result.Succeeded();
1512 }
1513
1514 // Find matching breakpoints and delete them.
1515
1516 // First create a copy of all the IDs.
1517 std::vector<break_id_t> BreakIDs;
1518 for (size_t i = 0; i < num_breakpoints; ++i)
1519 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1520
1521 int num_cleared = 0;
1522 StreamString ss;
1523 switch (break_type) {
1524 case eClearTypeFileAndLine: // Breakpoint by source position
1525 {
1526 const ConstString filename(m_options.m_filename.c_str());
1527 BreakpointLocationCollection loc_coll;
1528
1529 for (size_t i = 0; i < num_breakpoints; ++i) {
1530 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1531
1532 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1533 // If the collection size is 0, it's a full match and we can just
1534 // remove the breakpoint.
1535 if (loc_coll.GetSize() == 0) {
1536 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1537 ss.EOL();
1538 target->RemoveBreakpointByID(bp->GetID());
1539 ++num_cleared;
1540 }
1541 }
1542 }
1543 } break;
1544
1545 default:
1546 break;
1547 }
1548
1549 if (num_cleared > 0) {
1550 Stream &output_stream = result.GetOutputStream();
1551 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001552 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001553 output_stream.EOL();
1554 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1555 } else {
1556 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1557 result.SetStatus(eReturnStatusFailed);
1558 }
1559
1560 return result.Succeeded();
1561 }
1562
Jim Ingham5a988412012-06-08 21:56:10 +00001563private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001564 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001565};
1566
Jim Ingham5a988412012-06-08 21:56:10 +00001567// CommandObjectBreakpointDelete
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001568static constexpr OptionDefinition g_breakpoint_delete_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001569 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001570 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1571 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001572 // clang-format on
1573};
1574
Jim Ingham5a988412012-06-08 21:56:10 +00001575#pragma mark Delete
1576
Kate Stoneb9c1b512016-09-06 20:57:50 +00001577class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001578public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001579 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1580 : CommandObjectParsed(interpreter, "breakpoint delete",
1581 "Delete the specified breakpoint(s). If no "
1582 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001583 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001584 m_options() {
1585 CommandArgumentEntry arg;
1586 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1587 eArgTypeBreakpointIDRange);
1588 // Add the entry for the first argument for this command to the object's
1589 // arguments vector.
1590 m_arguments.push_back(arg);
1591 }
1592
1593 ~CommandObjectBreakpointDelete() override = default;
1594
1595 Options *GetOptions() override { return &m_options; }
1596
1597 class CommandOptions : public Options {
1598 public:
1599 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1600
1601 ~CommandOptions() override = default;
1602
Zachary Turner97206d52017-05-12 04:51:55 +00001603 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1604 ExecutionContext *execution_context) override {
1605 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001606 const int short_option = m_getopt_table[option_idx].val;
1607
1608 switch (short_option) {
1609 case 'f':
1610 m_force = true;
1611 break;
1612
1613 case 'D':
1614 m_use_dummy = true;
1615 break;
1616
1617 default:
1618 error.SetErrorStringWithFormat("unrecognized option '%c'",
1619 short_option);
1620 break;
1621 }
1622
1623 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001624 }
1625
Kate Stoneb9c1b512016-09-06 20:57:50 +00001626 void OptionParsingStarting(ExecutionContext *execution_context) override {
1627 m_use_dummy = false;
1628 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001629 }
1630
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001631 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001632 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001633 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001634
Kate Stoneb9c1b512016-09-06 20:57:50 +00001635 // Instance variables to hold the values for command options.
1636 bool m_use_dummy;
1637 bool m_force;
1638 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001639
Jim Ingham5a988412012-06-08 21:56:10 +00001640protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001641 bool DoExecute(Args &command, CommandReturnObject &result) override {
1642 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001643
Kate Stoneb9c1b512016-09-06 20:57:50 +00001644 if (target == nullptr) {
1645 result.AppendError("Invalid target. No existing target or breakpoints.");
1646 result.SetStatus(eReturnStatusFailed);
1647 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001648 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001649
Kate Stoneb9c1b512016-09-06 20:57:50 +00001650 std::unique_lock<std::recursive_mutex> lock;
1651 target->GetBreakpointList().GetListMutex(lock);
1652
1653 const BreakpointList &breakpoints = target->GetBreakpointList();
1654
1655 size_t num_breakpoints = breakpoints.GetSize();
1656
1657 if (num_breakpoints == 0) {
1658 result.AppendError("No breakpoints exist to be deleted.");
1659 result.SetStatus(eReturnStatusFailed);
1660 return false;
1661 }
1662
Zachary Turner11eb9c62016-10-05 20:03:37 +00001663 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001664 if (!m_options.m_force &&
1665 !m_interpreter.Confirm(
1666 "About to delete all breakpoints, do you want to do that?",
1667 true)) {
1668 result.AppendMessage("Operation cancelled...");
1669 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001670 target->RemoveAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001671 result.AppendMessageWithFormat(
1672 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1673 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1674 }
1675 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1676 } else {
1677 // Particular breakpoint selected; disable that breakpoint.
1678 BreakpointIDList valid_bp_ids;
1679 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001680 command, target, result, &valid_bp_ids,
1681 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001682
1683 if (result.Succeeded()) {
1684 int delete_count = 0;
1685 int disable_count = 0;
1686 const size_t count = valid_bp_ids.GetSize();
1687 for (size_t i = 0; i < count; ++i) {
1688 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1689
1690 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1691 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1692 Breakpoint *breakpoint =
1693 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1694 BreakpointLocation *location =
1695 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1696 // It makes no sense to try to delete individual locations, so we
1697 // disable them instead.
1698 if (location) {
1699 location->SetEnabled(false);
1700 ++disable_count;
1701 }
1702 } else {
1703 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1704 ++delete_count;
1705 }
1706 }
1707 }
1708 result.AppendMessageWithFormat(
1709 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1710 delete_count, disable_count);
1711 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1712 }
1713 }
1714 return result.Succeeded();
1715 }
1716
Jim Ingham33df7cd2014-12-06 01:28:03 +00001717private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001718 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001719};
1720
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001721// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001722
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001723static constexpr OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001724 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001725 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1726 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1727 {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1728 {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."},
Kate Stoneb9c1b512016-09-06 20:57:50 +00001729 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001730};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001731class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001732public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001733 BreakpointNameOptionGroup()
1734 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1735 }
1736
1737 ~BreakpointNameOptionGroup() override = default;
1738
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001739 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001740 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001741 }
1742
Zachary Turner97206d52017-05-12 04:51:55 +00001743 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1744 ExecutionContext *execution_context) override {
1745 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001746 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1747
1748 switch (short_option) {
1749 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001750 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001751 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001752 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001753 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001754 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001755 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001756 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001757 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001758 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001759 break;
1760 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001761 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001762 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001763 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001764 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001765 break;
Jim Inghame9632eb2017-09-15 00:52:35 +00001766 case 'H':
1767 m_help_string.SetValueFromString(option_arg);
1768 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001769
1770 default:
1771 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1772 short_option);
1773 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001774 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001775 return error;
1776 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001777
Kate Stoneb9c1b512016-09-06 20:57:50 +00001778 void OptionParsingStarting(ExecutionContext *execution_context) override {
1779 m_name.Clear();
1780 m_breakpoint.Clear();
1781 m_use_dummy.Clear();
1782 m_use_dummy.SetDefaultValue(false);
Jim Inghame9632eb2017-09-15 00:52:35 +00001783 m_help_string.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001784 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001785
Kate Stoneb9c1b512016-09-06 20:57:50 +00001786 OptionValueString m_name;
1787 OptionValueUInt64 m_breakpoint;
1788 OptionValueBoolean m_use_dummy;
Jim Inghame9632eb2017-09-15 00:52:35 +00001789 OptionValueString m_help_string;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001790};
1791
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001792static constexpr OptionDefinition g_breakpoint_access_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001793 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001794 {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
1795 {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
1796 {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."},
Jim Inghamb842f2e2017-09-14 20:22:49 +00001797 // clang-format on
1798};
1799
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001800class BreakpointAccessOptionGroup : public OptionGroup {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001801public:
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001802 BreakpointAccessOptionGroup() : OptionGroup() {}
1803
Jim Inghamb842f2e2017-09-14 20:22:49 +00001804 ~BreakpointAccessOptionGroup() override = default;
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001805
Jim Inghamb842f2e2017-09-14 20:22:49 +00001806 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1807 return llvm::makeArrayRef(g_breakpoint_access_options);
1808 }
1809 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1810 ExecutionContext *execution_context) override {
1811 Status error;
1812 const int short_option
1813 = g_breakpoint_access_options[option_idx].short_option;
1814
1815 switch (short_option) {
1816 case 'L': {
1817 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001818 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001819 if (success) {
1820 m_permissions.SetAllowList(value);
1821 } else
1822 error.SetErrorStringWithFormat(
1823 "invalid boolean value '%s' passed for -L option",
1824 option_arg.str().c_str());
1825 } break;
1826 case 'A': {
1827 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001828 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001829 if (success) {
1830 m_permissions.SetAllowDisable(value);
1831 } else
1832 error.SetErrorStringWithFormat(
1833 "invalid boolean value '%s' passed for -L option",
1834 option_arg.str().c_str());
1835 } break;
1836 case 'D': {
1837 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001838 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001839 if (success) {
1840 m_permissions.SetAllowDelete(value);
1841 } else
1842 error.SetErrorStringWithFormat(
1843 "invalid boolean value '%s' passed for -L option",
1844 option_arg.str().c_str());
1845 } break;
1846
1847 }
1848
1849 return error;
1850 }
1851
1852 void OptionParsingStarting(ExecutionContext *execution_context) override {
1853 }
1854
1855 const BreakpointName::Permissions &GetPermissions() const
1856 {
1857 return m_permissions;
1858 }
1859 BreakpointName::Permissions m_permissions;
1860};
1861
1862class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1863public:
1864 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1865 : CommandObjectParsed(
1866 interpreter, "configure", "Configure the options for the breakpoint"
1867 " name provided. "
1868 "If you provide a breakpoint id, the options will be copied from "
1869 "the breakpoint, otherwise only the options specified will be set "
1870 "on the name.",
1871 "breakpoint name configure <command-options> "
1872 "<breakpoint-name-list>"),
1873 m_bp_opts(), m_option_group() {
1874 // Create the first variant for the first (and only) argument for this
1875 // command.
1876 CommandArgumentEntry arg1;
1877 CommandArgumentData id_arg;
1878 id_arg.arg_type = eArgTypeBreakpointName;
1879 id_arg.arg_repetition = eArgRepeatOptional;
1880 arg1.push_back(id_arg);
1881 m_arguments.push_back(arg1);
1882
1883 m_option_group.Append(&m_bp_opts,
1884 LLDB_OPT_SET_ALL,
1885 LLDB_OPT_SET_1);
1886 m_option_group.Append(&m_access_options,
1887 LLDB_OPT_SET_ALL,
1888 LLDB_OPT_SET_ALL);
Jim Inghame9632eb2017-09-15 00:52:35 +00001889 m_option_group.Append(&m_bp_id,
1890 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1891 LLDB_OPT_SET_ALL);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001892 m_option_group.Finalize();
1893 }
1894
1895 ~CommandObjectBreakpointNameConfigure() override = default;
1896
1897 Options *GetOptions() override { return &m_option_group; }
1898
1899protected:
1900 bool DoExecute(Args &command, CommandReturnObject &result) override {
1901
1902 const size_t argc = command.GetArgumentCount();
1903 if (argc == 0) {
1904 result.AppendError("No names provided.");
1905 result.SetStatus(eReturnStatusFailed);
1906 return false;
1907 }
1908
1909 Target *target =
1910 GetSelectedOrDummyTarget(false);
1911
1912 if (target == nullptr) {
1913 result.AppendError("Invalid target. No existing target or breakpoints.");
1914 result.SetStatus(eReturnStatusFailed);
1915 return false;
1916 }
1917
1918 std::unique_lock<std::recursive_mutex> lock;
1919 target->GetBreakpointList().GetListMutex(lock);
1920
1921 // Make a pass through first to see that all the names are legal.
1922 for (auto &entry : command.entries()) {
1923 Status error;
1924 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1925 {
1926 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1927 entry.c_str(), error.AsCString());
1928 result.SetStatus(eReturnStatusFailed);
1929 return false;
1930 }
1931 }
Adrian Prantl05097242018-04-30 16:49:04 +00001932 // Now configure them, we already pre-checked the names so we don't need to
1933 // check the error:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001934 BreakpointSP bp_sp;
1935 if (m_bp_id.m_breakpoint.OptionWasSet())
1936 {
1937 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1938 bp_sp = target->GetBreakpointByID(bp_id);
1939 if (!bp_sp)
1940 {
1941 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1942 bp_id);
1943 result.SetStatus(eReturnStatusFailed);
1944 return false;
1945 }
1946 }
1947
1948 Status error;
1949 for (auto &entry : command.entries()) {
1950 ConstString name(entry.c_str());
1951 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1952 if (!bp_name)
1953 continue;
Jim Inghame9632eb2017-09-15 00:52:35 +00001954 if (m_bp_id.m_help_string.OptionWasSet())
1955 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1956
Jim Inghamb842f2e2017-09-14 20:22:49 +00001957 if (bp_sp)
1958 target->ConfigureBreakpointName(*bp_name,
1959 *bp_sp->GetOptions(),
1960 m_access_options.GetPermissions());
1961 else
1962 target->ConfigureBreakpointName(*bp_name,
1963 m_bp_opts.GetBreakpointOptions(),
1964 m_access_options.GetPermissions());
1965 }
1966 return true;
1967 }
1968
1969private:
1970 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1971 BreakpointOptionGroup m_bp_opts;
1972 BreakpointAccessOptionGroup m_access_options;
1973 OptionGroupOptions m_option_group;
1974};
1975
Kate Stoneb9c1b512016-09-06 20:57:50 +00001976class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001977public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001978 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1979 : CommandObjectParsed(
1980 interpreter, "add", "Add a name to the breakpoints provided.",
1981 "breakpoint name add <command-options> <breakpoint-id-list>"),
1982 m_name_options(), m_option_group() {
1983 // Create the first variant for the first (and only) argument for this
1984 // command.
1985 CommandArgumentEntry arg1;
1986 CommandArgumentData id_arg;
1987 id_arg.arg_type = eArgTypeBreakpointID;
1988 id_arg.arg_repetition = eArgRepeatOptional;
1989 arg1.push_back(id_arg);
1990 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001991
Kate Stoneb9c1b512016-09-06 20:57:50 +00001992 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1993 m_option_group.Finalize();
1994 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001995
Kate Stoneb9c1b512016-09-06 20:57:50 +00001996 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001997
Kate Stoneb9c1b512016-09-06 20:57:50 +00001998 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001999
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002000protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002001 bool DoExecute(Args &command, CommandReturnObject &result) override {
2002 if (!m_name_options.m_name.OptionWasSet()) {
2003 result.SetError("No name option provided.");
2004 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002005 }
2006
Kate Stoneb9c1b512016-09-06 20:57:50 +00002007 Target *target =
2008 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2009
2010 if (target == nullptr) {
2011 result.AppendError("Invalid target. No existing target or breakpoints.");
2012 result.SetStatus(eReturnStatusFailed);
2013 return false;
2014 }
2015
2016 std::unique_lock<std::recursive_mutex> lock;
2017 target->GetBreakpointList().GetListMutex(lock);
2018
2019 const BreakpointList &breakpoints = target->GetBreakpointList();
2020
2021 size_t num_breakpoints = breakpoints.GetSize();
2022 if (num_breakpoints == 0) {
2023 result.SetError("No breakpoints, cannot add names.");
2024 result.SetStatus(eReturnStatusFailed);
2025 return false;
2026 }
2027
2028 // Particular breakpoint selected; disable that breakpoint.
2029 BreakpointIDList valid_bp_ids;
2030 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002031 command, target, result, &valid_bp_ids,
2032 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002033
2034 if (result.Succeeded()) {
2035 if (valid_bp_ids.GetSize() == 0) {
2036 result.SetError("No breakpoints specified, cannot add names.");
2037 result.SetStatus(eReturnStatusFailed);
2038 return false;
2039 }
2040 size_t num_valid_ids = valid_bp_ids.GetSize();
Jim Inghamb842f2e2017-09-14 20:22:49 +00002041 const char *bp_name = m_name_options.m_name.GetCurrentValue();
2042 Status error; // This error reports illegal names, but we've already
2043 // checked that, so we don't need to check it again here.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002044 for (size_t index = 0; index < num_valid_ids; index++) {
2045 lldb::break_id_t bp_id =
2046 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2047 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002048 target->AddNameToBreakpoint(bp_sp, bp_name, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002049 }
2050 }
2051
2052 return true;
2053 }
2054
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002055private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002056 BreakpointNameOptionGroup m_name_options;
2057 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002058};
2059
Kate Stoneb9c1b512016-09-06 20:57:50 +00002060class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002061public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002062 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2063 : CommandObjectParsed(
2064 interpreter, "delete",
2065 "Delete a name from the breakpoints provided.",
2066 "breakpoint name delete <command-options> <breakpoint-id-list>"),
2067 m_name_options(), m_option_group() {
2068 // Create the first variant for the first (and only) argument for this
2069 // command.
2070 CommandArgumentEntry arg1;
2071 CommandArgumentData id_arg;
2072 id_arg.arg_type = eArgTypeBreakpointID;
2073 id_arg.arg_repetition = eArgRepeatOptional;
2074 arg1.push_back(id_arg);
2075 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002076
Kate Stoneb9c1b512016-09-06 20:57:50 +00002077 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2078 m_option_group.Finalize();
2079 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002080
Kate Stoneb9c1b512016-09-06 20:57:50 +00002081 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002082
Kate Stoneb9c1b512016-09-06 20:57:50 +00002083 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002084
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002085protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002086 bool DoExecute(Args &command, CommandReturnObject &result) override {
2087 if (!m_name_options.m_name.OptionWasSet()) {
2088 result.SetError("No name option provided.");
2089 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002090 }
2091
Kate Stoneb9c1b512016-09-06 20:57:50 +00002092 Target *target =
2093 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2094
2095 if (target == nullptr) {
2096 result.AppendError("Invalid target. No existing target or breakpoints.");
2097 result.SetStatus(eReturnStatusFailed);
2098 return false;
2099 }
2100
2101 std::unique_lock<std::recursive_mutex> lock;
2102 target->GetBreakpointList().GetListMutex(lock);
2103
2104 const BreakpointList &breakpoints = target->GetBreakpointList();
2105
2106 size_t num_breakpoints = breakpoints.GetSize();
2107 if (num_breakpoints == 0) {
2108 result.SetError("No breakpoints, cannot delete names.");
2109 result.SetStatus(eReturnStatusFailed);
2110 return false;
2111 }
2112
2113 // Particular breakpoint selected; disable that breakpoint.
2114 BreakpointIDList valid_bp_ids;
2115 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002116 command, target, result, &valid_bp_ids,
2117 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002118
2119 if (result.Succeeded()) {
2120 if (valid_bp_ids.GetSize() == 0) {
2121 result.SetError("No breakpoints specified, cannot delete names.");
2122 result.SetStatus(eReturnStatusFailed);
2123 return false;
2124 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002125 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +00002126 size_t num_valid_ids = valid_bp_ids.GetSize();
2127 for (size_t index = 0; index < num_valid_ids; index++) {
2128 lldb::break_id_t bp_id =
2129 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2130 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002131 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002132 }
2133 }
2134
2135 return true;
2136 }
2137
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002138private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002139 BreakpointNameOptionGroup m_name_options;
2140 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002141};
2142
Kate Stoneb9c1b512016-09-06 20:57:50 +00002143class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002144public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002145 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2146 : CommandObjectParsed(interpreter, "list",
Jim Inghamb842f2e2017-09-14 20:22:49 +00002147 "List either the names for a breakpoint or info "
2148 "about a given name. With no arguments, lists all "
2149 "names",
Kate Stoneb9c1b512016-09-06 20:57:50 +00002150 "breakpoint name list <command-options>"),
2151 m_name_options(), m_option_group() {
Jim Inghamb842f2e2017-09-14 20:22:49 +00002152 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002153 m_option_group.Finalize();
2154 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002155
Kate Stoneb9c1b512016-09-06 20:57:50 +00002156 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002157
Kate Stoneb9c1b512016-09-06 20:57:50 +00002158 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002159
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002160protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002161 bool DoExecute(Args &command, CommandReturnObject &result) override {
2162 Target *target =
2163 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002164
Kate Stoneb9c1b512016-09-06 20:57:50 +00002165 if (target == nullptr) {
2166 result.AppendError("Invalid target. No existing target or breakpoints.");
2167 result.SetStatus(eReturnStatusFailed);
2168 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002169 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002170
2171
2172 std::vector<std::string> name_list;
2173 if (command.empty()) {
2174 target->GetBreakpointNames(name_list);
2175 } else {
2176 for (const Args::ArgEntry &arg : command)
2177 {
2178 name_list.push_back(arg.c_str());
2179 }
2180 }
2181
2182 if (name_list.empty()) {
2183 result.AppendMessage("No breakpoint names found.");
2184 } else {
2185 for (const std::string &name_str : name_list) {
2186 const char *name = name_str.c_str();
2187 // First print out the options for the name:
2188 Status error;
2189 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2190 false,
2191 error);
2192 if (bp_name)
2193 {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002194 StreamString s;
Jim Inghamb842f2e2017-09-14 20:22:49 +00002195 result.AppendMessageWithFormat("Name: %s\n", name);
2196 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2197 {
2198 result.AppendMessage(s.GetString());
2199 }
2200
2201 std::unique_lock<std::recursive_mutex> lock;
2202 target->GetBreakpointList().GetListMutex(lock);
2203
2204 BreakpointList &breakpoints = target->GetBreakpointList();
2205 bool any_set = false;
2206 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2207 if (bp_sp->MatchesName(name)) {
2208 StreamString s;
2209 any_set = true;
2210 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2211 s.EOL();
2212 result.AppendMessage(s.GetString());
2213 }
2214 }
2215 if (!any_set)
2216 result.AppendMessage("No breakpoints using this name.");
2217 } else {
2218 result.AppendMessageWithFormat("Name: %s not found.\n", name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002219 }
2220 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002221 }
2222 return true;
2223 }
2224
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002225private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002226 BreakpointNameOptionGroup m_name_options;
2227 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002228};
2229
Jim Inghame14dc262016-09-12 23:10:56 +00002230// CommandObjectBreakpointName
Kate Stoneb9c1b512016-09-06 20:57:50 +00002231class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002232public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002233 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2234 : CommandObjectMultiword(
2235 interpreter, "name", "Commands to manage name tags for breakpoints",
2236 "breakpoint name <subcommand> [<command-options>]") {
2237 CommandObjectSP add_command_object(
2238 new CommandObjectBreakpointNameAdd(interpreter));
2239 CommandObjectSP delete_command_object(
2240 new CommandObjectBreakpointNameDelete(interpreter));
2241 CommandObjectSP list_command_object(
2242 new CommandObjectBreakpointNameList(interpreter));
Jim Inghamb842f2e2017-09-14 20:22:49 +00002243 CommandObjectSP configure_command_object(
2244 new CommandObjectBreakpointNameConfigure(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002245
Kate Stoneb9c1b512016-09-06 20:57:50 +00002246 LoadSubCommand("add", add_command_object);
2247 LoadSubCommand("delete", delete_command_object);
2248 LoadSubCommand("list", list_command_object);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002249 LoadSubCommand("configure", configure_command_object);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002250 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002251
Kate Stoneb9c1b512016-09-06 20:57:50 +00002252 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002253};
2254
Jim Inghame14dc262016-09-12 23:10:56 +00002255// CommandObjectBreakpointRead
Jim Ingham3acdf382016-09-22 22:20:28 +00002256#pragma mark Read::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002257static constexpr OptionDefinition g_breakpoint_read_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002258 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002259 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2260 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002261 // clang-format on
2262};
2263
2264#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002265
2266class CommandObjectBreakpointRead : public CommandObjectParsed {
2267public:
2268 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2269 : CommandObjectParsed(interpreter, "breakpoint read",
2270 "Read and set the breakpoints previously saved to "
2271 "a file with \"breakpoint write\". ",
2272 nullptr),
2273 m_options() {
2274 CommandArgumentEntry arg;
2275 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2276 eArgTypeBreakpointIDRange);
2277 // Add the entry for the first argument for this command to the object's
2278 // arguments vector.
2279 m_arguments.push_back(arg);
2280 }
2281
2282 ~CommandObjectBreakpointRead() override = default;
2283
2284 Options *GetOptions() override { return &m_options; }
2285
2286 class CommandOptions : public Options {
2287 public:
2288 CommandOptions() : Options() {}
2289
2290 ~CommandOptions() override = default;
2291
Zachary Turner97206d52017-05-12 04:51:55 +00002292 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2293 ExecutionContext *execution_context) override {
2294 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002295 const int short_option = m_getopt_table[option_idx].val;
2296
2297 switch (short_option) {
2298 case 'f':
2299 m_filename.assign(option_arg);
2300 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002301 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002302 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002303 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2304 name_error)) {
2305 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2306 name_error.AsCString());
2307 }
2308 m_names.push_back(option_arg);
2309 break;
2310 }
Jim Inghame14dc262016-09-12 23:10:56 +00002311 default:
2312 error.SetErrorStringWithFormat("unrecognized option '%c'",
2313 short_option);
2314 break;
2315 }
2316
2317 return error;
2318 }
2319
2320 void OptionParsingStarting(ExecutionContext *execution_context) override {
2321 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002322 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002323 }
2324
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002325 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002326 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002327 }
Jim Inghame14dc262016-09-12 23:10:56 +00002328
2329 // Instance variables to hold the values for command options.
2330
2331 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002332 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002333 };
2334
2335protected:
2336 bool DoExecute(Args &command, CommandReturnObject &result) override {
2337 Target *target = GetSelectedOrDummyTarget();
2338 if (target == nullptr) {
2339 result.AppendError("Invalid target. No existing target or breakpoints.");
2340 result.SetStatus(eReturnStatusFailed);
2341 return false;
2342 }
2343
Jim Ingham3acdf382016-09-22 22:20:28 +00002344 std::unique_lock<std::recursive_mutex> lock;
2345 target->GetBreakpointList().GetListMutex(lock);
2346
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002347 FileSpec input_spec(m_options.m_filename);
2348 FileSystem::Instance().Resolve(input_spec);
Jim Ingham01f16662016-09-14 19:07:35 +00002349 BreakpointIDList new_bps;
Zachary Turner97206d52017-05-12 04:51:55 +00002350 Status error = target->CreateBreakpointsFromFile(
2351 input_spec, m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002352
Jim Inghame14dc262016-09-12 23:10:56 +00002353 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002354 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002355 result.SetStatus(eReturnStatusFailed);
2356 return false;
2357 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002358
2359 Stream &output_stream = result.GetOutputStream();
2360
2361 size_t num_breakpoints = new_bps.GetSize();
2362 if (num_breakpoints == 0) {
2363 result.AppendMessage("No breakpoints added.");
2364 } else {
2365 // No breakpoint selected; show info about all currently set breakpoints.
2366 result.AppendMessage("New breakpoints:");
2367 for (size_t i = 0; i < num_breakpoints; ++i) {
2368 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2369 Breakpoint *bp = target->GetBreakpointList()
2370 .FindBreakpointByID(bp_id.GetBreakpointID())
2371 .get();
2372 if (bp)
2373 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2374 false);
2375 }
2376 }
Jim Inghame14dc262016-09-12 23:10:56 +00002377 return result.Succeeded();
2378 }
2379
2380private:
2381 CommandOptions m_options;
2382};
2383
Jim Inghame14dc262016-09-12 23:10:56 +00002384// CommandObjectBreakpointWrite
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002385#pragma mark Write::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002386static constexpr OptionDefinition g_breakpoint_write_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002387 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002388 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2389 { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002390 // clang-format on
2391};
2392
2393#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002394class CommandObjectBreakpointWrite : public CommandObjectParsed {
2395public:
2396 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2397 : CommandObjectParsed(interpreter, "breakpoint write",
2398 "Write the breakpoints listed to a file that can "
2399 "be read in with \"breakpoint read\". "
2400 "If given no arguments, writes all breakpoints.",
2401 nullptr),
2402 m_options() {
2403 CommandArgumentEntry arg;
2404 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2405 eArgTypeBreakpointIDRange);
2406 // Add the entry for the first argument for this command to the object's
2407 // arguments vector.
2408 m_arguments.push_back(arg);
2409 }
2410
2411 ~CommandObjectBreakpointWrite() override = default;
2412
2413 Options *GetOptions() override { return &m_options; }
2414
2415 class CommandOptions : public Options {
2416 public:
2417 CommandOptions() : Options() {}
2418
2419 ~CommandOptions() override = default;
2420
Zachary Turner97206d52017-05-12 04:51:55 +00002421 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2422 ExecutionContext *execution_context) override {
2423 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002424 const int short_option = m_getopt_table[option_idx].val;
2425
2426 switch (short_option) {
2427 case 'f':
2428 m_filename.assign(option_arg);
2429 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002430 case 'a':
2431 m_append = true;
2432 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002433 default:
2434 error.SetErrorStringWithFormat("unrecognized option '%c'",
2435 short_option);
2436 break;
2437 }
2438
2439 return error;
2440 }
2441
2442 void OptionParsingStarting(ExecutionContext *execution_context) override {
2443 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002444 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002445 }
2446
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002447 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002448 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002449 }
Jim Inghame14dc262016-09-12 23:10:56 +00002450
2451 // Instance variables to hold the values for command options.
2452
2453 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002454 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002455 };
2456
2457protected:
2458 bool DoExecute(Args &command, CommandReturnObject &result) override {
2459 Target *target = GetSelectedOrDummyTarget();
2460 if (target == nullptr) {
2461 result.AppendError("Invalid target. No existing target or breakpoints.");
2462 result.SetStatus(eReturnStatusFailed);
2463 return false;
2464 }
2465
Jim Inghame14dc262016-09-12 23:10:56 +00002466 std::unique_lock<std::recursive_mutex> lock;
2467 target->GetBreakpointList().GetListMutex(lock);
2468
Jim Ingham01f16662016-09-14 19:07:35 +00002469 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002470 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002471 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002472 command, target, result, &valid_bp_ids,
2473 BreakpointName::Permissions::PermissionKinds::listPerm);
Jim Inghame14dc262016-09-12 23:10:56 +00002474
Jim Ingham01f16662016-09-14 19:07:35 +00002475 if (!result.Succeeded()) {
2476 result.SetStatus(eReturnStatusFailed);
2477 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002478 }
2479 }
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002480 FileSpec file_spec(m_options.m_filename);
2481 FileSystem::Instance().Resolve(file_spec);
2482 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2483 m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002484 if (!error.Success()) {
2485 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2486 error.AsCString());
2487 result.SetStatus(eReturnStatusFailed);
2488 }
Jim Inghame14dc262016-09-12 23:10:56 +00002489 return result.Succeeded();
2490 }
2491
2492private:
2493 CommandOptions m_options;
2494};
2495
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002496// CommandObjectMultiwordBreakpoint
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002497#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002498
Kate Stoneb9c1b512016-09-06 20:57:50 +00002499CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2500 CommandInterpreter &interpreter)
2501 : CommandObjectMultiword(
2502 interpreter, "breakpoint",
2503 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2504 "breakpoint <subcommand> [<command-options>]") {
2505 CommandObjectSP list_command_object(
2506 new CommandObjectBreakpointList(interpreter));
2507 CommandObjectSP enable_command_object(
2508 new CommandObjectBreakpointEnable(interpreter));
2509 CommandObjectSP disable_command_object(
2510 new CommandObjectBreakpointDisable(interpreter));
2511 CommandObjectSP clear_command_object(
2512 new CommandObjectBreakpointClear(interpreter));
2513 CommandObjectSP delete_command_object(
2514 new CommandObjectBreakpointDelete(interpreter));
2515 CommandObjectSP set_command_object(
2516 new CommandObjectBreakpointSet(interpreter));
2517 CommandObjectSP command_command_object(
2518 new CommandObjectBreakpointCommand(interpreter));
2519 CommandObjectSP modify_command_object(
2520 new CommandObjectBreakpointModify(interpreter));
2521 CommandObjectSP name_command_object(
2522 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002523 CommandObjectSP write_command_object(
2524 new CommandObjectBreakpointWrite(interpreter));
2525 CommandObjectSP read_command_object(
2526 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002527
Kate Stoneb9c1b512016-09-06 20:57:50 +00002528 list_command_object->SetCommandName("breakpoint list");
2529 enable_command_object->SetCommandName("breakpoint enable");
2530 disable_command_object->SetCommandName("breakpoint disable");
2531 clear_command_object->SetCommandName("breakpoint clear");
2532 delete_command_object->SetCommandName("breakpoint delete");
2533 set_command_object->SetCommandName("breakpoint set");
2534 command_command_object->SetCommandName("breakpoint command");
2535 modify_command_object->SetCommandName("breakpoint modify");
2536 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002537 write_command_object->SetCommandName("breakpoint write");
2538 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002539
Kate Stoneb9c1b512016-09-06 20:57:50 +00002540 LoadSubCommand("list", list_command_object);
2541 LoadSubCommand("enable", enable_command_object);
2542 LoadSubCommand("disable", disable_command_object);
2543 LoadSubCommand("clear", clear_command_object);
2544 LoadSubCommand("delete", delete_command_object);
2545 LoadSubCommand("set", set_command_object);
2546 LoadSubCommand("command", command_command_object);
2547 LoadSubCommand("modify", modify_command_object);
2548 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002549 LoadSubCommand("write", write_command_object);
2550 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002551}
2552
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002553CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002554
Kate Stoneb9c1b512016-09-06 20:57:50 +00002555void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2556 bool allow_locations,
2557 CommandReturnObject &result,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002558 BreakpointIDList *valid_ids,
2559 BreakpointName::Permissions
2560 ::PermissionKinds
2561 purpose) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002562 // args can be strings representing 1). integers (for breakpoint ids)
2563 // 2). the full breakpoint & location
2564 // canonical representation
2565 // 3). the word "to" or a hyphen,
2566 // representing a range (in which case there
2567 // had *better* be an entry both before &
2568 // after of one of the first two types.
2569 // 4). A breakpoint name
2570 // If args is empty, we will use the last created breakpoint (if there is
2571 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002572
Kate Stoneb9c1b512016-09-06 20:57:50 +00002573 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002574
Zachary Turner11eb9c62016-10-05 20:03:37 +00002575 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002576 if (target->GetLastCreatedBreakpoint()) {
2577 valid_ids->AddBreakpointID(BreakpointID(
2578 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2579 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2580 } else {
2581 result.AppendError(
2582 "No breakpoint specified and no last created breakpoint.");
2583 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002584 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002585 return;
2586 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002587
Kate Stoneb9c1b512016-09-06 20:57:50 +00002588 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
Adrian Prantl05097242018-04-30 16:49:04 +00002589 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2590 // id range strings over; instead generate a list of strings for all the
2591 // breakpoint ids in the range, and shove all of those breakpoint id strings
2592 // into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002593
Jim Inghamb842f2e2017-09-14 20:22:49 +00002594 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2595 purpose, result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002596
Kate Stoneb9c1b512016-09-06 20:57:50 +00002597 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2598 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002599
Pavel Labath16662f32018-06-20 08:12:50 +00002600 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002601
Adrian Prantl05097242018-04-30 16:49:04 +00002602 // At this point, all of the breakpoint ids that the user passed in have
2603 // been converted to breakpoint IDs and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002604
Kate Stoneb9c1b512016-09-06 20:57:50 +00002605 if (result.Succeeded()) {
2606 // Now that we've converted everything from args into a list of breakpoint
Adrian Prantl05097242018-04-30 16:49:04 +00002607 // ids, go through our tentative list of breakpoint id's and verify that
2608 // they correspond to valid/currently set breakpoints.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002609
2610 const size_t count = valid_ids->GetSize();
2611 for (size_t i = 0; i < count; ++i) {
2612 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2613 Breakpoint *breakpoint =
2614 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2615 if (breakpoint != nullptr) {
2616 const size_t num_locations = breakpoint->GetNumLocations();
2617 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2618 StreamString id_str;
2619 BreakpointID::GetCanonicalReference(
2620 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2621 i = valid_ids->GetSize() + 1;
2622 result.AppendErrorWithFormat(
2623 "'%s' is not a currently valid breakpoint/location id.\n",
2624 id_str.GetData());
2625 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002626 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002627 } else {
2628 i = valid_ids->GetSize() + 1;
2629 result.AppendErrorWithFormat(
2630 "'%d' is not a currently valid breakpoint ID.\n",
2631 cur_bp_id.GetBreakpointID());
2632 result.SetStatus(eReturnStatusFailed);
2633 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002634 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002635 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002636}