1254721Semaste//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9309124Sdim#include "CommandObjectBreakpoint.h" 10309124Sdim#include "CommandObjectBreakpointCommand.h" 11254721Semaste#include "lldb/Breakpoint/Breakpoint.h" 12254721Semaste#include "lldb/Breakpoint/BreakpointIDList.h" 13254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h" 14321369Sdim#include "lldb/Host/OptionParser.h" 15314564Sdim#include "lldb/Interpreter/CommandInterpreter.h" 16314564Sdim#include "lldb/Interpreter/CommandReturnObject.h" 17341825Sdim#include "lldb/Interpreter/OptionArgParser.h" 18360784Sdim#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 19288943Sdim#include "lldb/Interpreter/OptionValueBoolean.h" 20280031Sdim#include "lldb/Interpreter/OptionValueString.h" 21280031Sdim#include "lldb/Interpreter/OptionValueUInt64.h" 22314564Sdim#include "lldb/Interpreter/Options.h" 23296417Sdim#include "lldb/Target/Language.h" 24314564Sdim#include "lldb/Target/StackFrame.h" 25254721Semaste#include "lldb/Target/Target.h" 26254721Semaste#include "lldb/Target/ThreadSpec.h" 27321369Sdim#include "lldb/Utility/RegularExpression.h" 28321369Sdim#include "lldb/Utility/StreamString.h" 29254721Semaste 30353358Sdim#include <memory> 31353358Sdim#include <vector> 32353358Sdim 33254721Semasteusing namespace lldb; 34254721Semasteusing namespace lldb_private; 35254721Semaste 36314564Sdimstatic void AddBreakpointDescription(Stream *s, Breakpoint *bp, 37314564Sdim lldb::DescriptionLevel level) { 38314564Sdim s->IndentMore(); 39314564Sdim bp->GetDescription(s, level, true); 40314564Sdim s->IndentLess(); 41314564Sdim s->EOL(); 42254721Semaste} 43254721Semaste 44327952Sdim// Modifiable Breakpoint Options 45327952Sdim#pragma mark Modify::CommandOptions 46360784Sdim#define LLDB_OPTIONS_breakpoint_modify 47360784Sdim#include "CommandOptions.inc" 48360784Sdim 49360784Sdimclass lldb_private::BreakpointOptionGroup : public OptionGroup { 50327952Sdimpublic: 51360784Sdim BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {} 52360784Sdim 53327952Sdim ~BreakpointOptionGroup() override = default; 54327952Sdim 55327952Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 56327952Sdim return llvm::makeArrayRef(g_breakpoint_modify_options); 57327952Sdim } 58327952Sdim 59327952Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 60360784Sdim ExecutionContext *execution_context) override { 61327952Sdim Status error; 62360784Sdim const int short_option = 63360784Sdim g_breakpoint_modify_options[option_idx].short_option; 64327952Sdim 65327952Sdim switch (short_option) { 66327952Sdim case 'c': 67341825Sdim // Normally an empty breakpoint condition marks is as unset. But we need 68341825Sdim // to say it was passed in. 69327952Sdim m_bp_opts.SetCondition(option_arg.str().c_str()); 70327952Sdim m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 71327952Sdim break; 72327952Sdim case 'C': 73327952Sdim m_commands.push_back(option_arg); 74327952Sdim break; 75327952Sdim case 'd': 76327952Sdim m_bp_opts.SetEnabled(false); 77327952Sdim break; 78327952Sdim case 'e': 79327952Sdim m_bp_opts.SetEnabled(true); 80327952Sdim break; 81327952Sdim case 'G': { 82327952Sdim bool value, success; 83341825Sdim value = OptionArgParser::ToBoolean(option_arg, false, &success); 84327952Sdim if (success) { 85327952Sdim m_bp_opts.SetAutoContinue(value); 86327952Sdim } else 87327952Sdim error.SetErrorStringWithFormat( 88327952Sdim "invalid boolean value '%s' passed for -G option", 89327952Sdim option_arg.str().c_str()); 90360784Sdim } break; 91360784Sdim case 'i': { 92327952Sdim uint32_t ignore_count; 93327952Sdim if (option_arg.getAsInteger(0, ignore_count)) 94327952Sdim error.SetErrorStringWithFormat("invalid ignore count '%s'", 95327952Sdim option_arg.str().c_str()); 96327952Sdim else 97327952Sdim m_bp_opts.SetIgnoreCount(ignore_count); 98360784Sdim } break; 99327952Sdim case 'o': { 100327952Sdim bool value, success; 101341825Sdim value = OptionArgParser::ToBoolean(option_arg, false, &success); 102327952Sdim if (success) { 103327952Sdim m_bp_opts.SetOneShot(value); 104327952Sdim } else 105327952Sdim error.SetErrorStringWithFormat( 106327952Sdim "invalid boolean value '%s' passed for -o option", 107327952Sdim option_arg.str().c_str()); 108327952Sdim } break; 109360784Sdim case 't': { 110327952Sdim lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 111327952Sdim if (option_arg[0] != '\0') { 112327952Sdim if (option_arg.getAsInteger(0, thread_id)) 113327952Sdim error.SetErrorStringWithFormat("invalid thread id string '%s'", 114327952Sdim option_arg.str().c_str()); 115327952Sdim } 116327952Sdim m_bp_opts.SetThreadID(thread_id); 117360784Sdim } break; 118327952Sdim case 'T': 119327952Sdim m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 120327952Sdim break; 121327952Sdim case 'q': 122327952Sdim m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 123327952Sdim break; 124360784Sdim case 'x': { 125327952Sdim uint32_t thread_index = UINT32_MAX; 126327952Sdim if (option_arg[0] != '\n') { 127327952Sdim if (option_arg.getAsInteger(0, thread_index)) 128327952Sdim error.SetErrorStringWithFormat("invalid thread index string '%s'", 129327952Sdim option_arg.str().c_str()); 130327952Sdim } 131327952Sdim m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 132360784Sdim } break; 133327952Sdim default: 134360784Sdim llvm_unreachable("Unimplemented option"); 135327952Sdim } 136327952Sdim 137327952Sdim return error; 138327952Sdim } 139327952Sdim 140327952Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 141327952Sdim m_bp_opts.Clear(); 142327952Sdim m_commands.clear(); 143327952Sdim } 144360784Sdim 145327952Sdim Status OptionParsingFinished(ExecutionContext *execution_context) override { 146360784Sdim if (!m_commands.empty()) { 147360784Sdim auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); 148327952Sdim 149360784Sdim for (std::string &str : m_commands) 150360784Sdim cmd_data->user_source.AppendString(str); 151360784Sdim 152360784Sdim cmd_data->stop_on_error = true; 153360784Sdim m_bp_opts.SetCommandDataCallback(cmd_data); 154327952Sdim } 155327952Sdim return Status(); 156327952Sdim } 157327952Sdim 158360784Sdim const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; } 159360784Sdim 160327952Sdim std::vector<std::string> m_commands; 161327952Sdim BreakpointOptions m_bp_opts; 162327952Sdim}; 163327952Sdim 164360784Sdim#define LLDB_OPTIONS_breakpoint_dummy 165360784Sdim#include "CommandOptions.inc" 166360784Sdim 167360784Sdimclass BreakpointDummyOptionGroup : public OptionGroup { 168327952Sdimpublic: 169360784Sdim BreakpointDummyOptionGroup() : OptionGroup() {} 170360784Sdim 171327952Sdim ~BreakpointDummyOptionGroup() override = default; 172327952Sdim 173327952Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 174327952Sdim return llvm::makeArrayRef(g_breakpoint_dummy_options); 175327952Sdim } 176327952Sdim 177327952Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 178360784Sdim ExecutionContext *execution_context) override { 179327952Sdim Status error; 180360784Sdim const int short_option = 181360784Sdim g_breakpoint_dummy_options[option_idx].short_option; 182327952Sdim 183327952Sdim switch (short_option) { 184360784Sdim case 'D': 185360784Sdim m_use_dummy = true; 186360784Sdim break; 187327952Sdim default: 188360784Sdim llvm_unreachable("Unimplemented option"); 189327952Sdim } 190327952Sdim 191327952Sdim return error; 192327952Sdim } 193327952Sdim 194327952Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 195327952Sdim m_use_dummy = false; 196327952Sdim } 197327952Sdim 198327952Sdim bool m_use_dummy; 199327952Sdim}; 200327952Sdim 201360784Sdim#define LLDB_OPTIONS_breakpoint_set 202360784Sdim#include "CommandOptions.inc" 203314564Sdim 204254721Semaste// CommandObjectBreakpointSet 205254721Semaste 206314564Sdimclass CommandObjectBreakpointSet : public CommandObjectParsed { 207254721Semastepublic: 208353358Sdim enum BreakpointSetType { 209314564Sdim eSetTypeInvalid, 210314564Sdim eSetTypeFileAndLine, 211314564Sdim eSetTypeAddress, 212314564Sdim eSetTypeFunctionName, 213314564Sdim eSetTypeFunctionRegexp, 214314564Sdim eSetTypeSourceRegexp, 215344779Sdim eSetTypeException, 216344779Sdim eSetTypeScripted, 217353358Sdim }; 218254721Semaste 219314564Sdim CommandObjectBreakpointSet(CommandInterpreter &interpreter) 220314564Sdim : CommandObjectParsed( 221314564Sdim interpreter, "breakpoint set", 222314564Sdim "Sets a breakpoint or set of breakpoints in the executable.", 223314564Sdim "breakpoint set <cmd-options>"), 224360784Sdim m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'), 225360784Sdim m_options() { 226360784Sdim // We're picking up all the normal options, commands and disable. 227360784Sdim m_all_options.Append(&m_python_class_options, 228360784Sdim LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11); 229360784Sdim m_all_options.Append(&m_bp_opts, 230360784Sdim LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 231360784Sdim LLDB_OPT_SET_ALL); 232360784Sdim m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 233360784Sdim m_all_options.Append(&m_options); 234360784Sdim m_all_options.Finalize(); 235360784Sdim } 236254721Semaste 237314564Sdim ~CommandObjectBreakpointSet() override = default; 238254721Semaste 239327952Sdim Options *GetOptions() override { return &m_all_options; } 240254721Semaste 241327952Sdim class CommandOptions : public OptionGroup { 242314564Sdim public: 243314564Sdim CommandOptions() 244360784Sdim : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), 245360784Sdim m_column(0), m_func_names(), 246360784Sdim m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(), 247360784Sdim m_source_text_regexp(), m_modules(), m_load_addr(), m_catch_bp(false), 248360784Sdim m_throw_bp(true), m_hardware(false), 249314564Sdim m_exception_language(eLanguageTypeUnknown), 250314564Sdim m_language(lldb::eLanguageTypeUnknown), 251360784Sdim m_skip_prologue(eLazyBoolCalculate), m_all_files(false), 252360784Sdim m_move_to_nearest_code(eLazyBoolCalculate) {} 253254721Semaste 254314564Sdim ~CommandOptions() override = default; 255254721Semaste 256321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 257321369Sdim ExecutionContext *execution_context) override { 258321369Sdim Status error; 259360784Sdim const int short_option = 260360784Sdim g_breakpoint_set_options[option_idx].short_option; 261254721Semaste 262314564Sdim switch (short_option) { 263314564Sdim case 'a': { 264341825Sdim m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 265341825Sdim LLDB_INVALID_ADDRESS, &error); 266314564Sdim } break; 267254721Semaste 268314564Sdim case 'A': 269314564Sdim m_all_files = true; 270314564Sdim break; 271288943Sdim 272314564Sdim case 'b': 273314564Sdim m_func_names.push_back(option_arg); 274314564Sdim m_func_name_type_mask |= eFunctionNameTypeBase; 275314564Sdim break; 276254721Semaste 277314564Sdim case 'C': 278314564Sdim if (option_arg.getAsInteger(0, m_column)) 279314564Sdim error.SetErrorStringWithFormat("invalid column number: %s", 280314564Sdim option_arg.str().c_str()); 281314564Sdim break; 282309124Sdim 283314564Sdim case 'E': { 284314564Sdim LanguageType language = Language::GetLanguageTypeFromString(option_arg); 285254721Semaste 286314564Sdim switch (language) { 287314564Sdim case eLanguageTypeC89: 288314564Sdim case eLanguageTypeC: 289314564Sdim case eLanguageTypeC99: 290314564Sdim case eLanguageTypeC11: 291314564Sdim m_exception_language = eLanguageTypeC; 292314564Sdim break; 293314564Sdim case eLanguageTypeC_plus_plus: 294314564Sdim case eLanguageTypeC_plus_plus_03: 295314564Sdim case eLanguageTypeC_plus_plus_11: 296314564Sdim case eLanguageTypeC_plus_plus_14: 297314564Sdim m_exception_language = eLanguageTypeC_plus_plus; 298314564Sdim break; 299314564Sdim case eLanguageTypeObjC: 300314564Sdim m_exception_language = eLanguageTypeObjC; 301314564Sdim break; 302314564Sdim case eLanguageTypeObjC_plus_plus: 303314564Sdim error.SetErrorStringWithFormat( 304314564Sdim "Set exception breakpoints separately for c++ and objective-c"); 305314564Sdim break; 306314564Sdim case eLanguageTypeUnknown: 307314564Sdim error.SetErrorStringWithFormat( 308314564Sdim "Unknown language type: '%s' for exception breakpoint", 309314564Sdim option_arg.str().c_str()); 310314564Sdim break; 311314564Sdim default: 312314564Sdim error.SetErrorStringWithFormat( 313314564Sdim "Unsupported language type: '%s' for exception breakpoint", 314314564Sdim option_arg.str().c_str()); 315314564Sdim } 316314564Sdim } break; 317254721Semaste 318314564Sdim case 'f': 319344779Sdim m_filenames.AppendIfUnique(FileSpec(option_arg)); 320314564Sdim break; 321254721Semaste 322314564Sdim case 'F': 323314564Sdim m_func_names.push_back(option_arg); 324314564Sdim m_func_name_type_mask |= eFunctionNameTypeFull; 325314564Sdim break; 326360784Sdim 327314564Sdim case 'h': { 328314564Sdim bool success; 329341825Sdim m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 330314564Sdim if (!success) 331314564Sdim error.SetErrorStringWithFormat( 332314564Sdim "Invalid boolean value for on-catch option: '%s'", 333314564Sdim option_arg.str().c_str()); 334314564Sdim } break; 335258054Semaste 336314564Sdim case 'H': 337314564Sdim m_hardware = true; 338314564Sdim break; 339360784Sdim 340314564Sdim case 'K': { 341314564Sdim bool success; 342314564Sdim bool value; 343341825Sdim value = OptionArgParser::ToBoolean(option_arg, true, &success); 344314564Sdim if (value) 345314564Sdim m_skip_prologue = eLazyBoolYes; 346314564Sdim else 347314564Sdim m_skip_prologue = eLazyBoolNo; 348254721Semaste 349314564Sdim if (!success) 350314564Sdim error.SetErrorStringWithFormat( 351314564Sdim "Invalid boolean value for skip prologue option: '%s'", 352314564Sdim option_arg.str().c_str()); 353314564Sdim } break; 354254721Semaste 355314564Sdim case 'l': 356314564Sdim if (option_arg.getAsInteger(0, m_line_num)) 357314564Sdim error.SetErrorStringWithFormat("invalid line number: %s.", 358314564Sdim option_arg.str().c_str()); 359314564Sdim break; 360296417Sdim 361314564Sdim case 'L': 362314564Sdim m_language = Language::GetLanguageTypeFromString(option_arg); 363314564Sdim if (m_language == eLanguageTypeUnknown) 364314564Sdim error.SetErrorStringWithFormat( 365314564Sdim "Unknown language type: '%s' for breakpoint", 366314564Sdim option_arg.str().c_str()); 367314564Sdim break; 368288943Sdim 369314564Sdim case 'm': { 370314564Sdim bool success; 371314564Sdim bool value; 372341825Sdim value = OptionArgParser::ToBoolean(option_arg, true, &success); 373314564Sdim if (value) 374314564Sdim m_move_to_nearest_code = eLazyBoolYes; 375314564Sdim else 376314564Sdim m_move_to_nearest_code = eLazyBoolNo; 377254721Semaste 378314564Sdim if (!success) 379314564Sdim error.SetErrorStringWithFormat( 380314564Sdim "Invalid boolean value for move-to-nearest-code option: '%s'", 381314564Sdim option_arg.str().c_str()); 382314564Sdim break; 383314564Sdim } 384254721Semaste 385314564Sdim case 'M': 386314564Sdim m_func_names.push_back(option_arg); 387314564Sdim m_func_name_type_mask |= eFunctionNameTypeMethod; 388314564Sdim break; 389280031Sdim 390314564Sdim case 'n': 391314564Sdim m_func_names.push_back(option_arg); 392314564Sdim m_func_name_type_mask |= eFunctionNameTypeAuto; 393314564Sdim break; 394309124Sdim 395314564Sdim case 'N': { 396314564Sdim if (BreakpointID::StringIsBreakpointName(option_arg, error)) 397314564Sdim m_breakpoint_names.push_back(option_arg); 398314564Sdim else 399314564Sdim error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 400314564Sdim option_arg.str().c_str()); 401314564Sdim break; 402314564Sdim } 403254721Semaste 404314564Sdim case 'R': { 405314564Sdim lldb::addr_t tmp_offset_addr; 406341825Sdim tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 407341825Sdim option_arg, 0, &error); 408314564Sdim if (error.Success()) 409314564Sdim m_offset_addr = tmp_offset_addr; 410314564Sdim } break; 411288943Sdim 412314564Sdim case 'O': 413314564Sdim m_exception_extra_args.AppendArgument("-O"); 414314564Sdim m_exception_extra_args.AppendArgument(option_arg); 415314564Sdim break; 416254721Semaste 417314564Sdim case 'p': 418314564Sdim m_source_text_regexp.assign(option_arg); 419314564Sdim break; 420254721Semaste 421314564Sdim case 'r': 422314564Sdim m_func_regexp.assign(option_arg); 423314564Sdim break; 424254721Semaste 425314564Sdim case 's': 426344779Sdim m_modules.AppendIfUnique(FileSpec(option_arg)); 427314564Sdim break; 428254721Semaste 429314564Sdim case 'S': 430314564Sdim m_func_names.push_back(option_arg); 431314564Sdim m_func_name_type_mask |= eFunctionNameTypeSelector; 432314564Sdim break; 433309124Sdim 434314564Sdim case 'w': { 435314564Sdim bool success; 436341825Sdim m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 437314564Sdim if (!success) 438314564Sdim error.SetErrorStringWithFormat( 439314564Sdim "Invalid boolean value for on-throw option: '%s'", 440314564Sdim option_arg.str().c_str()); 441314564Sdim } break; 442254721Semaste 443314564Sdim case 'X': 444314564Sdim m_source_regex_func_names.insert(option_arg); 445314564Sdim break; 446254721Semaste 447314564Sdim default: 448360784Sdim llvm_unreachable("Unimplemented option"); 449314564Sdim } 450254721Semaste 451314564Sdim return error; 452314564Sdim } 453254721Semaste 454314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 455314564Sdim m_filenames.Clear(); 456314564Sdim m_line_num = 0; 457314564Sdim m_column = 0; 458314564Sdim m_func_names.clear(); 459314564Sdim m_func_name_type_mask = eFunctionNameTypeNone; 460314564Sdim m_func_regexp.clear(); 461314564Sdim m_source_text_regexp.clear(); 462314564Sdim m_modules.Clear(); 463314564Sdim m_load_addr = LLDB_INVALID_ADDRESS; 464314564Sdim m_offset_addr = 0; 465314564Sdim m_catch_bp = false; 466314564Sdim m_throw_bp = true; 467314564Sdim m_hardware = false; 468314564Sdim m_exception_language = eLanguageTypeUnknown; 469314564Sdim m_language = lldb::eLanguageTypeUnknown; 470314564Sdim m_skip_prologue = eLazyBoolCalculate; 471314564Sdim m_breakpoint_names.clear(); 472314564Sdim m_all_files = false; 473314564Sdim m_exception_extra_args.Clear(); 474314564Sdim m_move_to_nearest_code = eLazyBoolCalculate; 475314564Sdim m_source_regex_func_names.clear(); 476344779Sdim m_current_key.clear(); 477314564Sdim } 478280031Sdim 479314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 480314564Sdim return llvm::makeArrayRef(g_breakpoint_set_options); 481314564Sdim } 482254721Semaste 483314564Sdim // Instance variables to hold the values for command options. 484254721Semaste 485314564Sdim std::string m_condition; 486314564Sdim FileSpecList m_filenames; 487314564Sdim uint32_t m_line_num; 488314564Sdim uint32_t m_column; 489314564Sdim std::vector<std::string> m_func_names; 490314564Sdim std::vector<std::string> m_breakpoint_names; 491344779Sdim lldb::FunctionNameType m_func_name_type_mask; 492314564Sdim std::string m_func_regexp; 493314564Sdim std::string m_source_text_regexp; 494314564Sdim FileSpecList m_modules; 495314564Sdim lldb::addr_t m_load_addr; 496314564Sdim lldb::addr_t m_offset_addr; 497314564Sdim bool m_catch_bp; 498314564Sdim bool m_throw_bp; 499314564Sdim bool m_hardware; // Request to use hardware breakpoints 500314564Sdim lldb::LanguageType m_exception_language; 501314564Sdim lldb::LanguageType m_language; 502314564Sdim LazyBool m_skip_prologue; 503314564Sdim bool m_all_files; 504314564Sdim Args m_exception_extra_args; 505314564Sdim LazyBool m_move_to_nearest_code; 506314564Sdim std::unordered_set<std::string> m_source_regex_func_names; 507344779Sdim std::string m_current_key; 508314564Sdim }; 509254721Semaste 510314564Sdimprotected: 511314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 512360784Sdim Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 513254721Semaste 514314564Sdim // The following are the various types of breakpoints that could be set: 515314564Sdim // 1). -f -l -p [-s -g] (setting breakpoint by source location) 516314564Sdim // 2). -a [-s -g] (setting breakpoint by address) 517314564Sdim // 3). -n [-s -g] (setting breakpoint by function name) 518314564Sdim // 4). -r [-s -g] (setting breakpoint by function name regular 519314564Sdim // expression) 520314564Sdim // 5). -p -f (setting a breakpoint by comparing a reg-exp 521314564Sdim // to source text) 522314564Sdim // 6). -E [-w -h] (setting a breakpoint for exceptions for a 523314564Sdim // given language.) 524254721Semaste 525314564Sdim BreakpointSetType break_type = eSetTypeInvalid; 526254721Semaste 527360784Sdim if (!m_python_class_options.GetName().empty()) 528344779Sdim break_type = eSetTypeScripted; 529344779Sdim else if (m_options.m_line_num != 0) 530314564Sdim break_type = eSetTypeFileAndLine; 531314564Sdim else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 532314564Sdim break_type = eSetTypeAddress; 533314564Sdim else if (!m_options.m_func_names.empty()) 534314564Sdim break_type = eSetTypeFunctionName; 535314564Sdim else if (!m_options.m_func_regexp.empty()) 536314564Sdim break_type = eSetTypeFunctionRegexp; 537314564Sdim else if (!m_options.m_source_text_regexp.empty()) 538314564Sdim break_type = eSetTypeSourceRegexp; 539314564Sdim else if (m_options.m_exception_language != eLanguageTypeUnknown) 540314564Sdim break_type = eSetTypeException; 541254721Semaste 542327952Sdim BreakpointSP bp_sp = nullptr; 543314564Sdim FileSpec module_spec; 544314564Sdim const bool internal = false; 545254721Semaste 546314564Sdim // If the user didn't specify skip-prologue, having an offset should turn 547314564Sdim // that off. 548314564Sdim if (m_options.m_offset_addr != 0 && 549314564Sdim m_options.m_skip_prologue == eLazyBoolCalculate) 550314564Sdim m_options.m_skip_prologue = eLazyBoolNo; 551280031Sdim 552314564Sdim switch (break_type) { 553314564Sdim case eSetTypeFileAndLine: // Breakpoint by source position 554314564Sdim { 555314564Sdim FileSpec file; 556314564Sdim const size_t num_files = m_options.m_filenames.GetSize(); 557314564Sdim if (num_files == 0) { 558314564Sdim if (!GetDefaultFile(target, file, result)) { 559314564Sdim result.AppendError("No file supplied and no default file available."); 560314564Sdim result.SetStatus(eReturnStatusFailed); 561314564Sdim return false; 562254721Semaste } 563314564Sdim } else if (num_files > 1) { 564314564Sdim result.AppendError("Only one file at a time is allowed for file and " 565314564Sdim "line breakpoints."); 566314564Sdim result.SetStatus(eReturnStatusFailed); 567314564Sdim return false; 568314564Sdim } else 569314564Sdim file = m_options.m_filenames.GetFileSpecAtIndex(0); 570254721Semaste 571314564Sdim // Only check for inline functions if 572314564Sdim LazyBool check_inlines = eLazyBoolCalculate; 573254721Semaste 574360784Sdim bp_sp = target.CreateBreakpoint( 575360784Sdim &(m_options.m_modules), file, m_options.m_line_num, 576360784Sdim m_options.m_column, m_options.m_offset_addr, check_inlines, 577360784Sdim m_options.m_skip_prologue, internal, m_options.m_hardware, 578360784Sdim m_options.m_move_to_nearest_code); 579314564Sdim } break; 580314564Sdim 581314564Sdim case eSetTypeAddress: // Breakpoint by address 582254721Semaste { 583314564Sdim // If a shared library has been specified, make an lldb_private::Address 584327952Sdim // with the library, and use that. That way the address breakpoint 585327952Sdim // will track the load location of the library. 586314564Sdim size_t num_modules_specified = m_options.m_modules.GetSize(); 587314564Sdim if (num_modules_specified == 1) { 588314564Sdim const FileSpec *file_spec = 589314564Sdim m_options.m_modules.GetFileSpecPointerAtIndex(0); 590360784Sdim bp_sp = target.CreateAddressInModuleBreakpoint( 591360784Sdim m_options.m_load_addr, internal, file_spec, m_options.m_hardware); 592314564Sdim } else if (num_modules_specified == 0) { 593360784Sdim bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal, 594360784Sdim m_options.m_hardware); 595314564Sdim } else { 596314564Sdim result.AppendError("Only one shared library can be specified for " 597314564Sdim "address breakpoints."); 598314564Sdim result.SetStatus(eReturnStatusFailed); 599314564Sdim return false; 600314564Sdim } 601314564Sdim break; 602254721Semaste } 603314564Sdim case eSetTypeFunctionName: // Breakpoint by function name 604314564Sdim { 605344779Sdim FunctionNameType name_type_mask = m_options.m_func_name_type_mask; 606309124Sdim 607314564Sdim if (name_type_mask == 0) 608314564Sdim name_type_mask = eFunctionNameTypeAuto; 609254721Semaste 610360784Sdim bp_sp = target.CreateBreakpoint( 611360784Sdim &(m_options.m_modules), &(m_options.m_filenames), 612360784Sdim m_options.m_func_names, name_type_mask, m_options.m_language, 613360784Sdim m_options.m_offset_addr, m_options.m_skip_prologue, internal, 614360784Sdim m_options.m_hardware); 615314564Sdim } break; 616254721Semaste 617314564Sdim case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 618314564Sdim // name 619360784Sdim { 620360784Sdim RegularExpression regexp(m_options.m_func_regexp); 621360784Sdim if (llvm::Error err = regexp.GetError()) { 622360784Sdim result.AppendErrorWithFormat( 623360784Sdim "Function name regular expression could not be compiled: \"%s\"", 624360784Sdim llvm::toString(std::move(err)).c_str()); 625360784Sdim result.SetStatus(eReturnStatusFailed); 626360784Sdim return false; 627360784Sdim } 628254721Semaste 629360784Sdim bp_sp = target.CreateFuncRegexBreakpoint( 630360784Sdim &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp), 631360784Sdim m_options.m_language, m_options.m_skip_prologue, internal, 632360784Sdim m_options.m_hardware); 633360784Sdim } break; 634314564Sdim case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 635314564Sdim { 636314564Sdim const size_t num_files = m_options.m_filenames.GetSize(); 637254721Semaste 638314564Sdim if (num_files == 0 && !m_options.m_all_files) { 639314564Sdim FileSpec file; 640314564Sdim if (!GetDefaultFile(target, file, result)) { 641314564Sdim result.AppendError( 642314564Sdim "No files provided and could not find default file."); 643314564Sdim result.SetStatus(eReturnStatusFailed); 644314564Sdim return false; 645314564Sdim } else { 646314564Sdim m_options.m_filenames.Append(file); 647314564Sdim } 648314564Sdim } 649254721Semaste 650314564Sdim RegularExpression regexp(m_options.m_source_text_regexp); 651360784Sdim if (llvm::Error err = regexp.GetError()) { 652314564Sdim result.AppendErrorWithFormat( 653314564Sdim "Source text regular expression could not be compiled: \"%s\"", 654360784Sdim llvm::toString(std::move(err)).c_str()); 655314564Sdim result.SetStatus(eReturnStatusFailed); 656314564Sdim return false; 657314564Sdim } 658360784Sdim bp_sp = target.CreateSourceRegexBreakpoint( 659360784Sdim &(m_options.m_modules), &(m_options.m_filenames), 660360784Sdim m_options.m_source_regex_func_names, std::move(regexp), internal, 661360784Sdim m_options.m_hardware, m_options.m_move_to_nearest_code); 662314564Sdim } break; 663314564Sdim case eSetTypeException: { 664321369Sdim Status precond_error; 665360784Sdim bp_sp = target.CreateExceptionBreakpoint( 666360784Sdim m_options.m_exception_language, m_options.m_catch_bp, 667360784Sdim m_options.m_throw_bp, internal, &m_options.m_exception_extra_args, 668360784Sdim &precond_error); 669314564Sdim if (precond_error.Fail()) { 670314564Sdim result.AppendErrorWithFormat( 671314564Sdim "Error setting extra exception arguments: %s", 672314564Sdim precond_error.AsCString()); 673360784Sdim target.RemoveBreakpointByID(bp_sp->GetID()); 674314564Sdim result.SetStatus(eReturnStatusFailed); 675314564Sdim return false; 676314564Sdim } 677314564Sdim } break; 678344779Sdim case eSetTypeScripted: { 679344779Sdim 680344779Sdim Status error; 681360784Sdim bp_sp = target.CreateScriptedBreakpoint( 682360784Sdim m_python_class_options.GetName().c_str(), &(m_options.m_modules), 683360784Sdim &(m_options.m_filenames), false, m_options.m_hardware, 684360784Sdim m_python_class_options.GetStructuredData(), &error); 685344779Sdim if (error.Fail()) { 686344779Sdim result.AppendErrorWithFormat( 687360784Sdim "Error setting extra exception arguments: %s", error.AsCString()); 688360784Sdim target.RemoveBreakpointByID(bp_sp->GetID()); 689344779Sdim result.SetStatus(eReturnStatusFailed); 690344779Sdim return false; 691344779Sdim } 692344779Sdim } break; 693314564Sdim default: 694314564Sdim break; 695314564Sdim } 696254721Semaste 697314564Sdim // Now set the various options that were passed in: 698327952Sdim if (bp_sp) { 699327952Sdim bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 700254721Semaste 701314564Sdim if (!m_options.m_breakpoint_names.empty()) { 702321369Sdim Status name_error; 703314564Sdim for (auto name : m_options.m_breakpoint_names) { 704360784Sdim target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 705314564Sdim if (name_error.Fail()) { 706314564Sdim result.AppendErrorWithFormat("Invalid breakpoint name: %s", 707314564Sdim name.c_str()); 708360784Sdim target.RemoveBreakpointByID(bp_sp->GetID()); 709314564Sdim result.SetStatus(eReturnStatusFailed); 710314564Sdim return false; 711314564Sdim } 712314564Sdim } 713314564Sdim } 714314564Sdim } 715360784Sdim 716327952Sdim if (bp_sp) { 717314564Sdim Stream &output_stream = result.GetOutputStream(); 718314564Sdim const bool show_locations = false; 719327952Sdim bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 720360784Sdim show_locations); 721360784Sdim if (&target == &GetDummyTarget()) 722314564Sdim output_stream.Printf("Breakpoint set in dummy target, will get copied " 723314564Sdim "into future targets.\n"); 724314564Sdim else { 725341825Sdim // Don't print out this warning for exception breakpoints. They can 726341825Sdim // get set before the target is set, but we won't know how to actually 727341825Sdim // set the breakpoint till we run. 728327952Sdim if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 729314564Sdim output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 730314564Sdim "actual locations.\n"); 731314564Sdim } 732314564Sdim } 733314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 734327952Sdim } else if (!bp_sp) { 735314564Sdim result.AppendError("Breakpoint creation failed: No breakpoint created."); 736314564Sdim result.SetStatus(eReturnStatusFailed); 737314564Sdim } 738254721Semaste 739314564Sdim return result.Succeeded(); 740314564Sdim } 741309124Sdim 742314564Sdimprivate: 743360784Sdim bool GetDefaultFile(Target &target, FileSpec &file, 744314564Sdim CommandReturnObject &result) { 745314564Sdim uint32_t default_line; 746341825Sdim // First use the Source Manager's default file. Then use the current stack 747341825Sdim // frame's file. 748360784Sdim if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 749314564Sdim StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 750314564Sdim if (cur_frame == nullptr) { 751314564Sdim result.AppendError( 752314564Sdim "No selected frame to use to find the default file."); 753314564Sdim result.SetStatus(eReturnStatusFailed); 754314564Sdim return false; 755314564Sdim } else if (!cur_frame->HasDebugInformation()) { 756314564Sdim result.AppendError("Cannot use the selected frame to find the default " 757314564Sdim "file, it has no debug info."); 758314564Sdim result.SetStatus(eReturnStatusFailed); 759314564Sdim return false; 760314564Sdim } else { 761314564Sdim const SymbolContext &sc = 762314564Sdim cur_frame->GetSymbolContext(eSymbolContextLineEntry); 763314564Sdim if (sc.line_entry.file) { 764314564Sdim file = sc.line_entry.file; 765314564Sdim } else { 766314564Sdim result.AppendError("Can't find the file for the selected frame to " 767314564Sdim "use as the default file."); 768314564Sdim result.SetStatus(eReturnStatusFailed); 769314564Sdim return false; 770314564Sdim } 771314564Sdim } 772314564Sdim } 773314564Sdim return true; 774314564Sdim } 775254721Semaste 776327952Sdim BreakpointOptionGroup m_bp_opts; 777327952Sdim BreakpointDummyOptionGroup m_dummy_options; 778360784Sdim OptionGroupPythonClassWithDict m_python_class_options; 779314564Sdim CommandOptions m_options; 780327952Sdim OptionGroupOptions m_all_options; 781314564Sdim}; 782254721Semaste 783314564Sdim// CommandObjectBreakpointModify 784314564Sdim#pragma mark Modify 785254721Semaste 786314564Sdimclass CommandObjectBreakpointModify : public CommandObjectParsed { 787314564Sdimpublic: 788314564Sdim CommandObjectBreakpointModify(CommandInterpreter &interpreter) 789314564Sdim : CommandObjectParsed(interpreter, "breakpoint modify", 790314564Sdim "Modify the options on a breakpoint or set of " 791314564Sdim "breakpoints in the executable. " 792314564Sdim "If no breakpoint is specified, acts on the last " 793314564Sdim "created breakpoint. " 794314564Sdim "With the exception of -e, -d and -i, passing an " 795314564Sdim "empty argument clears the modification.", 796314564Sdim nullptr), 797314564Sdim m_options() { 798314564Sdim CommandArgumentEntry arg; 799314564Sdim CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 800314564Sdim eArgTypeBreakpointIDRange); 801314564Sdim // Add the entry for the first argument for this command to the object's 802314564Sdim // arguments vector. 803314564Sdim m_arguments.push_back(arg); 804360784Sdim 805360784Sdim m_options.Append(&m_bp_opts, 806360784Sdim LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 807327952Sdim LLDB_OPT_SET_ALL); 808327952Sdim m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 809327952Sdim m_options.Finalize(); 810314564Sdim } 811254721Semaste 812314564Sdim ~CommandObjectBreakpointModify() override = default; 813288943Sdim 814314564Sdim Options *GetOptions() override { return &m_options; } 815254721Semaste 816314564Sdimprotected: 817314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 818360784Sdim Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 819254721Semaste 820314564Sdim std::unique_lock<std::recursive_mutex> lock; 821360784Sdim target.GetBreakpointList().GetListMutex(lock); 822254721Semaste 823314564Sdim BreakpointIDList valid_bp_ids; 824254721Semaste 825314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 826360784Sdim command, &target, result, &valid_bp_ids, 827327952Sdim BreakpointName::Permissions::PermissionKinds::disablePerm); 828254721Semaste 829314564Sdim if (result.Succeeded()) { 830314564Sdim const size_t count = valid_bp_ids.GetSize(); 831314564Sdim for (size_t i = 0; i < count; ++i) { 832314564Sdim BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 833254721Semaste 834314564Sdim if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 835314564Sdim Breakpoint *bp = 836360784Sdim target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 837314564Sdim if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 838314564Sdim BreakpointLocation *location = 839314564Sdim bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 840327952Sdim if (location) 841360784Sdim location->GetLocationOptions()->CopyOverSetOptions( 842360784Sdim m_bp_opts.GetBreakpointOptions()); 843314564Sdim } else { 844360784Sdim bp->GetOptions()->CopyOverSetOptions( 845360784Sdim m_bp_opts.GetBreakpointOptions()); 846314564Sdim } 847254721Semaste } 848314564Sdim } 849254721Semaste } 850254721Semaste 851314564Sdim return result.Succeeded(); 852314564Sdim } 853314564Sdim 854254721Semasteprivate: 855327952Sdim BreakpointOptionGroup m_bp_opts; 856327952Sdim BreakpointDummyOptionGroup m_dummy_opts; 857327952Sdim OptionGroupOptions m_options; 858254721Semaste}; 859254721Semaste 860254721Semaste// CommandObjectBreakpointEnable 861254721Semaste#pragma mark Enable 862254721Semaste 863314564Sdimclass CommandObjectBreakpointEnable : public CommandObjectParsed { 864254721Semastepublic: 865314564Sdim CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 866314564Sdim : CommandObjectParsed(interpreter, "enable", 867314564Sdim "Enable the specified disabled breakpoint(s). If " 868314564Sdim "no breakpoints are specified, enable all of them.", 869314564Sdim nullptr) { 870314564Sdim CommandArgumentEntry arg; 871314564Sdim CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 872314564Sdim eArgTypeBreakpointIDRange); 873314564Sdim // Add the entry for the first argument for this command to the object's 874314564Sdim // arguments vector. 875314564Sdim m_arguments.push_back(arg); 876314564Sdim } 877254721Semaste 878314564Sdim ~CommandObjectBreakpointEnable() override = default; 879254721Semaste 880254721Semasteprotected: 881314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 882360784Sdim Target &target = GetSelectedOrDummyTarget(); 883254721Semaste 884314564Sdim std::unique_lock<std::recursive_mutex> lock; 885360784Sdim target.GetBreakpointList().GetListMutex(lock); 886254721Semaste 887360784Sdim const BreakpointList &breakpoints = target.GetBreakpointList(); 888254721Semaste 889314564Sdim size_t num_breakpoints = breakpoints.GetSize(); 890254721Semaste 891314564Sdim if (num_breakpoints == 0) { 892314564Sdim result.AppendError("No breakpoints exist to be enabled."); 893314564Sdim result.SetStatus(eReturnStatusFailed); 894314564Sdim return false; 895314564Sdim } 896254721Semaste 897314564Sdim if (command.empty()) { 898314564Sdim // No breakpoint selected; enable all currently set breakpoints. 899360784Sdim target.EnableAllowedBreakpoints(); 900314564Sdim result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 901314564Sdim " breakpoints)\n", 902314564Sdim (uint64_t)num_breakpoints); 903314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 904314564Sdim } else { 905314564Sdim // Particular breakpoint selected; enable that breakpoint. 906314564Sdim BreakpointIDList valid_bp_ids; 907314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 908360784Sdim command, &target, result, &valid_bp_ids, 909327952Sdim BreakpointName::Permissions::PermissionKinds::disablePerm); 910254721Semaste 911314564Sdim if (result.Succeeded()) { 912314564Sdim int enable_count = 0; 913314564Sdim int loc_count = 0; 914314564Sdim const size_t count = valid_bp_ids.GetSize(); 915314564Sdim for (size_t i = 0; i < count; ++i) { 916314564Sdim BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 917254721Semaste 918314564Sdim if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 919314564Sdim Breakpoint *breakpoint = 920360784Sdim target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 921314564Sdim if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 922314564Sdim BreakpointLocation *location = 923314564Sdim breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 924314564Sdim if (location) { 925314564Sdim location->SetEnabled(true); 926314564Sdim ++loc_count; 927314564Sdim } 928314564Sdim } else { 929314564Sdim breakpoint->SetEnabled(true); 930314564Sdim ++enable_count; 931254721Semaste } 932314564Sdim } 933254721Semaste } 934314564Sdim result.AppendMessageWithFormat("%d breakpoints enabled.\n", 935314564Sdim enable_count + loc_count); 936314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 937314564Sdim } 938314564Sdim } 939254721Semaste 940314564Sdim return result.Succeeded(); 941314564Sdim } 942254721Semaste}; 943254721Semaste 944254721Semaste// CommandObjectBreakpointDisable 945254721Semaste#pragma mark Disable 946254721Semaste 947314564Sdimclass CommandObjectBreakpointDisable : public CommandObjectParsed { 948254721Semastepublic: 949314564Sdim CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 950314564Sdim : CommandObjectParsed( 951314564Sdim interpreter, "breakpoint disable", 952314564Sdim "Disable the specified breakpoint(s) without deleting " 953314564Sdim "them. If none are specified, disable all " 954314564Sdim "breakpoints.", 955314564Sdim nullptr) { 956314564Sdim SetHelpLong( 957314564Sdim "Disable the specified breakpoint(s) without deleting them. \ 958309124SdimIf none are specified, disable all breakpoints." 959314564Sdim R"( 960288943Sdim 961309124Sdim)" 962314564Sdim "Note: disabling a breakpoint will cause none of its locations to be hit \ 963309124Sdimregardless of whether individual locations are enabled or disabled. After the sequence:" 964314564Sdim R"( 965288943Sdim 966288943Sdim (lldb) break disable 1 967288943Sdim (lldb) break enable 1.1 968288943Sdim 969288943Sdimexecution will NOT stop at location 1.1. To achieve that, type: 970288943Sdim 971288943Sdim (lldb) break disable 1.* 972288943Sdim (lldb) break enable 1.1 973288943Sdim 974309124Sdim)" 975314564Sdim "The first command disables all locations for breakpoint 1, \ 976309124Sdimthe second re-enables the first location."); 977309124Sdim 978314564Sdim CommandArgumentEntry arg; 979314564Sdim CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 980314564Sdim eArgTypeBreakpointIDRange); 981314564Sdim // Add the entry for the first argument for this command to the object's 982314564Sdim // arguments vector. 983314564Sdim m_arguments.push_back(arg); 984314564Sdim } 985254721Semaste 986314564Sdim ~CommandObjectBreakpointDisable() override = default; 987254721Semaste 988254721Semasteprotected: 989314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 990360784Sdim Target &target = GetSelectedOrDummyTarget(); 991314564Sdim std::unique_lock<std::recursive_mutex> lock; 992360784Sdim target.GetBreakpointList().GetListMutex(lock); 993254721Semaste 994360784Sdim const BreakpointList &breakpoints = target.GetBreakpointList(); 995314564Sdim size_t num_breakpoints = breakpoints.GetSize(); 996254721Semaste 997314564Sdim if (num_breakpoints == 0) { 998314564Sdim result.AppendError("No breakpoints exist to be disabled."); 999314564Sdim result.SetStatus(eReturnStatusFailed); 1000314564Sdim return false; 1001314564Sdim } 1002254721Semaste 1003314564Sdim if (command.empty()) { 1004314564Sdim // No breakpoint selected; disable all currently set breakpoints. 1005360784Sdim target.DisableAllowedBreakpoints(); 1006314564Sdim result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1007314564Sdim " breakpoints)\n", 1008314564Sdim (uint64_t)num_breakpoints); 1009314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1010314564Sdim } else { 1011314564Sdim // Particular breakpoint selected; disable that breakpoint. 1012314564Sdim BreakpointIDList valid_bp_ids; 1013254721Semaste 1014314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1015360784Sdim command, &target, result, &valid_bp_ids, 1016327952Sdim BreakpointName::Permissions::PermissionKinds::disablePerm); 1017254721Semaste 1018314564Sdim if (result.Succeeded()) { 1019314564Sdim int disable_count = 0; 1020314564Sdim int loc_count = 0; 1021314564Sdim const size_t count = valid_bp_ids.GetSize(); 1022314564Sdim for (size_t i = 0; i < count; ++i) { 1023314564Sdim BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1024254721Semaste 1025314564Sdim if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1026314564Sdim Breakpoint *breakpoint = 1027360784Sdim target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1028314564Sdim if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1029314564Sdim BreakpointLocation *location = 1030314564Sdim breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1031314564Sdim if (location) { 1032314564Sdim location->SetEnabled(false); 1033314564Sdim ++loc_count; 1034314564Sdim } 1035314564Sdim } else { 1036314564Sdim breakpoint->SetEnabled(false); 1037314564Sdim ++disable_count; 1038254721Semaste } 1039314564Sdim } 1040254721Semaste } 1041314564Sdim result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1042314564Sdim disable_count + loc_count); 1043314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1044314564Sdim } 1045314564Sdim } 1046254721Semaste 1047314564Sdim return result.Succeeded(); 1048314564Sdim } 1049254721Semaste}; 1050254721Semaste 1051254721Semaste// CommandObjectBreakpointList 1052314564Sdim 1053314564Sdim#pragma mark List::CommandOptions 1054353358Sdim#define LLDB_OPTIONS_breakpoint_list 1055353358Sdim#include "CommandOptions.inc" 1056314564Sdim 1057254721Semaste#pragma mark List 1058254721Semaste 1059314564Sdimclass CommandObjectBreakpointList : public CommandObjectParsed { 1060254721Semastepublic: 1061314564Sdim CommandObjectBreakpointList(CommandInterpreter &interpreter) 1062314564Sdim : CommandObjectParsed( 1063314564Sdim interpreter, "breakpoint list", 1064314564Sdim "List some or all breakpoints at configurable levels of detail.", 1065314564Sdim nullptr), 1066314564Sdim m_options() { 1067314564Sdim CommandArgumentEntry arg; 1068314564Sdim CommandArgumentData bp_id_arg; 1069254721Semaste 1070314564Sdim // Define the first (and only) variant of this arg. 1071314564Sdim bp_id_arg.arg_type = eArgTypeBreakpointID; 1072314564Sdim bp_id_arg.arg_repetition = eArgRepeatOptional; 1073254721Semaste 1074314564Sdim // There is only one variant this argument could be; put it into the 1075314564Sdim // argument entry. 1076314564Sdim arg.push_back(bp_id_arg); 1077254721Semaste 1078314564Sdim // Push the data for the first argument into the m_arguments vector. 1079314564Sdim m_arguments.push_back(arg); 1080314564Sdim } 1081254721Semaste 1082314564Sdim ~CommandObjectBreakpointList() override = default; 1083254721Semaste 1084314564Sdim Options *GetOptions() override { return &m_options; } 1085314564Sdim 1086314564Sdim class CommandOptions : public Options { 1087314564Sdim public: 1088314564Sdim CommandOptions() 1089314564Sdim : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 1090254721Semaste } 1091254721Semaste 1092314564Sdim ~CommandOptions() override = default; 1093254721Semaste 1094321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1095321369Sdim ExecutionContext *execution_context) override { 1096321369Sdim Status error; 1097314564Sdim const int short_option = m_getopt_table[option_idx].val; 1098254721Semaste 1099314564Sdim switch (short_option) { 1100314564Sdim case 'b': 1101314564Sdim m_level = lldb::eDescriptionLevelBrief; 1102314564Sdim break; 1103314564Sdim case 'D': 1104314564Sdim m_use_dummy = true; 1105314564Sdim break; 1106314564Sdim case 'f': 1107314564Sdim m_level = lldb::eDescriptionLevelFull; 1108314564Sdim break; 1109314564Sdim case 'v': 1110314564Sdim m_level = lldb::eDescriptionLevelVerbose; 1111314564Sdim break; 1112314564Sdim case 'i': 1113314564Sdim m_internal = true; 1114314564Sdim break; 1115314564Sdim default: 1116360784Sdim llvm_unreachable("Unimplemented option"); 1117314564Sdim } 1118254721Semaste 1119314564Sdim return error; 1120314564Sdim } 1121254721Semaste 1122314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 1123314564Sdim m_level = lldb::eDescriptionLevelFull; 1124314564Sdim m_internal = false; 1125314564Sdim m_use_dummy = false; 1126314564Sdim } 1127254721Semaste 1128314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1129314564Sdim return llvm::makeArrayRef(g_breakpoint_list_options); 1130314564Sdim } 1131254721Semaste 1132314564Sdim // Instance variables to hold the values for command options. 1133254721Semaste 1134314564Sdim lldb::DescriptionLevel m_level; 1135254721Semaste 1136314564Sdim bool m_internal; 1137314564Sdim bool m_use_dummy; 1138314564Sdim }; 1139254721Semaste 1140254721Semasteprotected: 1141314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1142360784Sdim Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1143280031Sdim 1144314564Sdim const BreakpointList &breakpoints = 1145360784Sdim target.GetBreakpointList(m_options.m_internal); 1146314564Sdim std::unique_lock<std::recursive_mutex> lock; 1147360784Sdim target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); 1148254721Semaste 1149314564Sdim size_t num_breakpoints = breakpoints.GetSize(); 1150254721Semaste 1151314564Sdim if (num_breakpoints == 0) { 1152314564Sdim result.AppendMessage("No breakpoints currently set."); 1153314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1154314564Sdim return true; 1155314564Sdim } 1156254721Semaste 1157314564Sdim Stream &output_stream = result.GetOutputStream(); 1158254721Semaste 1159314564Sdim if (command.empty()) { 1160314564Sdim // No breakpoint selected; show info about all currently set breakpoints. 1161314564Sdim result.AppendMessage("Current breakpoints:"); 1162314564Sdim for (size_t i = 0; i < num_breakpoints; ++i) { 1163314564Sdim Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1164327952Sdim if (breakpoint->AllowList()) 1165360784Sdim AddBreakpointDescription(&output_stream, breakpoint, 1166327952Sdim m_options.m_level); 1167314564Sdim } 1168314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1169314564Sdim } else { 1170314564Sdim // Particular breakpoints selected; show info about that breakpoint. 1171314564Sdim BreakpointIDList valid_bp_ids; 1172314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1173360784Sdim command, &target, result, &valid_bp_ids, 1174327952Sdim BreakpointName::Permissions::PermissionKinds::listPerm); 1175254721Semaste 1176314564Sdim if (result.Succeeded()) { 1177314564Sdim for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 1178314564Sdim BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1179314564Sdim Breakpoint *breakpoint = 1180360784Sdim target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1181314564Sdim AddBreakpointDescription(&output_stream, breakpoint, 1182314564Sdim m_options.m_level); 1183254721Semaste } 1184314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1185314564Sdim } else { 1186314564Sdim result.AppendError("Invalid breakpoint ID."); 1187314564Sdim result.SetStatus(eReturnStatusFailed); 1188314564Sdim } 1189254721Semaste } 1190254721Semaste 1191314564Sdim return result.Succeeded(); 1192314564Sdim } 1193314564Sdim 1194254721Semasteprivate: 1195314564Sdim CommandOptions m_options; 1196254721Semaste}; 1197254721Semaste 1198314564Sdim// CommandObjectBreakpointClear 1199314564Sdim#pragma mark Clear::CommandOptions 1200254721Semaste 1201360784Sdim#define LLDB_OPTIONS_breakpoint_clear 1202360784Sdim#include "CommandOptions.inc" 1203254721Semaste 1204254721Semaste#pragma mark Clear 1205254721Semaste 1206314564Sdimclass CommandObjectBreakpointClear : public CommandObjectParsed { 1207254721Semastepublic: 1208353358Sdim enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 1209254721Semaste 1210314564Sdim CommandObjectBreakpointClear(CommandInterpreter &interpreter) 1211314564Sdim : CommandObjectParsed(interpreter, "breakpoint clear", 1212314564Sdim "Delete or disable breakpoints matching the " 1213314564Sdim "specified source file and line.", 1214314564Sdim "breakpoint clear <cmd-options>"), 1215314564Sdim m_options() {} 1216254721Semaste 1217314564Sdim ~CommandObjectBreakpointClear() override = default; 1218254721Semaste 1219314564Sdim Options *GetOptions() override { return &m_options; } 1220254721Semaste 1221314564Sdim class CommandOptions : public Options { 1222314564Sdim public: 1223314564Sdim CommandOptions() : Options(), m_filename(), m_line_num(0) {} 1224254721Semaste 1225314564Sdim ~CommandOptions() override = default; 1226254721Semaste 1227321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1228321369Sdim ExecutionContext *execution_context) override { 1229321369Sdim Status error; 1230314564Sdim const int short_option = m_getopt_table[option_idx].val; 1231254721Semaste 1232314564Sdim switch (short_option) { 1233314564Sdim case 'f': 1234314564Sdim m_filename.assign(option_arg); 1235314564Sdim break; 1236254721Semaste 1237314564Sdim case 'l': 1238314564Sdim option_arg.getAsInteger(0, m_line_num); 1239314564Sdim break; 1240254721Semaste 1241314564Sdim default: 1242360784Sdim llvm_unreachable("Unimplemented option"); 1243314564Sdim } 1244254721Semaste 1245314564Sdim return error; 1246314564Sdim } 1247254721Semaste 1248314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 1249314564Sdim m_filename.clear(); 1250314564Sdim m_line_num = 0; 1251314564Sdim } 1252254721Semaste 1253314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1254314564Sdim return llvm::makeArrayRef(g_breakpoint_clear_options); 1255314564Sdim } 1256254721Semaste 1257314564Sdim // Instance variables to hold the values for command options. 1258254721Semaste 1259314564Sdim std::string m_filename; 1260314564Sdim uint32_t m_line_num; 1261314564Sdim }; 1262254721Semaste 1263254721Semasteprotected: 1264314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1265360784Sdim Target &target = GetSelectedOrDummyTarget(); 1266254721Semaste 1267341825Sdim // The following are the various types of breakpoints that could be 1268341825Sdim // cleared: 1269314564Sdim // 1). -f -l (clearing breakpoint by source location) 1270254721Semaste 1271314564Sdim BreakpointClearType break_type = eClearTypeInvalid; 1272254721Semaste 1273314564Sdim if (m_options.m_line_num != 0) 1274314564Sdim break_type = eClearTypeFileAndLine; 1275254721Semaste 1276314564Sdim std::unique_lock<std::recursive_mutex> lock; 1277360784Sdim target.GetBreakpointList().GetListMutex(lock); 1278254721Semaste 1279360784Sdim BreakpointList &breakpoints = target.GetBreakpointList(); 1280314564Sdim size_t num_breakpoints = breakpoints.GetSize(); 1281254721Semaste 1282314564Sdim // Early return if there's no breakpoint at all. 1283314564Sdim if (num_breakpoints == 0) { 1284314564Sdim result.AppendError("Breakpoint clear: No breakpoint cleared."); 1285314564Sdim result.SetStatus(eReturnStatusFailed); 1286314564Sdim return result.Succeeded(); 1287314564Sdim } 1288254721Semaste 1289314564Sdim // Find matching breakpoints and delete them. 1290254721Semaste 1291314564Sdim // First create a copy of all the IDs. 1292314564Sdim std::vector<break_id_t> BreakIDs; 1293314564Sdim for (size_t i = 0; i < num_breakpoints; ++i) 1294314564Sdim BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 1295254721Semaste 1296314564Sdim int num_cleared = 0; 1297314564Sdim StreamString ss; 1298314564Sdim switch (break_type) { 1299314564Sdim case eClearTypeFileAndLine: // Breakpoint by source position 1300314564Sdim { 1301314564Sdim const ConstString filename(m_options.m_filename.c_str()); 1302314564Sdim BreakpointLocationCollection loc_coll; 1303254721Semaste 1304314564Sdim for (size_t i = 0; i < num_breakpoints; ++i) { 1305314564Sdim Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 1306254721Semaste 1307314564Sdim if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1308314564Sdim // If the collection size is 0, it's a full match and we can just 1309314564Sdim // remove the breakpoint. 1310314564Sdim if (loc_coll.GetSize() == 0) { 1311314564Sdim bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 1312314564Sdim ss.EOL(); 1313360784Sdim target.RemoveBreakpointByID(bp->GetID()); 1314314564Sdim ++num_cleared; 1315314564Sdim } 1316254721Semaste } 1317314564Sdim } 1318314564Sdim } break; 1319254721Semaste 1320314564Sdim default: 1321314564Sdim break; 1322314564Sdim } 1323254721Semaste 1324314564Sdim if (num_cleared > 0) { 1325314564Sdim Stream &output_stream = result.GetOutputStream(); 1326314564Sdim output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1327314564Sdim output_stream << ss.GetString(); 1328314564Sdim output_stream.EOL(); 1329314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1330314564Sdim } else { 1331314564Sdim result.AppendError("Breakpoint clear: No breakpoint cleared."); 1332314564Sdim result.SetStatus(eReturnStatusFailed); 1333254721Semaste } 1334254721Semaste 1335314564Sdim return result.Succeeded(); 1336314564Sdim } 1337314564Sdim 1338254721Semasteprivate: 1339314564Sdim CommandOptions m_options; 1340254721Semaste}; 1341254721Semaste 1342254721Semaste// CommandObjectBreakpointDelete 1343360784Sdim#define LLDB_OPTIONS_breakpoint_delete 1344360784Sdim#include "CommandOptions.inc" 1345314564Sdim 1346254721Semaste#pragma mark Delete 1347254721Semaste 1348314564Sdimclass CommandObjectBreakpointDelete : public CommandObjectParsed { 1349254721Semastepublic: 1350314564Sdim CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1351314564Sdim : CommandObjectParsed(interpreter, "breakpoint delete", 1352314564Sdim "Delete the specified breakpoint(s). If no " 1353314564Sdim "breakpoints are specified, delete them all.", 1354309124Sdim nullptr), 1355314564Sdim m_options() { 1356314564Sdim CommandArgumentEntry arg; 1357314564Sdim CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1358314564Sdim eArgTypeBreakpointIDRange); 1359314564Sdim // Add the entry for the first argument for this command to the object's 1360314564Sdim // arguments vector. 1361314564Sdim m_arguments.push_back(arg); 1362314564Sdim } 1363254721Semaste 1364314564Sdim ~CommandObjectBreakpointDelete() override = default; 1365254721Semaste 1366314564Sdim Options *GetOptions() override { return &m_options; } 1367280031Sdim 1368314564Sdim class CommandOptions : public Options { 1369314564Sdim public: 1370314564Sdim CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 1371280031Sdim 1372314564Sdim ~CommandOptions() override = default; 1373280031Sdim 1374321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1375321369Sdim ExecutionContext *execution_context) override { 1376321369Sdim Status error; 1377314564Sdim const int short_option = m_getopt_table[option_idx].val; 1378280031Sdim 1379314564Sdim switch (short_option) { 1380314564Sdim case 'f': 1381314564Sdim m_force = true; 1382314564Sdim break; 1383280031Sdim 1384314564Sdim case 'D': 1385314564Sdim m_use_dummy = true; 1386314564Sdim break; 1387280031Sdim 1388314564Sdim default: 1389360784Sdim llvm_unreachable("Unimplemented option"); 1390314564Sdim } 1391280031Sdim 1392314564Sdim return error; 1393314564Sdim } 1394280031Sdim 1395314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 1396314564Sdim m_use_dummy = false; 1397314564Sdim m_force = false; 1398314564Sdim } 1399280031Sdim 1400314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1401314564Sdim return llvm::makeArrayRef(g_breakpoint_delete_options); 1402314564Sdim } 1403280031Sdim 1404314564Sdim // Instance variables to hold the values for command options. 1405314564Sdim bool m_use_dummy; 1406314564Sdim bool m_force; 1407314564Sdim }; 1408280031Sdim 1409254721Semasteprotected: 1410314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1411360784Sdim Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1412280031Sdim 1413314564Sdim std::unique_lock<std::recursive_mutex> lock; 1414360784Sdim target.GetBreakpointList().GetListMutex(lock); 1415309124Sdim 1416360784Sdim const BreakpointList &breakpoints = target.GetBreakpointList(); 1417254721Semaste 1418314564Sdim size_t num_breakpoints = breakpoints.GetSize(); 1419254721Semaste 1420314564Sdim if (num_breakpoints == 0) { 1421314564Sdim result.AppendError("No breakpoints exist to be deleted."); 1422314564Sdim result.SetStatus(eReturnStatusFailed); 1423314564Sdim return false; 1424314564Sdim } 1425254721Semaste 1426314564Sdim if (command.empty()) { 1427314564Sdim if (!m_options.m_force && 1428314564Sdim !m_interpreter.Confirm( 1429314564Sdim "About to delete all breakpoints, do you want to do that?", 1430314564Sdim true)) { 1431314564Sdim result.AppendMessage("Operation cancelled..."); 1432314564Sdim } else { 1433360784Sdim target.RemoveAllowedBreakpoints(); 1434314564Sdim result.AppendMessageWithFormat( 1435314564Sdim "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1436314564Sdim (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 1437314564Sdim } 1438314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1439314564Sdim } else { 1440314564Sdim // Particular breakpoint selected; disable that breakpoint. 1441314564Sdim BreakpointIDList valid_bp_ids; 1442314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1443360784Sdim command, &target, result, &valid_bp_ids, 1444327952Sdim BreakpointName::Permissions::PermissionKinds::deletePerm); 1445254721Semaste 1446314564Sdim if (result.Succeeded()) { 1447314564Sdim int delete_count = 0; 1448314564Sdim int disable_count = 0; 1449314564Sdim const size_t count = valid_bp_ids.GetSize(); 1450314564Sdim for (size_t i = 0; i < count; ++i) { 1451314564Sdim BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1452254721Semaste 1453314564Sdim if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1454314564Sdim if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1455314564Sdim Breakpoint *breakpoint = 1456360784Sdim target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1457314564Sdim BreakpointLocation *location = 1458314564Sdim breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1459314564Sdim // It makes no sense to try to delete individual locations, so we 1460314564Sdim // disable them instead. 1461314564Sdim if (location) { 1462314564Sdim location->SetEnabled(false); 1463314564Sdim ++disable_count; 1464314564Sdim } 1465314564Sdim } else { 1466360784Sdim target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 1467314564Sdim ++delete_count; 1468254721Semaste } 1469314564Sdim } 1470254721Semaste } 1471314564Sdim result.AppendMessageWithFormat( 1472314564Sdim "%d breakpoints deleted; %d breakpoint locations disabled.\n", 1473314564Sdim delete_count, disable_count); 1474314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1475314564Sdim } 1476254721Semaste } 1477314564Sdim return result.Succeeded(); 1478314564Sdim } 1479309124Sdim 1480280031Sdimprivate: 1481314564Sdim CommandOptions m_options; 1482254721Semaste}; 1483254721Semaste 1484280031Sdim// CommandObjectBreakpointName 1485360784Sdim#define LLDB_OPTIONS_breakpoint_name 1486360784Sdim#include "CommandOptions.inc" 1487280031Sdim 1488314564Sdimclass BreakpointNameOptionGroup : public OptionGroup { 1489280031Sdimpublic: 1490314564Sdim BreakpointNameOptionGroup() 1491314564Sdim : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 1492314564Sdim } 1493280031Sdim 1494314564Sdim ~BreakpointNameOptionGroup() override = default; 1495309124Sdim 1496314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1497314564Sdim return llvm::makeArrayRef(g_breakpoint_name_options); 1498314564Sdim } 1499280031Sdim 1500321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1501321369Sdim ExecutionContext *execution_context) override { 1502321369Sdim Status error; 1503314564Sdim const int short_option = g_breakpoint_name_options[option_idx].short_option; 1504280031Sdim 1505314564Sdim switch (short_option) { 1506314564Sdim case 'N': 1507314564Sdim if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1508314564Sdim error.Success()) 1509314564Sdim m_name.SetValueFromString(option_arg); 1510314564Sdim break; 1511314564Sdim case 'B': 1512314564Sdim if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1513314564Sdim error.SetErrorStringWithFormat( 1514314564Sdim "unrecognized value \"%s\" for breakpoint", 1515314564Sdim option_arg.str().c_str()); 1516314564Sdim break; 1517314564Sdim case 'D': 1518314564Sdim if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1519314564Sdim error.SetErrorStringWithFormat( 1520314564Sdim "unrecognized value \"%s\" for use-dummy", 1521314564Sdim option_arg.str().c_str()); 1522314564Sdim break; 1523327952Sdim case 'H': 1524327952Sdim m_help_string.SetValueFromString(option_arg); 1525327952Sdim break; 1526280031Sdim 1527314564Sdim default: 1528360784Sdim llvm_unreachable("Unimplemented option"); 1529280031Sdim } 1530314564Sdim return error; 1531314564Sdim } 1532280031Sdim 1533314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 1534314564Sdim m_name.Clear(); 1535314564Sdim m_breakpoint.Clear(); 1536314564Sdim m_use_dummy.Clear(); 1537314564Sdim m_use_dummy.SetDefaultValue(false); 1538327952Sdim m_help_string.Clear(); 1539314564Sdim } 1540314564Sdim 1541314564Sdim OptionValueString m_name; 1542314564Sdim OptionValueUInt64 m_breakpoint; 1543314564Sdim OptionValueBoolean m_use_dummy; 1544327952Sdim OptionValueString m_help_string; 1545280031Sdim}; 1546280031Sdim 1547360784Sdim#define LLDB_OPTIONS_breakpoint_access 1548360784Sdim#include "CommandOptions.inc" 1549327952Sdim 1550344779Sdimclass BreakpointAccessOptionGroup : public OptionGroup { 1551327952Sdimpublic: 1552344779Sdim BreakpointAccessOptionGroup() : OptionGroup() {} 1553344779Sdim 1554327952Sdim ~BreakpointAccessOptionGroup() override = default; 1555344779Sdim 1556327952Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1557327952Sdim return llvm::makeArrayRef(g_breakpoint_access_options); 1558327952Sdim } 1559327952Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1560327952Sdim ExecutionContext *execution_context) override { 1561327952Sdim Status error; 1562360784Sdim const int short_option = 1563360784Sdim g_breakpoint_access_options[option_idx].short_option; 1564327952Sdim 1565327952Sdim switch (short_option) { 1566360784Sdim case 'L': { 1567360784Sdim bool value, success; 1568360784Sdim value = OptionArgParser::ToBoolean(option_arg, false, &success); 1569360784Sdim if (success) { 1570360784Sdim m_permissions.SetAllowList(value); 1571360784Sdim } else 1572360784Sdim error.SetErrorStringWithFormat( 1573360784Sdim "invalid boolean value '%s' passed for -L option", 1574360784Sdim option_arg.str().c_str()); 1575360784Sdim } break; 1576360784Sdim case 'A': { 1577360784Sdim bool value, success; 1578360784Sdim value = OptionArgParser::ToBoolean(option_arg, false, &success); 1579360784Sdim if (success) { 1580360784Sdim m_permissions.SetAllowDisable(value); 1581360784Sdim } else 1582360784Sdim error.SetErrorStringWithFormat( 1583360784Sdim "invalid boolean value '%s' passed for -L option", 1584360784Sdim option_arg.str().c_str()); 1585360784Sdim } break; 1586360784Sdim case 'D': { 1587360784Sdim bool value, success; 1588360784Sdim value = OptionArgParser::ToBoolean(option_arg, false, &success); 1589360784Sdim if (success) { 1590360784Sdim m_permissions.SetAllowDelete(value); 1591360784Sdim } else 1592360784Sdim error.SetErrorStringWithFormat( 1593360784Sdim "invalid boolean value '%s' passed for -L option", 1594360784Sdim option_arg.str().c_str()); 1595360784Sdim } break; 1596360784Sdim default: 1597360784Sdim llvm_unreachable("Unimplemented option"); 1598360784Sdim } 1599327952Sdim 1600327952Sdim return error; 1601327952Sdim } 1602360784Sdim 1603360784Sdim void OptionParsingStarting(ExecutionContext *execution_context) override {} 1604360784Sdim 1605360784Sdim const BreakpointName::Permissions &GetPermissions() const { 1606327952Sdim return m_permissions; 1607327952Sdim } 1608360784Sdim BreakpointName::Permissions m_permissions; 1609327952Sdim}; 1610327952Sdim 1611327952Sdimclass CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1612327952Sdimpublic: 1613327952Sdim CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1614327952Sdim : CommandObjectParsed( 1615360784Sdim interpreter, "configure", 1616360784Sdim "Configure the options for the breakpoint" 1617327952Sdim " name provided. " 1618327952Sdim "If you provide a breakpoint id, the options will be copied from " 1619327952Sdim "the breakpoint, otherwise only the options specified will be set " 1620327952Sdim "on the name.", 1621327952Sdim "breakpoint name configure <command-options> " 1622327952Sdim "<breakpoint-name-list>"), 1623327952Sdim m_bp_opts(), m_option_group() { 1624327952Sdim // Create the first variant for the first (and only) argument for this 1625327952Sdim // command. 1626327952Sdim CommandArgumentEntry arg1; 1627327952Sdim CommandArgumentData id_arg; 1628327952Sdim id_arg.arg_type = eArgTypeBreakpointName; 1629327952Sdim id_arg.arg_repetition = eArgRepeatOptional; 1630327952Sdim arg1.push_back(id_arg); 1631327952Sdim m_arguments.push_back(arg1); 1632327952Sdim 1633360784Sdim m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1634360784Sdim m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL, 1635327952Sdim LLDB_OPT_SET_ALL); 1636360784Sdim m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4, 1637327952Sdim LLDB_OPT_SET_ALL); 1638327952Sdim m_option_group.Finalize(); 1639327952Sdim } 1640327952Sdim 1641327952Sdim ~CommandObjectBreakpointNameConfigure() override = default; 1642327952Sdim 1643327952Sdim Options *GetOptions() override { return &m_option_group; } 1644327952Sdim 1645327952Sdimprotected: 1646327952Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1647327952Sdim 1648327952Sdim const size_t argc = command.GetArgumentCount(); 1649327952Sdim if (argc == 0) { 1650327952Sdim result.AppendError("No names provided."); 1651327952Sdim result.SetStatus(eReturnStatusFailed); 1652327952Sdim return false; 1653327952Sdim } 1654327952Sdim 1655360784Sdim Target &target = GetSelectedOrDummyTarget(false); 1656327952Sdim 1657327952Sdim std::unique_lock<std::recursive_mutex> lock; 1658360784Sdim target.GetBreakpointList().GetListMutex(lock); 1659327952Sdim 1660327952Sdim // Make a pass through first to see that all the names are legal. 1661327952Sdim for (auto &entry : command.entries()) { 1662327952Sdim Status error; 1663360784Sdim if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { 1664327952Sdim result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1665327952Sdim entry.c_str(), error.AsCString()); 1666327952Sdim result.SetStatus(eReturnStatusFailed); 1667327952Sdim return false; 1668327952Sdim } 1669327952Sdim } 1670341825Sdim // Now configure them, we already pre-checked the names so we don't need to 1671341825Sdim // check the error: 1672327952Sdim BreakpointSP bp_sp; 1673360784Sdim if (m_bp_id.m_breakpoint.OptionWasSet()) { 1674327952Sdim lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1675360784Sdim bp_sp = target.GetBreakpointByID(bp_id); 1676360784Sdim if (!bp_sp) { 1677327952Sdim result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1678360784Sdim bp_id); 1679327952Sdim result.SetStatus(eReturnStatusFailed); 1680327952Sdim return false; 1681327952Sdim } 1682327952Sdim } 1683327952Sdim 1684327952Sdim Status error; 1685327952Sdim for (auto &entry : command.entries()) { 1686327952Sdim ConstString name(entry.c_str()); 1687360784Sdim BreakpointName *bp_name = target.FindBreakpointName(name, true, error); 1688327952Sdim if (!bp_name) 1689327952Sdim continue; 1690327952Sdim if (m_bp_id.m_help_string.OptionWasSet()) 1691327952Sdim bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1692360784Sdim 1693327952Sdim if (bp_sp) 1694360784Sdim target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(), 1695327952Sdim m_access_options.GetPermissions()); 1696327952Sdim else 1697360784Sdim target.ConfigureBreakpointName(*bp_name, 1698327952Sdim m_bp_opts.GetBreakpointOptions(), 1699327952Sdim m_access_options.GetPermissions()); 1700327952Sdim } 1701327952Sdim return true; 1702327952Sdim } 1703327952Sdim 1704327952Sdimprivate: 1705327952Sdim BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1706327952Sdim BreakpointOptionGroup m_bp_opts; 1707327952Sdim BreakpointAccessOptionGroup m_access_options; 1708327952Sdim OptionGroupOptions m_option_group; 1709327952Sdim}; 1710327952Sdim 1711314564Sdimclass CommandObjectBreakpointNameAdd : public CommandObjectParsed { 1712280031Sdimpublic: 1713314564Sdim CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1714314564Sdim : CommandObjectParsed( 1715314564Sdim interpreter, "add", "Add a name to the breakpoints provided.", 1716314564Sdim "breakpoint name add <command-options> <breakpoint-id-list>"), 1717314564Sdim m_name_options(), m_option_group() { 1718314564Sdim // Create the first variant for the first (and only) argument for this 1719314564Sdim // command. 1720314564Sdim CommandArgumentEntry arg1; 1721314564Sdim CommandArgumentData id_arg; 1722314564Sdim id_arg.arg_type = eArgTypeBreakpointID; 1723314564Sdim id_arg.arg_repetition = eArgRepeatOptional; 1724314564Sdim arg1.push_back(id_arg); 1725314564Sdim m_arguments.push_back(arg1); 1726280031Sdim 1727314564Sdim m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1728314564Sdim m_option_group.Finalize(); 1729314564Sdim } 1730280031Sdim 1731314564Sdim ~CommandObjectBreakpointNameAdd() override = default; 1732280031Sdim 1733314564Sdim Options *GetOptions() override { return &m_option_group; } 1734309124Sdim 1735280031Sdimprotected: 1736314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1737314564Sdim if (!m_name_options.m_name.OptionWasSet()) { 1738314564Sdim result.SetError("No name option provided."); 1739314564Sdim return false; 1740314564Sdim } 1741280031Sdim 1742360784Sdim Target &target = 1743314564Sdim GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1744280031Sdim 1745314564Sdim std::unique_lock<std::recursive_mutex> lock; 1746360784Sdim target.GetBreakpointList().GetListMutex(lock); 1747309124Sdim 1748360784Sdim const BreakpointList &breakpoints = target.GetBreakpointList(); 1749280031Sdim 1750314564Sdim size_t num_breakpoints = breakpoints.GetSize(); 1751314564Sdim if (num_breakpoints == 0) { 1752314564Sdim result.SetError("No breakpoints, cannot add names."); 1753314564Sdim result.SetStatus(eReturnStatusFailed); 1754314564Sdim return false; 1755314564Sdim } 1756280031Sdim 1757314564Sdim // Particular breakpoint selected; disable that breakpoint. 1758314564Sdim BreakpointIDList valid_bp_ids; 1759314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1760360784Sdim command, &target, result, &valid_bp_ids, 1761327952Sdim BreakpointName::Permissions::PermissionKinds::listPerm); 1762280031Sdim 1763314564Sdim if (result.Succeeded()) { 1764314564Sdim if (valid_bp_ids.GetSize() == 0) { 1765314564Sdim result.SetError("No breakpoints specified, cannot add names."); 1766314564Sdim result.SetStatus(eReturnStatusFailed); 1767314564Sdim return false; 1768314564Sdim } 1769314564Sdim size_t num_valid_ids = valid_bp_ids.GetSize(); 1770327952Sdim const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1771360784Sdim Status error; // This error reports illegal names, but we've already 1772327952Sdim // checked that, so we don't need to check it again here. 1773314564Sdim for (size_t index = 0; index < num_valid_ids; index++) { 1774314564Sdim lldb::break_id_t bp_id = 1775314564Sdim valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1776314564Sdim BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1777360784Sdim target.AddNameToBreakpoint(bp_sp, bp_name, error); 1778314564Sdim } 1779280031Sdim } 1780280031Sdim 1781314564Sdim return true; 1782314564Sdim } 1783314564Sdim 1784280031Sdimprivate: 1785314564Sdim BreakpointNameOptionGroup m_name_options; 1786314564Sdim OptionGroupOptions m_option_group; 1787280031Sdim}; 1788280031Sdim 1789314564Sdimclass CommandObjectBreakpointNameDelete : public CommandObjectParsed { 1790280031Sdimpublic: 1791314564Sdim CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1792314564Sdim : CommandObjectParsed( 1793314564Sdim interpreter, "delete", 1794314564Sdim "Delete a name from the breakpoints provided.", 1795314564Sdim "breakpoint name delete <command-options> <breakpoint-id-list>"), 1796314564Sdim m_name_options(), m_option_group() { 1797314564Sdim // Create the first variant for the first (and only) argument for this 1798314564Sdim // command. 1799314564Sdim CommandArgumentEntry arg1; 1800314564Sdim CommandArgumentData id_arg; 1801314564Sdim id_arg.arg_type = eArgTypeBreakpointID; 1802314564Sdim id_arg.arg_repetition = eArgRepeatOptional; 1803314564Sdim arg1.push_back(id_arg); 1804314564Sdim m_arguments.push_back(arg1); 1805280031Sdim 1806314564Sdim m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1807314564Sdim m_option_group.Finalize(); 1808314564Sdim } 1809314564Sdim 1810314564Sdim ~CommandObjectBreakpointNameDelete() override = default; 1811314564Sdim 1812314564Sdim Options *GetOptions() override { return &m_option_group; } 1813314564Sdim 1814314564Sdimprotected: 1815314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1816314564Sdim if (!m_name_options.m_name.OptionWasSet()) { 1817314564Sdim result.SetError("No name option provided."); 1818314564Sdim return false; 1819280031Sdim } 1820280031Sdim 1821360784Sdim Target &target = 1822314564Sdim GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1823280031Sdim 1824314564Sdim std::unique_lock<std::recursive_mutex> lock; 1825360784Sdim target.GetBreakpointList().GetListMutex(lock); 1826280031Sdim 1827360784Sdim const BreakpointList &breakpoints = target.GetBreakpointList(); 1828280031Sdim 1829314564Sdim size_t num_breakpoints = breakpoints.GetSize(); 1830314564Sdim if (num_breakpoints == 0) { 1831314564Sdim result.SetError("No breakpoints, cannot delete names."); 1832314564Sdim result.SetStatus(eReturnStatusFailed); 1833314564Sdim return false; 1834314564Sdim } 1835280031Sdim 1836314564Sdim // Particular breakpoint selected; disable that breakpoint. 1837314564Sdim BreakpointIDList valid_bp_ids; 1838314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1839360784Sdim command, &target, result, &valid_bp_ids, 1840327952Sdim BreakpointName::Permissions::PermissionKinds::deletePerm); 1841309124Sdim 1842314564Sdim if (result.Succeeded()) { 1843314564Sdim if (valid_bp_ids.GetSize() == 0) { 1844314564Sdim result.SetError("No breakpoints specified, cannot delete names."); 1845314564Sdim result.SetStatus(eReturnStatusFailed); 1846314564Sdim return false; 1847314564Sdim } 1848327952Sdim ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 1849314564Sdim size_t num_valid_ids = valid_bp_ids.GetSize(); 1850314564Sdim for (size_t index = 0; index < num_valid_ids; index++) { 1851314564Sdim lldb::break_id_t bp_id = 1852314564Sdim valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1853314564Sdim BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1854360784Sdim target.RemoveNameFromBreakpoint(bp_sp, bp_name); 1855314564Sdim } 1856314564Sdim } 1857280031Sdim 1858314564Sdim return true; 1859314564Sdim } 1860280031Sdim 1861314564Sdimprivate: 1862314564Sdim BreakpointNameOptionGroup m_name_options; 1863314564Sdim OptionGroupOptions m_option_group; 1864314564Sdim}; 1865280031Sdim 1866314564Sdimclass CommandObjectBreakpointNameList : public CommandObjectParsed { 1867314564Sdimpublic: 1868314564Sdim CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1869314564Sdim : CommandObjectParsed(interpreter, "list", 1870327952Sdim "List either the names for a breakpoint or info " 1871327952Sdim "about a given name. With no arguments, lists all " 1872327952Sdim "names", 1873314564Sdim "breakpoint name list <command-options>"), 1874314564Sdim m_name_options(), m_option_group() { 1875327952Sdim m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 1876314564Sdim m_option_group.Finalize(); 1877314564Sdim } 1878314564Sdim 1879314564Sdim ~CommandObjectBreakpointNameList() override = default; 1880314564Sdim 1881314564Sdim Options *GetOptions() override { return &m_option_group; } 1882314564Sdim 1883314564Sdimprotected: 1884314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1885360784Sdim Target &target = 1886314564Sdim GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1887314564Sdim 1888327952Sdim std::vector<std::string> name_list; 1889327952Sdim if (command.empty()) { 1890360784Sdim target.GetBreakpointNames(name_list); 1891327952Sdim } else { 1892360784Sdim for (const Args::ArgEntry &arg : command) { 1893327952Sdim name_list.push_back(arg.c_str()); 1894327952Sdim } 1895327952Sdim } 1896360784Sdim 1897327952Sdim if (name_list.empty()) { 1898327952Sdim result.AppendMessage("No breakpoint names found."); 1899327952Sdim } else { 1900327952Sdim for (const std::string &name_str : name_list) { 1901327952Sdim const char *name = name_str.c_str(); 1902327952Sdim // First print out the options for the name: 1903327952Sdim Status error; 1904360784Sdim BreakpointName *bp_name = 1905360784Sdim target.FindBreakpointName(ConstString(name), false, error); 1906360784Sdim if (bp_name) { 1907327952Sdim StreamString s; 1908327952Sdim result.AppendMessageWithFormat("Name: %s\n", name); 1909360784Sdim if (bp_name->GetDescription(&s, eDescriptionLevelFull)) { 1910327952Sdim result.AppendMessage(s.GetString()); 1911327952Sdim } 1912360784Sdim 1913327952Sdim std::unique_lock<std::recursive_mutex> lock; 1914360784Sdim target.GetBreakpointList().GetListMutex(lock); 1915314564Sdim 1916360784Sdim BreakpointList &breakpoints = target.GetBreakpointList(); 1917327952Sdim bool any_set = false; 1918327952Sdim for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 1919327952Sdim if (bp_sp->MatchesName(name)) { 1920327952Sdim StreamString s; 1921327952Sdim any_set = true; 1922327952Sdim bp_sp->GetDescription(&s, eDescriptionLevelBrief); 1923327952Sdim s.EOL(); 1924327952Sdim result.AppendMessage(s.GetString()); 1925327952Sdim } 1926327952Sdim } 1927327952Sdim if (!any_set) 1928327952Sdim result.AppendMessage("No breakpoints using this name."); 1929327952Sdim } else { 1930327952Sdim result.AppendMessageWithFormat("Name: %s not found.\n", name); 1931280031Sdim } 1932314564Sdim } 1933280031Sdim } 1934314564Sdim return true; 1935314564Sdim } 1936280031Sdim 1937280031Sdimprivate: 1938314564Sdim BreakpointNameOptionGroup m_name_options; 1939314564Sdim OptionGroupOptions m_option_group; 1940280031Sdim}; 1941280031Sdim 1942314564Sdim// CommandObjectBreakpointName 1943314564Sdimclass CommandObjectBreakpointName : public CommandObjectMultiword { 1944280031Sdimpublic: 1945314564Sdim CommandObjectBreakpointName(CommandInterpreter &interpreter) 1946314564Sdim : CommandObjectMultiword( 1947314564Sdim interpreter, "name", "Commands to manage name tags for breakpoints", 1948314564Sdim "breakpoint name <subcommand> [<command-options>]") { 1949314564Sdim CommandObjectSP add_command_object( 1950314564Sdim new CommandObjectBreakpointNameAdd(interpreter)); 1951314564Sdim CommandObjectSP delete_command_object( 1952314564Sdim new CommandObjectBreakpointNameDelete(interpreter)); 1953314564Sdim CommandObjectSP list_command_object( 1954314564Sdim new CommandObjectBreakpointNameList(interpreter)); 1955327952Sdim CommandObjectSP configure_command_object( 1956327952Sdim new CommandObjectBreakpointNameConfigure(interpreter)); 1957314564Sdim 1958314564Sdim LoadSubCommand("add", add_command_object); 1959314564Sdim LoadSubCommand("delete", delete_command_object); 1960314564Sdim LoadSubCommand("list", list_command_object); 1961327952Sdim LoadSubCommand("configure", configure_command_object); 1962314564Sdim } 1963314564Sdim 1964314564Sdim ~CommandObjectBreakpointName() override = default; 1965314564Sdim}; 1966314564Sdim 1967314564Sdim// CommandObjectBreakpointRead 1968314564Sdim#pragma mark Read::CommandOptions 1969360784Sdim#define LLDB_OPTIONS_breakpoint_read 1970360784Sdim#include "CommandOptions.inc" 1971314564Sdim 1972314564Sdim#pragma mark Read 1973314564Sdim 1974314564Sdimclass CommandObjectBreakpointRead : public CommandObjectParsed { 1975314564Sdimpublic: 1976314564Sdim CommandObjectBreakpointRead(CommandInterpreter &interpreter) 1977314564Sdim : CommandObjectParsed(interpreter, "breakpoint read", 1978314564Sdim "Read and set the breakpoints previously saved to " 1979314564Sdim "a file with \"breakpoint write\". ", 1980314564Sdim nullptr), 1981314564Sdim m_options() { 1982314564Sdim CommandArgumentEntry arg; 1983314564Sdim CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1984314564Sdim eArgTypeBreakpointIDRange); 1985314564Sdim // Add the entry for the first argument for this command to the object's 1986314564Sdim // arguments vector. 1987314564Sdim m_arguments.push_back(arg); 1988314564Sdim } 1989314564Sdim 1990314564Sdim ~CommandObjectBreakpointRead() override = default; 1991314564Sdim 1992314564Sdim Options *GetOptions() override { return &m_options; } 1993314564Sdim 1994314564Sdim class CommandOptions : public Options { 1995314564Sdim public: 1996314564Sdim CommandOptions() : Options() {} 1997314564Sdim 1998314564Sdim ~CommandOptions() override = default; 1999314564Sdim 2000321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2001321369Sdim ExecutionContext *execution_context) override { 2002321369Sdim Status error; 2003314564Sdim const int short_option = m_getopt_table[option_idx].val; 2004314564Sdim 2005314564Sdim switch (short_option) { 2006314564Sdim case 'f': 2007314564Sdim m_filename.assign(option_arg); 2008314564Sdim break; 2009314564Sdim case 'N': { 2010321369Sdim Status name_error; 2011314564Sdim if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 2012314564Sdim name_error)) { 2013314564Sdim error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 2014314564Sdim name_error.AsCString()); 2015314564Sdim } 2016314564Sdim m_names.push_back(option_arg); 2017314564Sdim break; 2018314564Sdim } 2019314564Sdim default: 2020360784Sdim llvm_unreachable("Unimplemented option"); 2021314564Sdim } 2022314564Sdim 2023314564Sdim return error; 2024280031Sdim } 2025280031Sdim 2026314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 2027314564Sdim m_filename.clear(); 2028314564Sdim m_names.clear(); 2029314564Sdim } 2030280031Sdim 2031314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2032314564Sdim return llvm::makeArrayRef(g_breakpoint_read_options); 2033309124Sdim } 2034309124Sdim 2035314564Sdim // Instance variables to hold the values for command options. 2036314564Sdim 2037314564Sdim std::string m_filename; 2038314564Sdim std::vector<std::string> m_names; 2039314564Sdim }; 2040314564Sdim 2041280031Sdimprotected: 2042314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 2043360784Sdim Target &target = GetSelectedOrDummyTarget(); 2044280031Sdim 2045314564Sdim std::unique_lock<std::recursive_mutex> lock; 2046360784Sdim target.GetBreakpointList().GetListMutex(lock); 2047280031Sdim 2048344779Sdim FileSpec input_spec(m_options.m_filename); 2049344779Sdim FileSystem::Instance().Resolve(input_spec); 2050314564Sdim BreakpointIDList new_bps; 2051360784Sdim Status error = target.CreateBreakpointsFromFile(input_spec, 2052360784Sdim m_options.m_names, new_bps); 2053309124Sdim 2054314564Sdim if (!error.Success()) { 2055314564Sdim result.AppendError(error.AsCString()); 2056314564Sdim result.SetStatus(eReturnStatusFailed); 2057314564Sdim return false; 2058314564Sdim } 2059280031Sdim 2060314564Sdim Stream &output_stream = result.GetOutputStream(); 2061314564Sdim 2062314564Sdim size_t num_breakpoints = new_bps.GetSize(); 2063314564Sdim if (num_breakpoints == 0) { 2064314564Sdim result.AppendMessage("No breakpoints added."); 2065314564Sdim } else { 2066314564Sdim // No breakpoint selected; show info about all currently set breakpoints. 2067314564Sdim result.AppendMessage("New breakpoints:"); 2068314564Sdim for (size_t i = 0; i < num_breakpoints; ++i) { 2069314564Sdim BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2070360784Sdim Breakpoint *bp = target.GetBreakpointList() 2071314564Sdim .FindBreakpointByID(bp_id.GetBreakpointID()) 2072314564Sdim .get(); 2073314564Sdim if (bp) 2074314564Sdim bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 2075314564Sdim false); 2076314564Sdim } 2077280031Sdim } 2078314564Sdim return result.Succeeded(); 2079314564Sdim } 2080280031Sdim 2081280031Sdimprivate: 2082314564Sdim CommandOptions m_options; 2083280031Sdim}; 2084280031Sdim 2085314564Sdim// CommandObjectBreakpointWrite 2086314564Sdim#pragma mark Write::CommandOptions 2087360784Sdim#define LLDB_OPTIONS_breakpoint_write 2088360784Sdim#include "CommandOptions.inc" 2089314564Sdim 2090314564Sdim#pragma mark Write 2091314564Sdimclass CommandObjectBreakpointWrite : public CommandObjectParsed { 2092280031Sdimpublic: 2093314564Sdim CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2094314564Sdim : CommandObjectParsed(interpreter, "breakpoint write", 2095314564Sdim "Write the breakpoints listed to a file that can " 2096314564Sdim "be read in with \"breakpoint read\". " 2097314564Sdim "If given no arguments, writes all breakpoints.", 2098314564Sdim nullptr), 2099314564Sdim m_options() { 2100314564Sdim CommandArgumentEntry arg; 2101314564Sdim CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2102314564Sdim eArgTypeBreakpointIDRange); 2103314564Sdim // Add the entry for the first argument for this command to the object's 2104314564Sdim // arguments vector. 2105314564Sdim m_arguments.push_back(arg); 2106314564Sdim } 2107280031Sdim 2108314564Sdim ~CommandObjectBreakpointWrite() override = default; 2109314564Sdim 2110314564Sdim Options *GetOptions() override { return &m_options; } 2111314564Sdim 2112314564Sdim class CommandOptions : public Options { 2113314564Sdim public: 2114314564Sdim CommandOptions() : Options() {} 2115314564Sdim 2116314564Sdim ~CommandOptions() override = default; 2117314564Sdim 2118321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2119321369Sdim ExecutionContext *execution_context) override { 2120321369Sdim Status error; 2121314564Sdim const int short_option = m_getopt_table[option_idx].val; 2122314564Sdim 2123314564Sdim switch (short_option) { 2124314564Sdim case 'f': 2125314564Sdim m_filename.assign(option_arg); 2126314564Sdim break; 2127314564Sdim case 'a': 2128314564Sdim m_append = true; 2129314564Sdim break; 2130314564Sdim default: 2131360784Sdim llvm_unreachable("Unimplemented option"); 2132314564Sdim } 2133314564Sdim 2134314564Sdim return error; 2135280031Sdim } 2136280031Sdim 2137314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 2138314564Sdim m_filename.clear(); 2139314564Sdim m_append = false; 2140314564Sdim } 2141314564Sdim 2142314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2143314564Sdim return llvm::makeArrayRef(g_breakpoint_write_options); 2144314564Sdim } 2145314564Sdim 2146314564Sdim // Instance variables to hold the values for command options. 2147314564Sdim 2148314564Sdim std::string m_filename; 2149314564Sdim bool m_append = false; 2150314564Sdim }; 2151314564Sdim 2152314564Sdimprotected: 2153314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 2154360784Sdim Target &target = GetSelectedOrDummyTarget(); 2155314564Sdim 2156314564Sdim std::unique_lock<std::recursive_mutex> lock; 2157360784Sdim target.GetBreakpointList().GetListMutex(lock); 2158314564Sdim 2159314564Sdim BreakpointIDList valid_bp_ids; 2160314564Sdim if (!command.empty()) { 2161314564Sdim CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2162360784Sdim command, &target, result, &valid_bp_ids, 2163327952Sdim BreakpointName::Permissions::PermissionKinds::listPerm); 2164314564Sdim 2165314564Sdim if (!result.Succeeded()) { 2166314564Sdim result.SetStatus(eReturnStatusFailed); 2167314564Sdim return false; 2168314564Sdim } 2169314564Sdim } 2170344779Sdim FileSpec file_spec(m_options.m_filename); 2171344779Sdim FileSystem::Instance().Resolve(file_spec); 2172360784Sdim Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 2173360784Sdim m_options.m_append); 2174314564Sdim if (!error.Success()) { 2175314564Sdim result.AppendErrorWithFormat("error serializing breakpoints: %s.", 2176314564Sdim error.AsCString()); 2177314564Sdim result.SetStatus(eReturnStatusFailed); 2178314564Sdim } 2179314564Sdim return result.Succeeded(); 2180314564Sdim } 2181314564Sdim 2182314564Sdimprivate: 2183314564Sdim CommandOptions m_options; 2184280031Sdim}; 2185280031Sdim 2186280031Sdim// CommandObjectMultiwordBreakpoint 2187254721Semaste#pragma mark MultiwordBreakpoint 2188254721Semaste 2189314564SdimCommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2190314564Sdim CommandInterpreter &interpreter) 2191314564Sdim : CommandObjectMultiword( 2192314564Sdim interpreter, "breakpoint", 2193314564Sdim "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2194314564Sdim "breakpoint <subcommand> [<command-options>]") { 2195314564Sdim CommandObjectSP list_command_object( 2196314564Sdim new CommandObjectBreakpointList(interpreter)); 2197314564Sdim CommandObjectSP enable_command_object( 2198314564Sdim new CommandObjectBreakpointEnable(interpreter)); 2199314564Sdim CommandObjectSP disable_command_object( 2200314564Sdim new CommandObjectBreakpointDisable(interpreter)); 2201314564Sdim CommandObjectSP clear_command_object( 2202314564Sdim new CommandObjectBreakpointClear(interpreter)); 2203314564Sdim CommandObjectSP delete_command_object( 2204314564Sdim new CommandObjectBreakpointDelete(interpreter)); 2205314564Sdim CommandObjectSP set_command_object( 2206314564Sdim new CommandObjectBreakpointSet(interpreter)); 2207314564Sdim CommandObjectSP command_command_object( 2208314564Sdim new CommandObjectBreakpointCommand(interpreter)); 2209314564Sdim CommandObjectSP modify_command_object( 2210314564Sdim new CommandObjectBreakpointModify(interpreter)); 2211314564Sdim CommandObjectSP name_command_object( 2212314564Sdim new CommandObjectBreakpointName(interpreter)); 2213314564Sdim CommandObjectSP write_command_object( 2214314564Sdim new CommandObjectBreakpointWrite(interpreter)); 2215314564Sdim CommandObjectSP read_command_object( 2216314564Sdim new CommandObjectBreakpointRead(interpreter)); 2217254721Semaste 2218314564Sdim list_command_object->SetCommandName("breakpoint list"); 2219314564Sdim enable_command_object->SetCommandName("breakpoint enable"); 2220314564Sdim disable_command_object->SetCommandName("breakpoint disable"); 2221314564Sdim clear_command_object->SetCommandName("breakpoint clear"); 2222314564Sdim delete_command_object->SetCommandName("breakpoint delete"); 2223314564Sdim set_command_object->SetCommandName("breakpoint set"); 2224314564Sdim command_command_object->SetCommandName("breakpoint command"); 2225314564Sdim modify_command_object->SetCommandName("breakpoint modify"); 2226314564Sdim name_command_object->SetCommandName("breakpoint name"); 2227314564Sdim write_command_object->SetCommandName("breakpoint write"); 2228314564Sdim read_command_object->SetCommandName("breakpoint read"); 2229254721Semaste 2230314564Sdim LoadSubCommand("list", list_command_object); 2231314564Sdim LoadSubCommand("enable", enable_command_object); 2232314564Sdim LoadSubCommand("disable", disable_command_object); 2233314564Sdim LoadSubCommand("clear", clear_command_object); 2234314564Sdim LoadSubCommand("delete", delete_command_object); 2235314564Sdim LoadSubCommand("set", set_command_object); 2236314564Sdim LoadSubCommand("command", command_command_object); 2237314564Sdim LoadSubCommand("modify", modify_command_object); 2238314564Sdim LoadSubCommand("name", name_command_object); 2239314564Sdim LoadSubCommand("write", write_command_object); 2240314564Sdim LoadSubCommand("read", read_command_object); 2241254721Semaste} 2242254721Semaste 2243309124SdimCommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 2244254721Semaste 2245360784Sdimvoid CommandObjectMultiwordBreakpoint::VerifyIDs( 2246360784Sdim Args &args, Target *target, bool allow_locations, 2247360784Sdim CommandReturnObject &result, BreakpointIDList *valid_ids, 2248360784Sdim BreakpointName::Permissions ::PermissionKinds purpose) { 2249314564Sdim // args can be strings representing 1). integers (for breakpoint ids) 2250314564Sdim // 2). the full breakpoint & location 2251314564Sdim // canonical representation 2252314564Sdim // 3). the word "to" or a hyphen, 2253314564Sdim // representing a range (in which case there 2254314564Sdim // had *better* be an entry both before & 2255314564Sdim // after of one of the first two types. 2256314564Sdim // 4). A breakpoint name 2257314564Sdim // If args is empty, we will use the last created breakpoint (if there is 2258314564Sdim // one.) 2259254721Semaste 2260314564Sdim Args temp_args; 2261254721Semaste 2262314564Sdim if (args.empty()) { 2263314564Sdim if (target->GetLastCreatedBreakpoint()) { 2264314564Sdim valid_ids->AddBreakpointID(BreakpointID( 2265314564Sdim target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 2266314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 2267314564Sdim } else { 2268314564Sdim result.AppendError( 2269314564Sdim "No breakpoint specified and no last created breakpoint."); 2270314564Sdim result.SetStatus(eReturnStatusFailed); 2271254721Semaste } 2272314564Sdim return; 2273314564Sdim } 2274254721Semaste 2275314564Sdim // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2276341825Sdim // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 2277341825Sdim // id range strings over; instead generate a list of strings for all the 2278341825Sdim // breakpoint ids in the range, and shove all of those breakpoint id strings 2279341825Sdim // into TEMP_ARGS. 2280254721Semaste 2281360784Sdim BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2282327952Sdim purpose, result, temp_args); 2283254721Semaste 2284314564Sdim // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2285314564Sdim // BreakpointIDList: 2286254721Semaste 2287341825Sdim valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 2288254721Semaste 2289341825Sdim // At this point, all of the breakpoint ids that the user passed in have 2290341825Sdim // been converted to breakpoint IDs and put into valid_ids. 2291254721Semaste 2292314564Sdim if (result.Succeeded()) { 2293314564Sdim // Now that we've converted everything from args into a list of breakpoint 2294341825Sdim // ids, go through our tentative list of breakpoint id's and verify that 2295341825Sdim // they correspond to valid/currently set breakpoints. 2296314564Sdim 2297314564Sdim const size_t count = valid_ids->GetSize(); 2298314564Sdim for (size_t i = 0; i < count; ++i) { 2299314564Sdim BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2300314564Sdim Breakpoint *breakpoint = 2301314564Sdim target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2302314564Sdim if (breakpoint != nullptr) { 2303314564Sdim const size_t num_locations = breakpoint->GetNumLocations(); 2304314564Sdim if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 2305314564Sdim StreamString id_str; 2306314564Sdim BreakpointID::GetCanonicalReference( 2307314564Sdim &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2308314564Sdim i = valid_ids->GetSize() + 1; 2309314564Sdim result.AppendErrorWithFormat( 2310314564Sdim "'%s' is not a currently valid breakpoint/location id.\n", 2311314564Sdim id_str.GetData()); 2312314564Sdim result.SetStatus(eReturnStatusFailed); 2313254721Semaste } 2314314564Sdim } else { 2315314564Sdim i = valid_ids->GetSize() + 1; 2316314564Sdim result.AppendErrorWithFormat( 2317314564Sdim "'%d' is not a currently valid breakpoint ID.\n", 2318314564Sdim cur_bp_id.GetBreakpointID()); 2319314564Sdim result.SetStatus(eReturnStatusFailed); 2320314564Sdim } 2321254721Semaste } 2322314564Sdim } 2323254721Semaste} 2324