1 //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 #include "CommandObjectBreakpoint.h"
13 #include "CommandObjectBreakpointCommand.h"
14 #include "lldb/Breakpoint/Breakpoint.h"
15 #include "lldb/Breakpoint/BreakpointIDList.h"
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Host/OptionParser.h"
18 #include "lldb/Interpreter/CommandCompletions.h"
19 #include "lldb/Interpreter/CommandInterpreter.h"
20 #include "lldb/Interpreter/CommandReturnObject.h"
21 #include "lldb/Interpreter/OptionArgParser.h"
22 #include "lldb/Interpreter/OptionValueBoolean.h"
23 #include "lldb/Interpreter/OptionValueString.h"
24 #include "lldb/Interpreter/OptionValueUInt64.h"
25 #include "lldb/Interpreter/Options.h"
26 #include "lldb/Target/Language.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Target/ThreadSpec.h"
31 #include "lldb/Utility/RegularExpression.h"
32 #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 //-------------------------------------------------------------------------
46 // Modifiable Breakpoint Options
47 //-------------------------------------------------------------------------
48 #pragma mark Modify::CommandOptions
49 static constexpr OptionDefinition g_breakpoint_modify_options[] = {
51 { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
52 { 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." },
53 { 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." },
54 { 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." },
55 { 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." },
56 { 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." },
57 { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
58 { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
59 { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
60 { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
61 { 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." },
64 class lldb_private::BreakpointOptionGroup : public OptionGroup
67 BreakpointOptionGroup() :
71 ~BreakpointOptionGroup() override = default;
73 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
74 return llvm::makeArrayRef(g_breakpoint_modify_options);
77 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
78 ExecutionContext *execution_context) override {
80 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
82 switch (short_option) {
84 // Normally an empty breakpoint condition marks is as unset. But we need
85 // to say it was passed in.
86 m_bp_opts.SetCondition(option_arg.str().c_str());
87 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
90 m_commands.push_back(option_arg);
93 m_bp_opts.SetEnabled(false);
96 m_bp_opts.SetEnabled(true);
100 value = OptionArgParser::ToBoolean(option_arg, false, &success);
102 m_bp_opts.SetAutoContinue(value);
104 error.SetErrorStringWithFormat(
105 "invalid boolean value '%s' passed for -G option",
106 option_arg.str().c_str());
111 uint32_t ignore_count;
112 if (option_arg.getAsInteger(0, ignore_count))
113 error.SetErrorStringWithFormat("invalid ignore count '%s'",
114 option_arg.str().c_str());
116 m_bp_opts.SetIgnoreCount(ignore_count);
121 value = OptionArgParser::ToBoolean(option_arg, false, &success);
123 m_bp_opts.SetOneShot(value);
125 error.SetErrorStringWithFormat(
126 "invalid boolean value '%s' passed for -o option",
127 option_arg.str().c_str());
131 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
132 if (option_arg[0] != '\0') {
133 if (option_arg.getAsInteger(0, thread_id))
134 error.SetErrorStringWithFormat("invalid thread id string '%s'",
135 option_arg.str().c_str());
137 m_bp_opts.SetThreadID(thread_id);
141 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
144 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
148 uint32_t thread_index = UINT32_MAX;
149 if (option_arg[0] != '\n') {
150 if (option_arg.getAsInteger(0, thread_index))
151 error.SetErrorStringWithFormat("invalid thread index string '%s'",
152 option_arg.str().c_str());
154 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
158 error.SetErrorStringWithFormat("unrecognized option '%c'",
166 void OptionParsingStarting(ExecutionContext *execution_context) override {
171 Status OptionParsingFinished(ExecutionContext *execution_context) override {
172 if (!m_commands.empty())
174 if (!m_commands.empty())
176 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
178 for (std::string &str : m_commands)
179 cmd_data->user_source.AppendString(str);
181 cmd_data->stop_on_error = true;
182 m_bp_opts.SetCommandDataCallback(cmd_data);
188 const BreakpointOptions &GetBreakpointOptions()
193 std::vector<std::string> m_commands;
194 BreakpointOptions m_bp_opts;
197 static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
199 { 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, "
200 "which prime new targets." },
204 class BreakpointDummyOptionGroup : public OptionGroup
207 BreakpointDummyOptionGroup() :
210 ~BreakpointDummyOptionGroup() override = default;
212 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
213 return llvm::makeArrayRef(g_breakpoint_dummy_options);
216 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
217 ExecutionContext *execution_context) override {
219 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
221 switch (short_option) {
226 error.SetErrorStringWithFormat("unrecognized option '%c'",
234 void OptionParsingStarting(ExecutionContext *execution_context) override {
242 // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
243 // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
244 #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
245 #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
246 #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
247 #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
248 #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
249 #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
251 static constexpr OptionDefinition g_breakpoint_set_options[] = {
253 { 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 "
254 "multiple times to specify multiple shared libraries." },
255 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
256 { 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 "
257 "lldb only looks for files that are #included if they use the standard include "
258 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
259 "#included, set target.inline-breakpoint-strategy to \"always\"." },
260 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
262 // Comment out this option for the moment, as we don't actually use it, but
263 // will in the future. This way users won't see it, but the infrastructure is
265 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
266 // "Set the breakpoint by source location at this particular column."},
268 { 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 "
269 "a particular binary, then the address will be converted to a \"file\" "
270 "address, so that the breakpoint will track that binary+offset no matter where "
271 "the binary eventually loads. Alternately, if you also specify the module - "
272 "with the -s option - then the address will be treated as a file address in "
273 "that module, and resolved accordingly. Again, this will allow lldb to track "
274 "that offset on subsequent reloads. The module need not have been loaded at "
275 "the time you specify this breakpoint, and will get resolved when the module "
277 { 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 "
278 "one breakpoint for multiple names" },
279 { 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 "
280 "functions. Can be repeated multiple times." },
281 { 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 "
282 "namespaces and all arguments, and for Objective-C this means a full function "
283 "prototype with class and selector. Can be repeated multiple times to make "
284 "one breakpoint for multiple names." },
285 { 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 "
286 "make one breakpoint for multiple Selectors." },
287 { 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 "
288 "make one breakpoint for multiple methods." },
289 { 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 "
290 "the function name(s)." },
291 { 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 "
292 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
294 { 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 "
295 "against the source text in a source file or files specified with the -f "
296 "option. The -f option can be specified more than once. If no source files "
297 "are specified, uses the current \"default source file\". If you want to "
298 "match against all source files, pass the \"--all-files\" option." },
299 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
300 { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
301 { 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." },
302 { 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." },
303 { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
304 "options, on throw but not catch.)" },
305 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
306 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
308 // Don't add this option till it actually does something useful...
309 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
310 // "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" },
312 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
313 "(note: currently only implemented for setting breakpoints on identifiers). "
314 "If not set the target.language setting is used." },
315 { 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. "
316 "If not set the target.skip-prologue setting is used." },
317 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
318 { 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. "
319 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
320 { 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 "
321 "setting is used." },
325 //-------------------------------------------------------------------------
326 // CommandObjectBreakpointSet
327 //-------------------------------------------------------------------------
329 class CommandObjectBreakpointSet : public CommandObjectParsed {
331 typedef enum BreakpointSetType {
335 eSetTypeFunctionName,
336 eSetTypeFunctionRegexp,
337 eSetTypeSourceRegexp,
342 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
343 : CommandObjectParsed(
344 interpreter, "breakpoint set",
345 "Sets a breakpoint or set of breakpoints in the executable.",
346 "breakpoint set <cmd-options>"),
347 m_bp_opts(), m_options() {
348 // We're picking up all the normal options, commands and disable.
349 m_all_options.Append(&m_bp_opts,
350 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
352 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
353 m_all_options.Append(&m_options);
354 m_all_options.Finalize();
357 ~CommandObjectBreakpointSet() override = default;
359 Options *GetOptions() override { return &m_all_options; }
361 class CommandOptions : public OptionGroup {
364 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
365 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
366 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
367 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
368 m_exception_language(eLanguageTypeUnknown),
369 m_language(lldb::eLanguageTypeUnknown),
370 m_skip_prologue(eLazyBoolCalculate),
371 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
373 ~CommandOptions() override = default;
375 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
376 ExecutionContext *execution_context) override {
378 const int short_option = g_breakpoint_set_options[option_idx].short_option;
380 switch (short_option) {
382 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
383 LLDB_INVALID_ADDRESS, &error);
391 m_func_names.push_back(option_arg);
392 m_func_name_type_mask |= eFunctionNameTypeBase;
396 if (option_arg.getAsInteger(0, m_column))
397 error.SetErrorStringWithFormat("invalid column number: %s",
398 option_arg.str().c_str());
402 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
405 case eLanguageTypeC89:
407 case eLanguageTypeC99:
408 case eLanguageTypeC11:
409 m_exception_language = eLanguageTypeC;
411 case eLanguageTypeC_plus_plus:
412 case eLanguageTypeC_plus_plus_03:
413 case eLanguageTypeC_plus_plus_11:
414 case eLanguageTypeC_plus_plus_14:
415 m_exception_language = eLanguageTypeC_plus_plus;
417 case eLanguageTypeObjC:
418 m_exception_language = eLanguageTypeObjC;
420 case eLanguageTypeObjC_plus_plus:
421 error.SetErrorStringWithFormat(
422 "Set exception breakpoints separately for c++ and objective-c");
424 case eLanguageTypeUnknown:
425 error.SetErrorStringWithFormat(
426 "Unknown language type: '%s' for exception breakpoint",
427 option_arg.str().c_str());
430 error.SetErrorStringWithFormat(
431 "Unsupported language type: '%s' for exception breakpoint",
432 option_arg.str().c_str());
437 m_filenames.AppendIfUnique(FileSpec(option_arg));
441 m_func_names.push_back(option_arg);
442 m_func_name_type_mask |= eFunctionNameTypeFull;
447 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
449 error.SetErrorStringWithFormat(
450 "Invalid boolean value for on-catch option: '%s'",
451 option_arg.str().c_str());
459 if (m_current_key.empty())
460 m_current_key.assign(option_arg);
462 error.SetErrorStringWithFormat("Key: %s missing value.",
463 m_current_key.c_str());
469 value = OptionArgParser::ToBoolean(option_arg, true, &success);
471 m_skip_prologue = eLazyBoolYes;
473 m_skip_prologue = eLazyBoolNo;
476 error.SetErrorStringWithFormat(
477 "Invalid boolean value for skip prologue option: '%s'",
478 option_arg.str().c_str());
482 if (option_arg.getAsInteger(0, m_line_num))
483 error.SetErrorStringWithFormat("invalid line number: %s.",
484 option_arg.str().c_str());
488 m_language = Language::GetLanguageTypeFromString(option_arg);
489 if (m_language == eLanguageTypeUnknown)
490 error.SetErrorStringWithFormat(
491 "Unknown language type: '%s' for breakpoint",
492 option_arg.str().c_str());
498 value = OptionArgParser::ToBoolean(option_arg, true, &success);
500 m_move_to_nearest_code = eLazyBoolYes;
502 m_move_to_nearest_code = eLazyBoolNo;
505 error.SetErrorStringWithFormat(
506 "Invalid boolean value for move-to-nearest-code option: '%s'",
507 option_arg.str().c_str());
512 m_func_names.push_back(option_arg);
513 m_func_name_type_mask |= eFunctionNameTypeMethod;
517 m_func_names.push_back(option_arg);
518 m_func_name_type_mask |= eFunctionNameTypeAuto;
522 if (BreakpointID::StringIsBreakpointName(option_arg, error))
523 m_breakpoint_names.push_back(option_arg);
525 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
526 option_arg.str().c_str());
531 lldb::addr_t tmp_offset_addr;
532 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
533 option_arg, 0, &error);
535 m_offset_addr = tmp_offset_addr;
539 m_exception_extra_args.AppendArgument("-O");
540 m_exception_extra_args.AppendArgument(option_arg);
544 m_source_text_regexp.assign(option_arg);
548 m_python_class.assign(option_arg);
552 m_func_regexp.assign(option_arg);
556 m_modules.AppendIfUnique(FileSpec(option_arg));
560 m_func_names.push_back(option_arg);
561 m_func_name_type_mask |= eFunctionNameTypeSelector;
565 if (!m_current_key.empty()) {
566 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
567 m_current_key.clear();
570 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
571 option_arg.str().c_str());
576 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
578 error.SetErrorStringWithFormat(
579 "Invalid boolean value for on-throw option: '%s'",
580 option_arg.str().c_str());
584 m_source_regex_func_names.insert(option_arg);
588 error.SetErrorStringWithFormat("unrecognized option '%c'",
596 void OptionParsingStarting(ExecutionContext *execution_context) override {
600 m_func_names.clear();
601 m_func_name_type_mask = eFunctionNameTypeNone;
602 m_func_regexp.clear();
603 m_source_text_regexp.clear();
605 m_load_addr = LLDB_INVALID_ADDRESS;
610 m_exception_language = eLanguageTypeUnknown;
611 m_language = lldb::eLanguageTypeUnknown;
612 m_skip_prologue = eLazyBoolCalculate;
613 m_breakpoint_names.clear();
615 m_exception_extra_args.Clear();
616 m_move_to_nearest_code = eLazyBoolCalculate;
617 m_source_regex_func_names.clear();
618 m_python_class.clear();
619 m_extra_args_sp.reset(new StructuredData::Dictionary());
620 m_current_key.clear();
623 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
624 return llvm::makeArrayRef(g_breakpoint_set_options);
627 // Instance variables to hold the values for command options.
629 std::string m_condition;
630 FileSpecList m_filenames;
633 std::vector<std::string> m_func_names;
634 std::vector<std::string> m_breakpoint_names;
635 lldb::FunctionNameType m_func_name_type_mask;
636 std::string m_func_regexp;
637 std::string m_source_text_regexp;
638 FileSpecList m_modules;
639 lldb::addr_t m_load_addr;
640 lldb::addr_t m_offset_addr;
643 bool m_hardware; // Request to use hardware breakpoints
644 lldb::LanguageType m_exception_language;
645 lldb::LanguageType m_language;
646 LazyBool m_skip_prologue;
648 Args m_exception_extra_args;
649 LazyBool m_move_to_nearest_code;
650 std::unordered_set<std::string> m_source_regex_func_names;
651 std::string m_python_class;
652 StructuredData::DictionarySP m_extra_args_sp;
653 std::string m_current_key;
657 bool DoExecute(Args &command, CommandReturnObject &result) override {
658 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
660 if (target == nullptr) {
661 result.AppendError("Invalid target. Must set target before setting "
662 "breakpoints (see 'target create' command).");
663 result.SetStatus(eReturnStatusFailed);
667 // The following are the various types of breakpoints that could be set:
668 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
669 // 2). -a [-s -g] (setting breakpoint by address)
670 // 3). -n [-s -g] (setting breakpoint by function name)
671 // 4). -r [-s -g] (setting breakpoint by function name regular
673 // 5). -p -f (setting a breakpoint by comparing a reg-exp
675 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
678 BreakpointSetType break_type = eSetTypeInvalid;
680 if (!m_options.m_python_class.empty())
681 break_type = eSetTypeScripted;
682 else if (m_options.m_line_num != 0)
683 break_type = eSetTypeFileAndLine;
684 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
685 break_type = eSetTypeAddress;
686 else if (!m_options.m_func_names.empty())
687 break_type = eSetTypeFunctionName;
688 else if (!m_options.m_func_regexp.empty())
689 break_type = eSetTypeFunctionRegexp;
690 else if (!m_options.m_source_text_regexp.empty())
691 break_type = eSetTypeSourceRegexp;
692 else if (m_options.m_exception_language != eLanguageTypeUnknown)
693 break_type = eSetTypeException;
695 BreakpointSP bp_sp = nullptr;
696 FileSpec module_spec;
697 const bool internal = false;
699 // If the user didn't specify skip-prologue, having an offset should turn
701 if (m_options.m_offset_addr != 0 &&
702 m_options.m_skip_prologue == eLazyBoolCalculate)
703 m_options.m_skip_prologue = eLazyBoolNo;
705 switch (break_type) {
706 case eSetTypeFileAndLine: // Breakpoint by source position
709 const size_t num_files = m_options.m_filenames.GetSize();
710 if (num_files == 0) {
711 if (!GetDefaultFile(target, file, result)) {
712 result.AppendError("No file supplied and no default file available.");
713 result.SetStatus(eReturnStatusFailed);
716 } else if (num_files > 1) {
717 result.AppendError("Only one file at a time is allowed for file and "
718 "line breakpoints.");
719 result.SetStatus(eReturnStatusFailed);
722 file = m_options.m_filenames.GetFileSpecAtIndex(0);
724 // Only check for inline functions if
725 LazyBool check_inlines = eLazyBoolCalculate;
727 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
729 m_options.m_line_num,
731 m_options.m_offset_addr,
733 m_options.m_skip_prologue,
735 m_options.m_hardware,
736 m_options.m_move_to_nearest_code);
739 case eSetTypeAddress: // Breakpoint by address
741 // If a shared library has been specified, make an lldb_private::Address
742 // with the library, and use that. That way the address breakpoint
743 // will track the load location of the library.
744 size_t num_modules_specified = m_options.m_modules.GetSize();
745 if (num_modules_specified == 1) {
746 const FileSpec *file_spec =
747 m_options.m_modules.GetFileSpecPointerAtIndex(0);
748 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
750 m_options.m_hardware);
751 } else if (num_modules_specified == 0) {
752 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
753 m_options.m_hardware);
755 result.AppendError("Only one shared library can be specified for "
756 "address breakpoints.");
757 result.SetStatus(eReturnStatusFailed);
762 case eSetTypeFunctionName: // Breakpoint by function name
764 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
766 if (name_type_mask == 0)
767 name_type_mask = eFunctionNameTypeAuto;
769 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
770 &(m_options.m_filenames),
771 m_options.m_func_names,
773 m_options.m_language,
774 m_options.m_offset_addr,
775 m_options.m_skip_prologue,
777 m_options.m_hardware);
780 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
783 RegularExpression regexp(m_options.m_func_regexp);
784 if (!regexp.IsValid()) {
786 regexp.GetErrorAsCString(err_str, sizeof(err_str));
787 result.AppendErrorWithFormat(
788 "Function name regular expression could not be compiled: \"%s\"",
790 result.SetStatus(eReturnStatusFailed);
794 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
795 &(m_options.m_filenames),
797 m_options.m_language,
798 m_options.m_skip_prologue,
800 m_options.m_hardware);
803 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
805 const size_t num_files = m_options.m_filenames.GetSize();
807 if (num_files == 0 && !m_options.m_all_files) {
809 if (!GetDefaultFile(target, file, result)) {
811 "No files provided and could not find default file.");
812 result.SetStatus(eReturnStatusFailed);
815 m_options.m_filenames.Append(file);
819 RegularExpression regexp(m_options.m_source_text_regexp);
820 if (!regexp.IsValid()) {
822 regexp.GetErrorAsCString(err_str, sizeof(err_str));
823 result.AppendErrorWithFormat(
824 "Source text regular expression could not be compiled: \"%s\"",
826 result.SetStatus(eReturnStatusFailed);
830 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
831 &(m_options.m_filenames),
833 .m_source_regex_func_names,
836 m_options.m_hardware,
837 m_options.m_move_to_nearest_code);
839 case eSetTypeException: {
840 Status precond_error;
841 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
842 m_options.m_catch_bp,
843 m_options.m_throw_bp,
846 .m_exception_extra_args,
848 if (precond_error.Fail()) {
849 result.AppendErrorWithFormat(
850 "Error setting extra exception arguments: %s",
851 precond_error.AsCString());
852 target->RemoveBreakpointByID(bp_sp->GetID());
853 result.SetStatus(eReturnStatusFailed);
857 case eSetTypeScripted: {
860 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
861 &(m_options.m_modules),
862 &(m_options.m_filenames),
864 m_options.m_hardware,
865 m_options.m_extra_args_sp,
868 result.AppendErrorWithFormat(
869 "Error setting extra exception arguments: %s",
871 target->RemoveBreakpointByID(bp_sp->GetID());
872 result.SetStatus(eReturnStatusFailed);
880 // Now set the various options that were passed in:
882 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
884 if (!m_options.m_breakpoint_names.empty()) {
886 for (auto name : m_options.m_breakpoint_names) {
887 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
888 if (name_error.Fail()) {
889 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
891 target->RemoveBreakpointByID(bp_sp->GetID());
892 result.SetStatus(eReturnStatusFailed);
900 Stream &output_stream = result.GetOutputStream();
901 const bool show_locations = false;
902 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
904 if (target == m_interpreter.GetDebugger().GetDummyTarget())
905 output_stream.Printf("Breakpoint set in dummy target, will get copied "
906 "into future targets.\n");
908 // Don't print out this warning for exception breakpoints. They can
909 // get set before the target is set, but we won't know how to actually
910 // set the breakpoint till we run.
911 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
912 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
913 "actual locations.\n");
916 result.SetStatus(eReturnStatusSuccessFinishResult);
918 result.AppendError("Breakpoint creation failed: No breakpoint created.");
919 result.SetStatus(eReturnStatusFailed);
922 return result.Succeeded();
926 bool GetDefaultFile(Target *target, FileSpec &file,
927 CommandReturnObject &result) {
928 uint32_t default_line;
929 // First use the Source Manager's default file. Then use the current stack
931 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
932 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
933 if (cur_frame == nullptr) {
935 "No selected frame to use to find the default file.");
936 result.SetStatus(eReturnStatusFailed);
938 } else if (!cur_frame->HasDebugInformation()) {
939 result.AppendError("Cannot use the selected frame to find the default "
940 "file, it has no debug info.");
941 result.SetStatus(eReturnStatusFailed);
944 const SymbolContext &sc =
945 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
946 if (sc.line_entry.file) {
947 file = sc.line_entry.file;
949 result.AppendError("Can't find the file for the selected frame to "
950 "use as the default file.");
951 result.SetStatus(eReturnStatusFailed);
959 BreakpointOptionGroup m_bp_opts;
960 BreakpointDummyOptionGroup m_dummy_options;
961 CommandOptions m_options;
962 OptionGroupOptions m_all_options;
965 //-------------------------------------------------------------------------
966 // CommandObjectBreakpointModify
967 //-------------------------------------------------------------------------
970 class CommandObjectBreakpointModify : public CommandObjectParsed {
972 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
973 : CommandObjectParsed(interpreter, "breakpoint modify",
974 "Modify the options on a breakpoint or set of "
975 "breakpoints in the executable. "
976 "If no breakpoint is specified, acts on the last "
977 "created breakpoint. "
978 "With the exception of -e, -d and -i, passing an "
979 "empty argument clears the modification.",
982 CommandArgumentEntry arg;
983 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
984 eArgTypeBreakpointIDRange);
985 // Add the entry for the first argument for this command to the object's
987 m_arguments.push_back(arg);
989 m_options.Append(&m_bp_opts,
990 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
992 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
993 m_options.Finalize();
996 ~CommandObjectBreakpointModify() override = default;
998 Options *GetOptions() override { return &m_options; }
1001 bool DoExecute(Args &command, CommandReturnObject &result) override {
1002 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
1003 if (target == nullptr) {
1004 result.AppendError("Invalid target. No existing target or breakpoints.");
1005 result.SetStatus(eReturnStatusFailed);
1009 std::unique_lock<std::recursive_mutex> lock;
1010 target->GetBreakpointList().GetListMutex(lock);
1012 BreakpointIDList valid_bp_ids;
1014 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1015 command, target, result, &valid_bp_ids,
1016 BreakpointName::Permissions::PermissionKinds::disablePerm);
1018 if (result.Succeeded()) {
1019 const size_t count = valid_bp_ids.GetSize();
1020 for (size_t i = 0; i < count; ++i) {
1021 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1023 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1025 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1026 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1027 BreakpointLocation *location =
1028 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
1030 location->GetLocationOptions()
1031 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
1034 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
1040 return result.Succeeded();
1044 BreakpointOptionGroup m_bp_opts;
1045 BreakpointDummyOptionGroup m_dummy_opts;
1046 OptionGroupOptions m_options;
1049 //-------------------------------------------------------------------------
1050 // CommandObjectBreakpointEnable
1051 //-------------------------------------------------------------------------
1054 class CommandObjectBreakpointEnable : public CommandObjectParsed {
1056 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1057 : CommandObjectParsed(interpreter, "enable",
1058 "Enable the specified disabled breakpoint(s). If "
1059 "no breakpoints are specified, enable all of them.",
1061 CommandArgumentEntry arg;
1062 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1063 eArgTypeBreakpointIDRange);
1064 // Add the entry for the first argument for this command to the object's
1065 // arguments vector.
1066 m_arguments.push_back(arg);
1069 ~CommandObjectBreakpointEnable() override = default;
1072 bool DoExecute(Args &command, CommandReturnObject &result) override {
1073 Target *target = GetSelectedOrDummyTarget();
1074 if (target == nullptr) {
1075 result.AppendError("Invalid target. No existing target or breakpoints.");
1076 result.SetStatus(eReturnStatusFailed);
1080 std::unique_lock<std::recursive_mutex> lock;
1081 target->GetBreakpointList().GetListMutex(lock);
1083 const BreakpointList &breakpoints = target->GetBreakpointList();
1085 size_t num_breakpoints = breakpoints.GetSize();
1087 if (num_breakpoints == 0) {
1088 result.AppendError("No breakpoints exist to be enabled.");
1089 result.SetStatus(eReturnStatusFailed);
1093 if (command.empty()) {
1094 // No breakpoint selected; enable all currently set breakpoints.
1095 target->EnableAllowedBreakpoints();
1096 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1098 (uint64_t)num_breakpoints);
1099 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1101 // Particular breakpoint selected; enable that breakpoint.
1102 BreakpointIDList valid_bp_ids;
1103 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1104 command, target, result, &valid_bp_ids,
1105 BreakpointName::Permissions::PermissionKinds::disablePerm);
1107 if (result.Succeeded()) {
1108 int enable_count = 0;
1110 const size_t count = valid_bp_ids.GetSize();
1111 for (size_t i = 0; i < count; ++i) {
1112 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1114 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1115 Breakpoint *breakpoint =
1116 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1117 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1118 BreakpointLocation *location =
1119 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1121 location->SetEnabled(true);
1125 breakpoint->SetEnabled(true);
1130 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1131 enable_count + loc_count);
1132 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1136 return result.Succeeded();
1140 //-------------------------------------------------------------------------
1141 // CommandObjectBreakpointDisable
1142 //-------------------------------------------------------------------------
1143 #pragma mark Disable
1145 class CommandObjectBreakpointDisable : public CommandObjectParsed {
1147 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1148 : CommandObjectParsed(
1149 interpreter, "breakpoint disable",
1150 "Disable the specified breakpoint(s) without deleting "
1151 "them. If none are specified, disable all "
1155 "Disable the specified breakpoint(s) without deleting them. \
1156 If none are specified, disable all breakpoints."
1160 "Note: disabling a breakpoint will cause none of its locations to be hit \
1161 regardless of whether individual locations are enabled or disabled. After the sequence:"
1164 (lldb) break disable 1
1165 (lldb) break enable 1.1
1167 execution will NOT stop at location 1.1. To achieve that, type:
1169 (lldb) break disable 1.*
1170 (lldb) break enable 1.1
1173 "The first command disables all locations for breakpoint 1, \
1174 the second re-enables the first location.");
1176 CommandArgumentEntry arg;
1177 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1178 eArgTypeBreakpointIDRange);
1179 // Add the entry for the first argument for this command to the object's
1180 // arguments vector.
1181 m_arguments.push_back(arg);
1184 ~CommandObjectBreakpointDisable() override = default;
1187 bool DoExecute(Args &command, CommandReturnObject &result) override {
1188 Target *target = GetSelectedOrDummyTarget();
1189 if (target == nullptr) {
1190 result.AppendError("Invalid target. No existing target or breakpoints.");
1191 result.SetStatus(eReturnStatusFailed);
1195 std::unique_lock<std::recursive_mutex> lock;
1196 target->GetBreakpointList().GetListMutex(lock);
1198 const BreakpointList &breakpoints = target->GetBreakpointList();
1199 size_t num_breakpoints = breakpoints.GetSize();
1201 if (num_breakpoints == 0) {
1202 result.AppendError("No breakpoints exist to be disabled.");
1203 result.SetStatus(eReturnStatusFailed);
1207 if (command.empty()) {
1208 // No breakpoint selected; disable all currently set breakpoints.
1209 target->DisableAllowedBreakpoints();
1210 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1212 (uint64_t)num_breakpoints);
1213 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1215 // Particular breakpoint selected; disable that breakpoint.
1216 BreakpointIDList valid_bp_ids;
1218 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1219 command, target, result, &valid_bp_ids,
1220 BreakpointName::Permissions::PermissionKinds::disablePerm);
1222 if (result.Succeeded()) {
1223 int disable_count = 0;
1225 const size_t count = valid_bp_ids.GetSize();
1226 for (size_t i = 0; i < count; ++i) {
1227 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1229 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1230 Breakpoint *breakpoint =
1231 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1232 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1233 BreakpointLocation *location =
1234 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1236 location->SetEnabled(false);
1240 breakpoint->SetEnabled(false);
1245 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1246 disable_count + loc_count);
1247 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1251 return result.Succeeded();
1255 //-------------------------------------------------------------------------
1256 // CommandObjectBreakpointList
1257 //-------------------------------------------------------------------------
1259 #pragma mark List::CommandOptions
1260 static constexpr OptionDefinition g_breakpoint_list_options[] = {
1262 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1263 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
1264 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1265 // But I need to see it for now, and don't want to wait.
1266 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1267 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1268 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1274 class CommandObjectBreakpointList : public CommandObjectParsed {
1276 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1277 : CommandObjectParsed(
1278 interpreter, "breakpoint list",
1279 "List some or all breakpoints at configurable levels of detail.",
1282 CommandArgumentEntry arg;
1283 CommandArgumentData bp_id_arg;
1285 // Define the first (and only) variant of this arg.
1286 bp_id_arg.arg_type = eArgTypeBreakpointID;
1287 bp_id_arg.arg_repetition = eArgRepeatOptional;
1289 // There is only one variant this argument could be; put it into the
1291 arg.push_back(bp_id_arg);
1293 // Push the data for the first argument into the m_arguments vector.
1294 m_arguments.push_back(arg);
1297 ~CommandObjectBreakpointList() override = default;
1299 Options *GetOptions() override { return &m_options; }
1301 class CommandOptions : public Options {
1304 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
1307 ~CommandOptions() override = default;
1309 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1310 ExecutionContext *execution_context) override {
1312 const int short_option = m_getopt_table[option_idx].val;
1314 switch (short_option) {
1316 m_level = lldb::eDescriptionLevelBrief;
1322 m_level = lldb::eDescriptionLevelFull;
1325 m_level = lldb::eDescriptionLevelVerbose;
1331 error.SetErrorStringWithFormat("unrecognized option '%c'",
1339 void OptionParsingStarting(ExecutionContext *execution_context) override {
1340 m_level = lldb::eDescriptionLevelFull;
1342 m_use_dummy = false;
1345 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1346 return llvm::makeArrayRef(g_breakpoint_list_options);
1349 // Instance variables to hold the values for command options.
1351 lldb::DescriptionLevel m_level;
1358 bool DoExecute(Args &command, CommandReturnObject &result) override {
1359 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1361 if (target == nullptr) {
1362 result.AppendError("Invalid target. No current target or breakpoints.");
1363 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1367 const BreakpointList &breakpoints =
1368 target->GetBreakpointList(m_options.m_internal);
1369 std::unique_lock<std::recursive_mutex> lock;
1370 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1372 size_t num_breakpoints = breakpoints.GetSize();
1374 if (num_breakpoints == 0) {
1375 result.AppendMessage("No breakpoints currently set.");
1376 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1380 Stream &output_stream = result.GetOutputStream();
1382 if (command.empty()) {
1383 // No breakpoint selected; show info about all currently set breakpoints.
1384 result.AppendMessage("Current breakpoints:");
1385 for (size_t i = 0; i < num_breakpoints; ++i) {
1386 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1387 if (breakpoint->AllowList())
1388 AddBreakpointDescription(&output_stream, breakpoint,
1391 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1393 // Particular breakpoints selected; show info about that breakpoint.
1394 BreakpointIDList valid_bp_ids;
1395 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1396 command, target, result, &valid_bp_ids,
1397 BreakpointName::Permissions::PermissionKinds::listPerm);
1399 if (result.Succeeded()) {
1400 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1401 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1402 Breakpoint *breakpoint =
1403 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1404 AddBreakpointDescription(&output_stream, breakpoint,
1407 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1409 result.AppendError("Invalid breakpoint ID.");
1410 result.SetStatus(eReturnStatusFailed);
1414 return result.Succeeded();
1418 CommandOptions m_options;
1421 //-------------------------------------------------------------------------
1422 // CommandObjectBreakpointClear
1423 //-------------------------------------------------------------------------
1424 #pragma mark Clear::CommandOptions
1426 static constexpr OptionDefinition g_breakpoint_clear_options[] = {
1428 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1429 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
1435 class CommandObjectBreakpointClear : public CommandObjectParsed {
1437 typedef enum BreakpointClearType {
1439 eClearTypeFileAndLine
1440 } BreakpointClearType;
1442 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1443 : CommandObjectParsed(interpreter, "breakpoint clear",
1444 "Delete or disable breakpoints matching the "
1445 "specified source file and line.",
1446 "breakpoint clear <cmd-options>"),
1449 ~CommandObjectBreakpointClear() override = default;
1451 Options *GetOptions() override { return &m_options; }
1453 class CommandOptions : public Options {
1455 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1457 ~CommandOptions() override = default;
1459 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1460 ExecutionContext *execution_context) override {
1462 const int short_option = m_getopt_table[option_idx].val;
1464 switch (short_option) {
1466 m_filename.assign(option_arg);
1470 option_arg.getAsInteger(0, m_line_num);
1474 error.SetErrorStringWithFormat("unrecognized option '%c'",
1482 void OptionParsingStarting(ExecutionContext *execution_context) override {
1487 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1488 return llvm::makeArrayRef(g_breakpoint_clear_options);
1491 // Instance variables to hold the values for command options.
1493 std::string m_filename;
1494 uint32_t m_line_num;
1498 bool DoExecute(Args &command, CommandReturnObject &result) override {
1499 Target *target = GetSelectedOrDummyTarget();
1500 if (target == nullptr) {
1501 result.AppendError("Invalid target. No existing target or breakpoints.");
1502 result.SetStatus(eReturnStatusFailed);
1506 // The following are the various types of breakpoints that could be
1508 // 1). -f -l (clearing breakpoint by source location)
1510 BreakpointClearType break_type = eClearTypeInvalid;
1512 if (m_options.m_line_num != 0)
1513 break_type = eClearTypeFileAndLine;
1515 std::unique_lock<std::recursive_mutex> lock;
1516 target->GetBreakpointList().GetListMutex(lock);
1518 BreakpointList &breakpoints = target->GetBreakpointList();
1519 size_t num_breakpoints = breakpoints.GetSize();
1521 // Early return if there's no breakpoint at all.
1522 if (num_breakpoints == 0) {
1523 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1524 result.SetStatus(eReturnStatusFailed);
1525 return result.Succeeded();
1528 // Find matching breakpoints and delete them.
1530 // First create a copy of all the IDs.
1531 std::vector<break_id_t> BreakIDs;
1532 for (size_t i = 0; i < num_breakpoints; ++i)
1533 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1535 int num_cleared = 0;
1537 switch (break_type) {
1538 case eClearTypeFileAndLine: // Breakpoint by source position
1540 const ConstString filename(m_options.m_filename.c_str());
1541 BreakpointLocationCollection loc_coll;
1543 for (size_t i = 0; i < num_breakpoints; ++i) {
1544 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1546 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1547 // If the collection size is 0, it's a full match and we can just
1548 // remove the breakpoint.
1549 if (loc_coll.GetSize() == 0) {
1550 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1552 target->RemoveBreakpointByID(bp->GetID());
1563 if (num_cleared > 0) {
1564 Stream &output_stream = result.GetOutputStream();
1565 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1566 output_stream << ss.GetString();
1567 output_stream.EOL();
1568 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1570 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1571 result.SetStatus(eReturnStatusFailed);
1574 return result.Succeeded();
1578 CommandOptions m_options;
1581 //-------------------------------------------------------------------------
1582 // CommandObjectBreakpointDelete
1583 //-------------------------------------------------------------------------
1584 static constexpr OptionDefinition g_breakpoint_delete_options[] = {
1586 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1587 { 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." },
1593 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1595 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1596 : CommandObjectParsed(interpreter, "breakpoint delete",
1597 "Delete the specified breakpoint(s). If no "
1598 "breakpoints are specified, delete them all.",
1601 CommandArgumentEntry arg;
1602 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1603 eArgTypeBreakpointIDRange);
1604 // Add the entry for the first argument for this command to the object's
1605 // arguments vector.
1606 m_arguments.push_back(arg);
1609 ~CommandObjectBreakpointDelete() override = default;
1611 Options *GetOptions() override { return &m_options; }
1613 class CommandOptions : public Options {
1615 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1617 ~CommandOptions() override = default;
1619 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1620 ExecutionContext *execution_context) override {
1622 const int short_option = m_getopt_table[option_idx].val;
1624 switch (short_option) {
1634 error.SetErrorStringWithFormat("unrecognized option '%c'",
1642 void OptionParsingStarting(ExecutionContext *execution_context) override {
1643 m_use_dummy = false;
1647 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1648 return llvm::makeArrayRef(g_breakpoint_delete_options);
1651 // Instance variables to hold the values for command options.
1657 bool DoExecute(Args &command, CommandReturnObject &result) override {
1658 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1660 if (target == nullptr) {
1661 result.AppendError("Invalid target. No existing target or breakpoints.");
1662 result.SetStatus(eReturnStatusFailed);
1666 std::unique_lock<std::recursive_mutex> lock;
1667 target->GetBreakpointList().GetListMutex(lock);
1669 const BreakpointList &breakpoints = target->GetBreakpointList();
1671 size_t num_breakpoints = breakpoints.GetSize();
1673 if (num_breakpoints == 0) {
1674 result.AppendError("No breakpoints exist to be deleted.");
1675 result.SetStatus(eReturnStatusFailed);
1679 if (command.empty()) {
1680 if (!m_options.m_force &&
1681 !m_interpreter.Confirm(
1682 "About to delete all breakpoints, do you want to do that?",
1684 result.AppendMessage("Operation cancelled...");
1686 target->RemoveAllowedBreakpoints();
1687 result.AppendMessageWithFormat(
1688 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1689 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1691 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1693 // Particular breakpoint selected; disable that breakpoint.
1694 BreakpointIDList valid_bp_ids;
1695 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1696 command, target, result, &valid_bp_ids,
1697 BreakpointName::Permissions::PermissionKinds::deletePerm);
1699 if (result.Succeeded()) {
1700 int delete_count = 0;
1701 int disable_count = 0;
1702 const size_t count = valid_bp_ids.GetSize();
1703 for (size_t i = 0; i < count; ++i) {
1704 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1706 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1707 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1708 Breakpoint *breakpoint =
1709 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1710 BreakpointLocation *location =
1711 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1712 // It makes no sense to try to delete individual locations, so we
1713 // disable them instead.
1715 location->SetEnabled(false);
1719 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1724 result.AppendMessageWithFormat(
1725 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1726 delete_count, disable_count);
1727 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1730 return result.Succeeded();
1734 CommandOptions m_options;
1737 //-------------------------------------------------------------------------
1738 // CommandObjectBreakpointName
1739 //-------------------------------------------------------------------------
1741 static constexpr OptionDefinition g_breakpoint_name_options[] = {
1743 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1744 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1745 {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."},
1746 {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."},
1749 class BreakpointNameOptionGroup : public OptionGroup {
1751 BreakpointNameOptionGroup()
1752 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1755 ~BreakpointNameOptionGroup() override = default;
1757 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1758 return llvm::makeArrayRef(g_breakpoint_name_options);
1761 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1762 ExecutionContext *execution_context) override {
1764 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1766 switch (short_option) {
1768 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1770 m_name.SetValueFromString(option_arg);
1773 if (m_breakpoint.SetValueFromString(option_arg).Fail())
1774 error.SetErrorStringWithFormat(
1775 "unrecognized value \"%s\" for breakpoint",
1776 option_arg.str().c_str());
1779 if (m_use_dummy.SetValueFromString(option_arg).Fail())
1780 error.SetErrorStringWithFormat(
1781 "unrecognized value \"%s\" for use-dummy",
1782 option_arg.str().c_str());
1785 m_help_string.SetValueFromString(option_arg);
1789 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1796 void OptionParsingStarting(ExecutionContext *execution_context) override {
1798 m_breakpoint.Clear();
1799 m_use_dummy.Clear();
1800 m_use_dummy.SetDefaultValue(false);
1801 m_help_string.Clear();
1804 OptionValueString m_name;
1805 OptionValueUInt64 m_breakpoint;
1806 OptionValueBoolean m_use_dummy;
1807 OptionValueString m_help_string;
1810 static constexpr OptionDefinition g_breakpoint_access_options[] = {
1812 {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."},
1813 {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."},
1814 {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."},
1818 class BreakpointAccessOptionGroup : public OptionGroup {
1820 BreakpointAccessOptionGroup() : OptionGroup() {}
1822 ~BreakpointAccessOptionGroup() override = default;
1824 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1825 return llvm::makeArrayRef(g_breakpoint_access_options);
1827 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1828 ExecutionContext *execution_context) override {
1830 const int short_option
1831 = g_breakpoint_access_options[option_idx].short_option;
1833 switch (short_option) {
1835 bool value, success;
1836 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1838 m_permissions.SetAllowList(value);
1840 error.SetErrorStringWithFormat(
1841 "invalid boolean value '%s' passed for -L option",
1842 option_arg.str().c_str());
1845 bool value, success;
1846 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1848 m_permissions.SetAllowDisable(value);
1850 error.SetErrorStringWithFormat(
1851 "invalid boolean value '%s' passed for -L option",
1852 option_arg.str().c_str());
1855 bool value, success;
1856 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1858 m_permissions.SetAllowDelete(value);
1860 error.SetErrorStringWithFormat(
1861 "invalid boolean value '%s' passed for -L option",
1862 option_arg.str().c_str());
1870 void OptionParsingStarting(ExecutionContext *execution_context) override {
1873 const BreakpointName::Permissions &GetPermissions() const
1875 return m_permissions;
1877 BreakpointName::Permissions m_permissions;
1880 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1882 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1883 : CommandObjectParsed(
1884 interpreter, "configure", "Configure the options for the breakpoint"
1886 "If you provide a breakpoint id, the options will be copied from "
1887 "the breakpoint, otherwise only the options specified will be set "
1889 "breakpoint name configure <command-options> "
1890 "<breakpoint-name-list>"),
1891 m_bp_opts(), m_option_group() {
1892 // Create the first variant for the first (and only) argument for this
1894 CommandArgumentEntry arg1;
1895 CommandArgumentData id_arg;
1896 id_arg.arg_type = eArgTypeBreakpointName;
1897 id_arg.arg_repetition = eArgRepeatOptional;
1898 arg1.push_back(id_arg);
1899 m_arguments.push_back(arg1);
1901 m_option_group.Append(&m_bp_opts,
1904 m_option_group.Append(&m_access_options,
1907 m_option_group.Append(&m_bp_id,
1908 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1910 m_option_group.Finalize();
1913 ~CommandObjectBreakpointNameConfigure() override = default;
1915 Options *GetOptions() override { return &m_option_group; }
1918 bool DoExecute(Args &command, CommandReturnObject &result) override {
1920 const size_t argc = command.GetArgumentCount();
1922 result.AppendError("No names provided.");
1923 result.SetStatus(eReturnStatusFailed);
1928 GetSelectedOrDummyTarget(false);
1930 if (target == nullptr) {
1931 result.AppendError("Invalid target. No existing target or breakpoints.");
1932 result.SetStatus(eReturnStatusFailed);
1936 std::unique_lock<std::recursive_mutex> lock;
1937 target->GetBreakpointList().GetListMutex(lock);
1939 // Make a pass through first to see that all the names are legal.
1940 for (auto &entry : command.entries()) {
1942 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1944 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1945 entry.c_str(), error.AsCString());
1946 result.SetStatus(eReturnStatusFailed);
1950 // Now configure them, we already pre-checked the names so we don't need to
1953 if (m_bp_id.m_breakpoint.OptionWasSet())
1955 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1956 bp_sp = target->GetBreakpointByID(bp_id);
1959 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1961 result.SetStatus(eReturnStatusFailed);
1967 for (auto &entry : command.entries()) {
1968 ConstString name(entry.c_str());
1969 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1972 if (m_bp_id.m_help_string.OptionWasSet())
1973 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1976 target->ConfigureBreakpointName(*bp_name,
1977 *bp_sp->GetOptions(),
1978 m_access_options.GetPermissions());
1980 target->ConfigureBreakpointName(*bp_name,
1981 m_bp_opts.GetBreakpointOptions(),
1982 m_access_options.GetPermissions());
1988 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1989 BreakpointOptionGroup m_bp_opts;
1990 BreakpointAccessOptionGroup m_access_options;
1991 OptionGroupOptions m_option_group;
1994 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1996 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1997 : CommandObjectParsed(
1998 interpreter, "add", "Add a name to the breakpoints provided.",
1999 "breakpoint name add <command-options> <breakpoint-id-list>"),
2000 m_name_options(), m_option_group() {
2001 // Create the first variant for the first (and only) argument for this
2003 CommandArgumentEntry arg1;
2004 CommandArgumentData id_arg;
2005 id_arg.arg_type = eArgTypeBreakpointID;
2006 id_arg.arg_repetition = eArgRepeatOptional;
2007 arg1.push_back(id_arg);
2008 m_arguments.push_back(arg1);
2010 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2011 m_option_group.Finalize();
2014 ~CommandObjectBreakpointNameAdd() override = default;
2016 Options *GetOptions() override { return &m_option_group; }
2019 bool DoExecute(Args &command, CommandReturnObject &result) override {
2020 if (!m_name_options.m_name.OptionWasSet()) {
2021 result.SetError("No name option provided.");
2026 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2028 if (target == nullptr) {
2029 result.AppendError("Invalid target. No existing target or breakpoints.");
2030 result.SetStatus(eReturnStatusFailed);
2034 std::unique_lock<std::recursive_mutex> lock;
2035 target->GetBreakpointList().GetListMutex(lock);
2037 const BreakpointList &breakpoints = target->GetBreakpointList();
2039 size_t num_breakpoints = breakpoints.GetSize();
2040 if (num_breakpoints == 0) {
2041 result.SetError("No breakpoints, cannot add names.");
2042 result.SetStatus(eReturnStatusFailed);
2046 // Particular breakpoint selected; disable that breakpoint.
2047 BreakpointIDList valid_bp_ids;
2048 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2049 command, target, result, &valid_bp_ids,
2050 BreakpointName::Permissions::PermissionKinds::listPerm);
2052 if (result.Succeeded()) {
2053 if (valid_bp_ids.GetSize() == 0) {
2054 result.SetError("No breakpoints specified, cannot add names.");
2055 result.SetStatus(eReturnStatusFailed);
2058 size_t num_valid_ids = valid_bp_ids.GetSize();
2059 const char *bp_name = m_name_options.m_name.GetCurrentValue();
2060 Status error; // This error reports illegal names, but we've already
2061 // checked that, so we don't need to check it again here.
2062 for (size_t index = 0; index < num_valid_ids; index++) {
2063 lldb::break_id_t bp_id =
2064 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2065 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2066 target->AddNameToBreakpoint(bp_sp, bp_name, error);
2074 BreakpointNameOptionGroup m_name_options;
2075 OptionGroupOptions m_option_group;
2078 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
2080 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2081 : CommandObjectParsed(
2082 interpreter, "delete",
2083 "Delete a name from the breakpoints provided.",
2084 "breakpoint name delete <command-options> <breakpoint-id-list>"),
2085 m_name_options(), m_option_group() {
2086 // Create the first variant for the first (and only) argument for this
2088 CommandArgumentEntry arg1;
2089 CommandArgumentData id_arg;
2090 id_arg.arg_type = eArgTypeBreakpointID;
2091 id_arg.arg_repetition = eArgRepeatOptional;
2092 arg1.push_back(id_arg);
2093 m_arguments.push_back(arg1);
2095 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2096 m_option_group.Finalize();
2099 ~CommandObjectBreakpointNameDelete() override = default;
2101 Options *GetOptions() override { return &m_option_group; }
2104 bool DoExecute(Args &command, CommandReturnObject &result) override {
2105 if (!m_name_options.m_name.OptionWasSet()) {
2106 result.SetError("No name option provided.");
2111 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2113 if (target == nullptr) {
2114 result.AppendError("Invalid target. No existing target or breakpoints.");
2115 result.SetStatus(eReturnStatusFailed);
2119 std::unique_lock<std::recursive_mutex> lock;
2120 target->GetBreakpointList().GetListMutex(lock);
2122 const BreakpointList &breakpoints = target->GetBreakpointList();
2124 size_t num_breakpoints = breakpoints.GetSize();
2125 if (num_breakpoints == 0) {
2126 result.SetError("No breakpoints, cannot delete names.");
2127 result.SetStatus(eReturnStatusFailed);
2131 // Particular breakpoint selected; disable that breakpoint.
2132 BreakpointIDList valid_bp_ids;
2133 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2134 command, target, result, &valid_bp_ids,
2135 BreakpointName::Permissions::PermissionKinds::deletePerm);
2137 if (result.Succeeded()) {
2138 if (valid_bp_ids.GetSize() == 0) {
2139 result.SetError("No breakpoints specified, cannot delete names.");
2140 result.SetStatus(eReturnStatusFailed);
2143 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
2144 size_t num_valid_ids = valid_bp_ids.GetSize();
2145 for (size_t index = 0; index < num_valid_ids; index++) {
2146 lldb::break_id_t bp_id =
2147 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2148 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2149 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
2157 BreakpointNameOptionGroup m_name_options;
2158 OptionGroupOptions m_option_group;
2161 class CommandObjectBreakpointNameList : public CommandObjectParsed {
2163 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2164 : CommandObjectParsed(interpreter, "list",
2165 "List either the names for a breakpoint or info "
2166 "about a given name. With no arguments, lists all "
2168 "breakpoint name list <command-options>"),
2169 m_name_options(), m_option_group() {
2170 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
2171 m_option_group.Finalize();
2174 ~CommandObjectBreakpointNameList() override = default;
2176 Options *GetOptions() override { return &m_option_group; }
2179 bool DoExecute(Args &command, CommandReturnObject &result) override {
2181 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2183 if (target == nullptr) {
2184 result.AppendError("Invalid target. No existing target or breakpoints.");
2185 result.SetStatus(eReturnStatusFailed);
2190 std::vector<std::string> name_list;
2191 if (command.empty()) {
2192 target->GetBreakpointNames(name_list);
2194 for (const Args::ArgEntry &arg : command)
2196 name_list.push_back(arg.c_str());
2200 if (name_list.empty()) {
2201 result.AppendMessage("No breakpoint names found.");
2203 for (const std::string &name_str : name_list) {
2204 const char *name = name_str.c_str();
2205 // First print out the options for the name:
2207 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2213 result.AppendMessageWithFormat("Name: %s\n", name);
2214 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2216 result.AppendMessage(s.GetString());
2219 std::unique_lock<std::recursive_mutex> lock;
2220 target->GetBreakpointList().GetListMutex(lock);
2222 BreakpointList &breakpoints = target->GetBreakpointList();
2223 bool any_set = false;
2224 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2225 if (bp_sp->MatchesName(name)) {
2228 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2230 result.AppendMessage(s.GetString());
2234 result.AppendMessage("No breakpoints using this name.");
2236 result.AppendMessageWithFormat("Name: %s not found.\n", name);
2244 BreakpointNameOptionGroup m_name_options;
2245 OptionGroupOptions m_option_group;
2248 //-------------------------------------------------------------------------
2249 // CommandObjectBreakpointName
2250 //-------------------------------------------------------------------------
2251 class CommandObjectBreakpointName : public CommandObjectMultiword {
2253 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2254 : CommandObjectMultiword(
2255 interpreter, "name", "Commands to manage name tags for breakpoints",
2256 "breakpoint name <subcommand> [<command-options>]") {
2257 CommandObjectSP add_command_object(
2258 new CommandObjectBreakpointNameAdd(interpreter));
2259 CommandObjectSP delete_command_object(
2260 new CommandObjectBreakpointNameDelete(interpreter));
2261 CommandObjectSP list_command_object(
2262 new CommandObjectBreakpointNameList(interpreter));
2263 CommandObjectSP configure_command_object(
2264 new CommandObjectBreakpointNameConfigure(interpreter));
2266 LoadSubCommand("add", add_command_object);
2267 LoadSubCommand("delete", delete_command_object);
2268 LoadSubCommand("list", list_command_object);
2269 LoadSubCommand("configure", configure_command_object);
2272 ~CommandObjectBreakpointName() override = default;
2275 //-------------------------------------------------------------------------
2276 // CommandObjectBreakpointRead
2277 //-------------------------------------------------------------------------
2278 #pragma mark Read::CommandOptions
2279 static constexpr OptionDefinition g_breakpoint_read_options[] = {
2281 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2282 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
2288 class CommandObjectBreakpointRead : public CommandObjectParsed {
2290 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2291 : CommandObjectParsed(interpreter, "breakpoint read",
2292 "Read and set the breakpoints previously saved to "
2293 "a file with \"breakpoint write\". ",
2296 CommandArgumentEntry arg;
2297 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2298 eArgTypeBreakpointIDRange);
2299 // Add the entry for the first argument for this command to the object's
2300 // arguments vector.
2301 m_arguments.push_back(arg);
2304 ~CommandObjectBreakpointRead() override = default;
2306 Options *GetOptions() override { return &m_options; }
2308 class CommandOptions : public Options {
2310 CommandOptions() : Options() {}
2312 ~CommandOptions() override = default;
2314 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2315 ExecutionContext *execution_context) override {
2317 const int short_option = m_getopt_table[option_idx].val;
2319 switch (short_option) {
2321 m_filename.assign(option_arg);
2325 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2327 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2328 name_error.AsCString());
2330 m_names.push_back(option_arg);
2334 error.SetErrorStringWithFormat("unrecognized option '%c'",
2342 void OptionParsingStarting(ExecutionContext *execution_context) override {
2347 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2348 return llvm::makeArrayRef(g_breakpoint_read_options);
2351 // Instance variables to hold the values for command options.
2353 std::string m_filename;
2354 std::vector<std::string> m_names;
2358 bool DoExecute(Args &command, CommandReturnObject &result) override {
2359 Target *target = GetSelectedOrDummyTarget();
2360 if (target == nullptr) {
2361 result.AppendError("Invalid target. No existing target or breakpoints.");
2362 result.SetStatus(eReturnStatusFailed);
2366 std::unique_lock<std::recursive_mutex> lock;
2367 target->GetBreakpointList().GetListMutex(lock);
2369 FileSpec input_spec(m_options.m_filename);
2370 FileSystem::Instance().Resolve(input_spec);
2371 BreakpointIDList new_bps;
2372 Status error = target->CreateBreakpointsFromFile(
2373 input_spec, m_options.m_names, new_bps);
2375 if (!error.Success()) {
2376 result.AppendError(error.AsCString());
2377 result.SetStatus(eReturnStatusFailed);
2381 Stream &output_stream = result.GetOutputStream();
2383 size_t num_breakpoints = new_bps.GetSize();
2384 if (num_breakpoints == 0) {
2385 result.AppendMessage("No breakpoints added.");
2387 // No breakpoint selected; show info about all currently set breakpoints.
2388 result.AppendMessage("New breakpoints:");
2389 for (size_t i = 0; i < num_breakpoints; ++i) {
2390 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2391 Breakpoint *bp = target->GetBreakpointList()
2392 .FindBreakpointByID(bp_id.GetBreakpointID())
2395 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2399 return result.Succeeded();
2403 CommandOptions m_options;
2406 //-------------------------------------------------------------------------
2407 // CommandObjectBreakpointWrite
2408 //-------------------------------------------------------------------------
2409 #pragma mark Write::CommandOptions
2410 static constexpr OptionDefinition g_breakpoint_write_options[] = {
2412 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2413 { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
2418 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2420 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2421 : CommandObjectParsed(interpreter, "breakpoint write",
2422 "Write the breakpoints listed to a file that can "
2423 "be read in with \"breakpoint read\". "
2424 "If given no arguments, writes all breakpoints.",
2427 CommandArgumentEntry arg;
2428 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2429 eArgTypeBreakpointIDRange);
2430 // Add the entry for the first argument for this command to the object's
2431 // arguments vector.
2432 m_arguments.push_back(arg);
2435 ~CommandObjectBreakpointWrite() override = default;
2437 Options *GetOptions() override { return &m_options; }
2439 class CommandOptions : public Options {
2441 CommandOptions() : Options() {}
2443 ~CommandOptions() override = default;
2445 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2446 ExecutionContext *execution_context) override {
2448 const int short_option = m_getopt_table[option_idx].val;
2450 switch (short_option) {
2452 m_filename.assign(option_arg);
2458 error.SetErrorStringWithFormat("unrecognized option '%c'",
2466 void OptionParsingStarting(ExecutionContext *execution_context) override {
2471 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2472 return llvm::makeArrayRef(g_breakpoint_write_options);
2475 // Instance variables to hold the values for command options.
2477 std::string m_filename;
2478 bool m_append = false;
2482 bool DoExecute(Args &command, CommandReturnObject &result) override {
2483 Target *target = GetSelectedOrDummyTarget();
2484 if (target == nullptr) {
2485 result.AppendError("Invalid target. No existing target or breakpoints.");
2486 result.SetStatus(eReturnStatusFailed);
2490 std::unique_lock<std::recursive_mutex> lock;
2491 target->GetBreakpointList().GetListMutex(lock);
2493 BreakpointIDList valid_bp_ids;
2494 if (!command.empty()) {
2495 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2496 command, target, result, &valid_bp_ids,
2497 BreakpointName::Permissions::PermissionKinds::listPerm);
2499 if (!result.Succeeded()) {
2500 result.SetStatus(eReturnStatusFailed);
2504 FileSpec file_spec(m_options.m_filename);
2505 FileSystem::Instance().Resolve(file_spec);
2506 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2507 m_options.m_append);
2508 if (!error.Success()) {
2509 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2511 result.SetStatus(eReturnStatusFailed);
2513 return result.Succeeded();
2517 CommandOptions m_options;
2520 //-------------------------------------------------------------------------
2521 // CommandObjectMultiwordBreakpoint
2522 //-------------------------------------------------------------------------
2523 #pragma mark MultiwordBreakpoint
2525 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2526 CommandInterpreter &interpreter)
2527 : CommandObjectMultiword(
2528 interpreter, "breakpoint",
2529 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2530 "breakpoint <subcommand> [<command-options>]") {
2531 CommandObjectSP list_command_object(
2532 new CommandObjectBreakpointList(interpreter));
2533 CommandObjectSP enable_command_object(
2534 new CommandObjectBreakpointEnable(interpreter));
2535 CommandObjectSP disable_command_object(
2536 new CommandObjectBreakpointDisable(interpreter));
2537 CommandObjectSP clear_command_object(
2538 new CommandObjectBreakpointClear(interpreter));
2539 CommandObjectSP delete_command_object(
2540 new CommandObjectBreakpointDelete(interpreter));
2541 CommandObjectSP set_command_object(
2542 new CommandObjectBreakpointSet(interpreter));
2543 CommandObjectSP command_command_object(
2544 new CommandObjectBreakpointCommand(interpreter));
2545 CommandObjectSP modify_command_object(
2546 new CommandObjectBreakpointModify(interpreter));
2547 CommandObjectSP name_command_object(
2548 new CommandObjectBreakpointName(interpreter));
2549 CommandObjectSP write_command_object(
2550 new CommandObjectBreakpointWrite(interpreter));
2551 CommandObjectSP read_command_object(
2552 new CommandObjectBreakpointRead(interpreter));
2554 list_command_object->SetCommandName("breakpoint list");
2555 enable_command_object->SetCommandName("breakpoint enable");
2556 disable_command_object->SetCommandName("breakpoint disable");
2557 clear_command_object->SetCommandName("breakpoint clear");
2558 delete_command_object->SetCommandName("breakpoint delete");
2559 set_command_object->SetCommandName("breakpoint set");
2560 command_command_object->SetCommandName("breakpoint command");
2561 modify_command_object->SetCommandName("breakpoint modify");
2562 name_command_object->SetCommandName("breakpoint name");
2563 write_command_object->SetCommandName("breakpoint write");
2564 read_command_object->SetCommandName("breakpoint read");
2566 LoadSubCommand("list", list_command_object);
2567 LoadSubCommand("enable", enable_command_object);
2568 LoadSubCommand("disable", disable_command_object);
2569 LoadSubCommand("clear", clear_command_object);
2570 LoadSubCommand("delete", delete_command_object);
2571 LoadSubCommand("set", set_command_object);
2572 LoadSubCommand("command", command_command_object);
2573 LoadSubCommand("modify", modify_command_object);
2574 LoadSubCommand("name", name_command_object);
2575 LoadSubCommand("write", write_command_object);
2576 LoadSubCommand("read", read_command_object);
2579 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2581 void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2582 bool allow_locations,
2583 CommandReturnObject &result,
2584 BreakpointIDList *valid_ids,
2585 BreakpointName::Permissions
2588 // args can be strings representing 1). integers (for breakpoint ids)
2589 // 2). the full breakpoint & location
2590 // canonical representation
2591 // 3). the word "to" or a hyphen,
2592 // representing a range (in which case there
2593 // had *better* be an entry both before &
2594 // after of one of the first two types.
2595 // 4). A breakpoint name
2596 // If args is empty, we will use the last created breakpoint (if there is
2602 if (target->GetLastCreatedBreakpoint()) {
2603 valid_ids->AddBreakpointID(BreakpointID(
2604 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2605 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2608 "No breakpoint specified and no last created breakpoint.");
2609 result.SetStatus(eReturnStatusFailed);
2614 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2615 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2616 // id range strings over; instead generate a list of strings for all the
2617 // breakpoint ids in the range, and shove all of those breakpoint id strings
2620 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2621 purpose, result, temp_args);
2623 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2624 // BreakpointIDList:
2626 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2628 // At this point, all of the breakpoint ids that the user passed in have
2629 // been converted to breakpoint IDs and put into valid_ids.
2631 if (result.Succeeded()) {
2632 // Now that we've converted everything from args into a list of breakpoint
2633 // ids, go through our tentative list of breakpoint id's and verify that
2634 // they correspond to valid/currently set breakpoints.
2636 const size_t count = valid_ids->GetSize();
2637 for (size_t i = 0; i < count; ++i) {
2638 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2639 Breakpoint *breakpoint =
2640 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2641 if (breakpoint != nullptr) {
2642 const size_t num_locations = breakpoint->GetNumLocations();
2643 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2644 StreamString id_str;
2645 BreakpointID::GetCanonicalReference(
2646 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2647 i = valid_ids->GetSize() + 1;
2648 result.AppendErrorWithFormat(
2649 "'%s' is not a currently valid breakpoint/location id.\n",
2651 result.SetStatus(eReturnStatusFailed);
2654 i = valid_ids->GetSize() + 1;
2655 result.AppendErrorWithFormat(
2656 "'%d' is not a currently valid breakpoint ID.\n",
2657 cur_bp_id.GetBreakpointID());
2658 result.SetStatus(eReturnStatusFailed);