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