blob: bab8ecbf0ab3992e10f6651cf0f8ea532cff8398 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000012#include <vector>
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014// Other libraries and framework includes
15// Project includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000016#include "CommandObjectBreakpoint.h"
17#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Breakpoint/Breakpoint.h"
19#include "lldb/Breakpoint/BreakpointIDList.h"
20#include "lldb/Breakpoint/BreakpointLocation.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000021#include "lldb/Core/RegularExpression.h"
22#include "lldb/Core/StreamString.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000023#include "lldb/Host/StringConvert.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000024#include "lldb/Interpreter/CommandCompletions.h"
25#include "lldb/Interpreter/CommandInterpreter.h"
26#include "lldb/Interpreter/CommandReturnObject.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000027#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000028#include "lldb/Interpreter/OptionValueString.h"
29#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000030#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000031#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000032#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000033#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000034#include "lldb/Target/Thread.h"
35#include "lldb/Target/ThreadSpec.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036
37using namespace lldb;
38using namespace lldb_private;
39
Kate Stoneb9c1b512016-09-06 20:57:50 +000040static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
41 lldb::DescriptionLevel level) {
42 s->IndentMore();
43 bp->GetDescription(s, level, true);
44 s->IndentLess();
45 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046}
47
48//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +000049// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050//-------------------------------------------------------------------------
51
Kate Stoneb9c1b512016-09-06 20:57:50 +000052class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +000053public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 typedef enum BreakpointSetType {
55 eSetTypeInvalid,
56 eSetTypeFileAndLine,
57 eSetTypeAddress,
58 eSetTypeFunctionName,
59 eSetTypeFunctionRegexp,
60 eSetTypeSourceRegexp,
61 eSetTypeException
62 } BreakpointSetType;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
65 : CommandObjectParsed(
66 interpreter, "breakpoint set",
67 "Sets a breakpoint or set of breakpoints in the executable.",
68 "breakpoint set <cmd-options>"),
69 m_options() {}
70
71 ~CommandObjectBreakpointSet() override = default;
72
73 Options *GetOptions() override { return &m_options; }
74
75 class CommandOptions : public Options {
76 public:
77 CommandOptions()
78 : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
79 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
80 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
81 m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
82 m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(),
83 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
84 m_exception_language(eLanguageTypeUnknown),
85 m_language(lldb::eLanguageTypeUnknown),
86 m_skip_prologue(eLazyBoolCalculate), m_one_shot(false),
87 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
88
89 ~CommandOptions() override = default;
90
91 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
92 ExecutionContext *execution_context) override {
93 Error error;
94 const int short_option = m_getopt_table[option_idx].val;
Zachary Turner6fa7681b2016-09-17 02:00:02 +000095 llvm::StringRef option_strref(option_arg ? option_arg : "");
Kate Stoneb9c1b512016-09-06 20:57:50 +000096
97 switch (short_option) {
98 case 'a': {
99 m_load_addr = Args::StringToAddress(execution_context, option_arg,
100 LLDB_INVALID_ADDRESS, &error);
101 } break;
102
103 case 'A':
104 m_all_files = true;
105 break;
106
107 case 'b':
108 m_func_names.push_back(option_arg);
109 m_func_name_type_mask |= eFunctionNameTypeBase;
110 break;
111
112 case 'C': {
113 bool success;
114 m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success);
115 if (!success)
116 error.SetErrorStringWithFormat("invalid column number: %s",
117 option_arg);
118 break;
119 }
120
121 case 'c':
122 m_condition.assign(option_arg);
123 break;
124
125 case 'D':
126 m_use_dummy = true;
127 break;
128
129 case 'E': {
130 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
131
132 switch (language) {
133 case eLanguageTypeC89:
134 case eLanguageTypeC:
135 case eLanguageTypeC99:
136 case eLanguageTypeC11:
137 m_exception_language = eLanguageTypeC;
138 break;
139 case eLanguageTypeC_plus_plus:
140 case eLanguageTypeC_plus_plus_03:
141 case eLanguageTypeC_plus_plus_11:
142 case eLanguageTypeC_plus_plus_14:
143 m_exception_language = eLanguageTypeC_plus_plus;
144 break;
145 case eLanguageTypeObjC:
146 m_exception_language = eLanguageTypeObjC;
147 break;
148 case eLanguageTypeObjC_plus_plus:
149 error.SetErrorStringWithFormat(
150 "Set exception breakpoints separately for c++ and objective-c");
151 break;
152 case eLanguageTypeUnknown:
153 error.SetErrorStringWithFormat(
154 "Unknown language type: '%s' for exception breakpoint",
155 option_arg);
156 break;
157 default:
158 error.SetErrorStringWithFormat(
159 "Unsupported language type: '%s' for exception breakpoint",
160 option_arg);
161 }
162 } break;
163
164 case 'f':
165 m_filenames.AppendIfUnique(FileSpec(option_arg, false));
166 break;
167
168 case 'F':
169 m_func_names.push_back(option_arg);
170 m_func_name_type_mask |= eFunctionNameTypeFull;
171 break;
172
173 case 'h': {
174 bool success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000175 m_catch_bp = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176 if (!success)
177 error.SetErrorStringWithFormat(
178 "Invalid boolean value for on-catch option: '%s'", option_arg);
179 } break;
180
181 case 'H':
182 m_hardware = true;
183 break;
184
185 case 'i':
186 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
187 if (m_ignore_count == UINT32_MAX)
188 error.SetErrorStringWithFormat("invalid ignore count '%s'",
189 option_arg);
190 break;
191
192 case 'K': {
193 bool success;
194 bool value;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000195 value = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 if (value)
197 m_skip_prologue = eLazyBoolYes;
198 else
199 m_skip_prologue = eLazyBoolNo;
200
201 if (!success)
202 error.SetErrorStringWithFormat(
203 "Invalid boolean value for skip prologue option: '%s'",
204 option_arg);
205 } break;
206
207 case 'l': {
208 bool success;
209 m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success);
210 if (!success)
211 error.SetErrorStringWithFormat("invalid line number: %s.",
212 option_arg);
213 break;
214 }
215
216 case 'L':
217 m_language = Language::GetLanguageTypeFromString(option_arg);
218 if (m_language == eLanguageTypeUnknown)
219 error.SetErrorStringWithFormat(
220 "Unknown language type: '%s' for breakpoint", option_arg);
221 break;
222
223 case 'm': {
224 bool success;
225 bool value;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000226 value = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227 if (value)
228 m_move_to_nearest_code = eLazyBoolYes;
229 else
230 m_move_to_nearest_code = eLazyBoolNo;
231
232 if (!success)
233 error.SetErrorStringWithFormat(
234 "Invalid boolean value for move-to-nearest-code option: '%s'",
235 option_arg);
236 break;
237 }
238
239 case 'M':
240 m_func_names.push_back(option_arg);
241 m_func_name_type_mask |= eFunctionNameTypeMethod;
242 break;
243
244 case 'n':
245 m_func_names.push_back(option_arg);
246 m_func_name_type_mask |= eFunctionNameTypeAuto;
247 break;
248
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000249 case 'N': {
250 if (BreakpointID::StringIsBreakpointName(option_strref, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000251 m_breakpoint_names.push_back(option_arg);
252 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000253 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000254
255 case 'R': {
256 lldb::addr_t tmp_offset_addr;
257 tmp_offset_addr =
258 Args::StringToAddress(execution_context, option_arg, 0, &error);
259 if (error.Success())
260 m_offset_addr = tmp_offset_addr;
261 } break;
262
263 case 'o':
264 m_one_shot = true;
265 break;
266
267 case 'O':
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000268 m_exception_extra_args.AppendArgument(llvm::StringRef("-O"));
269 m_exception_extra_args.AppendArgument(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 break;
271
272 case 'p':
273 m_source_text_regexp.assign(option_arg);
274 break;
275
276 case 'q':
277 m_queue_name.assign(option_arg);
278 break;
279
280 case 'r':
281 m_func_regexp.assign(option_arg);
282 break;
283
284 case 's':
285 m_modules.AppendIfUnique(FileSpec(option_arg, false));
286 break;
287
288 case 'S':
289 m_func_names.push_back(option_arg);
290 m_func_name_type_mask |= eFunctionNameTypeSelector;
291 break;
292
293 case 't':
294 m_thread_id =
295 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
296 if (m_thread_id == LLDB_INVALID_THREAD_ID)
297 error.SetErrorStringWithFormat("invalid thread id string '%s'",
298 option_arg);
299 break;
300
301 case 'T':
302 m_thread_name.assign(option_arg);
303 break;
304
305 case 'w': {
306 bool success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000307 m_throw_bp = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000308 if (!success)
309 error.SetErrorStringWithFormat(
310 "Invalid boolean value for on-throw option: '%s'", option_arg);
311 } break;
312
313 case 'x':
314 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
315 if (m_thread_id == UINT32_MAX)
316 error.SetErrorStringWithFormat("invalid thread index string '%s'",
317 option_arg);
318 break;
319
320 case 'X':
321 m_source_regex_func_names.insert(option_arg);
322 break;
323
324 default:
325 error.SetErrorStringWithFormat("unrecognized option '%c'",
326 short_option);
327 break;
328 }
329
330 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000331 }
332
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333 void OptionParsingStarting(ExecutionContext *execution_context) override {
334 m_condition.clear();
335 m_filenames.Clear();
336 m_line_num = 0;
337 m_column = 0;
338 m_func_names.clear();
339 m_func_name_type_mask = eFunctionNameTypeNone;
340 m_func_regexp.clear();
341 m_source_text_regexp.clear();
342 m_modules.Clear();
343 m_load_addr = LLDB_INVALID_ADDRESS;
344 m_offset_addr = 0;
345 m_ignore_count = 0;
346 m_thread_id = LLDB_INVALID_THREAD_ID;
347 m_thread_index = UINT32_MAX;
348 m_thread_name.clear();
349 m_queue_name.clear();
350 m_catch_bp = false;
351 m_throw_bp = true;
352 m_hardware = false;
353 m_exception_language = eLanguageTypeUnknown;
354 m_language = lldb::eLanguageTypeUnknown;
355 m_skip_prologue = eLazyBoolCalculate;
356 m_one_shot = false;
357 m_use_dummy = false;
358 m_breakpoint_names.clear();
359 m_all_files = false;
360 m_exception_extra_args.Clear();
361 m_move_to_nearest_code = eLazyBoolCalculate;
362 m_source_regex_func_names.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000363 }
364
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham5a988412012-06-08 21:56:10 +0000366
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 // Options table: Required for subclasses of Options.
Jim Ingham5a988412012-06-08 21:56:10 +0000368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369 static OptionDefinition g_option_table[];
Jim Ingham5a988412012-06-08 21:56:10 +0000370
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000372
Kate Stoneb9c1b512016-09-06 20:57:50 +0000373 std::string m_condition;
374 FileSpecList m_filenames;
375 uint32_t m_line_num;
376 uint32_t m_column;
377 std::vector<std::string> m_func_names;
378 std::vector<std::string> m_breakpoint_names;
379 uint32_t m_func_name_type_mask;
380 std::string m_func_regexp;
381 std::string m_source_text_regexp;
382 FileSpecList m_modules;
383 lldb::addr_t m_load_addr;
384 lldb::addr_t m_offset_addr;
385 uint32_t m_ignore_count;
386 lldb::tid_t m_thread_id;
387 uint32_t m_thread_index;
388 std::string m_thread_name;
389 std::string m_queue_name;
390 bool m_catch_bp;
391 bool m_throw_bp;
392 bool m_hardware; // Request to use hardware breakpoints
393 lldb::LanguageType m_exception_language;
394 lldb::LanguageType m_language;
395 LazyBool m_skip_prologue;
396 bool m_one_shot;
397 bool m_use_dummy;
398 bool m_all_files;
399 Args m_exception_extra_args;
400 LazyBool m_move_to_nearest_code;
401 std::unordered_set<std::string> m_source_regex_func_names;
402 };
Jim Ingham5a988412012-06-08 21:56:10 +0000403
404protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000405 bool DoExecute(Args &command, CommandReturnObject &result) override {
406 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000407
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408 if (target == nullptr) {
409 result.AppendError("Invalid target. Must set target before setting "
410 "breakpoints (see 'target create' command).");
411 result.SetStatus(eReturnStatusFailed);
412 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000413 }
414
Kate Stoneb9c1b512016-09-06 20:57:50 +0000415 // The following are the various types of breakpoints that could be set:
416 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
417 // 2). -a [-s -g] (setting breakpoint by address)
418 // 3). -n [-s -g] (setting breakpoint by function name)
419 // 4). -r [-s -g] (setting breakpoint by function name regular
420 // expression)
421 // 5). -p -f (setting a breakpoint by comparing a reg-exp
422 // to source text)
423 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
424 // given language.)
425
426 BreakpointSetType break_type = eSetTypeInvalid;
427
428 if (m_options.m_line_num != 0)
429 break_type = eSetTypeFileAndLine;
430 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
431 break_type = eSetTypeAddress;
432 else if (!m_options.m_func_names.empty())
433 break_type = eSetTypeFunctionName;
434 else if (!m_options.m_func_regexp.empty())
435 break_type = eSetTypeFunctionRegexp;
436 else if (!m_options.m_source_text_regexp.empty())
437 break_type = eSetTypeSourceRegexp;
438 else if (m_options.m_exception_language != eLanguageTypeUnknown)
439 break_type = eSetTypeException;
440
441 Breakpoint *bp = nullptr;
442 FileSpec module_spec;
443 const bool internal = false;
444
445 // If the user didn't specify skip-prologue, having an offset should turn
446 // that off.
447 if (m_options.m_offset_addr != 0 &&
448 m_options.m_skip_prologue == eLazyBoolCalculate)
449 m_options.m_skip_prologue = eLazyBoolNo;
450
451 switch (break_type) {
452 case eSetTypeFileAndLine: // Breakpoint by source position
453 {
454 FileSpec file;
455 const size_t num_files = m_options.m_filenames.GetSize();
456 if (num_files == 0) {
457 if (!GetDefaultFile(target, file, result)) {
458 result.AppendError("No file supplied and no default file available.");
459 result.SetStatus(eReturnStatusFailed);
460 return false;
461 }
462 } else if (num_files > 1) {
463 result.AppendError("Only one file at a time is allowed for file and "
464 "line breakpoints.");
465 result.SetStatus(eReturnStatusFailed);
466 return false;
467 } else
468 file = m_options.m_filenames.GetFileSpecAtIndex(0);
469
470 // Only check for inline functions if
471 LazyBool check_inlines = eLazyBoolCalculate;
472
473 bp = target
474 ->CreateBreakpoint(&(m_options.m_modules), file,
475 m_options.m_line_num, m_options.m_offset_addr,
476 check_inlines, m_options.m_skip_prologue,
477 internal, m_options.m_hardware,
478 m_options.m_move_to_nearest_code)
479 .get();
480 } break;
481
482 case eSetTypeAddress: // Breakpoint by address
483 {
484 // If a shared library has been specified, make an lldb_private::Address
485 // with the library, and
486 // use that. That way the address breakpoint will track the load location
487 // of the library.
488 size_t num_modules_specified = m_options.m_modules.GetSize();
489 if (num_modules_specified == 1) {
490 const FileSpec *file_spec =
491 m_options.m_modules.GetFileSpecPointerAtIndex(0);
492 bp = target
493 ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
494 internal, file_spec,
495 m_options.m_hardware)
496 .get();
497 } else if (num_modules_specified == 0) {
498 bp = target
499 ->CreateBreakpoint(m_options.m_load_addr, internal,
500 m_options.m_hardware)
501 .get();
502 } else {
503 result.AppendError("Only one shared library can be specified for "
504 "address breakpoints.");
505 result.SetStatus(eReturnStatusFailed);
506 return false;
507 }
508 break;
509 }
510 case eSetTypeFunctionName: // Breakpoint by function name
511 {
512 uint32_t name_type_mask = m_options.m_func_name_type_mask;
513
514 if (name_type_mask == 0)
515 name_type_mask = eFunctionNameTypeAuto;
516
517 bp = target
518 ->CreateBreakpoint(
519 &(m_options.m_modules), &(m_options.m_filenames),
520 m_options.m_func_names, name_type_mask, m_options.m_language,
521 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
522 m_options.m_hardware)
523 .get();
524 } break;
525
526 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
527 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000528 {
529 RegularExpression regexp(m_options.m_func_regexp.c_str());
530 if (!regexp.IsValid()) {
531 char err_str[1024];
532 regexp.GetErrorAsCString(err_str, sizeof(err_str));
533 result.AppendErrorWithFormat(
534 "Function name regular expression could not be compiled: \"%s\"",
535 err_str);
536 result.SetStatus(eReturnStatusFailed);
537 return false;
538 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000539
Jim Inghame14dc262016-09-12 23:10:56 +0000540 bp = target
541 ->CreateFuncRegexBreakpoint(
542 &(m_options.m_modules), &(m_options.m_filenames), regexp,
543 m_options.m_language, m_options.m_skip_prologue, internal,
544 m_options.m_hardware)
545 .get();
546 }
547 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000548 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
549 {
550 const size_t num_files = m_options.m_filenames.GetSize();
551
552 if (num_files == 0 && !m_options.m_all_files) {
553 FileSpec file;
554 if (!GetDefaultFile(target, file, result)) {
555 result.AppendError(
556 "No files provided and could not find default file.");
557 result.SetStatus(eReturnStatusFailed);
558 return false;
559 } else {
560 m_options.m_filenames.Append(file);
561 }
562 }
563
564 RegularExpression regexp(m_options.m_source_text_regexp.c_str());
565 if (!regexp.IsValid()) {
566 char err_str[1024];
567 regexp.GetErrorAsCString(err_str, sizeof(err_str));
568 result.AppendErrorWithFormat(
569 "Source text regular expression could not be compiled: \"%s\"",
570 err_str);
571 result.SetStatus(eReturnStatusFailed);
572 return false;
573 }
574 bp = target
575 ->CreateSourceRegexBreakpoint(
576 &(m_options.m_modules), &(m_options.m_filenames),
577 m_options.m_source_regex_func_names, regexp, internal,
578 m_options.m_hardware, m_options.m_move_to_nearest_code)
579 .get();
580 } break;
581 case eSetTypeException: {
582 Error precond_error;
583 bp = target
584 ->CreateExceptionBreakpoint(
585 m_options.m_exception_language, m_options.m_catch_bp,
586 m_options.m_throw_bp, internal,
587 &m_options.m_exception_extra_args, &precond_error)
588 .get();
589 if (precond_error.Fail()) {
590 result.AppendErrorWithFormat(
591 "Error setting extra exception arguments: %s",
592 precond_error.AsCString());
593 target->RemoveBreakpointByID(bp->GetID());
594 result.SetStatus(eReturnStatusFailed);
595 return false;
596 }
597 } break;
598 default:
599 break;
600 }
601
602 // Now set the various options that were passed in:
603 if (bp) {
604 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
605 bp->SetThreadID(m_options.m_thread_id);
606
607 if (m_options.m_thread_index != UINT32_MAX)
608 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
609
610 if (!m_options.m_thread_name.empty())
611 bp->GetOptions()->GetThreadSpec()->SetName(
612 m_options.m_thread_name.c_str());
613
614 if (!m_options.m_queue_name.empty())
615 bp->GetOptions()->GetThreadSpec()->SetQueueName(
616 m_options.m_queue_name.c_str());
617
618 if (m_options.m_ignore_count != 0)
619 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
620
621 if (!m_options.m_condition.empty())
622 bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
623
624 if (!m_options.m_breakpoint_names.empty()) {
625 Error error; // We don't need to check the error here, since the option
626 // parser checked it...
627 for (auto name : m_options.m_breakpoint_names)
628 bp->AddName(name.c_str(), error);
629 }
630
631 bp->SetOneShot(m_options.m_one_shot);
632 }
633
634 if (bp) {
635 Stream &output_stream = result.GetOutputStream();
636 const bool show_locations = false;
637 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
638 show_locations);
639 if (target == m_interpreter.GetDebugger().GetDummyTarget())
640 output_stream.Printf("Breakpoint set in dummy target, will get copied "
641 "into future targets.\n");
642 else {
643 // Don't print out this warning for exception breakpoints. They can get
644 // set before the target
645 // is set, but we won't know how to actually set the breakpoint till we
646 // run.
647 if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
648 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
649 "actual locations.\n");
650 }
651 }
652 result.SetStatus(eReturnStatusSuccessFinishResult);
653 } else if (!bp) {
654 result.AppendError("Breakpoint creation failed: No breakpoint created.");
655 result.SetStatus(eReturnStatusFailed);
656 }
657
658 return result.Succeeded();
659 }
660
Jim Ingham5a988412012-06-08 21:56:10 +0000661private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000662 bool GetDefaultFile(Target *target, FileSpec &file,
663 CommandReturnObject &result) {
664 uint32_t default_line;
665 // First use the Source Manager's default file.
666 // Then use the current stack frame's file.
667 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
668 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
669 if (cur_frame == nullptr) {
670 result.AppendError(
671 "No selected frame to use to find the default file.");
672 result.SetStatus(eReturnStatusFailed);
673 return false;
674 } else if (!cur_frame->HasDebugInformation()) {
675 result.AppendError("Cannot use the selected frame to find the default "
676 "file, it has no debug info.");
677 result.SetStatus(eReturnStatusFailed);
678 return false;
679 } else {
680 const SymbolContext &sc =
681 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
682 if (sc.line_entry.file) {
683 file = sc.line_entry.file;
684 } else {
685 result.AppendError("Can't find the file for the selected frame to "
686 "use as the default file.");
687 result.SetStatus(eReturnStatusFailed);
688 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000689 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000690 }
Jim Ingham5a988412012-06-08 21:56:10 +0000691 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000692 return true;
693 }
694
695 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000696};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000697
Johnny Chen6943e7c2012-05-08 00:43:20 +0000698// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
699// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000700#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
701#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
702#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
703#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
704#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
705#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
Jim Ingham87df91b2011-09-23 00:54:11 +0000706
Kate Stoneb9c1b512016-09-06 20:57:50 +0000707OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
708 {
709 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +0000710 {LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option "
711 "multiple times to specify multiple shared libraries."},
712 {LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
713 {LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The breakpoint is deleted the first time it causes a stop." },
714 {LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
715 {LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument."},
716 {LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
717 {LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this "
718 "argument."},
719 {LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints."},
720 {LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by "
721 "this argument."},
722 {LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
723 "lldb only looks for files that are #included if they use the standard include "
724 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
725 "#included, set target.inline-breakpoint-strategy to \"always\"."},
726 {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint."},
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000727
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000728 // Comment out this option for the moment, as we don't actually use it, but will in the future.
729 // This way users won't see it, but the infrastructure is left in place.
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000730 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000731 // "Set the breakpoint by source location at this particular column."},
732
Kate Stoneac9c3a62016-08-26 23:28:47 +0000733 {LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to "
734 "a particular binary, then the address will be converted to a \"file\" "
735 "address, so that the breakpoint will track that binary+offset no matter where "
736 "the binary eventually loads. Alternately, if you also specify the module - "
737 "with the -s option - then the address will be treated as a file address in "
738 "that module, and resolved accordingly. Again, this will allow lldb to track "
739 "that offset on subsequent reloads. The module need not have been loaded at "
740 "the time you specify this breakpoint, and will get resolved when the module "
741 "is loaded."},
742 {LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make "
743 "one breakpoint for multiple names"},
744 {LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
745 "functions. Can be repeated multiple times."},
746 {LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
747 "namespaces and all arguments, and for Objective C this means a full function "
748 "prototype with class and selector. Can be repeated multiple times to make "
749 "one breakpoint for multiple names."},
750 {LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
751 "make one breakpoint for multiple Selectors."},
752 {LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to "
753 "make one breakpoint for multiple methods."},
754 {LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find "
755 "the function name(s)."},
756 {LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be "
757 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
758 "symbols."},
759 {LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched "
760 "against the source text in a source file or files specified with the -f "
761 "option. The -f option can be specified more than once. If no source files "
762 "are specified, uses the current \"default source file\". If you want to "
763 "match against all source files, pass the \"--all-files\" option."},
764 {LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches."},
765 {LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
766 "options, on throw but not catch.)"},
767 {LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW."},
768 {LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH."},
Jim Ingham969795f2011-09-21 01:17:13 +0000769
Jim Inghama72b31c2015-04-22 19:42:18 +0000770// Don't add this option till it actually does something useful...
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000771// { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
Jim Inghama72b31c2015-04-22 19:42:18 +0000772// "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" },
773
Kate Stoneac9c3a62016-08-26 23:28:47 +0000774 {LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
775 "(note: currently only implemented for setting breakpoints on identifiers). "
776 "If not set the target.language setting is used."},
777 {LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. "
778 "If not set the target.skip-prologue setting is used."},
779 {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, "
780 "which prime new targets."},
781 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint."},
782 {LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
Jim Ingham24111672016-03-09 18:59:13 +0000783 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries."},
Kate Stoneac9c3a62016-08-26 23:28:47 +0000784 {LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
785 "setting is used."},
786 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000787 // clang-format on
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000788};
789
Jim Ingham5a988412012-06-08 21:56:10 +0000790//-------------------------------------------------------------------------
791// CommandObjectBreakpointModify
792//-------------------------------------------------------------------------
793#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000794
Kate Stoneb9c1b512016-09-06 20:57:50 +0000795class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000796public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000797 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
798 : CommandObjectParsed(interpreter, "breakpoint modify",
799 "Modify the options on a breakpoint or set of "
800 "breakpoints in the executable. "
801 "If no breakpoint is specified, acts on the last "
802 "created breakpoint. "
803 "With the exception of -e, -d and -i, passing an "
804 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000805 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000806 m_options() {
807 CommandArgumentEntry arg;
808 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
809 eArgTypeBreakpointIDRange);
810 // Add the entry for the first argument for this command to the object's
811 // arguments vector.
812 m_arguments.push_back(arg);
813 }
814
815 ~CommandObjectBreakpointModify() override = default;
816
817 Options *GetOptions() override { return &m_options; }
818
819 class CommandOptions : public Options {
820 public:
821 CommandOptions()
822 : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
823 m_thread_id_passed(false), m_thread_index(UINT32_MAX),
824 m_thread_index_passed(false), m_thread_name(), m_queue_name(),
825 m_condition(), m_one_shot(false), m_enable_passed(false),
826 m_enable_value(false), m_name_passed(false), m_queue_passed(false),
827 m_condition_passed(false), m_one_shot_passed(false),
828 m_use_dummy(false) {}
829
830 ~CommandOptions() override = default;
831
832 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
833 ExecutionContext *execution_context) override {
834 Error error;
835 const int short_option = m_getopt_table[option_idx].val;
836
837 switch (short_option) {
838 case 'c':
839 if (option_arg != nullptr)
840 m_condition.assign(option_arg);
841 else
842 m_condition.clear();
843 m_condition_passed = true;
844 break;
845 case 'd':
846 m_enable_passed = true;
847 m_enable_value = false;
848 break;
849 case 'D':
850 m_use_dummy = true;
851 break;
852 case 'e':
853 m_enable_passed = true;
854 m_enable_value = true;
855 break;
856 case 'i':
857 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
858 if (m_ignore_count == UINT32_MAX)
859 error.SetErrorStringWithFormat("invalid ignore count '%s'",
860 option_arg);
861 break;
862 case 'o': {
863 bool value, success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000864 value = Args::StringToBoolean(
865 llvm::StringRef::withNullAsEmpty(option_arg), false, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000866 if (success) {
867 m_one_shot_passed = true;
868 m_one_shot = value;
869 } else
870 error.SetErrorStringWithFormat(
871 "invalid boolean value '%s' passed for -o option", option_arg);
872 } break;
873 case 't':
874 if (option_arg[0] == '\0') {
875 m_thread_id = LLDB_INVALID_THREAD_ID;
876 m_thread_id_passed = true;
877 } else {
878 m_thread_id =
879 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
880 if (m_thread_id == LLDB_INVALID_THREAD_ID)
881 error.SetErrorStringWithFormat("invalid thread id string '%s'",
882 option_arg);
883 else
884 m_thread_id_passed = true;
885 }
886 break;
887 case 'T':
888 if (option_arg != nullptr)
889 m_thread_name.assign(option_arg);
890 else
891 m_thread_name.clear();
892 m_name_passed = true;
893 break;
894 case 'q':
895 if (option_arg != nullptr)
896 m_queue_name.assign(option_arg);
897 else
898 m_queue_name.clear();
899 m_queue_passed = true;
900 break;
901 case 'x':
902 if (option_arg[0] == '\n') {
903 m_thread_index = UINT32_MAX;
904 m_thread_index_passed = true;
905 } else {
906 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
907 if (m_thread_id == UINT32_MAX)
908 error.SetErrorStringWithFormat("invalid thread index string '%s'",
909 option_arg);
910 else
911 m_thread_index_passed = true;
912 }
913 break;
914 default:
915 error.SetErrorStringWithFormat("unrecognized option '%c'",
916 short_option);
917 break;
918 }
919
920 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000921 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000922
Kate Stoneb9c1b512016-09-06 20:57:50 +0000923 void OptionParsingStarting(ExecutionContext *execution_context) override {
924 m_ignore_count = 0;
925 m_thread_id = LLDB_INVALID_THREAD_ID;
926 m_thread_id_passed = false;
927 m_thread_index = UINT32_MAX;
928 m_thread_index_passed = false;
929 m_thread_name.clear();
930 m_queue_name.clear();
931 m_condition.clear();
932 m_one_shot = false;
933 m_enable_passed = false;
934 m_queue_passed = false;
935 m_name_passed = false;
936 m_condition_passed = false;
937 m_one_shot_passed = false;
938 m_use_dummy = false;
Jim Ingham5a988412012-06-08 21:56:10 +0000939 }
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000940
Kate Stoneb9c1b512016-09-06 20:57:50 +0000941 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Greg Clayton0c5cd902010-06-28 21:30:43 +0000942
Kate Stoneb9c1b512016-09-06 20:57:50 +0000943 // Options table: Required for subclasses of Options.
Greg Clayton0c5cd902010-06-28 21:30:43 +0000944
Kate Stoneb9c1b512016-09-06 20:57:50 +0000945 static OptionDefinition g_option_table[];
Greg Claytone02b8502010-10-12 04:29:14 +0000946
Kate Stoneb9c1b512016-09-06 20:57:50 +0000947 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000948
Kate Stoneb9c1b512016-09-06 20:57:50 +0000949 uint32_t m_ignore_count;
950 lldb::tid_t m_thread_id;
951 bool m_thread_id_passed;
952 uint32_t m_thread_index;
953 bool m_thread_index_passed;
954 std::string m_thread_name;
955 std::string m_queue_name;
956 std::string m_condition;
957 bool m_one_shot;
958 bool m_enable_passed;
959 bool m_enable_value;
960 bool m_name_passed;
961 bool m_queue_passed;
962 bool m_condition_passed;
963 bool m_one_shot_passed;
964 bool m_use_dummy;
965 };
Jim Ingham5a988412012-06-08 21:56:10 +0000966
967protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000968 bool DoExecute(Args &command, CommandReturnObject &result) override {
969 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
970 if (target == nullptr) {
971 result.AppendError("Invalid target. No existing target or breakpoints.");
972 result.SetStatus(eReturnStatusFailed);
973 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000974 }
975
Kate Stoneb9c1b512016-09-06 20:57:50 +0000976 std::unique_lock<std::recursive_mutex> lock;
977 target->GetBreakpointList().GetListMutex(lock);
978
979 BreakpointIDList valid_bp_ids;
980
981 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
982 command, target, result, &valid_bp_ids);
983
984 if (result.Succeeded()) {
985 const size_t count = valid_bp_ids.GetSize();
986 for (size_t i = 0; i < count; ++i) {
987 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
988
989 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
990 Breakpoint *bp =
991 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
992 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
993 BreakpointLocation *location =
994 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
995 if (location) {
996 if (m_options.m_thread_id_passed)
997 location->SetThreadID(m_options.m_thread_id);
998
999 if (m_options.m_thread_index_passed)
1000 location->SetThreadIndex(m_options.m_thread_index);
1001
1002 if (m_options.m_name_passed)
1003 location->SetThreadName(m_options.m_thread_name.c_str());
1004
1005 if (m_options.m_queue_passed)
1006 location->SetQueueName(m_options.m_queue_name.c_str());
1007
1008 if (m_options.m_ignore_count != 0)
1009 location->SetIgnoreCount(m_options.m_ignore_count);
1010
1011 if (m_options.m_enable_passed)
1012 location->SetEnabled(m_options.m_enable_value);
1013
1014 if (m_options.m_condition_passed)
1015 location->SetCondition(m_options.m_condition.c_str());
1016 }
1017 } else {
1018 if (m_options.m_thread_id_passed)
1019 bp->SetThreadID(m_options.m_thread_id);
1020
1021 if (m_options.m_thread_index_passed)
1022 bp->SetThreadIndex(m_options.m_thread_index);
1023
1024 if (m_options.m_name_passed)
1025 bp->SetThreadName(m_options.m_thread_name.c_str());
1026
1027 if (m_options.m_queue_passed)
1028 bp->SetQueueName(m_options.m_queue_name.c_str());
1029
1030 if (m_options.m_ignore_count != 0)
1031 bp->SetIgnoreCount(m_options.m_ignore_count);
1032
1033 if (m_options.m_enable_passed)
1034 bp->SetEnabled(m_options.m_enable_value);
1035
1036 if (m_options.m_condition_passed)
1037 bp->SetCondition(m_options.m_condition.c_str());
1038 }
1039 }
1040 }
1041 }
1042
1043 return result.Succeeded();
1044 }
1045
Jim Ingham5a988412012-06-08 21:56:10 +00001046private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001047 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001048};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001049
Jim Ingham5a988412012-06-08 21:56:10 +00001050#pragma mark Modify::CommandOptions
1051OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001052 CommandObjectBreakpointModify::CommandOptions::g_option_table[] = {
1053 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001054 {LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping."},
1055 {LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop."},
1056 {LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."},
1057 {LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
1058 {LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
1059 {LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
1060 {LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
1061 {LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint."},
1062 {LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint."},
1063 {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1064 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001065 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001066};
1067
1068//-------------------------------------------------------------------------
1069// CommandObjectBreakpointEnable
1070//-------------------------------------------------------------------------
1071#pragma mark Enable
1072
Kate Stoneb9c1b512016-09-06 20:57:50 +00001073class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001074public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001075 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1076 : CommandObjectParsed(interpreter, "enable",
1077 "Enable the specified disabled breakpoint(s). If "
1078 "no breakpoints are specified, enable all of them.",
1079 nullptr) {
1080 CommandArgumentEntry arg;
1081 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1082 eArgTypeBreakpointIDRange);
1083 // Add the entry for the first argument for this command to the object's
1084 // arguments vector.
1085 m_arguments.push_back(arg);
1086 }
Jim Ingham5a988412012-06-08 21:56:10 +00001087
Kate Stoneb9c1b512016-09-06 20:57:50 +00001088 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001089
1090protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001091 bool DoExecute(Args &command, CommandReturnObject &result) override {
1092 Target *target = GetSelectedOrDummyTarget();
1093 if (target == nullptr) {
1094 result.AppendError("Invalid target. No existing target or breakpoints.");
1095 result.SetStatus(eReturnStatusFailed);
1096 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001097 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001098
1099 std::unique_lock<std::recursive_mutex> lock;
1100 target->GetBreakpointList().GetListMutex(lock);
1101
1102 const BreakpointList &breakpoints = target->GetBreakpointList();
1103
1104 size_t num_breakpoints = breakpoints.GetSize();
1105
1106 if (num_breakpoints == 0) {
1107 result.AppendError("No breakpoints exist to be enabled.");
1108 result.SetStatus(eReturnStatusFailed);
1109 return false;
1110 }
1111
1112 if (command.GetArgumentCount() == 0) {
1113 // No breakpoint selected; enable all currently set breakpoints.
1114 target->EnableAllBreakpoints();
1115 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1116 " breakpoints)\n",
1117 (uint64_t)num_breakpoints);
1118 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1119 } else {
1120 // Particular breakpoint selected; enable that breakpoint.
1121 BreakpointIDList valid_bp_ids;
1122 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1123 command, target, result, &valid_bp_ids);
1124
1125 if (result.Succeeded()) {
1126 int enable_count = 0;
1127 int loc_count = 0;
1128 const size_t count = valid_bp_ids.GetSize();
1129 for (size_t i = 0; i < count; ++i) {
1130 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1131
1132 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1133 Breakpoint *breakpoint =
1134 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1135 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1136 BreakpointLocation *location =
1137 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1138 if (location) {
1139 location->SetEnabled(true);
1140 ++loc_count;
1141 }
1142 } else {
1143 breakpoint->SetEnabled(true);
1144 ++enable_count;
1145 }
1146 }
1147 }
1148 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1149 enable_count + loc_count);
1150 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1151 }
1152 }
1153
1154 return result.Succeeded();
1155 }
Jim Ingham5a988412012-06-08 21:56:10 +00001156};
1157
1158//-------------------------------------------------------------------------
1159// CommandObjectBreakpointDisable
1160//-------------------------------------------------------------------------
1161#pragma mark Disable
1162
Kate Stoneb9c1b512016-09-06 20:57:50 +00001163class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001164public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001165 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1166 : CommandObjectParsed(
1167 interpreter, "breakpoint disable",
1168 "Disable the specified breakpoint(s) without deleting "
1169 "them. If none are specified, disable all "
1170 "breakpoints.",
1171 nullptr) {
1172 SetHelpLong(
1173 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001174If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001175 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001176
Kate Stone7428a182016-07-14 22:03:10 +00001177)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001178 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001179regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001180 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001181
1182 (lldb) break disable 1
1183 (lldb) break enable 1.1
1184
1185execution will NOT stop at location 1.1. To achieve that, type:
1186
1187 (lldb) break disable 1.*
1188 (lldb) break enable 1.1
1189
Kate Stone7428a182016-07-14 22:03:10 +00001190)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001191 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001192the second re-enables the first location.");
1193
Kate Stoneb9c1b512016-09-06 20:57:50 +00001194 CommandArgumentEntry arg;
1195 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1196 eArgTypeBreakpointIDRange);
1197 // Add the entry for the first argument for this command to the object's
1198 // arguments vector.
1199 m_arguments.push_back(arg);
1200 }
Jim Ingham5a988412012-06-08 21:56:10 +00001201
Kate Stoneb9c1b512016-09-06 20:57:50 +00001202 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001203
1204protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001205 bool DoExecute(Args &command, CommandReturnObject &result) override {
1206 Target *target = GetSelectedOrDummyTarget();
1207 if (target == nullptr) {
1208 result.AppendError("Invalid target. No existing target or breakpoints.");
1209 result.SetStatus(eReturnStatusFailed);
1210 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001211 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001212
1213 std::unique_lock<std::recursive_mutex> lock;
1214 target->GetBreakpointList().GetListMutex(lock);
1215
1216 const BreakpointList &breakpoints = target->GetBreakpointList();
1217 size_t num_breakpoints = breakpoints.GetSize();
1218
1219 if (num_breakpoints == 0) {
1220 result.AppendError("No breakpoints exist to be disabled.");
1221 result.SetStatus(eReturnStatusFailed);
1222 return false;
1223 }
1224
1225 if (command.GetArgumentCount() == 0) {
1226 // No breakpoint selected; disable all currently set breakpoints.
1227 target->DisableAllBreakpoints();
1228 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1229 " breakpoints)\n",
1230 (uint64_t)num_breakpoints);
1231 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1232 } else {
1233 // Particular breakpoint selected; disable that breakpoint.
1234 BreakpointIDList valid_bp_ids;
1235
1236 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1237 command, target, result, &valid_bp_ids);
1238
1239 if (result.Succeeded()) {
1240 int disable_count = 0;
1241 int loc_count = 0;
1242 const size_t count = valid_bp_ids.GetSize();
1243 for (size_t i = 0; i < count; ++i) {
1244 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1245
1246 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1247 Breakpoint *breakpoint =
1248 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1249 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1250 BreakpointLocation *location =
1251 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1252 if (location) {
1253 location->SetEnabled(false);
1254 ++loc_count;
1255 }
1256 } else {
1257 breakpoint->SetEnabled(false);
1258 ++disable_count;
1259 }
1260 }
1261 }
1262 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1263 disable_count + loc_count);
1264 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1265 }
1266 }
1267
1268 return result.Succeeded();
1269 }
Jim Ingham5a988412012-06-08 21:56:10 +00001270};
1271
1272//-------------------------------------------------------------------------
1273// CommandObjectBreakpointList
1274//-------------------------------------------------------------------------
1275#pragma mark List
1276
Kate Stoneb9c1b512016-09-06 20:57:50 +00001277class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001278public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001279 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1280 : CommandObjectParsed(
1281 interpreter, "breakpoint list",
1282 "List some or all breakpoints at configurable levels of detail.",
1283 nullptr),
1284 m_options() {
1285 CommandArgumentEntry arg;
1286 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001287
Kate Stoneb9c1b512016-09-06 20:57:50 +00001288 // Define the first (and only) variant of this arg.
1289 bp_id_arg.arg_type = eArgTypeBreakpointID;
1290 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001291
Kate Stoneb9c1b512016-09-06 20:57:50 +00001292 // There is only one variant this argument could be; put it into the
1293 // argument entry.
1294 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001295
Kate Stoneb9c1b512016-09-06 20:57:50 +00001296 // Push the data for the first argument into the m_arguments vector.
1297 m_arguments.push_back(arg);
1298 }
1299
1300 ~CommandObjectBreakpointList() override = default;
1301
1302 Options *GetOptions() override { return &m_options; }
1303
1304 class CommandOptions : public Options {
1305 public:
1306 CommandOptions()
1307 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001308 }
1309
Kate Stoneb9c1b512016-09-06 20:57:50 +00001310 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001311
Kate Stoneb9c1b512016-09-06 20:57:50 +00001312 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1313 ExecutionContext *execution_context) override {
1314 Error error;
1315 const int short_option = m_getopt_table[option_idx].val;
1316
1317 switch (short_option) {
1318 case 'b':
1319 m_level = lldb::eDescriptionLevelBrief;
1320 break;
1321 case 'D':
1322 m_use_dummy = true;
1323 break;
1324 case 'f':
1325 m_level = lldb::eDescriptionLevelFull;
1326 break;
1327 case 'v':
1328 m_level = lldb::eDescriptionLevelVerbose;
1329 break;
1330 case 'i':
1331 m_internal = true;
1332 break;
1333 default:
1334 error.SetErrorStringWithFormat("unrecognized option '%c'",
1335 short_option);
1336 break;
1337 }
1338
1339 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001340 }
Jim Ingham5a988412012-06-08 21:56:10 +00001341
Kate Stoneb9c1b512016-09-06 20:57:50 +00001342 void OptionParsingStarting(ExecutionContext *execution_context) override {
1343 m_level = lldb::eDescriptionLevelFull;
1344 m_internal = false;
1345 m_use_dummy = false;
1346 }
Jim Ingham5a988412012-06-08 21:56:10 +00001347
Kate Stoneb9c1b512016-09-06 20:57:50 +00001348 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham5a988412012-06-08 21:56:10 +00001349
Kate Stoneb9c1b512016-09-06 20:57:50 +00001350 // Options table: Required for subclasses of Options.
Jim Ingham5a988412012-06-08 21:56:10 +00001351
Kate Stoneb9c1b512016-09-06 20:57:50 +00001352 static OptionDefinition g_option_table[];
Jim Ingham5a988412012-06-08 21:56:10 +00001353
Kate Stoneb9c1b512016-09-06 20:57:50 +00001354 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001355
Kate Stoneb9c1b512016-09-06 20:57:50 +00001356 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001357
Kate Stoneb9c1b512016-09-06 20:57:50 +00001358 bool m_internal;
1359 bool m_use_dummy;
1360 };
Jim Ingham5a988412012-06-08 21:56:10 +00001361
1362protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001363 bool DoExecute(Args &command, CommandReturnObject &result) override {
1364 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001365
Kate Stoneb9c1b512016-09-06 20:57:50 +00001366 if (target == nullptr) {
1367 result.AppendError("Invalid target. No current target or breakpoints.");
1368 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1369 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001370 }
1371
Kate Stoneb9c1b512016-09-06 20:57:50 +00001372 const BreakpointList &breakpoints =
1373 target->GetBreakpointList(m_options.m_internal);
1374 std::unique_lock<std::recursive_mutex> lock;
1375 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1376
1377 size_t num_breakpoints = breakpoints.GetSize();
1378
1379 if (num_breakpoints == 0) {
1380 result.AppendMessage("No breakpoints currently set.");
1381 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1382 return true;
1383 }
1384
1385 Stream &output_stream = result.GetOutputStream();
1386
1387 if (command.GetArgumentCount() == 0) {
1388 // No breakpoint selected; show info about all currently set breakpoints.
1389 result.AppendMessage("Current breakpoints:");
1390 for (size_t i = 0; i < num_breakpoints; ++i) {
1391 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1392 AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
1393 }
1394 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1395 } else {
1396 // Particular breakpoints selected; show info about that breakpoint.
1397 BreakpointIDList valid_bp_ids;
1398 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1399 command, target, result, &valid_bp_ids);
1400
1401 if (result.Succeeded()) {
1402 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1403 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1404 Breakpoint *breakpoint =
1405 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1406 AddBreakpointDescription(&output_stream, breakpoint,
1407 m_options.m_level);
1408 }
1409 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1410 } else {
1411 result.AppendError("Invalid breakpoint ID.");
1412 result.SetStatus(eReturnStatusFailed);
1413 }
1414 }
1415
1416 return result.Succeeded();
1417 }
1418
Jim Ingham5a988412012-06-08 21:56:10 +00001419private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001420 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001421};
1422
1423#pragma mark List::CommandOptions
Kate Stoneb9c1b512016-09-06 20:57:50 +00001424OptionDefinition CommandObjectBreakpointList::CommandOptions::g_option_table[] =
1425 {
1426 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001427 {LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1428 {LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)."},
Jim Ingham5a988412012-06-08 21:56:10 +00001429 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1430 // But I need to see it for now, and don't want to wait.
Kate Stoneac9c3a62016-08-26 23:28:47 +00001431 {LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations."},
1432 {LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)."},
1433 {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1434 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001435 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001436};
1437
1438//-------------------------------------------------------------------------
1439// CommandObjectBreakpointClear
1440//-------------------------------------------------------------------------
1441#pragma mark Clear
1442
Kate Stoneb9c1b512016-09-06 20:57:50 +00001443class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001444public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001445 typedef enum BreakpointClearType {
1446 eClearTypeInvalid,
1447 eClearTypeFileAndLine
1448 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001449
Kate Stoneb9c1b512016-09-06 20:57:50 +00001450 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1451 : CommandObjectParsed(interpreter, "breakpoint clear",
1452 "Delete or disable breakpoints matching the "
1453 "specified source file and line.",
1454 "breakpoint clear <cmd-options>"),
1455 m_options() {}
1456
1457 ~CommandObjectBreakpointClear() override = default;
1458
1459 Options *GetOptions() override { return &m_options; }
1460
1461 class CommandOptions : public Options {
1462 public:
1463 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1464
1465 ~CommandOptions() override = default;
1466
1467 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1468 ExecutionContext *execution_context) override {
1469 Error error;
1470 const int short_option = m_getopt_table[option_idx].val;
1471
1472 switch (short_option) {
1473 case 'f':
1474 m_filename.assign(option_arg);
1475 break;
1476
1477 case 'l':
1478 m_line_num = StringConvert::ToUInt32(option_arg, 0);
1479 break;
1480
1481 default:
1482 error.SetErrorStringWithFormat("unrecognized option '%c'",
1483 short_option);
1484 break;
1485 }
1486
1487 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001488 }
1489
Kate Stoneb9c1b512016-09-06 20:57:50 +00001490 void OptionParsingStarting(ExecutionContext *execution_context) override {
1491 m_filename.clear();
1492 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001493 }
1494
Kate Stoneb9c1b512016-09-06 20:57:50 +00001495 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham5a988412012-06-08 21:56:10 +00001496
Kate Stoneb9c1b512016-09-06 20:57:50 +00001497 // Options table: Required for subclasses of Options.
Jim Ingham5a988412012-06-08 21:56:10 +00001498
Kate Stoneb9c1b512016-09-06 20:57:50 +00001499 static OptionDefinition g_option_table[];
Jim Ingham5a988412012-06-08 21:56:10 +00001500
Kate Stoneb9c1b512016-09-06 20:57:50 +00001501 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001502
Kate Stoneb9c1b512016-09-06 20:57:50 +00001503 std::string m_filename;
1504 uint32_t m_line_num;
1505 };
Jim Ingham5a988412012-06-08 21:56:10 +00001506
1507protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001508 bool DoExecute(Args &command, CommandReturnObject &result) override {
1509 Target *target = GetSelectedOrDummyTarget();
1510 if (target == nullptr) {
1511 result.AppendError("Invalid target. No existing target or breakpoints.");
1512 result.SetStatus(eReturnStatusFailed);
1513 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001514 }
1515
Kate Stoneb9c1b512016-09-06 20:57:50 +00001516 // The following are the various types of breakpoints that could be cleared:
1517 // 1). -f -l (clearing breakpoint by source location)
1518
1519 BreakpointClearType break_type = eClearTypeInvalid;
1520
1521 if (m_options.m_line_num != 0)
1522 break_type = eClearTypeFileAndLine;
1523
1524 std::unique_lock<std::recursive_mutex> lock;
1525 target->GetBreakpointList().GetListMutex(lock);
1526
1527 BreakpointList &breakpoints = target->GetBreakpointList();
1528 size_t num_breakpoints = breakpoints.GetSize();
1529
1530 // Early return if there's no breakpoint at all.
1531 if (num_breakpoints == 0) {
1532 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1533 result.SetStatus(eReturnStatusFailed);
1534 return result.Succeeded();
1535 }
1536
1537 // Find matching breakpoints and delete them.
1538
1539 // First create a copy of all the IDs.
1540 std::vector<break_id_t> BreakIDs;
1541 for (size_t i = 0; i < num_breakpoints; ++i)
1542 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1543
1544 int num_cleared = 0;
1545 StreamString ss;
1546 switch (break_type) {
1547 case eClearTypeFileAndLine: // Breakpoint by source position
1548 {
1549 const ConstString filename(m_options.m_filename.c_str());
1550 BreakpointLocationCollection loc_coll;
1551
1552 for (size_t i = 0; i < num_breakpoints; ++i) {
1553 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1554
1555 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1556 // If the collection size is 0, it's a full match and we can just
1557 // remove the breakpoint.
1558 if (loc_coll.GetSize() == 0) {
1559 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1560 ss.EOL();
1561 target->RemoveBreakpointByID(bp->GetID());
1562 ++num_cleared;
1563 }
1564 }
1565 }
1566 } break;
1567
1568 default:
1569 break;
1570 }
1571
1572 if (num_cleared > 0) {
1573 Stream &output_stream = result.GetOutputStream();
1574 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1575 output_stream << ss.GetData();
1576 output_stream.EOL();
1577 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1578 } else {
1579 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1580 result.SetStatus(eReturnStatusFailed);
1581 }
1582
1583 return result.Succeeded();
1584 }
1585
Jim Ingham5a988412012-06-08 21:56:10 +00001586private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001587 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001588};
1589
1590#pragma mark Clear::CommandOptions
1591
1592OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001593 CommandObjectBreakpointClear::CommandOptions::g_option_table[] = {
1594 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001595 {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file."},
1596 {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line."},
1597 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001598 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001599};
1600
1601//-------------------------------------------------------------------------
1602// CommandObjectBreakpointDelete
1603//-------------------------------------------------------------------------
1604#pragma mark Delete
1605
Kate Stoneb9c1b512016-09-06 20:57:50 +00001606class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001607public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001608 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1609 : CommandObjectParsed(interpreter, "breakpoint delete",
1610 "Delete the specified breakpoint(s). If no "
1611 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001612 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001613 m_options() {
1614 CommandArgumentEntry arg;
1615 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1616 eArgTypeBreakpointIDRange);
1617 // Add the entry for the first argument for this command to the object's
1618 // arguments vector.
1619 m_arguments.push_back(arg);
1620 }
1621
1622 ~CommandObjectBreakpointDelete() override = default;
1623
1624 Options *GetOptions() override { return &m_options; }
1625
1626 class CommandOptions : public Options {
1627 public:
1628 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1629
1630 ~CommandOptions() override = default;
1631
1632 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1633 ExecutionContext *execution_context) override {
1634 Error error;
1635 const int short_option = m_getopt_table[option_idx].val;
1636
1637 switch (short_option) {
1638 case 'f':
1639 m_force = true;
1640 break;
1641
1642 case 'D':
1643 m_use_dummy = true;
1644 break;
1645
1646 default:
1647 error.SetErrorStringWithFormat("unrecognized option '%c'",
1648 short_option);
1649 break;
1650 }
1651
1652 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001653 }
1654
Kate Stoneb9c1b512016-09-06 20:57:50 +00001655 void OptionParsingStarting(ExecutionContext *execution_context) override {
1656 m_use_dummy = false;
1657 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001658 }
1659
Kate Stoneb9c1b512016-09-06 20:57:50 +00001660 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001661
Kate Stoneb9c1b512016-09-06 20:57:50 +00001662 // Options table: Required for subclasses of Options.
Jim Ingham33df7cd2014-12-06 01:28:03 +00001663
Kate Stoneb9c1b512016-09-06 20:57:50 +00001664 static OptionDefinition g_option_table[];
Jim Ingham33df7cd2014-12-06 01:28:03 +00001665
Kate Stoneb9c1b512016-09-06 20:57:50 +00001666 // Instance variables to hold the values for command options.
1667 bool m_use_dummy;
1668 bool m_force;
1669 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001670
Jim Ingham5a988412012-06-08 21:56:10 +00001671protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001672 bool DoExecute(Args &command, CommandReturnObject &result) override {
1673 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001674
Kate Stoneb9c1b512016-09-06 20:57:50 +00001675 if (target == nullptr) {
1676 result.AppendError("Invalid target. No existing target or breakpoints.");
1677 result.SetStatus(eReturnStatusFailed);
1678 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001679 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001680
Kate Stoneb9c1b512016-09-06 20:57:50 +00001681 std::unique_lock<std::recursive_mutex> lock;
1682 target->GetBreakpointList().GetListMutex(lock);
1683
1684 const BreakpointList &breakpoints = target->GetBreakpointList();
1685
1686 size_t num_breakpoints = breakpoints.GetSize();
1687
1688 if (num_breakpoints == 0) {
1689 result.AppendError("No breakpoints exist to be deleted.");
1690 result.SetStatus(eReturnStatusFailed);
1691 return false;
1692 }
1693
1694 if (command.GetArgumentCount() == 0) {
1695 if (!m_options.m_force &&
1696 !m_interpreter.Confirm(
1697 "About to delete all breakpoints, do you want to do that?",
1698 true)) {
1699 result.AppendMessage("Operation cancelled...");
1700 } else {
1701 target->RemoveAllBreakpoints();
1702 result.AppendMessageWithFormat(
1703 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1704 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1705 }
1706 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1707 } else {
1708 // Particular breakpoint selected; disable that breakpoint.
1709 BreakpointIDList valid_bp_ids;
1710 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1711 command, target, result, &valid_bp_ids);
1712
1713 if (result.Succeeded()) {
1714 int delete_count = 0;
1715 int disable_count = 0;
1716 const size_t count = valid_bp_ids.GetSize();
1717 for (size_t i = 0; i < count; ++i) {
1718 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1719
1720 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1721 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1722 Breakpoint *breakpoint =
1723 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1724 BreakpointLocation *location =
1725 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1726 // It makes no sense to try to delete individual locations, so we
1727 // disable them instead.
1728 if (location) {
1729 location->SetEnabled(false);
1730 ++disable_count;
1731 }
1732 } else {
1733 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1734 ++delete_count;
1735 }
1736 }
1737 }
1738 result.AppendMessageWithFormat(
1739 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1740 delete_count, disable_count);
1741 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1742 }
1743 }
1744 return result.Succeeded();
1745 }
1746
Jim Ingham33df7cd2014-12-06 01:28:03 +00001747private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001748 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001749};
1750
1751OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001752 CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = {
1753 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001754 {LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation."},
1755 {LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1756 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001757 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001758};
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001759
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001760//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001761// CommandObjectBreakpointName
1762//-------------------------------------------------------------------------
1763
Kate Stone7428a182016-07-14 22:03:10 +00001764static OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001765 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001766 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1767 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1768 {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
Kate Stoneb9c1b512016-09-06 20:57:50 +00001769 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001770};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001771class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001772public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001773 BreakpointNameOptionGroup()
1774 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1775 }
1776
1777 ~BreakpointNameOptionGroup() override = default;
1778
1779 uint32_t GetNumDefinitions() override {
1780 return sizeof(g_breakpoint_name_options) / sizeof(OptionDefinition);
1781 }
1782
1783 const OptionDefinition *GetDefinitions() override {
1784 return g_breakpoint_name_options;
1785 }
1786
1787 Error SetOptionValue(uint32_t option_idx, const char *option_value,
1788 ExecutionContext *execution_context) override {
1789 Error error;
1790 const int short_option = g_breakpoint_name_options[option_idx].short_option;
Zachary Turner6fa7681b2016-09-17 02:00:02 +00001791 llvm::StringRef option_strref(option_value ? option_value : "");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001792
1793 switch (short_option) {
1794 case 'N':
Zachary Turner6fa7681b2016-09-17 02:00:02 +00001795 if (BreakpointID::StringIsBreakpointName(option_strref, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001796 error.Success())
Zachary Turner6fa7681b2016-09-17 02:00:02 +00001797 m_name.SetValueFromString(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001798 break;
1799
1800 case 'B':
1801 if (m_breakpoint.SetValueFromString(option_value).Fail())
1802 error.SetErrorStringWithFormat(
1803 "unrecognized value \"%s\" for breakpoint", option_value);
1804 break;
1805 case 'D':
1806 if (m_use_dummy.SetValueFromString(option_value).Fail())
1807 error.SetErrorStringWithFormat(
1808 "unrecognized value \"%s\" for use-dummy", option_value);
1809 break;
1810
1811 default:
1812 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1813 short_option);
1814 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001815 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001816 return error;
1817 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001818
Kate Stoneb9c1b512016-09-06 20:57:50 +00001819 void OptionParsingStarting(ExecutionContext *execution_context) override {
1820 m_name.Clear();
1821 m_breakpoint.Clear();
1822 m_use_dummy.Clear();
1823 m_use_dummy.SetDefaultValue(false);
1824 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001825
Kate Stoneb9c1b512016-09-06 20:57:50 +00001826 OptionValueString m_name;
1827 OptionValueUInt64 m_breakpoint;
1828 OptionValueBoolean m_use_dummy;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001829};
1830
Kate Stoneb9c1b512016-09-06 20:57:50 +00001831class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001832public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001833 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1834 : CommandObjectParsed(
1835 interpreter, "add", "Add a name to the breakpoints provided.",
1836 "breakpoint name add <command-options> <breakpoint-id-list>"),
1837 m_name_options(), m_option_group() {
1838 // Create the first variant for the first (and only) argument for this
1839 // command.
1840 CommandArgumentEntry arg1;
1841 CommandArgumentData id_arg;
1842 id_arg.arg_type = eArgTypeBreakpointID;
1843 id_arg.arg_repetition = eArgRepeatOptional;
1844 arg1.push_back(id_arg);
1845 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001846
Kate Stoneb9c1b512016-09-06 20:57:50 +00001847 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1848 m_option_group.Finalize();
1849 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001850
Kate Stoneb9c1b512016-09-06 20:57:50 +00001851 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001852
Kate Stoneb9c1b512016-09-06 20:57:50 +00001853 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001854
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001855protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001856 bool DoExecute(Args &command, CommandReturnObject &result) override {
1857 if (!m_name_options.m_name.OptionWasSet()) {
1858 result.SetError("No name option provided.");
1859 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001860 }
1861
Kate Stoneb9c1b512016-09-06 20:57:50 +00001862 Target *target =
1863 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1864
1865 if (target == nullptr) {
1866 result.AppendError("Invalid target. No existing target or breakpoints.");
1867 result.SetStatus(eReturnStatusFailed);
1868 return false;
1869 }
1870
1871 std::unique_lock<std::recursive_mutex> lock;
1872 target->GetBreakpointList().GetListMutex(lock);
1873
1874 const BreakpointList &breakpoints = target->GetBreakpointList();
1875
1876 size_t num_breakpoints = breakpoints.GetSize();
1877 if (num_breakpoints == 0) {
1878 result.SetError("No breakpoints, cannot add names.");
1879 result.SetStatus(eReturnStatusFailed);
1880 return false;
1881 }
1882
1883 // Particular breakpoint selected; disable that breakpoint.
1884 BreakpointIDList valid_bp_ids;
1885 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1886 command, target, result, &valid_bp_ids);
1887
1888 if (result.Succeeded()) {
1889 if (valid_bp_ids.GetSize() == 0) {
1890 result.SetError("No breakpoints specified, cannot add names.");
1891 result.SetStatus(eReturnStatusFailed);
1892 return false;
1893 }
1894 size_t num_valid_ids = valid_bp_ids.GetSize();
1895 for (size_t index = 0; index < num_valid_ids; index++) {
1896 lldb::break_id_t bp_id =
1897 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1898 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1899 Error error; // We don't need to check the error here, since the option
1900 // parser checked it...
1901 bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
1902 }
1903 }
1904
1905 return true;
1906 }
1907
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001908private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001909 BreakpointNameOptionGroup m_name_options;
1910 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001911};
1912
Kate Stoneb9c1b512016-09-06 20:57:50 +00001913class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001914public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001915 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1916 : CommandObjectParsed(
1917 interpreter, "delete",
1918 "Delete a name from the breakpoints provided.",
1919 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1920 m_name_options(), m_option_group() {
1921 // Create the first variant for the first (and only) argument for this
1922 // command.
1923 CommandArgumentEntry arg1;
1924 CommandArgumentData id_arg;
1925 id_arg.arg_type = eArgTypeBreakpointID;
1926 id_arg.arg_repetition = eArgRepeatOptional;
1927 arg1.push_back(id_arg);
1928 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001929
Kate Stoneb9c1b512016-09-06 20:57:50 +00001930 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1931 m_option_group.Finalize();
1932 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001933
Kate Stoneb9c1b512016-09-06 20:57:50 +00001934 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001935
Kate Stoneb9c1b512016-09-06 20:57:50 +00001936 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001937
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001938protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001939 bool DoExecute(Args &command, CommandReturnObject &result) override {
1940 if (!m_name_options.m_name.OptionWasSet()) {
1941 result.SetError("No name option provided.");
1942 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001943 }
1944
Kate Stoneb9c1b512016-09-06 20:57:50 +00001945 Target *target =
1946 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1947
1948 if (target == nullptr) {
1949 result.AppendError("Invalid target. No existing target or breakpoints.");
1950 result.SetStatus(eReturnStatusFailed);
1951 return false;
1952 }
1953
1954 std::unique_lock<std::recursive_mutex> lock;
1955 target->GetBreakpointList().GetListMutex(lock);
1956
1957 const BreakpointList &breakpoints = target->GetBreakpointList();
1958
1959 size_t num_breakpoints = breakpoints.GetSize();
1960 if (num_breakpoints == 0) {
1961 result.SetError("No breakpoints, cannot delete names.");
1962 result.SetStatus(eReturnStatusFailed);
1963 return false;
1964 }
1965
1966 // Particular breakpoint selected; disable that breakpoint.
1967 BreakpointIDList valid_bp_ids;
1968 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1969 command, target, result, &valid_bp_ids);
1970
1971 if (result.Succeeded()) {
1972 if (valid_bp_ids.GetSize() == 0) {
1973 result.SetError("No breakpoints specified, cannot delete names.");
1974 result.SetStatus(eReturnStatusFailed);
1975 return false;
1976 }
1977 size_t num_valid_ids = valid_bp_ids.GetSize();
1978 for (size_t index = 0; index < num_valid_ids; index++) {
1979 lldb::break_id_t bp_id =
1980 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1981 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1982 bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
1983 }
1984 }
1985
1986 return true;
1987 }
1988
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001989private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001990 BreakpointNameOptionGroup m_name_options;
1991 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001992};
1993
Kate Stoneb9c1b512016-09-06 20:57:50 +00001994class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001995public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001996 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1997 : CommandObjectParsed(interpreter, "list",
1998 "List either the names for a breakpoint or the "
1999 "breakpoints for a given name.",
2000 "breakpoint name list <command-options>"),
2001 m_name_options(), m_option_group() {
2002 m_option_group.Append(&m_name_options);
2003 m_option_group.Finalize();
2004 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002005
Kate Stoneb9c1b512016-09-06 20:57:50 +00002006 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002007
Kate Stoneb9c1b512016-09-06 20:57:50 +00002008 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002009
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002010protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002011 bool DoExecute(Args &command, CommandReturnObject &result) override {
2012 Target *target =
2013 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002014
Kate Stoneb9c1b512016-09-06 20:57:50 +00002015 if (target == nullptr) {
2016 result.AppendError("Invalid target. No existing target or breakpoints.");
2017 result.SetStatus(eReturnStatusFailed);
2018 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002019 }
2020
Kate Stoneb9c1b512016-09-06 20:57:50 +00002021 if (m_name_options.m_name.OptionWasSet()) {
2022 const char *name = m_name_options.m_name.GetCurrentValue();
2023 std::unique_lock<std::recursive_mutex> lock;
2024 target->GetBreakpointList().GetListMutex(lock);
2025
2026 BreakpointList &breakpoints = target->GetBreakpointList();
2027 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2028 if (bp_sp->MatchesName(name)) {
2029 StreamString s;
2030 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2031 s.EOL();
2032 result.AppendMessage(s.GetData());
2033 }
2034 }
2035
2036 } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2037 BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2038 m_name_options.m_breakpoint.GetCurrentValue());
2039 if (bp_sp) {
2040 std::vector<std::string> names;
2041 bp_sp->GetNames(names);
2042 result.AppendMessage("Names:");
2043 for (auto name : names)
2044 result.AppendMessageWithFormat(" %s\n", name.c_str());
2045 } else {
2046 result.AppendErrorWithFormat(
2047 "Could not find breakpoint %" PRId64 ".\n",
2048 m_name_options.m_breakpoint.GetCurrentValue());
2049 result.SetStatus(eReturnStatusFailed);
2050 return false;
2051 }
2052 } else {
2053 result.SetError("Must specify -N or -B option to list.");
2054 result.SetStatus(eReturnStatusFailed);
2055 return false;
2056 }
2057 return true;
2058 }
2059
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002060private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002061 BreakpointNameOptionGroup m_name_options;
2062 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002063};
2064
2065//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002066// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002067//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002068class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002069public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002070 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2071 : CommandObjectMultiword(
2072 interpreter, "name", "Commands to manage name tags for breakpoints",
2073 "breakpoint name <subcommand> [<command-options>]") {
2074 CommandObjectSP add_command_object(
2075 new CommandObjectBreakpointNameAdd(interpreter));
2076 CommandObjectSP delete_command_object(
2077 new CommandObjectBreakpointNameDelete(interpreter));
2078 CommandObjectSP list_command_object(
2079 new CommandObjectBreakpointNameList(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002080
Kate Stoneb9c1b512016-09-06 20:57:50 +00002081 LoadSubCommand("add", add_command_object);
2082 LoadSubCommand("delete", delete_command_object);
2083 LoadSubCommand("list", list_command_object);
2084 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002085
Kate Stoneb9c1b512016-09-06 20:57:50 +00002086 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002087};
2088
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002089//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002090// CommandObjectBreakpointRead
2091//-------------------------------------------------------------------------
2092#pragma mark Restore
2093
2094class CommandObjectBreakpointRead : public CommandObjectParsed {
2095public:
2096 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2097 : CommandObjectParsed(interpreter, "breakpoint read",
2098 "Read and set the breakpoints previously saved to "
2099 "a file with \"breakpoint write\". ",
2100 nullptr),
2101 m_options() {
2102 CommandArgumentEntry arg;
2103 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2104 eArgTypeBreakpointIDRange);
2105 // Add the entry for the first argument for this command to the object's
2106 // arguments vector.
2107 m_arguments.push_back(arg);
2108 }
2109
2110 ~CommandObjectBreakpointRead() override = default;
2111
2112 Options *GetOptions() override { return &m_options; }
2113
2114 class CommandOptions : public Options {
2115 public:
2116 CommandOptions() : Options() {}
2117
2118 ~CommandOptions() override = default;
2119
2120 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2121 ExecutionContext *execution_context) override {
2122 Error error;
2123 const int short_option = m_getopt_table[option_idx].val;
2124
2125 switch (short_option) {
2126 case 'f':
2127 m_filename.assign(option_arg);
2128 break;
2129 default:
2130 error.SetErrorStringWithFormat("unrecognized option '%c'",
2131 short_option);
2132 break;
2133 }
2134
2135 return error;
2136 }
2137
2138 void OptionParsingStarting(ExecutionContext *execution_context) override {
2139 m_filename.clear();
2140 }
2141
2142 const OptionDefinition *GetDefinitions() override { return g_option_table; }
2143
2144 // Options table: Required for subclasses of Options.
2145
2146 static OptionDefinition g_option_table[];
2147
2148 // Instance variables to hold the values for command options.
2149
2150 std::string m_filename;
2151 };
2152
2153protected:
2154 bool DoExecute(Args &command, CommandReturnObject &result) override {
2155 Target *target = GetSelectedOrDummyTarget();
2156 if (target == nullptr) {
2157 result.AppendError("Invalid target. No existing target or breakpoints.");
2158 result.SetStatus(eReturnStatusFailed);
2159 return false;
2160 }
2161
Jim Inghame14dc262016-09-12 23:10:56 +00002162 FileSpec input_spec(m_options.m_filename, true);
Jim Ingham01f16662016-09-14 19:07:35 +00002163 BreakpointIDList new_bps;
2164 Error error = target->CreateBreakpointsFromFile(input_spec, new_bps);
2165
Jim Inghame14dc262016-09-12 23:10:56 +00002166 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002167 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002168 result.SetStatus(eReturnStatusFailed);
2169 return false;
2170 }
Jim Ingham01f16662016-09-14 19:07:35 +00002171 // FIXME: Report the newly created breakpoints.
Jim Inghame14dc262016-09-12 23:10:56 +00002172 return result.Succeeded();
2173 }
2174
2175private:
2176 CommandOptions m_options;
2177};
2178
2179#pragma mark Modify::CommandOptions
2180OptionDefinition CommandObjectBreakpointRead::CommandOptions::g_option_table[] =
2181 {
2182 // clang-format off
2183 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints."},
2184 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
2185 // clang-format on
2186};
2187
2188//-------------------------------------------------------------------------
2189// CommandObjectBreakpointWrite
2190//-------------------------------------------------------------------------
2191#pragma mark Save
2192class CommandObjectBreakpointWrite : public CommandObjectParsed {
2193public:
2194 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2195 : CommandObjectParsed(interpreter, "breakpoint write",
2196 "Write the breakpoints listed to a file that can "
2197 "be read in with \"breakpoint read\". "
2198 "If given no arguments, writes all breakpoints.",
2199 nullptr),
2200 m_options() {
2201 CommandArgumentEntry arg;
2202 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2203 eArgTypeBreakpointIDRange);
2204 // Add the entry for the first argument for this command to the object's
2205 // arguments vector.
2206 m_arguments.push_back(arg);
2207 }
2208
2209 ~CommandObjectBreakpointWrite() override = default;
2210
2211 Options *GetOptions() override { return &m_options; }
2212
2213 class CommandOptions : public Options {
2214 public:
2215 CommandOptions() : Options() {}
2216
2217 ~CommandOptions() override = default;
2218
2219 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2220 ExecutionContext *execution_context) override {
2221 Error error;
2222 const int short_option = m_getopt_table[option_idx].val;
2223
2224 switch (short_option) {
2225 case 'f':
2226 m_filename.assign(option_arg);
2227 break;
2228 default:
2229 error.SetErrorStringWithFormat("unrecognized option '%c'",
2230 short_option);
2231 break;
2232 }
2233
2234 return error;
2235 }
2236
2237 void OptionParsingStarting(ExecutionContext *execution_context) override {
2238 m_filename.clear();
2239 }
2240
2241 const OptionDefinition *GetDefinitions() override { return g_option_table; }
2242
2243 // Options table: Required for subclasses of Options.
2244
2245 static OptionDefinition g_option_table[];
2246
2247 // Instance variables to hold the values for command options.
2248
2249 std::string m_filename;
2250 };
2251
2252protected:
2253 bool DoExecute(Args &command, CommandReturnObject &result) override {
2254 Target *target = GetSelectedOrDummyTarget();
2255 if (target == nullptr) {
2256 result.AppendError("Invalid target. No existing target or breakpoints.");
2257 result.SetStatus(eReturnStatusFailed);
2258 return false;
2259 }
2260
Jim Inghame14dc262016-09-12 23:10:56 +00002261 std::unique_lock<std::recursive_mutex> lock;
2262 target->GetBreakpointList().GetListMutex(lock);
2263
Jim Ingham01f16662016-09-14 19:07:35 +00002264 BreakpointIDList valid_bp_ids;
2265 if (command.GetArgumentCount() > 0) {
Jim Inghame14dc262016-09-12 23:10:56 +00002266 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2267 command, target, result, &valid_bp_ids);
2268
Jim Ingham01f16662016-09-14 19:07:35 +00002269 if (!result.Succeeded()) {
2270 result.SetStatus(eReturnStatusFailed);
2271 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002272 }
2273 }
Jim Ingham01f16662016-09-14 19:07:35 +00002274 Error error = target->SerializeBreakpointsToFile(
2275 FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids);
2276 if (!error.Success()) {
2277 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2278 error.AsCString());
2279 result.SetStatus(eReturnStatusFailed);
2280 }
Jim Inghame14dc262016-09-12 23:10:56 +00002281 return result.Succeeded();
2282 }
2283
2284private:
2285 CommandOptions m_options;
2286};
2287
2288#pragma mark Modify::CommandOptions
2289OptionDefinition
2290 CommandObjectBreakpointWrite::CommandOptions::g_option_table[] = {
2291 // clang-format off
2292 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints."},
2293 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
2294 // clang-format on
2295};
2296
2297//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002298// CommandObjectMultiwordBreakpoint
2299//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002300#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002301
Kate Stoneb9c1b512016-09-06 20:57:50 +00002302CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2303 CommandInterpreter &interpreter)
2304 : CommandObjectMultiword(
2305 interpreter, "breakpoint",
2306 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2307 "breakpoint <subcommand> [<command-options>]") {
2308 CommandObjectSP list_command_object(
2309 new CommandObjectBreakpointList(interpreter));
2310 CommandObjectSP enable_command_object(
2311 new CommandObjectBreakpointEnable(interpreter));
2312 CommandObjectSP disable_command_object(
2313 new CommandObjectBreakpointDisable(interpreter));
2314 CommandObjectSP clear_command_object(
2315 new CommandObjectBreakpointClear(interpreter));
2316 CommandObjectSP delete_command_object(
2317 new CommandObjectBreakpointDelete(interpreter));
2318 CommandObjectSP set_command_object(
2319 new CommandObjectBreakpointSet(interpreter));
2320 CommandObjectSP command_command_object(
2321 new CommandObjectBreakpointCommand(interpreter));
2322 CommandObjectSP modify_command_object(
2323 new CommandObjectBreakpointModify(interpreter));
2324 CommandObjectSP name_command_object(
2325 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002326 CommandObjectSP write_command_object(
2327 new CommandObjectBreakpointWrite(interpreter));
2328 CommandObjectSP read_command_object(
2329 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002330
Kate Stoneb9c1b512016-09-06 20:57:50 +00002331 list_command_object->SetCommandName("breakpoint list");
2332 enable_command_object->SetCommandName("breakpoint enable");
2333 disable_command_object->SetCommandName("breakpoint disable");
2334 clear_command_object->SetCommandName("breakpoint clear");
2335 delete_command_object->SetCommandName("breakpoint delete");
2336 set_command_object->SetCommandName("breakpoint set");
2337 command_command_object->SetCommandName("breakpoint command");
2338 modify_command_object->SetCommandName("breakpoint modify");
2339 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002340 write_command_object->SetCommandName("breakpoint write");
2341 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002342
Kate Stoneb9c1b512016-09-06 20:57:50 +00002343 LoadSubCommand("list", list_command_object);
2344 LoadSubCommand("enable", enable_command_object);
2345 LoadSubCommand("disable", disable_command_object);
2346 LoadSubCommand("clear", clear_command_object);
2347 LoadSubCommand("delete", delete_command_object);
2348 LoadSubCommand("set", set_command_object);
2349 LoadSubCommand("command", command_command_object);
2350 LoadSubCommand("modify", modify_command_object);
2351 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002352 LoadSubCommand("write", write_command_object);
2353 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002354}
2355
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002356CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002357
Kate Stoneb9c1b512016-09-06 20:57:50 +00002358void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2359 bool allow_locations,
2360 CommandReturnObject &result,
2361 BreakpointIDList *valid_ids) {
2362 // args can be strings representing 1). integers (for breakpoint ids)
2363 // 2). the full breakpoint & location
2364 // canonical representation
2365 // 3). the word "to" or a hyphen,
2366 // representing a range (in which case there
2367 // had *better* be an entry both before &
2368 // after of one of the first two types.
2369 // 4). A breakpoint name
2370 // If args is empty, we will use the last created breakpoint (if there is
2371 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002372
Kate Stoneb9c1b512016-09-06 20:57:50 +00002373 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002374
Kate Stoneb9c1b512016-09-06 20:57:50 +00002375 if (args.GetArgumentCount() == 0) {
2376 if (target->GetLastCreatedBreakpoint()) {
2377 valid_ids->AddBreakpointID(BreakpointID(
2378 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2379 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2380 } else {
2381 result.AppendError(
2382 "No breakpoint specified and no last created breakpoint.");
2383 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002384 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002385 return;
2386 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002387
Kate Stoneb9c1b512016-09-06 20:57:50 +00002388 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2389 // directly from the old ARGS to
2390 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead
2391 // generate a list of strings for
2392 // all the breakpoint ids in the range, and shove all of those breakpoint id
2393 // strings into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002394
Kate Stoneb9c1b512016-09-06 20:57:50 +00002395 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2396 result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002397
Kate Stoneb9c1b512016-09-06 20:57:50 +00002398 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2399 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002400
Kate Stoneb9c1b512016-09-06 20:57:50 +00002401 valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2402 temp_args.GetArgumentCount(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002403
Kate Stoneb9c1b512016-09-06 20:57:50 +00002404 // At this point, all of the breakpoint ids that the user passed in have been
2405 // converted to breakpoint IDs
2406 // and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002407
Kate Stoneb9c1b512016-09-06 20:57:50 +00002408 if (result.Succeeded()) {
2409 // Now that we've converted everything from args into a list of breakpoint
2410 // ids, go through our tentative list
2411 // of breakpoint id's and verify that they correspond to valid/currently set
2412 // breakpoints.
2413
2414 const size_t count = valid_ids->GetSize();
2415 for (size_t i = 0; i < count; ++i) {
2416 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2417 Breakpoint *breakpoint =
2418 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2419 if (breakpoint != nullptr) {
2420 const size_t num_locations = breakpoint->GetNumLocations();
2421 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2422 StreamString id_str;
2423 BreakpointID::GetCanonicalReference(
2424 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2425 i = valid_ids->GetSize() + 1;
2426 result.AppendErrorWithFormat(
2427 "'%s' is not a currently valid breakpoint/location id.\n",
2428 id_str.GetData());
2429 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002430 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002431 } else {
2432 i = valid_ids->GetSize() + 1;
2433 result.AppendErrorWithFormat(
2434 "'%d' is not a currently valid breakpoint ID.\n",
2435 cur_bp_id.GetBreakpointID());
2436 result.SetStatus(eReturnStatusFailed);
2437 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002438 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002439 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002440}