180814287SRaphael Isemann //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner
99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h"
109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h"
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h"
1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
16*7ced9fffSJonas Devlieghere #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
1847cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
19943a2481SJim Ingham #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
2032abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
21bc0a9a17SJim Ingham #include "lldb/Interpreter/OptionValueFileColonLine.h"
225e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
235e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
24b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
250e0984eeSJim Ingham #include "lldb/Target/Language.h"
26b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
27b9c1b51eSKate Stone #include "lldb/Target/Target.h"
281b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
29bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
30bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3130fdc8d8SChris Lattner
32796ac80bSJonas Devlieghere #include <memory>
33796ac80bSJonas Devlieghere #include <vector>
34796ac80bSJonas Devlieghere
3530fdc8d8SChris Lattner using namespace lldb;
3630fdc8d8SChris Lattner using namespace lldb_private;
3730fdc8d8SChris Lattner
AddBreakpointDescription(Stream * s,Breakpoint * bp,lldb::DescriptionLevel level)38b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
39b9c1b51eSKate Stone lldb::DescriptionLevel level) {
4030fdc8d8SChris Lattner s->IndentMore();
4130fdc8d8SChris Lattner bp->GetDescription(s, level, true);
4230fdc8d8SChris Lattner s->IndentLess();
4330fdc8d8SChris Lattner s->EOL();
4430fdc8d8SChris Lattner }
4530fdc8d8SChris Lattner
46b842f2ecSJim Ingham // Modifiable Breakpoint Options
47b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
48f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
49f94668e3SRaphael Isemann #include "CommandOptions.inc"
50bd68a052SRaphael Isemann
51a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup {
52b842f2ecSJim Ingham public:
BreakpointOptionGroup()53abb0ed44SKazu Hirata BreakpointOptionGroup() : m_bp_opts(false) {}
54b842f2ecSJim Ingham
55b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default;
56b842f2ecSJim Ingham
GetDefinitions()57b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
58b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options);
59b842f2ecSJim Ingham }
60b842f2ecSJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)61b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
62b842f2ecSJim Ingham ExecutionContext *execution_context) override {
63b842f2ecSJim Ingham Status error;
64a925974bSAdrian Prantl const int short_option =
65a925974bSAdrian Prantl g_breakpoint_modify_options[option_idx].short_option;
66b842f2ecSJim Ingham
67b842f2ecSJim Ingham switch (short_option) {
68b842f2ecSJim Ingham case 'c':
6905097246SAdrian Prantl // Normally an empty breakpoint condition marks is as unset. But we need
7005097246SAdrian Prantl // to say it was passed in.
71b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str());
72b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
73b842f2ecSJim Ingham break;
74b842f2ecSJim Ingham case 'C':
75adcd0268SBenjamin Kramer m_commands.push_back(std::string(option_arg));
76b842f2ecSJim Ingham break;
77b842f2ecSJim Ingham case 'd':
78b842f2ecSJim Ingham m_bp_opts.SetEnabled(false);
79b842f2ecSJim Ingham break;
80b842f2ecSJim Ingham case 'e':
81b842f2ecSJim Ingham m_bp_opts.SetEnabled(true);
82b842f2ecSJim Ingham break;
83b842f2ecSJim Ingham case 'G': {
84b842f2ecSJim Ingham bool value, success;
8547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success);
86b842f2ecSJim Ingham if (success) {
87b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value);
88b842f2ecSJim Ingham } else
89b842f2ecSJim Ingham error.SetErrorStringWithFormat(
90b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option",
91b842f2ecSJim Ingham option_arg.str().c_str());
92a925974bSAdrian Prantl } break;
93a925974bSAdrian Prantl case 'i': {
94b842f2ecSJim Ingham uint32_t ignore_count;
95b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count))
96b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'",
97b842f2ecSJim Ingham option_arg.str().c_str());
98b842f2ecSJim Ingham else
99b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count);
100a925974bSAdrian Prantl } break;
101b842f2ecSJim Ingham case 'o': {
102b842f2ecSJim Ingham bool value, success;
10347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success);
104b842f2ecSJim Ingham if (success) {
105b842f2ecSJim Ingham m_bp_opts.SetOneShot(value);
106b842f2ecSJim Ingham } else
107b842f2ecSJim Ingham error.SetErrorStringWithFormat(
108b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option",
109b842f2ecSJim Ingham option_arg.str().c_str());
110b842f2ecSJim Ingham } break;
111a925974bSAdrian Prantl case 't': {
112b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
113b842f2ecSJim Ingham if (option_arg[0] != '\0') {
114f362b05dSJim Ingham if (option_arg == "current") {
115f362b05dSJim Ingham if (!execution_context) {
116f362b05dSJim Ingham error.SetErrorStringWithFormat("No context to determine current "
117f362b05dSJim Ingham "thread");
118f362b05dSJim Ingham } else {
119f362b05dSJim Ingham ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
120f362b05dSJim Ingham if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
121f362b05dSJim Ingham error.SetErrorStringWithFormat("No currently selected thread");
122f362b05dSJim Ingham } else {
123f362b05dSJim Ingham thread_id = ctx_thread_sp->GetID();
124f362b05dSJim Ingham }
125f362b05dSJim Ingham }
126f362b05dSJim Ingham } else if (option_arg.getAsInteger(0, thread_id))
127b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'",
128b842f2ecSJim Ingham option_arg.str().c_str());
129b842f2ecSJim Ingham }
130b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id);
131a925974bSAdrian Prantl } break;
132b842f2ecSJim Ingham case 'T':
133b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
134b842f2ecSJim Ingham break;
135b842f2ecSJim Ingham case 'q':
136b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
137b842f2ecSJim Ingham break;
138a925974bSAdrian Prantl case 'x': {
139b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX;
140b842f2ecSJim Ingham if (option_arg[0] != '\n') {
141b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index))
142b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'",
143b842f2ecSJim Ingham option_arg.str().c_str());
144b842f2ecSJim Ingham }
145b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
146a925974bSAdrian Prantl } break;
147b842f2ecSJim Ingham default:
14836162014SRaphael Isemann llvm_unreachable("Unimplemented option");
149b842f2ecSJim Ingham }
150b842f2ecSJim Ingham
151b842f2ecSJim Ingham return error;
152b842f2ecSJim Ingham }
153b842f2ecSJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)154b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override {
155b842f2ecSJim Ingham m_bp_opts.Clear();
156b842f2ecSJim Ingham m_commands.clear();
157b842f2ecSJim Ingham }
158b842f2ecSJim Ingham
OptionParsingFinished(ExecutionContext * execution_context)159b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override {
160a925974bSAdrian Prantl if (!m_commands.empty()) {
161a8f3ae7cSJonas Devlieghere auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
162b842f2ecSJim Ingham
163b842f2ecSJim Ingham for (std::string &str : m_commands)
164b842f2ecSJim Ingham cmd_data->user_source.AppendString(str);
165b842f2ecSJim Ingham
166b842f2ecSJim Ingham cmd_data->stop_on_error = true;
167b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data);
168b842f2ecSJim Ingham }
169b842f2ecSJim Ingham return Status();
170b842f2ecSJim Ingham }
171b842f2ecSJim Ingham
GetBreakpointOptions()172a925974bSAdrian Prantl const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
173b842f2ecSJim Ingham
174b842f2ecSJim Ingham std::vector<std::string> m_commands;
175b842f2ecSJim Ingham BreakpointOptions m_bp_opts;
176b842f2ecSJim Ingham };
177bd68a052SRaphael Isemann
178f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
179f94668e3SRaphael Isemann #include "CommandOptions.inc"
180b842f2ecSJim Ingham
181a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup {
182b842f2ecSJim Ingham public:
18324f9a2f5SShafik Yaghmour BreakpointDummyOptionGroup() = default;
184b842f2ecSJim Ingham
185b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default;
186b842f2ecSJim Ingham
GetDefinitions()187b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
188b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options);
189b842f2ecSJim Ingham }
190b842f2ecSJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)191b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
192b842f2ecSJim Ingham ExecutionContext *execution_context) override {
193b842f2ecSJim Ingham Status error;
194a925974bSAdrian Prantl const int short_option =
195f1539b9dSJim Ingham g_breakpoint_dummy_options[option_idx].short_option;
196b842f2ecSJim Ingham
197b842f2ecSJim Ingham switch (short_option) {
198b842f2ecSJim Ingham case 'D':
199b842f2ecSJim Ingham m_use_dummy = true;
200b842f2ecSJim Ingham break;
201b842f2ecSJim Ingham default:
20236162014SRaphael Isemann llvm_unreachable("Unimplemented option");
203b842f2ecSJim Ingham }
204b842f2ecSJim Ingham
205b842f2ecSJim Ingham return error;
206b842f2ecSJim Ingham }
207b842f2ecSJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)208b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override {
209b842f2ecSJim Ingham m_use_dummy = false;
210b842f2ecSJim Ingham }
211b842f2ecSJim Ingham
212b842f2ecSJim Ingham bool m_use_dummy;
213b842f2ecSJim Ingham };
214b842f2ecSJim Ingham
215f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
216f94668e3SRaphael Isemann #include "CommandOptions.inc"
2171f0f5b5bSZachary Turner
2185a988416SJim Ingham // CommandObjectBreakpointSet
21930fdc8d8SChris Lattner
220b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2215a988416SJim Ingham public:
222efe8e7e3SFangrui Song enum BreakpointSetType {
2235a988416SJim Ingham eSetTypeInvalid,
2245a988416SJim Ingham eSetTypeFileAndLine,
2255a988416SJim Ingham eSetTypeAddress,
2265a988416SJim Ingham eSetTypeFunctionName,
2275a988416SJim Ingham eSetTypeFunctionRegexp,
2285a988416SJim Ingham eSetTypeSourceRegexp,
2293815e702SJim Ingham eSetTypeException,
2303815e702SJim Ingham eSetTypeScripted,
231efe8e7e3SFangrui Song };
2325a988416SJim Ingham
CommandObjectBreakpointSet(CommandInterpreter & interpreter)233b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter)
234b9c1b51eSKate Stone : CommandObjectParsed(
235b9c1b51eSKate Stone interpreter, "breakpoint set",
2365a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.",
2375a988416SJim Ingham "breakpoint set <cmd-options>"),
238abb0ed44SKazu Hirata m_python_class_options("scripted breakpoint", true, 'P') {
239b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable.
240a925974bSAdrian Prantl m_all_options.Append(&m_python_class_options,
241a925974bSAdrian Prantl LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
242b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts,
243b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
244b842f2ecSJim Ingham LLDB_OPT_SET_ALL);
245f6a2086dSSam McCall m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
246b842f2ecSJim Ingham m_all_options.Append(&m_options);
247b842f2ecSJim Ingham m_all_options.Finalize();
248b842f2ecSJim Ingham }
2495a988416SJim Ingham
2509e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default;
2515a988416SJim Ingham
GetOptions()252b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; }
2535a988416SJim Ingham
254b842f2ecSJim Ingham class CommandOptions : public OptionGroup {
2555a988416SJim Ingham public:
25624f9a2f5SShafik Yaghmour CommandOptions() = default;
25730fdc8d8SChris Lattner
2589e85e5a8SEugene Zelenko ~CommandOptions() override = default;
25987df91b8SJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)26097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
261b9c1b51eSKate Stone ExecutionContext *execution_context) override {
26297206d57SZachary Turner Status error;
263a925974bSAdrian Prantl const int short_option =
264a925974bSAdrian Prantl g_breakpoint_set_options[option_idx].short_option;
26530fdc8d8SChris Lattner
266b9c1b51eSKate Stone switch (short_option) {
267b9c1b51eSKate Stone case 'a': {
26847cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
269e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error);
270b9c1b51eSKate Stone } break;
27130fdc8d8SChris Lattner
272e732052fSJim Ingham case 'A':
273e732052fSJim Ingham m_all_files = true;
274e732052fSJim Ingham break;
275e732052fSJim Ingham
276ca36cd16SJim Ingham case 'b':
277adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg));
278ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase;
279ca36cd16SJim Ingham break;
280ca36cd16SJim Ingham
2816672a4f5SJonas Devlieghere case 'u':
282fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column))
283b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s",
284fe11483bSZachary Turner option_arg.str().c_str());
28530fdc8d8SChris Lattner break;
2869e85e5a8SEugene Zelenko
287b9c1b51eSKate Stone case 'E': {
288fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg);
289fab10e89SJim Ingham
290b9c1b51eSKate Stone switch (language) {
291fab10e89SJim Ingham case eLanguageTypeC89:
292fab10e89SJim Ingham case eLanguageTypeC:
293fab10e89SJim Ingham case eLanguageTypeC99:
2941d0089faSBruce Mitchener case eLanguageTypeC11:
295a72b31c7SJim Ingham m_exception_language = eLanguageTypeC;
296fab10e89SJim Ingham break;
297fab10e89SJim Ingham case eLanguageTypeC_plus_plus:
2981d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03:
2991d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11:
3002ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14:
301a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus;
302fab10e89SJim Ingham break;
303fab10e89SJim Ingham case eLanguageTypeObjC:
304a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC;
305fab10e89SJim Ingham break;
306fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus:
307b9c1b51eSKate Stone error.SetErrorStringWithFormat(
308b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c");
309fab10e89SJim Ingham break;
310fab10e89SJim Ingham case eLanguageTypeUnknown:
311b9c1b51eSKate Stone error.SetErrorStringWithFormat(
312b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint",
313fe11483bSZachary Turner option_arg.str().c_str());
314fab10e89SJim Ingham break;
315fab10e89SJim Ingham default:
316b9c1b51eSKate Stone error.SetErrorStringWithFormat(
317b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint",
318fe11483bSZachary Turner option_arg.str().c_str());
319fab10e89SJim Ingham }
320b9c1b51eSKate Stone } break;
321ca36cd16SJim Ingham
322ca36cd16SJim Ingham case 'f':
3238f3be7a3SJonas Devlieghere m_filenames.AppendIfUnique(FileSpec(option_arg));
324fab10e89SJim Ingham break;
325ca36cd16SJim Ingham
326ca36cd16SJim Ingham case 'F':
327adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg));
328ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull;
329ca36cd16SJim Ingham break;
330ca36cd16SJim Ingham
331b9c1b51eSKate Stone case 'h': {
332fab10e89SJim Ingham bool success;
33347cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
334fab10e89SJim Ingham if (!success)
335b9c1b51eSKate Stone error.SetErrorStringWithFormat(
336fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'",
337fe11483bSZachary Turner option_arg.str().c_str());
338b9c1b51eSKate Stone } break;
339eb023e75SGreg Clayton
340eb023e75SGreg Clayton case 'H':
341eb023e75SGreg Clayton m_hardware = true;
342eb023e75SGreg Clayton break;
343eb023e75SGreg Clayton
344b9c1b51eSKate Stone case 'K': {
345a8558b62SJim Ingham bool success;
346a8558b62SJim Ingham bool value;
34747cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success);
348a8558b62SJim Ingham if (value)
349a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes;
350a8558b62SJim Ingham else
351a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo;
352a8558b62SJim Ingham
353a8558b62SJim Ingham if (!success)
354b9c1b51eSKate Stone error.SetErrorStringWithFormat(
355b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'",
356fe11483bSZachary Turner option_arg.str().c_str());
357b9c1b51eSKate Stone } break;
358ca36cd16SJim Ingham
359fe11483bSZachary Turner case 'l':
360fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num))
361b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.",
362fe11483bSZachary Turner option_arg.str().c_str());
363ca36cd16SJim Ingham break;
364055ad9beSIlia K
36523b1decbSDawn Perchik case 'L':
366fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg);
36723b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown)
368b9c1b51eSKate Stone error.SetErrorStringWithFormat(
369fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint",
370fe11483bSZachary Turner option_arg.str().c_str());
37123b1decbSDawn Perchik break;
37223b1decbSDawn Perchik
373b9c1b51eSKate Stone case 'm': {
374055ad9beSIlia K bool success;
375055ad9beSIlia K bool value;
37647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success);
377055ad9beSIlia K if (value)
378055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes;
379055ad9beSIlia K else
380055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo;
381055ad9beSIlia K
382055ad9beSIlia K if (!success)
383b9c1b51eSKate Stone error.SetErrorStringWithFormat(
384b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'",
385fe11483bSZachary Turner option_arg.str().c_str());
386055ad9beSIlia K break;
387055ad9beSIlia K }
388055ad9beSIlia K
389ca36cd16SJim Ingham case 'M':
390adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg));
391ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod;
392ca36cd16SJim Ingham break;
393ca36cd16SJim Ingham
394ca36cd16SJim Ingham case 'n':
395adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg));
396ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto;
397ca36cd16SJim Ingham break;
398ca36cd16SJim Ingham
3996fa7681bSZachary Turner case 'N': {
400fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error))
401adcd0268SBenjamin Kramer m_breakpoint_names.push_back(std::string(option_arg));
402ff9a91eaSJim Ingham else
403ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
404fe11483bSZachary Turner option_arg.str().c_str());
4055e09c8c3SJim Ingham break;
4066fa7681bSZachary Turner }
4075e09c8c3SJim Ingham
408b9c1b51eSKate Stone case 'R': {
4092411167fSJim Ingham lldb::addr_t tmp_offset_addr;
41047cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
41147cbf4a0SPavel Labath option_arg, 0, &error);
4122411167fSJim Ingham if (error.Success())
4132411167fSJim Ingham m_offset_addr = tmp_offset_addr;
414b9c1b51eSKate Stone } break;
4152411167fSJim Ingham
416a72b31c7SJim Ingham case 'O':
417fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O");
418fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg);
419a72b31c7SJim Ingham break;
420a72b31c7SJim Ingham
421ca36cd16SJim Ingham case 'p':
422adcd0268SBenjamin Kramer m_source_text_regexp.assign(std::string(option_arg));
423ca36cd16SJim Ingham break;
424ca36cd16SJim Ingham
425ca36cd16SJim Ingham case 'r':
426adcd0268SBenjamin Kramer m_func_regexp.assign(std::string(option_arg));
427ca36cd16SJim Ingham break;
428ca36cd16SJim Ingham
429ca36cd16SJim Ingham case 's':
4308f3be7a3SJonas Devlieghere m_modules.AppendIfUnique(FileSpec(option_arg));
431ca36cd16SJim Ingham break;
432ca36cd16SJim Ingham
433ca36cd16SJim Ingham case 'S':
434adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg));
435ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector;
436ca36cd16SJim Ingham break;
437ca36cd16SJim Ingham
438b9c1b51eSKate Stone case 'w': {
439ca36cd16SJim Ingham bool success;
44047cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
441ca36cd16SJim Ingham if (!success)
442b9c1b51eSKate Stone error.SetErrorStringWithFormat(
443fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'",
444fe11483bSZachary Turner option_arg.str().c_str());
445b9c1b51eSKate Stone } break;
446ca36cd16SJim Ingham
44776bb8d67SJim Ingham case 'X':
448adcd0268SBenjamin Kramer m_source_regex_func_names.insert(std::string(option_arg));
44976bb8d67SJim Ingham break;
45076bb8d67SJim Ingham
451bc0a9a17SJim Ingham case 'y':
452bc0a9a17SJim Ingham {
453bc0a9a17SJim Ingham OptionValueFileColonLine value;
454bc0a9a17SJim Ingham Status fcl_err = value.SetValueFromString(option_arg);
455bc0a9a17SJim Ingham if (!fcl_err.Success()) {
456bc0a9a17SJim Ingham error.SetErrorStringWithFormat(
457bc0a9a17SJim Ingham "Invalid value for file:line specifier: %s",
458bc0a9a17SJim Ingham fcl_err.AsCString());
459bc0a9a17SJim Ingham } else {
460bc0a9a17SJim Ingham m_filenames.AppendIfUnique(value.GetFileSpec());
461bc0a9a17SJim Ingham m_line_num = value.GetLineNumber();
462bc0a9a17SJim Ingham m_column = value.GetColumnNumber();
463bc0a9a17SJim Ingham }
464bc0a9a17SJim Ingham } break;
465bc0a9a17SJim Ingham
46630fdc8d8SChris Lattner default:
46736162014SRaphael Isemann llvm_unreachable("Unimplemented option");
46830fdc8d8SChris Lattner }
46930fdc8d8SChris Lattner
47030fdc8d8SChris Lattner return error;
47130fdc8d8SChris Lattner }
4729e85e5a8SEugene Zelenko
OptionParsingStarting(ExecutionContext * execution_context)473b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override {
47487df91b8SJim Ingham m_filenames.Clear();
47530fdc8d8SChris Lattner m_line_num = 0;
47630fdc8d8SChris Lattner m_column = 0;
477fab10e89SJim Ingham m_func_names.clear();
4781f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone;
47930fdc8d8SChris Lattner m_func_regexp.clear();
4801f746071SGreg Clayton m_source_text_regexp.clear();
48187df91b8SJim Ingham m_modules.Clear();
4821f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS;
4832411167fSJim Ingham m_offset_addr = 0;
484fab10e89SJim Ingham m_catch_bp = false;
485fab10e89SJim Ingham m_throw_bp = true;
486eb023e75SGreg Clayton m_hardware = false;
487a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown;
48823b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown;
489a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate;
4905e09c8c3SJim Ingham m_breakpoint_names.clear();
491e732052fSJim Ingham m_all_files = false;
492a72b31c7SJim Ingham m_exception_extra_args.Clear();
493055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate;
49476bb8d67SJim Ingham m_source_regex_func_names.clear();
4953815e702SJim Ingham m_current_key.clear();
49630fdc8d8SChris Lattner }
49730fdc8d8SChris Lattner
GetDefinitions()4981f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
49970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options);
5001f0f5b5bSZachary Turner }
50130fdc8d8SChris Lattner
5025a988416SJim Ingham // Instance variables to hold the values for command options.
503969795f1SJim Ingham
5045a988416SJim Ingham std::string m_condition;
5055a988416SJim Ingham FileSpecList m_filenames;
5069494c510SJonas Devlieghere uint32_t m_line_num = 0;
5079494c510SJonas Devlieghere uint32_t m_column = 0;
5085a988416SJim Ingham std::vector<std::string> m_func_names;
5095e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names;
5109494c510SJonas Devlieghere lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
5115a988416SJim Ingham std::string m_func_regexp;
5125a988416SJim Ingham std::string m_source_text_regexp;
5135a988416SJim Ingham FileSpecList m_modules;
5149494c510SJonas Devlieghere lldb::addr_t m_load_addr = 0;
5152411167fSJim Ingham lldb::addr_t m_offset_addr;
5169494c510SJonas Devlieghere bool m_catch_bp = false;
5179494c510SJonas Devlieghere bool m_throw_bp = true;
5189494c510SJonas Devlieghere bool m_hardware = false; // Request to use hardware breakpoints
5199494c510SJonas Devlieghere lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
5209494c510SJonas Devlieghere lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
5219494c510SJonas Devlieghere LazyBool m_skip_prologue = eLazyBoolCalculate;
5229494c510SJonas Devlieghere bool m_all_files = false;
523a72b31c7SJim Ingham Args m_exception_extra_args;
5249494c510SJonas Devlieghere LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
52576bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names;
5263815e702SJim Ingham std::string m_current_key;
5275a988416SJim Ingham };
5285a988416SJim Ingham
5295a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)530b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
531cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
53230fdc8d8SChris Lattner
53330fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set:
53430fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location)
53530fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address)
53630fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name)
537b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular
538b9c1b51eSKate Stone // expression)
539b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp
540b9c1b51eSKate Stone // to source text)
541b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a
542b9c1b51eSKate Stone // given language.)
54330fdc8d8SChris Lattner
54430fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid;
54530fdc8d8SChris Lattner
546738af7a6SJim Ingham if (!m_python_class_options.GetName().empty())
5473815e702SJim Ingham break_type = eSetTypeScripted;
5483815e702SJim Ingham else if (m_options.m_line_num != 0)
54930fdc8d8SChris Lattner break_type = eSetTypeFileAndLine;
55030fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
55130fdc8d8SChris Lattner break_type = eSetTypeAddress;
552fab10e89SJim Ingham else if (!m_options.m_func_names.empty())
55330fdc8d8SChris Lattner break_type = eSetTypeFunctionName;
55430fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty())
55530fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp;
556969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty())
557969795f1SJim Ingham break_type = eSetTypeSourceRegexp;
558a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown)
559fab10e89SJim Ingham break_type = eSetTypeException;
56030fdc8d8SChris Lattner
561b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr;
562274060b6SGreg Clayton FileSpec module_spec;
563a8558b62SJim Ingham const bool internal = false;
564a8558b62SJim Ingham
565b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn
566b9c1b51eSKate Stone // that off.
567b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 &&
568b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate)
5692411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo;
5702411167fSJim Ingham
571b9c1b51eSKate Stone switch (break_type) {
57230fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position
57330fdc8d8SChris Lattner {
57430fdc8d8SChris Lattner FileSpec file;
575c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize();
576b9c1b51eSKate Stone if (num_files == 0) {
577b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) {
57887df91b8SJim Ingham result.AppendError("No file supplied and no default file available.");
57987df91b8SJim Ingham return false;
58087df91b8SJim Ingham }
581b9c1b51eSKate Stone } else if (num_files > 1) {
582b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and "
583b9c1b51eSKate Stone "line breakpoints.");
58487df91b8SJim Ingham return false;
585b9c1b51eSKate Stone } else
58687df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0);
58730fdc8d8SChris Lattner
5881f746071SGreg Clayton // Only check for inline functions if
5891f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate;
5901f746071SGreg Clayton
591cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint(
592cb2380c9SRaphael Isemann &(m_options.m_modules), file, m_options.m_line_num,
593cb2380c9SRaphael Isemann m_options.m_column, m_options.m_offset_addr, check_inlines,
594cb2380c9SRaphael Isemann m_options.m_skip_prologue, internal, m_options.m_hardware,
595b842f2ecSJim Ingham m_options.m_move_to_nearest_code);
596b9c1b51eSKate Stone } break;
5976eee5aa0SGreg Clayton
59830fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address
599055a08a4SJim Ingham {
600b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address
601b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint
602b842f2ecSJim Ingham // will track the load location of the library.
603055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize();
604b9c1b51eSKate Stone if (num_modules_specified == 1) {
605b9c1b51eSKate Stone const FileSpec *file_spec =
606b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0);
607cb2380c9SRaphael Isemann bp_sp = target.CreateAddressInModuleBreakpoint(
608cb2380c9SRaphael Isemann m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
609b9c1b51eSKate Stone } else if (num_modules_specified == 0) {
610cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
611b842f2ecSJim Ingham m_options.m_hardware);
612b9c1b51eSKate Stone } else {
613b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for "
614b9c1b51eSKate Stone "address breakpoints.");
615055a08a4SJim Ingham return false;
616055a08a4SJim Ingham }
61730fdc8d8SChris Lattner break;
618055a08a4SJim Ingham }
61930fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name
6200c5cd90dSGreg Clayton {
621117b1fa1SZachary Turner FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6220c5cd90dSGreg Clayton
6230c5cd90dSGreg Clayton if (name_type_mask == 0)
624e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto;
6250c5cd90dSGreg Clayton
626cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint(
627cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames),
628cb2380c9SRaphael Isemann m_options.m_func_names, name_type_mask, m_options.m_language,
629cb2380c9SRaphael Isemann m_options.m_offset_addr, m_options.m_skip_prologue, internal,
630b842f2ecSJim Ingham m_options.m_hardware);
631b9c1b51eSKate Stone } break;
6320c5cd90dSGreg Clayton
633b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
634b9c1b51eSKate Stone // name
63530fdc8d8SChris Lattner {
63695eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp);
6373af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) {
638b9c1b51eSKate Stone result.AppendErrorWithFormat(
639b58af8d2SRaphael Isemann "Function name regular expression could not be compiled: %s",
6403af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str());
641aaf68cd9SRaphael Isemann // Check if the incorrect regex looks like a globbing expression and
642aaf68cd9SRaphael Isemann // warn the user about it.
643aaf68cd9SRaphael Isemann if (!m_options.m_func_regexp.empty()) {
644aaf68cd9SRaphael Isemann if (m_options.m_func_regexp[0] == '*' ||
645aaf68cd9SRaphael Isemann m_options.m_func_regexp[0] == '?')
646aaf68cd9SRaphael Isemann result.AppendWarning(
647aaf68cd9SRaphael Isemann "Function name regex does not accept glob patterns.");
648aaf68cd9SRaphael Isemann }
649969795f1SJim Ingham return false;
65030fdc8d8SChris Lattner }
65187df91b8SJim Ingham
652cb2380c9SRaphael Isemann bp_sp = target.CreateFuncRegexBreakpoint(
6535aa1d819SJan Kratochvil &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
654cb2380c9SRaphael Isemann m_options.m_language, m_options.m_skip_prologue, internal,
655b842f2ecSJim Ingham m_options.m_hardware);
656a925974bSAdrian Prantl } break;
657969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
658969795f1SJim Ingham {
659c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize();
66087df91b8SJim Ingham
661b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) {
662969795f1SJim Ingham FileSpec file;
663b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) {
664b9c1b51eSKate Stone result.AppendError(
665b9c1b51eSKate Stone "No files provided and could not find default file.");
66687df91b8SJim Ingham return false;
667b9c1b51eSKate Stone } else {
66887df91b8SJim Ingham m_options.m_filenames.Append(file);
66987df91b8SJim Ingham }
67087df91b8SJim Ingham }
6710c5cd90dSGreg Clayton
67295eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp);
6733af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) {
674b9c1b51eSKate Stone result.AppendErrorWithFormat(
675b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"",
6763af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str());
677969795f1SJim Ingham return false;
678969795f1SJim Ingham }
679cb2380c9SRaphael Isemann bp_sp = target.CreateSourceRegexBreakpoint(
680cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames),
6815aa1d819SJan Kratochvil m_options.m_source_regex_func_names, std::move(regexp), internal,
682cb2380c9SRaphael Isemann m_options.m_hardware, m_options.m_move_to_nearest_code);
683b9c1b51eSKate Stone } break;
684b9c1b51eSKate Stone case eSetTypeException: {
68597206d57SZachary Turner Status precond_error;
686cb2380c9SRaphael Isemann bp_sp = target.CreateExceptionBreakpoint(
687cb2380c9SRaphael Isemann m_options.m_exception_language, m_options.m_catch_bp,
688cb2380c9SRaphael Isemann m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
689b842f2ecSJim Ingham &precond_error);
690b9c1b51eSKate Stone if (precond_error.Fail()) {
691b9c1b51eSKate Stone result.AppendErrorWithFormat(
692b9c1b51eSKate Stone "Error setting extra exception arguments: %s",
693a72b31c7SJim Ingham precond_error.AsCString());
694cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID());
695a72b31c7SJim Ingham return false;
696a72b31c7SJim Ingham }
697b9c1b51eSKate Stone } break;
6983815e702SJim Ingham case eSetTypeScripted: {
6993815e702SJim Ingham
7003815e702SJim Ingham Status error;
701cb2380c9SRaphael Isemann bp_sp = target.CreateScriptedBreakpoint(
702738af7a6SJim Ingham m_python_class_options.GetName().c_str(), &(m_options.m_modules),
703cb2380c9SRaphael Isemann &(m_options.m_filenames), false, m_options.m_hardware,
704943a2481SJim Ingham m_python_class_options.GetStructuredData(), &error);
7053815e702SJim Ingham if (error.Fail()) {
7063815e702SJim Ingham result.AppendErrorWithFormat(
707a925974bSAdrian Prantl "Error setting extra exception arguments: %s", error.AsCString());
708cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID());
7093815e702SJim Ingham return false;
7103815e702SJim Ingham }
7113815e702SJim Ingham } break;
71230fdc8d8SChris Lattner default:
71330fdc8d8SChris Lattner break;
71430fdc8d8SChris Lattner }
71530fdc8d8SChris Lattner
7161b54c88cSJim Ingham // Now set the various options that were passed in:
717b842f2ecSJim Ingham if (bp_sp) {
718cfb96d84SJim Ingham bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
719ca36cd16SJim Ingham
720b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) {
72197206d57SZachary Turner Status name_error;
722ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) {
723cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
724ff9a91eaSJim Ingham if (name_error.Fail()) {
725ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s",
726ff9a91eaSJim Ingham name.c_str());
727cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID());
728ff9a91eaSJim Ingham return false;
729ff9a91eaSJim Ingham }
730ff9a91eaSJim Ingham }
7315e09c8c3SJim Ingham }
7321b54c88cSJim Ingham }
7331b54c88cSJim Ingham
734b842f2ecSJim Ingham if (bp_sp) {
73585e8b814SJim Ingham Stream &output_stream = result.GetOutputStream();
7361391cc7dSJim Ingham const bool show_locations = false;
737b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
738b9c1b51eSKate Stone show_locations);
739cb2380c9SRaphael Isemann if (&target == &GetDummyTarget())
740b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied "
741b9c1b51eSKate Stone "into future targets.\n");
742b9c1b51eSKate Stone else {
74305097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can
74405097246SAdrian Prantl // get set before the target is set, but we won't know how to actually
74505097246SAdrian Prantl // set the breakpoint till we run.
746b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
747b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
748b9c1b51eSKate Stone "actual locations.\n");
7494aeb1989SJim Ingham }
7504aeb1989SJim Ingham }
75130fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult);
752b842f2ecSJim Ingham } else if (!bp_sp) {
75330fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created.");
75430fdc8d8SChris Lattner }
75530fdc8d8SChris Lattner
75630fdc8d8SChris Lattner return result.Succeeded();
75730fdc8d8SChris Lattner }
75830fdc8d8SChris Lattner
7595a988416SJim Ingham private:
GetDefaultFile(Target & target,FileSpec & file,CommandReturnObject & result)760cb2380c9SRaphael Isemann bool GetDefaultFile(Target &target, FileSpec &file,
761b9c1b51eSKate Stone CommandReturnObject &result) {
7625a988416SJim Ingham uint32_t default_line;
76305097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack
76405097246SAdrian Prantl // frame's file.
765cb2380c9SRaphael Isemann if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
766b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
767b9c1b51eSKate Stone if (cur_frame == nullptr) {
768b9c1b51eSKate Stone result.AppendError(
769b9c1b51eSKate Stone "No selected frame to use to find the default file.");
7705a988416SJim Ingham return false;
771b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) {
772b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default "
773b9c1b51eSKate Stone "file, it has no debug info.");
7745a988416SJim Ingham return false;
775b9c1b51eSKate Stone } else {
776b9c1b51eSKate Stone const SymbolContext &sc =
777b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry);
778b9c1b51eSKate Stone if (sc.line_entry.file) {
7795a988416SJim Ingham file = sc.line_entry.file;
780b9c1b51eSKate Stone } else {
781b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to "
782b9c1b51eSKate Stone "use as the default file.");
7835a988416SJim Ingham return false;
7845a988416SJim Ingham }
7855a988416SJim Ingham }
7865a988416SJim Ingham }
7875a988416SJim Ingham return true;
7885a988416SJim Ingham }
7895a988416SJim Ingham
790b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts;
791b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options;
792943a2481SJim Ingham OptionGroupPythonClassWithDict m_python_class_options;
7935a988416SJim Ingham CommandOptions m_options;
794b842f2ecSJim Ingham OptionGroupOptions m_all_options;
7955a988416SJim Ingham };
7969e85e5a8SEugene Zelenko
7975a988416SJim Ingham // CommandObjectBreakpointModify
7985a988416SJim Ingham #pragma mark Modify
7995a988416SJim Ingham
800b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8015a988416SJim Ingham public:
CommandObjectBreakpointModify(CommandInterpreter & interpreter)802b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter)
803b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify",
804b9c1b51eSKate Stone "Modify the options on a breakpoint or set of "
805b9c1b51eSKate Stone "breakpoints in the executable. "
806b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last "
807b9c1b51eSKate Stone "created breakpoint. "
808b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an "
809b9c1b51eSKate Stone "empty argument clears the modification.",
810abb0ed44SKazu Hirata nullptr) {
8115a988416SJim Ingham CommandArgumentEntry arg;
812b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
813b9c1b51eSKate Stone eArgTypeBreakpointIDRange);
814b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's
815b9c1b51eSKate Stone // arguments vector.
8165a988416SJim Ingham m_arguments.push_back(arg);
817b842f2ecSJim Ingham
818b842f2ecSJim Ingham m_options.Append(&m_bp_opts,
819b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
820b842f2ecSJim Ingham LLDB_OPT_SET_ALL);
821b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
822b842f2ecSJim Ingham m_options.Finalize();
8235a988416SJim Ingham }
8245a988416SJim Ingham
8259e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default;
8265a988416SJim Ingham
8270e50b9a4SGongyu Deng void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)8280e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request,
8290e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override {
8300e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
8310e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8320e50b9a4SGongyu Deng request, nullptr);
8330e50b9a4SGongyu Deng }
8340e50b9a4SGongyu Deng
GetOptions()835b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; }
8365a988416SJim Ingham
8375a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)838b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
839cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8405a988416SJim Ingham
841bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
842cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
8435a988416SJim Ingham
8445a988416SJim Ingham BreakpointIDList valid_bp_ids;
8455a988416SJim Ingham
846b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
847cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
848b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm);
8495a988416SJim Ingham
850b9c1b51eSKate Stone if (result.Succeeded()) {
8515a988416SJim Ingham const size_t count = valid_bp_ids.GetSize();
852b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) {
8535a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8545a988416SJim Ingham
855b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
856b9c1b51eSKate Stone Breakpoint *bp =
857cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
858b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
859b9c1b51eSKate Stone BreakpointLocation *location =
860b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
861b842f2ecSJim Ingham if (location)
862cfb96d84SJim Ingham location->GetLocationOptions().CopyOverSetOptions(
863a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions());
864b9c1b51eSKate Stone } else {
865cfb96d84SJim Ingham bp->GetOptions().CopyOverSetOptions(
866a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions());
8675a988416SJim Ingham }
8685a988416SJim Ingham }
8695a988416SJim Ingham }
8705a988416SJim Ingham }
8715a988416SJim Ingham
8725a988416SJim Ingham return result.Succeeded();
8735a988416SJim Ingham }
8745a988416SJim Ingham
8755a988416SJim Ingham private:
876b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts;
877b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts;
878b842f2ecSJim Ingham OptionGroupOptions m_options;
8795a988416SJim Ingham };
8805a988416SJim Ingham
8815a988416SJim Ingham // CommandObjectBreakpointEnable
8825a988416SJim Ingham #pragma mark Enable
8835a988416SJim Ingham
884b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
8855a988416SJim Ingham public:
CommandObjectBreakpointEnable(CommandInterpreter & interpreter)886b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
887b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable",
888b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If "
889b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.",
890b9c1b51eSKate Stone nullptr) {
8915a988416SJim Ingham CommandArgumentEntry arg;
892b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
893b9c1b51eSKate Stone eArgTypeBreakpointIDRange);
894b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's
895b9c1b51eSKate Stone // arguments vector.
8965a988416SJim Ingham m_arguments.push_back(arg);
8975a988416SJim Ingham }
8985a988416SJim Ingham
8999e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default;
9005a988416SJim Ingham
9010e50b9a4SGongyu Deng void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)9020e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request,
9030e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override {
9040e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
9050e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
9060e50b9a4SGongyu Deng request, nullptr);
9070e50b9a4SGongyu Deng }
9080e50b9a4SGongyu Deng
9095a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)910b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
911cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget();
9125a988416SJim Ingham
913bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
914cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
9155a988416SJim Ingham
916cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList();
9175a988416SJim Ingham
9185a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize();
9195a988416SJim Ingham
920b9c1b51eSKate Stone if (num_breakpoints == 0) {
9215a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled.");
9225a988416SJim Ingham return false;
9235a988416SJim Ingham }
9245a988416SJim Ingham
92511eb9c64SZachary Turner if (command.empty()) {
9265a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints.
927cb2380c9SRaphael Isemann target.EnableAllowedBreakpoints();
928b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
929b9c1b51eSKate Stone " breakpoints)\n",
930b9c1b51eSKate Stone (uint64_t)num_breakpoints);
9315a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
932b9c1b51eSKate Stone } else {
9335a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint.
9345a988416SJim Ingham BreakpointIDList valid_bp_ids;
935b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
936cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
937b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm);
9385a988416SJim Ingham
939b9c1b51eSKate Stone if (result.Succeeded()) {
9405a988416SJim Ingham int enable_count = 0;
9415a988416SJim Ingham int loc_count = 0;
9425a988416SJim Ingham const size_t count = valid_bp_ids.GetSize();
943b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) {
9445a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9455a988416SJim Ingham
946b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
947b9c1b51eSKate Stone Breakpoint *breakpoint =
948cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
949b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
950b9c1b51eSKate Stone BreakpointLocation *location =
951b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
952b9c1b51eSKate Stone if (location) {
9535a988416SJim Ingham location->SetEnabled(true);
9545a988416SJim Ingham ++loc_count;
9555a988416SJim Ingham }
956b9c1b51eSKate Stone } else {
9575a988416SJim Ingham breakpoint->SetEnabled(true);
9585a988416SJim Ingham ++enable_count;
9595a988416SJim Ingham }
9605a988416SJim Ingham }
9615a988416SJim Ingham }
962b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n",
963b9c1b51eSKate Stone enable_count + loc_count);
9645a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
9655a988416SJim Ingham }
9665a988416SJim Ingham }
9675a988416SJim Ingham
9685a988416SJim Ingham return result.Succeeded();
9695a988416SJim Ingham }
9705a988416SJim Ingham };
9715a988416SJim Ingham
9725a988416SJim Ingham // CommandObjectBreakpointDisable
9735a988416SJim Ingham #pragma mark Disable
9745a988416SJim Ingham
975b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9765a988416SJim Ingham public:
CommandObjectBreakpointDisable(CommandInterpreter & interpreter)9777428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
978b9c1b51eSKate Stone : CommandObjectParsed(
979b9c1b51eSKate Stone interpreter, "breakpoint disable",
980b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting "
9817428a18cSKate Stone "them. If none are specified, disable all "
9827428a18cSKate Stone "breakpoints.",
983b9c1b51eSKate Stone nullptr) {
984b9c1b51eSKate Stone SetHelpLong(
985b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \
9867428a18cSKate Stone If none are specified, disable all breakpoints."
9877428a18cSKate Stone R"(
988ea671fbdSKate Stone
9897428a18cSKate Stone )"
9907428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \
9917428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:"
9927428a18cSKate Stone R"(
993ea671fbdSKate Stone
994ea671fbdSKate Stone (lldb) break disable 1
995ea671fbdSKate Stone (lldb) break enable 1.1
996ea671fbdSKate Stone
997ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type:
998ea671fbdSKate Stone
999ea671fbdSKate Stone (lldb) break disable 1.*
1000ea671fbdSKate Stone (lldb) break enable 1.1
1001ea671fbdSKate Stone
10027428a18cSKate Stone )"
10037428a18cSKate Stone "The first command disables all locations for breakpoint 1, \
10047428a18cSKate Stone the second re-enables the first location.");
1005b0fac509SJim Ingham
10065a988416SJim Ingham CommandArgumentEntry arg;
1007b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1008b9c1b51eSKate Stone eArgTypeBreakpointIDRange);
1009b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's
1010b9c1b51eSKate Stone // arguments vector.
10115a988416SJim Ingham m_arguments.push_back(arg);
10125a988416SJim Ingham }
10135a988416SJim Ingham
10149e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default;
10155a988416SJim Ingham
10160e50b9a4SGongyu Deng void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)10170e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request,
10180e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override {
10190e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
10200e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
10210e50b9a4SGongyu Deng request, nullptr);
10220e50b9a4SGongyu Deng }
10230e50b9a4SGongyu Deng
10245a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1025b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
1026cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget();
1027bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
1028cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
10295a988416SJim Ingham
1030cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList();
10315a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize();
10325a988416SJim Ingham
1033b9c1b51eSKate Stone if (num_breakpoints == 0) {
10345a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled.");
10355a988416SJim Ingham return false;
10365a988416SJim Ingham }
10375a988416SJim Ingham
103811eb9c64SZachary Turner if (command.empty()) {
10395a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints.
1040cb2380c9SRaphael Isemann target.DisableAllowedBreakpoints();
1041b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1042b9c1b51eSKate Stone " breakpoints)\n",
1043b9c1b51eSKate Stone (uint64_t)num_breakpoints);
10445a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
1045b9c1b51eSKate Stone } else {
10465a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint.
10475a988416SJim Ingham BreakpointIDList valid_bp_ids;
10485a988416SJim Ingham
1049b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1050cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
1051b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm);
10525a988416SJim Ingham
1053b9c1b51eSKate Stone if (result.Succeeded()) {
10545a988416SJim Ingham int disable_count = 0;
10555a988416SJim Ingham int loc_count = 0;
10565a988416SJim Ingham const size_t count = valid_bp_ids.GetSize();
1057b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) {
10585a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10595a988416SJim Ingham
1060b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1061b9c1b51eSKate Stone Breakpoint *breakpoint =
1062cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1063b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1064b9c1b51eSKate Stone BreakpointLocation *location =
1065b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1066b9c1b51eSKate Stone if (location) {
10675a988416SJim Ingham location->SetEnabled(false);
10685a988416SJim Ingham ++loc_count;
10695a988416SJim Ingham }
1070b9c1b51eSKate Stone } else {
10715a988416SJim Ingham breakpoint->SetEnabled(false);
10725a988416SJim Ingham ++disable_count;
10735a988416SJim Ingham }
10745a988416SJim Ingham }
10755a988416SJim Ingham }
1076b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1077b9c1b51eSKate Stone disable_count + loc_count);
10785a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
10795a988416SJim Ingham }
10805a988416SJim Ingham }
10815a988416SJim Ingham
10825a988416SJim Ingham return result.Succeeded();
10835a988416SJim Ingham }
10845a988416SJim Ingham };
10855a988416SJim Ingham
10865a988416SJim Ingham // CommandObjectBreakpointList
10871f0f5b5bSZachary Turner
10881f0f5b5bSZachary Turner #pragma mark List::CommandOptions
10896f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1090c5a2d747SRaphael Isemann #include "CommandOptions.inc"
10911f0f5b5bSZachary Turner
10925a988416SJim Ingham #pragma mark List
10935a988416SJim Ingham
1094b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
10955a988416SJim Ingham public:
CommandObjectBreakpointList(CommandInterpreter & interpreter)1096b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter)
1097b9c1b51eSKate Stone : CommandObjectParsed(
1098b9c1b51eSKate Stone interpreter, "breakpoint list",
10995a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.",
1100abb0ed44SKazu Hirata nullptr) {
11015a988416SJim Ingham CommandArgumentEntry arg;
11025a988416SJim Ingham CommandArgumentData bp_id_arg;
11035a988416SJim Ingham
11045a988416SJim Ingham // Define the first (and only) variant of this arg.
11055a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID;
11065a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional;
11075a988416SJim Ingham
1108b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the
1109b9c1b51eSKate Stone // argument entry.
11105a988416SJim Ingham arg.push_back(bp_id_arg);
11115a988416SJim Ingham
11125a988416SJim Ingham // Push the data for the first argument into the m_arguments vector.
11135a988416SJim Ingham m_arguments.push_back(arg);
11145a988416SJim Ingham }
11155a988416SJim Ingham
11169e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default;
11175a988416SJim Ingham
GetOptions()1118b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; }
11195a988416SJim Ingham
1120b9c1b51eSKate Stone class CommandOptions : public Options {
11215a988416SJim Ingham public:
112224f9a2f5SShafik Yaghmour CommandOptions() = default;
11235a988416SJim Ingham
11249e85e5a8SEugene Zelenko ~CommandOptions() override = default;
11255a988416SJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)112697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1127b9c1b51eSKate Stone ExecutionContext *execution_context) override {
112897206d57SZachary Turner Status error;
11293bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val;
11305a988416SJim Ingham
1131b9c1b51eSKate Stone switch (short_option) {
11325a988416SJim Ingham case 'b':
11335a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief;
11345a988416SJim Ingham break;
113533df7cd3SJim Ingham case 'D':
113633df7cd3SJim Ingham m_use_dummy = true;
113733df7cd3SJim Ingham break;
11385a988416SJim Ingham case 'f':
11395a988416SJim Ingham m_level = lldb::eDescriptionLevelFull;
11405a988416SJim Ingham break;
11415a988416SJim Ingham case 'v':
11425a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose;
11435a988416SJim Ingham break;
11445a988416SJim Ingham case 'i':
11455a988416SJim Ingham m_internal = true;
11465a988416SJim Ingham break;
11475a988416SJim Ingham default:
114836162014SRaphael Isemann llvm_unreachable("Unimplemented option");
11495a988416SJim Ingham }
11505a988416SJim Ingham
11515a988416SJim Ingham return error;
11525a988416SJim Ingham }
11535a988416SJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)1154b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override {
11555a988416SJim Ingham m_level = lldb::eDescriptionLevelFull;
11565a988416SJim Ingham m_internal = false;
115733df7cd3SJim Ingham m_use_dummy = false;
11585a988416SJim Ingham }
11595a988416SJim Ingham
GetDefinitions()11601f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options);
11621f0f5b5bSZachary Turner }
11635a988416SJim Ingham
11645a988416SJim Ingham // Instance variables to hold the values for command options.
11655a988416SJim Ingham
11669494c510SJonas Devlieghere lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
11675a988416SJim Ingham
11685a988416SJim Ingham bool m_internal;
11699494c510SJonas Devlieghere bool m_use_dummy = false;
11705a988416SJim Ingham };
11715a988416SJim Ingham
11725a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1173b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
1174cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11755a988416SJim Ingham
1176b9c1b51eSKate Stone const BreakpointList &breakpoints =
1177cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal);
1178bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
1179cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11805a988416SJim Ingham
11815a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize();
11825a988416SJim Ingham
1183b9c1b51eSKate Stone if (num_breakpoints == 0) {
11845a988416SJim Ingham result.AppendMessage("No breakpoints currently set.");
11855a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
11865a988416SJim Ingham return true;
11875a988416SJim Ingham }
11885a988416SJim Ingham
11895a988416SJim Ingham Stream &output_stream = result.GetOutputStream();
11905a988416SJim Ingham
119111eb9c64SZachary Turner if (command.empty()) {
11925a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints.
11935a988416SJim Ingham result.AppendMessage("Current breakpoints:");
1194b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) {
11955a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1196b842f2ecSJim Ingham if (breakpoint->AllowList())
1197b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint,
1198b842f2ecSJim Ingham m_options.m_level);
11995a988416SJim Ingham }
12005a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
1201b9c1b51eSKate Stone } else {
12025a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint.
12035a988416SJim Ingham BreakpointIDList valid_bp_ids;
1204b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1205cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
1206b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm);
12075a988416SJim Ingham
1208b9c1b51eSKate Stone if (result.Succeeded()) {
1209b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12105a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1211b9c1b51eSKate Stone Breakpoint *breakpoint =
1212cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1213b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint,
1214b9c1b51eSKate Stone m_options.m_level);
12155a988416SJim Ingham }
12165a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
1217b9c1b51eSKate Stone } else {
12187428a18cSKate Stone result.AppendError("Invalid breakpoint ID.");
12195a988416SJim Ingham }
12205a988416SJim Ingham }
12215a988416SJim Ingham
12225a988416SJim Ingham return result.Succeeded();
12235a988416SJim Ingham }
12245a988416SJim Ingham
12255a988416SJim Ingham private:
12265a988416SJim Ingham CommandOptions m_options;
12275a988416SJim Ingham };
12285a988416SJim Ingham
12295a988416SJim Ingham // CommandObjectBreakpointClear
12301f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12311f0f5b5bSZachary Turner
1232f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1233f94668e3SRaphael Isemann #include "CommandOptions.inc"
12341f0f5b5bSZachary Turner
12355a988416SJim Ingham #pragma mark Clear
12365a988416SJim Ingham
1237b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12385a988416SJim Ingham public:
1239efe8e7e3SFangrui Song enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12405a988416SJim Ingham
CommandObjectBreakpointClear(CommandInterpreter & interpreter)12417428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12427428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear",
1243b9c1b51eSKate Stone "Delete or disable breakpoints matching the "
1244b9c1b51eSKate Stone "specified source file and line.",
1245abb0ed44SKazu Hirata "breakpoint clear <cmd-options>") {}
12465a988416SJim Ingham
12479e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default;
12485a988416SJim Ingham
GetOptions()1249b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; }
12505a988416SJim Ingham
1251b9c1b51eSKate Stone class CommandOptions : public Options {
12525a988416SJim Ingham public:
125324f9a2f5SShafik Yaghmour CommandOptions() = default;
12545a988416SJim Ingham
12559e85e5a8SEugene Zelenko ~CommandOptions() override = default;
12565a988416SJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)125797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1258b9c1b51eSKate Stone ExecutionContext *execution_context) override {
125997206d57SZachary Turner Status error;
12603bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val;
12615a988416SJim Ingham
1262b9c1b51eSKate Stone switch (short_option) {
12635a988416SJim Ingham case 'f':
1264adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg));
12655a988416SJim Ingham break;
12665a988416SJim Ingham
12675a988416SJim Ingham case 'l':
1268fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num);
12695a988416SJim Ingham break;
12705a988416SJim Ingham
12715a988416SJim Ingham default:
127236162014SRaphael Isemann llvm_unreachable("Unimplemented option");
12735a988416SJim Ingham }
12745a988416SJim Ingham
12755a988416SJim Ingham return error;
12765a988416SJim Ingham }
12775a988416SJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)1278b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override {
12795a988416SJim Ingham m_filename.clear();
12805a988416SJim Ingham m_line_num = 0;
12815a988416SJim Ingham }
12825a988416SJim Ingham
GetDefinitions()12831f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
128470602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options);
12851f0f5b5bSZachary Turner }
12865a988416SJim Ingham
12875a988416SJim Ingham // Instance variables to hold the values for command options.
12885a988416SJim Ingham
12895a988416SJim Ingham std::string m_filename;
12909494c510SJonas Devlieghere uint32_t m_line_num = 0;
12915a988416SJim Ingham };
12925a988416SJim Ingham
12935a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1294b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
1295cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget();
12965a988416SJim Ingham
129705097246SAdrian Prantl // The following are the various types of breakpoints that could be
129805097246SAdrian Prantl // cleared:
12995a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location)
13005a988416SJim Ingham
13015a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid;
13025a988416SJim Ingham
13035a988416SJim Ingham if (m_options.m_line_num != 0)
13045a988416SJim Ingham break_type = eClearTypeFileAndLine;
13055a988416SJim Ingham
1306bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
1307cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
13085a988416SJim Ingham
1309cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList();
13105a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize();
13115a988416SJim Ingham
13125a988416SJim Ingham // Early return if there's no breakpoint at all.
1313b9c1b51eSKate Stone if (num_breakpoints == 0) {
13145a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared.");
13155a988416SJim Ingham return result.Succeeded();
13165a988416SJim Ingham }
13175a988416SJim Ingham
13185a988416SJim Ingham // Find matching breakpoints and delete them.
13195a988416SJim Ingham
13205a988416SJim Ingham // First create a copy of all the IDs.
13215a988416SJim Ingham std::vector<break_id_t> BreakIDs;
13225a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i)
13239e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13245a988416SJim Ingham
13255a988416SJim Ingham int num_cleared = 0;
13265a988416SJim Ingham StreamString ss;
1327b9c1b51eSKate Stone switch (break_type) {
13285a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position
13295a988416SJim Ingham {
13305a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str());
13315a988416SJim Ingham BreakpointLocationCollection loc_coll;
13325a988416SJim Ingham
1333b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) {
13345a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13355a988416SJim Ingham
1336b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1337b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just
1338b9c1b51eSKate Stone // remove the breakpoint.
1339b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) {
13405a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13415a988416SJim Ingham ss.EOL();
1342cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp->GetID());
13435a988416SJim Ingham ++num_cleared;
13445a988416SJim Ingham }
13455a988416SJim Ingham }
13465a988416SJim Ingham }
1347b9c1b51eSKate Stone } break;
13485a988416SJim Ingham
13495a988416SJim Ingham default:
13505a988416SJim Ingham break;
13515a988416SJim Ingham }
13525a988416SJim Ingham
1353b9c1b51eSKate Stone if (num_cleared > 0) {
13545a988416SJim Ingham Stream &output_stream = result.GetOutputStream();
13555a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1356c156427dSZachary Turner output_stream << ss.GetString();
13575a988416SJim Ingham output_stream.EOL();
13585a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
1359b9c1b51eSKate Stone } else {
13605a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared.");
13615a988416SJim Ingham }
13625a988416SJim Ingham
13635a988416SJim Ingham return result.Succeeded();
13645a988416SJim Ingham }
13655a988416SJim Ingham
13665a988416SJim Ingham private:
13675a988416SJim Ingham CommandOptions m_options;
13685a988416SJim Ingham };
13695a988416SJim Ingham
13705a988416SJim Ingham // CommandObjectBreakpointDelete
1371f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1372f94668e3SRaphael Isemann #include "CommandOptions.inc"
13731f0f5b5bSZachary Turner
13745a988416SJim Ingham #pragma mark Delete
13755a988416SJim Ingham
1376b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13775a988416SJim Ingham public:
CommandObjectBreakpointDelete(CommandInterpreter & interpreter)1378b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1379b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete",
1380b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no "
1381b9c1b51eSKate Stone "breakpoints are specified, delete them all.",
1382abb0ed44SKazu Hirata nullptr) {
13835a988416SJim Ingham CommandArgumentEntry arg;
1384b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1385b9c1b51eSKate Stone eArgTypeBreakpointIDRange);
1386b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's
1387b9c1b51eSKate Stone // arguments vector.
13885a988416SJim Ingham m_arguments.push_back(arg);
13895a988416SJim Ingham }
13905a988416SJim Ingham
13919e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default;
13925a988416SJim Ingham
13930e50b9a4SGongyu Deng void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)13940e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request,
13950e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override {
13960e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
13970e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
13980e50b9a4SGongyu Deng request, nullptr);
13990e50b9a4SGongyu Deng }
14000e50b9a4SGongyu Deng
GetOptions()1401b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; }
140233df7cd3SJim Ingham
1403b9c1b51eSKate Stone class CommandOptions : public Options {
140433df7cd3SJim Ingham public:
140524f9a2f5SShafik Yaghmour CommandOptions() = default;
140633df7cd3SJim Ingham
14079e85e5a8SEugene Zelenko ~CommandOptions() override = default;
140833df7cd3SJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)140997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1410b9c1b51eSKate Stone ExecutionContext *execution_context) override {
141197206d57SZachary Turner Status error;
141233df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val;
141333df7cd3SJim Ingham
1414b9c1b51eSKate Stone switch (short_option) {
141533df7cd3SJim Ingham case 'f':
141633df7cd3SJim Ingham m_force = true;
141733df7cd3SJim Ingham break;
141833df7cd3SJim Ingham
141933df7cd3SJim Ingham case 'D':
142033df7cd3SJim Ingham m_use_dummy = true;
142133df7cd3SJim Ingham break;
142233df7cd3SJim Ingham
14233726ac41SJim Ingham case 'd':
14243726ac41SJim Ingham m_delete_disabled = true;
14253726ac41SJim Ingham break;
14263726ac41SJim Ingham
142733df7cd3SJim Ingham default:
142836162014SRaphael Isemann llvm_unreachable("Unimplemented option");
142933df7cd3SJim Ingham }
143033df7cd3SJim Ingham
143133df7cd3SJim Ingham return error;
143233df7cd3SJim Ingham }
143333df7cd3SJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)1434b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override {
143533df7cd3SJim Ingham m_use_dummy = false;
143633df7cd3SJim Ingham m_force = false;
14373726ac41SJim Ingham m_delete_disabled = false;
143833df7cd3SJim Ingham }
143933df7cd3SJim Ingham
GetDefinitions()14401f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
144170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options);
14421f0f5b5bSZachary Turner }
144333df7cd3SJim Ingham
144433df7cd3SJim Ingham // Instance variables to hold the values for command options.
14459494c510SJonas Devlieghere bool m_use_dummy = false;
14469494c510SJonas Devlieghere bool m_force = false;
14479494c510SJonas Devlieghere bool m_delete_disabled = false;
144833df7cd3SJim Ingham };
144933df7cd3SJim Ingham
14505a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1451b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
1452cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14533726ac41SJim Ingham result.Clear();
14545a988416SJim Ingham
1455bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
1456cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
14575a988416SJim Ingham
14583726ac41SJim Ingham BreakpointList &breakpoints = target.GetBreakpointList();
14595a988416SJim Ingham
14605a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize();
14615a988416SJim Ingham
1462b9c1b51eSKate Stone if (num_breakpoints == 0) {
14635a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted.");
14645a988416SJim Ingham return false;
14655a988416SJim Ingham }
14665a988416SJim Ingham
14670018c712SJim Ingham // Handle the delete all breakpoints case:
14683726ac41SJim Ingham if (command.empty() && !m_options.m_delete_disabled) {
1469b9c1b51eSKate Stone if (!m_options.m_force &&
1470b9c1b51eSKate Stone !m_interpreter.Confirm(
1471b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?",
1472b9c1b51eSKate Stone true)) {
14735a988416SJim Ingham result.AppendMessage("Operation cancelled...");
1474b9c1b51eSKate Stone } else {
1475cb2380c9SRaphael Isemann target.RemoveAllowedBreakpoints();
1476b9c1b51eSKate Stone result.AppendMessageWithFormat(
1477b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1478b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14795a988416SJim Ingham }
14805a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
14810018c712SJim Ingham return result.Succeeded();
14820018c712SJim Ingham }
14830018c712SJim Ingham
14840018c712SJim Ingham // Either we have some kind of breakpoint specification(s),
14850018c712SJim Ingham // or we are handling "break disable --deleted". Gather the list
14860018c712SJim Ingham // of breakpoints to delete here, the we'll delete them below.
14875a988416SJim Ingham BreakpointIDList valid_bp_ids;
14883726ac41SJim Ingham
14893726ac41SJim Ingham if (m_options.m_delete_disabled) {
14903726ac41SJim Ingham BreakpointIDList excluded_bp_ids;
14913726ac41SJim Ingham
14923726ac41SJim Ingham if (!command.empty()) {
14933726ac41SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
14943726ac41SJim Ingham command, &target, result, &excluded_bp_ids,
14953726ac41SJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm);
14960018c712SJim Ingham if (!result.Succeeded())
14970018c712SJim Ingham return false;
14983726ac41SJim Ingham }
14990018c712SJim Ingham
15003726ac41SJim Ingham for (auto breakpoint_sp : breakpoints.Breakpoints()) {
15013726ac41SJim Ingham if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
15023726ac41SJim Ingham BreakpointID bp_id(breakpoint_sp->GetID());
15033726ac41SJim Ingham size_t pos = 0;
15043726ac41SJim Ingham if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
15053726ac41SJim Ingham valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
15063726ac41SJim Ingham }
15073726ac41SJim Ingham }
15083726ac41SJim Ingham if (valid_bp_ids.GetSize() == 0) {
15093726ac41SJim Ingham result.AppendError("No disabled breakpoints.");
15103726ac41SJim Ingham return false;
15113726ac41SJim Ingham }
15123726ac41SJim Ingham } else {
1513b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1514cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
1515b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm);
15160018c712SJim Ingham if (!result.Succeeded())
15170018c712SJim Ingham return false;
15183726ac41SJim Ingham }
15195a988416SJim Ingham
15205a988416SJim Ingham int delete_count = 0;
15215a988416SJim Ingham int disable_count = 0;
15225a988416SJim Ingham const size_t count = valid_bp_ids.GetSize();
1523b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) {
15245a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15255a988416SJim Ingham
1526b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1527b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1528b9c1b51eSKate Stone Breakpoint *breakpoint =
1529cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1530b9c1b51eSKate Stone BreakpointLocation *location =
1531b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1532b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we
1533b9c1b51eSKate Stone // disable them instead.
1534b9c1b51eSKate Stone if (location) {
15355a988416SJim Ingham location->SetEnabled(false);
15365a988416SJim Ingham ++disable_count;
15375a988416SJim Ingham }
1538b9c1b51eSKate Stone } else {
1539cb2380c9SRaphael Isemann target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15405a988416SJim Ingham ++delete_count;
15415a988416SJim Ingham }
15425a988416SJim Ingham }
15435a988416SJim Ingham }
1544b9c1b51eSKate Stone result.AppendMessageWithFormat(
1545b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15465a988416SJim Ingham delete_count, disable_count);
15475a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
15485a988416SJim Ingham return result.Succeeded();
15495a988416SJim Ingham }
15509e85e5a8SEugene Zelenko
155133df7cd3SJim Ingham private:
155233df7cd3SJim Ingham CommandOptions m_options;
155333df7cd3SJim Ingham };
155433df7cd3SJim Ingham
15555e09c8c3SJim Ingham // CommandObjectBreakpointName
1556f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1557f94668e3SRaphael Isemann #include "CommandOptions.inc"
1558bd68a052SRaphael Isemann
1559b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15605e09c8c3SJim Ingham public:
BreakpointNameOptionGroup()1561b9c1b51eSKate Stone BreakpointNameOptionGroup()
1562abb0ed44SKazu Hirata : m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {}
15635e09c8c3SJim Ingham
15649e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default;
15655e09c8c3SJim Ingham
GetDefinitions()15661f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
156770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options);
15685e09c8c3SJim Ingham }
15695e09c8c3SJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)157097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1571b9c1b51eSKate Stone ExecutionContext *execution_context) override {
157297206d57SZachary Turner Status error;
15735e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option;
15745e09c8c3SJim Ingham
1575b9c1b51eSKate Stone switch (short_option) {
15765e09c8c3SJim Ingham case 'N':
1577fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1578b9c1b51eSKate Stone error.Success())
1579fe11483bSZachary Turner m_name.SetValueFromString(option_arg);
15805e09c8c3SJim Ingham break;
15815e09c8c3SJim Ingham case 'B':
1582fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail())
1583b9c1b51eSKate Stone error.SetErrorStringWithFormat(
15848cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint",
1585fe11483bSZachary Turner option_arg.str().c_str());
15865e09c8c3SJim Ingham break;
15875e09c8c3SJim Ingham case 'D':
1588fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail())
1589b9c1b51eSKate Stone error.SetErrorStringWithFormat(
15908cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy",
1591fe11483bSZachary Turner option_arg.str().c_str());
15925e09c8c3SJim Ingham break;
1593e9632ebaSJim Ingham case 'H':
1594e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg);
1595e9632ebaSJim Ingham break;
15965e09c8c3SJim Ingham
15975e09c8c3SJim Ingham default:
159836162014SRaphael Isemann llvm_unreachable("Unimplemented option");
15995e09c8c3SJim Ingham }
16005e09c8c3SJim Ingham return error;
16015e09c8c3SJim Ingham }
16025e09c8c3SJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)1603b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override {
16045e09c8c3SJim Ingham m_name.Clear();
16055e09c8c3SJim Ingham m_breakpoint.Clear();
16065e09c8c3SJim Ingham m_use_dummy.Clear();
16075e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false);
1608e9632ebaSJim Ingham m_help_string.Clear();
16095e09c8c3SJim Ingham }
16105e09c8c3SJim Ingham
16115e09c8c3SJim Ingham OptionValueString m_name;
16125e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint;
16135e09c8c3SJim Ingham OptionValueBoolean m_use_dummy;
1614e9632ebaSJim Ingham OptionValueString m_help_string;
16155e09c8c3SJim Ingham };
16165e09c8c3SJim Ingham
1617f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1618f94668e3SRaphael Isemann #include "CommandOptions.inc"
1619b842f2ecSJim Ingham
16208fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1621b842f2ecSJim Ingham public:
162224f9a2f5SShafik Yaghmour BreakpointAccessOptionGroup() = default;
1623b842f2ecSJim Ingham
1624b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default;
1625b842f2ecSJim Ingham
GetDefinitions()1626b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1627b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options);
1628b842f2ecSJim Ingham }
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1629b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1630b842f2ecSJim Ingham ExecutionContext *execution_context) override {
1631b842f2ecSJim Ingham Status error;
1632a925974bSAdrian Prantl const int short_option =
1633a925974bSAdrian Prantl g_breakpoint_access_options[option_idx].short_option;
1634b842f2ecSJim Ingham
1635b842f2ecSJim Ingham switch (short_option) {
1636b842f2ecSJim Ingham case 'L': {
1637b842f2ecSJim Ingham bool value, success;
163847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success);
1639b842f2ecSJim Ingham if (success) {
1640b842f2ecSJim Ingham m_permissions.SetAllowList(value);
1641b842f2ecSJim Ingham } else
1642b842f2ecSJim Ingham error.SetErrorStringWithFormat(
1643b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option",
1644b842f2ecSJim Ingham option_arg.str().c_str());
1645b842f2ecSJim Ingham } break;
1646b842f2ecSJim Ingham case 'A': {
1647b842f2ecSJim Ingham bool value, success;
164847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success);
1649b842f2ecSJim Ingham if (success) {
1650b842f2ecSJim Ingham m_permissions.SetAllowDisable(value);
1651b842f2ecSJim Ingham } else
1652b842f2ecSJim Ingham error.SetErrorStringWithFormat(
1653b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option",
1654b842f2ecSJim Ingham option_arg.str().c_str());
1655b842f2ecSJim Ingham } break;
1656b842f2ecSJim Ingham case 'D': {
1657b842f2ecSJim Ingham bool value, success;
165847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success);
1659b842f2ecSJim Ingham if (success) {
1660b842f2ecSJim Ingham m_permissions.SetAllowDelete(value);
1661b842f2ecSJim Ingham } else
1662b842f2ecSJim Ingham error.SetErrorStringWithFormat(
1663b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option",
1664b842f2ecSJim Ingham option_arg.str().c_str());
1665b842f2ecSJim Ingham } break;
166636162014SRaphael Isemann default:
166736162014SRaphael Isemann llvm_unreachable("Unimplemented option");
1668b842f2ecSJim Ingham }
1669b842f2ecSJim Ingham
1670b842f2ecSJim Ingham return error;
1671b842f2ecSJim Ingham }
1672b842f2ecSJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)1673a925974bSAdrian Prantl void OptionParsingStarting(ExecutionContext *execution_context) override {}
1674b842f2ecSJim Ingham
GetPermissions() const1675a925974bSAdrian Prantl const BreakpointName::Permissions &GetPermissions() const {
1676b842f2ecSJim Ingham return m_permissions;
1677b842f2ecSJim Ingham }
1678b842f2ecSJim Ingham BreakpointName::Permissions m_permissions;
1679b842f2ecSJim Ingham };
1680b842f2ecSJim Ingham
1681b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1682b842f2ecSJim Ingham public:
CommandObjectBreakpointNameConfigure(CommandInterpreter & interpreter)1683b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1684b842f2ecSJim Ingham : CommandObjectParsed(
1685a925974bSAdrian Prantl interpreter, "configure",
1686a925974bSAdrian Prantl "Configure the options for the breakpoint"
1687b842f2ecSJim Ingham " name provided. "
1688b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from "
1689b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set "
1690b842f2ecSJim Ingham "on the name.",
1691b842f2ecSJim Ingham "breakpoint name configure <command-options> "
1692abb0ed44SKazu Hirata "<breakpoint-name-list>") {
1693b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this
1694b842f2ecSJim Ingham // command.
1695b842f2ecSJim Ingham CommandArgumentEntry arg1;
1696b842f2ecSJim Ingham CommandArgumentData id_arg;
1697b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName;
1698b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional;
1699b842f2ecSJim Ingham arg1.push_back(id_arg);
1700b842f2ecSJim Ingham m_arguments.push_back(arg1);
1701b842f2ecSJim Ingham
1702a925974bSAdrian Prantl m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1703a925974bSAdrian Prantl m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1704b842f2ecSJim Ingham LLDB_OPT_SET_ALL);
1705a925974bSAdrian Prantl m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1706e9632ebaSJim Ingham LLDB_OPT_SET_ALL);
1707b842f2ecSJim Ingham m_option_group.Finalize();
1708b842f2ecSJim Ingham }
1709b842f2ecSJim Ingham
1710b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default;
1711b842f2ecSJim Ingham
GetOptions()1712b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; }
1713b842f2ecSJim Ingham
1714b842f2ecSJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1715b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override {
1716b842f2ecSJim Ingham
1717b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount();
1718b842f2ecSJim Ingham if (argc == 0) {
1719b842f2ecSJim Ingham result.AppendError("No names provided.");
1720b842f2ecSJim Ingham return false;
1721b842f2ecSJim Ingham }
1722b842f2ecSJim Ingham
1723cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(false);
1724b842f2ecSJim Ingham
1725b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock;
1726cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
1727b842f2ecSJim Ingham
1728b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal.
1729b842f2ecSJim Ingham for (auto &entry : command.entries()) {
1730b842f2ecSJim Ingham Status error;
1731a925974bSAdrian Prantl if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1732b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1733b842f2ecSJim Ingham entry.c_str(), error.AsCString());
1734b842f2ecSJim Ingham return false;
1735b842f2ecSJim Ingham }
1736b842f2ecSJim Ingham }
173705097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to
173805097246SAdrian Prantl // check the error:
1739b842f2ecSJim Ingham BreakpointSP bp_sp;
1740a925974bSAdrian Prantl if (m_bp_id.m_breakpoint.OptionWasSet()) {
1741b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1742cb2380c9SRaphael Isemann bp_sp = target.GetBreakpointByID(bp_id);
1743a925974bSAdrian Prantl if (!bp_sp) {
1744b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1745b842f2ecSJim Ingham bp_id);
1746b842f2ecSJim Ingham return false;
1747b842f2ecSJim Ingham }
1748b842f2ecSJim Ingham }
1749b842f2ecSJim Ingham
1750b842f2ecSJim Ingham Status error;
1751b842f2ecSJim Ingham for (auto &entry : command.entries()) {
1752b842f2ecSJim Ingham ConstString name(entry.c_str());
1753cb2380c9SRaphael Isemann BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1754b842f2ecSJim Ingham if (!bp_name)
1755b842f2ecSJim Ingham continue;
1756e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet())
1757e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1758e9632ebaSJim Ingham
1759b842f2ecSJim Ingham if (bp_sp)
1760cfb96d84SJim Ingham target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1761b842f2ecSJim Ingham m_access_options.GetPermissions());
1762b842f2ecSJim Ingham else
1763cb2380c9SRaphael Isemann target.ConfigureBreakpointName(*bp_name,
1764b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(),
1765b842f2ecSJim Ingham m_access_options.GetPermissions());
1766b842f2ecSJim Ingham }
1767b842f2ecSJim Ingham return true;
1768b842f2ecSJim Ingham }
1769b842f2ecSJim Ingham
1770b842f2ecSJim Ingham private:
1771b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1772b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts;
1773b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options;
1774b842f2ecSJim Ingham OptionGroupOptions m_option_group;
1775b842f2ecSJim Ingham };
1776b842f2ecSJim Ingham
1777b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17785e09c8c3SJim Ingham public:
CommandObjectBreakpointNameAdd(CommandInterpreter & interpreter)1779b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1780b9c1b51eSKate Stone : CommandObjectParsed(
1781b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.",
1782abb0ed44SKazu Hirata "breakpoint name add <command-options> <breakpoint-id-list>") {
1783b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this
1784b9c1b51eSKate Stone // command.
17855e09c8c3SJim Ingham CommandArgumentEntry arg1;
17865e09c8c3SJim Ingham CommandArgumentData id_arg;
17875e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID;
17885e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional;
17895e09c8c3SJim Ingham arg1.push_back(id_arg);
17905e09c8c3SJim Ingham m_arguments.push_back(arg1);
17915e09c8c3SJim Ingham
17925e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17935e09c8c3SJim Ingham m_option_group.Finalize();
17945e09c8c3SJim Ingham }
17955e09c8c3SJim Ingham
17969e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default;
17975e09c8c3SJim Ingham
1798e87362e6SGongyu Deng void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1799e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request,
1800e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override {
1801e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
1802e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1803e87362e6SGongyu Deng request, nullptr);
1804e87362e6SGongyu Deng }
1805e87362e6SGongyu Deng
GetOptions()1806b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; }
18075e09c8c3SJim Ingham
18085e09c8c3SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1809b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
1810b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) {
18111b1c8e4aSDavid Spickett result.AppendError("No name option provided.");
18125e09c8c3SJim Ingham return false;
18135e09c8c3SJim Ingham }
18145e09c8c3SJim Ingham
1815cb2380c9SRaphael Isemann Target &target =
1816b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18175e09c8c3SJim Ingham
1818bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
1819cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
18205e09c8c3SJim Ingham
1821cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList();
18225e09c8c3SJim Ingham
18235e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize();
1824b9c1b51eSKate Stone if (num_breakpoints == 0) {
18251b1c8e4aSDavid Spickett result.AppendError("No breakpoints, cannot add names.");
18265e09c8c3SJim Ingham return false;
18275e09c8c3SJim Ingham }
18285e09c8c3SJim Ingham
18295e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint.
18305e09c8c3SJim Ingham BreakpointIDList valid_bp_ids;
1831b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1832cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
1833b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm);
18345e09c8c3SJim Ingham
1835b9c1b51eSKate Stone if (result.Succeeded()) {
1836b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) {
18371b1c8e4aSDavid Spickett result.AppendError("No breakpoints specified, cannot add names.");
18385e09c8c3SJim Ingham return false;
18395e09c8c3SJim Ingham }
18405e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize();
1841b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue();
1842b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already
1843b842f2ecSJim Ingham // checked that, so we don't need to check it again here.
1844b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) {
1845b9c1b51eSKate Stone lldb::break_id_t bp_id =
1846b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18475e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1848cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, bp_name, error);
18495e09c8c3SJim Ingham }
18505e09c8c3SJim Ingham }
18515e09c8c3SJim Ingham
18525e09c8c3SJim Ingham return true;
18535e09c8c3SJim Ingham }
18545e09c8c3SJim Ingham
18555e09c8c3SJim Ingham private:
18565e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options;
18575e09c8c3SJim Ingham OptionGroupOptions m_option_group;
18585e09c8c3SJim Ingham };
18595e09c8c3SJim Ingham
1860b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18615e09c8c3SJim Ingham public:
CommandObjectBreakpointNameDelete(CommandInterpreter & interpreter)1862b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1863b9c1b51eSKate Stone : CommandObjectParsed(
1864b9c1b51eSKate Stone interpreter, "delete",
18655e09c8c3SJim Ingham "Delete a name from the breakpoints provided.",
1866abb0ed44SKazu Hirata "breakpoint name delete <command-options> <breakpoint-id-list>") {
1867b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this
1868b9c1b51eSKate Stone // command.
18695e09c8c3SJim Ingham CommandArgumentEntry arg1;
18705e09c8c3SJim Ingham CommandArgumentData id_arg;
18715e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID;
18725e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional;
18735e09c8c3SJim Ingham arg1.push_back(id_arg);
18745e09c8c3SJim Ingham m_arguments.push_back(arg1);
18755e09c8c3SJim Ingham
18765e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18775e09c8c3SJim Ingham m_option_group.Finalize();
18785e09c8c3SJim Ingham }
18795e09c8c3SJim Ingham
18809e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default;
18815e09c8c3SJim Ingham
1882e87362e6SGongyu Deng void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1883e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request,
1884e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override {
1885e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
1886e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1887e87362e6SGongyu Deng request, nullptr);
1888e87362e6SGongyu Deng }
1889e87362e6SGongyu Deng
GetOptions()1890b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; }
18915e09c8c3SJim Ingham
18925e09c8c3SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1893b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
1894b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) {
18951b1c8e4aSDavid Spickett result.AppendError("No name option provided.");
18965e09c8c3SJim Ingham return false;
18975e09c8c3SJim Ingham }
18985e09c8c3SJim Ingham
1899cb2380c9SRaphael Isemann Target &target =
1900b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19015e09c8c3SJim Ingham
1902bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
1903cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
19045e09c8c3SJim Ingham
1905cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList();
19065e09c8c3SJim Ingham
19075e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize();
1908b9c1b51eSKate Stone if (num_breakpoints == 0) {
19091b1c8e4aSDavid Spickett result.AppendError("No breakpoints, cannot delete names.");
19105e09c8c3SJim Ingham return false;
19115e09c8c3SJim Ingham }
19125e09c8c3SJim Ingham
19135e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint.
19145e09c8c3SJim Ingham BreakpointIDList valid_bp_ids;
1915b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1916cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
1917b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm);
19185e09c8c3SJim Ingham
1919b9c1b51eSKate Stone if (result.Succeeded()) {
1920b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) {
19211b1c8e4aSDavid Spickett result.AppendError("No breakpoints specified, cannot delete names.");
19225e09c8c3SJim Ingham return false;
19235e09c8c3SJim Ingham }
1924b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19255e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize();
1926b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) {
1927b9c1b51eSKate Stone lldb::break_id_t bp_id =
1928b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19295e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1930cb2380c9SRaphael Isemann target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19315e09c8c3SJim Ingham }
19325e09c8c3SJim Ingham }
19335e09c8c3SJim Ingham
19345e09c8c3SJim Ingham return true;
19355e09c8c3SJim Ingham }
19365e09c8c3SJim Ingham
19375e09c8c3SJim Ingham private:
19385e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options;
19395e09c8c3SJim Ingham OptionGroupOptions m_option_group;
19405e09c8c3SJim Ingham };
19415e09c8c3SJim Ingham
1942b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19435e09c8c3SJim Ingham public:
CommandObjectBreakpointNameList(CommandInterpreter & interpreter)1944b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1945b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list",
1946b842f2ecSJim Ingham "List either the names for a breakpoint or info "
1947b842f2ecSJim Ingham "about a given name. With no arguments, lists all "
1948b842f2ecSJim Ingham "names",
1949abb0ed44SKazu Hirata "breakpoint name list <command-options>") {
1950b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19515e09c8c3SJim Ingham m_option_group.Finalize();
19525e09c8c3SJim Ingham }
19535e09c8c3SJim Ingham
19549e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default;
19555e09c8c3SJim Ingham
GetOptions()1956b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; }
19575e09c8c3SJim Ingham
19585e09c8c3SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1959b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override {
1960cb2380c9SRaphael Isemann Target &target =
1961b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19625e09c8c3SJim Ingham
1963b842f2ecSJim Ingham std::vector<std::string> name_list;
1964b842f2ecSJim Ingham if (command.empty()) {
1965cb2380c9SRaphael Isemann target.GetBreakpointNames(name_list);
1966b842f2ecSJim Ingham } else {
1967a925974bSAdrian Prantl for (const Args::ArgEntry &arg : command) {
1968b842f2ecSJim Ingham name_list.push_back(arg.c_str());
1969b842f2ecSJim Ingham }
1970b842f2ecSJim Ingham }
1971b842f2ecSJim Ingham
1972b842f2ecSJim Ingham if (name_list.empty()) {
1973b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found.");
1974b842f2ecSJim Ingham } else {
1975b842f2ecSJim Ingham for (const std::string &name_str : name_list) {
1976b842f2ecSJim Ingham const char *name = name_str.c_str();
1977b842f2ecSJim Ingham // First print out the options for the name:
1978b842f2ecSJim Ingham Status error;
1979cb2380c9SRaphael Isemann BreakpointName *bp_name =
1980cb2380c9SRaphael Isemann target.FindBreakpointName(ConstString(name), false, error);
1981a925974bSAdrian Prantl if (bp_name) {
1982b842f2ecSJim Ingham StreamString s;
1983b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name);
1984a925974bSAdrian Prantl if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1985b842f2ecSJim Ingham result.AppendMessage(s.GetString());
1986b842f2ecSJim Ingham }
1987b842f2ecSJim Ingham
1988bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock;
1989cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
19905e09c8c3SJim Ingham
1991cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList();
1992b842f2ecSJim Ingham bool any_set = false;
1993b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1994b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) {
19955e09c8c3SJim Ingham StreamString s;
1996b842f2ecSJim Ingham any_set = true;
19975e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19985e09c8c3SJim Ingham s.EOL();
1999c156427dSZachary Turner result.AppendMessage(s.GetString());
20005e09c8c3SJim Ingham }
20015e09c8c3SJim Ingham }
2002b842f2ecSJim Ingham if (!any_set)
2003b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name.");
2004b9c1b51eSKate Stone } else {
2005b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name);
20065e09c8c3SJim Ingham }
2007b842f2ecSJim Ingham }
20085e09c8c3SJim Ingham }
20095e09c8c3SJim Ingham return true;
20105e09c8c3SJim Ingham }
20115e09c8c3SJim Ingham
20125e09c8c3SJim Ingham private:
20135e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options;
20145e09c8c3SJim Ingham OptionGroupOptions m_option_group;
20155e09c8c3SJim Ingham };
20165e09c8c3SJim Ingham
2017e14dc268SJim Ingham // CommandObjectBreakpointName
2018b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20195e09c8c3SJim Ingham public:
CommandObjectBreakpointName(CommandInterpreter & interpreter)20207428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter)
2021b9c1b51eSKate Stone : CommandObjectMultiword(
2022aaaf8e4cSJim Ingham interpreter, "name", "Commands to manage breakpoint names") {
2023aaaf8e4cSJim Ingham
2024aaaf8e4cSJim Ingham
2025aaaf8e4cSJim Ingham SetHelpLong(
2026aaaf8e4cSJim Ingham R"(
2027aaaf8e4cSJim Ingham Breakpoint names provide a general tagging mechanism for breakpoints. Each
2028aaaf8e4cSJim Ingham breakpoint name can be added to any number of breakpoints, and each breakpoint
2029aaaf8e4cSJim Ingham can have any number of breakpoint names attached to it. For instance:
2030aaaf8e4cSJim Ingham
2031aaaf8e4cSJim Ingham (lldb) break name add -N MyName 1-10
2032aaaf8e4cSJim Ingham
2033aaaf8e4cSJim Ingham adds the name MyName to breakpoints 1-10, and:
2034aaaf8e4cSJim Ingham
2035aaaf8e4cSJim Ingham (lldb) break set -n myFunc -N Name1 -N Name2
2036aaaf8e4cSJim Ingham
2037aaaf8e4cSJim Ingham adds two names to the breakpoint set at myFunc.
2038aaaf8e4cSJim Ingham
2039aaaf8e4cSJim Ingham They have a number of interrelated uses:
2040aaaf8e4cSJim Ingham
2041aaaf8e4cSJim Ingham 1) They provide a stable way to refer to a breakpoint (e.g. in another
2042aaaf8e4cSJim Ingham breakpoint's action). Using the breakpoint ID for this purpose is fragile, since
2043aaaf8e4cSJim Ingham it depends on the order of breakpoint creation. Giving a name to the breakpoint
2044aaaf8e4cSJim Ingham you want to act on, and then referring to it by name, is more robust:
2045aaaf8e4cSJim Ingham
2046aaaf8e4cSJim Ingham (lldb) break set -n myFunc -N BKPT1
2047aaaf8e4cSJim Ingham (lldb) break set -n myOtherFunc -C "break disable BKPT1"
2048aaaf8e4cSJim Ingham
2049aaaf8e4cSJim Ingham 2) This is actually just a specific use of a more general feature of breakpoint
2050aaaf8e4cSJim Ingham names. The <breakpt-id-list> argument type used to specify one or more
2051aaaf8e4cSJim Ingham breakpoints in most of the commands that deal with breakpoints also accepts
2052aaaf8e4cSJim Ingham breakpoint names. That allows you to refer to one breakpoint in a stable
2053aaaf8e4cSJim Ingham manner, but also makes them a convenient grouping mechanism, allowing you to
2054aaaf8e4cSJim Ingham easily act on a group of breakpoints by using their name, for instance disabling
2055aaaf8e4cSJim Ingham them all in one action:
2056aaaf8e4cSJim Ingham
2057aaaf8e4cSJim Ingham (lldb) break set -n myFunc -N Group1
2058aaaf8e4cSJim Ingham (lldb) break set -n myOtherFunc -N Group1
2059aaaf8e4cSJim Ingham (lldb) break disable Group1
2060aaaf8e4cSJim Ingham
2061aaaf8e4cSJim Ingham 3) But breakpoint names are also entities in their own right, and can be
2062aaaf8e4cSJim Ingham configured with all the modifiable attributes of a breakpoint. Then when you
2063aaaf8e4cSJim Ingham add a breakpoint name to a breakpoint, the breakpoint will be configured to
2064aaaf8e4cSJim Ingham match the state of the breakpoint name. The link between the name and the
2065aaaf8e4cSJim Ingham breakpoints sharing it remains live, so if you change the configuration on the
2066aaaf8e4cSJim Ingham name, it will also change the configurations on the breakpoints:
2067aaaf8e4cSJim Ingham
2068aaaf8e4cSJim Ingham (lldb) break name configure -i 10 IgnoreSome
2069aaaf8e4cSJim Ingham (lldb) break set -n myFunc -N IgnoreSome
2070aaaf8e4cSJim Ingham (lldb) break list IgnoreSome
2071aaaf8e4cSJim Ingham 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled
2072aaaf8e4cSJim Ingham Names:
2073aaaf8e4cSJim Ingham IgnoreSome
2074aaaf8e4cSJim Ingham (lldb) break name configure -i 5 IgnoreSome
2075aaaf8e4cSJim Ingham (lldb) break list IgnoreSome
2076aaaf8e4cSJim Ingham 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled
2077aaaf8e4cSJim Ingham Names:
2078aaaf8e4cSJim Ingham IgnoreSome
2079aaaf8e4cSJim Ingham
2080aaaf8e4cSJim Ingham Options that are not configured on a breakpoint name don't affect the value of
2081aaaf8e4cSJim Ingham those options on the breakpoints they are added to. So for instance, if Name1
2082aaaf8e4cSJim Ingham has the -i option configured and Name2 the -c option, adding both names to a
2083aaaf8e4cSJim Ingham breakpoint will set the -i option from Name1 and the -c option from Name2, and
2084aaaf8e4cSJim Ingham the other options will be unaltered.
2085aaaf8e4cSJim Ingham
2086aaaf8e4cSJim Ingham If you add multiple names to a breakpoint which have configured values for
2087aaaf8e4cSJim Ingham the same option, the last name added's value wins.
2088aaaf8e4cSJim Ingham
2089aaaf8e4cSJim Ingham The "liveness" of these settings is one way, from name to breakpoint.
2090aaaf8e4cSJim Ingham If you use "break modify" to change an option that is also configured on a name
2091aaaf8e4cSJim Ingham which that breakpoint has, the "break modify" command will override the setting
2092aaaf8e4cSJim Ingham for that breakpoint, but won't change the value configured in the name or on the
2093aaaf8e4cSJim Ingham other breakpoints sharing that name.
2094aaaf8e4cSJim Ingham
2095aaaf8e4cSJim Ingham 4) Breakpoint names are also a convenient way to copy option sets from one
2096aaaf8e4cSJim Ingham breakpoint to another. Using the -B option to "breakpoint name configure" makes
2097aaaf8e4cSJim Ingham a name configured with all the options of the original breakpoint. Then
2098aaaf8e4cSJim Ingham adding that name to another breakpoint copies over all the values from the
2099aaaf8e4cSJim Ingham original breakpoint to the new one.
2100aaaf8e4cSJim Ingham
2101aaaf8e4cSJim Ingham 5) You can also use breakpoint names to hide breakpoints from the breakpoint
2102aaaf8e4cSJim Ingham operations that act on all breakpoints: "break delete", "break disable" and
2103aaaf8e4cSJim Ingham "break list". You do that by specifying a "false" value for the
2104aaaf8e4cSJim Ingham --allow-{list,delete,disable} options to "breakpoint name configure" and then
2105aaaf8e4cSJim Ingham adding that name to a breakpoint.
2106aaaf8e4cSJim Ingham
2107aaaf8e4cSJim Ingham This won't keep the breakpoint from being deleted or disabled if you refer to it
2108aaaf8e4cSJim Ingham specifically by ID. The point of the feature is to make sure users don't
2109aaaf8e4cSJim Ingham inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using
2110aaaf8e4cSJim Ingham for its own purposes) as part of a "delete all" or "disable all" operation. The
2111aaaf8e4cSJim Ingham list hiding is because it's confusing for people to see breakpoints they
2112aaaf8e4cSJim Ingham didn't set.
2113aaaf8e4cSJim Ingham
2114aaaf8e4cSJim Ingham )");
2115b9c1b51eSKate Stone CommandObjectSP add_command_object(
2116b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter));
2117b9c1b51eSKate Stone CommandObjectSP delete_command_object(
2118b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter));
2119b9c1b51eSKate Stone CommandObjectSP list_command_object(
2120b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter));
2121b842f2ecSJim Ingham CommandObjectSP configure_command_object(
2122b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter));
21235e09c8c3SJim Ingham
21245e09c8c3SJim Ingham LoadSubCommand("add", add_command_object);
21255e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object);
21265e09c8c3SJim Ingham LoadSubCommand("list", list_command_object);
2127b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object);
21285e09c8c3SJim Ingham }
21295e09c8c3SJim Ingham
21309e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default;
21315e09c8c3SJim Ingham };
21325e09c8c3SJim Ingham
2133e14dc268SJim Ingham // CommandObjectBreakpointRead
21343acdf385SJim Ingham #pragma mark Read::CommandOptions
2135f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2136f94668e3SRaphael Isemann #include "CommandOptions.inc"
21371f0f5b5bSZachary Turner
21381f0f5b5bSZachary Turner #pragma mark Read
2139e14dc268SJim Ingham
2140e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2141e14dc268SJim Ingham public:
CommandObjectBreakpointRead(CommandInterpreter & interpreter)2142e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2143e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read",
2144e14dc268SJim Ingham "Read and set the breakpoints previously saved to "
2145e14dc268SJim Ingham "a file with \"breakpoint write\". ",
2146abb0ed44SKazu Hirata nullptr) {}
2147e14dc268SJim Ingham
2148e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default;
2149e14dc268SJim Ingham
GetOptions()2150e14dc268SJim Ingham Options *GetOptions() override { return &m_options; }
2151e14dc268SJim Ingham
2152e14dc268SJim Ingham class CommandOptions : public Options {
2153e14dc268SJim Ingham public:
215424f9a2f5SShafik Yaghmour CommandOptions() = default;
2155e14dc268SJim Ingham
2156e14dc268SJim Ingham ~CommandOptions() override = default;
2157e14dc268SJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)215897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2159e14dc268SJim Ingham ExecutionContext *execution_context) override {
216097206d57SZachary Turner Status error;
2161e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val;
2162e14dc268SJim Ingham
2163e14dc268SJim Ingham switch (short_option) {
2164e14dc268SJim Ingham case 'f':
2165adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg));
2166e14dc268SJim Ingham break;
21673acdf385SJim Ingham case 'N': {
216897206d57SZachary Turner Status name_error;
21693acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
21703acdf385SJim Ingham name_error)) {
21713acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
21723acdf385SJim Ingham name_error.AsCString());
21733acdf385SJim Ingham }
2174adcd0268SBenjamin Kramer m_names.push_back(std::string(option_arg));
21753acdf385SJim Ingham break;
21763acdf385SJim Ingham }
2177e14dc268SJim Ingham default:
217836162014SRaphael Isemann llvm_unreachable("Unimplemented option");
2179e14dc268SJim Ingham }
2180e14dc268SJim Ingham
2181e14dc268SJim Ingham return error;
2182e14dc268SJim Ingham }
2183e14dc268SJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)2184e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override {
2185e14dc268SJim Ingham m_filename.clear();
21863acdf385SJim Ingham m_names.clear();
2187e14dc268SJim Ingham }
2188e14dc268SJim Ingham
GetDefinitions()21891f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
219070602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options);
21911f0f5b5bSZachary Turner }
2192e14dc268SJim Ingham
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)219322e63cbaSGongyu Deng void HandleOptionArgumentCompletion(
219422e63cbaSGongyu Deng CompletionRequest &request, OptionElementVector &opt_element_vector,
219522e63cbaSGongyu Deng int opt_element_index, CommandInterpreter &interpreter) override {
219622e63cbaSGongyu Deng int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
219722e63cbaSGongyu Deng int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
219822e63cbaSGongyu Deng
219922e63cbaSGongyu Deng switch (GetDefinitions()[opt_defs_index].short_option) {
220022e63cbaSGongyu Deng case 'f':
220122e63cbaSGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
220222e63cbaSGongyu Deng interpreter, CommandCompletions::eDiskFileCompletion, request,
220322e63cbaSGongyu Deng nullptr);
220422e63cbaSGongyu Deng break;
220522e63cbaSGongyu Deng
220622e63cbaSGongyu Deng case 'N':
220722e63cbaSGongyu Deng llvm::Optional<FileSpec> file_spec;
220822e63cbaSGongyu Deng const llvm::StringRef dash_f("-f");
220922e63cbaSGongyu Deng for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
221022e63cbaSGongyu Deng if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
221122e63cbaSGongyu Deng file_spec.emplace(
221222e63cbaSGongyu Deng request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
221322e63cbaSGongyu Deng break;
221422e63cbaSGongyu Deng }
221522e63cbaSGongyu Deng }
221622e63cbaSGongyu Deng if (!file_spec)
221722e63cbaSGongyu Deng return;
221822e63cbaSGongyu Deng
221922e63cbaSGongyu Deng FileSystem::Instance().Resolve(*file_spec);
222022e63cbaSGongyu Deng Status error;
222122e63cbaSGongyu Deng StructuredData::ObjectSP input_data_sp =
222222e63cbaSGongyu Deng StructuredData::ParseJSONFromFile(*file_spec, error);
222322e63cbaSGongyu Deng if (!error.Success())
222422e63cbaSGongyu Deng return;
222522e63cbaSGongyu Deng
222622e63cbaSGongyu Deng StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
222722e63cbaSGongyu Deng if (!bkpt_array)
222822e63cbaSGongyu Deng return;
222922e63cbaSGongyu Deng
223022e63cbaSGongyu Deng const size_t num_bkpts = bkpt_array->GetSize();
223122e63cbaSGongyu Deng for (size_t i = 0; i < num_bkpts; i++) {
223222e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_object_sp =
223322e63cbaSGongyu Deng bkpt_array->GetItemAtIndex(i);
223422e63cbaSGongyu Deng if (!bkpt_object_sp)
223522e63cbaSGongyu Deng return;
223622e63cbaSGongyu Deng
223722e63cbaSGongyu Deng StructuredData::Dictionary *bkpt_dict =
223822e63cbaSGongyu Deng bkpt_object_sp->GetAsDictionary();
223922e63cbaSGongyu Deng if (!bkpt_dict)
224022e63cbaSGongyu Deng return;
224122e63cbaSGongyu Deng
224222e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_data_sp =
224322e63cbaSGongyu Deng bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
224422e63cbaSGongyu Deng if (!bkpt_data_sp)
224522e63cbaSGongyu Deng return;
224622e63cbaSGongyu Deng
224722e63cbaSGongyu Deng bkpt_dict = bkpt_data_sp->GetAsDictionary();
224822e63cbaSGongyu Deng if (!bkpt_dict)
224922e63cbaSGongyu Deng return;
225022e63cbaSGongyu Deng
225122e63cbaSGongyu Deng StructuredData::Array *names_array;
225222e63cbaSGongyu Deng
225322e63cbaSGongyu Deng if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
225422e63cbaSGongyu Deng return;
225522e63cbaSGongyu Deng
225622e63cbaSGongyu Deng size_t num_names = names_array->GetSize();
225722e63cbaSGongyu Deng
225822e63cbaSGongyu Deng for (size_t i = 0; i < num_names; i++) {
225922e63cbaSGongyu Deng llvm::StringRef name;
226022e63cbaSGongyu Deng if (names_array->GetItemAtIndexAsString(i, name))
226122e63cbaSGongyu Deng request.TryCompleteCurrentArg(name);
226222e63cbaSGongyu Deng }
226322e63cbaSGongyu Deng }
226422e63cbaSGongyu Deng }
226522e63cbaSGongyu Deng }
2266e14dc268SJim Ingham
2267e14dc268SJim Ingham std::string m_filename;
22683acdf385SJim Ingham std::vector<std::string> m_names;
2269e14dc268SJim Ingham };
2270e14dc268SJim Ingham
2271e14dc268SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)2272e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override {
2273cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget();
2274e14dc268SJim Ingham
22753acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock;
2276cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
22773acdf385SJim Ingham
22788f3be7a3SJonas Devlieghere FileSpec input_spec(m_options.m_filename);
22798f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(input_spec);
228001f16664SJim Ingham BreakpointIDList new_bps;
2281cb2380c9SRaphael Isemann Status error = target.CreateBreakpointsFromFile(input_spec,
2282cb2380c9SRaphael Isemann m_options.m_names, new_bps);
2283e14dc268SJim Ingham
2284e14dc268SJim Ingham if (!error.Success()) {
228501f16664SJim Ingham result.AppendError(error.AsCString());
228601f16664SJim Ingham return false;
2287e14dc268SJim Ingham }
22883acdf385SJim Ingham
22893acdf385SJim Ingham Stream &output_stream = result.GetOutputStream();
22903acdf385SJim Ingham
22913acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize();
22923acdf385SJim Ingham if (num_breakpoints == 0) {
22933acdf385SJim Ingham result.AppendMessage("No breakpoints added.");
22943acdf385SJim Ingham } else {
22953acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints.
22963acdf385SJim Ingham result.AppendMessage("New breakpoints:");
22973acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) {
22983acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2299cb2380c9SRaphael Isemann Breakpoint *bp = target.GetBreakpointList()
23003acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID())
23013acdf385SJim Ingham .get();
23023acdf385SJim Ingham if (bp)
23033acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
23043acdf385SJim Ingham false);
23053acdf385SJim Ingham }
23063acdf385SJim Ingham }
2307e14dc268SJim Ingham return result.Succeeded();
2308e14dc268SJim Ingham }
2309e14dc268SJim Ingham
2310e14dc268SJim Ingham private:
2311e14dc268SJim Ingham CommandOptions m_options;
2312e14dc268SJim Ingham };
2313e14dc268SJim Ingham
2314e14dc268SJim Ingham // CommandObjectBreakpointWrite
23151f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2316f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2317f94668e3SRaphael Isemann #include "CommandOptions.inc"
23181f0f5b5bSZachary Turner
23191f0f5b5bSZachary Turner #pragma mark Write
2320e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2321e14dc268SJim Ingham public:
CommandObjectBreakpointWrite(CommandInterpreter & interpreter)2322e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2323e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write",
2324e14dc268SJim Ingham "Write the breakpoints listed to a file that can "
2325e14dc268SJim Ingham "be read in with \"breakpoint read\". "
2326e14dc268SJim Ingham "If given no arguments, writes all breakpoints.",
2327abb0ed44SKazu Hirata nullptr) {
2328e14dc268SJim Ingham CommandArgumentEntry arg;
2329e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2330e14dc268SJim Ingham eArgTypeBreakpointIDRange);
2331e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's
2332e14dc268SJim Ingham // arguments vector.
2333e14dc268SJim Ingham m_arguments.push_back(arg);
2334e14dc268SJim Ingham }
2335e14dc268SJim Ingham
2336e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default;
2337e14dc268SJim Ingham
2338e87362e6SGongyu Deng void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2339e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request,
2340e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override {
2341e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks(
2342e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2343e87362e6SGongyu Deng request, nullptr);
2344e87362e6SGongyu Deng }
2345e87362e6SGongyu Deng
GetOptions()2346e14dc268SJim Ingham Options *GetOptions() override { return &m_options; }
2347e14dc268SJim Ingham
2348e14dc268SJim Ingham class CommandOptions : public Options {
2349e14dc268SJim Ingham public:
235024f9a2f5SShafik Yaghmour CommandOptions() = default;
2351e14dc268SJim Ingham
2352e14dc268SJim Ingham ~CommandOptions() override = default;
2353e14dc268SJim Ingham
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)235497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2355e14dc268SJim Ingham ExecutionContext *execution_context) override {
235697206d57SZachary Turner Status error;
2357e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val;
2358e14dc268SJim Ingham
2359e14dc268SJim Ingham switch (short_option) {
2360e14dc268SJim Ingham case 'f':
2361adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg));
2362e14dc268SJim Ingham break;
23632d3628e1SJim Ingham case 'a':
23642d3628e1SJim Ingham m_append = true;
23652d3628e1SJim Ingham break;
2366e14dc268SJim Ingham default:
236736162014SRaphael Isemann llvm_unreachable("Unimplemented option");
2368e14dc268SJim Ingham }
2369e14dc268SJim Ingham
2370e14dc268SJim Ingham return error;
2371e14dc268SJim Ingham }
2372e14dc268SJim Ingham
OptionParsingStarting(ExecutionContext * execution_context)2373e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override {
2374e14dc268SJim Ingham m_filename.clear();
23752d3628e1SJim Ingham m_append = false;
2376e14dc268SJim Ingham }
2377e14dc268SJim Ingham
GetDefinitions()23781f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
237970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options);
23801f0f5b5bSZachary Turner }
2381e14dc268SJim Ingham
2382e14dc268SJim Ingham // Instance variables to hold the values for command options.
2383e14dc268SJim Ingham
2384e14dc268SJim Ingham std::string m_filename;
23852d3628e1SJim Ingham bool m_append = false;
2386e14dc268SJim Ingham };
2387e14dc268SJim Ingham
2388e14dc268SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)2389e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override {
2390cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget();
2391e14dc268SJim Ingham
2392e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock;
2393cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock);
2394e14dc268SJim Ingham
2395e14dc268SJim Ingham BreakpointIDList valid_bp_ids;
239611eb9c64SZachary Turner if (!command.empty()) {
2397e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2398cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids,
2399b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm);
2400e14dc268SJim Ingham
240101f16664SJim Ingham if (!result.Succeeded()) {
2402e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed);
2403e14dc268SJim Ingham return false;
2404e14dc268SJim Ingham }
2405e14dc268SJim Ingham }
24068f3be7a3SJonas Devlieghere FileSpec file_spec(m_options.m_filename);
24078f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec);
2408cb2380c9SRaphael Isemann Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
24098f3be7a3SJonas Devlieghere m_options.m_append);
241001f16664SJim Ingham if (!error.Success()) {
241101f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.",
241201f16664SJim Ingham error.AsCString());
2413e14dc268SJim Ingham }
2414e14dc268SJim Ingham return result.Succeeded();
2415e14dc268SJim Ingham }
2416e14dc268SJim Ingham
2417e14dc268SJim Ingham private:
2418e14dc268SJim Ingham CommandOptions m_options;
2419e14dc268SJim Ingham };
2420e14dc268SJim Ingham
242130fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2422ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
242330fdc8d8SChris Lattner
CommandObjectMultiwordBreakpoint(CommandInterpreter & interpreter)2424b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2425b9c1b51eSKate Stone CommandInterpreter &interpreter)
2426b9c1b51eSKate Stone : CommandObjectMultiword(
2427b9c1b51eSKate Stone interpreter, "breakpoint",
24287428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2429b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") {
2430b9c1b51eSKate Stone CommandObjectSP list_command_object(
2431b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter));
2432b9c1b51eSKate Stone CommandObjectSP enable_command_object(
2433b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter));
2434b9c1b51eSKate Stone CommandObjectSP disable_command_object(
2435b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter));
2436b9c1b51eSKate Stone CommandObjectSP clear_command_object(
2437b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter));
2438b9c1b51eSKate Stone CommandObjectSP delete_command_object(
2439b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter));
2440b9c1b51eSKate Stone CommandObjectSP set_command_object(
2441b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter));
2442b9c1b51eSKate Stone CommandObjectSP command_command_object(
2443b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter));
2444b9c1b51eSKate Stone CommandObjectSP modify_command_object(
2445b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter));
2446b9c1b51eSKate Stone CommandObjectSP name_command_object(
2447b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter));
2448e14dc268SJim Ingham CommandObjectSP write_command_object(
2449e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter));
2450e14dc268SJim Ingham CommandObjectSP read_command_object(
2451e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter));
245230fdc8d8SChris Lattner
2453b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list");
245430fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable");
245530fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable");
2456b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear");
2457b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete");
2458ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set");
2459b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command");
2460b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify");
24615e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name");
2462e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write");
2463e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read");
246430fdc8d8SChris Lattner
246523f59509SGreg Clayton LoadSubCommand("list", list_command_object);
246623f59509SGreg Clayton LoadSubCommand("enable", enable_command_object);
246723f59509SGreg Clayton LoadSubCommand("disable", disable_command_object);
246823f59509SGreg Clayton LoadSubCommand("clear", clear_command_object);
246923f59509SGreg Clayton LoadSubCommand("delete", delete_command_object);
247023f59509SGreg Clayton LoadSubCommand("set", set_command_object);
247123f59509SGreg Clayton LoadSubCommand("command", command_command_object);
247223f59509SGreg Clayton LoadSubCommand("modify", modify_command_object);
24735e09c8c3SJim Ingham LoadSubCommand("name", name_command_object);
2474e14dc268SJim Ingham LoadSubCommand("write", write_command_object);
2475e14dc268SJim Ingham LoadSubCommand("read", read_command_object);
247630fdc8d8SChris Lattner }
247730fdc8d8SChris Lattner
24789e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
247930fdc8d8SChris Lattner
VerifyIDs(Args & args,Target * target,bool allow_locations,CommandReturnObject & result,BreakpointIDList * valid_ids,BreakpointName::Permissions::PermissionKinds purpose)2480a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs(
2481a925974bSAdrian Prantl Args &args, Target *target, bool allow_locations,
2482a925974bSAdrian Prantl CommandReturnObject &result, BreakpointIDList *valid_ids,
2483a925974bSAdrian Prantl BreakpointName::Permissions ::PermissionKinds purpose) {
248430fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids)
2485b9c1b51eSKate Stone // 2). the full breakpoint & location
2486b9c1b51eSKate Stone // canonical representation
2487b9c1b51eSKate Stone // 3). the word "to" or a hyphen,
2488b9c1b51eSKate Stone // representing a range (in which case there
2489b9c1b51eSKate Stone // had *better* be an entry both before &
2490b9c1b51eSKate Stone // after of one of the first two types.
24915e09c8c3SJim Ingham // 4). A breakpoint name
2492b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is
2493b9c1b51eSKate Stone // one.)
249430fdc8d8SChris Lattner
249530fdc8d8SChris Lattner Args temp_args;
249630fdc8d8SChris Lattner
249711eb9c64SZachary Turner if (args.empty()) {
2498b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) {
2499b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID(
2500b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
250136f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult);
2502b9c1b51eSKate Stone } else {
2503b9c1b51eSKate Stone result.AppendError(
2504b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint.");
250536f3b369SJim Ingham }
250636f3b369SJim Ingham return;
250736f3b369SJim Ingham }
250836f3b369SJim Ingham
2509b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
251005097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
251105097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the
251205097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings
251305097246SAdrian Prantl // into TEMP_ARGS.
251430fdc8d8SChris Lattner
2515b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2516b842f2ecSJim Ingham purpose, result, temp_args);
251730fdc8d8SChris Lattner
2518b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2519b9c1b51eSKate Stone // BreakpointIDList:
252030fdc8d8SChris Lattner
252116662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
252230fdc8d8SChris Lattner
252305097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have
252405097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids.
252530fdc8d8SChris Lattner
2526b9c1b51eSKate Stone if (result.Succeeded()) {
2527b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint
252805097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that
252905097246SAdrian Prantl // they correspond to valid/currently set breakpoints.
253030fdc8d8SChris Lattner
2531c982c768SGreg Clayton const size_t count = valid_ids->GetSize();
2532b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) {
253330fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2534b9c1b51eSKate Stone Breakpoint *breakpoint =
2535b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2536b9c1b51eSKate Stone if (breakpoint != nullptr) {
2537c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations();
2538b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
253930fdc8d8SChris Lattner StreamString id_str;
2540b9c1b51eSKate Stone BreakpointID::GetCanonicalReference(
2541b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2542c982c768SGreg Clayton i = valid_ids->GetSize() + 1;
2543b9c1b51eSKate Stone result.AppendErrorWithFormat(
2544b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n",
254530fdc8d8SChris Lattner id_str.GetData());
254630fdc8d8SChris Lattner }
2547b9c1b51eSKate Stone } else {
2548c982c768SGreg Clayton i = valid_ids->GetSize() + 1;
2549b9c1b51eSKate Stone result.AppendErrorWithFormat(
2550b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n",
25517428a18cSKate Stone cur_bp_id.GetBreakpointID());
255230fdc8d8SChris Lattner }
255330fdc8d8SChris Lattner }
255430fdc8d8SChris Lattner }
255530fdc8d8SChris Lattner }
2556