Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / source / Commands / CommandObjectBreakpoint.cpp
blobe1d1c5e42c32a03b64e8ad8af564dbef4f9333e7
1 //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
2 //
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
6 //
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/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
20 #include "lldb/Interpreter/OptionValueBoolean.h"
21 #include "lldb/Interpreter/OptionValueFileColonLine.h"
22 #include "lldb/Interpreter/OptionValueString.h"
23 #include "lldb/Interpreter/OptionValueUInt64.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Target/Language.h"
26 #include "lldb/Target/StackFrame.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/ThreadSpec.h"
29 #include "lldb/Utility/RegularExpression.h"
30 #include "lldb/Utility/StreamString.h"
32 #include <memory>
33 #include <optional>
34 #include <vector>
36 using namespace lldb;
37 using namespace lldb_private;
39 static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
40 lldb::DescriptionLevel level) {
41 s->IndentMore();
42 bp->GetDescription(s, level, true);
43 s->IndentLess();
44 s->EOL();
47 // Modifiable Breakpoint Options
48 #pragma mark Modify::CommandOptions
49 #define LLDB_OPTIONS_breakpoint_modify
50 #include "CommandOptions.inc"
52 class lldb_private::BreakpointOptionGroup : public OptionGroup {
53 public:
54 BreakpointOptionGroup() : m_bp_opts(false) {}
56 ~BreakpointOptionGroup() override = default;
58 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
59 return llvm::ArrayRef(g_breakpoint_modify_options);
62 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
63 ExecutionContext *execution_context) override {
64 Status error;
65 const int short_option =
66 g_breakpoint_modify_options[option_idx].short_option;
68 switch (short_option) {
69 case 'c':
70 // Normally an empty breakpoint condition marks is as unset. But we need
71 // to say it was passed in.
72 m_bp_opts.SetCondition(option_arg.str().c_str());
73 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
74 break;
75 case 'C':
76 m_commands.push_back(std::string(option_arg));
77 break;
78 case 'd':
79 m_bp_opts.SetEnabled(false);
80 break;
81 case 'e':
82 m_bp_opts.SetEnabled(true);
83 break;
84 case 'G': {
85 bool value, success;
86 value = OptionArgParser::ToBoolean(option_arg, false, &success);
87 if (success) {
88 m_bp_opts.SetAutoContinue(value);
89 } else
90 error.SetErrorStringWithFormat(
91 "invalid boolean value '%s' passed for -G option",
92 option_arg.str().c_str());
93 } break;
94 case 'i': {
95 uint32_t ignore_count;
96 if (option_arg.getAsInteger(0, ignore_count))
97 error.SetErrorStringWithFormat("invalid ignore count '%s'",
98 option_arg.str().c_str());
99 else
100 m_bp_opts.SetIgnoreCount(ignore_count);
101 } break;
102 case 'o': {
103 bool value, success;
104 value = OptionArgParser::ToBoolean(option_arg, false, &success);
105 if (success) {
106 m_bp_opts.SetOneShot(value);
107 } else
108 error.SetErrorStringWithFormat(
109 "invalid boolean value '%s' passed for -o option",
110 option_arg.str().c_str());
111 } break;
112 case 't': {
113 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
114 if (option_arg == "current") {
115 if (!execution_context) {
116 error.SetErrorStringWithFormat("No context to determine current "
117 "thread");
118 } else {
119 ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
120 if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
121 error.SetErrorStringWithFormat("No currently selected thread");
122 } else {
123 thread_id = ctx_thread_sp->GetID();
126 } else if (option_arg.getAsInteger(0, thread_id)) {
127 error.SetErrorStringWithFormat("invalid thread id string '%s'",
128 option_arg.str().c_str());
130 if (thread_id != LLDB_INVALID_THREAD_ID)
131 m_bp_opts.SetThreadID(thread_id);
132 } break;
133 case 'T':
134 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
135 break;
136 case 'q':
137 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
138 break;
139 case 'x': {
140 uint32_t thread_index = UINT32_MAX;
141 if (option_arg.getAsInteger(0, thread_index)) {
142 error.SetErrorStringWithFormat("invalid thread index string '%s'",
143 option_arg.str().c_str());
144 } else {
145 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
147 } break;
148 default:
149 llvm_unreachable("Unimplemented option");
152 return error;
155 void OptionParsingStarting(ExecutionContext *execution_context) override {
156 m_bp_opts.Clear();
157 m_commands.clear();
160 Status OptionParsingFinished(ExecutionContext *execution_context) override {
161 if (!m_commands.empty()) {
162 auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
164 for (std::string &str : m_commands)
165 cmd_data->user_source.AppendString(str);
167 cmd_data->stop_on_error = true;
168 m_bp_opts.SetCommandDataCallback(cmd_data);
170 return Status();
173 const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
175 std::vector<std::string> m_commands;
176 BreakpointOptions m_bp_opts;
179 #define LLDB_OPTIONS_breakpoint_dummy
180 #include "CommandOptions.inc"
182 class BreakpointDummyOptionGroup : public OptionGroup {
183 public:
184 BreakpointDummyOptionGroup() = default;
186 ~BreakpointDummyOptionGroup() override = default;
188 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
189 return llvm::ArrayRef(g_breakpoint_dummy_options);
192 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
193 ExecutionContext *execution_context) override {
194 Status error;
195 const int short_option =
196 g_breakpoint_dummy_options[option_idx].short_option;
198 switch (short_option) {
199 case 'D':
200 m_use_dummy = true;
201 break;
202 default:
203 llvm_unreachable("Unimplemented option");
206 return error;
209 void OptionParsingStarting(ExecutionContext *execution_context) override {
210 m_use_dummy = false;
213 bool m_use_dummy;
216 #define LLDB_OPTIONS_breakpoint_set
217 #include "CommandOptions.inc"
219 // CommandObjectBreakpointSet
221 class CommandObjectBreakpointSet : public CommandObjectParsed {
222 public:
223 enum BreakpointSetType {
224 eSetTypeInvalid,
225 eSetTypeFileAndLine,
226 eSetTypeAddress,
227 eSetTypeFunctionName,
228 eSetTypeFunctionRegexp,
229 eSetTypeSourceRegexp,
230 eSetTypeException,
231 eSetTypeScripted,
234 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
235 : CommandObjectParsed(
236 interpreter, "breakpoint set",
237 "Sets a breakpoint or set of breakpoints in the executable.",
238 "breakpoint set <cmd-options>"),
239 m_python_class_options("scripted breakpoint", true, 'P') {
240 // We're picking up all the normal options, commands and disable.
241 m_all_options.Append(&m_python_class_options,
242 LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
243 m_all_options.Append(&m_bp_opts,
244 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
245 LLDB_OPT_SET_ALL);
246 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
247 m_all_options.Append(&m_options);
248 m_all_options.Finalize();
251 ~CommandObjectBreakpointSet() override = default;
253 Options *GetOptions() override { return &m_all_options; }
255 class CommandOptions : public OptionGroup {
256 public:
257 CommandOptions() = default;
259 ~CommandOptions() override = default;
261 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
262 ExecutionContext *execution_context) override {
263 Status error;
264 const int short_option =
265 g_breakpoint_set_options[option_idx].short_option;
267 switch (short_option) {
268 case 'a': {
269 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
270 LLDB_INVALID_ADDRESS, &error);
271 } break;
273 case 'A':
274 m_all_files = true;
275 break;
277 case 'b':
278 m_func_names.push_back(std::string(option_arg));
279 m_func_name_type_mask |= eFunctionNameTypeBase;
280 break;
282 case 'u':
283 if (option_arg.getAsInteger(0, m_column))
284 error.SetErrorStringWithFormat("invalid column number: %s",
285 option_arg.str().c_str());
286 break;
288 case 'E': {
289 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
291 switch (language) {
292 case eLanguageTypeC89:
293 case eLanguageTypeC:
294 case eLanguageTypeC99:
295 case eLanguageTypeC11:
296 m_exception_language = eLanguageTypeC;
297 break;
298 case eLanguageTypeC_plus_plus:
299 case eLanguageTypeC_plus_plus_03:
300 case eLanguageTypeC_plus_plus_11:
301 case eLanguageTypeC_plus_plus_14:
302 m_exception_language = eLanguageTypeC_plus_plus;
303 break;
304 case eLanguageTypeObjC:
305 m_exception_language = eLanguageTypeObjC;
306 break;
307 case eLanguageTypeObjC_plus_plus:
308 error.SetErrorStringWithFormat(
309 "Set exception breakpoints separately for c++ and objective-c");
310 break;
311 case eLanguageTypeUnknown:
312 error.SetErrorStringWithFormat(
313 "Unknown language type: '%s' for exception breakpoint",
314 option_arg.str().c_str());
315 break;
316 default:
317 error.SetErrorStringWithFormat(
318 "Unsupported language type: '%s' for exception breakpoint",
319 option_arg.str().c_str());
321 } break;
323 case 'f':
324 m_filenames.AppendIfUnique(FileSpec(option_arg));
325 break;
327 case 'F':
328 m_func_names.push_back(std::string(option_arg));
329 m_func_name_type_mask |= eFunctionNameTypeFull;
330 break;
332 case 'h': {
333 bool success;
334 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
335 if (!success)
336 error.SetErrorStringWithFormat(
337 "Invalid boolean value for on-catch option: '%s'",
338 option_arg.str().c_str());
339 } break;
341 case 'H':
342 m_hardware = true;
343 break;
345 case 'K': {
346 bool success;
347 bool value;
348 value = OptionArgParser::ToBoolean(option_arg, true, &success);
349 if (value)
350 m_skip_prologue = eLazyBoolYes;
351 else
352 m_skip_prologue = eLazyBoolNo;
354 if (!success)
355 error.SetErrorStringWithFormat(
356 "Invalid boolean value for skip prologue option: '%s'",
357 option_arg.str().c_str());
358 } break;
360 case 'l':
361 if (option_arg.getAsInteger(0, m_line_num))
362 error.SetErrorStringWithFormat("invalid line number: %s.",
363 option_arg.str().c_str());
364 break;
366 case 'L':
367 m_language = Language::GetLanguageTypeFromString(option_arg);
368 if (m_language == eLanguageTypeUnknown)
369 error.SetErrorStringWithFormat(
370 "Unknown language type: '%s' for breakpoint",
371 option_arg.str().c_str());
372 break;
374 case 'm': {
375 bool success;
376 bool value;
377 value = OptionArgParser::ToBoolean(option_arg, true, &success);
378 if (value)
379 m_move_to_nearest_code = eLazyBoolYes;
380 else
381 m_move_to_nearest_code = eLazyBoolNo;
383 if (!success)
384 error.SetErrorStringWithFormat(
385 "Invalid boolean value for move-to-nearest-code option: '%s'",
386 option_arg.str().c_str());
387 break;
390 case 'M':
391 m_func_names.push_back(std::string(option_arg));
392 m_func_name_type_mask |= eFunctionNameTypeMethod;
393 break;
395 case 'n':
396 m_func_names.push_back(std::string(option_arg));
397 m_func_name_type_mask |= eFunctionNameTypeAuto;
398 break;
400 case 'N': {
401 if (BreakpointID::StringIsBreakpointName(option_arg, error))
402 m_breakpoint_names.push_back(std::string(option_arg));
403 else
404 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
405 option_arg.str().c_str());
406 break;
409 case 'R': {
410 lldb::addr_t tmp_offset_addr;
411 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
412 option_arg, 0, &error);
413 if (error.Success())
414 m_offset_addr = tmp_offset_addr;
415 } break;
417 case 'O':
418 m_exception_extra_args.AppendArgument("-O");
419 m_exception_extra_args.AppendArgument(option_arg);
420 break;
422 case 'p':
423 m_source_text_regexp.assign(std::string(option_arg));
424 break;
426 case 'r':
427 m_func_regexp.assign(std::string(option_arg));
428 break;
430 case 's':
431 m_modules.AppendIfUnique(FileSpec(option_arg));
432 break;
434 case 'S':
435 m_func_names.push_back(std::string(option_arg));
436 m_func_name_type_mask |= eFunctionNameTypeSelector;
437 break;
439 case 'w': {
440 bool success;
441 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
442 if (!success)
443 error.SetErrorStringWithFormat(
444 "Invalid boolean value for on-throw option: '%s'",
445 option_arg.str().c_str());
446 } break;
448 case 'X':
449 m_source_regex_func_names.insert(std::string(option_arg));
450 break;
452 case 'y':
454 OptionValueFileColonLine value;
455 Status fcl_err = value.SetValueFromString(option_arg);
456 if (!fcl_err.Success()) {
457 error.SetErrorStringWithFormat(
458 "Invalid value for file:line specifier: %s",
459 fcl_err.AsCString());
460 } else {
461 m_filenames.AppendIfUnique(value.GetFileSpec());
462 m_line_num = value.GetLineNumber();
463 m_column = value.GetColumnNumber();
465 } break;
467 default:
468 llvm_unreachable("Unimplemented option");
471 return error;
474 void OptionParsingStarting(ExecutionContext *execution_context) override {
475 m_filenames.Clear();
476 m_line_num = 0;
477 m_column = 0;
478 m_func_names.clear();
479 m_func_name_type_mask = eFunctionNameTypeNone;
480 m_func_regexp.clear();
481 m_source_text_regexp.clear();
482 m_modules.Clear();
483 m_load_addr = LLDB_INVALID_ADDRESS;
484 m_offset_addr = 0;
485 m_catch_bp = false;
486 m_throw_bp = true;
487 m_hardware = false;
488 m_exception_language = eLanguageTypeUnknown;
489 m_language = lldb::eLanguageTypeUnknown;
490 m_skip_prologue = eLazyBoolCalculate;
491 m_breakpoint_names.clear();
492 m_all_files = false;
493 m_exception_extra_args.Clear();
494 m_move_to_nearest_code = eLazyBoolCalculate;
495 m_source_regex_func_names.clear();
496 m_current_key.clear();
499 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
500 return llvm::ArrayRef(g_breakpoint_set_options);
503 // Instance variables to hold the values for command options.
505 std::string m_condition;
506 FileSpecList m_filenames;
507 uint32_t m_line_num = 0;
508 uint32_t m_column = 0;
509 std::vector<std::string> m_func_names;
510 std::vector<std::string> m_breakpoint_names;
511 lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
512 std::string m_func_regexp;
513 std::string m_source_text_regexp;
514 FileSpecList m_modules;
515 lldb::addr_t m_load_addr = 0;
516 lldb::addr_t m_offset_addr;
517 bool m_catch_bp = false;
518 bool m_throw_bp = true;
519 bool m_hardware = false; // Request to use hardware breakpoints
520 lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
521 lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
522 LazyBool m_skip_prologue = eLazyBoolCalculate;
523 bool m_all_files = false;
524 Args m_exception_extra_args;
525 LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
526 std::unordered_set<std::string> m_source_regex_func_names;
527 std::string m_current_key;
530 protected:
531 void DoExecute(Args &command, CommandReturnObject &result) override {
532 Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
534 // The following are the various types of breakpoints that could be set:
535 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
536 // 2). -a [-s -g] (setting breakpoint by address)
537 // 3). -n [-s -g] (setting breakpoint by function name)
538 // 4). -r [-s -g] (setting breakpoint by function name regular
539 // expression)
540 // 5). -p -f (setting a breakpoint by comparing a reg-exp
541 // to source text)
542 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
543 // given language.)
545 BreakpointSetType break_type = eSetTypeInvalid;
547 if (!m_python_class_options.GetName().empty())
548 break_type = eSetTypeScripted;
549 else if (m_options.m_line_num != 0)
550 break_type = eSetTypeFileAndLine;
551 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
552 break_type = eSetTypeAddress;
553 else if (!m_options.m_func_names.empty())
554 break_type = eSetTypeFunctionName;
555 else if (!m_options.m_func_regexp.empty())
556 break_type = eSetTypeFunctionRegexp;
557 else if (!m_options.m_source_text_regexp.empty())
558 break_type = eSetTypeSourceRegexp;
559 else if (m_options.m_exception_language != eLanguageTypeUnknown)
560 break_type = eSetTypeException;
562 BreakpointSP bp_sp = nullptr;
563 FileSpec module_spec;
564 const bool internal = false;
566 // If the user didn't specify skip-prologue, having an offset should turn
567 // that off.
568 if (m_options.m_offset_addr != 0 &&
569 m_options.m_skip_prologue == eLazyBoolCalculate)
570 m_options.m_skip_prologue = eLazyBoolNo;
572 switch (break_type) {
573 case eSetTypeFileAndLine: // Breakpoint by source position
575 FileSpec file;
576 const size_t num_files = m_options.m_filenames.GetSize();
577 if (num_files == 0) {
578 if (!GetDefaultFile(target, file, result)) {
579 result.AppendError("No file supplied and no default file available.");
580 return;
582 } else if (num_files > 1) {
583 result.AppendError("Only one file at a time is allowed for file and "
584 "line breakpoints.");
585 return;
586 } else
587 file = m_options.m_filenames.GetFileSpecAtIndex(0);
589 // Only check for inline functions if
590 LazyBool check_inlines = eLazyBoolCalculate;
592 bp_sp = target.CreateBreakpoint(
593 &(m_options.m_modules), file, m_options.m_line_num,
594 m_options.m_column, m_options.m_offset_addr, check_inlines,
595 m_options.m_skip_prologue, internal, m_options.m_hardware,
596 m_options.m_move_to_nearest_code);
597 } break;
599 case eSetTypeAddress: // Breakpoint by address
601 // If a shared library has been specified, make an lldb_private::Address
602 // with the library, and use that. That way the address breakpoint
603 // will track the load location of the library.
604 size_t num_modules_specified = m_options.m_modules.GetSize();
605 if (num_modules_specified == 1) {
606 const FileSpec &file_spec =
607 m_options.m_modules.GetFileSpecAtIndex(0);
608 bp_sp = target.CreateAddressInModuleBreakpoint(
609 m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
610 } else if (num_modules_specified == 0) {
611 bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
612 m_options.m_hardware);
613 } else {
614 result.AppendError("Only one shared library can be specified for "
615 "address breakpoints.");
616 return;
618 break;
620 case eSetTypeFunctionName: // Breakpoint by function name
622 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
624 if (name_type_mask == 0)
625 name_type_mask = eFunctionNameTypeAuto;
627 bp_sp = target.CreateBreakpoint(
628 &(m_options.m_modules), &(m_options.m_filenames),
629 m_options.m_func_names, name_type_mask, m_options.m_language,
630 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
631 m_options.m_hardware);
632 } break;
634 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
635 // name
637 RegularExpression regexp(m_options.m_func_regexp);
638 if (llvm::Error err = regexp.GetError()) {
639 result.AppendErrorWithFormat(
640 "Function name regular expression could not be compiled: %s",
641 llvm::toString(std::move(err)).c_str());
642 // Check if the incorrect regex looks like a globbing expression and
643 // warn the user about it.
644 if (!m_options.m_func_regexp.empty()) {
645 if (m_options.m_func_regexp[0] == '*' ||
646 m_options.m_func_regexp[0] == '?')
647 result.AppendWarning(
648 "Function name regex does not accept glob patterns.");
650 return;
653 bp_sp = target.CreateFuncRegexBreakpoint(
654 &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
655 m_options.m_language, m_options.m_skip_prologue, internal,
656 m_options.m_hardware);
657 } break;
658 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
660 const size_t num_files = m_options.m_filenames.GetSize();
662 if (num_files == 0 && !m_options.m_all_files) {
663 FileSpec file;
664 if (!GetDefaultFile(target, file, result)) {
665 result.AppendError(
666 "No files provided and could not find default file.");
667 return;
668 } else {
669 m_options.m_filenames.Append(file);
673 RegularExpression regexp(m_options.m_source_text_regexp);
674 if (llvm::Error err = regexp.GetError()) {
675 result.AppendErrorWithFormat(
676 "Source text regular expression could not be compiled: \"%s\"",
677 llvm::toString(std::move(err)).c_str());
678 return;
680 bp_sp = target.CreateSourceRegexBreakpoint(
681 &(m_options.m_modules), &(m_options.m_filenames),
682 m_options.m_source_regex_func_names, std::move(regexp), internal,
683 m_options.m_hardware, m_options.m_move_to_nearest_code);
684 } break;
685 case eSetTypeException: {
686 Status precond_error;
687 bp_sp = target.CreateExceptionBreakpoint(
688 m_options.m_exception_language, m_options.m_catch_bp,
689 m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
690 &precond_error);
691 if (precond_error.Fail()) {
692 result.AppendErrorWithFormat(
693 "Error setting extra exception arguments: %s",
694 precond_error.AsCString());
695 target.RemoveBreakpointByID(bp_sp->GetID());
696 return;
698 } break;
699 case eSetTypeScripted: {
701 Status error;
702 bp_sp = target.CreateScriptedBreakpoint(
703 m_python_class_options.GetName().c_str(), &(m_options.m_modules),
704 &(m_options.m_filenames), false, m_options.m_hardware,
705 m_python_class_options.GetStructuredData(), &error);
706 if (error.Fail()) {
707 result.AppendErrorWithFormat(
708 "Error setting extra exception arguments: %s", error.AsCString());
709 target.RemoveBreakpointByID(bp_sp->GetID());
710 return;
712 } break;
713 default:
714 break;
717 // Now set the various options that were passed in:
718 if (bp_sp) {
719 bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
721 if (!m_options.m_breakpoint_names.empty()) {
722 Status name_error;
723 for (auto name : m_options.m_breakpoint_names) {
724 target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
725 if (name_error.Fail()) {
726 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
727 name.c_str());
728 target.RemoveBreakpointByID(bp_sp->GetID());
729 return;
735 if (bp_sp) {
736 Stream &output_stream = result.GetOutputStream();
737 const bool show_locations = false;
738 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
739 show_locations);
740 if (&target == &GetDummyTarget())
741 output_stream.Printf("Breakpoint set in dummy target, will get copied "
742 "into future targets.\n");
743 else {
744 // Don't print out this warning for exception breakpoints. They can
745 // get set before the target is set, but we won't know how to actually
746 // set the breakpoint till we run.
747 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
748 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
749 "actual locations.\n");
752 result.SetStatus(eReturnStatusSuccessFinishResult);
753 } else if (!bp_sp) {
754 result.AppendError("Breakpoint creation failed: No breakpoint created.");
758 private:
759 bool GetDefaultFile(Target &target, FileSpec &file,
760 CommandReturnObject &result) {
761 uint32_t default_line;
762 // First use the Source Manager's default file. Then use the current stack
763 // frame's file.
764 if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
765 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
766 if (cur_frame == nullptr) {
767 result.AppendError(
768 "No selected frame to use to find the default file.");
769 return false;
770 } else if (!cur_frame->HasDebugInformation()) {
771 result.AppendError("Cannot use the selected frame to find the default "
772 "file, it has no debug info.");
773 return false;
774 } else {
775 const SymbolContext &sc =
776 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
777 if (sc.line_entry.file) {
778 file = sc.line_entry.file;
779 } else {
780 result.AppendError("Can't find the file for the selected frame to "
781 "use as the default file.");
782 return false;
786 return true;
789 BreakpointOptionGroup m_bp_opts;
790 BreakpointDummyOptionGroup m_dummy_options;
791 OptionGroupPythonClassWithDict m_python_class_options;
792 CommandOptions m_options;
793 OptionGroupOptions m_all_options;
796 // CommandObjectBreakpointModify
797 #pragma mark Modify
799 class CommandObjectBreakpointModify : public CommandObjectParsed {
800 public:
801 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
802 : CommandObjectParsed(interpreter, "breakpoint modify",
803 "Modify the options on a breakpoint or set of "
804 "breakpoints in the executable. "
805 "If no breakpoint is specified, acts on the last "
806 "created breakpoint. "
807 "With the exception of -e, -d and -i, passing an "
808 "empty argument clears the modification.",
809 nullptr) {
810 CommandArgumentEntry arg;
811 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
812 eArgTypeBreakpointIDRange);
813 // Add the entry for the first argument for this command to the object's
814 // arguments vector.
815 m_arguments.push_back(arg);
817 m_options.Append(&m_bp_opts,
818 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
819 LLDB_OPT_SET_ALL);
820 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
821 m_options.Finalize();
824 ~CommandObjectBreakpointModify() override = default;
826 void
827 HandleArgumentCompletion(CompletionRequest &request,
828 OptionElementVector &opt_element_vector) override {
829 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
830 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
833 Options *GetOptions() override { return &m_options; }
835 protected:
836 void DoExecute(Args &command, CommandReturnObject &result) override {
837 Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
839 std::unique_lock<std::recursive_mutex> lock;
840 target.GetBreakpointList().GetListMutex(lock);
842 BreakpointIDList valid_bp_ids;
844 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
845 command, &target, result, &valid_bp_ids,
846 BreakpointName::Permissions::PermissionKinds::disablePerm);
848 if (result.Succeeded()) {
849 const size_t count = valid_bp_ids.GetSize();
850 for (size_t i = 0; i < count; ++i) {
851 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
853 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
854 Breakpoint *bp =
855 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
856 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
857 BreakpointLocation *location =
858 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
859 if (location)
860 location->GetLocationOptions().CopyOverSetOptions(
861 m_bp_opts.GetBreakpointOptions());
862 } else {
863 bp->GetOptions().CopyOverSetOptions(
864 m_bp_opts.GetBreakpointOptions());
871 private:
872 BreakpointOptionGroup m_bp_opts;
873 BreakpointDummyOptionGroup m_dummy_opts;
874 OptionGroupOptions m_options;
877 // CommandObjectBreakpointEnable
878 #pragma mark Enable
880 class CommandObjectBreakpointEnable : public CommandObjectParsed {
881 public:
882 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
883 : CommandObjectParsed(interpreter, "enable",
884 "Enable the specified disabled breakpoint(s). If "
885 "no breakpoints are specified, enable all of them.",
886 nullptr) {
887 CommandArgumentEntry arg;
888 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
889 eArgTypeBreakpointIDRange);
890 // Add the entry for the first argument for this command to the object's
891 // arguments vector.
892 m_arguments.push_back(arg);
895 ~CommandObjectBreakpointEnable() override = default;
897 void
898 HandleArgumentCompletion(CompletionRequest &request,
899 OptionElementVector &opt_element_vector) override {
900 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
901 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
904 protected:
905 void DoExecute(Args &command, CommandReturnObject &result) override {
906 Target &target = GetSelectedOrDummyTarget();
908 std::unique_lock<std::recursive_mutex> lock;
909 target.GetBreakpointList().GetListMutex(lock);
911 const BreakpointList &breakpoints = target.GetBreakpointList();
913 size_t num_breakpoints = breakpoints.GetSize();
915 if (num_breakpoints == 0) {
916 result.AppendError("No breakpoints exist to be enabled.");
917 return;
920 if (command.empty()) {
921 // No breakpoint selected; enable all currently set breakpoints.
922 target.EnableAllowedBreakpoints();
923 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
924 " breakpoints)\n",
925 (uint64_t)num_breakpoints);
926 result.SetStatus(eReturnStatusSuccessFinishNoResult);
927 } else {
928 // Particular breakpoint selected; enable that breakpoint.
929 BreakpointIDList valid_bp_ids;
930 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
931 command, &target, result, &valid_bp_ids,
932 BreakpointName::Permissions::PermissionKinds::disablePerm);
934 if (result.Succeeded()) {
935 int enable_count = 0;
936 int loc_count = 0;
937 const size_t count = valid_bp_ids.GetSize();
938 for (size_t i = 0; i < count; ++i) {
939 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
941 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
942 Breakpoint *breakpoint =
943 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
944 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
945 BreakpointLocation *location =
946 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
947 if (location) {
948 location->SetEnabled(true);
949 ++loc_count;
951 } else {
952 breakpoint->SetEnabled(true);
953 ++enable_count;
957 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
958 enable_count + loc_count);
959 result.SetStatus(eReturnStatusSuccessFinishNoResult);
965 // CommandObjectBreakpointDisable
966 #pragma mark Disable
968 class CommandObjectBreakpointDisable : public CommandObjectParsed {
969 public:
970 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
971 : CommandObjectParsed(
972 interpreter, "breakpoint disable",
973 "Disable the specified breakpoint(s) without deleting "
974 "them. If none are specified, disable all "
975 "breakpoints.",
976 nullptr) {
977 SetHelpLong(
978 "Disable the specified breakpoint(s) without deleting them. \
979 If none are specified, disable all breakpoints."
983 "Note: disabling a breakpoint will cause none of its locations to be hit \
984 regardless of whether individual locations are enabled or disabled. After the sequence:"
987 (lldb) break disable 1
988 (lldb) break enable 1.1
990 execution will NOT stop at location 1.1. To achieve that, type:
992 (lldb) break disable 1.*
993 (lldb) break enable 1.1
996 "The first command disables all locations for breakpoint 1, \
997 the second re-enables the first location.");
999 CommandArgumentEntry arg;
1000 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1001 eArgTypeBreakpointIDRange);
1002 // Add the entry for the first argument for this command to the object's
1003 // arguments vector.
1004 m_arguments.push_back(arg);
1007 ~CommandObjectBreakpointDisable() override = default;
1009 void
1010 HandleArgumentCompletion(CompletionRequest &request,
1011 OptionElementVector &opt_element_vector) override {
1012 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1013 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1016 protected:
1017 void DoExecute(Args &command, CommandReturnObject &result) override {
1018 Target &target = GetSelectedOrDummyTarget();
1019 std::unique_lock<std::recursive_mutex> lock;
1020 target.GetBreakpointList().GetListMutex(lock);
1022 const BreakpointList &breakpoints = target.GetBreakpointList();
1023 size_t num_breakpoints = breakpoints.GetSize();
1025 if (num_breakpoints == 0) {
1026 result.AppendError("No breakpoints exist to be disabled.");
1027 return;
1030 if (command.empty()) {
1031 // No breakpoint selected; disable all currently set breakpoints.
1032 target.DisableAllowedBreakpoints();
1033 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1034 " breakpoints)\n",
1035 (uint64_t)num_breakpoints);
1036 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1037 } else {
1038 // Particular breakpoint selected; disable that breakpoint.
1039 BreakpointIDList valid_bp_ids;
1041 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1042 command, &target, result, &valid_bp_ids,
1043 BreakpointName::Permissions::PermissionKinds::disablePerm);
1045 if (result.Succeeded()) {
1046 int disable_count = 0;
1047 int loc_count = 0;
1048 const size_t count = valid_bp_ids.GetSize();
1049 for (size_t i = 0; i < count; ++i) {
1050 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1052 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1053 Breakpoint *breakpoint =
1054 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1055 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1056 BreakpointLocation *location =
1057 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1058 if (location) {
1059 location->SetEnabled(false);
1060 ++loc_count;
1062 } else {
1063 breakpoint->SetEnabled(false);
1064 ++disable_count;
1068 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1069 disable_count + loc_count);
1070 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1076 // CommandObjectBreakpointList
1078 #pragma mark List::CommandOptions
1079 #define LLDB_OPTIONS_breakpoint_list
1080 #include "CommandOptions.inc"
1082 #pragma mark List
1084 class CommandObjectBreakpointList : public CommandObjectParsed {
1085 public:
1086 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1087 : CommandObjectParsed(
1088 interpreter, "breakpoint list",
1089 "List some or all breakpoints at configurable levels of detail.",
1090 nullptr) {
1091 CommandArgumentEntry arg;
1092 CommandArgumentData bp_id_arg;
1094 // Define the first (and only) variant of this arg.
1095 bp_id_arg.arg_type = eArgTypeBreakpointID;
1096 bp_id_arg.arg_repetition = eArgRepeatOptional;
1098 // There is only one variant this argument could be; put it into the
1099 // argument entry.
1100 arg.push_back(bp_id_arg);
1102 // Push the data for the first argument into the m_arguments vector.
1103 m_arguments.push_back(arg);
1106 ~CommandObjectBreakpointList() override = default;
1108 Options *GetOptions() override { return &m_options; }
1110 class CommandOptions : public Options {
1111 public:
1112 CommandOptions() = default;
1114 ~CommandOptions() override = default;
1116 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1117 ExecutionContext *execution_context) override {
1118 Status error;
1119 const int short_option = m_getopt_table[option_idx].val;
1121 switch (short_option) {
1122 case 'b':
1123 m_level = lldb::eDescriptionLevelBrief;
1124 break;
1125 case 'D':
1126 m_use_dummy = true;
1127 break;
1128 case 'f':
1129 m_level = lldb::eDescriptionLevelFull;
1130 break;
1131 case 'v':
1132 m_level = lldb::eDescriptionLevelVerbose;
1133 break;
1134 case 'i':
1135 m_internal = true;
1136 break;
1137 default:
1138 llvm_unreachable("Unimplemented option");
1141 return error;
1144 void OptionParsingStarting(ExecutionContext *execution_context) override {
1145 m_level = lldb::eDescriptionLevelFull;
1146 m_internal = false;
1147 m_use_dummy = false;
1150 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1151 return llvm::ArrayRef(g_breakpoint_list_options);
1154 // Instance variables to hold the values for command options.
1156 lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
1158 bool m_internal;
1159 bool m_use_dummy = false;
1162 protected:
1163 void DoExecute(Args &command, CommandReturnObject &result) override {
1164 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1166 const BreakpointList &breakpoints =
1167 target.GetBreakpointList(m_options.m_internal);
1168 std::unique_lock<std::recursive_mutex> lock;
1169 target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1171 size_t num_breakpoints = breakpoints.GetSize();
1173 if (num_breakpoints == 0) {
1174 result.AppendMessage("No breakpoints currently set.");
1175 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1176 return;
1179 Stream &output_stream = result.GetOutputStream();
1181 if (command.empty()) {
1182 // No breakpoint selected; show info about all currently set breakpoints.
1183 result.AppendMessage("Current breakpoints:");
1184 for (size_t i = 0; i < num_breakpoints; ++i) {
1185 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1186 if (breakpoint->AllowList())
1187 AddBreakpointDescription(&output_stream, breakpoint,
1188 m_options.m_level);
1190 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1191 } else {
1192 // Particular breakpoints selected; show info about that breakpoint.
1193 BreakpointIDList valid_bp_ids;
1194 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1195 command, &target, result, &valid_bp_ids,
1196 BreakpointName::Permissions::PermissionKinds::listPerm);
1198 if (result.Succeeded()) {
1199 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1200 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1201 Breakpoint *breakpoint =
1202 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1203 AddBreakpointDescription(&output_stream, breakpoint,
1204 m_options.m_level);
1206 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1207 } else {
1208 result.AppendError("Invalid breakpoint ID.");
1213 private:
1214 CommandOptions m_options;
1217 // CommandObjectBreakpointClear
1218 #pragma mark Clear::CommandOptions
1220 #define LLDB_OPTIONS_breakpoint_clear
1221 #include "CommandOptions.inc"
1223 #pragma mark Clear
1225 class CommandObjectBreakpointClear : public CommandObjectParsed {
1226 public:
1227 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1229 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1230 : CommandObjectParsed(interpreter, "breakpoint clear",
1231 "Delete or disable breakpoints matching the "
1232 "specified source file and line.",
1233 "breakpoint clear <cmd-options>") {}
1235 ~CommandObjectBreakpointClear() override = default;
1237 Options *GetOptions() override { return &m_options; }
1239 class CommandOptions : public Options {
1240 public:
1241 CommandOptions() = default;
1243 ~CommandOptions() override = default;
1245 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1246 ExecutionContext *execution_context) override {
1247 Status error;
1248 const int short_option = m_getopt_table[option_idx].val;
1250 switch (short_option) {
1251 case 'f':
1252 m_filename.assign(std::string(option_arg));
1253 break;
1255 case 'l':
1256 option_arg.getAsInteger(0, m_line_num);
1257 break;
1259 default:
1260 llvm_unreachable("Unimplemented option");
1263 return error;
1266 void OptionParsingStarting(ExecutionContext *execution_context) override {
1267 m_filename.clear();
1268 m_line_num = 0;
1271 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1272 return llvm::ArrayRef(g_breakpoint_clear_options);
1275 // Instance variables to hold the values for command options.
1277 std::string m_filename;
1278 uint32_t m_line_num = 0;
1281 protected:
1282 void DoExecute(Args &command, CommandReturnObject &result) override {
1283 Target &target = GetSelectedOrDummyTarget();
1285 // The following are the various types of breakpoints that could be
1286 // cleared:
1287 // 1). -f -l (clearing breakpoint by source location)
1289 BreakpointClearType break_type = eClearTypeInvalid;
1291 if (m_options.m_line_num != 0)
1292 break_type = eClearTypeFileAndLine;
1294 std::unique_lock<std::recursive_mutex> lock;
1295 target.GetBreakpointList().GetListMutex(lock);
1297 BreakpointList &breakpoints = target.GetBreakpointList();
1298 size_t num_breakpoints = breakpoints.GetSize();
1300 // Early return if there's no breakpoint at all.
1301 if (num_breakpoints == 0) {
1302 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1303 return;
1306 // Find matching breakpoints and delete them.
1308 // First create a copy of all the IDs.
1309 std::vector<break_id_t> BreakIDs;
1310 for (size_t i = 0; i < num_breakpoints; ++i)
1311 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1313 int num_cleared = 0;
1314 StreamString ss;
1315 switch (break_type) {
1316 case eClearTypeFileAndLine: // Breakpoint by source position
1318 const ConstString filename(m_options.m_filename.c_str());
1319 BreakpointLocationCollection loc_coll;
1321 for (size_t i = 0; i < num_breakpoints; ++i) {
1322 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1324 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1325 // If the collection size is 0, it's a full match and we can just
1326 // remove the breakpoint.
1327 if (loc_coll.GetSize() == 0) {
1328 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1329 ss.EOL();
1330 target.RemoveBreakpointByID(bp->GetID());
1331 ++num_cleared;
1335 } break;
1337 default:
1338 break;
1341 if (num_cleared > 0) {
1342 Stream &output_stream = result.GetOutputStream();
1343 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1344 output_stream << ss.GetString();
1345 output_stream.EOL();
1346 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1347 } else {
1348 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1352 private:
1353 CommandOptions m_options;
1356 // CommandObjectBreakpointDelete
1357 #define LLDB_OPTIONS_breakpoint_delete
1358 #include "CommandOptions.inc"
1360 #pragma mark Delete
1362 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1363 public:
1364 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1365 : CommandObjectParsed(interpreter, "breakpoint delete",
1366 "Delete the specified breakpoint(s). If no "
1367 "breakpoints are specified, delete them all.",
1368 nullptr) {
1369 CommandArgumentEntry arg;
1370 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1371 eArgTypeBreakpointIDRange);
1372 // Add the entry for the first argument for this command to the object's
1373 // arguments vector.
1374 m_arguments.push_back(arg);
1377 ~CommandObjectBreakpointDelete() override = default;
1379 void
1380 HandleArgumentCompletion(CompletionRequest &request,
1381 OptionElementVector &opt_element_vector) override {
1382 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1383 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1386 Options *GetOptions() override { return &m_options; }
1388 class CommandOptions : public Options {
1389 public:
1390 CommandOptions() = default;
1392 ~CommandOptions() override = default;
1394 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1395 ExecutionContext *execution_context) override {
1396 Status error;
1397 const int short_option = m_getopt_table[option_idx].val;
1399 switch (short_option) {
1400 case 'f':
1401 m_force = true;
1402 break;
1404 case 'D':
1405 m_use_dummy = true;
1406 break;
1408 case 'd':
1409 m_delete_disabled = true;
1410 break;
1412 default:
1413 llvm_unreachable("Unimplemented option");
1416 return error;
1419 void OptionParsingStarting(ExecutionContext *execution_context) override {
1420 m_use_dummy = false;
1421 m_force = false;
1422 m_delete_disabled = false;
1425 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1426 return llvm::ArrayRef(g_breakpoint_delete_options);
1429 // Instance variables to hold the values for command options.
1430 bool m_use_dummy = false;
1431 bool m_force = false;
1432 bool m_delete_disabled = false;
1435 protected:
1436 void DoExecute(Args &command, CommandReturnObject &result) override {
1437 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1438 result.Clear();
1440 std::unique_lock<std::recursive_mutex> lock;
1441 target.GetBreakpointList().GetListMutex(lock);
1443 BreakpointList &breakpoints = target.GetBreakpointList();
1445 size_t num_breakpoints = breakpoints.GetSize();
1447 if (num_breakpoints == 0) {
1448 result.AppendError("No breakpoints exist to be deleted.");
1449 return;
1452 // Handle the delete all breakpoints case:
1453 if (command.empty() && !m_options.m_delete_disabled) {
1454 if (!m_options.m_force &&
1455 !m_interpreter.Confirm(
1456 "About to delete all breakpoints, do you want to do that?",
1457 true)) {
1458 result.AppendMessage("Operation cancelled...");
1459 } else {
1460 target.RemoveAllowedBreakpoints();
1461 result.AppendMessageWithFormat(
1462 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1463 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1465 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1466 return;
1469 // Either we have some kind of breakpoint specification(s),
1470 // or we are handling "break disable --deleted". Gather the list
1471 // of breakpoints to delete here, the we'll delete them below.
1472 BreakpointIDList valid_bp_ids;
1474 if (m_options.m_delete_disabled) {
1475 BreakpointIDList excluded_bp_ids;
1477 if (!command.empty()) {
1478 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1479 command, &target, result, &excluded_bp_ids,
1480 BreakpointName::Permissions::PermissionKinds::deletePerm);
1481 if (!result.Succeeded())
1482 return;
1485 for (auto breakpoint_sp : breakpoints.Breakpoints()) {
1486 if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
1487 BreakpointID bp_id(breakpoint_sp->GetID());
1488 size_t pos = 0;
1489 if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
1490 valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
1493 if (valid_bp_ids.GetSize() == 0) {
1494 result.AppendError("No disabled breakpoints.");
1495 return;
1497 } else {
1498 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1499 command, &target, result, &valid_bp_ids,
1500 BreakpointName::Permissions::PermissionKinds::deletePerm);
1501 if (!result.Succeeded())
1502 return;
1505 int delete_count = 0;
1506 int disable_count = 0;
1507 const size_t count = valid_bp_ids.GetSize();
1508 for (size_t i = 0; i < count; ++i) {
1509 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1511 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1512 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1513 Breakpoint *breakpoint =
1514 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1515 BreakpointLocation *location =
1516 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1517 // It makes no sense to try to delete individual locations, so we
1518 // disable them instead.
1519 if (location) {
1520 location->SetEnabled(false);
1521 ++disable_count;
1523 } else {
1524 target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1525 ++delete_count;
1529 result.AppendMessageWithFormat(
1530 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1531 delete_count, disable_count);
1532 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1535 private:
1536 CommandOptions m_options;
1539 // CommandObjectBreakpointName
1540 #define LLDB_OPTIONS_breakpoint_name
1541 #include "CommandOptions.inc"
1543 class BreakpointNameOptionGroup : public OptionGroup {
1544 public:
1545 BreakpointNameOptionGroup()
1546 : m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {}
1548 ~BreakpointNameOptionGroup() override = default;
1550 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1551 return llvm::ArrayRef(g_breakpoint_name_options);
1554 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1555 ExecutionContext *execution_context) override {
1556 Status error;
1557 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1559 switch (short_option) {
1560 case 'N':
1561 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1562 error.Success())
1563 m_name.SetValueFromString(option_arg);
1564 break;
1565 case 'B':
1566 if (m_breakpoint.SetValueFromString(option_arg).Fail())
1567 error.SetErrorStringWithFormat(
1568 "unrecognized value \"%s\" for breakpoint",
1569 option_arg.str().c_str());
1570 break;
1571 case 'D':
1572 if (m_use_dummy.SetValueFromString(option_arg).Fail())
1573 error.SetErrorStringWithFormat(
1574 "unrecognized value \"%s\" for use-dummy",
1575 option_arg.str().c_str());
1576 break;
1577 case 'H':
1578 m_help_string.SetValueFromString(option_arg);
1579 break;
1581 default:
1582 llvm_unreachable("Unimplemented option");
1584 return error;
1587 void OptionParsingStarting(ExecutionContext *execution_context) override {
1588 m_name.Clear();
1589 m_breakpoint.Clear();
1590 m_use_dummy.Clear();
1591 m_use_dummy.SetDefaultValue(false);
1592 m_help_string.Clear();
1595 OptionValueString m_name;
1596 OptionValueUInt64 m_breakpoint;
1597 OptionValueBoolean m_use_dummy;
1598 OptionValueString m_help_string;
1601 #define LLDB_OPTIONS_breakpoint_access
1602 #include "CommandOptions.inc"
1604 class BreakpointAccessOptionGroup : public OptionGroup {
1605 public:
1606 BreakpointAccessOptionGroup() = default;
1608 ~BreakpointAccessOptionGroup() override = default;
1610 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1611 return llvm::ArrayRef(g_breakpoint_access_options);
1613 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1614 ExecutionContext *execution_context) override {
1615 Status error;
1616 const int short_option =
1617 g_breakpoint_access_options[option_idx].short_option;
1619 switch (short_option) {
1620 case 'L': {
1621 bool value, success;
1622 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1623 if (success) {
1624 m_permissions.SetAllowList(value);
1625 } else
1626 error.SetErrorStringWithFormat(
1627 "invalid boolean value '%s' passed for -L option",
1628 option_arg.str().c_str());
1629 } break;
1630 case 'A': {
1631 bool value, success;
1632 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1633 if (success) {
1634 m_permissions.SetAllowDisable(value);
1635 } else
1636 error.SetErrorStringWithFormat(
1637 "invalid boolean value '%s' passed for -L option",
1638 option_arg.str().c_str());
1639 } break;
1640 case 'D': {
1641 bool value, success;
1642 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1643 if (success) {
1644 m_permissions.SetAllowDelete(value);
1645 } else
1646 error.SetErrorStringWithFormat(
1647 "invalid boolean value '%s' passed for -L option",
1648 option_arg.str().c_str());
1649 } break;
1650 default:
1651 llvm_unreachable("Unimplemented option");
1654 return error;
1657 void OptionParsingStarting(ExecutionContext *execution_context) override {}
1659 const BreakpointName::Permissions &GetPermissions() const {
1660 return m_permissions;
1662 BreakpointName::Permissions m_permissions;
1665 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1666 public:
1667 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1668 : CommandObjectParsed(
1669 interpreter, "configure",
1670 "Configure the options for the breakpoint"
1671 " name provided. "
1672 "If you provide a breakpoint id, the options will be copied from "
1673 "the breakpoint, otherwise only the options specified will be set "
1674 "on the name.",
1675 "breakpoint name configure <command-options> "
1676 "<breakpoint-name-list>") {
1677 // Create the first variant for the first (and only) argument for this
1678 // command.
1679 CommandArgumentEntry arg1;
1680 CommandArgumentData id_arg;
1681 id_arg.arg_type = eArgTypeBreakpointName;
1682 id_arg.arg_repetition = eArgRepeatOptional;
1683 arg1.push_back(id_arg);
1684 m_arguments.push_back(arg1);
1686 m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1687 m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1688 LLDB_OPT_SET_ALL);
1689 m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1690 LLDB_OPT_SET_ALL);
1691 m_option_group.Finalize();
1694 ~CommandObjectBreakpointNameConfigure() override = default;
1696 Options *GetOptions() override { return &m_option_group; }
1698 protected:
1699 void DoExecute(Args &command, CommandReturnObject &result) override {
1701 const size_t argc = command.GetArgumentCount();
1702 if (argc == 0) {
1703 result.AppendError("No names provided.");
1704 return;
1707 Target &target = GetSelectedOrDummyTarget(false);
1709 std::unique_lock<std::recursive_mutex> lock;
1710 target.GetBreakpointList().GetListMutex(lock);
1712 // Make a pass through first to see that all the names are legal.
1713 for (auto &entry : command.entries()) {
1714 Status error;
1715 if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1716 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1717 entry.c_str(), error.AsCString());
1718 return;
1721 // Now configure them, we already pre-checked the names so we don't need to
1722 // check the error:
1723 BreakpointSP bp_sp;
1724 if (m_bp_id.m_breakpoint.OptionWasSet()) {
1725 lldb::break_id_t bp_id =
1726 m_bp_id.m_breakpoint.GetValueAs<uint64_t>().value_or(0);
1727 bp_sp = target.GetBreakpointByID(bp_id);
1728 if (!bp_sp) {
1729 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1730 bp_id);
1731 return;
1735 Status error;
1736 for (auto &entry : command.entries()) {
1737 ConstString name(entry.c_str());
1738 BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1739 if (!bp_name)
1740 continue;
1741 if (m_bp_id.m_help_string.OptionWasSet())
1742 bp_name->SetHelp(m_bp_id.m_help_string.GetValueAs<llvm::StringRef>()
1743 .value_or("")
1744 .str()
1745 .c_str());
1747 if (bp_sp)
1748 target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1749 m_access_options.GetPermissions());
1750 else
1751 target.ConfigureBreakpointName(*bp_name,
1752 m_bp_opts.GetBreakpointOptions(),
1753 m_access_options.GetPermissions());
1757 private:
1758 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1759 BreakpointOptionGroup m_bp_opts;
1760 BreakpointAccessOptionGroup m_access_options;
1761 OptionGroupOptions m_option_group;
1764 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1765 public:
1766 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1767 : CommandObjectParsed(
1768 interpreter, "add", "Add a name to the breakpoints provided.",
1769 "breakpoint name add <command-options> <breakpoint-id-list>") {
1770 // Create the first variant for the first (and only) argument for this
1771 // command.
1772 CommandArgumentEntry arg1;
1773 CommandArgumentData id_arg;
1774 id_arg.arg_type = eArgTypeBreakpointID;
1775 id_arg.arg_repetition = eArgRepeatOptional;
1776 arg1.push_back(id_arg);
1777 m_arguments.push_back(arg1);
1779 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1780 m_option_group.Finalize();
1783 ~CommandObjectBreakpointNameAdd() override = default;
1785 void
1786 HandleArgumentCompletion(CompletionRequest &request,
1787 OptionElementVector &opt_element_vector) override {
1788 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1789 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1792 Options *GetOptions() override { return &m_option_group; }
1794 protected:
1795 void DoExecute(Args &command, CommandReturnObject &result) override {
1796 if (!m_name_options.m_name.OptionWasSet()) {
1797 result.AppendError("No name option provided.");
1798 return;
1801 Target &target =
1802 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1804 std::unique_lock<std::recursive_mutex> lock;
1805 target.GetBreakpointList().GetListMutex(lock);
1807 const BreakpointList &breakpoints = target.GetBreakpointList();
1809 size_t num_breakpoints = breakpoints.GetSize();
1810 if (num_breakpoints == 0) {
1811 result.AppendError("No breakpoints, cannot add names.");
1812 return;
1815 // Particular breakpoint selected; disable that breakpoint.
1816 BreakpointIDList valid_bp_ids;
1817 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1818 command, &target, result, &valid_bp_ids,
1819 BreakpointName::Permissions::PermissionKinds::listPerm);
1821 if (result.Succeeded()) {
1822 if (valid_bp_ids.GetSize() == 0) {
1823 result.AppendError("No breakpoints specified, cannot add names.");
1824 return;
1826 size_t num_valid_ids = valid_bp_ids.GetSize();
1827 const char *bp_name = m_name_options.m_name.GetCurrentValue();
1828 Status error; // This error reports illegal names, but we've already
1829 // checked that, so we don't need to check it again here.
1830 for (size_t index = 0; index < num_valid_ids; index++) {
1831 lldb::break_id_t bp_id =
1832 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1833 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1834 target.AddNameToBreakpoint(bp_sp, bp_name, error);
1839 private:
1840 BreakpointNameOptionGroup m_name_options;
1841 OptionGroupOptions m_option_group;
1844 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1845 public:
1846 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1847 : CommandObjectParsed(
1848 interpreter, "delete",
1849 "Delete a name from the breakpoints provided.",
1850 "breakpoint name delete <command-options> <breakpoint-id-list>") {
1851 // Create the first variant for the first (and only) argument for this
1852 // command.
1853 CommandArgumentEntry arg1;
1854 CommandArgumentData id_arg;
1855 id_arg.arg_type = eArgTypeBreakpointID;
1856 id_arg.arg_repetition = eArgRepeatOptional;
1857 arg1.push_back(id_arg);
1858 m_arguments.push_back(arg1);
1860 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1861 m_option_group.Finalize();
1864 ~CommandObjectBreakpointNameDelete() override = default;
1866 void
1867 HandleArgumentCompletion(CompletionRequest &request,
1868 OptionElementVector &opt_element_vector) override {
1869 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1870 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1873 Options *GetOptions() override { return &m_option_group; }
1875 protected:
1876 void DoExecute(Args &command, CommandReturnObject &result) override {
1877 if (!m_name_options.m_name.OptionWasSet()) {
1878 result.AppendError("No name option provided.");
1879 return;
1882 Target &target =
1883 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1885 std::unique_lock<std::recursive_mutex> lock;
1886 target.GetBreakpointList().GetListMutex(lock);
1888 const BreakpointList &breakpoints = target.GetBreakpointList();
1890 size_t num_breakpoints = breakpoints.GetSize();
1891 if (num_breakpoints == 0) {
1892 result.AppendError("No breakpoints, cannot delete names.");
1893 return;
1896 // Particular breakpoint selected; disable that breakpoint.
1897 BreakpointIDList valid_bp_ids;
1898 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1899 command, &target, result, &valid_bp_ids,
1900 BreakpointName::Permissions::PermissionKinds::deletePerm);
1902 if (result.Succeeded()) {
1903 if (valid_bp_ids.GetSize() == 0) {
1904 result.AppendError("No breakpoints specified, cannot delete names.");
1905 return;
1907 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
1908 size_t num_valid_ids = valid_bp_ids.GetSize();
1909 for (size_t index = 0; index < num_valid_ids; index++) {
1910 lldb::break_id_t bp_id =
1911 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1912 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1913 target.RemoveNameFromBreakpoint(bp_sp, bp_name);
1918 private:
1919 BreakpointNameOptionGroup m_name_options;
1920 OptionGroupOptions m_option_group;
1923 class CommandObjectBreakpointNameList : public CommandObjectParsed {
1924 public:
1925 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1926 : CommandObjectParsed(interpreter, "list",
1927 "List either the names for a breakpoint or info "
1928 "about a given name. With no arguments, lists all "
1929 "names",
1930 "breakpoint name list <command-options>") {
1931 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
1932 m_option_group.Finalize();
1935 ~CommandObjectBreakpointNameList() override = default;
1937 Options *GetOptions() override { return &m_option_group; }
1939 protected:
1940 void DoExecute(Args &command, CommandReturnObject &result) override {
1941 Target &target =
1942 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1944 std::vector<std::string> name_list;
1945 if (command.empty()) {
1946 target.GetBreakpointNames(name_list);
1947 } else {
1948 for (const Args::ArgEntry &arg : command) {
1949 name_list.push_back(arg.c_str());
1953 if (name_list.empty()) {
1954 result.AppendMessage("No breakpoint names found.");
1955 } else {
1956 for (const std::string &name_str : name_list) {
1957 const char *name = name_str.c_str();
1958 // First print out the options for the name:
1959 Status error;
1960 BreakpointName *bp_name =
1961 target.FindBreakpointName(ConstString(name), false, error);
1962 if (bp_name) {
1963 StreamString s;
1964 result.AppendMessageWithFormat("Name: %s\n", name);
1965 if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1966 result.AppendMessage(s.GetString());
1969 std::unique_lock<std::recursive_mutex> lock;
1970 target.GetBreakpointList().GetListMutex(lock);
1972 BreakpointList &breakpoints = target.GetBreakpointList();
1973 bool any_set = false;
1974 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1975 if (bp_sp->MatchesName(name)) {
1976 StreamString s;
1977 any_set = true;
1978 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1979 s.EOL();
1980 result.AppendMessage(s.GetString());
1983 if (!any_set)
1984 result.AppendMessage("No breakpoints using this name.");
1985 } else {
1986 result.AppendMessageWithFormat("Name: %s not found.\n", name);
1992 private:
1993 BreakpointNameOptionGroup m_name_options;
1994 OptionGroupOptions m_option_group;
1997 // CommandObjectBreakpointName
1998 class CommandObjectBreakpointName : public CommandObjectMultiword {
1999 public:
2000 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2001 : CommandObjectMultiword(
2002 interpreter, "name", "Commands to manage breakpoint names") {
2005 SetHelpLong(
2007 Breakpoint names provide a general tagging mechanism for breakpoints. Each
2008 breakpoint name can be added to any number of breakpoints, and each breakpoint
2009 can have any number of breakpoint names attached to it. For instance:
2011 (lldb) break name add -N MyName 1-10
2013 adds the name MyName to breakpoints 1-10, and:
2015 (lldb) break set -n myFunc -N Name1 -N Name2
2017 adds two names to the breakpoint set at myFunc.
2019 They have a number of interrelated uses:
2021 1) They provide a stable way to refer to a breakpoint (e.g. in another
2022 breakpoint's action). Using the breakpoint ID for this purpose is fragile, since
2023 it depends on the order of breakpoint creation. Giving a name to the breakpoint
2024 you want to act on, and then referring to it by name, is more robust:
2026 (lldb) break set -n myFunc -N BKPT1
2027 (lldb) break set -n myOtherFunc -C "break disable BKPT1"
2029 2) This is actually just a specific use of a more general feature of breakpoint
2030 names. The <breakpt-id-list> argument type used to specify one or more
2031 breakpoints in most of the commands that deal with breakpoints also accepts
2032 breakpoint names. That allows you to refer to one breakpoint in a stable
2033 manner, but also makes them a convenient grouping mechanism, allowing you to
2034 easily act on a group of breakpoints by using their name, for instance disabling
2035 them all in one action:
2037 (lldb) break set -n myFunc -N Group1
2038 (lldb) break set -n myOtherFunc -N Group1
2039 (lldb) break disable Group1
2041 3) But breakpoint names are also entities in their own right, and can be
2042 configured with all the modifiable attributes of a breakpoint. Then when you
2043 add a breakpoint name to a breakpoint, the breakpoint will be configured to
2044 match the state of the breakpoint name. The link between the name and the
2045 breakpoints sharing it remains live, so if you change the configuration on the
2046 name, it will also change the configurations on the breakpoints:
2048 (lldb) break name configure -i 10 IgnoreSome
2049 (lldb) break set -n myFunc -N IgnoreSome
2050 (lldb) break list IgnoreSome
2051 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled
2052 Names:
2053 IgnoreSome
2054 (lldb) break name configure -i 5 IgnoreSome
2055 (lldb) break list IgnoreSome
2056 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled
2057 Names:
2058 IgnoreSome
2060 Options that are not configured on a breakpoint name don't affect the value of
2061 those options on the breakpoints they are added to. So for instance, if Name1
2062 has the -i option configured and Name2 the -c option, adding both names to a
2063 breakpoint will set the -i option from Name1 and the -c option from Name2, and
2064 the other options will be unaltered.
2066 If you add multiple names to a breakpoint which have configured values for
2067 the same option, the last name added's value wins.
2069 The "liveness" of these settings is one way, from name to breakpoint.
2070 If you use "break modify" to change an option that is also configured on a name
2071 which that breakpoint has, the "break modify" command will override the setting
2072 for that breakpoint, but won't change the value configured in the name or on the
2073 other breakpoints sharing that name.
2075 4) Breakpoint names are also a convenient way to copy option sets from one
2076 breakpoint to another. Using the -B option to "breakpoint name configure" makes
2077 a name configured with all the options of the original breakpoint. Then
2078 adding that name to another breakpoint copies over all the values from the
2079 original breakpoint to the new one.
2081 5) You can also use breakpoint names to hide breakpoints from the breakpoint
2082 operations that act on all breakpoints: "break delete", "break disable" and
2083 "break list". You do that by specifying a "false" value for the
2084 --allow-{list,delete,disable} options to "breakpoint name configure" and then
2085 adding that name to a breakpoint.
2087 This won't keep the breakpoint from being deleted or disabled if you refer to it
2088 specifically by ID. The point of the feature is to make sure users don't
2089 inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using
2090 for its own purposes) as part of a "delete all" or "disable all" operation. The
2091 list hiding is because it's confusing for people to see breakpoints they
2092 didn't set.
2094 )");
2095 CommandObjectSP add_command_object(
2096 new CommandObjectBreakpointNameAdd(interpreter));
2097 CommandObjectSP delete_command_object(
2098 new CommandObjectBreakpointNameDelete(interpreter));
2099 CommandObjectSP list_command_object(
2100 new CommandObjectBreakpointNameList(interpreter));
2101 CommandObjectSP configure_command_object(
2102 new CommandObjectBreakpointNameConfigure(interpreter));
2104 LoadSubCommand("add", add_command_object);
2105 LoadSubCommand("delete", delete_command_object);
2106 LoadSubCommand("list", list_command_object);
2107 LoadSubCommand("configure", configure_command_object);
2110 ~CommandObjectBreakpointName() override = default;
2113 // CommandObjectBreakpointRead
2114 #pragma mark Read::CommandOptions
2115 #define LLDB_OPTIONS_breakpoint_read
2116 #include "CommandOptions.inc"
2118 #pragma mark Read
2120 class CommandObjectBreakpointRead : public CommandObjectParsed {
2121 public:
2122 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2123 : CommandObjectParsed(interpreter, "breakpoint read",
2124 "Read and set the breakpoints previously saved to "
2125 "a file with \"breakpoint write\". ",
2126 nullptr) {}
2128 ~CommandObjectBreakpointRead() override = default;
2130 Options *GetOptions() override { return &m_options; }
2132 class CommandOptions : public Options {
2133 public:
2134 CommandOptions() = default;
2136 ~CommandOptions() override = default;
2138 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2139 ExecutionContext *execution_context) override {
2140 Status error;
2141 const int short_option = m_getopt_table[option_idx].val;
2143 switch (short_option) {
2144 case 'f':
2145 m_filename.assign(std::string(option_arg));
2146 break;
2147 case 'N': {
2148 Status name_error;
2149 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2150 name_error)) {
2151 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2152 name_error.AsCString());
2154 m_names.push_back(std::string(option_arg));
2155 break;
2157 default:
2158 llvm_unreachable("Unimplemented option");
2161 return error;
2164 void OptionParsingStarting(ExecutionContext *execution_context) override {
2165 m_filename.clear();
2166 m_names.clear();
2169 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2170 return llvm::ArrayRef(g_breakpoint_read_options);
2173 void HandleOptionArgumentCompletion(
2174 CompletionRequest &request, OptionElementVector &opt_element_vector,
2175 int opt_element_index, CommandInterpreter &interpreter) override {
2176 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2177 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2179 switch (GetDefinitions()[opt_defs_index].short_option) {
2180 case 'f':
2181 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2182 interpreter, lldb::eDiskFileCompletion, request, nullptr);
2183 break;
2185 case 'N':
2186 std::optional<FileSpec> file_spec;
2187 const llvm::StringRef dash_f("-f");
2188 for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2189 if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2190 file_spec.emplace(
2191 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2192 break;
2195 if (!file_spec)
2196 return;
2198 FileSystem::Instance().Resolve(*file_spec);
2199 Status error;
2200 StructuredData::ObjectSP input_data_sp =
2201 StructuredData::ParseJSONFromFile(*file_spec, error);
2202 if (!error.Success())
2203 return;
2205 StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2206 if (!bkpt_array)
2207 return;
2209 const size_t num_bkpts = bkpt_array->GetSize();
2210 for (size_t i = 0; i < num_bkpts; i++) {
2211 StructuredData::ObjectSP bkpt_object_sp =
2212 bkpt_array->GetItemAtIndex(i);
2213 if (!bkpt_object_sp)
2214 return;
2216 StructuredData::Dictionary *bkpt_dict =
2217 bkpt_object_sp->GetAsDictionary();
2218 if (!bkpt_dict)
2219 return;
2221 StructuredData::ObjectSP bkpt_data_sp =
2222 bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2223 if (!bkpt_data_sp)
2224 return;
2226 bkpt_dict = bkpt_data_sp->GetAsDictionary();
2227 if (!bkpt_dict)
2228 return;
2230 StructuredData::Array *names_array;
2232 if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2233 return;
2235 size_t num_names = names_array->GetSize();
2237 for (size_t i = 0; i < num_names; i++) {
2238 llvm::StringRef name;
2239 if (names_array->GetItemAtIndexAsString(i, name))
2240 request.TryCompleteCurrentArg(name);
2246 std::string m_filename;
2247 std::vector<std::string> m_names;
2250 protected:
2251 void DoExecute(Args &command, CommandReturnObject &result) override {
2252 Target &target = GetSelectedOrDummyTarget();
2254 std::unique_lock<std::recursive_mutex> lock;
2255 target.GetBreakpointList().GetListMutex(lock);
2257 FileSpec input_spec(m_options.m_filename);
2258 FileSystem::Instance().Resolve(input_spec);
2259 BreakpointIDList new_bps;
2260 Status error = target.CreateBreakpointsFromFile(input_spec,
2261 m_options.m_names, new_bps);
2263 if (!error.Success()) {
2264 result.AppendError(error.AsCString());
2265 return;
2268 Stream &output_stream = result.GetOutputStream();
2270 size_t num_breakpoints = new_bps.GetSize();
2271 if (num_breakpoints == 0) {
2272 result.AppendMessage("No breakpoints added.");
2273 } else {
2274 // No breakpoint selected; show info about all currently set breakpoints.
2275 result.AppendMessage("New breakpoints:");
2276 for (size_t i = 0; i < num_breakpoints; ++i) {
2277 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2278 Breakpoint *bp = target.GetBreakpointList()
2279 .FindBreakpointByID(bp_id.GetBreakpointID())
2280 .get();
2281 if (bp)
2282 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2283 false);
2288 private:
2289 CommandOptions m_options;
2292 // CommandObjectBreakpointWrite
2293 #pragma mark Write::CommandOptions
2294 #define LLDB_OPTIONS_breakpoint_write
2295 #include "CommandOptions.inc"
2297 #pragma mark Write
2298 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2299 public:
2300 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2301 : CommandObjectParsed(interpreter, "breakpoint write",
2302 "Write the breakpoints listed to a file that can "
2303 "be read in with \"breakpoint read\". "
2304 "If given no arguments, writes all breakpoints.",
2305 nullptr) {
2306 CommandArgumentEntry arg;
2307 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2308 eArgTypeBreakpointIDRange);
2309 // Add the entry for the first argument for this command to the object's
2310 // arguments vector.
2311 m_arguments.push_back(arg);
2314 ~CommandObjectBreakpointWrite() override = default;
2316 void
2317 HandleArgumentCompletion(CompletionRequest &request,
2318 OptionElementVector &opt_element_vector) override {
2319 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2320 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
2323 Options *GetOptions() override { return &m_options; }
2325 class CommandOptions : public Options {
2326 public:
2327 CommandOptions() = default;
2329 ~CommandOptions() override = default;
2331 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2332 ExecutionContext *execution_context) override {
2333 Status error;
2334 const int short_option = m_getopt_table[option_idx].val;
2336 switch (short_option) {
2337 case 'f':
2338 m_filename.assign(std::string(option_arg));
2339 break;
2340 case 'a':
2341 m_append = true;
2342 break;
2343 default:
2344 llvm_unreachable("Unimplemented option");
2347 return error;
2350 void OptionParsingStarting(ExecutionContext *execution_context) override {
2351 m_filename.clear();
2352 m_append = false;
2355 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2356 return llvm::ArrayRef(g_breakpoint_write_options);
2359 // Instance variables to hold the values for command options.
2361 std::string m_filename;
2362 bool m_append = false;
2365 protected:
2366 void DoExecute(Args &command, CommandReturnObject &result) override {
2367 Target &target = GetSelectedOrDummyTarget();
2369 std::unique_lock<std::recursive_mutex> lock;
2370 target.GetBreakpointList().GetListMutex(lock);
2372 BreakpointIDList valid_bp_ids;
2373 if (!command.empty()) {
2374 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2375 command, &target, result, &valid_bp_ids,
2376 BreakpointName::Permissions::PermissionKinds::listPerm);
2378 if (!result.Succeeded()) {
2379 result.SetStatus(eReturnStatusFailed);
2380 return;
2383 FileSpec file_spec(m_options.m_filename);
2384 FileSystem::Instance().Resolve(file_spec);
2385 Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2386 m_options.m_append);
2387 if (!error.Success()) {
2388 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2389 error.AsCString());
2393 private:
2394 CommandOptions m_options;
2397 // CommandObjectMultiwordBreakpoint
2398 #pragma mark MultiwordBreakpoint
2400 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2401 CommandInterpreter &interpreter)
2402 : CommandObjectMultiword(
2403 interpreter, "breakpoint",
2404 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2405 "breakpoint <subcommand> [<command-options>]") {
2406 CommandObjectSP list_command_object(
2407 new CommandObjectBreakpointList(interpreter));
2408 CommandObjectSP enable_command_object(
2409 new CommandObjectBreakpointEnable(interpreter));
2410 CommandObjectSP disable_command_object(
2411 new CommandObjectBreakpointDisable(interpreter));
2412 CommandObjectSP clear_command_object(
2413 new CommandObjectBreakpointClear(interpreter));
2414 CommandObjectSP delete_command_object(
2415 new CommandObjectBreakpointDelete(interpreter));
2416 CommandObjectSP set_command_object(
2417 new CommandObjectBreakpointSet(interpreter));
2418 CommandObjectSP command_command_object(
2419 new CommandObjectBreakpointCommand(interpreter));
2420 CommandObjectSP modify_command_object(
2421 new CommandObjectBreakpointModify(interpreter));
2422 CommandObjectSP name_command_object(
2423 new CommandObjectBreakpointName(interpreter));
2424 CommandObjectSP write_command_object(
2425 new CommandObjectBreakpointWrite(interpreter));
2426 CommandObjectSP read_command_object(
2427 new CommandObjectBreakpointRead(interpreter));
2429 list_command_object->SetCommandName("breakpoint list");
2430 enable_command_object->SetCommandName("breakpoint enable");
2431 disable_command_object->SetCommandName("breakpoint disable");
2432 clear_command_object->SetCommandName("breakpoint clear");
2433 delete_command_object->SetCommandName("breakpoint delete");
2434 set_command_object->SetCommandName("breakpoint set");
2435 command_command_object->SetCommandName("breakpoint command");
2436 modify_command_object->SetCommandName("breakpoint modify");
2437 name_command_object->SetCommandName("breakpoint name");
2438 write_command_object->SetCommandName("breakpoint write");
2439 read_command_object->SetCommandName("breakpoint read");
2441 LoadSubCommand("list", list_command_object);
2442 LoadSubCommand("enable", enable_command_object);
2443 LoadSubCommand("disable", disable_command_object);
2444 LoadSubCommand("clear", clear_command_object);
2445 LoadSubCommand("delete", delete_command_object);
2446 LoadSubCommand("set", set_command_object);
2447 LoadSubCommand("command", command_command_object);
2448 LoadSubCommand("modify", modify_command_object);
2449 LoadSubCommand("name", name_command_object);
2450 LoadSubCommand("write", write_command_object);
2451 LoadSubCommand("read", read_command_object);
2454 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2456 void CommandObjectMultiwordBreakpoint::VerifyIDs(
2457 Args &args, Target *target, bool allow_locations,
2458 CommandReturnObject &result, BreakpointIDList *valid_ids,
2459 BreakpointName::Permissions ::PermissionKinds purpose) {
2460 // args can be strings representing 1). integers (for breakpoint ids)
2461 // 2). the full breakpoint & location
2462 // canonical representation
2463 // 3). the word "to" or a hyphen,
2464 // representing a range (in which case there
2465 // had *better* be an entry both before &
2466 // after of one of the first two types.
2467 // 4). A breakpoint name
2468 // If args is empty, we will use the last created breakpoint (if there is
2469 // one.)
2471 Args temp_args;
2473 if (args.empty()) {
2474 if (target->GetLastCreatedBreakpoint()) {
2475 valid_ids->AddBreakpointID(BreakpointID(
2476 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2477 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2478 } else {
2479 result.AppendError(
2480 "No breakpoint specified and no last created breakpoint.");
2482 return;
2485 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2486 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2487 // id range strings over; instead generate a list of strings for all the
2488 // breakpoint ids in the range, and shove all of those breakpoint id strings
2489 // into TEMP_ARGS.
2491 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2492 purpose, result, temp_args);
2494 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2495 // BreakpointIDList:
2497 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2499 // At this point, all of the breakpoint ids that the user passed in have
2500 // been converted to breakpoint IDs and put into valid_ids.
2502 if (result.Succeeded()) {
2503 // Now that we've converted everything from args into a list of breakpoint
2504 // ids, go through our tentative list of breakpoint id's and verify that
2505 // they correspond to valid/currently set breakpoints.
2507 const size_t count = valid_ids->GetSize();
2508 for (size_t i = 0; i < count; ++i) {
2509 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2510 Breakpoint *breakpoint =
2511 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2512 if (breakpoint != nullptr) {
2513 const size_t num_locations = breakpoint->GetNumLocations();
2514 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2515 StreamString id_str;
2516 BreakpointID::GetCanonicalReference(
2517 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2518 i = valid_ids->GetSize() + 1;
2519 result.AppendErrorWithFormat(
2520 "'%s' is not a currently valid breakpoint/location id.\n",
2521 id_str.GetData());
2523 } else {
2524 i = valid_ids->GetSize() + 1;
2525 result.AppendErrorWithFormat(
2526 "'%d' is not a currently valid breakpoint ID.\n",
2527 cur_bp_id.GetBreakpointID());