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