blob: 222bb5f4601df83f366e19871bb23572bb7b23d6 [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;
95
96 switch (short_option) {
97 case 'a': {
98 m_load_addr = Args::StringToAddress(execution_context, option_arg,
99 LLDB_INVALID_ADDRESS, &error);
100 } break;
101
102 case 'A':
103 m_all_files = true;
104 break;
105
106 case 'b':
107 m_func_names.push_back(option_arg);
108 m_func_name_type_mask |= eFunctionNameTypeBase;
109 break;
110
111 case 'C': {
112 bool success;
113 m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success);
114 if (!success)
115 error.SetErrorStringWithFormat("invalid column number: %s",
116 option_arg);
117 break;
118 }
119
120 case 'c':
121 m_condition.assign(option_arg);
122 break;
123
124 case 'D':
125 m_use_dummy = true;
126 break;
127
128 case 'E': {
129 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
130
131 switch (language) {
132 case eLanguageTypeC89:
133 case eLanguageTypeC:
134 case eLanguageTypeC99:
135 case eLanguageTypeC11:
136 m_exception_language = eLanguageTypeC;
137 break;
138 case eLanguageTypeC_plus_plus:
139 case eLanguageTypeC_plus_plus_03:
140 case eLanguageTypeC_plus_plus_11:
141 case eLanguageTypeC_plus_plus_14:
142 m_exception_language = eLanguageTypeC_plus_plus;
143 break;
144 case eLanguageTypeObjC:
145 m_exception_language = eLanguageTypeObjC;
146 break;
147 case eLanguageTypeObjC_plus_plus:
148 error.SetErrorStringWithFormat(
149 "Set exception breakpoints separately for c++ and objective-c");
150 break;
151 case eLanguageTypeUnknown:
152 error.SetErrorStringWithFormat(
153 "Unknown language type: '%s' for exception breakpoint",
154 option_arg);
155 break;
156 default:
157 error.SetErrorStringWithFormat(
158 "Unsupported language type: '%s' for exception breakpoint",
159 option_arg);
160 }
161 } break;
162
163 case 'f':
164 m_filenames.AppendIfUnique(FileSpec(option_arg, false));
165 break;
166
167 case 'F':
168 m_func_names.push_back(option_arg);
169 m_func_name_type_mask |= eFunctionNameTypeFull;
170 break;
171
172 case 'h': {
173 bool success;
174 m_catch_bp = Args::StringToBoolean(option_arg, true, &success);
175 if (!success)
176 error.SetErrorStringWithFormat(
177 "Invalid boolean value for on-catch option: '%s'", option_arg);
178 } break;
179
180 case 'H':
181 m_hardware = true;
182 break;
183
184 case 'i':
185 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
186 if (m_ignore_count == UINT32_MAX)
187 error.SetErrorStringWithFormat("invalid ignore count '%s'",
188 option_arg);
189 break;
190
191 case 'K': {
192 bool success;
193 bool value;
194 value = Args::StringToBoolean(option_arg, true, &success);
195 if (value)
196 m_skip_prologue = eLazyBoolYes;
197 else
198 m_skip_prologue = eLazyBoolNo;
199
200 if (!success)
201 error.SetErrorStringWithFormat(
202 "Invalid boolean value for skip prologue option: '%s'",
203 option_arg);
204 } break;
205
206 case 'l': {
207 bool success;
208 m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success);
209 if (!success)
210 error.SetErrorStringWithFormat("invalid line number: %s.",
211 option_arg);
212 break;
213 }
214
215 case 'L':
216 m_language = Language::GetLanguageTypeFromString(option_arg);
217 if (m_language == eLanguageTypeUnknown)
218 error.SetErrorStringWithFormat(
219 "Unknown language type: '%s' for breakpoint", option_arg);
220 break;
221
222 case 'm': {
223 bool success;
224 bool value;
225 value = Args::StringToBoolean(option_arg, true, &success);
226 if (value)
227 m_move_to_nearest_code = eLazyBoolYes;
228 else
229 m_move_to_nearest_code = eLazyBoolNo;
230
231 if (!success)
232 error.SetErrorStringWithFormat(
233 "Invalid boolean value for move-to-nearest-code option: '%s'",
234 option_arg);
235 break;
236 }
237
238 case 'M':
239 m_func_names.push_back(option_arg);
240 m_func_name_type_mask |= eFunctionNameTypeMethod;
241 break;
242
243 case 'n':
244 m_func_names.push_back(option_arg);
245 m_func_name_type_mask |= eFunctionNameTypeAuto;
246 break;
247
248 case 'N':
249 if (BreakpointID::StringIsBreakpointName(option_arg, error))
250 m_breakpoint_names.push_back(option_arg);
251 break;
252
253 case 'R': {
254 lldb::addr_t tmp_offset_addr;
255 tmp_offset_addr =
256 Args::StringToAddress(execution_context, option_arg, 0, &error);
257 if (error.Success())
258 m_offset_addr = tmp_offset_addr;
259 } break;
260
261 case 'o':
262 m_one_shot = true;
263 break;
264
265 case 'O':
266 m_exception_extra_args.AppendArgument("-O");
267 m_exception_extra_args.AppendArgument(option_arg);
268 break;
269
270 case 'p':
271 m_source_text_regexp.assign(option_arg);
272 break;
273
274 case 'q':
275 m_queue_name.assign(option_arg);
276 break;
277
278 case 'r':
279 m_func_regexp.assign(option_arg);
280 break;
281
282 case 's':
283 m_modules.AppendIfUnique(FileSpec(option_arg, false));
284 break;
285
286 case 'S':
287 m_func_names.push_back(option_arg);
288 m_func_name_type_mask |= eFunctionNameTypeSelector;
289 break;
290
291 case 't':
292 m_thread_id =
293 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
294 if (m_thread_id == LLDB_INVALID_THREAD_ID)
295 error.SetErrorStringWithFormat("invalid thread id string '%s'",
296 option_arg);
297 break;
298
299 case 'T':
300 m_thread_name.assign(option_arg);
301 break;
302
303 case 'w': {
304 bool success;
305 m_throw_bp = Args::StringToBoolean(option_arg, true, &success);
306 if (!success)
307 error.SetErrorStringWithFormat(
308 "Invalid boolean value for on-throw option: '%s'", option_arg);
309 } break;
310
311 case 'x':
312 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
313 if (m_thread_id == UINT32_MAX)
314 error.SetErrorStringWithFormat("invalid thread index string '%s'",
315 option_arg);
316 break;
317
318 case 'X':
319 m_source_regex_func_names.insert(option_arg);
320 break;
321
322 default:
323 error.SetErrorStringWithFormat("unrecognized option '%c'",
324 short_option);
325 break;
326 }
327
328 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000329 }
330
Kate Stoneb9c1b512016-09-06 20:57:50 +0000331 void OptionParsingStarting(ExecutionContext *execution_context) override {
332 m_condition.clear();
333 m_filenames.Clear();
334 m_line_num = 0;
335 m_column = 0;
336 m_func_names.clear();
337 m_func_name_type_mask = eFunctionNameTypeNone;
338 m_func_regexp.clear();
339 m_source_text_regexp.clear();
340 m_modules.Clear();
341 m_load_addr = LLDB_INVALID_ADDRESS;
342 m_offset_addr = 0;
343 m_ignore_count = 0;
344 m_thread_id = LLDB_INVALID_THREAD_ID;
345 m_thread_index = UINT32_MAX;
346 m_thread_name.clear();
347 m_queue_name.clear();
348 m_catch_bp = false;
349 m_throw_bp = true;
350 m_hardware = false;
351 m_exception_language = eLanguageTypeUnknown;
352 m_language = lldb::eLanguageTypeUnknown;
353 m_skip_prologue = eLazyBoolCalculate;
354 m_one_shot = false;
355 m_use_dummy = false;
356 m_breakpoint_names.clear();
357 m_all_files = false;
358 m_exception_extra_args.Clear();
359 m_move_to_nearest_code = eLazyBoolCalculate;
360 m_source_regex_func_names.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000361 }
362
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham5a988412012-06-08 21:56:10 +0000364
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 // Options table: Required for subclasses of Options.
Jim Ingham5a988412012-06-08 21:56:10 +0000366
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 static OptionDefinition g_option_table[];
Jim Ingham5a988412012-06-08 21:56:10 +0000368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000370
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371 std::string m_condition;
372 FileSpecList m_filenames;
373 uint32_t m_line_num;
374 uint32_t m_column;
375 std::vector<std::string> m_func_names;
376 std::vector<std::string> m_breakpoint_names;
377 uint32_t m_func_name_type_mask;
378 std::string m_func_regexp;
379 std::string m_source_text_regexp;
380 FileSpecList m_modules;
381 lldb::addr_t m_load_addr;
382 lldb::addr_t m_offset_addr;
383 uint32_t m_ignore_count;
384 lldb::tid_t m_thread_id;
385 uint32_t m_thread_index;
386 std::string m_thread_name;
387 std::string m_queue_name;
388 bool m_catch_bp;
389 bool m_throw_bp;
390 bool m_hardware; // Request to use hardware breakpoints
391 lldb::LanguageType m_exception_language;
392 lldb::LanguageType m_language;
393 LazyBool m_skip_prologue;
394 bool m_one_shot;
395 bool m_use_dummy;
396 bool m_all_files;
397 Args m_exception_extra_args;
398 LazyBool m_move_to_nearest_code;
399 std::unordered_set<std::string> m_source_regex_func_names;
400 };
Jim Ingham5a988412012-06-08 21:56:10 +0000401
402protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000403 bool DoExecute(Args &command, CommandReturnObject &result) override {
404 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000405
Kate Stoneb9c1b512016-09-06 20:57:50 +0000406 if (target == nullptr) {
407 result.AppendError("Invalid target. Must set target before setting "
408 "breakpoints (see 'target create' command).");
409 result.SetStatus(eReturnStatusFailed);
410 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000411 }
412
Kate Stoneb9c1b512016-09-06 20:57:50 +0000413 // The following are the various types of breakpoints that could be set:
414 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
415 // 2). -a [-s -g] (setting breakpoint by address)
416 // 3). -n [-s -g] (setting breakpoint by function name)
417 // 4). -r [-s -g] (setting breakpoint by function name regular
418 // expression)
419 // 5). -p -f (setting a breakpoint by comparing a reg-exp
420 // to source text)
421 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
422 // given language.)
423
424 BreakpointSetType break_type = eSetTypeInvalid;
425
426 if (m_options.m_line_num != 0)
427 break_type = eSetTypeFileAndLine;
428 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
429 break_type = eSetTypeAddress;
430 else if (!m_options.m_func_names.empty())
431 break_type = eSetTypeFunctionName;
432 else if (!m_options.m_func_regexp.empty())
433 break_type = eSetTypeFunctionRegexp;
434 else if (!m_options.m_source_text_regexp.empty())
435 break_type = eSetTypeSourceRegexp;
436 else if (m_options.m_exception_language != eLanguageTypeUnknown)
437 break_type = eSetTypeException;
438
439 Breakpoint *bp = nullptr;
440 FileSpec module_spec;
441 const bool internal = false;
442
443 // If the user didn't specify skip-prologue, having an offset should turn
444 // that off.
445 if (m_options.m_offset_addr != 0 &&
446 m_options.m_skip_prologue == eLazyBoolCalculate)
447 m_options.m_skip_prologue = eLazyBoolNo;
448
449 switch (break_type) {
450 case eSetTypeFileAndLine: // Breakpoint by source position
451 {
452 FileSpec file;
453 const size_t num_files = m_options.m_filenames.GetSize();
454 if (num_files == 0) {
455 if (!GetDefaultFile(target, file, result)) {
456 result.AppendError("No file supplied and no default file available.");
457 result.SetStatus(eReturnStatusFailed);
458 return false;
459 }
460 } else if (num_files > 1) {
461 result.AppendError("Only one file at a time is allowed for file and "
462 "line breakpoints.");
463 result.SetStatus(eReturnStatusFailed);
464 return false;
465 } else
466 file = m_options.m_filenames.GetFileSpecAtIndex(0);
467
468 // Only check for inline functions if
469 LazyBool check_inlines = eLazyBoolCalculate;
470
471 bp = target
472 ->CreateBreakpoint(&(m_options.m_modules), file,
473 m_options.m_line_num, m_options.m_offset_addr,
474 check_inlines, m_options.m_skip_prologue,
475 internal, m_options.m_hardware,
476 m_options.m_move_to_nearest_code)
477 .get();
478 } break;
479
480 case eSetTypeAddress: // Breakpoint by address
481 {
482 // If a shared library has been specified, make an lldb_private::Address
483 // with the library, and
484 // use that. That way the address breakpoint will track the load location
485 // of the library.
486 size_t num_modules_specified = m_options.m_modules.GetSize();
487 if (num_modules_specified == 1) {
488 const FileSpec *file_spec =
489 m_options.m_modules.GetFileSpecPointerAtIndex(0);
490 bp = target
491 ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
492 internal, file_spec,
493 m_options.m_hardware)
494 .get();
495 } else if (num_modules_specified == 0) {
496 bp = target
497 ->CreateBreakpoint(m_options.m_load_addr, internal,
498 m_options.m_hardware)
499 .get();
500 } else {
501 result.AppendError("Only one shared library can be specified for "
502 "address breakpoints.");
503 result.SetStatus(eReturnStatusFailed);
504 return false;
505 }
506 break;
507 }
508 case eSetTypeFunctionName: // Breakpoint by function name
509 {
510 uint32_t name_type_mask = m_options.m_func_name_type_mask;
511
512 if (name_type_mask == 0)
513 name_type_mask = eFunctionNameTypeAuto;
514
515 bp = target
516 ->CreateBreakpoint(
517 &(m_options.m_modules), &(m_options.m_filenames),
518 m_options.m_func_names, name_type_mask, m_options.m_language,
519 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
520 m_options.m_hardware)
521 .get();
522 } break;
523
524 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
525 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000526 {
527 RegularExpression regexp(m_options.m_func_regexp.c_str());
528 if (!regexp.IsValid()) {
529 char err_str[1024];
530 regexp.GetErrorAsCString(err_str, sizeof(err_str));
531 result.AppendErrorWithFormat(
532 "Function name regular expression could not be compiled: \"%s\"",
533 err_str);
534 result.SetStatus(eReturnStatusFailed);
535 return false;
536 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000537
Jim Inghame14dc262016-09-12 23:10:56 +0000538 bp = target
539 ->CreateFuncRegexBreakpoint(
540 &(m_options.m_modules), &(m_options.m_filenames), regexp,
541 m_options.m_language, m_options.m_skip_prologue, internal,
542 m_options.m_hardware)
543 .get();
544 }
545 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
547 {
548 const size_t num_files = m_options.m_filenames.GetSize();
549
550 if (num_files == 0 && !m_options.m_all_files) {
551 FileSpec file;
552 if (!GetDefaultFile(target, file, result)) {
553 result.AppendError(
554 "No files provided and could not find default file.");
555 result.SetStatus(eReturnStatusFailed);
556 return false;
557 } else {
558 m_options.m_filenames.Append(file);
559 }
560 }
561
562 RegularExpression regexp(m_options.m_source_text_regexp.c_str());
563 if (!regexp.IsValid()) {
564 char err_str[1024];
565 regexp.GetErrorAsCString(err_str, sizeof(err_str));
566 result.AppendErrorWithFormat(
567 "Source text regular expression could not be compiled: \"%s\"",
568 err_str);
569 result.SetStatus(eReturnStatusFailed);
570 return false;
571 }
572 bp = target
573 ->CreateSourceRegexBreakpoint(
574 &(m_options.m_modules), &(m_options.m_filenames),
575 m_options.m_source_regex_func_names, regexp, internal,
576 m_options.m_hardware, m_options.m_move_to_nearest_code)
577 .get();
578 } break;
579 case eSetTypeException: {
580 Error precond_error;
581 bp = target
582 ->CreateExceptionBreakpoint(
583 m_options.m_exception_language, m_options.m_catch_bp,
584 m_options.m_throw_bp, internal,
585 &m_options.m_exception_extra_args, &precond_error)
586 .get();
587 if (precond_error.Fail()) {
588 result.AppendErrorWithFormat(
589 "Error setting extra exception arguments: %s",
590 precond_error.AsCString());
591 target->RemoveBreakpointByID(bp->GetID());
592 result.SetStatus(eReturnStatusFailed);
593 return false;
594 }
595 } break;
596 default:
597 break;
598 }
599
600 // Now set the various options that were passed in:
601 if (bp) {
602 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
603 bp->SetThreadID(m_options.m_thread_id);
604
605 if (m_options.m_thread_index != UINT32_MAX)
606 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
607
608 if (!m_options.m_thread_name.empty())
609 bp->GetOptions()->GetThreadSpec()->SetName(
610 m_options.m_thread_name.c_str());
611
612 if (!m_options.m_queue_name.empty())
613 bp->GetOptions()->GetThreadSpec()->SetQueueName(
614 m_options.m_queue_name.c_str());
615
616 if (m_options.m_ignore_count != 0)
617 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
618
619 if (!m_options.m_condition.empty())
620 bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
621
622 if (!m_options.m_breakpoint_names.empty()) {
623 Error error; // We don't need to check the error here, since the option
624 // parser checked it...
625 for (auto name : m_options.m_breakpoint_names)
626 bp->AddName(name.c_str(), error);
627 }
628
629 bp->SetOneShot(m_options.m_one_shot);
630 }
631
632 if (bp) {
633 Stream &output_stream = result.GetOutputStream();
634 const bool show_locations = false;
635 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
636 show_locations);
637 if (target == m_interpreter.GetDebugger().GetDummyTarget())
638 output_stream.Printf("Breakpoint set in dummy target, will get copied "
639 "into future targets.\n");
640 else {
641 // Don't print out this warning for exception breakpoints. They can get
642 // set before the target
643 // is set, but we won't know how to actually set the breakpoint till we
644 // run.
645 if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
646 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
647 "actual locations.\n");
648 }
649 }
650 result.SetStatus(eReturnStatusSuccessFinishResult);
651 } else if (!bp) {
652 result.AppendError("Breakpoint creation failed: No breakpoint created.");
653 result.SetStatus(eReturnStatusFailed);
654 }
655
656 return result.Succeeded();
657 }
658
Jim Ingham5a988412012-06-08 21:56:10 +0000659private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000660 bool GetDefaultFile(Target *target, FileSpec &file,
661 CommandReturnObject &result) {
662 uint32_t default_line;
663 // First use the Source Manager's default file.
664 // Then use the current stack frame's file.
665 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
666 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
667 if (cur_frame == nullptr) {
668 result.AppendError(
669 "No selected frame to use to find the default file.");
670 result.SetStatus(eReturnStatusFailed);
671 return false;
672 } else if (!cur_frame->HasDebugInformation()) {
673 result.AppendError("Cannot use the selected frame to find the default "
674 "file, it has no debug info.");
675 result.SetStatus(eReturnStatusFailed);
676 return false;
677 } else {
678 const SymbolContext &sc =
679 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
680 if (sc.line_entry.file) {
681 file = sc.line_entry.file;
682 } else {
683 result.AppendError("Can't find the file for the selected frame to "
684 "use as the default file.");
685 result.SetStatus(eReturnStatusFailed);
686 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000687 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000688 }
Jim Ingham5a988412012-06-08 21:56:10 +0000689 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000690 return true;
691 }
692
693 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000694};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000695
Johnny Chen6943e7c2012-05-08 00:43:20 +0000696// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
697// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000698#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
699#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
700#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
701#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
702#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
703#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
Jim Ingham87df91b2011-09-23 00:54:11 +0000704
Kate Stoneb9c1b512016-09-06 20:57:50 +0000705OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
706 {
707 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +0000708 {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 "
709 "multiple times to specify multiple shared libraries."},
710 {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." },
711 {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." },
712 {LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
713 {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."},
714 {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."},
715 {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 "
716 "argument."},
717 {LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints."},
718 {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 "
719 "this argument."},
720 {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 "
721 "lldb only looks for files that are #included if they use the standard include "
722 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
723 "#included, set target.inline-breakpoint-strategy to \"always\"."},
724 {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 +0000725
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000726 // Comment out this option for the moment, as we don't actually use it, but will in the future.
727 // This way users won't see it, but the infrastructure is left in place.
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000728 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000729 // "Set the breakpoint by source location at this particular column."},
730
Kate Stoneac9c3a62016-08-26 23:28:47 +0000731 {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 "
732 "a particular binary, then the address will be converted to a \"file\" "
733 "address, so that the breakpoint will track that binary+offset no matter where "
734 "the binary eventually loads. Alternately, if you also specify the module - "
735 "with the -s option - then the address will be treated as a file address in "
736 "that module, and resolved accordingly. Again, this will allow lldb to track "
737 "that offset on subsequent reloads. The module need not have been loaded at "
738 "the time you specify this breakpoint, and will get resolved when the module "
739 "is loaded."},
740 {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 "
741 "one breakpoint for multiple names"},
742 {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 "
743 "functions. Can be repeated multiple times."},
744 {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 "
745 "namespaces and all arguments, and for Objective C this means a full function "
746 "prototype with class and selector. Can be repeated multiple times to make "
747 "one breakpoint for multiple names."},
748 {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 "
749 "make one breakpoint for multiple Selectors."},
750 {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 "
751 "make one breakpoint for multiple methods."},
752 {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 "
753 "the function name(s)."},
754 {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 "
755 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
756 "symbols."},
757 {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 "
758 "against the source text in a source file or files specified with the -f "
759 "option. The -f option can be specified more than once. If no source files "
760 "are specified, uses the current \"default source file\". If you want to "
761 "match against all source files, pass the \"--all-files\" option."},
762 {LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches."},
763 {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 "
764 "options, on throw but not catch.)"},
765 {LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW."},
766 {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 +0000767
Jim Inghama72b31c2015-04-22 19:42:18 +0000768// Don't add this option till it actually does something useful...
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000769// { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
Jim Inghama72b31c2015-04-22 19:42:18 +0000770// "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" },
771
Kate Stoneac9c3a62016-08-26 23:28:47 +0000772 {LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
773 "(note: currently only implemented for setting breakpoints on identifiers). "
774 "If not set the target.language setting is used."},
775 {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. "
776 "If not set the target.skip-prologue setting is used."},
777 {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, "
778 "which prime new targets."},
779 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint."},
780 {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 +0000781 "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 +0000782 {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 "
783 "setting is used."},
784 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000785 // clang-format on
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000786};
787
Jim Ingham5a988412012-06-08 21:56:10 +0000788//-------------------------------------------------------------------------
789// CommandObjectBreakpointModify
790//-------------------------------------------------------------------------
791#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000792
Kate Stoneb9c1b512016-09-06 20:57:50 +0000793class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000794public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000795 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
796 : CommandObjectParsed(interpreter, "breakpoint modify",
797 "Modify the options on a breakpoint or set of "
798 "breakpoints in the executable. "
799 "If no breakpoint is specified, acts on the last "
800 "created breakpoint. "
801 "With the exception of -e, -d and -i, passing an "
802 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000803 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000804 m_options() {
805 CommandArgumentEntry arg;
806 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
807 eArgTypeBreakpointIDRange);
808 // Add the entry for the first argument for this command to the object's
809 // arguments vector.
810 m_arguments.push_back(arg);
811 }
812
813 ~CommandObjectBreakpointModify() override = default;
814
815 Options *GetOptions() override { return &m_options; }
816
817 class CommandOptions : public Options {
818 public:
819 CommandOptions()
820 : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
821 m_thread_id_passed(false), m_thread_index(UINT32_MAX),
822 m_thread_index_passed(false), m_thread_name(), m_queue_name(),
823 m_condition(), m_one_shot(false), m_enable_passed(false),
824 m_enable_value(false), m_name_passed(false), m_queue_passed(false),
825 m_condition_passed(false), m_one_shot_passed(false),
826 m_use_dummy(false) {}
827
828 ~CommandOptions() override = default;
829
830 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
831 ExecutionContext *execution_context) override {
832 Error error;
833 const int short_option = m_getopt_table[option_idx].val;
834
835 switch (short_option) {
836 case 'c':
837 if (option_arg != nullptr)
838 m_condition.assign(option_arg);
839 else
840 m_condition.clear();
841 m_condition_passed = true;
842 break;
843 case 'd':
844 m_enable_passed = true;
845 m_enable_value = false;
846 break;
847 case 'D':
848 m_use_dummy = true;
849 break;
850 case 'e':
851 m_enable_passed = true;
852 m_enable_value = true;
853 break;
854 case 'i':
855 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
856 if (m_ignore_count == UINT32_MAX)
857 error.SetErrorStringWithFormat("invalid ignore count '%s'",
858 option_arg);
859 break;
860 case 'o': {
861 bool value, success;
862 value = Args::StringToBoolean(option_arg, false, &success);
863 if (success) {
864 m_one_shot_passed = true;
865 m_one_shot = value;
866 } else
867 error.SetErrorStringWithFormat(
868 "invalid boolean value '%s' passed for -o option", option_arg);
869 } break;
870 case 't':
871 if (option_arg[0] == '\0') {
872 m_thread_id = LLDB_INVALID_THREAD_ID;
873 m_thread_id_passed = true;
874 } else {
875 m_thread_id =
876 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
877 if (m_thread_id == LLDB_INVALID_THREAD_ID)
878 error.SetErrorStringWithFormat("invalid thread id string '%s'",
879 option_arg);
880 else
881 m_thread_id_passed = true;
882 }
883 break;
884 case 'T':
885 if (option_arg != nullptr)
886 m_thread_name.assign(option_arg);
887 else
888 m_thread_name.clear();
889 m_name_passed = true;
890 break;
891 case 'q':
892 if (option_arg != nullptr)
893 m_queue_name.assign(option_arg);
894 else
895 m_queue_name.clear();
896 m_queue_passed = true;
897 break;
898 case 'x':
899 if (option_arg[0] == '\n') {
900 m_thread_index = UINT32_MAX;
901 m_thread_index_passed = true;
902 } else {
903 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
904 if (m_thread_id == UINT32_MAX)
905 error.SetErrorStringWithFormat("invalid thread index string '%s'",
906 option_arg);
907 else
908 m_thread_index_passed = true;
909 }
910 break;
911 default:
912 error.SetErrorStringWithFormat("unrecognized option '%c'",
913 short_option);
914 break;
915 }
916
917 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000918 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000919
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920 void OptionParsingStarting(ExecutionContext *execution_context) override {
921 m_ignore_count = 0;
922 m_thread_id = LLDB_INVALID_THREAD_ID;
923 m_thread_id_passed = false;
924 m_thread_index = UINT32_MAX;
925 m_thread_index_passed = false;
926 m_thread_name.clear();
927 m_queue_name.clear();
928 m_condition.clear();
929 m_one_shot = false;
930 m_enable_passed = false;
931 m_queue_passed = false;
932 m_name_passed = false;
933 m_condition_passed = false;
934 m_one_shot_passed = false;
935 m_use_dummy = false;
Jim Ingham5a988412012-06-08 21:56:10 +0000936 }
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000937
Kate Stoneb9c1b512016-09-06 20:57:50 +0000938 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Greg Clayton0c5cd902010-06-28 21:30:43 +0000939
Kate Stoneb9c1b512016-09-06 20:57:50 +0000940 // Options table: Required for subclasses of Options.
Greg Clayton0c5cd902010-06-28 21:30:43 +0000941
Kate Stoneb9c1b512016-09-06 20:57:50 +0000942 static OptionDefinition g_option_table[];
Greg Claytone02b8502010-10-12 04:29:14 +0000943
Kate Stoneb9c1b512016-09-06 20:57:50 +0000944 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000945
Kate Stoneb9c1b512016-09-06 20:57:50 +0000946 uint32_t m_ignore_count;
947 lldb::tid_t m_thread_id;
948 bool m_thread_id_passed;
949 uint32_t m_thread_index;
950 bool m_thread_index_passed;
951 std::string m_thread_name;
952 std::string m_queue_name;
953 std::string m_condition;
954 bool m_one_shot;
955 bool m_enable_passed;
956 bool m_enable_value;
957 bool m_name_passed;
958 bool m_queue_passed;
959 bool m_condition_passed;
960 bool m_one_shot_passed;
961 bool m_use_dummy;
962 };
Jim Ingham5a988412012-06-08 21:56:10 +0000963
964protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000965 bool DoExecute(Args &command, CommandReturnObject &result) override {
966 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
967 if (target == nullptr) {
968 result.AppendError("Invalid target. No existing target or breakpoints.");
969 result.SetStatus(eReturnStatusFailed);
970 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000971 }
972
Kate Stoneb9c1b512016-09-06 20:57:50 +0000973 std::unique_lock<std::recursive_mutex> lock;
974 target->GetBreakpointList().GetListMutex(lock);
975
976 BreakpointIDList valid_bp_ids;
977
978 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
979 command, target, result, &valid_bp_ids);
980
981 if (result.Succeeded()) {
982 const size_t count = valid_bp_ids.GetSize();
983 for (size_t i = 0; i < count; ++i) {
984 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
985
986 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
987 Breakpoint *bp =
988 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
989 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
990 BreakpointLocation *location =
991 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
992 if (location) {
993 if (m_options.m_thread_id_passed)
994 location->SetThreadID(m_options.m_thread_id);
995
996 if (m_options.m_thread_index_passed)
997 location->SetThreadIndex(m_options.m_thread_index);
998
999 if (m_options.m_name_passed)
1000 location->SetThreadName(m_options.m_thread_name.c_str());
1001
1002 if (m_options.m_queue_passed)
1003 location->SetQueueName(m_options.m_queue_name.c_str());
1004
1005 if (m_options.m_ignore_count != 0)
1006 location->SetIgnoreCount(m_options.m_ignore_count);
1007
1008 if (m_options.m_enable_passed)
1009 location->SetEnabled(m_options.m_enable_value);
1010
1011 if (m_options.m_condition_passed)
1012 location->SetCondition(m_options.m_condition.c_str());
1013 }
1014 } else {
1015 if (m_options.m_thread_id_passed)
1016 bp->SetThreadID(m_options.m_thread_id);
1017
1018 if (m_options.m_thread_index_passed)
1019 bp->SetThreadIndex(m_options.m_thread_index);
1020
1021 if (m_options.m_name_passed)
1022 bp->SetThreadName(m_options.m_thread_name.c_str());
1023
1024 if (m_options.m_queue_passed)
1025 bp->SetQueueName(m_options.m_queue_name.c_str());
1026
1027 if (m_options.m_ignore_count != 0)
1028 bp->SetIgnoreCount(m_options.m_ignore_count);
1029
1030 if (m_options.m_enable_passed)
1031 bp->SetEnabled(m_options.m_enable_value);
1032
1033 if (m_options.m_condition_passed)
1034 bp->SetCondition(m_options.m_condition.c_str());
1035 }
1036 }
1037 }
1038 }
1039
1040 return result.Succeeded();
1041 }
1042
Jim Ingham5a988412012-06-08 21:56:10 +00001043private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001044 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001045};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001046
Jim Ingham5a988412012-06-08 21:56:10 +00001047#pragma mark Modify::CommandOptions
1048OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001049 CommandObjectBreakpointModify::CommandOptions::g_option_table[] = {
1050 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001051 {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."},
1052 {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."},
1053 {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."},
1054 {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."},
1055 {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."},
1056 {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."},
1057 {LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
1058 {LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint."},
1059 {LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint."},
1060 {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."},
1061 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001062 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001063};
1064
1065//-------------------------------------------------------------------------
1066// CommandObjectBreakpointEnable
1067//-------------------------------------------------------------------------
1068#pragma mark Enable
1069
Kate Stoneb9c1b512016-09-06 20:57:50 +00001070class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001071public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001072 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1073 : CommandObjectParsed(interpreter, "enable",
1074 "Enable the specified disabled breakpoint(s). If "
1075 "no breakpoints are specified, enable all of them.",
1076 nullptr) {
1077 CommandArgumentEntry arg;
1078 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1079 eArgTypeBreakpointIDRange);
1080 // Add the entry for the first argument for this command to the object's
1081 // arguments vector.
1082 m_arguments.push_back(arg);
1083 }
Jim Ingham5a988412012-06-08 21:56:10 +00001084
Kate Stoneb9c1b512016-09-06 20:57:50 +00001085 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001086
1087protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001088 bool DoExecute(Args &command, CommandReturnObject &result) override {
1089 Target *target = GetSelectedOrDummyTarget();
1090 if (target == nullptr) {
1091 result.AppendError("Invalid target. No existing target or breakpoints.");
1092 result.SetStatus(eReturnStatusFailed);
1093 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001094 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001095
1096 std::unique_lock<std::recursive_mutex> lock;
1097 target->GetBreakpointList().GetListMutex(lock);
1098
1099 const BreakpointList &breakpoints = target->GetBreakpointList();
1100
1101 size_t num_breakpoints = breakpoints.GetSize();
1102
1103 if (num_breakpoints == 0) {
1104 result.AppendError("No breakpoints exist to be enabled.");
1105 result.SetStatus(eReturnStatusFailed);
1106 return false;
1107 }
1108
1109 if (command.GetArgumentCount() == 0) {
1110 // No breakpoint selected; enable all currently set breakpoints.
1111 target->EnableAllBreakpoints();
1112 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1113 " breakpoints)\n",
1114 (uint64_t)num_breakpoints);
1115 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1116 } else {
1117 // Particular breakpoint selected; enable that breakpoint.
1118 BreakpointIDList valid_bp_ids;
1119 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1120 command, target, result, &valid_bp_ids);
1121
1122 if (result.Succeeded()) {
1123 int enable_count = 0;
1124 int loc_count = 0;
1125 const size_t count = valid_bp_ids.GetSize();
1126 for (size_t i = 0; i < count; ++i) {
1127 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1128
1129 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1130 Breakpoint *breakpoint =
1131 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1132 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1133 BreakpointLocation *location =
1134 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1135 if (location) {
1136 location->SetEnabled(true);
1137 ++loc_count;
1138 }
1139 } else {
1140 breakpoint->SetEnabled(true);
1141 ++enable_count;
1142 }
1143 }
1144 }
1145 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1146 enable_count + loc_count);
1147 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1148 }
1149 }
1150
1151 return result.Succeeded();
1152 }
Jim Ingham5a988412012-06-08 21:56:10 +00001153};
1154
1155//-------------------------------------------------------------------------
1156// CommandObjectBreakpointDisable
1157//-------------------------------------------------------------------------
1158#pragma mark Disable
1159
Kate Stoneb9c1b512016-09-06 20:57:50 +00001160class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001161public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001162 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1163 : CommandObjectParsed(
1164 interpreter, "breakpoint disable",
1165 "Disable the specified breakpoint(s) without deleting "
1166 "them. If none are specified, disable all "
1167 "breakpoints.",
1168 nullptr) {
1169 SetHelpLong(
1170 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001171If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001172 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001173
Kate Stone7428a182016-07-14 22:03:10 +00001174)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001175 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001176regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001177 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001178
1179 (lldb) break disable 1
1180 (lldb) break enable 1.1
1181
1182execution will NOT stop at location 1.1. To achieve that, type:
1183
1184 (lldb) break disable 1.*
1185 (lldb) break enable 1.1
1186
Kate Stone7428a182016-07-14 22:03:10 +00001187)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001188 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001189the second re-enables the first location.");
1190
Kate Stoneb9c1b512016-09-06 20:57:50 +00001191 CommandArgumentEntry arg;
1192 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1193 eArgTypeBreakpointIDRange);
1194 // Add the entry for the first argument for this command to the object's
1195 // arguments vector.
1196 m_arguments.push_back(arg);
1197 }
Jim Ingham5a988412012-06-08 21:56:10 +00001198
Kate Stoneb9c1b512016-09-06 20:57:50 +00001199 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001200
1201protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001202 bool DoExecute(Args &command, CommandReturnObject &result) override {
1203 Target *target = GetSelectedOrDummyTarget();
1204 if (target == nullptr) {
1205 result.AppendError("Invalid target. No existing target or breakpoints.");
1206 result.SetStatus(eReturnStatusFailed);
1207 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001208 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001209
1210 std::unique_lock<std::recursive_mutex> lock;
1211 target->GetBreakpointList().GetListMutex(lock);
1212
1213 const BreakpointList &breakpoints = target->GetBreakpointList();
1214 size_t num_breakpoints = breakpoints.GetSize();
1215
1216 if (num_breakpoints == 0) {
1217 result.AppendError("No breakpoints exist to be disabled.");
1218 result.SetStatus(eReturnStatusFailed);
1219 return false;
1220 }
1221
1222 if (command.GetArgumentCount() == 0) {
1223 // No breakpoint selected; disable all currently set breakpoints.
1224 target->DisableAllBreakpoints();
1225 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1226 " breakpoints)\n",
1227 (uint64_t)num_breakpoints);
1228 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1229 } else {
1230 // Particular breakpoint selected; disable that breakpoint.
1231 BreakpointIDList valid_bp_ids;
1232
1233 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1234 command, target, result, &valid_bp_ids);
1235
1236 if (result.Succeeded()) {
1237 int disable_count = 0;
1238 int loc_count = 0;
1239 const size_t count = valid_bp_ids.GetSize();
1240 for (size_t i = 0; i < count; ++i) {
1241 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1242
1243 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1244 Breakpoint *breakpoint =
1245 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1246 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1247 BreakpointLocation *location =
1248 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1249 if (location) {
1250 location->SetEnabled(false);
1251 ++loc_count;
1252 }
1253 } else {
1254 breakpoint->SetEnabled(false);
1255 ++disable_count;
1256 }
1257 }
1258 }
1259 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1260 disable_count + loc_count);
1261 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1262 }
1263 }
1264
1265 return result.Succeeded();
1266 }
Jim Ingham5a988412012-06-08 21:56:10 +00001267};
1268
1269//-------------------------------------------------------------------------
1270// CommandObjectBreakpointList
1271//-------------------------------------------------------------------------
1272#pragma mark List
1273
Kate Stoneb9c1b512016-09-06 20:57:50 +00001274class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001275public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001276 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1277 : CommandObjectParsed(
1278 interpreter, "breakpoint list",
1279 "List some or all breakpoints at configurable levels of detail.",
1280 nullptr),
1281 m_options() {
1282 CommandArgumentEntry arg;
1283 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001284
Kate Stoneb9c1b512016-09-06 20:57:50 +00001285 // Define the first (and only) variant of this arg.
1286 bp_id_arg.arg_type = eArgTypeBreakpointID;
1287 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001288
Kate Stoneb9c1b512016-09-06 20:57:50 +00001289 // There is only one variant this argument could be; put it into the
1290 // argument entry.
1291 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001292
Kate Stoneb9c1b512016-09-06 20:57:50 +00001293 // Push the data for the first argument into the m_arguments vector.
1294 m_arguments.push_back(arg);
1295 }
1296
1297 ~CommandObjectBreakpointList() override = default;
1298
1299 Options *GetOptions() override { return &m_options; }
1300
1301 class CommandOptions : public Options {
1302 public:
1303 CommandOptions()
1304 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001305 }
1306
Kate Stoneb9c1b512016-09-06 20:57:50 +00001307 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001308
Kate Stoneb9c1b512016-09-06 20:57:50 +00001309 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1310 ExecutionContext *execution_context) override {
1311 Error error;
1312 const int short_option = m_getopt_table[option_idx].val;
1313
1314 switch (short_option) {
1315 case 'b':
1316 m_level = lldb::eDescriptionLevelBrief;
1317 break;
1318 case 'D':
1319 m_use_dummy = true;
1320 break;
1321 case 'f':
1322 m_level = lldb::eDescriptionLevelFull;
1323 break;
1324 case 'v':
1325 m_level = lldb::eDescriptionLevelVerbose;
1326 break;
1327 case 'i':
1328 m_internal = true;
1329 break;
1330 default:
1331 error.SetErrorStringWithFormat("unrecognized option '%c'",
1332 short_option);
1333 break;
1334 }
1335
1336 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001337 }
Jim Ingham5a988412012-06-08 21:56:10 +00001338
Kate Stoneb9c1b512016-09-06 20:57:50 +00001339 void OptionParsingStarting(ExecutionContext *execution_context) override {
1340 m_level = lldb::eDescriptionLevelFull;
1341 m_internal = false;
1342 m_use_dummy = false;
1343 }
Jim Ingham5a988412012-06-08 21:56:10 +00001344
Kate Stoneb9c1b512016-09-06 20:57:50 +00001345 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham5a988412012-06-08 21:56:10 +00001346
Kate Stoneb9c1b512016-09-06 20:57:50 +00001347 // Options table: Required for subclasses of Options.
Jim Ingham5a988412012-06-08 21:56:10 +00001348
Kate Stoneb9c1b512016-09-06 20:57:50 +00001349 static OptionDefinition g_option_table[];
Jim Ingham5a988412012-06-08 21:56:10 +00001350
Kate Stoneb9c1b512016-09-06 20:57:50 +00001351 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001352
Kate Stoneb9c1b512016-09-06 20:57:50 +00001353 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001354
Kate Stoneb9c1b512016-09-06 20:57:50 +00001355 bool m_internal;
1356 bool m_use_dummy;
1357 };
Jim Ingham5a988412012-06-08 21:56:10 +00001358
1359protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001360 bool DoExecute(Args &command, CommandReturnObject &result) override {
1361 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001362
Kate Stoneb9c1b512016-09-06 20:57:50 +00001363 if (target == nullptr) {
1364 result.AppendError("Invalid target. No current target or breakpoints.");
1365 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1366 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001367 }
1368
Kate Stoneb9c1b512016-09-06 20:57:50 +00001369 const BreakpointList &breakpoints =
1370 target->GetBreakpointList(m_options.m_internal);
1371 std::unique_lock<std::recursive_mutex> lock;
1372 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1373
1374 size_t num_breakpoints = breakpoints.GetSize();
1375
1376 if (num_breakpoints == 0) {
1377 result.AppendMessage("No breakpoints currently set.");
1378 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1379 return true;
1380 }
1381
1382 Stream &output_stream = result.GetOutputStream();
1383
1384 if (command.GetArgumentCount() == 0) {
1385 // No breakpoint selected; show info about all currently set breakpoints.
1386 result.AppendMessage("Current breakpoints:");
1387 for (size_t i = 0; i < num_breakpoints; ++i) {
1388 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1389 AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
1390 }
1391 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1392 } else {
1393 // Particular breakpoints selected; show info about that breakpoint.
1394 BreakpointIDList valid_bp_ids;
1395 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1396 command, target, result, &valid_bp_ids);
1397
1398 if (result.Succeeded()) {
1399 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1400 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1401 Breakpoint *breakpoint =
1402 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1403 AddBreakpointDescription(&output_stream, breakpoint,
1404 m_options.m_level);
1405 }
1406 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1407 } else {
1408 result.AppendError("Invalid breakpoint ID.");
1409 result.SetStatus(eReturnStatusFailed);
1410 }
1411 }
1412
1413 return result.Succeeded();
1414 }
1415
Jim Ingham5a988412012-06-08 21:56:10 +00001416private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001417 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001418};
1419
1420#pragma mark List::CommandOptions
Kate Stoneb9c1b512016-09-06 20:57:50 +00001421OptionDefinition CommandObjectBreakpointList::CommandOptions::g_option_table[] =
1422 {
1423 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001424 {LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1425 {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 +00001426 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1427 // But I need to see it for now, and don't want to wait.
Kate Stoneac9c3a62016-08-26 23:28:47 +00001428 {LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations."},
1429 {LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)."},
1430 {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."},
1431 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001432 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001433};
1434
1435//-------------------------------------------------------------------------
1436// CommandObjectBreakpointClear
1437//-------------------------------------------------------------------------
1438#pragma mark Clear
1439
Kate Stoneb9c1b512016-09-06 20:57:50 +00001440class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001441public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001442 typedef enum BreakpointClearType {
1443 eClearTypeInvalid,
1444 eClearTypeFileAndLine
1445 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001446
Kate Stoneb9c1b512016-09-06 20:57:50 +00001447 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1448 : CommandObjectParsed(interpreter, "breakpoint clear",
1449 "Delete or disable breakpoints matching the "
1450 "specified source file and line.",
1451 "breakpoint clear <cmd-options>"),
1452 m_options() {}
1453
1454 ~CommandObjectBreakpointClear() override = default;
1455
1456 Options *GetOptions() override { return &m_options; }
1457
1458 class CommandOptions : public Options {
1459 public:
1460 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1461
1462 ~CommandOptions() override = default;
1463
1464 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1465 ExecutionContext *execution_context) override {
1466 Error error;
1467 const int short_option = m_getopt_table[option_idx].val;
1468
1469 switch (short_option) {
1470 case 'f':
1471 m_filename.assign(option_arg);
1472 break;
1473
1474 case 'l':
1475 m_line_num = StringConvert::ToUInt32(option_arg, 0);
1476 break;
1477
1478 default:
1479 error.SetErrorStringWithFormat("unrecognized option '%c'",
1480 short_option);
1481 break;
1482 }
1483
1484 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001485 }
1486
Kate Stoneb9c1b512016-09-06 20:57:50 +00001487 void OptionParsingStarting(ExecutionContext *execution_context) override {
1488 m_filename.clear();
1489 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001490 }
1491
Kate Stoneb9c1b512016-09-06 20:57:50 +00001492 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham5a988412012-06-08 21:56:10 +00001493
Kate Stoneb9c1b512016-09-06 20:57:50 +00001494 // Options table: Required for subclasses of Options.
Jim Ingham5a988412012-06-08 21:56:10 +00001495
Kate Stoneb9c1b512016-09-06 20:57:50 +00001496 static OptionDefinition g_option_table[];
Jim Ingham5a988412012-06-08 21:56:10 +00001497
Kate Stoneb9c1b512016-09-06 20:57:50 +00001498 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001499
Kate Stoneb9c1b512016-09-06 20:57:50 +00001500 std::string m_filename;
1501 uint32_t m_line_num;
1502 };
Jim Ingham5a988412012-06-08 21:56:10 +00001503
1504protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001505 bool DoExecute(Args &command, CommandReturnObject &result) override {
1506 Target *target = GetSelectedOrDummyTarget();
1507 if (target == nullptr) {
1508 result.AppendError("Invalid target. No existing target or breakpoints.");
1509 result.SetStatus(eReturnStatusFailed);
1510 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001511 }
1512
Kate Stoneb9c1b512016-09-06 20:57:50 +00001513 // The following are the various types of breakpoints that could be cleared:
1514 // 1). -f -l (clearing breakpoint by source location)
1515
1516 BreakpointClearType break_type = eClearTypeInvalid;
1517
1518 if (m_options.m_line_num != 0)
1519 break_type = eClearTypeFileAndLine;
1520
1521 std::unique_lock<std::recursive_mutex> lock;
1522 target->GetBreakpointList().GetListMutex(lock);
1523
1524 BreakpointList &breakpoints = target->GetBreakpointList();
1525 size_t num_breakpoints = breakpoints.GetSize();
1526
1527 // Early return if there's no breakpoint at all.
1528 if (num_breakpoints == 0) {
1529 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1530 result.SetStatus(eReturnStatusFailed);
1531 return result.Succeeded();
1532 }
1533
1534 // Find matching breakpoints and delete them.
1535
1536 // First create a copy of all the IDs.
1537 std::vector<break_id_t> BreakIDs;
1538 for (size_t i = 0; i < num_breakpoints; ++i)
1539 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1540
1541 int num_cleared = 0;
1542 StreamString ss;
1543 switch (break_type) {
1544 case eClearTypeFileAndLine: // Breakpoint by source position
1545 {
1546 const ConstString filename(m_options.m_filename.c_str());
1547 BreakpointLocationCollection loc_coll;
1548
1549 for (size_t i = 0; i < num_breakpoints; ++i) {
1550 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1551
1552 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1553 // If the collection size is 0, it's a full match and we can just
1554 // remove the breakpoint.
1555 if (loc_coll.GetSize() == 0) {
1556 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1557 ss.EOL();
1558 target->RemoveBreakpointByID(bp->GetID());
1559 ++num_cleared;
1560 }
1561 }
1562 }
1563 } break;
1564
1565 default:
1566 break;
1567 }
1568
1569 if (num_cleared > 0) {
1570 Stream &output_stream = result.GetOutputStream();
1571 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1572 output_stream << ss.GetData();
1573 output_stream.EOL();
1574 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1575 } else {
1576 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1577 result.SetStatus(eReturnStatusFailed);
1578 }
1579
1580 return result.Succeeded();
1581 }
1582
Jim Ingham5a988412012-06-08 21:56:10 +00001583private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001584 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001585};
1586
1587#pragma mark Clear::CommandOptions
1588
1589OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001590 CommandObjectBreakpointClear::CommandOptions::g_option_table[] = {
1591 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001592 {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file."},
1593 {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line."},
1594 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001595 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001596};
1597
1598//-------------------------------------------------------------------------
1599// CommandObjectBreakpointDelete
1600//-------------------------------------------------------------------------
1601#pragma mark Delete
1602
Kate Stoneb9c1b512016-09-06 20:57:50 +00001603class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001604public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001605 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1606 : CommandObjectParsed(interpreter, "breakpoint delete",
1607 "Delete the specified breakpoint(s). If no "
1608 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001609 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001610 m_options() {
1611 CommandArgumentEntry arg;
1612 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1613 eArgTypeBreakpointIDRange);
1614 // Add the entry for the first argument for this command to the object's
1615 // arguments vector.
1616 m_arguments.push_back(arg);
1617 }
1618
1619 ~CommandObjectBreakpointDelete() override = default;
1620
1621 Options *GetOptions() override { return &m_options; }
1622
1623 class CommandOptions : public Options {
1624 public:
1625 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1626
1627 ~CommandOptions() override = default;
1628
1629 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1630 ExecutionContext *execution_context) override {
1631 Error error;
1632 const int short_option = m_getopt_table[option_idx].val;
1633
1634 switch (short_option) {
1635 case 'f':
1636 m_force = true;
1637 break;
1638
1639 case 'D':
1640 m_use_dummy = true;
1641 break;
1642
1643 default:
1644 error.SetErrorStringWithFormat("unrecognized option '%c'",
1645 short_option);
1646 break;
1647 }
1648
1649 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001650 }
1651
Kate Stoneb9c1b512016-09-06 20:57:50 +00001652 void OptionParsingStarting(ExecutionContext *execution_context) override {
1653 m_use_dummy = false;
1654 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001655 }
1656
Kate Stoneb9c1b512016-09-06 20:57:50 +00001657 const OptionDefinition *GetDefinitions() override { return g_option_table; }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001658
Kate Stoneb9c1b512016-09-06 20:57:50 +00001659 // Options table: Required for subclasses of Options.
Jim Ingham33df7cd2014-12-06 01:28:03 +00001660
Kate Stoneb9c1b512016-09-06 20:57:50 +00001661 static OptionDefinition g_option_table[];
Jim Ingham33df7cd2014-12-06 01:28:03 +00001662
Kate Stoneb9c1b512016-09-06 20:57:50 +00001663 // Instance variables to hold the values for command options.
1664 bool m_use_dummy;
1665 bool m_force;
1666 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001667
Jim Ingham5a988412012-06-08 21:56:10 +00001668protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001669 bool DoExecute(Args &command, CommandReturnObject &result) override {
1670 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001671
Kate Stoneb9c1b512016-09-06 20:57:50 +00001672 if (target == nullptr) {
1673 result.AppendError("Invalid target. No existing target or breakpoints.");
1674 result.SetStatus(eReturnStatusFailed);
1675 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001676 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001677
Kate Stoneb9c1b512016-09-06 20:57:50 +00001678 std::unique_lock<std::recursive_mutex> lock;
1679 target->GetBreakpointList().GetListMutex(lock);
1680
1681 const BreakpointList &breakpoints = target->GetBreakpointList();
1682
1683 size_t num_breakpoints = breakpoints.GetSize();
1684
1685 if (num_breakpoints == 0) {
1686 result.AppendError("No breakpoints exist to be deleted.");
1687 result.SetStatus(eReturnStatusFailed);
1688 return false;
1689 }
1690
1691 if (command.GetArgumentCount() == 0) {
1692 if (!m_options.m_force &&
1693 !m_interpreter.Confirm(
1694 "About to delete all breakpoints, do you want to do that?",
1695 true)) {
1696 result.AppendMessage("Operation cancelled...");
1697 } else {
1698 target->RemoveAllBreakpoints();
1699 result.AppendMessageWithFormat(
1700 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1701 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1702 }
1703 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1704 } else {
1705 // Particular breakpoint selected; disable that breakpoint.
1706 BreakpointIDList valid_bp_ids;
1707 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1708 command, target, result, &valid_bp_ids);
1709
1710 if (result.Succeeded()) {
1711 int delete_count = 0;
1712 int disable_count = 0;
1713 const size_t count = valid_bp_ids.GetSize();
1714 for (size_t i = 0; i < count; ++i) {
1715 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1716
1717 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1718 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1719 Breakpoint *breakpoint =
1720 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1721 BreakpointLocation *location =
1722 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1723 // It makes no sense to try to delete individual locations, so we
1724 // disable them instead.
1725 if (location) {
1726 location->SetEnabled(false);
1727 ++disable_count;
1728 }
1729 } else {
1730 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1731 ++delete_count;
1732 }
1733 }
1734 }
1735 result.AppendMessageWithFormat(
1736 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1737 delete_count, disable_count);
1738 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1739 }
1740 }
1741 return result.Succeeded();
1742 }
1743
Jim Ingham33df7cd2014-12-06 01:28:03 +00001744private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001745 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001746};
1747
1748OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001749 CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = {
1750 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001751 {LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation."},
1752 {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."},
1753 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001754 // clang-format on
Jim Ingham5a988412012-06-08 21:56:10 +00001755};
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001756
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001757//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001758// CommandObjectBreakpointName
1759//-------------------------------------------------------------------------
1760
Kate Stone7428a182016-07-14 22:03:10 +00001761static OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001762 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001763 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1764 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1765 {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 +00001766 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001767};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001768class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001769public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001770 BreakpointNameOptionGroup()
1771 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1772 }
1773
1774 ~BreakpointNameOptionGroup() override = default;
1775
1776 uint32_t GetNumDefinitions() override {
1777 return sizeof(g_breakpoint_name_options) / sizeof(OptionDefinition);
1778 }
1779
1780 const OptionDefinition *GetDefinitions() override {
1781 return g_breakpoint_name_options;
1782 }
1783
1784 Error SetOptionValue(uint32_t option_idx, const char *option_value,
1785 ExecutionContext *execution_context) override {
1786 Error error;
1787 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1788
1789 switch (short_option) {
1790 case 'N':
1791 if (BreakpointID::StringIsBreakpointName(option_value, error) &&
1792 error.Success())
1793 m_name.SetValueFromString(option_value);
1794 break;
1795
1796 case 'B':
1797 if (m_breakpoint.SetValueFromString(option_value).Fail())
1798 error.SetErrorStringWithFormat(
1799 "unrecognized value \"%s\" for breakpoint", option_value);
1800 break;
1801 case 'D':
1802 if (m_use_dummy.SetValueFromString(option_value).Fail())
1803 error.SetErrorStringWithFormat(
1804 "unrecognized value \"%s\" for use-dummy", option_value);
1805 break;
1806
1807 default:
1808 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1809 short_option);
1810 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001811 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001812 return error;
1813 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001814
Kate Stoneb9c1b512016-09-06 20:57:50 +00001815 void OptionParsingStarting(ExecutionContext *execution_context) override {
1816 m_name.Clear();
1817 m_breakpoint.Clear();
1818 m_use_dummy.Clear();
1819 m_use_dummy.SetDefaultValue(false);
1820 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001821
Kate Stoneb9c1b512016-09-06 20:57:50 +00001822 OptionValueString m_name;
1823 OptionValueUInt64 m_breakpoint;
1824 OptionValueBoolean m_use_dummy;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001825};
1826
Kate Stoneb9c1b512016-09-06 20:57:50 +00001827class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001828public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001829 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1830 : CommandObjectParsed(
1831 interpreter, "add", "Add a name to the breakpoints provided.",
1832 "breakpoint name add <command-options> <breakpoint-id-list>"),
1833 m_name_options(), m_option_group() {
1834 // Create the first variant for the first (and only) argument for this
1835 // command.
1836 CommandArgumentEntry arg1;
1837 CommandArgumentData id_arg;
1838 id_arg.arg_type = eArgTypeBreakpointID;
1839 id_arg.arg_repetition = eArgRepeatOptional;
1840 arg1.push_back(id_arg);
1841 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001842
Kate Stoneb9c1b512016-09-06 20:57:50 +00001843 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1844 m_option_group.Finalize();
1845 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001846
Kate Stoneb9c1b512016-09-06 20:57:50 +00001847 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001848
Kate Stoneb9c1b512016-09-06 20:57:50 +00001849 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001850
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001851protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001852 bool DoExecute(Args &command, CommandReturnObject &result) override {
1853 if (!m_name_options.m_name.OptionWasSet()) {
1854 result.SetError("No name option provided.");
1855 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001856 }
1857
Kate Stoneb9c1b512016-09-06 20:57:50 +00001858 Target *target =
1859 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1860
1861 if (target == nullptr) {
1862 result.AppendError("Invalid target. No existing target or breakpoints.");
1863 result.SetStatus(eReturnStatusFailed);
1864 return false;
1865 }
1866
1867 std::unique_lock<std::recursive_mutex> lock;
1868 target->GetBreakpointList().GetListMutex(lock);
1869
1870 const BreakpointList &breakpoints = target->GetBreakpointList();
1871
1872 size_t num_breakpoints = breakpoints.GetSize();
1873 if (num_breakpoints == 0) {
1874 result.SetError("No breakpoints, cannot add names.");
1875 result.SetStatus(eReturnStatusFailed);
1876 return false;
1877 }
1878
1879 // Particular breakpoint selected; disable that breakpoint.
1880 BreakpointIDList valid_bp_ids;
1881 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1882 command, target, result, &valid_bp_ids);
1883
1884 if (result.Succeeded()) {
1885 if (valid_bp_ids.GetSize() == 0) {
1886 result.SetError("No breakpoints specified, cannot add names.");
1887 result.SetStatus(eReturnStatusFailed);
1888 return false;
1889 }
1890 size_t num_valid_ids = valid_bp_ids.GetSize();
1891 for (size_t index = 0; index < num_valid_ids; index++) {
1892 lldb::break_id_t bp_id =
1893 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1894 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1895 Error error; // We don't need to check the error here, since the option
1896 // parser checked it...
1897 bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
1898 }
1899 }
1900
1901 return true;
1902 }
1903
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001904private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001905 BreakpointNameOptionGroup m_name_options;
1906 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001907};
1908
Kate Stoneb9c1b512016-09-06 20:57:50 +00001909class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001910public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001911 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1912 : CommandObjectParsed(
1913 interpreter, "delete",
1914 "Delete a name from the breakpoints provided.",
1915 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1916 m_name_options(), m_option_group() {
1917 // Create the first variant for the first (and only) argument for this
1918 // command.
1919 CommandArgumentEntry arg1;
1920 CommandArgumentData id_arg;
1921 id_arg.arg_type = eArgTypeBreakpointID;
1922 id_arg.arg_repetition = eArgRepeatOptional;
1923 arg1.push_back(id_arg);
1924 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001925
Kate Stoneb9c1b512016-09-06 20:57:50 +00001926 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1927 m_option_group.Finalize();
1928 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001929
Kate Stoneb9c1b512016-09-06 20:57:50 +00001930 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001931
Kate Stoneb9c1b512016-09-06 20:57:50 +00001932 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001933
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001934protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001935 bool DoExecute(Args &command, CommandReturnObject &result) override {
1936 if (!m_name_options.m_name.OptionWasSet()) {
1937 result.SetError("No name option provided.");
1938 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001939 }
1940
Kate Stoneb9c1b512016-09-06 20:57:50 +00001941 Target *target =
1942 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1943
1944 if (target == nullptr) {
1945 result.AppendError("Invalid target. No existing target or breakpoints.");
1946 result.SetStatus(eReturnStatusFailed);
1947 return false;
1948 }
1949
1950 std::unique_lock<std::recursive_mutex> lock;
1951 target->GetBreakpointList().GetListMutex(lock);
1952
1953 const BreakpointList &breakpoints = target->GetBreakpointList();
1954
1955 size_t num_breakpoints = breakpoints.GetSize();
1956 if (num_breakpoints == 0) {
1957 result.SetError("No breakpoints, cannot delete names.");
1958 result.SetStatus(eReturnStatusFailed);
1959 return false;
1960 }
1961
1962 // Particular breakpoint selected; disable that breakpoint.
1963 BreakpointIDList valid_bp_ids;
1964 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1965 command, target, result, &valid_bp_ids);
1966
1967 if (result.Succeeded()) {
1968 if (valid_bp_ids.GetSize() == 0) {
1969 result.SetError("No breakpoints specified, cannot delete names.");
1970 result.SetStatus(eReturnStatusFailed);
1971 return false;
1972 }
1973 size_t num_valid_ids = valid_bp_ids.GetSize();
1974 for (size_t index = 0; index < num_valid_ids; index++) {
1975 lldb::break_id_t bp_id =
1976 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1977 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1978 bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
1979 }
1980 }
1981
1982 return true;
1983 }
1984
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001985private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001986 BreakpointNameOptionGroup m_name_options;
1987 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001988};
1989
Kate Stoneb9c1b512016-09-06 20:57:50 +00001990class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001991public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001992 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1993 : CommandObjectParsed(interpreter, "list",
1994 "List either the names for a breakpoint or the "
1995 "breakpoints for a given name.",
1996 "breakpoint name list <command-options>"),
1997 m_name_options(), m_option_group() {
1998 m_option_group.Append(&m_name_options);
1999 m_option_group.Finalize();
2000 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002001
Kate Stoneb9c1b512016-09-06 20:57:50 +00002002 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002003
Kate Stoneb9c1b512016-09-06 20:57:50 +00002004 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002005
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002006protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002007 bool DoExecute(Args &command, CommandReturnObject &result) override {
2008 Target *target =
2009 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002010
Kate Stoneb9c1b512016-09-06 20:57:50 +00002011 if (target == nullptr) {
2012 result.AppendError("Invalid target. No existing target or breakpoints.");
2013 result.SetStatus(eReturnStatusFailed);
2014 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002015 }
2016
Kate Stoneb9c1b512016-09-06 20:57:50 +00002017 if (m_name_options.m_name.OptionWasSet()) {
2018 const char *name = m_name_options.m_name.GetCurrentValue();
2019 std::unique_lock<std::recursive_mutex> lock;
2020 target->GetBreakpointList().GetListMutex(lock);
2021
2022 BreakpointList &breakpoints = target->GetBreakpointList();
2023 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2024 if (bp_sp->MatchesName(name)) {
2025 StreamString s;
2026 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2027 s.EOL();
2028 result.AppendMessage(s.GetData());
2029 }
2030 }
2031
2032 } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2033 BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2034 m_name_options.m_breakpoint.GetCurrentValue());
2035 if (bp_sp) {
2036 std::vector<std::string> names;
2037 bp_sp->GetNames(names);
2038 result.AppendMessage("Names:");
2039 for (auto name : names)
2040 result.AppendMessageWithFormat(" %s\n", name.c_str());
2041 } else {
2042 result.AppendErrorWithFormat(
2043 "Could not find breakpoint %" PRId64 ".\n",
2044 m_name_options.m_breakpoint.GetCurrentValue());
2045 result.SetStatus(eReturnStatusFailed);
2046 return false;
2047 }
2048 } else {
2049 result.SetError("Must specify -N or -B option to list.");
2050 result.SetStatus(eReturnStatusFailed);
2051 return false;
2052 }
2053 return true;
2054 }
2055
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002056private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002057 BreakpointNameOptionGroup m_name_options;
2058 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002059};
2060
2061//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002062// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002063//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002064class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002065public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002066 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2067 : CommandObjectMultiword(
2068 interpreter, "name", "Commands to manage name tags for breakpoints",
2069 "breakpoint name <subcommand> [<command-options>]") {
2070 CommandObjectSP add_command_object(
2071 new CommandObjectBreakpointNameAdd(interpreter));
2072 CommandObjectSP delete_command_object(
2073 new CommandObjectBreakpointNameDelete(interpreter));
2074 CommandObjectSP list_command_object(
2075 new CommandObjectBreakpointNameList(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002076
Kate Stoneb9c1b512016-09-06 20:57:50 +00002077 LoadSubCommand("add", add_command_object);
2078 LoadSubCommand("delete", delete_command_object);
2079 LoadSubCommand("list", list_command_object);
2080 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002081
Kate Stoneb9c1b512016-09-06 20:57:50 +00002082 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002083};
2084
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002085//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002086// CommandObjectBreakpointRead
2087//-------------------------------------------------------------------------
2088#pragma mark Restore
2089
2090class CommandObjectBreakpointRead : public CommandObjectParsed {
2091public:
2092 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2093 : CommandObjectParsed(interpreter, "breakpoint read",
2094 "Read and set the breakpoints previously saved to "
2095 "a file with \"breakpoint write\". ",
2096 nullptr),
2097 m_options() {
2098 CommandArgumentEntry arg;
2099 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2100 eArgTypeBreakpointIDRange);
2101 // Add the entry for the first argument for this command to the object's
2102 // arguments vector.
2103 m_arguments.push_back(arg);
2104 }
2105
2106 ~CommandObjectBreakpointRead() override = default;
2107
2108 Options *GetOptions() override { return &m_options; }
2109
2110 class CommandOptions : public Options {
2111 public:
2112 CommandOptions() : Options() {}
2113
2114 ~CommandOptions() override = default;
2115
2116 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2117 ExecutionContext *execution_context) override {
2118 Error error;
2119 const int short_option = m_getopt_table[option_idx].val;
2120
2121 switch (short_option) {
2122 case 'f':
2123 m_filename.assign(option_arg);
2124 break;
2125 default:
2126 error.SetErrorStringWithFormat("unrecognized option '%c'",
2127 short_option);
2128 break;
2129 }
2130
2131 return error;
2132 }
2133
2134 void OptionParsingStarting(ExecutionContext *execution_context) override {
2135 m_filename.clear();
2136 }
2137
2138 const OptionDefinition *GetDefinitions() override { return g_option_table; }
2139
2140 // Options table: Required for subclasses of Options.
2141
2142 static OptionDefinition g_option_table[];
2143
2144 // Instance variables to hold the values for command options.
2145
2146 std::string m_filename;
2147 };
2148
2149protected:
2150 bool DoExecute(Args &command, CommandReturnObject &result) override {
2151 Target *target = GetSelectedOrDummyTarget();
2152 if (target == nullptr) {
2153 result.AppendError("Invalid target. No existing target or breakpoints.");
2154 result.SetStatus(eReturnStatusFailed);
2155 return false;
2156 }
2157
2158 std::unique_lock<std::recursive_mutex> lock;
2159 target->GetBreakpointList().GetListMutex(lock);
2160
2161 FileSpec input_spec(m_options.m_filename, true);
2162 Error error;
2163 StructuredData::ObjectSP input_data_sp =
2164 StructuredData::ParseJSONFromFile(input_spec, error);
2165 if (!error.Success()) {
2166 result.AppendErrorWithFormat("Error reading data from input file: %s.",
2167 error.AsCString());
2168 result.SetStatus(eReturnStatusFailed);
2169 return false;
2170 } else if (!input_data_sp || !input_data_sp->IsValid()) {
2171 result.AppendErrorWithFormat("Invalid JSON from input file: %s.",
2172 input_spec.GetPath().c_str());
2173 result.SetStatus(eReturnStatusFailed);
2174 return false;
2175 }
2176
2177 StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2178 if (!bkpt_array) {
2179 result.AppendErrorWithFormat(
2180 "Invalid breakpoint data from input file: %s.",
2181 input_spec.GetPath().c_str());
2182 result.SetStatus(eReturnStatusFailed);
2183 return false;
2184 }
2185
2186 size_t num_bkpts = bkpt_array->GetSize();
2187 for (size_t i = 0; i < num_bkpts; i++) {
2188 StructuredData::ObjectSP bkpt_object_sp = bkpt_array->GetItemAtIndex(i);
2189 // Peel off the breakpoint key, and feed the rest to the Breakpoint:
2190 StructuredData::Dictionary *bkpt_dict = bkpt_object_sp->GetAsDictionary();
2191 if (!bkpt_dict) {
2192 result.AppendErrorWithFormat(
2193 "Invalid breakpoint data for element %zu from input file: %s.", i,
2194 input_spec.GetPath().c_str());
2195 result.SetStatus(eReturnStatusFailed);
2196 return false;
2197 }
2198 StructuredData::ObjectSP bkpt_data_sp =
2199 bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2200 BreakpointSP bkpt_sp =
2201 Breakpoint::CreateFromStructuredData(*target, bkpt_data_sp, error);
2202 if (!error.Success()) {
2203 result.AppendErrorWithFormat(
2204 "Error restoring breakpoint %zu from %s: %s.", i,
2205 input_spec.GetPath().c_str(), error.AsCString());
2206 result.SetStatus(eReturnStatusFailed);
2207 }
2208 }
2209 return result.Succeeded();
2210 }
2211
2212private:
2213 CommandOptions m_options;
2214};
2215
2216#pragma mark Modify::CommandOptions
2217OptionDefinition CommandObjectBreakpointRead::CommandOptions::g_option_table[] =
2218 {
2219 // clang-format off
2220 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints."},
2221 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
2222 // clang-format on
2223};
2224
2225//-------------------------------------------------------------------------
2226// CommandObjectBreakpointWrite
2227//-------------------------------------------------------------------------
2228#pragma mark Save
2229class CommandObjectBreakpointWrite : public CommandObjectParsed {
2230public:
2231 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2232 : CommandObjectParsed(interpreter, "breakpoint write",
2233 "Write the breakpoints listed to a file that can "
2234 "be read in with \"breakpoint read\". "
2235 "If given no arguments, writes all breakpoints.",
2236 nullptr),
2237 m_options() {
2238 CommandArgumentEntry arg;
2239 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2240 eArgTypeBreakpointIDRange);
2241 // Add the entry for the first argument for this command to the object's
2242 // arguments vector.
2243 m_arguments.push_back(arg);
2244 }
2245
2246 ~CommandObjectBreakpointWrite() override = default;
2247
2248 Options *GetOptions() override { return &m_options; }
2249
2250 class CommandOptions : public Options {
2251 public:
2252 CommandOptions() : Options() {}
2253
2254 ~CommandOptions() override = default;
2255
2256 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2257 ExecutionContext *execution_context) override {
2258 Error error;
2259 const int short_option = m_getopt_table[option_idx].val;
2260
2261 switch (short_option) {
2262 case 'f':
2263 m_filename.assign(option_arg);
2264 break;
2265 default:
2266 error.SetErrorStringWithFormat("unrecognized option '%c'",
2267 short_option);
2268 break;
2269 }
2270
2271 return error;
2272 }
2273
2274 void OptionParsingStarting(ExecutionContext *execution_context) override {
2275 m_filename.clear();
2276 }
2277
2278 const OptionDefinition *GetDefinitions() override { return g_option_table; }
2279
2280 // Options table: Required for subclasses of Options.
2281
2282 static OptionDefinition g_option_table[];
2283
2284 // Instance variables to hold the values for command options.
2285
2286 std::string m_filename;
2287 };
2288
2289protected:
2290 bool DoExecute(Args &command, CommandReturnObject &result) override {
2291 Target *target = GetSelectedOrDummyTarget();
2292 if (target == nullptr) {
2293 result.AppendError("Invalid target. No existing target or breakpoints.");
2294 result.SetStatus(eReturnStatusFailed);
2295 return false;
2296 }
2297
2298 // Before we do anything else make sure we can actually write to this file:
2299 StreamFile out_file(m_options.m_filename.c_str(),
2300 File::OpenOptions::eOpenOptionTruncate |
2301 File::OpenOptions::eOpenOptionWrite |
2302 File::OpenOptions::eOpenOptionCanCreate |
2303 File::OpenOptions::eOpenOptionCloseOnExec,
2304 lldb::eFilePermissionsFileDefault);
2305 if (!out_file.GetFile().IsValid()) {
2306 result.AppendErrorWithFormat("Unable to open output file: %s.",
2307 m_options.m_filename.c_str());
2308 result.SetStatus(eReturnStatusFailed);
2309 return false;
2310 }
2311
2312 std::unique_lock<std::recursive_mutex> lock;
2313 target->GetBreakpointList().GetListMutex(lock);
2314
2315 StructuredData::ArraySP break_store_sp(new StructuredData::Array());
2316
2317 if (command.GetArgumentCount() == 0) {
2318 const BreakpointList &breakpoints = target->GetBreakpointList();
2319
2320 size_t num_breakpoints = breakpoints.GetSize();
2321 for (size_t i = 0; i < num_breakpoints; i++) {
2322 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
2323 StructuredData::ObjectSP bkpt_save_sp = bp->SerializeToStructuredData();
2324 // If a breakpoint can't serialize it, just ignore it for now:
2325 if (bkpt_save_sp)
2326 break_store_sp->AddItem(bkpt_save_sp);
2327 }
2328 } else {
2329
2330 BreakpointIDList valid_bp_ids;
2331
2332 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2333 command, target, result, &valid_bp_ids);
2334
2335 if (result.Succeeded()) {
2336 std::unordered_set<lldb::break_id_t> processed_bkpts;
2337 const size_t count = valid_bp_ids.GetSize();
2338 for (size_t i = 0; i < count; ++i) {
2339 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
2340 lldb::break_id_t bp_id = cur_bp_id.GetBreakpointID();
2341
2342 if (bp_id != LLDB_INVALID_BREAK_ID) {
2343 // Only do each breakpoint once:
2344 std::pair<std::unordered_set<lldb::break_id_t>::iterator, bool>
2345 insert_result = processed_bkpts.insert(bp_id);
2346 if (!insert_result.second)
2347 continue;
2348
2349 Breakpoint *bp = target->GetBreakpointByID(bp_id).get();
2350 StructuredData::ObjectSP bkpt_save_sp =
2351 bp->SerializeToStructuredData();
2352 // If the user explicitly asked to serialize a breakpoint, and we
2353 // can't, then
2354 // raise an error:
2355 if (!bkpt_save_sp) {
2356 result.AppendErrorWithFormat("Unable to serialize breakpoint %d",
2357 bp_id);
2358 result.SetStatus(eReturnStatusFailed);
2359 return false;
2360 }
2361 break_store_sp->AddItem(bkpt_save_sp);
2362 }
2363 }
2364 }
2365 }
2366
2367 break_store_sp->Dump(out_file, false);
2368 out_file.PutChar('\n');
2369
2370 return result.Succeeded();
2371 }
2372
2373private:
2374 CommandOptions m_options;
2375};
2376
2377#pragma mark Modify::CommandOptions
2378OptionDefinition
2379 CommandObjectBreakpointWrite::CommandOptions::g_option_table[] = {
2380 // clang-format off
2381 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints."},
2382 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
2383 // clang-format on
2384};
2385
2386//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002387// CommandObjectMultiwordBreakpoint
2388//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002389#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002390
Kate Stoneb9c1b512016-09-06 20:57:50 +00002391CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2392 CommandInterpreter &interpreter)
2393 : CommandObjectMultiword(
2394 interpreter, "breakpoint",
2395 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2396 "breakpoint <subcommand> [<command-options>]") {
2397 CommandObjectSP list_command_object(
2398 new CommandObjectBreakpointList(interpreter));
2399 CommandObjectSP enable_command_object(
2400 new CommandObjectBreakpointEnable(interpreter));
2401 CommandObjectSP disable_command_object(
2402 new CommandObjectBreakpointDisable(interpreter));
2403 CommandObjectSP clear_command_object(
2404 new CommandObjectBreakpointClear(interpreter));
2405 CommandObjectSP delete_command_object(
2406 new CommandObjectBreakpointDelete(interpreter));
2407 CommandObjectSP set_command_object(
2408 new CommandObjectBreakpointSet(interpreter));
2409 CommandObjectSP command_command_object(
2410 new CommandObjectBreakpointCommand(interpreter));
2411 CommandObjectSP modify_command_object(
2412 new CommandObjectBreakpointModify(interpreter));
2413 CommandObjectSP name_command_object(
2414 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002415 CommandObjectSP write_command_object(
2416 new CommandObjectBreakpointWrite(interpreter));
2417 CommandObjectSP read_command_object(
2418 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002419
Kate Stoneb9c1b512016-09-06 20:57:50 +00002420 list_command_object->SetCommandName("breakpoint list");
2421 enable_command_object->SetCommandName("breakpoint enable");
2422 disable_command_object->SetCommandName("breakpoint disable");
2423 clear_command_object->SetCommandName("breakpoint clear");
2424 delete_command_object->SetCommandName("breakpoint delete");
2425 set_command_object->SetCommandName("breakpoint set");
2426 command_command_object->SetCommandName("breakpoint command");
2427 modify_command_object->SetCommandName("breakpoint modify");
2428 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002429 write_command_object->SetCommandName("breakpoint write");
2430 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002431
Kate Stoneb9c1b512016-09-06 20:57:50 +00002432 LoadSubCommand("list", list_command_object);
2433 LoadSubCommand("enable", enable_command_object);
2434 LoadSubCommand("disable", disable_command_object);
2435 LoadSubCommand("clear", clear_command_object);
2436 LoadSubCommand("delete", delete_command_object);
2437 LoadSubCommand("set", set_command_object);
2438 LoadSubCommand("command", command_command_object);
2439 LoadSubCommand("modify", modify_command_object);
2440 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002441 LoadSubCommand("write", write_command_object);
2442 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002443}
2444
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002445CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002446
Kate Stoneb9c1b512016-09-06 20:57:50 +00002447void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2448 bool allow_locations,
2449 CommandReturnObject &result,
2450 BreakpointIDList *valid_ids) {
2451 // args can be strings representing 1). integers (for breakpoint ids)
2452 // 2). the full breakpoint & location
2453 // canonical representation
2454 // 3). the word "to" or a hyphen,
2455 // representing a range (in which case there
2456 // had *better* be an entry both before &
2457 // after of one of the first two types.
2458 // 4). A breakpoint name
2459 // If args is empty, we will use the last created breakpoint (if there is
2460 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002461
Kate Stoneb9c1b512016-09-06 20:57:50 +00002462 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002463
Kate Stoneb9c1b512016-09-06 20:57:50 +00002464 if (args.GetArgumentCount() == 0) {
2465 if (target->GetLastCreatedBreakpoint()) {
2466 valid_ids->AddBreakpointID(BreakpointID(
2467 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2468 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2469 } else {
2470 result.AppendError(
2471 "No breakpoint specified and no last created breakpoint.");
2472 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002473 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002474 return;
2475 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002476
Kate Stoneb9c1b512016-09-06 20:57:50 +00002477 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2478 // directly from the old ARGS to
2479 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead
2480 // generate a list of strings for
2481 // all the breakpoint ids in the range, and shove all of those breakpoint id
2482 // strings into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002483
Kate Stoneb9c1b512016-09-06 20:57:50 +00002484 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2485 result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002486
Kate Stoneb9c1b512016-09-06 20:57:50 +00002487 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2488 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002489
Kate Stoneb9c1b512016-09-06 20:57:50 +00002490 valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2491 temp_args.GetArgumentCount(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002492
Kate Stoneb9c1b512016-09-06 20:57:50 +00002493 // At this point, all of the breakpoint ids that the user passed in have been
2494 // converted to breakpoint IDs
2495 // and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002496
Kate Stoneb9c1b512016-09-06 20:57:50 +00002497 if (result.Succeeded()) {
2498 // Now that we've converted everything from args into a list of breakpoint
2499 // ids, go through our tentative list
2500 // of breakpoint id's and verify that they correspond to valid/currently set
2501 // breakpoints.
2502
2503 const size_t count = valid_ids->GetSize();
2504 for (size_t i = 0; i < count; ++i) {
2505 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2506 Breakpoint *breakpoint =
2507 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2508 if (breakpoint != nullptr) {
2509 const size_t num_locations = breakpoint->GetNumLocations();
2510 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2511 StreamString id_str;
2512 BreakpointID::GetCanonicalReference(
2513 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2514 i = valid_ids->GetSize() + 1;
2515 result.AppendErrorWithFormat(
2516 "'%s' is not a currently valid breakpoint/location id.\n",
2517 id_str.GetData());
2518 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002519 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002520 } else {
2521 i = valid_ids->GetSize() + 1;
2522 result.AppendErrorWithFormat(
2523 "'%d' is not a currently valid breakpoint ID.\n",
2524 cur_bp_id.GetBreakpointID());
2525 result.SetStatus(eReturnStatusFailed);
2526 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002527 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002528 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002529}