1 //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectBreakpoint.h"
10 #include "CommandObjectBreakpointCommand.h"
11 #include "lldb/Breakpoint/Breakpoint.h"
12 #include "lldb/Breakpoint/BreakpointIDList.h"
13 #include "lldb/Breakpoint/BreakpointLocation.h"
14 #include "lldb/Host/OptionParser.h"
15 #include "lldb/Interpreter/CommandCompletions.h"
16 #include "lldb/Interpreter/CommandInterpreter.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionValueBoolean.h"
20 #include "lldb/Interpreter/OptionValueString.h"
21 #include "lldb/Interpreter/OptionValueUInt64.h"
22 #include "lldb/Interpreter/Options.h"
23 #include "lldb/Target/Language.h"
24 #include "lldb/Target/StackFrame.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Target/ThreadSpec.h"
28 #include "lldb/Utility/RegularExpression.h"
29 #include "lldb/Utility/StreamString.h"
35 using namespace lldb_private;
37 static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38 lldb::DescriptionLevel level) {
40 bp->GetDescription(s, level, true);
45 // Modifiable Breakpoint Options
46 #pragma mark Modify::CommandOptions
47 static constexpr OptionDefinition g_breakpoint_modify_options[] = {
49 { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
50 { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
51 { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
52 { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
53 { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
54 { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
55 { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
56 { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
57 { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
58 { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
59 { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." },
62 class lldb_private::BreakpointOptionGroup : public OptionGroup
65 BreakpointOptionGroup() :
69 ~BreakpointOptionGroup() override = default;
71 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
72 return llvm::makeArrayRef(g_breakpoint_modify_options);
75 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
76 ExecutionContext *execution_context) override {
78 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
80 switch (short_option) {
82 // Normally an empty breakpoint condition marks is as unset. But we need
83 // to say it was passed in.
84 m_bp_opts.SetCondition(option_arg.str().c_str());
85 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
88 m_commands.push_back(option_arg);
91 m_bp_opts.SetEnabled(false);
94 m_bp_opts.SetEnabled(true);
98 value = OptionArgParser::ToBoolean(option_arg, false, &success);
100 m_bp_opts.SetAutoContinue(value);
102 error.SetErrorStringWithFormat(
103 "invalid boolean value '%s' passed for -G option",
104 option_arg.str().c_str());
109 uint32_t ignore_count;
110 if (option_arg.getAsInteger(0, ignore_count))
111 error.SetErrorStringWithFormat("invalid ignore count '%s'",
112 option_arg.str().c_str());
114 m_bp_opts.SetIgnoreCount(ignore_count);
119 value = OptionArgParser::ToBoolean(option_arg, false, &success);
121 m_bp_opts.SetOneShot(value);
123 error.SetErrorStringWithFormat(
124 "invalid boolean value '%s' passed for -o option",
125 option_arg.str().c_str());
129 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
130 if (option_arg[0] != '\0') {
131 if (option_arg.getAsInteger(0, thread_id))
132 error.SetErrorStringWithFormat("invalid thread id string '%s'",
133 option_arg.str().c_str());
135 m_bp_opts.SetThreadID(thread_id);
139 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
142 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
146 uint32_t thread_index = UINT32_MAX;
147 if (option_arg[0] != '\n') {
148 if (option_arg.getAsInteger(0, thread_index))
149 error.SetErrorStringWithFormat("invalid thread index string '%s'",
150 option_arg.str().c_str());
152 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
156 error.SetErrorStringWithFormat("unrecognized option '%c'",
164 void OptionParsingStarting(ExecutionContext *execution_context) override {
169 Status OptionParsingFinished(ExecutionContext *execution_context) override {
170 if (!m_commands.empty())
172 if (!m_commands.empty())
174 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
176 for (std::string &str : m_commands)
177 cmd_data->user_source.AppendString(str);
179 cmd_data->stop_on_error = true;
180 m_bp_opts.SetCommandDataCallback(cmd_data);
186 const BreakpointOptions &GetBreakpointOptions()
191 std::vector<std::string> m_commands;
192 BreakpointOptions m_bp_opts;
195 static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
197 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, "
198 "which prime new targets." },
202 class BreakpointDummyOptionGroup : public OptionGroup
205 BreakpointDummyOptionGroup() :
208 ~BreakpointDummyOptionGroup() override = default;
210 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
211 return llvm::makeArrayRef(g_breakpoint_dummy_options);
214 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
215 ExecutionContext *execution_context) override {
217 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
219 switch (short_option) {
224 error.SetErrorStringWithFormat("unrecognized option '%c'",
232 void OptionParsingStarting(ExecutionContext *execution_context) override {
240 // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
241 // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
242 #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
243 #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
244 #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
245 #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
246 #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
247 #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
249 static constexpr OptionDefinition g_breakpoint_set_options[] = {
251 { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option "
252 "multiple times to specify multiple shared libraries." },
253 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
254 { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
255 "lldb only looks for files that are #included if they use the standard include "
256 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
257 "#included, set target.inline-breakpoint-strategy to \"always\"." },
258 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
260 // Comment out this option for the moment, as we don't actually use it, but
261 // will in the future. This way users won't see it, but the infrastructure is
263 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
264 // "Set the breakpoint by source location at this particular column."},
266 { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to "
267 "a particular binary, then the address will be converted to a \"file\" "
268 "address, so that the breakpoint will track that binary+offset no matter where "
269 "the binary eventually loads. Alternately, if you also specify the module - "
270 "with the -s option - then the address will be treated as a file address in "
271 "that module, and resolved accordingly. Again, this will allow lldb to track "
272 "that offset on subsequent reloads. The module need not have been loaded at "
273 "the time you specify this breakpoint, and will get resolved when the module "
275 { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make "
276 "one breakpoint for multiple names" },
277 { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
278 "functions. Can be repeated multiple times." },
279 { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
280 "namespaces and all arguments, and for Objective-C this means a full function "
281 "prototype with class and selector. Can be repeated multiple times to make "
282 "one breakpoint for multiple names." },
283 { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
284 "make one breakpoint for multiple Selectors." },
285 { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to "
286 "make one breakpoint for multiple methods." },
287 { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find "
288 "the function name(s)." },
289 { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be "
290 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
292 { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched "
293 "against the source text in a source file or files specified with the -f "
294 "option. The -f option can be specified more than once. If no source files "
295 "are specified, uses the current \"default source file\". If you want to "
296 "match against all source files, pass the \"--all-files\" option." },
297 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
298 { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
299 { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
300 { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
301 { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
302 "options, on throw but not catch.)" },
303 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
304 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
306 // Don't add this option till it actually does something useful...
307 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
308 // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" },
310 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
311 "(note: currently only implemented for setting breakpoints on identifiers). "
312 "If not set the target.language setting is used." },
313 { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. "
314 "If not set the target.skip-prologue setting is used." },
315 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
316 { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
317 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
318 { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
319 "setting is used." },
323 // CommandObjectBreakpointSet
325 class CommandObjectBreakpointSet : public CommandObjectParsed {
327 enum BreakpointSetType {
331 eSetTypeFunctionName,
332 eSetTypeFunctionRegexp,
333 eSetTypeSourceRegexp,
338 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
339 : CommandObjectParsed(
340 interpreter, "breakpoint set",
341 "Sets a breakpoint or set of breakpoints in the executable.",
342 "breakpoint set <cmd-options>"),
343 m_bp_opts(), m_options() {
344 // We're picking up all the normal options, commands and disable.
345 m_all_options.Append(&m_bp_opts,
346 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
348 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
349 m_all_options.Append(&m_options);
350 m_all_options.Finalize();
353 ~CommandObjectBreakpointSet() override = default;
355 Options *GetOptions() override { return &m_all_options; }
357 class CommandOptions : public OptionGroup {
360 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
361 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
362 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
363 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
364 m_exception_language(eLanguageTypeUnknown),
365 m_language(lldb::eLanguageTypeUnknown),
366 m_skip_prologue(eLazyBoolCalculate),
367 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
369 ~CommandOptions() override = default;
371 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
372 ExecutionContext *execution_context) override {
374 const int short_option = g_breakpoint_set_options[option_idx].short_option;
376 switch (short_option) {
378 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
379 LLDB_INVALID_ADDRESS, &error);
387 m_func_names.push_back(option_arg);
388 m_func_name_type_mask |= eFunctionNameTypeBase;
392 if (option_arg.getAsInteger(0, m_column))
393 error.SetErrorStringWithFormat("invalid column number: %s",
394 option_arg.str().c_str());
398 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
401 case eLanguageTypeC89:
403 case eLanguageTypeC99:
404 case eLanguageTypeC11:
405 m_exception_language = eLanguageTypeC;
407 case eLanguageTypeC_plus_plus:
408 case eLanguageTypeC_plus_plus_03:
409 case eLanguageTypeC_plus_plus_11:
410 case eLanguageTypeC_plus_plus_14:
411 m_exception_language = eLanguageTypeC_plus_plus;
413 case eLanguageTypeObjC:
414 m_exception_language = eLanguageTypeObjC;
416 case eLanguageTypeObjC_plus_plus:
417 error.SetErrorStringWithFormat(
418 "Set exception breakpoints separately for c++ and objective-c");
420 case eLanguageTypeUnknown:
421 error.SetErrorStringWithFormat(
422 "Unknown language type: '%s' for exception breakpoint",
423 option_arg.str().c_str());
426 error.SetErrorStringWithFormat(
427 "Unsupported language type: '%s' for exception breakpoint",
428 option_arg.str().c_str());
433 m_filenames.AppendIfUnique(FileSpec(option_arg));
437 m_func_names.push_back(option_arg);
438 m_func_name_type_mask |= eFunctionNameTypeFull;
443 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
445 error.SetErrorStringWithFormat(
446 "Invalid boolean value for on-catch option: '%s'",
447 option_arg.str().c_str());
455 if (m_current_key.empty())
456 m_current_key.assign(option_arg);
458 error.SetErrorStringWithFormat("Key: %s missing value.",
459 m_current_key.c_str());
465 value = OptionArgParser::ToBoolean(option_arg, true, &success);
467 m_skip_prologue = eLazyBoolYes;
469 m_skip_prologue = eLazyBoolNo;
472 error.SetErrorStringWithFormat(
473 "Invalid boolean value for skip prologue option: '%s'",
474 option_arg.str().c_str());
478 if (option_arg.getAsInteger(0, m_line_num))
479 error.SetErrorStringWithFormat("invalid line number: %s.",
480 option_arg.str().c_str());
484 m_language = Language::GetLanguageTypeFromString(option_arg);
485 if (m_language == eLanguageTypeUnknown)
486 error.SetErrorStringWithFormat(
487 "Unknown language type: '%s' for breakpoint",
488 option_arg.str().c_str());
494 value = OptionArgParser::ToBoolean(option_arg, true, &success);
496 m_move_to_nearest_code = eLazyBoolYes;
498 m_move_to_nearest_code = eLazyBoolNo;
501 error.SetErrorStringWithFormat(
502 "Invalid boolean value for move-to-nearest-code option: '%s'",
503 option_arg.str().c_str());
508 m_func_names.push_back(option_arg);
509 m_func_name_type_mask |= eFunctionNameTypeMethod;
513 m_func_names.push_back(option_arg);
514 m_func_name_type_mask |= eFunctionNameTypeAuto;
518 if (BreakpointID::StringIsBreakpointName(option_arg, error))
519 m_breakpoint_names.push_back(option_arg);
521 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
522 option_arg.str().c_str());
527 lldb::addr_t tmp_offset_addr;
528 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
529 option_arg, 0, &error);
531 m_offset_addr = tmp_offset_addr;
535 m_exception_extra_args.AppendArgument("-O");
536 m_exception_extra_args.AppendArgument(option_arg);
540 m_source_text_regexp.assign(option_arg);
544 m_python_class.assign(option_arg);
548 m_func_regexp.assign(option_arg);
552 m_modules.AppendIfUnique(FileSpec(option_arg));
556 m_func_names.push_back(option_arg);
557 m_func_name_type_mask |= eFunctionNameTypeSelector;
561 if (!m_current_key.empty()) {
562 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
563 m_current_key.clear();
566 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
567 option_arg.str().c_str());
572 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
574 error.SetErrorStringWithFormat(
575 "Invalid boolean value for on-throw option: '%s'",
576 option_arg.str().c_str());
580 m_source_regex_func_names.insert(option_arg);
584 error.SetErrorStringWithFormat("unrecognized option '%c'",
592 void OptionParsingStarting(ExecutionContext *execution_context) override {
596 m_func_names.clear();
597 m_func_name_type_mask = eFunctionNameTypeNone;
598 m_func_regexp.clear();
599 m_source_text_regexp.clear();
601 m_load_addr = LLDB_INVALID_ADDRESS;
606 m_exception_language = eLanguageTypeUnknown;
607 m_language = lldb::eLanguageTypeUnknown;
608 m_skip_prologue = eLazyBoolCalculate;
609 m_breakpoint_names.clear();
611 m_exception_extra_args.Clear();
612 m_move_to_nearest_code = eLazyBoolCalculate;
613 m_source_regex_func_names.clear();
614 m_python_class.clear();
615 m_extra_args_sp = std::make_shared<StructuredData::Dictionary>();
616 m_current_key.clear();
619 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
620 return llvm::makeArrayRef(g_breakpoint_set_options);
623 // Instance variables to hold the values for command options.
625 std::string m_condition;
626 FileSpecList m_filenames;
629 std::vector<std::string> m_func_names;
630 std::vector<std::string> m_breakpoint_names;
631 lldb::FunctionNameType m_func_name_type_mask;
632 std::string m_func_regexp;
633 std::string m_source_text_regexp;
634 FileSpecList m_modules;
635 lldb::addr_t m_load_addr;
636 lldb::addr_t m_offset_addr;
639 bool m_hardware; // Request to use hardware breakpoints
640 lldb::LanguageType m_exception_language;
641 lldb::LanguageType m_language;
642 LazyBool m_skip_prologue;
644 Args m_exception_extra_args;
645 LazyBool m_move_to_nearest_code;
646 std::unordered_set<std::string> m_source_regex_func_names;
647 std::string m_python_class;
648 StructuredData::DictionarySP m_extra_args_sp;
649 std::string m_current_key;
653 bool DoExecute(Args &command, CommandReturnObject &result) override {
654 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
656 if (target == nullptr) {
657 result.AppendError("Invalid target. Must set target before setting "
658 "breakpoints (see 'target create' command).");
659 result.SetStatus(eReturnStatusFailed);
663 // The following are the various types of breakpoints that could be set:
664 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
665 // 2). -a [-s -g] (setting breakpoint by address)
666 // 3). -n [-s -g] (setting breakpoint by function name)
667 // 4). -r [-s -g] (setting breakpoint by function name regular
669 // 5). -p -f (setting a breakpoint by comparing a reg-exp
671 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
674 BreakpointSetType break_type = eSetTypeInvalid;
676 if (!m_options.m_python_class.empty())
677 break_type = eSetTypeScripted;
678 else if (m_options.m_line_num != 0)
679 break_type = eSetTypeFileAndLine;
680 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
681 break_type = eSetTypeAddress;
682 else if (!m_options.m_func_names.empty())
683 break_type = eSetTypeFunctionName;
684 else if (!m_options.m_func_regexp.empty())
685 break_type = eSetTypeFunctionRegexp;
686 else if (!m_options.m_source_text_regexp.empty())
687 break_type = eSetTypeSourceRegexp;
688 else if (m_options.m_exception_language != eLanguageTypeUnknown)
689 break_type = eSetTypeException;
691 BreakpointSP bp_sp = nullptr;
692 FileSpec module_spec;
693 const bool internal = false;
695 // If the user didn't specify skip-prologue, having an offset should turn
697 if (m_options.m_offset_addr != 0 &&
698 m_options.m_skip_prologue == eLazyBoolCalculate)
699 m_options.m_skip_prologue = eLazyBoolNo;
701 switch (break_type) {
702 case eSetTypeFileAndLine: // Breakpoint by source position
705 const size_t num_files = m_options.m_filenames.GetSize();
706 if (num_files == 0) {
707 if (!GetDefaultFile(target, file, result)) {
708 result.AppendError("No file supplied and no default file available.");
709 result.SetStatus(eReturnStatusFailed);
712 } else if (num_files > 1) {
713 result.AppendError("Only one file at a time is allowed for file and "
714 "line breakpoints.");
715 result.SetStatus(eReturnStatusFailed);
718 file = m_options.m_filenames.GetFileSpecAtIndex(0);
720 // Only check for inline functions if
721 LazyBool check_inlines = eLazyBoolCalculate;
723 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
725 m_options.m_line_num,
727 m_options.m_offset_addr,
729 m_options.m_skip_prologue,
731 m_options.m_hardware,
732 m_options.m_move_to_nearest_code);
735 case eSetTypeAddress: // Breakpoint by address
737 // If a shared library has been specified, make an lldb_private::Address
738 // with the library, and use that. That way the address breakpoint
739 // will track the load location of the library.
740 size_t num_modules_specified = m_options.m_modules.GetSize();
741 if (num_modules_specified == 1) {
742 const FileSpec *file_spec =
743 m_options.m_modules.GetFileSpecPointerAtIndex(0);
744 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
746 m_options.m_hardware);
747 } else if (num_modules_specified == 0) {
748 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
749 m_options.m_hardware);
751 result.AppendError("Only one shared library can be specified for "
752 "address breakpoints.");
753 result.SetStatus(eReturnStatusFailed);
758 case eSetTypeFunctionName: // Breakpoint by function name
760 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
762 if (name_type_mask == 0)
763 name_type_mask = eFunctionNameTypeAuto;
765 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
766 &(m_options.m_filenames),
767 m_options.m_func_names,
769 m_options.m_language,
770 m_options.m_offset_addr,
771 m_options.m_skip_prologue,
773 m_options.m_hardware);
776 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
779 RegularExpression regexp(m_options.m_func_regexp);
780 if (!regexp.IsValid()) {
782 regexp.GetErrorAsCString(err_str, sizeof(err_str));
783 result.AppendErrorWithFormat(
784 "Function name regular expression could not be compiled: \"%s\"",
786 result.SetStatus(eReturnStatusFailed);
790 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
791 &(m_options.m_filenames),
793 m_options.m_language,
794 m_options.m_skip_prologue,
796 m_options.m_hardware);
799 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
801 const size_t num_files = m_options.m_filenames.GetSize();
803 if (num_files == 0 && !m_options.m_all_files) {
805 if (!GetDefaultFile(target, file, result)) {
807 "No files provided and could not find default file.");
808 result.SetStatus(eReturnStatusFailed);
811 m_options.m_filenames.Append(file);
815 RegularExpression regexp(m_options.m_source_text_regexp);
816 if (!regexp.IsValid()) {
818 regexp.GetErrorAsCString(err_str, sizeof(err_str));
819 result.AppendErrorWithFormat(
820 "Source text regular expression could not be compiled: \"%s\"",
822 result.SetStatus(eReturnStatusFailed);
826 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
827 &(m_options.m_filenames),
829 .m_source_regex_func_names,
832 m_options.m_hardware,
833 m_options.m_move_to_nearest_code);
835 case eSetTypeException: {
836 Status precond_error;
837 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
838 m_options.m_catch_bp,
839 m_options.m_throw_bp,
842 .m_exception_extra_args,
844 if (precond_error.Fail()) {
845 result.AppendErrorWithFormat(
846 "Error setting extra exception arguments: %s",
847 precond_error.AsCString());
848 target->RemoveBreakpointByID(bp_sp->GetID());
849 result.SetStatus(eReturnStatusFailed);
853 case eSetTypeScripted: {
856 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
857 &(m_options.m_modules),
858 &(m_options.m_filenames),
860 m_options.m_hardware,
861 m_options.m_extra_args_sp,
864 result.AppendErrorWithFormat(
865 "Error setting extra exception arguments: %s",
867 target->RemoveBreakpointByID(bp_sp->GetID());
868 result.SetStatus(eReturnStatusFailed);
876 // Now set the various options that were passed in:
878 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
880 if (!m_options.m_breakpoint_names.empty()) {
882 for (auto name : m_options.m_breakpoint_names) {
883 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
884 if (name_error.Fail()) {
885 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
887 target->RemoveBreakpointByID(bp_sp->GetID());
888 result.SetStatus(eReturnStatusFailed);
896 Stream &output_stream = result.GetOutputStream();
897 const bool show_locations = false;
898 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
900 if (target == GetDebugger().GetDummyTarget())
901 output_stream.Printf("Breakpoint set in dummy target, will get copied "
902 "into future targets.\n");
904 // Don't print out this warning for exception breakpoints. They can
905 // get set before the target is set, but we won't know how to actually
906 // set the breakpoint till we run.
907 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
908 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
909 "actual locations.\n");
912 result.SetStatus(eReturnStatusSuccessFinishResult);
914 result.AppendError("Breakpoint creation failed: No breakpoint created.");
915 result.SetStatus(eReturnStatusFailed);
918 return result.Succeeded();
922 bool GetDefaultFile(Target *target, FileSpec &file,
923 CommandReturnObject &result) {
924 uint32_t default_line;
925 // First use the Source Manager's default file. Then use the current stack
927 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
928 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
929 if (cur_frame == nullptr) {
931 "No selected frame to use to find the default file.");
932 result.SetStatus(eReturnStatusFailed);
934 } else if (!cur_frame->HasDebugInformation()) {
935 result.AppendError("Cannot use the selected frame to find the default "
936 "file, it has no debug info.");
937 result.SetStatus(eReturnStatusFailed);
940 const SymbolContext &sc =
941 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
942 if (sc.line_entry.file) {
943 file = sc.line_entry.file;
945 result.AppendError("Can't find the file for the selected frame to "
946 "use as the default file.");
947 result.SetStatus(eReturnStatusFailed);
955 BreakpointOptionGroup m_bp_opts;
956 BreakpointDummyOptionGroup m_dummy_options;
957 CommandOptions m_options;
958 OptionGroupOptions m_all_options;
961 // CommandObjectBreakpointModify
964 class CommandObjectBreakpointModify : public CommandObjectParsed {
966 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
967 : CommandObjectParsed(interpreter, "breakpoint modify",
968 "Modify the options on a breakpoint or set of "
969 "breakpoints in the executable. "
970 "If no breakpoint is specified, acts on the last "
971 "created breakpoint. "
972 "With the exception of -e, -d and -i, passing an "
973 "empty argument clears the modification.",
976 CommandArgumentEntry arg;
977 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
978 eArgTypeBreakpointIDRange);
979 // Add the entry for the first argument for this command to the object's
981 m_arguments.push_back(arg);
983 m_options.Append(&m_bp_opts,
984 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
986 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
987 m_options.Finalize();
990 ~CommandObjectBreakpointModify() override = default;
992 Options *GetOptions() override { return &m_options; }
995 bool DoExecute(Args &command, CommandReturnObject &result) override {
996 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
997 if (target == nullptr) {
998 result.AppendError("Invalid target. No existing target or breakpoints.");
999 result.SetStatus(eReturnStatusFailed);
1003 std::unique_lock<std::recursive_mutex> lock;
1004 target->GetBreakpointList().GetListMutex(lock);
1006 BreakpointIDList valid_bp_ids;
1008 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1009 command, target, result, &valid_bp_ids,
1010 BreakpointName::Permissions::PermissionKinds::disablePerm);
1012 if (result.Succeeded()) {
1013 const size_t count = valid_bp_ids.GetSize();
1014 for (size_t i = 0; i < count; ++i) {
1015 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1017 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1019 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1020 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1021 BreakpointLocation *location =
1022 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
1024 location->GetLocationOptions()
1025 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
1028 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
1034 return result.Succeeded();
1038 BreakpointOptionGroup m_bp_opts;
1039 BreakpointDummyOptionGroup m_dummy_opts;
1040 OptionGroupOptions m_options;
1043 // CommandObjectBreakpointEnable
1046 class CommandObjectBreakpointEnable : public CommandObjectParsed {
1048 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1049 : CommandObjectParsed(interpreter, "enable",
1050 "Enable the specified disabled breakpoint(s). If "
1051 "no breakpoints are specified, enable all of them.",
1053 CommandArgumentEntry arg;
1054 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1055 eArgTypeBreakpointIDRange);
1056 // Add the entry for the first argument for this command to the object's
1057 // arguments vector.
1058 m_arguments.push_back(arg);
1061 ~CommandObjectBreakpointEnable() override = default;
1064 bool DoExecute(Args &command, CommandReturnObject &result) override {
1065 Target *target = GetSelectedOrDummyTarget();
1066 if (target == nullptr) {
1067 result.AppendError("Invalid target. No existing target or breakpoints.");
1068 result.SetStatus(eReturnStatusFailed);
1072 std::unique_lock<std::recursive_mutex> lock;
1073 target->GetBreakpointList().GetListMutex(lock);
1075 const BreakpointList &breakpoints = target->GetBreakpointList();
1077 size_t num_breakpoints = breakpoints.GetSize();
1079 if (num_breakpoints == 0) {
1080 result.AppendError("No breakpoints exist to be enabled.");
1081 result.SetStatus(eReturnStatusFailed);
1085 if (command.empty()) {
1086 // No breakpoint selected; enable all currently set breakpoints.
1087 target->EnableAllowedBreakpoints();
1088 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1090 (uint64_t)num_breakpoints);
1091 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1093 // Particular breakpoint selected; enable that breakpoint.
1094 BreakpointIDList valid_bp_ids;
1095 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1096 command, target, result, &valid_bp_ids,
1097 BreakpointName::Permissions::PermissionKinds::disablePerm);
1099 if (result.Succeeded()) {
1100 int enable_count = 0;
1102 const size_t count = valid_bp_ids.GetSize();
1103 for (size_t i = 0; i < count; ++i) {
1104 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1106 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1107 Breakpoint *breakpoint =
1108 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1109 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1110 BreakpointLocation *location =
1111 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1113 location->SetEnabled(true);
1117 breakpoint->SetEnabled(true);
1122 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1123 enable_count + loc_count);
1124 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1128 return result.Succeeded();
1132 // CommandObjectBreakpointDisable
1133 #pragma mark Disable
1135 class CommandObjectBreakpointDisable : public CommandObjectParsed {
1137 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1138 : CommandObjectParsed(
1139 interpreter, "breakpoint disable",
1140 "Disable the specified breakpoint(s) without deleting "
1141 "them. If none are specified, disable all "
1145 "Disable the specified breakpoint(s) without deleting them. \
1146 If none are specified, disable all breakpoints."
1150 "Note: disabling a breakpoint will cause none of its locations to be hit \
1151 regardless of whether individual locations are enabled or disabled. After the sequence:"
1154 (lldb) break disable 1
1155 (lldb) break enable 1.1
1157 execution will NOT stop at location 1.1. To achieve that, type:
1159 (lldb) break disable 1.*
1160 (lldb) break enable 1.1
1163 "The first command disables all locations for breakpoint 1, \
1164 the second re-enables the first location.");
1166 CommandArgumentEntry arg;
1167 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1168 eArgTypeBreakpointIDRange);
1169 // Add the entry for the first argument for this command to the object's
1170 // arguments vector.
1171 m_arguments.push_back(arg);
1174 ~CommandObjectBreakpointDisable() override = default;
1177 bool DoExecute(Args &command, CommandReturnObject &result) override {
1178 Target *target = GetSelectedOrDummyTarget();
1179 if (target == nullptr) {
1180 result.AppendError("Invalid target. No existing target or breakpoints.");
1181 result.SetStatus(eReturnStatusFailed);
1185 std::unique_lock<std::recursive_mutex> lock;
1186 target->GetBreakpointList().GetListMutex(lock);
1188 const BreakpointList &breakpoints = target->GetBreakpointList();
1189 size_t num_breakpoints = breakpoints.GetSize();
1191 if (num_breakpoints == 0) {
1192 result.AppendError("No breakpoints exist to be disabled.");
1193 result.SetStatus(eReturnStatusFailed);
1197 if (command.empty()) {
1198 // No breakpoint selected; disable all currently set breakpoints.
1199 target->DisableAllowedBreakpoints();
1200 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1202 (uint64_t)num_breakpoints);
1203 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1205 // Particular breakpoint selected; disable that breakpoint.
1206 BreakpointIDList valid_bp_ids;
1208 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1209 command, target, result, &valid_bp_ids,
1210 BreakpointName::Permissions::PermissionKinds::disablePerm);
1212 if (result.Succeeded()) {
1213 int disable_count = 0;
1215 const size_t count = valid_bp_ids.GetSize();
1216 for (size_t i = 0; i < count; ++i) {
1217 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1219 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1220 Breakpoint *breakpoint =
1221 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1222 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1223 BreakpointLocation *location =
1224 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1226 location->SetEnabled(false);
1230 breakpoint->SetEnabled(false);
1235 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1236 disable_count + loc_count);
1237 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1241 return result.Succeeded();
1245 // CommandObjectBreakpointList
1247 #pragma mark List::CommandOptions
1248 static constexpr OptionDefinition g_breakpoint_list_options[] = {
1249 // FIXME: We need to add an "internal" command, and then add this sort of
1250 // thing to it. But I need to see it for now, and don't want to wait.
1251 #define LLDB_OPTIONS_breakpoint_list
1252 #include "CommandOptions.inc"
1257 class CommandObjectBreakpointList : public CommandObjectParsed {
1259 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1260 : CommandObjectParsed(
1261 interpreter, "breakpoint list",
1262 "List some or all breakpoints at configurable levels of detail.",
1265 CommandArgumentEntry arg;
1266 CommandArgumentData bp_id_arg;
1268 // Define the first (and only) variant of this arg.
1269 bp_id_arg.arg_type = eArgTypeBreakpointID;
1270 bp_id_arg.arg_repetition = eArgRepeatOptional;
1272 // There is only one variant this argument could be; put it into the
1274 arg.push_back(bp_id_arg);
1276 // Push the data for the first argument into the m_arguments vector.
1277 m_arguments.push_back(arg);
1280 ~CommandObjectBreakpointList() override = default;
1282 Options *GetOptions() override { return &m_options; }
1284 class CommandOptions : public Options {
1287 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
1290 ~CommandOptions() override = default;
1292 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1293 ExecutionContext *execution_context) override {
1295 const int short_option = m_getopt_table[option_idx].val;
1297 switch (short_option) {
1299 m_level = lldb::eDescriptionLevelBrief;
1305 m_level = lldb::eDescriptionLevelFull;
1308 m_level = lldb::eDescriptionLevelVerbose;
1314 error.SetErrorStringWithFormat("unrecognized option '%c'",
1322 void OptionParsingStarting(ExecutionContext *execution_context) override {
1323 m_level = lldb::eDescriptionLevelFull;
1325 m_use_dummy = false;
1328 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1329 return llvm::makeArrayRef(g_breakpoint_list_options);
1332 // Instance variables to hold the values for command options.
1334 lldb::DescriptionLevel m_level;
1341 bool DoExecute(Args &command, CommandReturnObject &result) override {
1342 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1344 if (target == nullptr) {
1345 result.AppendError("Invalid target. No current target or breakpoints.");
1346 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1350 const BreakpointList &breakpoints =
1351 target->GetBreakpointList(m_options.m_internal);
1352 std::unique_lock<std::recursive_mutex> lock;
1353 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1355 size_t num_breakpoints = breakpoints.GetSize();
1357 if (num_breakpoints == 0) {
1358 result.AppendMessage("No breakpoints currently set.");
1359 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1363 Stream &output_stream = result.GetOutputStream();
1365 if (command.empty()) {
1366 // No breakpoint selected; show info about all currently set breakpoints.
1367 result.AppendMessage("Current breakpoints:");
1368 for (size_t i = 0; i < num_breakpoints; ++i) {
1369 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1370 if (breakpoint->AllowList())
1371 AddBreakpointDescription(&output_stream, breakpoint,
1374 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1376 // Particular breakpoints selected; show info about that breakpoint.
1377 BreakpointIDList valid_bp_ids;
1378 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1379 command, target, result, &valid_bp_ids,
1380 BreakpointName::Permissions::PermissionKinds::listPerm);
1382 if (result.Succeeded()) {
1383 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1384 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1385 Breakpoint *breakpoint =
1386 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1387 AddBreakpointDescription(&output_stream, breakpoint,
1390 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1392 result.AppendError("Invalid breakpoint ID.");
1393 result.SetStatus(eReturnStatusFailed);
1397 return result.Succeeded();
1401 CommandOptions m_options;
1404 // CommandObjectBreakpointClear
1405 #pragma mark Clear::CommandOptions
1407 static constexpr OptionDefinition g_breakpoint_clear_options[] = {
1409 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1410 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
1416 class CommandObjectBreakpointClear : public CommandObjectParsed {
1418 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1420 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1421 : CommandObjectParsed(interpreter, "breakpoint clear",
1422 "Delete or disable breakpoints matching the "
1423 "specified source file and line.",
1424 "breakpoint clear <cmd-options>"),
1427 ~CommandObjectBreakpointClear() override = default;
1429 Options *GetOptions() override { return &m_options; }
1431 class CommandOptions : public Options {
1433 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1435 ~CommandOptions() override = default;
1437 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1438 ExecutionContext *execution_context) override {
1440 const int short_option = m_getopt_table[option_idx].val;
1442 switch (short_option) {
1444 m_filename.assign(option_arg);
1448 option_arg.getAsInteger(0, m_line_num);
1452 error.SetErrorStringWithFormat("unrecognized option '%c'",
1460 void OptionParsingStarting(ExecutionContext *execution_context) override {
1465 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1466 return llvm::makeArrayRef(g_breakpoint_clear_options);
1469 // Instance variables to hold the values for command options.
1471 std::string m_filename;
1472 uint32_t m_line_num;
1476 bool DoExecute(Args &command, CommandReturnObject &result) override {
1477 Target *target = GetSelectedOrDummyTarget();
1478 if (target == nullptr) {
1479 result.AppendError("Invalid target. No existing target or breakpoints.");
1480 result.SetStatus(eReturnStatusFailed);
1484 // The following are the various types of breakpoints that could be
1486 // 1). -f -l (clearing breakpoint by source location)
1488 BreakpointClearType break_type = eClearTypeInvalid;
1490 if (m_options.m_line_num != 0)
1491 break_type = eClearTypeFileAndLine;
1493 std::unique_lock<std::recursive_mutex> lock;
1494 target->GetBreakpointList().GetListMutex(lock);
1496 BreakpointList &breakpoints = target->GetBreakpointList();
1497 size_t num_breakpoints = breakpoints.GetSize();
1499 // Early return if there's no breakpoint at all.
1500 if (num_breakpoints == 0) {
1501 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1502 result.SetStatus(eReturnStatusFailed);
1503 return result.Succeeded();
1506 // Find matching breakpoints and delete them.
1508 // First create a copy of all the IDs.
1509 std::vector<break_id_t> BreakIDs;
1510 for (size_t i = 0; i < num_breakpoints; ++i)
1511 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1513 int num_cleared = 0;
1515 switch (break_type) {
1516 case eClearTypeFileAndLine: // Breakpoint by source position
1518 const ConstString filename(m_options.m_filename.c_str());
1519 BreakpointLocationCollection loc_coll;
1521 for (size_t i = 0; i < num_breakpoints; ++i) {
1522 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1524 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1525 // If the collection size is 0, it's a full match and we can just
1526 // remove the breakpoint.
1527 if (loc_coll.GetSize() == 0) {
1528 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1530 target->RemoveBreakpointByID(bp->GetID());
1541 if (num_cleared > 0) {
1542 Stream &output_stream = result.GetOutputStream();
1543 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1544 output_stream << ss.GetString();
1545 output_stream.EOL();
1546 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1548 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1549 result.SetStatus(eReturnStatusFailed);
1552 return result.Succeeded();
1556 CommandOptions m_options;
1559 // CommandObjectBreakpointDelete
1560 static constexpr OptionDefinition g_breakpoint_delete_options[] = {
1562 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1563 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1569 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1571 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1572 : CommandObjectParsed(interpreter, "breakpoint delete",
1573 "Delete the specified breakpoint(s). If no "
1574 "breakpoints are specified, delete them all.",
1577 CommandArgumentEntry arg;
1578 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1579 eArgTypeBreakpointIDRange);
1580 // Add the entry for the first argument for this command to the object's
1581 // arguments vector.
1582 m_arguments.push_back(arg);
1585 ~CommandObjectBreakpointDelete() override = default;
1587 Options *GetOptions() override { return &m_options; }
1589 class CommandOptions : public Options {
1591 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1593 ~CommandOptions() override = default;
1595 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1596 ExecutionContext *execution_context) override {
1598 const int short_option = m_getopt_table[option_idx].val;
1600 switch (short_option) {
1610 error.SetErrorStringWithFormat("unrecognized option '%c'",
1618 void OptionParsingStarting(ExecutionContext *execution_context) override {
1619 m_use_dummy = false;
1623 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1624 return llvm::makeArrayRef(g_breakpoint_delete_options);
1627 // Instance variables to hold the values for command options.
1633 bool DoExecute(Args &command, CommandReturnObject &result) override {
1634 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1636 if (target == nullptr) {
1637 result.AppendError("Invalid target. No existing target or breakpoints.");
1638 result.SetStatus(eReturnStatusFailed);
1642 std::unique_lock<std::recursive_mutex> lock;
1643 target->GetBreakpointList().GetListMutex(lock);
1645 const BreakpointList &breakpoints = target->GetBreakpointList();
1647 size_t num_breakpoints = breakpoints.GetSize();
1649 if (num_breakpoints == 0) {
1650 result.AppendError("No breakpoints exist to be deleted.");
1651 result.SetStatus(eReturnStatusFailed);
1655 if (command.empty()) {
1656 if (!m_options.m_force &&
1657 !m_interpreter.Confirm(
1658 "About to delete all breakpoints, do you want to do that?",
1660 result.AppendMessage("Operation cancelled...");
1662 target->RemoveAllowedBreakpoints();
1663 result.AppendMessageWithFormat(
1664 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1665 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1667 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1669 // Particular breakpoint selected; disable that breakpoint.
1670 BreakpointIDList valid_bp_ids;
1671 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1672 command, target, result, &valid_bp_ids,
1673 BreakpointName::Permissions::PermissionKinds::deletePerm);
1675 if (result.Succeeded()) {
1676 int delete_count = 0;
1677 int disable_count = 0;
1678 const size_t count = valid_bp_ids.GetSize();
1679 for (size_t i = 0; i < count; ++i) {
1680 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1682 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1683 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1684 Breakpoint *breakpoint =
1685 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1686 BreakpointLocation *location =
1687 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1688 // It makes no sense to try to delete individual locations, so we
1689 // disable them instead.
1691 location->SetEnabled(false);
1695 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1700 result.AppendMessageWithFormat(
1701 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1702 delete_count, disable_count);
1703 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1706 return result.Succeeded();
1710 CommandOptions m_options;
1713 // CommandObjectBreakpointName
1715 static constexpr OptionDefinition g_breakpoint_name_options[] = {
1717 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1718 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1719 {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1720 {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."},
1723 class BreakpointNameOptionGroup : public OptionGroup {
1725 BreakpointNameOptionGroup()
1726 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1729 ~BreakpointNameOptionGroup() override = default;
1731 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1732 return llvm::makeArrayRef(g_breakpoint_name_options);
1735 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1736 ExecutionContext *execution_context) override {
1738 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1740 switch (short_option) {
1742 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1744 m_name.SetValueFromString(option_arg);
1747 if (m_breakpoint.SetValueFromString(option_arg).Fail())
1748 error.SetErrorStringWithFormat(
1749 "unrecognized value \"%s\" for breakpoint",
1750 option_arg.str().c_str());
1753 if (m_use_dummy.SetValueFromString(option_arg).Fail())
1754 error.SetErrorStringWithFormat(
1755 "unrecognized value \"%s\" for use-dummy",
1756 option_arg.str().c_str());
1759 m_help_string.SetValueFromString(option_arg);
1763 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1770 void OptionParsingStarting(ExecutionContext *execution_context) override {
1772 m_breakpoint.Clear();
1773 m_use_dummy.Clear();
1774 m_use_dummy.SetDefaultValue(false);
1775 m_help_string.Clear();
1778 OptionValueString m_name;
1779 OptionValueUInt64 m_breakpoint;
1780 OptionValueBoolean m_use_dummy;
1781 OptionValueString m_help_string;
1784 static constexpr OptionDefinition g_breakpoint_access_options[] = {
1786 {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
1787 {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
1788 {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."},
1792 class BreakpointAccessOptionGroup : public OptionGroup {
1794 BreakpointAccessOptionGroup() : OptionGroup() {}
1796 ~BreakpointAccessOptionGroup() override = default;
1798 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1799 return llvm::makeArrayRef(g_breakpoint_access_options);
1801 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1802 ExecutionContext *execution_context) override {
1804 const int short_option
1805 = g_breakpoint_access_options[option_idx].short_option;
1807 switch (short_option) {
1809 bool value, success;
1810 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1812 m_permissions.SetAllowList(value);
1814 error.SetErrorStringWithFormat(
1815 "invalid boolean value '%s' passed for -L option",
1816 option_arg.str().c_str());
1819 bool value, success;
1820 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1822 m_permissions.SetAllowDisable(value);
1824 error.SetErrorStringWithFormat(
1825 "invalid boolean value '%s' passed for -L option",
1826 option_arg.str().c_str());
1829 bool value, success;
1830 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1832 m_permissions.SetAllowDelete(value);
1834 error.SetErrorStringWithFormat(
1835 "invalid boolean value '%s' passed for -L option",
1836 option_arg.str().c_str());
1844 void OptionParsingStarting(ExecutionContext *execution_context) override {
1847 const BreakpointName::Permissions &GetPermissions() const
1849 return m_permissions;
1851 BreakpointName::Permissions m_permissions;
1854 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1856 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1857 : CommandObjectParsed(
1858 interpreter, "configure", "Configure the options for the breakpoint"
1860 "If you provide a breakpoint id, the options will be copied from "
1861 "the breakpoint, otherwise only the options specified will be set "
1863 "breakpoint name configure <command-options> "
1864 "<breakpoint-name-list>"),
1865 m_bp_opts(), m_option_group() {
1866 // Create the first variant for the first (and only) argument for this
1868 CommandArgumentEntry arg1;
1869 CommandArgumentData id_arg;
1870 id_arg.arg_type = eArgTypeBreakpointName;
1871 id_arg.arg_repetition = eArgRepeatOptional;
1872 arg1.push_back(id_arg);
1873 m_arguments.push_back(arg1);
1875 m_option_group.Append(&m_bp_opts,
1878 m_option_group.Append(&m_access_options,
1881 m_option_group.Append(&m_bp_id,
1882 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1884 m_option_group.Finalize();
1887 ~CommandObjectBreakpointNameConfigure() override = default;
1889 Options *GetOptions() override { return &m_option_group; }
1892 bool DoExecute(Args &command, CommandReturnObject &result) override {
1894 const size_t argc = command.GetArgumentCount();
1896 result.AppendError("No names provided.");
1897 result.SetStatus(eReturnStatusFailed);
1902 GetSelectedOrDummyTarget(false);
1904 if (target == nullptr) {
1905 result.AppendError("Invalid target. No existing target or breakpoints.");
1906 result.SetStatus(eReturnStatusFailed);
1910 std::unique_lock<std::recursive_mutex> lock;
1911 target->GetBreakpointList().GetListMutex(lock);
1913 // Make a pass through first to see that all the names are legal.
1914 for (auto &entry : command.entries()) {
1916 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1918 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1919 entry.c_str(), error.AsCString());
1920 result.SetStatus(eReturnStatusFailed);
1924 // Now configure them, we already pre-checked the names so we don't need to
1927 if (m_bp_id.m_breakpoint.OptionWasSet())
1929 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1930 bp_sp = target->GetBreakpointByID(bp_id);
1933 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1935 result.SetStatus(eReturnStatusFailed);
1941 for (auto &entry : command.entries()) {
1942 ConstString name(entry.c_str());
1943 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1946 if (m_bp_id.m_help_string.OptionWasSet())
1947 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1950 target->ConfigureBreakpointName(*bp_name,
1951 *bp_sp->GetOptions(),
1952 m_access_options.GetPermissions());
1954 target->ConfigureBreakpointName(*bp_name,
1955 m_bp_opts.GetBreakpointOptions(),
1956 m_access_options.GetPermissions());
1962 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1963 BreakpointOptionGroup m_bp_opts;
1964 BreakpointAccessOptionGroup m_access_options;
1965 OptionGroupOptions m_option_group;
1968 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1970 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1971 : CommandObjectParsed(
1972 interpreter, "add", "Add a name to the breakpoints provided.",
1973 "breakpoint name add <command-options> <breakpoint-id-list>"),
1974 m_name_options(), m_option_group() {
1975 // Create the first variant for the first (and only) argument for this
1977 CommandArgumentEntry arg1;
1978 CommandArgumentData id_arg;
1979 id_arg.arg_type = eArgTypeBreakpointID;
1980 id_arg.arg_repetition = eArgRepeatOptional;
1981 arg1.push_back(id_arg);
1982 m_arguments.push_back(arg1);
1984 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1985 m_option_group.Finalize();
1988 ~CommandObjectBreakpointNameAdd() override = default;
1990 Options *GetOptions() override { return &m_option_group; }
1993 bool DoExecute(Args &command, CommandReturnObject &result) override {
1994 if (!m_name_options.m_name.OptionWasSet()) {
1995 result.SetError("No name option provided.");
2000 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2002 if (target == nullptr) {
2003 result.AppendError("Invalid target. No existing target or breakpoints.");
2004 result.SetStatus(eReturnStatusFailed);
2008 std::unique_lock<std::recursive_mutex> lock;
2009 target->GetBreakpointList().GetListMutex(lock);
2011 const BreakpointList &breakpoints = target->GetBreakpointList();
2013 size_t num_breakpoints = breakpoints.GetSize();
2014 if (num_breakpoints == 0) {
2015 result.SetError("No breakpoints, cannot add names.");
2016 result.SetStatus(eReturnStatusFailed);
2020 // Particular breakpoint selected; disable that breakpoint.
2021 BreakpointIDList valid_bp_ids;
2022 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2023 command, target, result, &valid_bp_ids,
2024 BreakpointName::Permissions::PermissionKinds::listPerm);
2026 if (result.Succeeded()) {
2027 if (valid_bp_ids.GetSize() == 0) {
2028 result.SetError("No breakpoints specified, cannot add names.");
2029 result.SetStatus(eReturnStatusFailed);
2032 size_t num_valid_ids = valid_bp_ids.GetSize();
2033 const char *bp_name = m_name_options.m_name.GetCurrentValue();
2034 Status error; // This error reports illegal names, but we've already
2035 // checked that, so we don't need to check it again here.
2036 for (size_t index = 0; index < num_valid_ids; index++) {
2037 lldb::break_id_t bp_id =
2038 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2039 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2040 target->AddNameToBreakpoint(bp_sp, bp_name, error);
2048 BreakpointNameOptionGroup m_name_options;
2049 OptionGroupOptions m_option_group;
2052 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
2054 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2055 : CommandObjectParsed(
2056 interpreter, "delete",
2057 "Delete a name from the breakpoints provided.",
2058 "breakpoint name delete <command-options> <breakpoint-id-list>"),
2059 m_name_options(), m_option_group() {
2060 // Create the first variant for the first (and only) argument for this
2062 CommandArgumentEntry arg1;
2063 CommandArgumentData id_arg;
2064 id_arg.arg_type = eArgTypeBreakpointID;
2065 id_arg.arg_repetition = eArgRepeatOptional;
2066 arg1.push_back(id_arg);
2067 m_arguments.push_back(arg1);
2069 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2070 m_option_group.Finalize();
2073 ~CommandObjectBreakpointNameDelete() override = default;
2075 Options *GetOptions() override { return &m_option_group; }
2078 bool DoExecute(Args &command, CommandReturnObject &result) override {
2079 if (!m_name_options.m_name.OptionWasSet()) {
2080 result.SetError("No name option provided.");
2085 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2087 if (target == nullptr) {
2088 result.AppendError("Invalid target. No existing target or breakpoints.");
2089 result.SetStatus(eReturnStatusFailed);
2093 std::unique_lock<std::recursive_mutex> lock;
2094 target->GetBreakpointList().GetListMutex(lock);
2096 const BreakpointList &breakpoints = target->GetBreakpointList();
2098 size_t num_breakpoints = breakpoints.GetSize();
2099 if (num_breakpoints == 0) {
2100 result.SetError("No breakpoints, cannot delete names.");
2101 result.SetStatus(eReturnStatusFailed);
2105 // Particular breakpoint selected; disable that breakpoint.
2106 BreakpointIDList valid_bp_ids;
2107 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2108 command, target, result, &valid_bp_ids,
2109 BreakpointName::Permissions::PermissionKinds::deletePerm);
2111 if (result.Succeeded()) {
2112 if (valid_bp_ids.GetSize() == 0) {
2113 result.SetError("No breakpoints specified, cannot delete names.");
2114 result.SetStatus(eReturnStatusFailed);
2117 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
2118 size_t num_valid_ids = valid_bp_ids.GetSize();
2119 for (size_t index = 0; index < num_valid_ids; index++) {
2120 lldb::break_id_t bp_id =
2121 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2122 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2123 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
2131 BreakpointNameOptionGroup m_name_options;
2132 OptionGroupOptions m_option_group;
2135 class CommandObjectBreakpointNameList : public CommandObjectParsed {
2137 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2138 : CommandObjectParsed(interpreter, "list",
2139 "List either the names for a breakpoint or info "
2140 "about a given name. With no arguments, lists all "
2142 "breakpoint name list <command-options>"),
2143 m_name_options(), m_option_group() {
2144 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
2145 m_option_group.Finalize();
2148 ~CommandObjectBreakpointNameList() override = default;
2150 Options *GetOptions() override { return &m_option_group; }
2153 bool DoExecute(Args &command, CommandReturnObject &result) override {
2155 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2157 if (target == nullptr) {
2158 result.AppendError("Invalid target. No existing target or breakpoints.");
2159 result.SetStatus(eReturnStatusFailed);
2164 std::vector<std::string> name_list;
2165 if (command.empty()) {
2166 target->GetBreakpointNames(name_list);
2168 for (const Args::ArgEntry &arg : command)
2170 name_list.push_back(arg.c_str());
2174 if (name_list.empty()) {
2175 result.AppendMessage("No breakpoint names found.");
2177 for (const std::string &name_str : name_list) {
2178 const char *name = name_str.c_str();
2179 // First print out the options for the name:
2181 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2187 result.AppendMessageWithFormat("Name: %s\n", name);
2188 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2190 result.AppendMessage(s.GetString());
2193 std::unique_lock<std::recursive_mutex> lock;
2194 target->GetBreakpointList().GetListMutex(lock);
2196 BreakpointList &breakpoints = target->GetBreakpointList();
2197 bool any_set = false;
2198 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2199 if (bp_sp->MatchesName(name)) {
2202 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2204 result.AppendMessage(s.GetString());
2208 result.AppendMessage("No breakpoints using this name.");
2210 result.AppendMessageWithFormat("Name: %s not found.\n", name);
2218 BreakpointNameOptionGroup m_name_options;
2219 OptionGroupOptions m_option_group;
2222 // CommandObjectBreakpointName
2223 class CommandObjectBreakpointName : public CommandObjectMultiword {
2225 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2226 : CommandObjectMultiword(
2227 interpreter, "name", "Commands to manage name tags for breakpoints",
2228 "breakpoint name <subcommand> [<command-options>]") {
2229 CommandObjectSP add_command_object(
2230 new CommandObjectBreakpointNameAdd(interpreter));
2231 CommandObjectSP delete_command_object(
2232 new CommandObjectBreakpointNameDelete(interpreter));
2233 CommandObjectSP list_command_object(
2234 new CommandObjectBreakpointNameList(interpreter));
2235 CommandObjectSP configure_command_object(
2236 new CommandObjectBreakpointNameConfigure(interpreter));
2238 LoadSubCommand("add", add_command_object);
2239 LoadSubCommand("delete", delete_command_object);
2240 LoadSubCommand("list", list_command_object);
2241 LoadSubCommand("configure", configure_command_object);
2244 ~CommandObjectBreakpointName() override = default;
2247 // CommandObjectBreakpointRead
2248 #pragma mark Read::CommandOptions
2249 static constexpr OptionDefinition g_breakpoint_read_options[] = {
2251 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2252 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
2258 class CommandObjectBreakpointRead : public CommandObjectParsed {
2260 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2261 : CommandObjectParsed(interpreter, "breakpoint read",
2262 "Read and set the breakpoints previously saved to "
2263 "a file with \"breakpoint write\". ",
2266 CommandArgumentEntry arg;
2267 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2268 eArgTypeBreakpointIDRange);
2269 // Add the entry for the first argument for this command to the object's
2270 // arguments vector.
2271 m_arguments.push_back(arg);
2274 ~CommandObjectBreakpointRead() override = default;
2276 Options *GetOptions() override { return &m_options; }
2278 class CommandOptions : public Options {
2280 CommandOptions() : Options() {}
2282 ~CommandOptions() override = default;
2284 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2285 ExecutionContext *execution_context) override {
2287 const int short_option = m_getopt_table[option_idx].val;
2289 switch (short_option) {
2291 m_filename.assign(option_arg);
2295 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2297 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2298 name_error.AsCString());
2300 m_names.push_back(option_arg);
2304 error.SetErrorStringWithFormat("unrecognized option '%c'",
2312 void OptionParsingStarting(ExecutionContext *execution_context) override {
2317 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2318 return llvm::makeArrayRef(g_breakpoint_read_options);
2321 // Instance variables to hold the values for command options.
2323 std::string m_filename;
2324 std::vector<std::string> m_names;
2328 bool DoExecute(Args &command, CommandReturnObject &result) override {
2329 Target *target = GetSelectedOrDummyTarget();
2330 if (target == nullptr) {
2331 result.AppendError("Invalid target. No existing target or breakpoints.");
2332 result.SetStatus(eReturnStatusFailed);
2336 std::unique_lock<std::recursive_mutex> lock;
2337 target->GetBreakpointList().GetListMutex(lock);
2339 FileSpec input_spec(m_options.m_filename);
2340 FileSystem::Instance().Resolve(input_spec);
2341 BreakpointIDList new_bps;
2342 Status error = target->CreateBreakpointsFromFile(
2343 input_spec, m_options.m_names, new_bps);
2345 if (!error.Success()) {
2346 result.AppendError(error.AsCString());
2347 result.SetStatus(eReturnStatusFailed);
2351 Stream &output_stream = result.GetOutputStream();
2353 size_t num_breakpoints = new_bps.GetSize();
2354 if (num_breakpoints == 0) {
2355 result.AppendMessage("No breakpoints added.");
2357 // No breakpoint selected; show info about all currently set breakpoints.
2358 result.AppendMessage("New breakpoints:");
2359 for (size_t i = 0; i < num_breakpoints; ++i) {
2360 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2361 Breakpoint *bp = target->GetBreakpointList()
2362 .FindBreakpointByID(bp_id.GetBreakpointID())
2365 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2369 return result.Succeeded();
2373 CommandOptions m_options;
2376 // CommandObjectBreakpointWrite
2377 #pragma mark Write::CommandOptions
2378 static constexpr OptionDefinition g_breakpoint_write_options[] = {
2380 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2381 { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
2386 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2388 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2389 : CommandObjectParsed(interpreter, "breakpoint write",
2390 "Write the breakpoints listed to a file that can "
2391 "be read in with \"breakpoint read\". "
2392 "If given no arguments, writes all breakpoints.",
2395 CommandArgumentEntry arg;
2396 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2397 eArgTypeBreakpointIDRange);
2398 // Add the entry for the first argument for this command to the object's
2399 // arguments vector.
2400 m_arguments.push_back(arg);
2403 ~CommandObjectBreakpointWrite() override = default;
2405 Options *GetOptions() override { return &m_options; }
2407 class CommandOptions : public Options {
2409 CommandOptions() : Options() {}
2411 ~CommandOptions() override = default;
2413 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2414 ExecutionContext *execution_context) override {
2416 const int short_option = m_getopt_table[option_idx].val;
2418 switch (short_option) {
2420 m_filename.assign(option_arg);
2426 error.SetErrorStringWithFormat("unrecognized option '%c'",
2434 void OptionParsingStarting(ExecutionContext *execution_context) override {
2439 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2440 return llvm::makeArrayRef(g_breakpoint_write_options);
2443 // Instance variables to hold the values for command options.
2445 std::string m_filename;
2446 bool m_append = false;
2450 bool DoExecute(Args &command, CommandReturnObject &result) override {
2451 Target *target = GetSelectedOrDummyTarget();
2452 if (target == nullptr) {
2453 result.AppendError("Invalid target. No existing target or breakpoints.");
2454 result.SetStatus(eReturnStatusFailed);
2458 std::unique_lock<std::recursive_mutex> lock;
2459 target->GetBreakpointList().GetListMutex(lock);
2461 BreakpointIDList valid_bp_ids;
2462 if (!command.empty()) {
2463 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2464 command, target, result, &valid_bp_ids,
2465 BreakpointName::Permissions::PermissionKinds::listPerm);
2467 if (!result.Succeeded()) {
2468 result.SetStatus(eReturnStatusFailed);
2472 FileSpec file_spec(m_options.m_filename);
2473 FileSystem::Instance().Resolve(file_spec);
2474 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2475 m_options.m_append);
2476 if (!error.Success()) {
2477 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2479 result.SetStatus(eReturnStatusFailed);
2481 return result.Succeeded();
2485 CommandOptions m_options;
2488 // CommandObjectMultiwordBreakpoint
2489 #pragma mark MultiwordBreakpoint
2491 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2492 CommandInterpreter &interpreter)
2493 : CommandObjectMultiword(
2494 interpreter, "breakpoint",
2495 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2496 "breakpoint <subcommand> [<command-options>]") {
2497 CommandObjectSP list_command_object(
2498 new CommandObjectBreakpointList(interpreter));
2499 CommandObjectSP enable_command_object(
2500 new CommandObjectBreakpointEnable(interpreter));
2501 CommandObjectSP disable_command_object(
2502 new CommandObjectBreakpointDisable(interpreter));
2503 CommandObjectSP clear_command_object(
2504 new CommandObjectBreakpointClear(interpreter));
2505 CommandObjectSP delete_command_object(
2506 new CommandObjectBreakpointDelete(interpreter));
2507 CommandObjectSP set_command_object(
2508 new CommandObjectBreakpointSet(interpreter));
2509 CommandObjectSP command_command_object(
2510 new CommandObjectBreakpointCommand(interpreter));
2511 CommandObjectSP modify_command_object(
2512 new CommandObjectBreakpointModify(interpreter));
2513 CommandObjectSP name_command_object(
2514 new CommandObjectBreakpointName(interpreter));
2515 CommandObjectSP write_command_object(
2516 new CommandObjectBreakpointWrite(interpreter));
2517 CommandObjectSP read_command_object(
2518 new CommandObjectBreakpointRead(interpreter));
2520 list_command_object->SetCommandName("breakpoint list");
2521 enable_command_object->SetCommandName("breakpoint enable");
2522 disable_command_object->SetCommandName("breakpoint disable");
2523 clear_command_object->SetCommandName("breakpoint clear");
2524 delete_command_object->SetCommandName("breakpoint delete");
2525 set_command_object->SetCommandName("breakpoint set");
2526 command_command_object->SetCommandName("breakpoint command");
2527 modify_command_object->SetCommandName("breakpoint modify");
2528 name_command_object->SetCommandName("breakpoint name");
2529 write_command_object->SetCommandName("breakpoint write");
2530 read_command_object->SetCommandName("breakpoint read");
2532 LoadSubCommand("list", list_command_object);
2533 LoadSubCommand("enable", enable_command_object);
2534 LoadSubCommand("disable", disable_command_object);
2535 LoadSubCommand("clear", clear_command_object);
2536 LoadSubCommand("delete", delete_command_object);
2537 LoadSubCommand("set", set_command_object);
2538 LoadSubCommand("command", command_command_object);
2539 LoadSubCommand("modify", modify_command_object);
2540 LoadSubCommand("name", name_command_object);
2541 LoadSubCommand("write", write_command_object);
2542 LoadSubCommand("read", read_command_object);
2545 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2547 void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2548 bool allow_locations,
2549 CommandReturnObject &result,
2550 BreakpointIDList *valid_ids,
2551 BreakpointName::Permissions
2554 // args can be strings representing 1). integers (for breakpoint ids)
2555 // 2). the full breakpoint & location
2556 // canonical representation
2557 // 3). the word "to" or a hyphen,
2558 // representing a range (in which case there
2559 // had *better* be an entry both before &
2560 // after of one of the first two types.
2561 // 4). A breakpoint name
2562 // If args is empty, we will use the last created breakpoint (if there is
2568 if (target->GetLastCreatedBreakpoint()) {
2569 valid_ids->AddBreakpointID(BreakpointID(
2570 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2571 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2574 "No breakpoint specified and no last created breakpoint.");
2575 result.SetStatus(eReturnStatusFailed);
2580 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2581 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2582 // id range strings over; instead generate a list of strings for all the
2583 // breakpoint ids in the range, and shove all of those breakpoint id strings
2586 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2587 purpose, result, temp_args);
2589 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2590 // BreakpointIDList:
2592 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2594 // At this point, all of the breakpoint ids that the user passed in have
2595 // been converted to breakpoint IDs and put into valid_ids.
2597 if (result.Succeeded()) {
2598 // Now that we've converted everything from args into a list of breakpoint
2599 // ids, go through our tentative list of breakpoint id's and verify that
2600 // they correspond to valid/currently set breakpoints.
2602 const size_t count = valid_ids->GetSize();
2603 for (size_t i = 0; i < count; ++i) {
2604 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2605 Breakpoint *breakpoint =
2606 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2607 if (breakpoint != nullptr) {
2608 const size_t num_locations = breakpoint->GetNumLocations();
2609 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2610 StreamString id_str;
2611 BreakpointID::GetCanonicalReference(
2612 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2613 i = valid_ids->GetSize() + 1;
2614 result.AppendErrorWithFormat(
2615 "'%s' is not a currently valid breakpoint/location id.\n",
2617 result.SetStatus(eReturnStatusFailed);
2620 i = valid_ids->GetSize() + 1;
2621 result.AppendErrorWithFormat(
2622 "'%d' is not a currently valid breakpoint ID.\n",
2623 cur_bp_id.GetBreakpointID());
2624 result.SetStatus(eReturnStatusFailed);