1 //===-- CommandObjectType.cpp ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CommandObjectType.h" 10 11 #include "lldb/Core/Debugger.h" 12 #include "lldb/Core/IOHandler.h" 13 #include "lldb/DataFormatters/DataVisualization.h" 14 #include "lldb/Host/Config.h" 15 #include "lldb/Host/OptionParser.h" 16 #include "lldb/Interpreter/CommandInterpreter.h" 17 #include "lldb/Interpreter/CommandObject.h" 18 #include "lldb/Interpreter/CommandReturnObject.h" 19 #include "lldb/Interpreter/OptionArgParser.h" 20 #include "lldb/Interpreter/OptionGroupFormat.h" 21 #include "lldb/Interpreter/OptionValueBoolean.h" 22 #include "lldb/Interpreter/OptionValueLanguage.h" 23 #include "lldb/Interpreter/OptionValueString.h" 24 #include "lldb/Interpreter/Options.h" 25 #include "lldb/Symbol/Symbol.h" 26 #include "lldb/Target/Language.h" 27 #include "lldb/Target/StackFrame.h" 28 #include "lldb/Target/Target.h" 29 #include "lldb/Target/Thread.h" 30 #include "lldb/Utility/ConstString.h" 31 #include "lldb/Utility/RegularExpression.h" 32 #include "lldb/Utility/StringList.h" 33 34 #include "llvm/ADT/STLExtras.h" 35 36 #include <algorithm> 37 #include <functional> 38 #include <memory> 39 40 #define CHECK_FORMATTER_KIND_MASK(VAL) \ 41 ((m_formatter_kind_mask & (VAL)) == (VAL)) 42 43 using namespace lldb; 44 using namespace lldb_private; 45 46 class ScriptAddOptions { 47 public: 48 TypeSummaryImpl::Flags m_flags; 49 StringList m_target_types; 50 bool m_regex; 51 ConstString m_name; 52 std::string m_category; 53 54 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx, 55 ConstString name, std::string catg) 56 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {} 57 58 typedef std::shared_ptr<ScriptAddOptions> SharedPointer; 59 }; 60 61 class SynthAddOptions { 62 public: 63 bool m_skip_pointers; 64 bool m_skip_references; 65 bool m_cascade; 66 bool m_regex; 67 StringList m_target_types; 68 std::string m_category; 69 70 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg) 71 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc), 72 m_regex(regx), m_target_types(), m_category(catg) {} 73 74 typedef std::shared_ptr<SynthAddOptions> SharedPointer; 75 }; 76 77 static bool WarnOnPotentialUnquotedUnsignedType(Args &command, 78 CommandReturnObject &result) { 79 if (command.empty()) 80 return false; 81 82 for (auto entry : llvm::enumerate(command.entries().drop_back())) { 83 if (entry.value().ref() != "unsigned") 84 continue; 85 auto next = command.entries()[entry.index() + 1].ref(); 86 if (next == "int" || next == "short" || next == "char" || next == "long") { 87 result.AppendWarningWithFormat( 88 "unsigned %s being treated as two types. if you meant the combined " 89 "type " 90 "name use quotes, as in \"unsigned %s\"\n", 91 next.str().c_str(), next.str().c_str()); 92 return true; 93 } 94 } 95 return false; 96 } 97 98 #define LLDB_OPTIONS_type_summary_add 99 #include "CommandOptions.inc" 100 101 class CommandObjectTypeSummaryAdd : public CommandObjectParsed, 102 public IOHandlerDelegateMultiline { 103 private: 104 class CommandOptions : public Options { 105 public: 106 CommandOptions(CommandInterpreter &interpreter) : Options() {} 107 108 ~CommandOptions() override = default; 109 110 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 111 ExecutionContext *execution_context) override; 112 113 void OptionParsingStarting(ExecutionContext *execution_context) override; 114 115 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 116 return llvm::makeArrayRef(g_type_summary_add_options); 117 } 118 119 // Instance variables to hold the values for command options. 120 121 TypeSummaryImpl::Flags m_flags; 122 bool m_regex; 123 std::string m_format_string; 124 ConstString m_name; 125 std::string m_python_script; 126 std::string m_python_function; 127 bool m_is_add_script; 128 std::string m_category; 129 }; 130 131 CommandOptions m_options; 132 133 Options *GetOptions() override { return &m_options; } 134 135 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result); 136 137 bool Execute_StringSummary(Args &command, CommandReturnObject &result); 138 139 public: 140 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary }; 141 142 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter); 143 144 ~CommandObjectTypeSummaryAdd() override = default; 145 146 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 147 static const char *g_summary_addreader_instructions = 148 "Enter your Python command(s). Type 'DONE' to end.\n" 149 "def function (valobj,internal_dict):\n" 150 " \"\"\"valobj: an SBValue which you want to provide a summary " 151 "for\n" 152 " internal_dict: an LLDB support object not to be used\"\"\"\n"; 153 154 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 155 if (output_sp && interactive) { 156 output_sp->PutCString(g_summary_addreader_instructions); 157 output_sp->Flush(); 158 } 159 } 160 161 void IOHandlerInputComplete(IOHandler &io_handler, 162 std::string &data) override { 163 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); 164 165 #if LLDB_ENABLE_PYTHON 166 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 167 if (interpreter) { 168 StringList lines; 169 lines.SplitIntoLines(data); 170 if (lines.GetSize() > 0) { 171 ScriptAddOptions *options_ptr = 172 ((ScriptAddOptions *)io_handler.GetUserData()); 173 if (options_ptr) { 174 ScriptAddOptions::SharedPointer options( 175 options_ptr); // this will ensure that we get rid of the pointer 176 // when going out of scope 177 178 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 179 if (interpreter) { 180 std::string funct_name_str; 181 if (interpreter->GenerateTypeScriptFunction(lines, 182 funct_name_str)) { 183 if (funct_name_str.empty()) { 184 error_sp->Printf("unable to obtain a valid function name from " 185 "the script interpreter.\n"); 186 error_sp->Flush(); 187 } else { 188 // now I have a valid function name, let's add this as script 189 // for every type in the list 190 191 TypeSummaryImplSP script_format; 192 script_format = std::make_shared<ScriptSummaryFormat>( 193 options->m_flags, funct_name_str.c_str(), 194 lines.CopyList(" ").c_str()); 195 196 Status error; 197 198 for (const std::string &type_name : options->m_target_types) { 199 CommandObjectTypeSummaryAdd::AddSummary( 200 ConstString(type_name), script_format, 201 (options->m_regex 202 ? CommandObjectTypeSummaryAdd::eRegexSummary 203 : CommandObjectTypeSummaryAdd::eRegularSummary), 204 options->m_category, &error); 205 if (error.Fail()) { 206 error_sp->Printf("error: %s", error.AsCString()); 207 error_sp->Flush(); 208 } 209 } 210 211 if (options->m_name) { 212 CommandObjectTypeSummaryAdd::AddSummary( 213 options->m_name, script_format, 214 CommandObjectTypeSummaryAdd::eNamedSummary, 215 options->m_category, &error); 216 if (error.Fail()) { 217 CommandObjectTypeSummaryAdd::AddSummary( 218 options->m_name, script_format, 219 CommandObjectTypeSummaryAdd::eNamedSummary, 220 options->m_category, &error); 221 if (error.Fail()) { 222 error_sp->Printf("error: %s", error.AsCString()); 223 error_sp->Flush(); 224 } 225 } else { 226 error_sp->Printf("error: %s", error.AsCString()); 227 error_sp->Flush(); 228 } 229 } else { 230 if (error.AsCString()) { 231 error_sp->Printf("error: %s", error.AsCString()); 232 error_sp->Flush(); 233 } 234 } 235 } 236 } else { 237 error_sp->Printf("error: unable to generate a function.\n"); 238 error_sp->Flush(); 239 } 240 } else { 241 error_sp->Printf("error: no script interpreter.\n"); 242 error_sp->Flush(); 243 } 244 } else { 245 error_sp->Printf("error: internal synchronization information " 246 "missing or invalid.\n"); 247 error_sp->Flush(); 248 } 249 } else { 250 error_sp->Printf("error: empty function, didn't add python command.\n"); 251 error_sp->Flush(); 252 } 253 } else { 254 error_sp->Printf( 255 "error: script interpreter missing, didn't add python command.\n"); 256 error_sp->Flush(); 257 } 258 #endif 259 io_handler.SetIsDone(true); 260 } 261 262 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, 263 SummaryFormatType type, std::string category, 264 Status *error = nullptr); 265 266 protected: 267 bool DoExecute(Args &command, CommandReturnObject &result) override; 268 }; 269 270 static const char *g_synth_addreader_instructions = 271 "Enter your Python command(s). Type 'DONE' to end.\n" 272 "You must define a Python class with these methods:\n" 273 " def __init__(self, valobj, internal_dict):\n" 274 " def num_children(self):\n" 275 " def get_child_at_index(self, index):\n" 276 " def get_child_index(self, name):\n" 277 " def update(self):\n" 278 " '''Optional'''\n" 279 "class synthProvider:\n"; 280 281 #define LLDB_OPTIONS_type_synth_add 282 #include "CommandOptions.inc" 283 284 class CommandObjectTypeSynthAdd : public CommandObjectParsed, 285 public IOHandlerDelegateMultiline { 286 private: 287 class CommandOptions : public Options { 288 public: 289 CommandOptions() : Options() {} 290 291 ~CommandOptions() override = default; 292 293 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 294 ExecutionContext *execution_context) override { 295 Status error; 296 const int short_option = m_getopt_table[option_idx].val; 297 bool success; 298 299 switch (short_option) { 300 case 'C': 301 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success); 302 if (!success) 303 error.SetErrorStringWithFormat("invalid value for cascade: %s", 304 option_arg.str().c_str()); 305 break; 306 case 'P': 307 handwrite_python = true; 308 break; 309 case 'l': 310 m_class_name = std::string(option_arg); 311 is_class_based = true; 312 break; 313 case 'p': 314 m_skip_pointers = true; 315 break; 316 case 'r': 317 m_skip_references = true; 318 break; 319 case 'w': 320 m_category = std::string(option_arg); 321 break; 322 case 'x': 323 m_regex = true; 324 break; 325 default: 326 llvm_unreachable("Unimplemented option"); 327 } 328 329 return error; 330 } 331 332 void OptionParsingStarting(ExecutionContext *execution_context) override { 333 m_cascade = true; 334 m_class_name = ""; 335 m_skip_pointers = false; 336 m_skip_references = false; 337 m_category = "default"; 338 is_class_based = false; 339 handwrite_python = false; 340 m_regex = false; 341 } 342 343 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 344 return llvm::makeArrayRef(g_type_synth_add_options); 345 } 346 347 // Instance variables to hold the values for command options. 348 349 bool m_cascade; 350 bool m_skip_references; 351 bool m_skip_pointers; 352 std::string m_class_name; 353 bool m_input_python; 354 std::string m_category; 355 bool is_class_based; 356 bool handwrite_python; 357 bool m_regex; 358 }; 359 360 CommandOptions m_options; 361 362 Options *GetOptions() override { return &m_options; } 363 364 bool Execute_HandwritePython(Args &command, CommandReturnObject &result); 365 366 bool Execute_PythonClass(Args &command, CommandReturnObject &result); 367 368 protected: 369 bool DoExecute(Args &command, CommandReturnObject &result) override { 370 WarnOnPotentialUnquotedUnsignedType(command, result); 371 372 if (m_options.handwrite_python) 373 return Execute_HandwritePython(command, result); 374 else if (m_options.is_class_based) 375 return Execute_PythonClass(command, result); 376 else { 377 result.AppendError("must either provide a children list, a Python class " 378 "name, or use -P and type a Python class " 379 "line-by-line"); 380 result.SetStatus(eReturnStatusFailed); 381 return false; 382 } 383 } 384 385 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 386 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 387 if (output_sp && interactive) { 388 output_sp->PutCString(g_synth_addreader_instructions); 389 output_sp->Flush(); 390 } 391 } 392 393 void IOHandlerInputComplete(IOHandler &io_handler, 394 std::string &data) override { 395 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); 396 397 #if LLDB_ENABLE_PYTHON 398 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 399 if (interpreter) { 400 StringList lines; 401 lines.SplitIntoLines(data); 402 if (lines.GetSize() > 0) { 403 SynthAddOptions *options_ptr = 404 ((SynthAddOptions *)io_handler.GetUserData()); 405 if (options_ptr) { 406 SynthAddOptions::SharedPointer options( 407 options_ptr); // this will ensure that we get rid of the pointer 408 // when going out of scope 409 410 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 411 if (interpreter) { 412 std::string class_name_str; 413 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) { 414 if (class_name_str.empty()) { 415 error_sp->Printf( 416 "error: unable to obtain a proper name for the class.\n"); 417 error_sp->Flush(); 418 } else { 419 // everything should be fine now, let's add the synth provider 420 // class 421 422 SyntheticChildrenSP synth_provider; 423 synth_provider = std::make_shared<ScriptedSyntheticChildren>( 424 SyntheticChildren::Flags() 425 .SetCascades(options->m_cascade) 426 .SetSkipPointers(options->m_skip_pointers) 427 .SetSkipReferences(options->m_skip_references), 428 class_name_str.c_str()); 429 430 lldb::TypeCategoryImplSP category; 431 DataVisualization::Categories::GetCategory( 432 ConstString(options->m_category.c_str()), category); 433 434 Status error; 435 436 for (const std::string &type_name : options->m_target_types) { 437 if (!type_name.empty()) { 438 if (!CommandObjectTypeSynthAdd::AddSynth( 439 ConstString(type_name), synth_provider, 440 options->m_regex 441 ? CommandObjectTypeSynthAdd::eRegexSynth 442 : CommandObjectTypeSynthAdd::eRegularSynth, 443 options->m_category, &error)) { 444 error_sp->Printf("error: %s\n", error.AsCString()); 445 error_sp->Flush(); 446 break; 447 } 448 } else { 449 error_sp->Printf("error: invalid type name.\n"); 450 error_sp->Flush(); 451 break; 452 } 453 } 454 } 455 } else { 456 error_sp->Printf("error: unable to generate a class.\n"); 457 error_sp->Flush(); 458 } 459 } else { 460 error_sp->Printf("error: no script interpreter.\n"); 461 error_sp->Flush(); 462 } 463 } else { 464 error_sp->Printf("error: internal synchronization data missing.\n"); 465 error_sp->Flush(); 466 } 467 } else { 468 error_sp->Printf("error: empty function, didn't add python command.\n"); 469 error_sp->Flush(); 470 } 471 } else { 472 error_sp->Printf( 473 "error: script interpreter missing, didn't add python command.\n"); 474 error_sp->Flush(); 475 } 476 477 #endif 478 io_handler.SetIsDone(true); 479 } 480 481 public: 482 enum SynthFormatType { eRegularSynth, eRegexSynth }; 483 484 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter); 485 486 ~CommandObjectTypeSynthAdd() override = default; 487 488 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry, 489 SynthFormatType type, std::string category_name, 490 Status *error); 491 }; 492 493 // CommandObjectTypeFormatAdd 494 495 #define LLDB_OPTIONS_type_format_add 496 #include "CommandOptions.inc" 497 498 class CommandObjectTypeFormatAdd : public CommandObjectParsed { 499 private: 500 class CommandOptions : public OptionGroup { 501 public: 502 CommandOptions() : OptionGroup() {} 503 504 ~CommandOptions() override = default; 505 506 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 507 return llvm::makeArrayRef(g_type_format_add_options); 508 } 509 510 void OptionParsingStarting(ExecutionContext *execution_context) override { 511 m_cascade = true; 512 m_skip_pointers = false; 513 m_skip_references = false; 514 m_regex = false; 515 m_category.assign("default"); 516 m_custom_type_name.clear(); 517 } 518 519 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 520 ExecutionContext *execution_context) override { 521 Status error; 522 const int short_option = 523 g_type_format_add_options[option_idx].short_option; 524 bool success; 525 526 switch (short_option) { 527 case 'C': 528 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success); 529 if (!success) 530 error.SetErrorStringWithFormat("invalid value for cascade: %s", 531 option_value.str().c_str()); 532 break; 533 case 'p': 534 m_skip_pointers = true; 535 break; 536 case 'w': 537 m_category.assign(std::string(option_value)); 538 break; 539 case 'r': 540 m_skip_references = true; 541 break; 542 case 'x': 543 m_regex = true; 544 break; 545 case 't': 546 m_custom_type_name.assign(std::string(option_value)); 547 break; 548 default: 549 llvm_unreachable("Unimplemented option"); 550 } 551 552 return error; 553 } 554 555 // Instance variables to hold the values for command options. 556 557 bool m_cascade; 558 bool m_skip_references; 559 bool m_skip_pointers; 560 bool m_regex; 561 std::string m_category; 562 std::string m_custom_type_name; 563 }; 564 565 OptionGroupOptions m_option_group; 566 OptionGroupFormat m_format_options; 567 CommandOptions m_command_options; 568 569 Options *GetOptions() override { return &m_option_group; } 570 571 public: 572 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter) 573 : CommandObjectParsed(interpreter, "type format add", 574 "Add a new formatting style for a type.", nullptr), 575 m_option_group(), m_format_options(eFormatInvalid), 576 m_command_options() { 577 CommandArgumentEntry type_arg; 578 CommandArgumentData type_style_arg; 579 580 type_style_arg.arg_type = eArgTypeName; 581 type_style_arg.arg_repetition = eArgRepeatPlus; 582 583 type_arg.push_back(type_style_arg); 584 585 m_arguments.push_back(type_arg); 586 587 SetHelpLong( 588 R"( 589 The following examples of 'type format add' refer to this code snippet for context: 590 591 typedef int Aint; 592 typedef float Afloat; 593 typedef Aint Bint; 594 typedef Afloat Bfloat; 595 596 Aint ix = 5; 597 Bint iy = 5; 598 599 Afloat fx = 3.14; 600 BFloat fy = 3.14; 601 602 Adding default formatting: 603 604 (lldb) type format add -f hex AInt 605 (lldb) frame variable iy 606 607 )" 608 " Produces hexadecimal display of iy, because no formatter is available for Bint and \ 609 the one for Aint is used instead." 610 R"( 611 612 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains: 613 614 615 (lldb) type format add -f hex -C no AInt 616 617 Similar reasoning applies to this: 618 619 (lldb) type format add -f hex -C no float -p 620 621 )" 622 " All float values and float references are now formatted as hexadecimal, but not \ 623 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects."); 624 625 // Add the "--format" to all options groups 626 m_option_group.Append(&m_format_options, 627 OptionGroupFormat::OPTION_GROUP_FORMAT, 628 LLDB_OPT_SET_1); 629 m_option_group.Append(&m_command_options); 630 m_option_group.Finalize(); 631 } 632 633 ~CommandObjectTypeFormatAdd() override = default; 634 635 protected: 636 bool DoExecute(Args &command, CommandReturnObject &result) override { 637 const size_t argc = command.GetArgumentCount(); 638 639 if (argc < 1) { 640 result.AppendErrorWithFormat("%s takes one or more args.\n", 641 m_cmd_name.c_str()); 642 result.SetStatus(eReturnStatusFailed); 643 return false; 644 } 645 646 const Format format = m_format_options.GetFormat(); 647 if (format == eFormatInvalid && 648 m_command_options.m_custom_type_name.empty()) { 649 result.AppendErrorWithFormat("%s needs a valid format.\n", 650 m_cmd_name.c_str()); 651 result.SetStatus(eReturnStatusFailed); 652 return false; 653 } 654 655 TypeFormatImplSP entry; 656 657 if (m_command_options.m_custom_type_name.empty()) 658 entry = std::make_shared<TypeFormatImpl_Format>( 659 format, TypeFormatImpl::Flags() 660 .SetCascades(m_command_options.m_cascade) 661 .SetSkipPointers(m_command_options.m_skip_pointers) 662 .SetSkipReferences(m_command_options.m_skip_references)); 663 else 664 entry = std::make_shared<TypeFormatImpl_EnumType>( 665 ConstString(m_command_options.m_custom_type_name.c_str()), 666 TypeFormatImpl::Flags() 667 .SetCascades(m_command_options.m_cascade) 668 .SetSkipPointers(m_command_options.m_skip_pointers) 669 .SetSkipReferences(m_command_options.m_skip_references)); 670 671 // now I have a valid format, let's add it to every type 672 673 TypeCategoryImplSP category_sp; 674 DataVisualization::Categories::GetCategory( 675 ConstString(m_command_options.m_category), category_sp); 676 if (!category_sp) 677 return false; 678 679 WarnOnPotentialUnquotedUnsignedType(command, result); 680 681 for (auto &arg_entry : command.entries()) { 682 if (arg_entry.ref().empty()) { 683 result.AppendError("empty typenames not allowed"); 684 result.SetStatus(eReturnStatusFailed); 685 return false; 686 } 687 688 ConstString typeCS(arg_entry.ref()); 689 if (m_command_options.m_regex) { 690 RegularExpression typeRX(arg_entry.ref()); 691 if (!typeRX.IsValid()) { 692 result.AppendError( 693 "regex format error (maybe this is not really a regex?)"); 694 result.SetStatus(eReturnStatusFailed); 695 return false; 696 } 697 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); 698 category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX), 699 entry); 700 } else 701 category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry); 702 } 703 704 result.SetStatus(eReturnStatusSuccessFinishNoResult); 705 return result.Succeeded(); 706 } 707 }; 708 709 #define LLDB_OPTIONS_type_formatter_delete 710 #include "CommandOptions.inc" 711 712 class CommandObjectTypeFormatterDelete : public CommandObjectParsed { 713 protected: 714 class CommandOptions : public Options { 715 public: 716 CommandOptions() : Options() {} 717 718 ~CommandOptions() override = default; 719 720 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 721 ExecutionContext *execution_context) override { 722 Status error; 723 const int short_option = m_getopt_table[option_idx].val; 724 725 switch (short_option) { 726 case 'a': 727 m_delete_all = true; 728 break; 729 case 'w': 730 m_category = std::string(option_arg); 731 break; 732 case 'l': 733 m_language = Language::GetLanguageTypeFromString(option_arg); 734 break; 735 default: 736 llvm_unreachable("Unimplemented option"); 737 } 738 739 return error; 740 } 741 742 void OptionParsingStarting(ExecutionContext *execution_context) override { 743 m_delete_all = false; 744 m_category = "default"; 745 m_language = lldb::eLanguageTypeUnknown; 746 } 747 748 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 749 return llvm::makeArrayRef(g_type_formatter_delete_options); 750 } 751 752 // Instance variables to hold the values for command options. 753 754 bool m_delete_all; 755 std::string m_category; 756 lldb::LanguageType m_language; 757 }; 758 759 CommandOptions m_options; 760 uint32_t m_formatter_kind_mask; 761 762 Options *GetOptions() override { return &m_options; } 763 764 public: 765 CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter, 766 uint32_t formatter_kind_mask, 767 const char *name, const char *help) 768 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(), 769 m_formatter_kind_mask(formatter_kind_mask) { 770 CommandArgumentEntry type_arg; 771 CommandArgumentData type_style_arg; 772 773 type_style_arg.arg_type = eArgTypeName; 774 type_style_arg.arg_repetition = eArgRepeatPlain; 775 776 type_arg.push_back(type_style_arg); 777 778 m_arguments.push_back(type_arg); 779 } 780 781 ~CommandObjectTypeFormatterDelete() override = default; 782 783 void 784 HandleArgumentCompletion(CompletionRequest &request, 785 OptionElementVector &opt_element_vector) override { 786 if (request.GetCursorIndex()) 787 return; 788 789 DataVisualization::Categories::ForEach( 790 [this, &request](const lldb::TypeCategoryImplSP &category_sp) { 791 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemValue)) 792 category_sp->GetTypeFormatsContainer()->AutoComplete(request); 793 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexValue)) 794 category_sp->GetRegexTypeFormatsContainer()->AutoComplete(request); 795 796 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSummary)) 797 category_sp->GetTypeSummariesContainer()->AutoComplete(request); 798 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSummary)) 799 category_sp->GetRegexTypeSummariesContainer()->AutoComplete( 800 request); 801 802 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemFilter)) 803 category_sp->GetTypeFiltersContainer()->AutoComplete(request); 804 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexFilter)) 805 category_sp->GetRegexTypeFiltersContainer()->AutoComplete(request); 806 807 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemSynth)) 808 category_sp->GetTypeSyntheticsContainer()->AutoComplete(request); 809 if (CHECK_FORMATTER_KIND_MASK(eFormatCategoryItemRegexSynth)) 810 category_sp->GetRegexTypeSyntheticsContainer()->AutoComplete( 811 request); 812 return true; 813 }); 814 } 815 816 protected: 817 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; } 818 819 bool DoExecute(Args &command, CommandReturnObject &result) override { 820 const size_t argc = command.GetArgumentCount(); 821 822 if (argc != 1) { 823 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str()); 824 result.SetStatus(eReturnStatusFailed); 825 return false; 826 } 827 828 const char *typeA = command.GetArgumentAtIndex(0); 829 ConstString typeCS(typeA); 830 831 if (!typeCS) { 832 result.AppendError("empty typenames not allowed"); 833 result.SetStatus(eReturnStatusFailed); 834 return false; 835 } 836 837 if (m_options.m_delete_all) { 838 DataVisualization::Categories::ForEach( 839 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool { 840 category_sp->Delete(typeCS, m_formatter_kind_mask); 841 return true; 842 }); 843 result.SetStatus(eReturnStatusSuccessFinishNoResult); 844 return result.Succeeded(); 845 } 846 847 bool delete_category = false; 848 bool extra_deletion = false; 849 850 if (m_options.m_language != lldb::eLanguageTypeUnknown) { 851 lldb::TypeCategoryImplSP category; 852 DataVisualization::Categories::GetCategory(m_options.m_language, 853 category); 854 if (category) 855 delete_category = category->Delete(typeCS, m_formatter_kind_mask); 856 extra_deletion = FormatterSpecificDeletion(typeCS); 857 } else { 858 lldb::TypeCategoryImplSP category; 859 DataVisualization::Categories::GetCategory( 860 ConstString(m_options.m_category.c_str()), category); 861 if (category) 862 delete_category = category->Delete(typeCS, m_formatter_kind_mask); 863 extra_deletion = FormatterSpecificDeletion(typeCS); 864 } 865 866 if (delete_category || extra_deletion) { 867 result.SetStatus(eReturnStatusSuccessFinishNoResult); 868 return result.Succeeded(); 869 } else { 870 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA); 871 result.SetStatus(eReturnStatusFailed); 872 return false; 873 } 874 } 875 }; 876 877 #define LLDB_OPTIONS_type_formatter_clear 878 #include "CommandOptions.inc" 879 880 class CommandObjectTypeFormatterClear : public CommandObjectParsed { 881 private: 882 class CommandOptions : public Options { 883 public: 884 CommandOptions() : Options() {} 885 886 ~CommandOptions() override = default; 887 888 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 889 ExecutionContext *execution_context) override { 890 Status error; 891 const int short_option = m_getopt_table[option_idx].val; 892 893 switch (short_option) { 894 case 'a': 895 m_delete_all = true; 896 break; 897 default: 898 llvm_unreachable("Unimplemented option"); 899 } 900 901 return error; 902 } 903 904 void OptionParsingStarting(ExecutionContext *execution_context) override { 905 m_delete_all = false; 906 } 907 908 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 909 return llvm::makeArrayRef(g_type_formatter_clear_options); 910 } 911 912 // Instance variables to hold the values for command options. 913 bool m_delete_all; 914 }; 915 916 CommandOptions m_options; 917 uint32_t m_formatter_kind_mask; 918 919 Options *GetOptions() override { return &m_options; } 920 921 public: 922 CommandObjectTypeFormatterClear(CommandInterpreter &interpreter, 923 uint32_t formatter_kind_mask, 924 const char *name, const char *help) 925 : CommandObjectParsed(interpreter, name, help, nullptr), m_options(), 926 m_formatter_kind_mask(formatter_kind_mask) {} 927 928 ~CommandObjectTypeFormatterClear() override = default; 929 930 protected: 931 virtual void FormatterSpecificDeletion() {} 932 933 bool DoExecute(Args &command, CommandReturnObject &result) override { 934 if (m_options.m_delete_all) { 935 DataVisualization::Categories::ForEach( 936 [this](const TypeCategoryImplSP &category_sp) -> bool { 937 category_sp->Clear(m_formatter_kind_mask); 938 return true; 939 }); 940 } else { 941 lldb::TypeCategoryImplSP category; 942 if (command.GetArgumentCount() > 0) { 943 const char *cat_name = command.GetArgumentAtIndex(0); 944 ConstString cat_nameCS(cat_name); 945 DataVisualization::Categories::GetCategory(cat_nameCS, category); 946 } else { 947 DataVisualization::Categories::GetCategory(ConstString(nullptr), 948 category); 949 } 950 category->Clear(m_formatter_kind_mask); 951 } 952 953 FormatterSpecificDeletion(); 954 955 result.SetStatus(eReturnStatusSuccessFinishResult); 956 return result.Succeeded(); 957 } 958 }; 959 960 // CommandObjectTypeFormatDelete 961 962 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete { 963 public: 964 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter) 965 : CommandObjectTypeFormatterDelete( 966 interpreter, 967 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 968 "type format delete", 969 "Delete an existing formatting style for a type.") {} 970 971 ~CommandObjectTypeFormatDelete() override = default; 972 }; 973 974 // CommandObjectTypeFormatClear 975 976 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear { 977 public: 978 CommandObjectTypeFormatClear(CommandInterpreter &interpreter) 979 : CommandObjectTypeFormatterClear( 980 interpreter, 981 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 982 "type format clear", "Delete all existing format styles.") {} 983 }; 984 985 #define LLDB_OPTIONS_type_formatter_list 986 #include "CommandOptions.inc" 987 988 template <typename FormatterType> 989 class CommandObjectTypeFormatterList : public CommandObjectParsed { 990 typedef typename FormatterType::SharedPointer FormatterSharedPointer; 991 992 class CommandOptions : public Options { 993 public: 994 CommandOptions() 995 : Options(), m_category_regex("", ""), 996 m_category_language(lldb::eLanguageTypeUnknown, 997 lldb::eLanguageTypeUnknown) {} 998 999 ~CommandOptions() override = default; 1000 1001 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1002 ExecutionContext *execution_context) override { 1003 Status error; 1004 const int short_option = m_getopt_table[option_idx].val; 1005 switch (short_option) { 1006 case 'w': 1007 m_category_regex.SetCurrentValue(option_arg); 1008 m_category_regex.SetOptionWasSet(); 1009 break; 1010 case 'l': 1011 error = m_category_language.SetValueFromString(option_arg); 1012 if (error.Success()) 1013 m_category_language.SetOptionWasSet(); 1014 break; 1015 default: 1016 llvm_unreachable("Unimplemented option"); 1017 } 1018 1019 return error; 1020 } 1021 1022 void OptionParsingStarting(ExecutionContext *execution_context) override { 1023 m_category_regex.Clear(); 1024 m_category_language.Clear(); 1025 } 1026 1027 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1028 return llvm::makeArrayRef(g_type_formatter_list_options); 1029 } 1030 1031 // Instance variables to hold the values for command options. 1032 1033 OptionValueString m_category_regex; 1034 OptionValueLanguage m_category_language; 1035 }; 1036 1037 CommandOptions m_options; 1038 1039 Options *GetOptions() override { return &m_options; } 1040 1041 public: 1042 CommandObjectTypeFormatterList(CommandInterpreter &interpreter, 1043 const char *name, const char *help) 1044 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() { 1045 CommandArgumentEntry type_arg; 1046 CommandArgumentData type_style_arg; 1047 1048 type_style_arg.arg_type = eArgTypeName; 1049 type_style_arg.arg_repetition = eArgRepeatOptional; 1050 1051 type_arg.push_back(type_style_arg); 1052 1053 m_arguments.push_back(type_arg); 1054 } 1055 1056 ~CommandObjectTypeFormatterList() override = default; 1057 1058 protected: 1059 virtual bool FormatterSpecificList(CommandReturnObject &result) { 1060 return false; 1061 } 1062 1063 bool DoExecute(Args &command, CommandReturnObject &result) override { 1064 const size_t argc = command.GetArgumentCount(); 1065 1066 std::unique_ptr<RegularExpression> category_regex; 1067 std::unique_ptr<RegularExpression> formatter_regex; 1068 1069 if (m_options.m_category_regex.OptionWasSet()) { 1070 category_regex = std::make_unique<RegularExpression>( 1071 m_options.m_category_regex.GetCurrentValueAsRef()); 1072 if (!category_regex->IsValid()) { 1073 result.AppendErrorWithFormat( 1074 "syntax error in category regular expression '%s'", 1075 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str()); 1076 result.SetStatus(eReturnStatusFailed); 1077 return false; 1078 } 1079 } 1080 1081 if (argc == 1) { 1082 const char *arg = command.GetArgumentAtIndex(0); 1083 formatter_regex = std::make_unique<RegularExpression>( 1084 llvm::StringRef::withNullAsEmpty(arg)); 1085 if (!formatter_regex->IsValid()) { 1086 result.AppendErrorWithFormat("syntax error in regular expression '%s'", 1087 arg); 1088 result.SetStatus(eReturnStatusFailed); 1089 return false; 1090 } 1091 } 1092 1093 bool any_printed = false; 1094 1095 auto category_closure = 1096 [&result, &formatter_regex, 1097 &any_printed](const lldb::TypeCategoryImplSP &category) -> void { 1098 result.GetOutputStream().Printf( 1099 "-----------------------\nCategory: %s%s\n-----------------------\n", 1100 category->GetName(), category->IsEnabled() ? "" : " (disabled)"); 1101 1102 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; 1103 foreach 1104 .SetExact([&result, &formatter_regex, &any_printed]( 1105 const TypeMatcher &type_matcher, 1106 const FormatterSharedPointer &format_sp) -> bool { 1107 if (formatter_regex) { 1108 bool escape = true; 1109 if (type_matcher.CreatedBySameMatchString( 1110 ConstString(formatter_regex->GetText()))) { 1111 escape = false; 1112 } else if (formatter_regex->Execute( 1113 type_matcher.GetMatchString().GetStringRef())) { 1114 escape = false; 1115 } 1116 1117 if (escape) 1118 return true; 1119 } 1120 1121 any_printed = true; 1122 result.GetOutputStream().Printf( 1123 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1124 format_sp->GetDescription().c_str()); 1125 return true; 1126 }); 1127 1128 foreach 1129 .SetWithRegex([&result, &formatter_regex, &any_printed]( 1130 const TypeMatcher &type_matcher, 1131 const FormatterSharedPointer &format_sp) -> bool { 1132 if (formatter_regex) { 1133 bool escape = true; 1134 if (type_matcher.CreatedBySameMatchString( 1135 ConstString(formatter_regex->GetText()))) { 1136 escape = false; 1137 } else if (formatter_regex->Execute( 1138 type_matcher.GetMatchString().GetStringRef())) { 1139 escape = false; 1140 } 1141 1142 if (escape) 1143 return true; 1144 } 1145 1146 any_printed = true; 1147 result.GetOutputStream().Printf( 1148 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1149 format_sp->GetDescription().c_str()); 1150 return true; 1151 }); 1152 1153 category->ForEach(foreach); 1154 }; 1155 1156 if (m_options.m_category_language.OptionWasSet()) { 1157 lldb::TypeCategoryImplSP category_sp; 1158 DataVisualization::Categories::GetCategory( 1159 m_options.m_category_language.GetCurrentValue(), category_sp); 1160 if (category_sp) 1161 category_closure(category_sp); 1162 } else { 1163 DataVisualization::Categories::ForEach( 1164 [&category_regex, &category_closure]( 1165 const lldb::TypeCategoryImplSP &category) -> bool { 1166 if (category_regex) { 1167 bool escape = true; 1168 if (category->GetName() == category_regex->GetText()) { 1169 escape = false; 1170 } else if (category_regex->Execute( 1171 llvm::StringRef::withNullAsEmpty( 1172 category->GetName()))) { 1173 escape = false; 1174 } 1175 1176 if (escape) 1177 return true; 1178 } 1179 1180 category_closure(category); 1181 1182 return true; 1183 }); 1184 1185 any_printed = FormatterSpecificList(result) | any_printed; 1186 } 1187 1188 if (any_printed) 1189 result.SetStatus(eReturnStatusSuccessFinishResult); 1190 else { 1191 result.GetOutputStream().PutCString("no matching results found.\n"); 1192 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1193 } 1194 return result.Succeeded(); 1195 } 1196 }; 1197 1198 // CommandObjectTypeFormatList 1199 1200 class CommandObjectTypeFormatList 1201 : public CommandObjectTypeFormatterList<TypeFormatImpl> { 1202 public: 1203 CommandObjectTypeFormatList(CommandInterpreter &interpreter) 1204 : CommandObjectTypeFormatterList(interpreter, "type format list", 1205 "Show a list of current formats.") {} 1206 }; 1207 1208 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( 1209 uint32_t option_idx, llvm::StringRef option_arg, 1210 ExecutionContext *execution_context) { 1211 Status error; 1212 const int short_option = m_getopt_table[option_idx].val; 1213 bool success; 1214 1215 switch (short_option) { 1216 case 'C': 1217 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success)); 1218 if (!success) 1219 error.SetErrorStringWithFormat("invalid value for cascade: %s", 1220 option_arg.str().c_str()); 1221 break; 1222 case 'e': 1223 m_flags.SetDontShowChildren(false); 1224 break; 1225 case 'h': 1226 m_flags.SetHideEmptyAggregates(true); 1227 break; 1228 case 'v': 1229 m_flags.SetDontShowValue(true); 1230 break; 1231 case 'c': 1232 m_flags.SetShowMembersOneLiner(true); 1233 break; 1234 case 's': 1235 m_format_string = std::string(option_arg); 1236 break; 1237 case 'p': 1238 m_flags.SetSkipPointers(true); 1239 break; 1240 case 'r': 1241 m_flags.SetSkipReferences(true); 1242 break; 1243 case 'x': 1244 m_regex = true; 1245 break; 1246 case 'n': 1247 m_name.SetString(option_arg); 1248 break; 1249 case 'o': 1250 m_python_script = std::string(option_arg); 1251 m_is_add_script = true; 1252 break; 1253 case 'F': 1254 m_python_function = std::string(option_arg); 1255 m_is_add_script = true; 1256 break; 1257 case 'P': 1258 m_is_add_script = true; 1259 break; 1260 case 'w': 1261 m_category = std::string(option_arg); 1262 break; 1263 case 'O': 1264 m_flags.SetHideItemNames(true); 1265 break; 1266 default: 1267 llvm_unreachable("Unimplemented option"); 1268 } 1269 1270 return error; 1271 } 1272 1273 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting( 1274 ExecutionContext *execution_context) { 1275 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 1276 m_flags.SetShowMembersOneLiner(false) 1277 .SetSkipPointers(false) 1278 .SetSkipReferences(false) 1279 .SetHideItemNames(false); 1280 1281 m_regex = false; 1282 m_name.Clear(); 1283 m_python_script = ""; 1284 m_python_function = ""; 1285 m_format_string = ""; 1286 m_is_add_script = false; 1287 m_category = "default"; 1288 } 1289 1290 #if LLDB_ENABLE_PYTHON 1291 1292 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( 1293 Args &command, CommandReturnObject &result) { 1294 const size_t argc = command.GetArgumentCount(); 1295 1296 if (argc < 1 && !m_options.m_name) { 1297 result.AppendErrorWithFormat("%s takes one or more args.\n", 1298 m_cmd_name.c_str()); 1299 result.SetStatus(eReturnStatusFailed); 1300 return false; 1301 } 1302 1303 TypeSummaryImplSP script_format; 1304 1305 if (!m_options.m_python_function 1306 .empty()) // we have a Python function ready to use 1307 { 1308 const char *funct_name = m_options.m_python_function.c_str(); 1309 if (!funct_name || !funct_name[0]) { 1310 result.AppendError("function name empty.\n"); 1311 result.SetStatus(eReturnStatusFailed); 1312 return false; 1313 } 1314 1315 std::string code = 1316 (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1317 1318 script_format = std::make_shared<ScriptSummaryFormat>( 1319 m_options.m_flags, funct_name, code.c_str()); 1320 1321 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1322 1323 if (interpreter && !interpreter->CheckObjectExists(funct_name)) 1324 result.AppendWarningWithFormat( 1325 "The provided function \"%s\" does not exist - " 1326 "please define it before attempting to use this summary.\n", 1327 funct_name); 1328 } else if (!m_options.m_python_script 1329 .empty()) // we have a quick 1-line script, just use it 1330 { 1331 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1332 if (!interpreter) { 1333 result.AppendError("script interpreter missing - unable to generate " 1334 "function wrapper.\n"); 1335 result.SetStatus(eReturnStatusFailed); 1336 return false; 1337 } 1338 StringList funct_sl; 1339 funct_sl << m_options.m_python_script.c_str(); 1340 std::string funct_name_str; 1341 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) { 1342 result.AppendError("unable to generate function wrapper.\n"); 1343 result.SetStatus(eReturnStatusFailed); 1344 return false; 1345 } 1346 if (funct_name_str.empty()) { 1347 result.AppendError( 1348 "script interpreter failed to generate a valid function name.\n"); 1349 result.SetStatus(eReturnStatusFailed); 1350 return false; 1351 } 1352 1353 std::string code = " " + m_options.m_python_script; 1354 1355 script_format = std::make_shared<ScriptSummaryFormat>( 1356 m_options.m_flags, funct_name_str.c_str(), code.c_str()); 1357 } else { 1358 // Use an IOHandler to grab Python code from the user 1359 ScriptAddOptions *options = 1360 new ScriptAddOptions(m_options.m_flags, m_options.m_regex, 1361 m_options.m_name, m_options.m_category); 1362 1363 for (auto &entry : command.entries()) { 1364 if (entry.ref().empty()) { 1365 result.AppendError("empty typenames not allowed"); 1366 result.SetStatus(eReturnStatusFailed); 1367 return false; 1368 } 1369 1370 options->m_target_types << std::string(entry.ref()); 1371 } 1372 1373 m_interpreter.GetPythonCommandsFromIOHandler( 1374 " ", // Prompt 1375 *this, // IOHandlerDelegate 1376 options); // Baton for the "io_handler" that will be passed back into 1377 // our IOHandlerDelegate functions 1378 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1379 1380 return result.Succeeded(); 1381 } 1382 1383 // if I am here, script_format must point to something good, so I can add 1384 // that as a script summary to all interested parties 1385 1386 Status error; 1387 1388 for (auto &entry : command.entries()) { 1389 CommandObjectTypeSummaryAdd::AddSummary( 1390 ConstString(entry.ref()), script_format, 1391 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1392 m_options.m_category, &error); 1393 if (error.Fail()) { 1394 result.AppendError(error.AsCString()); 1395 result.SetStatus(eReturnStatusFailed); 1396 return false; 1397 } 1398 } 1399 1400 if (m_options.m_name) { 1401 AddSummary(m_options.m_name, script_format, eNamedSummary, 1402 m_options.m_category, &error); 1403 if (error.Fail()) { 1404 result.AppendError(error.AsCString()); 1405 result.AppendError("added to types, but not given a name"); 1406 result.SetStatus(eReturnStatusFailed); 1407 return false; 1408 } 1409 } 1410 1411 return result.Succeeded(); 1412 } 1413 1414 #endif 1415 1416 bool CommandObjectTypeSummaryAdd::Execute_StringSummary( 1417 Args &command, CommandReturnObject &result) { 1418 const size_t argc = command.GetArgumentCount(); 1419 1420 if (argc < 1 && !m_options.m_name) { 1421 result.AppendErrorWithFormat("%s takes one or more args.\n", 1422 m_cmd_name.c_str()); 1423 result.SetStatus(eReturnStatusFailed); 1424 return false; 1425 } 1426 1427 if (!m_options.m_flags.GetShowMembersOneLiner() && 1428 m_options.m_format_string.empty()) { 1429 result.AppendError("empty summary strings not allowed"); 1430 result.SetStatus(eReturnStatusFailed); 1431 return false; 1432 } 1433 1434 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner() 1435 ? "" 1436 : m_options.m_format_string.c_str()); 1437 1438 // ${var%S} is an endless recursion, prevent it 1439 if (strcmp(format_cstr, "${var%S}") == 0) { 1440 result.AppendError("recursive summary not allowed"); 1441 result.SetStatus(eReturnStatusFailed); 1442 return false; 1443 } 1444 1445 std::unique_ptr<StringSummaryFormat> string_format( 1446 new StringSummaryFormat(m_options.m_flags, format_cstr)); 1447 if (!string_format) { 1448 result.AppendError("summary creation failed"); 1449 result.SetStatus(eReturnStatusFailed); 1450 return false; 1451 } 1452 if (string_format->m_error.Fail()) { 1453 result.AppendErrorWithFormat("syntax error: %s", 1454 string_format->m_error.AsCString("<unknown>")); 1455 result.SetStatus(eReturnStatusFailed); 1456 return false; 1457 } 1458 lldb::TypeSummaryImplSP entry(string_format.release()); 1459 1460 // now I have a valid format, let's add it to every type 1461 Status error; 1462 for (auto &arg_entry : command.entries()) { 1463 if (arg_entry.ref().empty()) { 1464 result.AppendError("empty typenames not allowed"); 1465 result.SetStatus(eReturnStatusFailed); 1466 return false; 1467 } 1468 ConstString typeCS(arg_entry.ref()); 1469 1470 AddSummary(typeCS, entry, 1471 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1472 m_options.m_category, &error); 1473 1474 if (error.Fail()) { 1475 result.AppendError(error.AsCString()); 1476 result.SetStatus(eReturnStatusFailed); 1477 return false; 1478 } 1479 } 1480 1481 if (m_options.m_name) { 1482 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, 1483 &error); 1484 if (error.Fail()) { 1485 result.AppendError(error.AsCString()); 1486 result.AppendError("added to types, but not given a name"); 1487 result.SetStatus(eReturnStatusFailed); 1488 return false; 1489 } 1490 } 1491 1492 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1493 return result.Succeeded(); 1494 } 1495 1496 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd( 1497 CommandInterpreter &interpreter) 1498 : CommandObjectParsed(interpreter, "type summary add", 1499 "Add a new summary style for a type.", nullptr), 1500 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) { 1501 CommandArgumentEntry type_arg; 1502 CommandArgumentData type_style_arg; 1503 1504 type_style_arg.arg_type = eArgTypeName; 1505 type_style_arg.arg_repetition = eArgRepeatPlus; 1506 1507 type_arg.push_back(type_style_arg); 1508 1509 m_arguments.push_back(type_arg); 1510 1511 SetHelpLong( 1512 R"( 1513 The following examples of 'type summary add' refer to this code snippet for context: 1514 1515 struct JustADemo 1516 { 1517 int* ptr; 1518 float value; 1519 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {} 1520 }; 1521 JustADemo demo_instance(42, 3.14); 1522 1523 typedef JustADemo NewDemo; 1524 NewDemo new_demo_instance(42, 3.14); 1525 1526 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo 1527 1528 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42" 1529 1530 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo 1531 1532 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" 1533 1534 )" 1535 "Alternatively, you could define formatting for all pointers to integers and \ 1536 rely on that when formatting JustADemo to obtain the same result:" 1537 R"( 1538 1539 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" 1540 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo 1541 1542 )" 1543 "Type summaries are automatically applied to derived typedefs, so the examples \ 1544 above apply to both JustADemo and NewDemo. The cascade option can be used to \ 1545 suppress this behavior:" 1546 R"( 1547 1548 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no 1549 1550 The summary will now be used for values of JustADemo but not NewDemo. 1551 1552 )" 1553 "By default summaries are shown for pointers and references to values of the \ 1554 specified type. To suppress formatting for pointers use the -p option, or apply \ 1555 the corresponding -r option to suppress formatting for references:" 1556 R"( 1557 1558 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo 1559 1560 )" 1561 "One-line summaries including all fields in a type can be inferred without supplying an \ 1562 explicit summary string by passing the -c option:" 1563 R"( 1564 1565 (lldb) type summary add -c JustADemo 1566 (lldb) frame variable demo_instance 1567 (ptr=<address>, value=3.14) 1568 1569 )" 1570 "Type summaries normally suppress the nested display of individual fields. To \ 1571 supply a summary to supplement the default structure add the -e option:" 1572 R"( 1573 1574 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo 1575 1576 )" 1577 "Now when displaying JustADemo values the int* is displayed, followed by the \ 1578 standard LLDB sequence of children, one per line:" 1579 R"( 1580 1581 *ptr = 42 { 1582 ptr = <address> 1583 value = 3.14 1584 } 1585 1586 )" 1587 "You can also add summaries written in Python. These scripts use lldb public API to \ 1588 gather information from your variables and produce a meaningful summary. To start a \ 1589 multi-line script use the -P option. The function declaration will be displayed along with \ 1590 a comment describing the two arguments. End your script with the word 'DONE' on a line by \ 1591 itself:" 1592 R"( 1593 1594 (lldb) type summary add JustADemo -P 1595 def function (valobj,internal_dict): 1596 """valobj: an SBValue which you want to provide a summary for 1597 internal_dict: an LLDB support object not to be used""" 1598 value = valobj.GetChildMemberWithName('value'); 1599 return 'My value is ' + value.GetValue(); 1600 DONE 1601 1602 Alternatively, the -o option can be used when providing a simple one-line Python script: 1603 1604 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"); 1605 } 1606 1607 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command, 1608 CommandReturnObject &result) { 1609 WarnOnPotentialUnquotedUnsignedType(command, result); 1610 1611 if (m_options.m_is_add_script) { 1612 #if LLDB_ENABLE_PYTHON 1613 return Execute_ScriptSummary(command, result); 1614 #else 1615 result.AppendError("python is disabled"); 1616 result.SetStatus(eReturnStatusFailed); 1617 return false; 1618 #endif 1619 } 1620 1621 return Execute_StringSummary(command, result); 1622 } 1623 1624 static bool FixArrayTypeNameWithRegex(ConstString &type_name) { 1625 llvm::StringRef type_name_ref(type_name.GetStringRef()); 1626 1627 if (type_name_ref.endswith("[]")) { 1628 std::string type_name_str(type_name.GetCString()); 1629 type_name_str.resize(type_name_str.length() - 2); 1630 if (type_name_str.back() != ' ') 1631 type_name_str.append(" \\[[0-9]+\\]"); 1632 else 1633 type_name_str.append("\\[[0-9]+\\]"); 1634 type_name.SetCString(type_name_str.c_str()); 1635 return true; 1636 } 1637 return false; 1638 } 1639 1640 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, 1641 TypeSummaryImplSP entry, 1642 SummaryFormatType type, 1643 std::string category_name, 1644 Status *error) { 1645 lldb::TypeCategoryImplSP category; 1646 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 1647 category); 1648 1649 if (type == eRegularSummary) { 1650 if (FixArrayTypeNameWithRegex(type_name)) 1651 type = eRegexSummary; 1652 } 1653 1654 if (type == eRegexSummary) { 1655 RegularExpression typeRX(type_name.GetStringRef()); 1656 if (!typeRX.IsValid()) { 1657 if (error) 1658 error->SetErrorString( 1659 "regex format error (maybe this is not really a regex?)"); 1660 return false; 1661 } 1662 1663 category->GetRegexTypeSummariesContainer()->Delete(type_name); 1664 category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry); 1665 1666 return true; 1667 } else if (type == eNamedSummary) { 1668 // system named summaries do not exist (yet?) 1669 DataVisualization::NamedSummaryFormats::Add(type_name, entry); 1670 return true; 1671 } else { 1672 category->GetTypeSummariesContainer()->Add(std::move(type_name), entry); 1673 return true; 1674 } 1675 } 1676 1677 // CommandObjectTypeSummaryDelete 1678 1679 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { 1680 public: 1681 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter) 1682 : CommandObjectTypeFormatterDelete( 1683 interpreter, 1684 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1685 "type summary delete", "Delete an existing summary for a type.") {} 1686 1687 ~CommandObjectTypeSummaryDelete() override = default; 1688 1689 protected: 1690 bool FormatterSpecificDeletion(ConstString typeCS) override { 1691 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1692 return false; 1693 return DataVisualization::NamedSummaryFormats::Delete(typeCS); 1694 } 1695 }; 1696 1697 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear { 1698 public: 1699 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter) 1700 : CommandObjectTypeFormatterClear( 1701 interpreter, 1702 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1703 "type summary clear", "Delete all existing summaries.") {} 1704 1705 protected: 1706 void FormatterSpecificDeletion() override { 1707 DataVisualization::NamedSummaryFormats::Clear(); 1708 } 1709 }; 1710 1711 // CommandObjectTypeSummaryList 1712 1713 class CommandObjectTypeSummaryList 1714 : public CommandObjectTypeFormatterList<TypeSummaryImpl> { 1715 public: 1716 CommandObjectTypeSummaryList(CommandInterpreter &interpreter) 1717 : CommandObjectTypeFormatterList(interpreter, "type summary list", 1718 "Show a list of current summaries.") {} 1719 1720 protected: 1721 bool FormatterSpecificList(CommandReturnObject &result) override { 1722 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) { 1723 result.GetOutputStream().Printf("Named summaries:\n"); 1724 DataVisualization::NamedSummaryFormats::ForEach( 1725 [&result](const TypeMatcher &type_matcher, 1726 const TypeSummaryImplSP &summary_sp) -> bool { 1727 result.GetOutputStream().Printf( 1728 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1729 summary_sp->GetDescription().c_str()); 1730 return true; 1731 }); 1732 return true; 1733 } 1734 return false; 1735 } 1736 }; 1737 1738 // CommandObjectTypeCategoryDefine 1739 #define LLDB_OPTIONS_type_category_define 1740 #include "CommandOptions.inc" 1741 1742 class CommandObjectTypeCategoryDefine : public CommandObjectParsed { 1743 class CommandOptions : public Options { 1744 public: 1745 CommandOptions() 1746 : Options(), m_define_enabled(false, false), 1747 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {} 1748 1749 ~CommandOptions() override = default; 1750 1751 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1752 ExecutionContext *execution_context) override { 1753 Status error; 1754 const int short_option = m_getopt_table[option_idx].val; 1755 1756 switch (short_option) { 1757 case 'e': 1758 m_define_enabled.SetValueFromString(llvm::StringRef("true")); 1759 break; 1760 case 'l': 1761 error = m_cate_language.SetValueFromString(option_arg); 1762 break; 1763 default: 1764 llvm_unreachable("Unimplemented option"); 1765 } 1766 1767 return error; 1768 } 1769 1770 void OptionParsingStarting(ExecutionContext *execution_context) override { 1771 m_define_enabled.Clear(); 1772 m_cate_language.Clear(); 1773 } 1774 1775 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1776 return llvm::makeArrayRef(g_type_category_define_options); 1777 } 1778 1779 // Instance variables to hold the values for command options. 1780 1781 OptionValueBoolean m_define_enabled; 1782 OptionValueLanguage m_cate_language; 1783 }; 1784 1785 CommandOptions m_options; 1786 1787 Options *GetOptions() override { return &m_options; } 1788 1789 public: 1790 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter) 1791 : CommandObjectParsed(interpreter, "type category define", 1792 "Define a new category as a source of formatters.", 1793 nullptr), 1794 m_options() { 1795 CommandArgumentEntry type_arg; 1796 CommandArgumentData type_style_arg; 1797 1798 type_style_arg.arg_type = eArgTypeName; 1799 type_style_arg.arg_repetition = eArgRepeatPlus; 1800 1801 type_arg.push_back(type_style_arg); 1802 1803 m_arguments.push_back(type_arg); 1804 } 1805 1806 ~CommandObjectTypeCategoryDefine() override = default; 1807 1808 void 1809 HandleArgumentCompletion(CompletionRequest &request, 1810 OptionElementVector &opt_element_vector) override { 1811 CommandCompletions::InvokeCommonCompletionCallbacks( 1812 GetCommandInterpreter(), 1813 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1814 } 1815 1816 protected: 1817 bool DoExecute(Args &command, CommandReturnObject &result) override { 1818 const size_t argc = command.GetArgumentCount(); 1819 1820 if (argc < 1) { 1821 result.AppendErrorWithFormat("%s takes 1 or more args.\n", 1822 m_cmd_name.c_str()); 1823 result.SetStatus(eReturnStatusFailed); 1824 return false; 1825 } 1826 1827 for (auto &entry : command.entries()) { 1828 TypeCategoryImplSP category_sp; 1829 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), 1830 category_sp) && 1831 category_sp) { 1832 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 1833 if (m_options.m_define_enabled.GetCurrentValue()) 1834 DataVisualization::Categories::Enable(category_sp, 1835 TypeCategoryMap::Default); 1836 } 1837 } 1838 1839 result.SetStatus(eReturnStatusSuccessFinishResult); 1840 return result.Succeeded(); 1841 } 1842 }; 1843 1844 // CommandObjectTypeCategoryEnable 1845 #define LLDB_OPTIONS_type_category_enable 1846 #include "CommandOptions.inc" 1847 1848 class CommandObjectTypeCategoryEnable : public CommandObjectParsed { 1849 class CommandOptions : public Options { 1850 public: 1851 CommandOptions() : Options() {} 1852 1853 ~CommandOptions() override = default; 1854 1855 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1856 ExecutionContext *execution_context) override { 1857 Status error; 1858 const int short_option = m_getopt_table[option_idx].val; 1859 1860 switch (short_option) { 1861 case 'l': 1862 if (!option_arg.empty()) { 1863 m_language = Language::GetLanguageTypeFromString(option_arg); 1864 if (m_language == lldb::eLanguageTypeUnknown) 1865 error.SetErrorStringWithFormat("unrecognized language '%s'", 1866 option_arg.str().c_str()); 1867 } 1868 break; 1869 default: 1870 llvm_unreachable("Unimplemented option"); 1871 } 1872 1873 return error; 1874 } 1875 1876 void OptionParsingStarting(ExecutionContext *execution_context) override { 1877 m_language = lldb::eLanguageTypeUnknown; 1878 } 1879 1880 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1881 return llvm::makeArrayRef(g_type_category_enable_options); 1882 } 1883 1884 // Instance variables to hold the values for command options. 1885 1886 lldb::LanguageType m_language; 1887 }; 1888 1889 CommandOptions m_options; 1890 1891 Options *GetOptions() override { return &m_options; } 1892 1893 public: 1894 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter) 1895 : CommandObjectParsed(interpreter, "type category enable", 1896 "Enable a category as a source of formatters.", 1897 nullptr), 1898 m_options() { 1899 CommandArgumentEntry type_arg; 1900 CommandArgumentData type_style_arg; 1901 1902 type_style_arg.arg_type = eArgTypeName; 1903 type_style_arg.arg_repetition = eArgRepeatPlus; 1904 1905 type_arg.push_back(type_style_arg); 1906 1907 m_arguments.push_back(type_arg); 1908 } 1909 1910 ~CommandObjectTypeCategoryEnable() override = default; 1911 1912 void 1913 HandleArgumentCompletion(CompletionRequest &request, 1914 OptionElementVector &opt_element_vector) override { 1915 CommandCompletions::InvokeCommonCompletionCallbacks( 1916 GetCommandInterpreter(), 1917 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1918 } 1919 1920 protected: 1921 bool DoExecute(Args &command, CommandReturnObject &result) override { 1922 const size_t argc = command.GetArgumentCount(); 1923 1924 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 1925 result.AppendErrorWithFormat("%s takes arguments and/or a language", 1926 m_cmd_name.c_str()); 1927 result.SetStatus(eReturnStatusFailed); 1928 return false; 1929 } 1930 1931 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 1932 DataVisualization::Categories::EnableStar(); 1933 } else if (argc > 0) { 1934 for (int i = argc - 1; i >= 0; i--) { 1935 const char *typeA = command.GetArgumentAtIndex(i); 1936 ConstString typeCS(typeA); 1937 1938 if (!typeCS) { 1939 result.AppendError("empty category name not allowed"); 1940 result.SetStatus(eReturnStatusFailed); 1941 return false; 1942 } 1943 DataVisualization::Categories::Enable(typeCS); 1944 lldb::TypeCategoryImplSP cate; 1945 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) { 1946 if (cate->GetCount() == 0) { 1947 result.AppendWarning("empty category enabled (typo?)"); 1948 } 1949 } 1950 } 1951 } 1952 1953 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1954 DataVisualization::Categories::Enable(m_options.m_language); 1955 1956 result.SetStatus(eReturnStatusSuccessFinishResult); 1957 return result.Succeeded(); 1958 } 1959 }; 1960 1961 // CommandObjectTypeCategoryDelete 1962 1963 class CommandObjectTypeCategoryDelete : public CommandObjectParsed { 1964 public: 1965 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter) 1966 : CommandObjectParsed(interpreter, "type category delete", 1967 "Delete a category and all associated formatters.", 1968 nullptr) { 1969 CommandArgumentEntry type_arg; 1970 CommandArgumentData type_style_arg; 1971 1972 type_style_arg.arg_type = eArgTypeName; 1973 type_style_arg.arg_repetition = eArgRepeatPlus; 1974 1975 type_arg.push_back(type_style_arg); 1976 1977 m_arguments.push_back(type_arg); 1978 } 1979 1980 ~CommandObjectTypeCategoryDelete() override = default; 1981 1982 void 1983 HandleArgumentCompletion(CompletionRequest &request, 1984 OptionElementVector &opt_element_vector) override { 1985 CommandCompletions::InvokeCommonCompletionCallbacks( 1986 GetCommandInterpreter(), 1987 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1988 } 1989 1990 protected: 1991 bool DoExecute(Args &command, CommandReturnObject &result) override { 1992 const size_t argc = command.GetArgumentCount(); 1993 1994 if (argc < 1) { 1995 result.AppendErrorWithFormat("%s takes 1 or more arg.\n", 1996 m_cmd_name.c_str()); 1997 result.SetStatus(eReturnStatusFailed); 1998 return false; 1999 } 2000 2001 bool success = true; 2002 2003 // the order is not relevant here 2004 for (int i = argc - 1; i >= 0; i--) { 2005 const char *typeA = command.GetArgumentAtIndex(i); 2006 ConstString typeCS(typeA); 2007 2008 if (!typeCS) { 2009 result.AppendError("empty category name not allowed"); 2010 result.SetStatus(eReturnStatusFailed); 2011 return false; 2012 } 2013 if (!DataVisualization::Categories::Delete(typeCS)) 2014 success = false; // keep deleting even if we hit an error 2015 } 2016 if (success) { 2017 result.SetStatus(eReturnStatusSuccessFinishResult); 2018 return result.Succeeded(); 2019 } else { 2020 result.AppendError("cannot delete one or more categories\n"); 2021 result.SetStatus(eReturnStatusFailed); 2022 return false; 2023 } 2024 } 2025 }; 2026 2027 // CommandObjectTypeCategoryDisable 2028 #define LLDB_OPTIONS_type_category_disable 2029 #include "CommandOptions.inc" 2030 2031 class CommandObjectTypeCategoryDisable : public CommandObjectParsed { 2032 class CommandOptions : public Options { 2033 public: 2034 CommandOptions() : Options() {} 2035 2036 ~CommandOptions() override = default; 2037 2038 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2039 ExecutionContext *execution_context) override { 2040 Status error; 2041 const int short_option = m_getopt_table[option_idx].val; 2042 2043 switch (short_option) { 2044 case 'l': 2045 if (!option_arg.empty()) { 2046 m_language = Language::GetLanguageTypeFromString(option_arg); 2047 if (m_language == lldb::eLanguageTypeUnknown) 2048 error.SetErrorStringWithFormat("unrecognized language '%s'", 2049 option_arg.str().c_str()); 2050 } 2051 break; 2052 default: 2053 llvm_unreachable("Unimplemented option"); 2054 } 2055 2056 return error; 2057 } 2058 2059 void OptionParsingStarting(ExecutionContext *execution_context) override { 2060 m_language = lldb::eLanguageTypeUnknown; 2061 } 2062 2063 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2064 return llvm::makeArrayRef(g_type_category_disable_options); 2065 } 2066 2067 // Instance variables to hold the values for command options. 2068 2069 lldb::LanguageType m_language; 2070 }; 2071 2072 CommandOptions m_options; 2073 2074 Options *GetOptions() override { return &m_options; } 2075 2076 public: 2077 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter) 2078 : CommandObjectParsed(interpreter, "type category disable", 2079 "Disable a category as a source of formatters.", 2080 nullptr), 2081 m_options() { 2082 CommandArgumentEntry type_arg; 2083 CommandArgumentData type_style_arg; 2084 2085 type_style_arg.arg_type = eArgTypeName; 2086 type_style_arg.arg_repetition = eArgRepeatPlus; 2087 2088 type_arg.push_back(type_style_arg); 2089 2090 m_arguments.push_back(type_arg); 2091 } 2092 2093 ~CommandObjectTypeCategoryDisable() override = default; 2094 2095 void 2096 HandleArgumentCompletion(CompletionRequest &request, 2097 OptionElementVector &opt_element_vector) override { 2098 CommandCompletions::InvokeCommonCompletionCallbacks( 2099 GetCommandInterpreter(), 2100 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2101 } 2102 2103 protected: 2104 bool DoExecute(Args &command, CommandReturnObject &result) override { 2105 const size_t argc = command.GetArgumentCount(); 2106 2107 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 2108 result.AppendErrorWithFormat("%s takes arguments and/or a language", 2109 m_cmd_name.c_str()); 2110 result.SetStatus(eReturnStatusFailed); 2111 return false; 2112 } 2113 2114 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 2115 DataVisualization::Categories::DisableStar(); 2116 } else if (argc > 0) { 2117 // the order is not relevant here 2118 for (int i = argc - 1; i >= 0; i--) { 2119 const char *typeA = command.GetArgumentAtIndex(i); 2120 ConstString typeCS(typeA); 2121 2122 if (!typeCS) { 2123 result.AppendError("empty category name not allowed"); 2124 result.SetStatus(eReturnStatusFailed); 2125 return false; 2126 } 2127 DataVisualization::Categories::Disable(typeCS); 2128 } 2129 } 2130 2131 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2132 DataVisualization::Categories::Disable(m_options.m_language); 2133 2134 result.SetStatus(eReturnStatusSuccessFinishResult); 2135 return result.Succeeded(); 2136 } 2137 }; 2138 2139 // CommandObjectTypeCategoryList 2140 2141 class CommandObjectTypeCategoryList : public CommandObjectParsed { 2142 public: 2143 CommandObjectTypeCategoryList(CommandInterpreter &interpreter) 2144 : CommandObjectParsed(interpreter, "type category list", 2145 "Provide a list of all existing categories.", 2146 nullptr) { 2147 CommandArgumentEntry type_arg; 2148 CommandArgumentData type_style_arg; 2149 2150 type_style_arg.arg_type = eArgTypeName; 2151 type_style_arg.arg_repetition = eArgRepeatOptional; 2152 2153 type_arg.push_back(type_style_arg); 2154 2155 m_arguments.push_back(type_arg); 2156 } 2157 2158 ~CommandObjectTypeCategoryList() override = default; 2159 2160 void 2161 HandleArgumentCompletion(CompletionRequest &request, 2162 OptionElementVector &opt_element_vector) override { 2163 if (request.GetCursorIndex()) 2164 return; 2165 CommandCompletions::InvokeCommonCompletionCallbacks( 2166 GetCommandInterpreter(), 2167 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2168 } 2169 2170 protected: 2171 bool DoExecute(Args &command, CommandReturnObject &result) override { 2172 const size_t argc = command.GetArgumentCount(); 2173 2174 std::unique_ptr<RegularExpression> regex; 2175 2176 if (argc == 1) { 2177 const char *arg = command.GetArgumentAtIndex(0); 2178 regex = std::make_unique<RegularExpression>( 2179 llvm::StringRef::withNullAsEmpty(arg)); 2180 if (!regex->IsValid()) { 2181 result.AppendErrorWithFormat( 2182 "syntax error in category regular expression '%s'", arg); 2183 result.SetStatus(eReturnStatusFailed); 2184 return false; 2185 } 2186 } else if (argc != 0) { 2187 result.AppendErrorWithFormat("%s takes 0 or one arg.\n", 2188 m_cmd_name.c_str()); 2189 result.SetStatus(eReturnStatusFailed); 2190 return false; 2191 } 2192 2193 DataVisualization::Categories::ForEach( 2194 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool { 2195 if (regex) { 2196 bool escape = true; 2197 if (regex->GetText() == category_sp->GetName()) { 2198 escape = false; 2199 } else if (regex->Execute(llvm::StringRef::withNullAsEmpty( 2200 category_sp->GetName()))) { 2201 escape = false; 2202 } 2203 2204 if (escape) 2205 return true; 2206 } 2207 2208 result.GetOutputStream().Printf( 2209 "Category: %s\n", category_sp->GetDescription().c_str()); 2210 2211 return true; 2212 }); 2213 2214 result.SetStatus(eReturnStatusSuccessFinishResult); 2215 return result.Succeeded(); 2216 } 2217 }; 2218 2219 // CommandObjectTypeFilterList 2220 2221 class CommandObjectTypeFilterList 2222 : public CommandObjectTypeFormatterList<TypeFilterImpl> { 2223 public: 2224 CommandObjectTypeFilterList(CommandInterpreter &interpreter) 2225 : CommandObjectTypeFormatterList(interpreter, "type filter list", 2226 "Show a list of current filters.") {} 2227 }; 2228 2229 #if LLDB_ENABLE_PYTHON 2230 2231 // CommandObjectTypeSynthList 2232 2233 class CommandObjectTypeSynthList 2234 : public CommandObjectTypeFormatterList<SyntheticChildren> { 2235 public: 2236 CommandObjectTypeSynthList(CommandInterpreter &interpreter) 2237 : CommandObjectTypeFormatterList( 2238 interpreter, "type synthetic list", 2239 "Show a list of current synthetic providers.") {} 2240 }; 2241 2242 #endif 2243 2244 // CommandObjectTypeFilterDelete 2245 2246 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { 2247 public: 2248 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) 2249 : CommandObjectTypeFormatterDelete( 2250 interpreter, 2251 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2252 "type filter delete", "Delete an existing filter for a type.") {} 2253 2254 ~CommandObjectTypeFilterDelete() override = default; 2255 }; 2256 2257 #if LLDB_ENABLE_PYTHON 2258 2259 // CommandObjectTypeSynthDelete 2260 2261 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { 2262 public: 2263 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) 2264 : CommandObjectTypeFormatterDelete( 2265 interpreter, 2266 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2267 "type synthetic delete", 2268 "Delete an existing synthetic provider for a type.") {} 2269 2270 ~CommandObjectTypeSynthDelete() override = default; 2271 }; 2272 2273 #endif 2274 2275 // CommandObjectTypeFilterClear 2276 2277 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { 2278 public: 2279 CommandObjectTypeFilterClear(CommandInterpreter &interpreter) 2280 : CommandObjectTypeFormatterClear( 2281 interpreter, 2282 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2283 "type filter clear", "Delete all existing filter.") {} 2284 }; 2285 2286 #if LLDB_ENABLE_PYTHON 2287 // CommandObjectTypeSynthClear 2288 2289 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { 2290 public: 2291 CommandObjectTypeSynthClear(CommandInterpreter &interpreter) 2292 : CommandObjectTypeFormatterClear( 2293 interpreter, 2294 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2295 "type synthetic clear", 2296 "Delete all existing synthetic providers.") {} 2297 }; 2298 2299 bool CommandObjectTypeSynthAdd::Execute_HandwritePython( 2300 Args &command, CommandReturnObject &result) { 2301 SynthAddOptions *options = new SynthAddOptions( 2302 m_options.m_skip_pointers, m_options.m_skip_references, 2303 m_options.m_cascade, m_options.m_regex, m_options.m_category); 2304 2305 for (auto &entry : command.entries()) { 2306 if (entry.ref().empty()) { 2307 result.AppendError("empty typenames not allowed"); 2308 result.SetStatus(eReturnStatusFailed); 2309 return false; 2310 } 2311 2312 options->m_target_types << std::string(entry.ref()); 2313 } 2314 2315 m_interpreter.GetPythonCommandsFromIOHandler( 2316 " ", // Prompt 2317 *this, // IOHandlerDelegate 2318 options); // Baton for the "io_handler" that will be passed back into our 2319 // IOHandlerDelegate functions 2320 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2321 return result.Succeeded(); 2322 } 2323 2324 bool CommandObjectTypeSynthAdd::Execute_PythonClass( 2325 Args &command, CommandReturnObject &result) { 2326 const size_t argc = command.GetArgumentCount(); 2327 2328 if (argc < 1) { 2329 result.AppendErrorWithFormat("%s takes one or more args.\n", 2330 m_cmd_name.c_str()); 2331 result.SetStatus(eReturnStatusFailed); 2332 return false; 2333 } 2334 2335 if (m_options.m_class_name.empty() && !m_options.m_input_python) { 2336 result.AppendErrorWithFormat("%s needs either a Python class name or -P to " 2337 "directly input Python code.\n", 2338 m_cmd_name.c_str()); 2339 result.SetStatus(eReturnStatusFailed); 2340 return false; 2341 } 2342 2343 SyntheticChildrenSP entry; 2344 2345 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren( 2346 SyntheticChildren::Flags() 2347 .SetCascades(m_options.m_cascade) 2348 .SetSkipPointers(m_options.m_skip_pointers) 2349 .SetSkipReferences(m_options.m_skip_references), 2350 m_options.m_class_name.c_str()); 2351 2352 entry.reset(impl); 2353 2354 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2355 2356 if (interpreter && 2357 !interpreter->CheckObjectExists(impl->GetPythonClassName())) 2358 result.AppendWarning("The provided class does not exist - please define it " 2359 "before attempting to use this synthetic provider"); 2360 2361 // now I have a valid provider, let's add it to every type 2362 2363 lldb::TypeCategoryImplSP category; 2364 DataVisualization::Categories::GetCategory( 2365 ConstString(m_options.m_category.c_str()), category); 2366 2367 Status error; 2368 2369 for (auto &arg_entry : command.entries()) { 2370 if (arg_entry.ref().empty()) { 2371 result.AppendError("empty typenames not allowed"); 2372 result.SetStatus(eReturnStatusFailed); 2373 return false; 2374 } 2375 2376 ConstString typeCS(arg_entry.ref()); 2377 if (!AddSynth(typeCS, entry, 2378 m_options.m_regex ? eRegexSynth : eRegularSynth, 2379 m_options.m_category, &error)) { 2380 result.AppendError(error.AsCString()); 2381 result.SetStatus(eReturnStatusFailed); 2382 return false; 2383 } 2384 } 2385 2386 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2387 return result.Succeeded(); 2388 } 2389 2390 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd( 2391 CommandInterpreter &interpreter) 2392 : CommandObjectParsed(interpreter, "type synthetic add", 2393 "Add a new synthetic provider for a type.", nullptr), 2394 IOHandlerDelegateMultiline("DONE"), m_options() { 2395 CommandArgumentEntry type_arg; 2396 CommandArgumentData type_style_arg; 2397 2398 type_style_arg.arg_type = eArgTypeName; 2399 type_style_arg.arg_repetition = eArgRepeatPlus; 2400 2401 type_arg.push_back(type_style_arg); 2402 2403 m_arguments.push_back(type_arg); 2404 } 2405 2406 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 2407 SyntheticChildrenSP entry, 2408 SynthFormatType type, 2409 std::string category_name, 2410 Status *error) { 2411 lldb::TypeCategoryImplSP category; 2412 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 2413 category); 2414 2415 if (type == eRegularSynth) { 2416 if (FixArrayTypeNameWithRegex(type_name)) 2417 type = eRegexSynth; 2418 } 2419 2420 if (category->AnyMatches( 2421 type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2422 false)) { 2423 if (error) 2424 error->SetErrorStringWithFormat("cannot add synthetic for type %s when " 2425 "filter is defined in same category!", 2426 type_name.AsCString()); 2427 return false; 2428 } 2429 2430 if (type == eRegexSynth) { 2431 RegularExpression typeRX(type_name.GetStringRef()); 2432 if (!typeRX.IsValid()) { 2433 if (error) 2434 error->SetErrorString( 2435 "regex format error (maybe this is not really a regex?)"); 2436 return false; 2437 } 2438 2439 category->GetRegexTypeSyntheticsContainer()->Delete(type_name); 2440 category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry); 2441 2442 return true; 2443 } else { 2444 category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry); 2445 return true; 2446 } 2447 } 2448 2449 #endif 2450 #define LLDB_OPTIONS_type_filter_add 2451 #include "CommandOptions.inc" 2452 2453 class CommandObjectTypeFilterAdd : public CommandObjectParsed { 2454 private: 2455 class CommandOptions : public Options { 2456 typedef std::vector<std::string> option_vector; 2457 2458 public: 2459 CommandOptions() : Options() {} 2460 2461 ~CommandOptions() override = default; 2462 2463 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2464 ExecutionContext *execution_context) override { 2465 Status error; 2466 const int short_option = m_getopt_table[option_idx].val; 2467 bool success; 2468 2469 switch (short_option) { 2470 case 'C': 2471 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success); 2472 if (!success) 2473 error.SetErrorStringWithFormat("invalid value for cascade: %s", 2474 option_arg.str().c_str()); 2475 break; 2476 case 'c': 2477 m_expr_paths.push_back(std::string(option_arg)); 2478 has_child_list = true; 2479 break; 2480 case 'p': 2481 m_skip_pointers = true; 2482 break; 2483 case 'r': 2484 m_skip_references = true; 2485 break; 2486 case 'w': 2487 m_category = std::string(option_arg); 2488 break; 2489 case 'x': 2490 m_regex = true; 2491 break; 2492 default: 2493 llvm_unreachable("Unimplemented option"); 2494 } 2495 2496 return error; 2497 } 2498 2499 void OptionParsingStarting(ExecutionContext *execution_context) override { 2500 m_cascade = true; 2501 m_skip_pointers = false; 2502 m_skip_references = false; 2503 m_category = "default"; 2504 m_expr_paths.clear(); 2505 has_child_list = false; 2506 m_regex = false; 2507 } 2508 2509 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2510 return llvm::makeArrayRef(g_type_filter_add_options); 2511 } 2512 2513 // Instance variables to hold the values for command options. 2514 2515 bool m_cascade; 2516 bool m_skip_references; 2517 bool m_skip_pointers; 2518 bool m_input_python; 2519 option_vector m_expr_paths; 2520 std::string m_category; 2521 bool has_child_list; 2522 bool m_regex; 2523 2524 typedef option_vector::iterator ExpressionPathsIterator; 2525 }; 2526 2527 CommandOptions m_options; 2528 2529 Options *GetOptions() override { return &m_options; } 2530 2531 enum FilterFormatType { eRegularFilter, eRegexFilter }; 2532 2533 bool AddFilter(ConstString type_name, TypeFilterImplSP entry, 2534 FilterFormatType type, std::string category_name, 2535 Status *error) { 2536 lldb::TypeCategoryImplSP category; 2537 DataVisualization::Categories::GetCategory( 2538 ConstString(category_name.c_str()), category); 2539 2540 if (type == eRegularFilter) { 2541 if (FixArrayTypeNameWithRegex(type_name)) 2542 type = eRegexFilter; 2543 } 2544 2545 if (category->AnyMatches( 2546 type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2547 false)) { 2548 if (error) 2549 error->SetErrorStringWithFormat("cannot add filter for type %s when " 2550 "synthetic is defined in same " 2551 "category!", 2552 type_name.AsCString()); 2553 return false; 2554 } 2555 2556 if (type == eRegexFilter) { 2557 RegularExpression typeRX(type_name.GetStringRef()); 2558 if (!typeRX.IsValid()) { 2559 if (error) 2560 error->SetErrorString( 2561 "regex format error (maybe this is not really a regex?)"); 2562 return false; 2563 } 2564 2565 category->GetRegexTypeFiltersContainer()->Delete(type_name); 2566 category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry); 2567 2568 return true; 2569 } else { 2570 category->GetTypeFiltersContainer()->Add(std::move(type_name), entry); 2571 return true; 2572 } 2573 } 2574 2575 public: 2576 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter) 2577 : CommandObjectParsed(interpreter, "type filter add", 2578 "Add a new filter for a type.", nullptr), 2579 m_options() { 2580 CommandArgumentEntry type_arg; 2581 CommandArgumentData type_style_arg; 2582 2583 type_style_arg.arg_type = eArgTypeName; 2584 type_style_arg.arg_repetition = eArgRepeatPlus; 2585 2586 type_arg.push_back(type_style_arg); 2587 2588 m_arguments.push_back(type_arg); 2589 2590 SetHelpLong( 2591 R"( 2592 The following examples of 'type filter add' refer to this code snippet for context: 2593 2594 class Foo { 2595 int a; 2596 int b; 2597 int c; 2598 int d; 2599 int e; 2600 int f; 2601 int g; 2602 int h; 2603 int i; 2604 } 2605 Foo my_foo; 2606 2607 Adding a simple filter: 2608 2609 (lldb) type filter add --child a --child g Foo 2610 (lldb) frame variable my_foo 2611 2612 )" 2613 "Produces output where only a and g are displayed. Other children of my_foo \ 2614 (b, c, d, e, f, h and i) are available by asking for them explicitly:" 2615 R"( 2616 2617 (lldb) frame variable my_foo.b my_foo.c my_foo.i 2618 2619 )" 2620 "The formatting option --raw on frame variable bypasses the filter, showing \ 2621 all children of my_foo as if no filter was defined:" 2622 R"( 2623 2624 (lldb) frame variable my_foo --raw)"); 2625 } 2626 2627 ~CommandObjectTypeFilterAdd() override = default; 2628 2629 protected: 2630 bool DoExecute(Args &command, CommandReturnObject &result) override { 2631 const size_t argc = command.GetArgumentCount(); 2632 2633 if (argc < 1) { 2634 result.AppendErrorWithFormat("%s takes one or more args.\n", 2635 m_cmd_name.c_str()); 2636 result.SetStatus(eReturnStatusFailed); 2637 return false; 2638 } 2639 2640 if (m_options.m_expr_paths.empty()) { 2641 result.AppendErrorWithFormat("%s needs one or more children.\n", 2642 m_cmd_name.c_str()); 2643 result.SetStatus(eReturnStatusFailed); 2644 return false; 2645 } 2646 2647 TypeFilterImplSP entry(new TypeFilterImpl( 2648 SyntheticChildren::Flags() 2649 .SetCascades(m_options.m_cascade) 2650 .SetSkipPointers(m_options.m_skip_pointers) 2651 .SetSkipReferences(m_options.m_skip_references))); 2652 2653 // go through the expression paths 2654 CommandOptions::ExpressionPathsIterator begin, 2655 end = m_options.m_expr_paths.end(); 2656 2657 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 2658 entry->AddExpressionPath(*begin); 2659 2660 // now I have a valid provider, let's add it to every type 2661 2662 lldb::TypeCategoryImplSP category; 2663 DataVisualization::Categories::GetCategory( 2664 ConstString(m_options.m_category.c_str()), category); 2665 2666 Status error; 2667 2668 WarnOnPotentialUnquotedUnsignedType(command, result); 2669 2670 for (auto &arg_entry : command.entries()) { 2671 if (arg_entry.ref().empty()) { 2672 result.AppendError("empty typenames not allowed"); 2673 result.SetStatus(eReturnStatusFailed); 2674 return false; 2675 } 2676 2677 ConstString typeCS(arg_entry.ref()); 2678 if (!AddFilter(typeCS, entry, 2679 m_options.m_regex ? eRegexFilter : eRegularFilter, 2680 m_options.m_category, &error)) { 2681 result.AppendError(error.AsCString()); 2682 result.SetStatus(eReturnStatusFailed); 2683 return false; 2684 } 2685 } 2686 2687 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2688 return result.Succeeded(); 2689 } 2690 }; 2691 2692 // "type lookup" 2693 #define LLDB_OPTIONS_type_lookup 2694 #include "CommandOptions.inc" 2695 2696 class CommandObjectTypeLookup : public CommandObjectRaw { 2697 protected: 2698 // this function is allowed to do a more aggressive job at guessing languages 2699 // than the expression parser is comfortable with - so leave the original 2700 // call alone and add one that is specific to type lookup 2701 lldb::LanguageType GuessLanguage(StackFrame *frame) { 2702 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; 2703 2704 if (!frame) 2705 return lang_type; 2706 2707 lang_type = frame->GuessLanguage(); 2708 if (lang_type != lldb::eLanguageTypeUnknown) 2709 return lang_type; 2710 2711 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 2712 if (s) 2713 lang_type = s->GetMangled().GuessLanguage(); 2714 2715 return lang_type; 2716 } 2717 2718 class CommandOptions : public OptionGroup { 2719 public: 2720 CommandOptions() 2721 : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {} 2722 2723 ~CommandOptions() override = default; 2724 2725 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2726 return llvm::makeArrayRef(g_type_lookup_options); 2727 } 2728 2729 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 2730 ExecutionContext *execution_context) override { 2731 Status error; 2732 2733 const int short_option = g_type_lookup_options[option_idx].short_option; 2734 2735 switch (short_option) { 2736 case 'h': 2737 m_show_help = true; 2738 break; 2739 2740 case 'l': 2741 m_language = Language::GetLanguageTypeFromString(option_value); 2742 break; 2743 2744 default: 2745 llvm_unreachable("Unimplemented option"); 2746 } 2747 2748 return error; 2749 } 2750 2751 void OptionParsingStarting(ExecutionContext *execution_context) override { 2752 m_show_help = false; 2753 m_language = eLanguageTypeUnknown; 2754 } 2755 2756 // Options table: Required for subclasses of Options. 2757 2758 bool m_show_help; 2759 lldb::LanguageType m_language; 2760 }; 2761 2762 OptionGroupOptions m_option_group; 2763 CommandOptions m_command_options; 2764 2765 public: 2766 CommandObjectTypeLookup(CommandInterpreter &interpreter) 2767 : CommandObjectRaw(interpreter, "type lookup", 2768 "Lookup types and declarations in the current target, " 2769 "following language-specific naming conventions.", 2770 "type lookup <type-specifier>", 2771 eCommandRequiresTarget), 2772 m_option_group(), m_command_options() { 2773 m_option_group.Append(&m_command_options); 2774 m_option_group.Finalize(); 2775 } 2776 2777 ~CommandObjectTypeLookup() override = default; 2778 2779 Options *GetOptions() override { return &m_option_group; } 2780 2781 llvm::StringRef GetHelpLong() override { 2782 if (!m_cmd_help_long.empty()) 2783 return m_cmd_help_long; 2784 2785 StreamString stream; 2786 Language::ForEach([&](Language *lang) { 2787 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp()) 2788 stream.Printf("%s\n", help); 2789 return true; 2790 }); 2791 2792 m_cmd_help_long = std::string(stream.GetString()); 2793 return m_cmd_help_long; 2794 } 2795 2796 bool DoExecute(llvm::StringRef raw_command_line, 2797 CommandReturnObject &result) override { 2798 if (raw_command_line.empty()) { 2799 result.SetError( 2800 "type lookup cannot be invoked without a type name as argument"); 2801 return false; 2802 } 2803 2804 auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 2805 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 2806 2807 OptionsWithRaw args(raw_command_line); 2808 const char *name_of_type = args.GetRawPart().c_str(); 2809 2810 if (args.HasArgs()) 2811 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 2812 exe_ctx)) 2813 return false; 2814 2815 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 2816 2817 bool any_found = false; 2818 2819 std::vector<Language *> languages; 2820 2821 bool is_global_search = false; 2822 LanguageType guessed_language = lldb::eLanguageTypeUnknown; 2823 2824 if ((is_global_search = 2825 (m_command_options.m_language == eLanguageTypeUnknown))) { 2826 Language::ForEach([&](Language *lang) { 2827 languages.push_back(lang); 2828 return true; 2829 }); 2830 } else { 2831 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 2832 } 2833 2834 // This is not the most efficient way to do this, but we support very few 2835 // languages so the cost of the sort is going to be dwarfed by the actual 2836 // lookup anyway 2837 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { 2838 guessed_language = GuessLanguage(frame); 2839 if (guessed_language != eLanguageTypeUnknown) { 2840 llvm::sort( 2841 languages.begin(), languages.end(), 2842 [guessed_language](Language *lang1, Language *lang2) -> bool { 2843 if (!lang1 || !lang2) 2844 return false; 2845 LanguageType lt1 = lang1->GetLanguageType(); 2846 LanguageType lt2 = lang2->GetLanguageType(); 2847 if (lt1 == guessed_language) 2848 return true; // make the selected frame's language come first 2849 if (lt2 == guessed_language) 2850 return false; // make the selected frame's language come first 2851 return (lt1 < lt2); // normal comparison otherwise 2852 }); 2853 } 2854 } 2855 2856 bool is_first_language = true; 2857 2858 for (Language *language : languages) { 2859 if (!language) 2860 continue; 2861 2862 if (auto scavenger = language->GetTypeScavenger()) { 2863 Language::TypeScavenger::ResultSet search_results; 2864 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) { 2865 for (const auto &search_result : search_results) { 2866 if (search_result && search_result->IsValid()) { 2867 any_found = true; 2868 search_result->DumpToStream(result.GetOutputStream(), 2869 this->m_command_options.m_show_help); 2870 } 2871 } 2872 } 2873 } 2874 // this is "type lookup SomeName" and we did find a match, so get out 2875 if (any_found && is_global_search) 2876 break; 2877 else if (is_first_language && is_global_search && 2878 guessed_language != lldb::eLanguageTypeUnknown) { 2879 is_first_language = false; 2880 result.GetOutputStream().Printf( 2881 "no type was found in the current language %s matching '%s'; " 2882 "performing a global search across all languages\n", 2883 Language::GetNameForLanguageType(guessed_language), name_of_type); 2884 } 2885 } 2886 2887 if (!any_found) 2888 result.AppendMessageWithFormat("no type was found matching '%s'\n", 2889 name_of_type); 2890 2891 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult 2892 : lldb::eReturnStatusSuccessFinishNoResult); 2893 return true; 2894 } 2895 }; 2896 2897 template <typename FormatterType> 2898 class CommandObjectFormatterInfo : public CommandObjectRaw { 2899 public: 2900 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)> 2901 DiscoveryFunction; 2902 CommandObjectFormatterInfo(CommandInterpreter &interpreter, 2903 const char *formatter_name, 2904 DiscoveryFunction discovery_func) 2905 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame), 2906 m_formatter_name(formatter_name ? formatter_name : ""), 2907 m_discovery_function(discovery_func) { 2908 StreamString name; 2909 name.Printf("type %s info", formatter_name); 2910 SetCommandName(name.GetString()); 2911 StreamString help; 2912 help.Printf("This command evaluates the provided expression and shows " 2913 "which %s is applied to the resulting value (if any).", 2914 formatter_name); 2915 SetHelp(help.GetString()); 2916 StreamString syntax; 2917 syntax.Printf("type %s info <expr>", formatter_name); 2918 SetSyntax(syntax.GetString()); 2919 } 2920 2921 ~CommandObjectFormatterInfo() override = default; 2922 2923 protected: 2924 bool DoExecute(llvm::StringRef command, 2925 CommandReturnObject &result) override { 2926 TargetSP target_sp = GetDebugger().GetSelectedTarget(); 2927 Thread *thread = GetDefaultThread(); 2928 if (!thread) { 2929 result.AppendError("no default thread"); 2930 result.SetStatus(lldb::eReturnStatusFailed); 2931 return false; 2932 } 2933 2934 StackFrameSP frame_sp = thread->GetSelectedFrame(); 2935 ValueObjectSP result_valobj_sp; 2936 EvaluateExpressionOptions options; 2937 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( 2938 command, frame_sp.get(), result_valobj_sp, options); 2939 if (expr_result == eExpressionCompleted && result_valobj_sp) { 2940 result_valobj_sp = 2941 result_valobj_sp->GetQualifiedRepresentationIfAvailable( 2942 target_sp->GetPreferDynamicValue(), 2943 target_sp->GetEnableSyntheticValue()); 2944 typename FormatterType::SharedPointer formatter_sp = 2945 m_discovery_function(*result_valobj_sp); 2946 if (formatter_sp) { 2947 std::string description(formatter_sp->GetDescription()); 2948 result.GetOutputStream() 2949 << m_formatter_name << " applied to (" 2950 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2951 << ") " << command << " is: " << description << "\n"; 2952 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 2953 } else { 2954 result.GetOutputStream() 2955 << "no " << m_formatter_name << " applies to (" 2956 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2957 << ") " << command << "\n"; 2958 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 2959 } 2960 return true; 2961 } else { 2962 result.AppendError("failed to evaluate expression"); 2963 result.SetStatus(lldb::eReturnStatusFailed); 2964 return false; 2965 } 2966 } 2967 2968 private: 2969 std::string m_formatter_name; 2970 DiscoveryFunction m_discovery_function; 2971 }; 2972 2973 class CommandObjectTypeFormat : public CommandObjectMultiword { 2974 public: 2975 CommandObjectTypeFormat(CommandInterpreter &interpreter) 2976 : CommandObjectMultiword( 2977 interpreter, "type format", 2978 "Commands for customizing value display formats.", 2979 "type format [<sub-command-options>] ") { 2980 LoadSubCommand( 2981 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter))); 2982 LoadSubCommand("clear", CommandObjectSP( 2983 new CommandObjectTypeFormatClear(interpreter))); 2984 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete( 2985 interpreter))); 2986 LoadSubCommand( 2987 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter))); 2988 LoadSubCommand( 2989 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>( 2990 interpreter, "format", 2991 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer { 2992 return valobj.GetValueFormat(); 2993 }))); 2994 } 2995 2996 ~CommandObjectTypeFormat() override = default; 2997 }; 2998 2999 #if LLDB_ENABLE_PYTHON 3000 3001 class CommandObjectTypeSynth : public CommandObjectMultiword { 3002 public: 3003 CommandObjectTypeSynth(CommandInterpreter &interpreter) 3004 : CommandObjectMultiword( 3005 interpreter, "type synthetic", 3006 "Commands for operating on synthetic type representations.", 3007 "type synthetic [<sub-command-options>] ") { 3008 LoadSubCommand("add", 3009 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter))); 3010 LoadSubCommand( 3011 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter))); 3012 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete( 3013 interpreter))); 3014 LoadSubCommand( 3015 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter))); 3016 LoadSubCommand( 3017 "info", 3018 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>( 3019 interpreter, "synthetic", 3020 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer { 3021 return valobj.GetSyntheticChildren(); 3022 }))); 3023 } 3024 3025 ~CommandObjectTypeSynth() override = default; 3026 }; 3027 3028 #endif 3029 3030 class CommandObjectTypeFilter : public CommandObjectMultiword { 3031 public: 3032 CommandObjectTypeFilter(CommandInterpreter &interpreter) 3033 : CommandObjectMultiword(interpreter, "type filter", 3034 "Commands for operating on type filters.", 3035 "type synthetic [<sub-command-options>] ") { 3036 LoadSubCommand( 3037 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter))); 3038 LoadSubCommand("clear", CommandObjectSP( 3039 new CommandObjectTypeFilterClear(interpreter))); 3040 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete( 3041 interpreter))); 3042 LoadSubCommand( 3043 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter))); 3044 } 3045 3046 ~CommandObjectTypeFilter() override = default; 3047 }; 3048 3049 class CommandObjectTypeCategory : public CommandObjectMultiword { 3050 public: 3051 CommandObjectTypeCategory(CommandInterpreter &interpreter) 3052 : CommandObjectMultiword(interpreter, "type category", 3053 "Commands for operating on type categories.", 3054 "type category [<sub-command-options>] ") { 3055 LoadSubCommand( 3056 "define", 3057 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter))); 3058 LoadSubCommand( 3059 "enable", 3060 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter))); 3061 LoadSubCommand( 3062 "disable", 3063 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter))); 3064 LoadSubCommand( 3065 "delete", 3066 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter))); 3067 LoadSubCommand("list", CommandObjectSP( 3068 new CommandObjectTypeCategoryList(interpreter))); 3069 } 3070 3071 ~CommandObjectTypeCategory() override = default; 3072 }; 3073 3074 class CommandObjectTypeSummary : public CommandObjectMultiword { 3075 public: 3076 CommandObjectTypeSummary(CommandInterpreter &interpreter) 3077 : CommandObjectMultiword( 3078 interpreter, "type summary", 3079 "Commands for editing variable summary display options.", 3080 "type summary [<sub-command-options>] ") { 3081 LoadSubCommand( 3082 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter))); 3083 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear( 3084 interpreter))); 3085 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete( 3086 interpreter))); 3087 LoadSubCommand( 3088 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter))); 3089 LoadSubCommand( 3090 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>( 3091 interpreter, "summary", 3092 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer { 3093 return valobj.GetSummaryFormat(); 3094 }))); 3095 } 3096 3097 ~CommandObjectTypeSummary() override = default; 3098 }; 3099 3100 // CommandObjectType 3101 3102 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) 3103 : CommandObjectMultiword(interpreter, "type", 3104 "Commands for operating on the type system.", 3105 "type [<sub-command-options>]") { 3106 LoadSubCommand("category", 3107 CommandObjectSP(new CommandObjectTypeCategory(interpreter))); 3108 LoadSubCommand("filter", 3109 CommandObjectSP(new CommandObjectTypeFilter(interpreter))); 3110 LoadSubCommand("format", 3111 CommandObjectSP(new CommandObjectTypeFormat(interpreter))); 3112 LoadSubCommand("summary", 3113 CommandObjectSP(new CommandObjectTypeSummary(interpreter))); 3114 #if LLDB_ENABLE_PYTHON 3115 LoadSubCommand("synthetic", 3116 CommandObjectSP(new CommandObjectTypeSynth(interpreter))); 3117 #endif 3118 LoadSubCommand("lookup", 3119 CommandObjectSP(new CommandObjectTypeLookup(interpreter))); 3120 } 3121 3122 CommandObjectType::~CommandObjectType() = default; 3123