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