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 //===----------------------------------------------------------------------===//
8
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/CommandReturnObject.h"
17 #include "lldb/Interpreter/OptionArgParser.h"
18 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
19 #include "lldb/Interpreter/OptionValueBoolean.h"
20 #include "lldb/Interpreter/OptionValueFileColonLine.h"
21 #include "lldb/Interpreter/OptionValueString.h"
22 #include "lldb/Interpreter/OptionValueUInt64.h"
23 #include "lldb/Interpreter/Options.h"
24 #include "lldb/Target/Language.h"
25 #include "lldb/Target/StackFrame.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/ThreadSpec.h"
28 #include "lldb/Utility/RegularExpression.h"
29 #include "lldb/Utility/StreamString.h"
30
31 #include <memory>
32 #include <vector>
33
34 using namespace lldb;
35 using namespace lldb_private;
36
AddBreakpointDescription(Stream * s,Breakpoint * bp,lldb::DescriptionLevel level)37 static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38 lldb::DescriptionLevel level) {
39 s->IndentMore();
40 bp->GetDescription(s, level, true);
41 s->IndentLess();
42 s->EOL();
43 }
44
45 // Modifiable Breakpoint Options
46 #pragma mark Modify::CommandOptions
47 #define LLDB_OPTIONS_breakpoint_modify
48 #include "CommandOptions.inc"
49
50 class lldb_private::BreakpointOptionGroup : public OptionGroup {
51 public:
BreakpointOptionGroup()52 BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {}
53
54 ~BreakpointOptionGroup() override = default;
55
GetDefinitions()56 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
57 return llvm::makeArrayRef(g_breakpoint_modify_options);
58 }
59
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)60 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
61 ExecutionContext *execution_context) override {
62 Status error;
63 const int short_option =
64 g_breakpoint_modify_options[option_idx].short_option;
65
66 switch (short_option) {
67 case 'c':
68 // Normally an empty breakpoint condition marks is as unset. But we need
69 // to say it was passed in.
70 m_bp_opts.SetCondition(option_arg.str().c_str());
71 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
72 break;
73 case 'C':
74 m_commands.push_back(std::string(option_arg));
75 break;
76 case 'd':
77 m_bp_opts.SetEnabled(false);
78 break;
79 case 'e':
80 m_bp_opts.SetEnabled(true);
81 break;
82 case 'G': {
83 bool value, success;
84 value = OptionArgParser::ToBoolean(option_arg, false, &success);
85 if (success) {
86 m_bp_opts.SetAutoContinue(value);
87 } else
88 error.SetErrorStringWithFormat(
89 "invalid boolean value '%s' passed for -G option",
90 option_arg.str().c_str());
91 } break;
92 case 'i': {
93 uint32_t ignore_count;
94 if (option_arg.getAsInteger(0, ignore_count))
95 error.SetErrorStringWithFormat("invalid ignore count '%s'",
96 option_arg.str().c_str());
97 else
98 m_bp_opts.SetIgnoreCount(ignore_count);
99 } break;
100 case 'o': {
101 bool value, success;
102 value = OptionArgParser::ToBoolean(option_arg, false, &success);
103 if (success) {
104 m_bp_opts.SetOneShot(value);
105 } else
106 error.SetErrorStringWithFormat(
107 "invalid boolean value '%s' passed for -o option",
108 option_arg.str().c_str());
109 } break;
110 case 't': {
111 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
112 if (option_arg[0] != '\0') {
113 if (option_arg.getAsInteger(0, thread_id))
114 error.SetErrorStringWithFormat("invalid thread id string '%s'",
115 option_arg.str().c_str());
116 }
117 m_bp_opts.SetThreadID(thread_id);
118 } break;
119 case 'T':
120 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
121 break;
122 case 'q':
123 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
124 break;
125 case 'x': {
126 uint32_t thread_index = UINT32_MAX;
127 if (option_arg[0] != '\n') {
128 if (option_arg.getAsInteger(0, thread_index))
129 error.SetErrorStringWithFormat("invalid thread index string '%s'",
130 option_arg.str().c_str());
131 }
132 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
133 } break;
134 default:
135 llvm_unreachable("Unimplemented option");
136 }
137
138 return error;
139 }
140
OptionParsingStarting(ExecutionContext * execution_context)141 void OptionParsingStarting(ExecutionContext *execution_context) override {
142 m_bp_opts.Clear();
143 m_commands.clear();
144 }
145
OptionParsingFinished(ExecutionContext * execution_context)146 Status OptionParsingFinished(ExecutionContext *execution_context) override {
147 if (!m_commands.empty()) {
148 auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
149
150 for (std::string &str : m_commands)
151 cmd_data->user_source.AppendString(str);
152
153 cmd_data->stop_on_error = true;
154 m_bp_opts.SetCommandDataCallback(cmd_data);
155 }
156 return Status();
157 }
158
GetBreakpointOptions()159 const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
160
161 std::vector<std::string> m_commands;
162 BreakpointOptions m_bp_opts;
163 };
164
165 #define LLDB_OPTIONS_breakpoint_dummy
166 #include "CommandOptions.inc"
167
168 class BreakpointDummyOptionGroup : public OptionGroup {
169 public:
BreakpointDummyOptionGroup()170 BreakpointDummyOptionGroup() : OptionGroup() {}
171
172 ~BreakpointDummyOptionGroup() override = default;
173
GetDefinitions()174 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
175 return llvm::makeArrayRef(g_breakpoint_dummy_options);
176 }
177
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)178 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
179 ExecutionContext *execution_context) override {
180 Status error;
181 const int short_option =
182 g_breakpoint_dummy_options[option_idx].short_option;
183
184 switch (short_option) {
185 case 'D':
186 m_use_dummy = true;
187 break;
188 default:
189 llvm_unreachable("Unimplemented option");
190 }
191
192 return error;
193 }
194
OptionParsingStarting(ExecutionContext * execution_context)195 void OptionParsingStarting(ExecutionContext *execution_context) override {
196 m_use_dummy = false;
197 }
198
199 bool m_use_dummy;
200 };
201
202 #define LLDB_OPTIONS_breakpoint_set
203 #include "CommandOptions.inc"
204
205 // CommandObjectBreakpointSet
206
207 class CommandObjectBreakpointSet : public CommandObjectParsed {
208 public:
209 enum BreakpointSetType {
210 eSetTypeInvalid,
211 eSetTypeFileAndLine,
212 eSetTypeAddress,
213 eSetTypeFunctionName,
214 eSetTypeFunctionRegexp,
215 eSetTypeSourceRegexp,
216 eSetTypeException,
217 eSetTypeScripted,
218 };
219
CommandObjectBreakpointSet(CommandInterpreter & interpreter)220 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
221 : CommandObjectParsed(
222 interpreter, "breakpoint set",
223 "Sets a breakpoint or set of breakpoints in the executable.",
224 "breakpoint set <cmd-options>"),
225 m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'),
226 m_options() {
227 // We're picking up all the normal options, commands and disable.
228 m_all_options.Append(&m_python_class_options,
229 LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
230 m_all_options.Append(&m_bp_opts,
231 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
232 LLDB_OPT_SET_ALL);
233 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
234 m_all_options.Append(&m_options);
235 m_all_options.Finalize();
236 }
237
238 ~CommandObjectBreakpointSet() override = default;
239
GetOptions()240 Options *GetOptions() override { return &m_all_options; }
241
242 class CommandOptions : public OptionGroup {
243 public:
CommandOptions()244 CommandOptions()
245 : OptionGroup(), m_condition(), m_filenames(), m_func_names(),
246 m_func_regexp(), m_source_text_regexp(), m_modules() {}
247
248 ~CommandOptions() override = default;
249
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)250 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
251 ExecutionContext *execution_context) override {
252 Status error;
253 const int short_option =
254 g_breakpoint_set_options[option_idx].short_option;
255
256 switch (short_option) {
257 case 'a': {
258 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
259 LLDB_INVALID_ADDRESS, &error);
260 } break;
261
262 case 'A':
263 m_all_files = true;
264 break;
265
266 case 'b':
267 m_func_names.push_back(std::string(option_arg));
268 m_func_name_type_mask |= eFunctionNameTypeBase;
269 break;
270
271 case 'u':
272 if (option_arg.getAsInteger(0, m_column))
273 error.SetErrorStringWithFormat("invalid column number: %s",
274 option_arg.str().c_str());
275 break;
276
277 case 'E': {
278 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
279
280 switch (language) {
281 case eLanguageTypeC89:
282 case eLanguageTypeC:
283 case eLanguageTypeC99:
284 case eLanguageTypeC11:
285 m_exception_language = eLanguageTypeC;
286 break;
287 case eLanguageTypeC_plus_plus:
288 case eLanguageTypeC_plus_plus_03:
289 case eLanguageTypeC_plus_plus_11:
290 case eLanguageTypeC_plus_plus_14:
291 m_exception_language = eLanguageTypeC_plus_plus;
292 break;
293 case eLanguageTypeObjC:
294 m_exception_language = eLanguageTypeObjC;
295 break;
296 case eLanguageTypeObjC_plus_plus:
297 error.SetErrorStringWithFormat(
298 "Set exception breakpoints separately for c++ and objective-c");
299 break;
300 case eLanguageTypeUnknown:
301 error.SetErrorStringWithFormat(
302 "Unknown language type: '%s' for exception breakpoint",
303 option_arg.str().c_str());
304 break;
305 default:
306 error.SetErrorStringWithFormat(
307 "Unsupported language type: '%s' for exception breakpoint",
308 option_arg.str().c_str());
309 }
310 } break;
311
312 case 'f':
313 m_filenames.AppendIfUnique(FileSpec(option_arg));
314 break;
315
316 case 'F':
317 m_func_names.push_back(std::string(option_arg));
318 m_func_name_type_mask |= eFunctionNameTypeFull;
319 break;
320
321 case 'h': {
322 bool success;
323 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
324 if (!success)
325 error.SetErrorStringWithFormat(
326 "Invalid boolean value for on-catch option: '%s'",
327 option_arg.str().c_str());
328 } break;
329
330 case 'H':
331 m_hardware = true;
332 break;
333
334 case 'K': {
335 bool success;
336 bool value;
337 value = OptionArgParser::ToBoolean(option_arg, true, &success);
338 if (value)
339 m_skip_prologue = eLazyBoolYes;
340 else
341 m_skip_prologue = eLazyBoolNo;
342
343 if (!success)
344 error.SetErrorStringWithFormat(
345 "Invalid boolean value for skip prologue option: '%s'",
346 option_arg.str().c_str());
347 } break;
348
349 case 'l':
350 if (option_arg.getAsInteger(0, m_line_num))
351 error.SetErrorStringWithFormat("invalid line number: %s.",
352 option_arg.str().c_str());
353 break;
354
355 case 'L':
356 m_language = Language::GetLanguageTypeFromString(option_arg);
357 if (m_language == eLanguageTypeUnknown)
358 error.SetErrorStringWithFormat(
359 "Unknown language type: '%s' for breakpoint",
360 option_arg.str().c_str());
361 break;
362
363 case 'm': {
364 bool success;
365 bool value;
366 value = OptionArgParser::ToBoolean(option_arg, true, &success);
367 if (value)
368 m_move_to_nearest_code = eLazyBoolYes;
369 else
370 m_move_to_nearest_code = eLazyBoolNo;
371
372 if (!success)
373 error.SetErrorStringWithFormat(
374 "Invalid boolean value for move-to-nearest-code option: '%s'",
375 option_arg.str().c_str());
376 break;
377 }
378
379 case 'M':
380 m_func_names.push_back(std::string(option_arg));
381 m_func_name_type_mask |= eFunctionNameTypeMethod;
382 break;
383
384 case 'n':
385 m_func_names.push_back(std::string(option_arg));
386 m_func_name_type_mask |= eFunctionNameTypeAuto;
387 break;
388
389 case 'N': {
390 if (BreakpointID::StringIsBreakpointName(option_arg, error))
391 m_breakpoint_names.push_back(std::string(option_arg));
392 else
393 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
394 option_arg.str().c_str());
395 break;
396 }
397
398 case 'R': {
399 lldb::addr_t tmp_offset_addr;
400 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
401 option_arg, 0, &error);
402 if (error.Success())
403 m_offset_addr = tmp_offset_addr;
404 } break;
405
406 case 'O':
407 m_exception_extra_args.AppendArgument("-O");
408 m_exception_extra_args.AppendArgument(option_arg);
409 break;
410
411 case 'p':
412 m_source_text_regexp.assign(std::string(option_arg));
413 break;
414
415 case 'r':
416 m_func_regexp.assign(std::string(option_arg));
417 break;
418
419 case 's':
420 m_modules.AppendIfUnique(FileSpec(option_arg));
421 break;
422
423 case 'S':
424 m_func_names.push_back(std::string(option_arg));
425 m_func_name_type_mask |= eFunctionNameTypeSelector;
426 break;
427
428 case 'w': {
429 bool success;
430 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
431 if (!success)
432 error.SetErrorStringWithFormat(
433 "Invalid boolean value for on-throw option: '%s'",
434 option_arg.str().c_str());
435 } break;
436
437 case 'X':
438 m_source_regex_func_names.insert(std::string(option_arg));
439 break;
440
441 case 'y':
442 {
443 OptionValueFileColonLine value;
444 Status fcl_err = value.SetValueFromString(option_arg);
445 if (!fcl_err.Success()) {
446 error.SetErrorStringWithFormat(
447 "Invalid value for file:line specifier: %s",
448 fcl_err.AsCString());
449 } else {
450 m_filenames.AppendIfUnique(value.GetFileSpec());
451 m_line_num = value.GetLineNumber();
452 m_column = value.GetColumnNumber();
453 }
454 } break;
455
456 default:
457 llvm_unreachable("Unimplemented option");
458 }
459
460 return error;
461 }
462
OptionParsingStarting(ExecutionContext * execution_context)463 void OptionParsingStarting(ExecutionContext *execution_context) override {
464 m_filenames.Clear();
465 m_line_num = 0;
466 m_column = 0;
467 m_func_names.clear();
468 m_func_name_type_mask = eFunctionNameTypeNone;
469 m_func_regexp.clear();
470 m_source_text_regexp.clear();
471 m_modules.Clear();
472 m_load_addr = LLDB_INVALID_ADDRESS;
473 m_offset_addr = 0;
474 m_catch_bp = false;
475 m_throw_bp = true;
476 m_hardware = false;
477 m_exception_language = eLanguageTypeUnknown;
478 m_language = lldb::eLanguageTypeUnknown;
479 m_skip_prologue = eLazyBoolCalculate;
480 m_breakpoint_names.clear();
481 m_all_files = false;
482 m_exception_extra_args.Clear();
483 m_move_to_nearest_code = eLazyBoolCalculate;
484 m_source_regex_func_names.clear();
485 m_current_key.clear();
486 }
487
GetDefinitions()488 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
489 return llvm::makeArrayRef(g_breakpoint_set_options);
490 }
491
492 // Instance variables to hold the values for command options.
493
494 std::string m_condition;
495 FileSpecList m_filenames;
496 uint32_t m_line_num = 0;
497 uint32_t m_column = 0;
498 std::vector<std::string> m_func_names;
499 std::vector<std::string> m_breakpoint_names;
500 lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
501 std::string m_func_regexp;
502 std::string m_source_text_regexp;
503 FileSpecList m_modules;
504 lldb::addr_t m_load_addr = 0;
505 lldb::addr_t m_offset_addr;
506 bool m_catch_bp = false;
507 bool m_throw_bp = true;
508 bool m_hardware = false; // Request to use hardware breakpoints
509 lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
510 lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
511 LazyBool m_skip_prologue = eLazyBoolCalculate;
512 bool m_all_files = false;
513 Args m_exception_extra_args;
514 LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
515 std::unordered_set<std::string> m_source_regex_func_names;
516 std::string m_current_key;
517 };
518
519 protected:
DoExecute(Args & command,CommandReturnObject & result)520 bool DoExecute(Args &command, CommandReturnObject &result) override {
521 Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
522
523 // The following are the various types of breakpoints that could be set:
524 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
525 // 2). -a [-s -g] (setting breakpoint by address)
526 // 3). -n [-s -g] (setting breakpoint by function name)
527 // 4). -r [-s -g] (setting breakpoint by function name regular
528 // expression)
529 // 5). -p -f (setting a breakpoint by comparing a reg-exp
530 // to source text)
531 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
532 // given language.)
533
534 BreakpointSetType break_type = eSetTypeInvalid;
535
536 if (!m_python_class_options.GetName().empty())
537 break_type = eSetTypeScripted;
538 else if (m_options.m_line_num != 0)
539 break_type = eSetTypeFileAndLine;
540 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
541 break_type = eSetTypeAddress;
542 else if (!m_options.m_func_names.empty())
543 break_type = eSetTypeFunctionName;
544 else if (!m_options.m_func_regexp.empty())
545 break_type = eSetTypeFunctionRegexp;
546 else if (!m_options.m_source_text_regexp.empty())
547 break_type = eSetTypeSourceRegexp;
548 else if (m_options.m_exception_language != eLanguageTypeUnknown)
549 break_type = eSetTypeException;
550
551 BreakpointSP bp_sp = nullptr;
552 FileSpec module_spec;
553 const bool internal = false;
554
555 // If the user didn't specify skip-prologue, having an offset should turn
556 // that off.
557 if (m_options.m_offset_addr != 0 &&
558 m_options.m_skip_prologue == eLazyBoolCalculate)
559 m_options.m_skip_prologue = eLazyBoolNo;
560
561 switch (break_type) {
562 case eSetTypeFileAndLine: // Breakpoint by source position
563 {
564 FileSpec file;
565 const size_t num_files = m_options.m_filenames.GetSize();
566 if (num_files == 0) {
567 if (!GetDefaultFile(target, file, result)) {
568 result.AppendError("No file supplied and no default file available.");
569 return false;
570 }
571 } else if (num_files > 1) {
572 result.AppendError("Only one file at a time is allowed for file and "
573 "line breakpoints.");
574 return false;
575 } else
576 file = m_options.m_filenames.GetFileSpecAtIndex(0);
577
578 // Only check for inline functions if
579 LazyBool check_inlines = eLazyBoolCalculate;
580
581 bp_sp = target.CreateBreakpoint(
582 &(m_options.m_modules), file, m_options.m_line_num,
583 m_options.m_column, m_options.m_offset_addr, check_inlines,
584 m_options.m_skip_prologue, internal, m_options.m_hardware,
585 m_options.m_move_to_nearest_code);
586 } break;
587
588 case eSetTypeAddress: // Breakpoint by address
589 {
590 // If a shared library has been specified, make an lldb_private::Address
591 // with the library, and use that. That way the address breakpoint
592 // will track the load location of the library.
593 size_t num_modules_specified = m_options.m_modules.GetSize();
594 if (num_modules_specified == 1) {
595 const FileSpec *file_spec =
596 m_options.m_modules.GetFileSpecPointerAtIndex(0);
597 bp_sp = target.CreateAddressInModuleBreakpoint(
598 m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
599 } else if (num_modules_specified == 0) {
600 bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
601 m_options.m_hardware);
602 } else {
603 result.AppendError("Only one shared library can be specified for "
604 "address breakpoints.");
605 return false;
606 }
607 break;
608 }
609 case eSetTypeFunctionName: // Breakpoint by function name
610 {
611 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
612
613 if (name_type_mask == 0)
614 name_type_mask = eFunctionNameTypeAuto;
615
616 bp_sp = target.CreateBreakpoint(
617 &(m_options.m_modules), &(m_options.m_filenames),
618 m_options.m_func_names, name_type_mask, m_options.m_language,
619 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
620 m_options.m_hardware);
621 } break;
622
623 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
624 // name
625 {
626 RegularExpression regexp(m_options.m_func_regexp);
627 if (llvm::Error err = regexp.GetError()) {
628 result.AppendErrorWithFormat(
629 "Function name regular expression could not be compiled: %s",
630 llvm::toString(std::move(err)).c_str());
631 // Check if the incorrect regex looks like a globbing expression and
632 // warn the user about it.
633 if (!m_options.m_func_regexp.empty()) {
634 if (m_options.m_func_regexp[0] == '*' ||
635 m_options.m_func_regexp[0] == '?')
636 result.AppendWarning(
637 "Function name regex does not accept glob patterns.");
638 }
639 return false;
640 }
641
642 bp_sp = target.CreateFuncRegexBreakpoint(
643 &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
644 m_options.m_language, m_options.m_skip_prologue, internal,
645 m_options.m_hardware);
646 } break;
647 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
648 {
649 const size_t num_files = m_options.m_filenames.GetSize();
650
651 if (num_files == 0 && !m_options.m_all_files) {
652 FileSpec file;
653 if (!GetDefaultFile(target, file, result)) {
654 result.AppendError(
655 "No files provided and could not find default file.");
656 return false;
657 } else {
658 m_options.m_filenames.Append(file);
659 }
660 }
661
662 RegularExpression regexp(m_options.m_source_text_regexp);
663 if (llvm::Error err = regexp.GetError()) {
664 result.AppendErrorWithFormat(
665 "Source text regular expression could not be compiled: \"%s\"",
666 llvm::toString(std::move(err)).c_str());
667 return false;
668 }
669 bp_sp = target.CreateSourceRegexBreakpoint(
670 &(m_options.m_modules), &(m_options.m_filenames),
671 m_options.m_source_regex_func_names, std::move(regexp), internal,
672 m_options.m_hardware, m_options.m_move_to_nearest_code);
673 } break;
674 case eSetTypeException: {
675 Status precond_error;
676 bp_sp = target.CreateExceptionBreakpoint(
677 m_options.m_exception_language, m_options.m_catch_bp,
678 m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
679 &precond_error);
680 if (precond_error.Fail()) {
681 result.AppendErrorWithFormat(
682 "Error setting extra exception arguments: %s",
683 precond_error.AsCString());
684 target.RemoveBreakpointByID(bp_sp->GetID());
685 return false;
686 }
687 } break;
688 case eSetTypeScripted: {
689
690 Status error;
691 bp_sp = target.CreateScriptedBreakpoint(
692 m_python_class_options.GetName().c_str(), &(m_options.m_modules),
693 &(m_options.m_filenames), false, m_options.m_hardware,
694 m_python_class_options.GetStructuredData(), &error);
695 if (error.Fail()) {
696 result.AppendErrorWithFormat(
697 "Error setting extra exception arguments: %s", error.AsCString());
698 target.RemoveBreakpointByID(bp_sp->GetID());
699 return false;
700 }
701 } break;
702 default:
703 break;
704 }
705
706 // Now set the various options that were passed in:
707 if (bp_sp) {
708 bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
709
710 if (!m_options.m_breakpoint_names.empty()) {
711 Status name_error;
712 for (auto name : m_options.m_breakpoint_names) {
713 target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
714 if (name_error.Fail()) {
715 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
716 name.c_str());
717 target.RemoveBreakpointByID(bp_sp->GetID());
718 return false;
719 }
720 }
721 }
722 }
723
724 if (bp_sp) {
725 Stream &output_stream = result.GetOutputStream();
726 const bool show_locations = false;
727 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
728 show_locations);
729 if (&target == &GetDummyTarget())
730 output_stream.Printf("Breakpoint set in dummy target, will get copied "
731 "into future targets.\n");
732 else {
733 // Don't print out this warning for exception breakpoints. They can
734 // get set before the target is set, but we won't know how to actually
735 // set the breakpoint till we run.
736 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
737 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
738 "actual locations.\n");
739 }
740 }
741 result.SetStatus(eReturnStatusSuccessFinishResult);
742 } else if (!bp_sp) {
743 result.AppendError("Breakpoint creation failed: No breakpoint created.");
744 }
745
746 return result.Succeeded();
747 }
748
749 private:
GetDefaultFile(Target & target,FileSpec & file,CommandReturnObject & result)750 bool GetDefaultFile(Target &target, FileSpec &file,
751 CommandReturnObject &result) {
752 uint32_t default_line;
753 // First use the Source Manager's default file. Then use the current stack
754 // frame's file.
755 if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
756 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
757 if (cur_frame == nullptr) {
758 result.AppendError(
759 "No selected frame to use to find the default file.");
760 return false;
761 } else if (!cur_frame->HasDebugInformation()) {
762 result.AppendError("Cannot use the selected frame to find the default "
763 "file, it has no debug info.");
764 return false;
765 } else {
766 const SymbolContext &sc =
767 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
768 if (sc.line_entry.file) {
769 file = sc.line_entry.file;
770 } else {
771 result.AppendError("Can't find the file for the selected frame to "
772 "use as the default file.");
773 return false;
774 }
775 }
776 }
777 return true;
778 }
779
780 BreakpointOptionGroup m_bp_opts;
781 BreakpointDummyOptionGroup m_dummy_options;
782 OptionGroupPythonClassWithDict m_python_class_options;
783 CommandOptions m_options;
784 OptionGroupOptions m_all_options;
785 };
786
787 // CommandObjectBreakpointModify
788 #pragma mark Modify
789
790 class CommandObjectBreakpointModify : public CommandObjectParsed {
791 public:
CommandObjectBreakpointModify(CommandInterpreter & interpreter)792 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
793 : CommandObjectParsed(interpreter, "breakpoint modify",
794 "Modify the options on a breakpoint or set of "
795 "breakpoints in the executable. "
796 "If no breakpoint is specified, acts on the last "
797 "created breakpoint. "
798 "With the exception of -e, -d and -i, passing an "
799 "empty argument clears the modification.",
800 nullptr),
801 m_options() {
802 CommandArgumentEntry arg;
803 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
804 eArgTypeBreakpointIDRange);
805 // Add the entry for the first argument for this command to the object's
806 // arguments vector.
807 m_arguments.push_back(arg);
808
809 m_options.Append(&m_bp_opts,
810 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
811 LLDB_OPT_SET_ALL);
812 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
813 m_options.Finalize();
814 }
815
816 ~CommandObjectBreakpointModify() override = default;
817
818 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)819 HandleArgumentCompletion(CompletionRequest &request,
820 OptionElementVector &opt_element_vector) override {
821 CommandCompletions::InvokeCommonCompletionCallbacks(
822 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
823 request, nullptr);
824 }
825
GetOptions()826 Options *GetOptions() override { return &m_options; }
827
828 protected:
DoExecute(Args & command,CommandReturnObject & result)829 bool DoExecute(Args &command, CommandReturnObject &result) override {
830 Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
831
832 std::unique_lock<std::recursive_mutex> lock;
833 target.GetBreakpointList().GetListMutex(lock);
834
835 BreakpointIDList valid_bp_ids;
836
837 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
838 command, &target, result, &valid_bp_ids,
839 BreakpointName::Permissions::PermissionKinds::disablePerm);
840
841 if (result.Succeeded()) {
842 const size_t count = valid_bp_ids.GetSize();
843 for (size_t i = 0; i < count; ++i) {
844 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
845
846 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
847 Breakpoint *bp =
848 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
849 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
850 BreakpointLocation *location =
851 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
852 if (location)
853 location->GetLocationOptions().CopyOverSetOptions(
854 m_bp_opts.GetBreakpointOptions());
855 } else {
856 bp->GetOptions().CopyOverSetOptions(
857 m_bp_opts.GetBreakpointOptions());
858 }
859 }
860 }
861 }
862
863 return result.Succeeded();
864 }
865
866 private:
867 BreakpointOptionGroup m_bp_opts;
868 BreakpointDummyOptionGroup m_dummy_opts;
869 OptionGroupOptions m_options;
870 };
871
872 // CommandObjectBreakpointEnable
873 #pragma mark Enable
874
875 class CommandObjectBreakpointEnable : public CommandObjectParsed {
876 public:
CommandObjectBreakpointEnable(CommandInterpreter & interpreter)877 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
878 : CommandObjectParsed(interpreter, "enable",
879 "Enable the specified disabled breakpoint(s). If "
880 "no breakpoints are specified, enable all of them.",
881 nullptr) {
882 CommandArgumentEntry arg;
883 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
884 eArgTypeBreakpointIDRange);
885 // Add the entry for the first argument for this command to the object's
886 // arguments vector.
887 m_arguments.push_back(arg);
888 }
889
890 ~CommandObjectBreakpointEnable() override = default;
891
892 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)893 HandleArgumentCompletion(CompletionRequest &request,
894 OptionElementVector &opt_element_vector) override {
895 CommandCompletions::InvokeCommonCompletionCallbacks(
896 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
897 request, nullptr);
898 }
899
900 protected:
DoExecute(Args & command,CommandReturnObject & result)901 bool DoExecute(Args &command, CommandReturnObject &result) override {
902 Target &target = GetSelectedOrDummyTarget();
903
904 std::unique_lock<std::recursive_mutex> lock;
905 target.GetBreakpointList().GetListMutex(lock);
906
907 const BreakpointList &breakpoints = target.GetBreakpointList();
908
909 size_t num_breakpoints = breakpoints.GetSize();
910
911 if (num_breakpoints == 0) {
912 result.AppendError("No breakpoints exist to be enabled.");
913 return false;
914 }
915
916 if (command.empty()) {
917 // No breakpoint selected; enable all currently set breakpoints.
918 target.EnableAllowedBreakpoints();
919 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
920 " breakpoints)\n",
921 (uint64_t)num_breakpoints);
922 result.SetStatus(eReturnStatusSuccessFinishNoResult);
923 } else {
924 // Particular breakpoint selected; enable that breakpoint.
925 BreakpointIDList valid_bp_ids;
926 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
927 command, &target, result, &valid_bp_ids,
928 BreakpointName::Permissions::PermissionKinds::disablePerm);
929
930 if (result.Succeeded()) {
931 int enable_count = 0;
932 int loc_count = 0;
933 const size_t count = valid_bp_ids.GetSize();
934 for (size_t i = 0; i < count; ++i) {
935 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
936
937 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
938 Breakpoint *breakpoint =
939 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
940 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
941 BreakpointLocation *location =
942 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
943 if (location) {
944 location->SetEnabled(true);
945 ++loc_count;
946 }
947 } else {
948 breakpoint->SetEnabled(true);
949 ++enable_count;
950 }
951 }
952 }
953 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
954 enable_count + loc_count);
955 result.SetStatus(eReturnStatusSuccessFinishNoResult);
956 }
957 }
958
959 return result.Succeeded();
960 }
961 };
962
963 // CommandObjectBreakpointDisable
964 #pragma mark Disable
965
966 class CommandObjectBreakpointDisable : public CommandObjectParsed {
967 public:
CommandObjectBreakpointDisable(CommandInterpreter & interpreter)968 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
969 : CommandObjectParsed(
970 interpreter, "breakpoint disable",
971 "Disable the specified breakpoint(s) without deleting "
972 "them. If none are specified, disable all "
973 "breakpoints.",
974 nullptr) {
975 SetHelpLong(
976 "Disable the specified breakpoint(s) without deleting them. \
977 If none are specified, disable all breakpoints."
978 R"(
979
980 )"
981 "Note: disabling a breakpoint will cause none of its locations to be hit \
982 regardless of whether individual locations are enabled or disabled. After the sequence:"
983 R"(
984
985 (lldb) break disable 1
986 (lldb) break enable 1.1
987
988 execution will NOT stop at location 1.1. To achieve that, type:
989
990 (lldb) break disable 1.*
991 (lldb) break enable 1.1
992
993 )"
994 "The first command disables all locations for breakpoint 1, \
995 the second re-enables the first location.");
996
997 CommandArgumentEntry arg;
998 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
999 eArgTypeBreakpointIDRange);
1000 // Add the entry for the first argument for this command to the object's
1001 // arguments vector.
1002 m_arguments.push_back(arg);
1003 }
1004
1005 ~CommandObjectBreakpointDisable() override = default;
1006
1007 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1008 HandleArgumentCompletion(CompletionRequest &request,
1009 OptionElementVector &opt_element_vector) override {
1010 CommandCompletions::InvokeCommonCompletionCallbacks(
1011 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1012 request, nullptr);
1013 }
1014
1015 protected:
DoExecute(Args & command,CommandReturnObject & result)1016 bool DoExecute(Args &command, CommandReturnObject &result) override {
1017 Target &target = GetSelectedOrDummyTarget();
1018 std::unique_lock<std::recursive_mutex> lock;
1019 target.GetBreakpointList().GetListMutex(lock);
1020
1021 const BreakpointList &breakpoints = target.GetBreakpointList();
1022 size_t num_breakpoints = breakpoints.GetSize();
1023
1024 if (num_breakpoints == 0) {
1025 result.AppendError("No breakpoints exist to be disabled.");
1026 return false;
1027 }
1028
1029 if (command.empty()) {
1030 // No breakpoint selected; disable all currently set breakpoints.
1031 target.DisableAllowedBreakpoints();
1032 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1033 " breakpoints)\n",
1034 (uint64_t)num_breakpoints);
1035 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1036 } else {
1037 // Particular breakpoint selected; disable that breakpoint.
1038 BreakpointIDList valid_bp_ids;
1039
1040 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1041 command, &target, result, &valid_bp_ids,
1042 BreakpointName::Permissions::PermissionKinds::disablePerm);
1043
1044 if (result.Succeeded()) {
1045 int disable_count = 0;
1046 int loc_count = 0;
1047 const size_t count = valid_bp_ids.GetSize();
1048 for (size_t i = 0; i < count; ++i) {
1049 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1050
1051 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1052 Breakpoint *breakpoint =
1053 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1054 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1055 BreakpointLocation *location =
1056 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1057 if (location) {
1058 location->SetEnabled(false);
1059 ++loc_count;
1060 }
1061 } else {
1062 breakpoint->SetEnabled(false);
1063 ++disable_count;
1064 }
1065 }
1066 }
1067 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1068 disable_count + loc_count);
1069 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1070 }
1071 }
1072
1073 return result.Succeeded();
1074 }
1075 };
1076
1077 // CommandObjectBreakpointList
1078
1079 #pragma mark List::CommandOptions
1080 #define LLDB_OPTIONS_breakpoint_list
1081 #include "CommandOptions.inc"
1082
1083 #pragma mark List
1084
1085 class CommandObjectBreakpointList : public CommandObjectParsed {
1086 public:
CommandObjectBreakpointList(CommandInterpreter & interpreter)1087 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1088 : CommandObjectParsed(
1089 interpreter, "breakpoint list",
1090 "List some or all breakpoints at configurable levels of detail.",
1091 nullptr),
1092 m_options() {
1093 CommandArgumentEntry arg;
1094 CommandArgumentData bp_id_arg;
1095
1096 // Define the first (and only) variant of this arg.
1097 bp_id_arg.arg_type = eArgTypeBreakpointID;
1098 bp_id_arg.arg_repetition = eArgRepeatOptional;
1099
1100 // There is only one variant this argument could be; put it into the
1101 // argument entry.
1102 arg.push_back(bp_id_arg);
1103
1104 // Push the data for the first argument into the m_arguments vector.
1105 m_arguments.push_back(arg);
1106 }
1107
1108 ~CommandObjectBreakpointList() override = default;
1109
GetOptions()1110 Options *GetOptions() override { return &m_options; }
1111
1112 class CommandOptions : public Options {
1113 public:
CommandOptions()1114 CommandOptions() : Options() {}
1115
1116 ~CommandOptions() override = default;
1117
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1118 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1119 ExecutionContext *execution_context) override {
1120 Status error;
1121 const int short_option = m_getopt_table[option_idx].val;
1122
1123 switch (short_option) {
1124 case 'b':
1125 m_level = lldb::eDescriptionLevelBrief;
1126 break;
1127 case 'D':
1128 m_use_dummy = true;
1129 break;
1130 case 'f':
1131 m_level = lldb::eDescriptionLevelFull;
1132 break;
1133 case 'v':
1134 m_level = lldb::eDescriptionLevelVerbose;
1135 break;
1136 case 'i':
1137 m_internal = true;
1138 break;
1139 default:
1140 llvm_unreachable("Unimplemented option");
1141 }
1142
1143 return error;
1144 }
1145
OptionParsingStarting(ExecutionContext * execution_context)1146 void OptionParsingStarting(ExecutionContext *execution_context) override {
1147 m_level = lldb::eDescriptionLevelFull;
1148 m_internal = false;
1149 m_use_dummy = false;
1150 }
1151
GetDefinitions()1152 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1153 return llvm::makeArrayRef(g_breakpoint_list_options);
1154 }
1155
1156 // Instance variables to hold the values for command options.
1157
1158 lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
1159
1160 bool m_internal;
1161 bool m_use_dummy = false;
1162 };
1163
1164 protected:
DoExecute(Args & command,CommandReturnObject & result)1165 bool DoExecute(Args &command, CommandReturnObject &result) override {
1166 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1167
1168 const BreakpointList &breakpoints =
1169 target.GetBreakpointList(m_options.m_internal);
1170 std::unique_lock<std::recursive_mutex> lock;
1171 target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1172
1173 size_t num_breakpoints = breakpoints.GetSize();
1174
1175 if (num_breakpoints == 0) {
1176 result.AppendMessage("No breakpoints currently set.");
1177 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1178 return true;
1179 }
1180
1181 Stream &output_stream = result.GetOutputStream();
1182
1183 if (command.empty()) {
1184 // No breakpoint selected; show info about all currently set breakpoints.
1185 result.AppendMessage("Current breakpoints:");
1186 for (size_t i = 0; i < num_breakpoints; ++i) {
1187 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1188 if (breakpoint->AllowList())
1189 AddBreakpointDescription(&output_stream, breakpoint,
1190 m_options.m_level);
1191 }
1192 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1193 } else {
1194 // Particular breakpoints selected; show info about that breakpoint.
1195 BreakpointIDList valid_bp_ids;
1196 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1197 command, &target, result, &valid_bp_ids,
1198 BreakpointName::Permissions::PermissionKinds::listPerm);
1199
1200 if (result.Succeeded()) {
1201 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1202 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1203 Breakpoint *breakpoint =
1204 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1205 AddBreakpointDescription(&output_stream, breakpoint,
1206 m_options.m_level);
1207 }
1208 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1209 } else {
1210 result.AppendError("Invalid breakpoint ID.");
1211 }
1212 }
1213
1214 return result.Succeeded();
1215 }
1216
1217 private:
1218 CommandOptions m_options;
1219 };
1220
1221 // CommandObjectBreakpointClear
1222 #pragma mark Clear::CommandOptions
1223
1224 #define LLDB_OPTIONS_breakpoint_clear
1225 #include "CommandOptions.inc"
1226
1227 #pragma mark Clear
1228
1229 class CommandObjectBreakpointClear : public CommandObjectParsed {
1230 public:
1231 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1232
CommandObjectBreakpointClear(CommandInterpreter & interpreter)1233 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1234 : CommandObjectParsed(interpreter, "breakpoint clear",
1235 "Delete or disable breakpoints matching the "
1236 "specified source file and line.",
1237 "breakpoint clear <cmd-options>"),
1238 m_options() {}
1239
1240 ~CommandObjectBreakpointClear() override = default;
1241
GetOptions()1242 Options *GetOptions() override { return &m_options; }
1243
1244 class CommandOptions : public Options {
1245 public:
CommandOptions()1246 CommandOptions() : Options(), m_filename() {}
1247
1248 ~CommandOptions() override = default;
1249
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1250 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1251 ExecutionContext *execution_context) override {
1252 Status error;
1253 const int short_option = m_getopt_table[option_idx].val;
1254
1255 switch (short_option) {
1256 case 'f':
1257 m_filename.assign(std::string(option_arg));
1258 break;
1259
1260 case 'l':
1261 option_arg.getAsInteger(0, m_line_num);
1262 break;
1263
1264 default:
1265 llvm_unreachable("Unimplemented option");
1266 }
1267
1268 return error;
1269 }
1270
OptionParsingStarting(ExecutionContext * execution_context)1271 void OptionParsingStarting(ExecutionContext *execution_context) override {
1272 m_filename.clear();
1273 m_line_num = 0;
1274 }
1275
GetDefinitions()1276 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1277 return llvm::makeArrayRef(g_breakpoint_clear_options);
1278 }
1279
1280 // Instance variables to hold the values for command options.
1281
1282 std::string m_filename;
1283 uint32_t m_line_num = 0;
1284 };
1285
1286 protected:
DoExecute(Args & command,CommandReturnObject & result)1287 bool DoExecute(Args &command, CommandReturnObject &result) override {
1288 Target &target = GetSelectedOrDummyTarget();
1289
1290 // The following are the various types of breakpoints that could be
1291 // cleared:
1292 // 1). -f -l (clearing breakpoint by source location)
1293
1294 BreakpointClearType break_type = eClearTypeInvalid;
1295
1296 if (m_options.m_line_num != 0)
1297 break_type = eClearTypeFileAndLine;
1298
1299 std::unique_lock<std::recursive_mutex> lock;
1300 target.GetBreakpointList().GetListMutex(lock);
1301
1302 BreakpointList &breakpoints = target.GetBreakpointList();
1303 size_t num_breakpoints = breakpoints.GetSize();
1304
1305 // Early return if there's no breakpoint at all.
1306 if (num_breakpoints == 0) {
1307 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1308 return result.Succeeded();
1309 }
1310
1311 // Find matching breakpoints and delete them.
1312
1313 // First create a copy of all the IDs.
1314 std::vector<break_id_t> BreakIDs;
1315 for (size_t i = 0; i < num_breakpoints; ++i)
1316 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1317
1318 int num_cleared = 0;
1319 StreamString ss;
1320 switch (break_type) {
1321 case eClearTypeFileAndLine: // Breakpoint by source position
1322 {
1323 const ConstString filename(m_options.m_filename.c_str());
1324 BreakpointLocationCollection loc_coll;
1325
1326 for (size_t i = 0; i < num_breakpoints; ++i) {
1327 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1328
1329 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1330 // If the collection size is 0, it's a full match and we can just
1331 // remove the breakpoint.
1332 if (loc_coll.GetSize() == 0) {
1333 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1334 ss.EOL();
1335 target.RemoveBreakpointByID(bp->GetID());
1336 ++num_cleared;
1337 }
1338 }
1339 }
1340 } break;
1341
1342 default:
1343 break;
1344 }
1345
1346 if (num_cleared > 0) {
1347 Stream &output_stream = result.GetOutputStream();
1348 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1349 output_stream << ss.GetString();
1350 output_stream.EOL();
1351 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1352 } else {
1353 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1354 }
1355
1356 return result.Succeeded();
1357 }
1358
1359 private:
1360 CommandOptions m_options;
1361 };
1362
1363 // CommandObjectBreakpointDelete
1364 #define LLDB_OPTIONS_breakpoint_delete
1365 #include "CommandOptions.inc"
1366
1367 #pragma mark Delete
1368
1369 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1370 public:
CommandObjectBreakpointDelete(CommandInterpreter & interpreter)1371 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1372 : CommandObjectParsed(interpreter, "breakpoint delete",
1373 "Delete the specified breakpoint(s). If no "
1374 "breakpoints are specified, delete them all.",
1375 nullptr),
1376 m_options() {
1377 CommandArgumentEntry arg;
1378 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1379 eArgTypeBreakpointIDRange);
1380 // Add the entry for the first argument for this command to the object's
1381 // arguments vector.
1382 m_arguments.push_back(arg);
1383 }
1384
1385 ~CommandObjectBreakpointDelete() override = default;
1386
1387 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1388 HandleArgumentCompletion(CompletionRequest &request,
1389 OptionElementVector &opt_element_vector) override {
1390 CommandCompletions::InvokeCommonCompletionCallbacks(
1391 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1392 request, nullptr);
1393 }
1394
GetOptions()1395 Options *GetOptions() override { return &m_options; }
1396
1397 class CommandOptions : public Options {
1398 public:
CommandOptions()1399 CommandOptions() : Options() {}
1400
1401 ~CommandOptions() override = default;
1402
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1403 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1404 ExecutionContext *execution_context) override {
1405 Status error;
1406 const int short_option = m_getopt_table[option_idx].val;
1407
1408 switch (short_option) {
1409 case 'f':
1410 m_force = true;
1411 break;
1412
1413 case 'D':
1414 m_use_dummy = true;
1415 break;
1416
1417 case 'd':
1418 m_delete_disabled = true;
1419 break;
1420
1421 default:
1422 llvm_unreachable("Unimplemented option");
1423 }
1424
1425 return error;
1426 }
1427
OptionParsingStarting(ExecutionContext * execution_context)1428 void OptionParsingStarting(ExecutionContext *execution_context) override {
1429 m_use_dummy = false;
1430 m_force = false;
1431 m_delete_disabled = false;
1432 }
1433
GetDefinitions()1434 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1435 return llvm::makeArrayRef(g_breakpoint_delete_options);
1436 }
1437
1438 // Instance variables to hold the values for command options.
1439 bool m_use_dummy = false;
1440 bool m_force = false;
1441 bool m_delete_disabled = false;
1442 };
1443
1444 protected:
DoExecute(Args & command,CommandReturnObject & result)1445 bool DoExecute(Args &command, CommandReturnObject &result) override {
1446 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1447 result.Clear();
1448
1449 std::unique_lock<std::recursive_mutex> lock;
1450 target.GetBreakpointList().GetListMutex(lock);
1451
1452 BreakpointList &breakpoints = target.GetBreakpointList();
1453
1454 size_t num_breakpoints = breakpoints.GetSize();
1455
1456 if (num_breakpoints == 0) {
1457 result.AppendError("No breakpoints exist to be deleted.");
1458 return false;
1459 }
1460
1461 // Handle the delete all breakpoints case:
1462 if (command.empty() && !m_options.m_delete_disabled) {
1463 if (!m_options.m_force &&
1464 !m_interpreter.Confirm(
1465 "About to delete all breakpoints, do you want to do that?",
1466 true)) {
1467 result.AppendMessage("Operation cancelled...");
1468 } else {
1469 target.RemoveAllowedBreakpoints();
1470 result.AppendMessageWithFormat(
1471 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1472 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1473 }
1474 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1475 return result.Succeeded();
1476 }
1477
1478 // Either we have some kind of breakpoint specification(s),
1479 // or we are handling "break disable --deleted". Gather the list
1480 // of breakpoints to delete here, the we'll delete them below.
1481 BreakpointIDList valid_bp_ids;
1482
1483 if (m_options.m_delete_disabled) {
1484 BreakpointIDList excluded_bp_ids;
1485
1486 if (!command.empty()) {
1487 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1488 command, &target, result, &excluded_bp_ids,
1489 BreakpointName::Permissions::PermissionKinds::deletePerm);
1490 if (!result.Succeeded())
1491 return false;
1492 }
1493
1494 for (auto breakpoint_sp : breakpoints.Breakpoints()) {
1495 if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
1496 BreakpointID bp_id(breakpoint_sp->GetID());
1497 size_t pos = 0;
1498 if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
1499 valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
1500 }
1501 }
1502 if (valid_bp_ids.GetSize() == 0) {
1503 result.AppendError("No disabled breakpoints.");
1504 return false;
1505 }
1506 } else {
1507 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1508 command, &target, result, &valid_bp_ids,
1509 BreakpointName::Permissions::PermissionKinds::deletePerm);
1510 if (!result.Succeeded())
1511 return false;
1512 }
1513
1514 int delete_count = 0;
1515 int disable_count = 0;
1516 const size_t count = valid_bp_ids.GetSize();
1517 for (size_t i = 0; i < count; ++i) {
1518 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1519
1520 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1521 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1522 Breakpoint *breakpoint =
1523 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1524 BreakpointLocation *location =
1525 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1526 // It makes no sense to try to delete individual locations, so we
1527 // disable them instead.
1528 if (location) {
1529 location->SetEnabled(false);
1530 ++disable_count;
1531 }
1532 } else {
1533 target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1534 ++delete_count;
1535 }
1536 }
1537 }
1538 result.AppendMessageWithFormat(
1539 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1540 delete_count, disable_count);
1541 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1542 return result.Succeeded();
1543 }
1544
1545 private:
1546 CommandOptions m_options;
1547 };
1548
1549 // CommandObjectBreakpointName
1550 #define LLDB_OPTIONS_breakpoint_name
1551 #include "CommandOptions.inc"
1552
1553 class BreakpointNameOptionGroup : public OptionGroup {
1554 public:
BreakpointNameOptionGroup()1555 BreakpointNameOptionGroup()
1556 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1557 }
1558
1559 ~BreakpointNameOptionGroup() override = default;
1560
GetDefinitions()1561 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1562 return llvm::makeArrayRef(g_breakpoint_name_options);
1563 }
1564
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1565 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1566 ExecutionContext *execution_context) override {
1567 Status error;
1568 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1569
1570 switch (short_option) {
1571 case 'N':
1572 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1573 error.Success())
1574 m_name.SetValueFromString(option_arg);
1575 break;
1576 case 'B':
1577 if (m_breakpoint.SetValueFromString(option_arg).Fail())
1578 error.SetErrorStringWithFormat(
1579 "unrecognized value \"%s\" for breakpoint",
1580 option_arg.str().c_str());
1581 break;
1582 case 'D':
1583 if (m_use_dummy.SetValueFromString(option_arg).Fail())
1584 error.SetErrorStringWithFormat(
1585 "unrecognized value \"%s\" for use-dummy",
1586 option_arg.str().c_str());
1587 break;
1588 case 'H':
1589 m_help_string.SetValueFromString(option_arg);
1590 break;
1591
1592 default:
1593 llvm_unreachable("Unimplemented option");
1594 }
1595 return error;
1596 }
1597
OptionParsingStarting(ExecutionContext * execution_context)1598 void OptionParsingStarting(ExecutionContext *execution_context) override {
1599 m_name.Clear();
1600 m_breakpoint.Clear();
1601 m_use_dummy.Clear();
1602 m_use_dummy.SetDefaultValue(false);
1603 m_help_string.Clear();
1604 }
1605
1606 OptionValueString m_name;
1607 OptionValueUInt64 m_breakpoint;
1608 OptionValueBoolean m_use_dummy;
1609 OptionValueString m_help_string;
1610 };
1611
1612 #define LLDB_OPTIONS_breakpoint_access
1613 #include "CommandOptions.inc"
1614
1615 class BreakpointAccessOptionGroup : public OptionGroup {
1616 public:
BreakpointAccessOptionGroup()1617 BreakpointAccessOptionGroup() : OptionGroup() {}
1618
1619 ~BreakpointAccessOptionGroup() override = default;
1620
GetDefinitions()1621 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1622 return llvm::makeArrayRef(g_breakpoint_access_options);
1623 }
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1624 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1625 ExecutionContext *execution_context) override {
1626 Status error;
1627 const int short_option =
1628 g_breakpoint_access_options[option_idx].short_option;
1629
1630 switch (short_option) {
1631 case 'L': {
1632 bool value, success;
1633 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1634 if (success) {
1635 m_permissions.SetAllowList(value);
1636 } else
1637 error.SetErrorStringWithFormat(
1638 "invalid boolean value '%s' passed for -L option",
1639 option_arg.str().c_str());
1640 } break;
1641 case 'A': {
1642 bool value, success;
1643 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1644 if (success) {
1645 m_permissions.SetAllowDisable(value);
1646 } else
1647 error.SetErrorStringWithFormat(
1648 "invalid boolean value '%s' passed for -L option",
1649 option_arg.str().c_str());
1650 } break;
1651 case 'D': {
1652 bool value, success;
1653 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1654 if (success) {
1655 m_permissions.SetAllowDelete(value);
1656 } else
1657 error.SetErrorStringWithFormat(
1658 "invalid boolean value '%s' passed for -L option",
1659 option_arg.str().c_str());
1660 } break;
1661 default:
1662 llvm_unreachable("Unimplemented option");
1663 }
1664
1665 return error;
1666 }
1667
OptionParsingStarting(ExecutionContext * execution_context)1668 void OptionParsingStarting(ExecutionContext *execution_context) override {}
1669
GetPermissions() const1670 const BreakpointName::Permissions &GetPermissions() const {
1671 return m_permissions;
1672 }
1673 BreakpointName::Permissions m_permissions;
1674 };
1675
1676 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1677 public:
CommandObjectBreakpointNameConfigure(CommandInterpreter & interpreter)1678 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1679 : CommandObjectParsed(
1680 interpreter, "configure",
1681 "Configure the options for the breakpoint"
1682 " name provided. "
1683 "If you provide a breakpoint id, the options will be copied from "
1684 "the breakpoint, otherwise only the options specified will be set "
1685 "on the name.",
1686 "breakpoint name configure <command-options> "
1687 "<breakpoint-name-list>"),
1688 m_bp_opts(), m_option_group() {
1689 // Create the first variant for the first (and only) argument for this
1690 // command.
1691 CommandArgumentEntry arg1;
1692 CommandArgumentData id_arg;
1693 id_arg.arg_type = eArgTypeBreakpointName;
1694 id_arg.arg_repetition = eArgRepeatOptional;
1695 arg1.push_back(id_arg);
1696 m_arguments.push_back(arg1);
1697
1698 m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1699 m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1700 LLDB_OPT_SET_ALL);
1701 m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1702 LLDB_OPT_SET_ALL);
1703 m_option_group.Finalize();
1704 }
1705
1706 ~CommandObjectBreakpointNameConfigure() override = default;
1707
GetOptions()1708 Options *GetOptions() override { return &m_option_group; }
1709
1710 protected:
DoExecute(Args & command,CommandReturnObject & result)1711 bool DoExecute(Args &command, CommandReturnObject &result) override {
1712
1713 const size_t argc = command.GetArgumentCount();
1714 if (argc == 0) {
1715 result.AppendError("No names provided.");
1716 return false;
1717 }
1718
1719 Target &target = GetSelectedOrDummyTarget(false);
1720
1721 std::unique_lock<std::recursive_mutex> lock;
1722 target.GetBreakpointList().GetListMutex(lock);
1723
1724 // Make a pass through first to see that all the names are legal.
1725 for (auto &entry : command.entries()) {
1726 Status error;
1727 if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1728 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1729 entry.c_str(), error.AsCString());
1730 return false;
1731 }
1732 }
1733 // Now configure them, we already pre-checked the names so we don't need to
1734 // check the error:
1735 BreakpointSP bp_sp;
1736 if (m_bp_id.m_breakpoint.OptionWasSet()) {
1737 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1738 bp_sp = target.GetBreakpointByID(bp_id);
1739 if (!bp_sp) {
1740 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1741 bp_id);
1742 return false;
1743 }
1744 }
1745
1746 Status error;
1747 for (auto &entry : command.entries()) {
1748 ConstString name(entry.c_str());
1749 BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1750 if (!bp_name)
1751 continue;
1752 if (m_bp_id.m_help_string.OptionWasSet())
1753 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1754
1755 if (bp_sp)
1756 target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1757 m_access_options.GetPermissions());
1758 else
1759 target.ConfigureBreakpointName(*bp_name,
1760 m_bp_opts.GetBreakpointOptions(),
1761 m_access_options.GetPermissions());
1762 }
1763 return true;
1764 }
1765
1766 private:
1767 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1768 BreakpointOptionGroup m_bp_opts;
1769 BreakpointAccessOptionGroup m_access_options;
1770 OptionGroupOptions m_option_group;
1771 };
1772
1773 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1774 public:
CommandObjectBreakpointNameAdd(CommandInterpreter & interpreter)1775 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1776 : CommandObjectParsed(
1777 interpreter, "add", "Add a name to the breakpoints provided.",
1778 "breakpoint name add <command-options> <breakpoint-id-list>"),
1779 m_name_options(), m_option_group() {
1780 // Create the first variant for the first (and only) argument for this
1781 // command.
1782 CommandArgumentEntry arg1;
1783 CommandArgumentData id_arg;
1784 id_arg.arg_type = eArgTypeBreakpointID;
1785 id_arg.arg_repetition = eArgRepeatOptional;
1786 arg1.push_back(id_arg);
1787 m_arguments.push_back(arg1);
1788
1789 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1790 m_option_group.Finalize();
1791 }
1792
1793 ~CommandObjectBreakpointNameAdd() override = default;
1794
1795 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1796 HandleArgumentCompletion(CompletionRequest &request,
1797 OptionElementVector &opt_element_vector) override {
1798 CommandCompletions::InvokeCommonCompletionCallbacks(
1799 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1800 request, nullptr);
1801 }
1802
GetOptions()1803 Options *GetOptions() override { return &m_option_group; }
1804
1805 protected:
DoExecute(Args & command,CommandReturnObject & result)1806 bool DoExecute(Args &command, CommandReturnObject &result) override {
1807 if (!m_name_options.m_name.OptionWasSet()) {
1808 result.AppendError("No name option provided.");
1809 return false;
1810 }
1811
1812 Target &target =
1813 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1814
1815 std::unique_lock<std::recursive_mutex> lock;
1816 target.GetBreakpointList().GetListMutex(lock);
1817
1818 const BreakpointList &breakpoints = target.GetBreakpointList();
1819
1820 size_t num_breakpoints = breakpoints.GetSize();
1821 if (num_breakpoints == 0) {
1822 result.AppendError("No breakpoints, cannot add names.");
1823 return false;
1824 }
1825
1826 // Particular breakpoint selected; disable that breakpoint.
1827 BreakpointIDList valid_bp_ids;
1828 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1829 command, &target, result, &valid_bp_ids,
1830 BreakpointName::Permissions::PermissionKinds::listPerm);
1831
1832 if (result.Succeeded()) {
1833 if (valid_bp_ids.GetSize() == 0) {
1834 result.AppendError("No breakpoints specified, cannot add names.");
1835 return false;
1836 }
1837 size_t num_valid_ids = valid_bp_ids.GetSize();
1838 const char *bp_name = m_name_options.m_name.GetCurrentValue();
1839 Status error; // This error reports illegal names, but we've already
1840 // checked that, so we don't need to check it again here.
1841 for (size_t index = 0; index < num_valid_ids; index++) {
1842 lldb::break_id_t bp_id =
1843 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1844 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1845 target.AddNameToBreakpoint(bp_sp, bp_name, error);
1846 }
1847 }
1848
1849 return true;
1850 }
1851
1852 private:
1853 BreakpointNameOptionGroup m_name_options;
1854 OptionGroupOptions m_option_group;
1855 };
1856
1857 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1858 public:
CommandObjectBreakpointNameDelete(CommandInterpreter & interpreter)1859 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1860 : CommandObjectParsed(
1861 interpreter, "delete",
1862 "Delete a name from the breakpoints provided.",
1863 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1864 m_name_options(), m_option_group() {
1865 // Create the first variant for the first (and only) argument for this
1866 // command.
1867 CommandArgumentEntry arg1;
1868 CommandArgumentData id_arg;
1869 id_arg.arg_type = eArgTypeBreakpointID;
1870 id_arg.arg_repetition = eArgRepeatOptional;
1871 arg1.push_back(id_arg);
1872 m_arguments.push_back(arg1);
1873
1874 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1875 m_option_group.Finalize();
1876 }
1877
1878 ~CommandObjectBreakpointNameDelete() override = default;
1879
1880 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1881 HandleArgumentCompletion(CompletionRequest &request,
1882 OptionElementVector &opt_element_vector) override {
1883 CommandCompletions::InvokeCommonCompletionCallbacks(
1884 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1885 request, nullptr);
1886 }
1887
GetOptions()1888 Options *GetOptions() override { return &m_option_group; }
1889
1890 protected:
DoExecute(Args & command,CommandReturnObject & result)1891 bool DoExecute(Args &command, CommandReturnObject &result) override {
1892 if (!m_name_options.m_name.OptionWasSet()) {
1893 result.AppendError("No name option provided.");
1894 return false;
1895 }
1896
1897 Target &target =
1898 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1899
1900 std::unique_lock<std::recursive_mutex> lock;
1901 target.GetBreakpointList().GetListMutex(lock);
1902
1903 const BreakpointList &breakpoints = target.GetBreakpointList();
1904
1905 size_t num_breakpoints = breakpoints.GetSize();
1906 if (num_breakpoints == 0) {
1907 result.AppendError("No breakpoints, cannot delete names.");
1908 return false;
1909 }
1910
1911 // Particular breakpoint selected; disable that breakpoint.
1912 BreakpointIDList valid_bp_ids;
1913 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1914 command, &target, result, &valid_bp_ids,
1915 BreakpointName::Permissions::PermissionKinds::deletePerm);
1916
1917 if (result.Succeeded()) {
1918 if (valid_bp_ids.GetSize() == 0) {
1919 result.AppendError("No breakpoints specified, cannot delete names.");
1920 return false;
1921 }
1922 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
1923 size_t num_valid_ids = valid_bp_ids.GetSize();
1924 for (size_t index = 0; index < num_valid_ids; index++) {
1925 lldb::break_id_t bp_id =
1926 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1927 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1928 target.RemoveNameFromBreakpoint(bp_sp, bp_name);
1929 }
1930 }
1931
1932 return true;
1933 }
1934
1935 private:
1936 BreakpointNameOptionGroup m_name_options;
1937 OptionGroupOptions m_option_group;
1938 };
1939
1940 class CommandObjectBreakpointNameList : public CommandObjectParsed {
1941 public:
CommandObjectBreakpointNameList(CommandInterpreter & interpreter)1942 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1943 : CommandObjectParsed(interpreter, "list",
1944 "List either the names for a breakpoint or info "
1945 "about a given name. With no arguments, lists all "
1946 "names",
1947 "breakpoint name list <command-options>"),
1948 m_name_options(), m_option_group() {
1949 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
1950 m_option_group.Finalize();
1951 }
1952
1953 ~CommandObjectBreakpointNameList() override = default;
1954
GetOptions()1955 Options *GetOptions() override { return &m_option_group; }
1956
1957 protected:
DoExecute(Args & command,CommandReturnObject & result)1958 bool DoExecute(Args &command, CommandReturnObject &result) override {
1959 Target &target =
1960 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1961
1962 std::vector<std::string> name_list;
1963 if (command.empty()) {
1964 target.GetBreakpointNames(name_list);
1965 } else {
1966 for (const Args::ArgEntry &arg : command) {
1967 name_list.push_back(arg.c_str());
1968 }
1969 }
1970
1971 if (name_list.empty()) {
1972 result.AppendMessage("No breakpoint names found.");
1973 } else {
1974 for (const std::string &name_str : name_list) {
1975 const char *name = name_str.c_str();
1976 // First print out the options for the name:
1977 Status error;
1978 BreakpointName *bp_name =
1979 target.FindBreakpointName(ConstString(name), false, error);
1980 if (bp_name) {
1981 StreamString s;
1982 result.AppendMessageWithFormat("Name: %s\n", name);
1983 if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1984 result.AppendMessage(s.GetString());
1985 }
1986
1987 std::unique_lock<std::recursive_mutex> lock;
1988 target.GetBreakpointList().GetListMutex(lock);
1989
1990 BreakpointList &breakpoints = target.GetBreakpointList();
1991 bool any_set = false;
1992 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1993 if (bp_sp->MatchesName(name)) {
1994 StreamString s;
1995 any_set = true;
1996 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1997 s.EOL();
1998 result.AppendMessage(s.GetString());
1999 }
2000 }
2001 if (!any_set)
2002 result.AppendMessage("No breakpoints using this name.");
2003 } else {
2004 result.AppendMessageWithFormat("Name: %s not found.\n", name);
2005 }
2006 }
2007 }
2008 return true;
2009 }
2010
2011 private:
2012 BreakpointNameOptionGroup m_name_options;
2013 OptionGroupOptions m_option_group;
2014 };
2015
2016 // CommandObjectBreakpointName
2017 class CommandObjectBreakpointName : public CommandObjectMultiword {
2018 public:
CommandObjectBreakpointName(CommandInterpreter & interpreter)2019 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2020 : CommandObjectMultiword(
2021 interpreter, "name", "Commands to manage name tags for breakpoints",
2022 "breakpoint name <subcommand> [<command-options>]") {
2023 CommandObjectSP add_command_object(
2024 new CommandObjectBreakpointNameAdd(interpreter));
2025 CommandObjectSP delete_command_object(
2026 new CommandObjectBreakpointNameDelete(interpreter));
2027 CommandObjectSP list_command_object(
2028 new CommandObjectBreakpointNameList(interpreter));
2029 CommandObjectSP configure_command_object(
2030 new CommandObjectBreakpointNameConfigure(interpreter));
2031
2032 LoadSubCommand("add", add_command_object);
2033 LoadSubCommand("delete", delete_command_object);
2034 LoadSubCommand("list", list_command_object);
2035 LoadSubCommand("configure", configure_command_object);
2036 }
2037
2038 ~CommandObjectBreakpointName() override = default;
2039 };
2040
2041 // CommandObjectBreakpointRead
2042 #pragma mark Read::CommandOptions
2043 #define LLDB_OPTIONS_breakpoint_read
2044 #include "CommandOptions.inc"
2045
2046 #pragma mark Read
2047
2048 class CommandObjectBreakpointRead : public CommandObjectParsed {
2049 public:
CommandObjectBreakpointRead(CommandInterpreter & interpreter)2050 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2051 : CommandObjectParsed(interpreter, "breakpoint read",
2052 "Read and set the breakpoints previously saved to "
2053 "a file with \"breakpoint write\". ",
2054 nullptr),
2055 m_options() {}
2056
2057 ~CommandObjectBreakpointRead() override = default;
2058
GetOptions()2059 Options *GetOptions() override { return &m_options; }
2060
2061 class CommandOptions : public Options {
2062 public:
CommandOptions()2063 CommandOptions() : Options() {}
2064
2065 ~CommandOptions() override = default;
2066
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2067 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2068 ExecutionContext *execution_context) override {
2069 Status error;
2070 const int short_option = m_getopt_table[option_idx].val;
2071
2072 switch (short_option) {
2073 case 'f':
2074 m_filename.assign(std::string(option_arg));
2075 break;
2076 case 'N': {
2077 Status name_error;
2078 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2079 name_error)) {
2080 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2081 name_error.AsCString());
2082 }
2083 m_names.push_back(std::string(option_arg));
2084 break;
2085 }
2086 default:
2087 llvm_unreachable("Unimplemented option");
2088 }
2089
2090 return error;
2091 }
2092
OptionParsingStarting(ExecutionContext * execution_context)2093 void OptionParsingStarting(ExecutionContext *execution_context) override {
2094 m_filename.clear();
2095 m_names.clear();
2096 }
2097
GetDefinitions()2098 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2099 return llvm::makeArrayRef(g_breakpoint_read_options);
2100 }
2101
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)2102 void HandleOptionArgumentCompletion(
2103 CompletionRequest &request, OptionElementVector &opt_element_vector,
2104 int opt_element_index, CommandInterpreter &interpreter) override {
2105 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2106 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2107
2108 switch (GetDefinitions()[opt_defs_index].short_option) {
2109 case 'f':
2110 CommandCompletions::InvokeCommonCompletionCallbacks(
2111 interpreter, CommandCompletions::eDiskFileCompletion, request,
2112 nullptr);
2113 break;
2114
2115 case 'N':
2116 llvm::Optional<FileSpec> file_spec;
2117 const llvm::StringRef dash_f("-f");
2118 for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2119 if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2120 file_spec.emplace(
2121 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2122 break;
2123 }
2124 }
2125 if (!file_spec)
2126 return;
2127
2128 FileSystem::Instance().Resolve(*file_spec);
2129 Status error;
2130 StructuredData::ObjectSP input_data_sp =
2131 StructuredData::ParseJSONFromFile(*file_spec, error);
2132 if (!error.Success())
2133 return;
2134
2135 StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2136 if (!bkpt_array)
2137 return;
2138
2139 const size_t num_bkpts = bkpt_array->GetSize();
2140 for (size_t i = 0; i < num_bkpts; i++) {
2141 StructuredData::ObjectSP bkpt_object_sp =
2142 bkpt_array->GetItemAtIndex(i);
2143 if (!bkpt_object_sp)
2144 return;
2145
2146 StructuredData::Dictionary *bkpt_dict =
2147 bkpt_object_sp->GetAsDictionary();
2148 if (!bkpt_dict)
2149 return;
2150
2151 StructuredData::ObjectSP bkpt_data_sp =
2152 bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2153 if (!bkpt_data_sp)
2154 return;
2155
2156 bkpt_dict = bkpt_data_sp->GetAsDictionary();
2157 if (!bkpt_dict)
2158 return;
2159
2160 StructuredData::Array *names_array;
2161
2162 if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2163 return;
2164
2165 size_t num_names = names_array->GetSize();
2166
2167 for (size_t i = 0; i < num_names; i++) {
2168 llvm::StringRef name;
2169 if (names_array->GetItemAtIndexAsString(i, name))
2170 request.TryCompleteCurrentArg(name);
2171 }
2172 }
2173 }
2174 }
2175
2176 std::string m_filename;
2177 std::vector<std::string> m_names;
2178 };
2179
2180 protected:
DoExecute(Args & command,CommandReturnObject & result)2181 bool DoExecute(Args &command, CommandReturnObject &result) override {
2182 Target &target = GetSelectedOrDummyTarget();
2183
2184 std::unique_lock<std::recursive_mutex> lock;
2185 target.GetBreakpointList().GetListMutex(lock);
2186
2187 FileSpec input_spec(m_options.m_filename);
2188 FileSystem::Instance().Resolve(input_spec);
2189 BreakpointIDList new_bps;
2190 Status error = target.CreateBreakpointsFromFile(input_spec,
2191 m_options.m_names, new_bps);
2192
2193 if (!error.Success()) {
2194 result.AppendError(error.AsCString());
2195 return false;
2196 }
2197
2198 Stream &output_stream = result.GetOutputStream();
2199
2200 size_t num_breakpoints = new_bps.GetSize();
2201 if (num_breakpoints == 0) {
2202 result.AppendMessage("No breakpoints added.");
2203 } else {
2204 // No breakpoint selected; show info about all currently set breakpoints.
2205 result.AppendMessage("New breakpoints:");
2206 for (size_t i = 0; i < num_breakpoints; ++i) {
2207 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2208 Breakpoint *bp = target.GetBreakpointList()
2209 .FindBreakpointByID(bp_id.GetBreakpointID())
2210 .get();
2211 if (bp)
2212 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2213 false);
2214 }
2215 }
2216 return result.Succeeded();
2217 }
2218
2219 private:
2220 CommandOptions m_options;
2221 };
2222
2223 // CommandObjectBreakpointWrite
2224 #pragma mark Write::CommandOptions
2225 #define LLDB_OPTIONS_breakpoint_write
2226 #include "CommandOptions.inc"
2227
2228 #pragma mark Write
2229 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2230 public:
CommandObjectBreakpointWrite(CommandInterpreter & interpreter)2231 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2232 : CommandObjectParsed(interpreter, "breakpoint write",
2233 "Write the breakpoints listed to a file that can "
2234 "be read in with \"breakpoint read\". "
2235 "If given no arguments, writes all breakpoints.",
2236 nullptr),
2237 m_options() {
2238 CommandArgumentEntry arg;
2239 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2240 eArgTypeBreakpointIDRange);
2241 // Add the entry for the first argument for this command to the object's
2242 // arguments vector.
2243 m_arguments.push_back(arg);
2244 }
2245
2246 ~CommandObjectBreakpointWrite() override = default;
2247
2248 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2249 HandleArgumentCompletion(CompletionRequest &request,
2250 OptionElementVector &opt_element_vector) override {
2251 CommandCompletions::InvokeCommonCompletionCallbacks(
2252 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2253 request, nullptr);
2254 }
2255
GetOptions()2256 Options *GetOptions() override { return &m_options; }
2257
2258 class CommandOptions : public Options {
2259 public:
CommandOptions()2260 CommandOptions() : Options() {}
2261
2262 ~CommandOptions() override = default;
2263
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2264 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2265 ExecutionContext *execution_context) override {
2266 Status error;
2267 const int short_option = m_getopt_table[option_idx].val;
2268
2269 switch (short_option) {
2270 case 'f':
2271 m_filename.assign(std::string(option_arg));
2272 break;
2273 case 'a':
2274 m_append = true;
2275 break;
2276 default:
2277 llvm_unreachable("Unimplemented option");
2278 }
2279
2280 return error;
2281 }
2282
OptionParsingStarting(ExecutionContext * execution_context)2283 void OptionParsingStarting(ExecutionContext *execution_context) override {
2284 m_filename.clear();
2285 m_append = false;
2286 }
2287
GetDefinitions()2288 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2289 return llvm::makeArrayRef(g_breakpoint_write_options);
2290 }
2291
2292 // Instance variables to hold the values for command options.
2293
2294 std::string m_filename;
2295 bool m_append = false;
2296 };
2297
2298 protected:
DoExecute(Args & command,CommandReturnObject & result)2299 bool DoExecute(Args &command, CommandReturnObject &result) override {
2300 Target &target = GetSelectedOrDummyTarget();
2301
2302 std::unique_lock<std::recursive_mutex> lock;
2303 target.GetBreakpointList().GetListMutex(lock);
2304
2305 BreakpointIDList valid_bp_ids;
2306 if (!command.empty()) {
2307 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2308 command, &target, result, &valid_bp_ids,
2309 BreakpointName::Permissions::PermissionKinds::listPerm);
2310
2311 if (!result.Succeeded()) {
2312 result.SetStatus(eReturnStatusFailed);
2313 return false;
2314 }
2315 }
2316 FileSpec file_spec(m_options.m_filename);
2317 FileSystem::Instance().Resolve(file_spec);
2318 Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2319 m_options.m_append);
2320 if (!error.Success()) {
2321 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2322 error.AsCString());
2323 }
2324 return result.Succeeded();
2325 }
2326
2327 private:
2328 CommandOptions m_options;
2329 };
2330
2331 // CommandObjectMultiwordBreakpoint
2332 #pragma mark MultiwordBreakpoint
2333
CommandObjectMultiwordBreakpoint(CommandInterpreter & interpreter)2334 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2335 CommandInterpreter &interpreter)
2336 : CommandObjectMultiword(
2337 interpreter, "breakpoint",
2338 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2339 "breakpoint <subcommand> [<command-options>]") {
2340 CommandObjectSP list_command_object(
2341 new CommandObjectBreakpointList(interpreter));
2342 CommandObjectSP enable_command_object(
2343 new CommandObjectBreakpointEnable(interpreter));
2344 CommandObjectSP disable_command_object(
2345 new CommandObjectBreakpointDisable(interpreter));
2346 CommandObjectSP clear_command_object(
2347 new CommandObjectBreakpointClear(interpreter));
2348 CommandObjectSP delete_command_object(
2349 new CommandObjectBreakpointDelete(interpreter));
2350 CommandObjectSP set_command_object(
2351 new CommandObjectBreakpointSet(interpreter));
2352 CommandObjectSP command_command_object(
2353 new CommandObjectBreakpointCommand(interpreter));
2354 CommandObjectSP modify_command_object(
2355 new CommandObjectBreakpointModify(interpreter));
2356 CommandObjectSP name_command_object(
2357 new CommandObjectBreakpointName(interpreter));
2358 CommandObjectSP write_command_object(
2359 new CommandObjectBreakpointWrite(interpreter));
2360 CommandObjectSP read_command_object(
2361 new CommandObjectBreakpointRead(interpreter));
2362
2363 list_command_object->SetCommandName("breakpoint list");
2364 enable_command_object->SetCommandName("breakpoint enable");
2365 disable_command_object->SetCommandName("breakpoint disable");
2366 clear_command_object->SetCommandName("breakpoint clear");
2367 delete_command_object->SetCommandName("breakpoint delete");
2368 set_command_object->SetCommandName("breakpoint set");
2369 command_command_object->SetCommandName("breakpoint command");
2370 modify_command_object->SetCommandName("breakpoint modify");
2371 name_command_object->SetCommandName("breakpoint name");
2372 write_command_object->SetCommandName("breakpoint write");
2373 read_command_object->SetCommandName("breakpoint read");
2374
2375 LoadSubCommand("list", list_command_object);
2376 LoadSubCommand("enable", enable_command_object);
2377 LoadSubCommand("disable", disable_command_object);
2378 LoadSubCommand("clear", clear_command_object);
2379 LoadSubCommand("delete", delete_command_object);
2380 LoadSubCommand("set", set_command_object);
2381 LoadSubCommand("command", command_command_object);
2382 LoadSubCommand("modify", modify_command_object);
2383 LoadSubCommand("name", name_command_object);
2384 LoadSubCommand("write", write_command_object);
2385 LoadSubCommand("read", read_command_object);
2386 }
2387
2388 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2389
VerifyIDs(Args & args,Target * target,bool allow_locations,CommandReturnObject & result,BreakpointIDList * valid_ids,BreakpointName::Permissions::PermissionKinds purpose)2390 void CommandObjectMultiwordBreakpoint::VerifyIDs(
2391 Args &args, Target *target, bool allow_locations,
2392 CommandReturnObject &result, BreakpointIDList *valid_ids,
2393 BreakpointName::Permissions ::PermissionKinds purpose) {
2394 // args can be strings representing 1). integers (for breakpoint ids)
2395 // 2). the full breakpoint & location
2396 // canonical representation
2397 // 3). the word "to" or a hyphen,
2398 // representing a range (in which case there
2399 // had *better* be an entry both before &
2400 // after of one of the first two types.
2401 // 4). A breakpoint name
2402 // If args is empty, we will use the last created breakpoint (if there is
2403 // one.)
2404
2405 Args temp_args;
2406
2407 if (args.empty()) {
2408 if (target->GetLastCreatedBreakpoint()) {
2409 valid_ids->AddBreakpointID(BreakpointID(
2410 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2411 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2412 } else {
2413 result.AppendError(
2414 "No breakpoint specified and no last created breakpoint.");
2415 }
2416 return;
2417 }
2418
2419 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2420 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2421 // id range strings over; instead generate a list of strings for all the
2422 // breakpoint ids in the range, and shove all of those breakpoint id strings
2423 // into TEMP_ARGS.
2424
2425 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2426 purpose, result, temp_args);
2427
2428 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2429 // BreakpointIDList:
2430
2431 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2432
2433 // At this point, all of the breakpoint ids that the user passed in have
2434 // been converted to breakpoint IDs and put into valid_ids.
2435
2436 if (result.Succeeded()) {
2437 // Now that we've converted everything from args into a list of breakpoint
2438 // ids, go through our tentative list of breakpoint id's and verify that
2439 // they correspond to valid/currently set breakpoints.
2440
2441 const size_t count = valid_ids->GetSize();
2442 for (size_t i = 0; i < count; ++i) {
2443 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2444 Breakpoint *breakpoint =
2445 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2446 if (breakpoint != nullptr) {
2447 const size_t num_locations = breakpoint->GetNumLocations();
2448 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2449 StreamString id_str;
2450 BreakpointID::GetCanonicalReference(
2451 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2452 i = valid_ids->GetSize() + 1;
2453 result.AppendErrorWithFormat(
2454 "'%s' is not a currently valid breakpoint/location id.\n",
2455 id_str.GetData());
2456 }
2457 } else {
2458 i = valid_ids->GetSize() + 1;
2459 result.AppendErrorWithFormat(
2460 "'%d' is not a currently valid breakpoint ID.\n",
2461 cur_bp_id.GetBreakpointID());
2462 }
2463 }
2464 }
2465 }
2466