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 protected: 1762 void DoExecute(Args &command, CommandReturnObject &result) override { 1763 const size_t argc = command.GetArgumentCount(); 1764 1765 if (argc < 1) { 1766 result.AppendErrorWithFormat("%s takes 1 or more args.\n", 1767 m_cmd_name.c_str()); 1768 return; 1769 } 1770 1771 for (auto &entry : command.entries()) { 1772 TypeCategoryImplSP category_sp; 1773 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), 1774 category_sp) && 1775 category_sp) { 1776 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 1777 if (m_options.m_define_enabled.GetCurrentValue()) 1778 DataVisualization::Categories::Enable(category_sp, 1779 TypeCategoryMap::Default); 1780 } 1781 } 1782 1783 result.SetStatus(eReturnStatusSuccessFinishResult); 1784 } 1785 }; 1786 1787 // CommandObjectTypeCategoryEnable 1788 #define LLDB_OPTIONS_type_category_enable 1789 #include "CommandOptions.inc" 1790 1791 class CommandObjectTypeCategoryEnable : public CommandObjectParsed { 1792 class CommandOptions : public Options { 1793 public: 1794 CommandOptions() = default; 1795 1796 ~CommandOptions() override = default; 1797 1798 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1799 ExecutionContext *execution_context) override { 1800 Status error; 1801 const int short_option = m_getopt_table[option_idx].val; 1802 1803 switch (short_option) { 1804 case 'l': 1805 if (!option_arg.empty()) { 1806 m_language = Language::GetLanguageTypeFromString(option_arg); 1807 if (m_language == lldb::eLanguageTypeUnknown) 1808 error.SetErrorStringWithFormat("unrecognized language '%s'", 1809 option_arg.str().c_str()); 1810 } 1811 break; 1812 default: 1813 llvm_unreachable("Unimplemented option"); 1814 } 1815 1816 return error; 1817 } 1818 1819 void OptionParsingStarting(ExecutionContext *execution_context) override { 1820 m_language = lldb::eLanguageTypeUnknown; 1821 } 1822 1823 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1824 return llvm::ArrayRef(g_type_category_enable_options); 1825 } 1826 1827 // Instance variables to hold the values for command options. 1828 1829 lldb::LanguageType m_language; 1830 }; 1831 1832 CommandOptions m_options; 1833 1834 Options *GetOptions() override { return &m_options; } 1835 1836 public: 1837 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter) 1838 : CommandObjectParsed(interpreter, "type category enable", 1839 "Enable a category as a source of formatters.", 1840 nullptr) { 1841 CommandArgumentEntry type_arg; 1842 CommandArgumentData type_style_arg; 1843 1844 type_style_arg.arg_type = eArgTypeName; 1845 type_style_arg.arg_repetition = eArgRepeatPlus; 1846 1847 type_arg.push_back(type_style_arg); 1848 1849 m_arguments.push_back(type_arg); 1850 } 1851 1852 ~CommandObjectTypeCategoryEnable() override = default; 1853 1854 protected: 1855 void DoExecute(Args &command, CommandReturnObject &result) override { 1856 const size_t argc = command.GetArgumentCount(); 1857 1858 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 1859 result.AppendErrorWithFormat("%s takes arguments and/or a language", 1860 m_cmd_name.c_str()); 1861 return; 1862 } 1863 1864 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 1865 DataVisualization::Categories::EnableStar(); 1866 } else if (argc > 0) { 1867 for (int i = argc - 1; i >= 0; i--) { 1868 const char *typeA = command.GetArgumentAtIndex(i); 1869 ConstString typeCS(typeA); 1870 1871 if (!typeCS) { 1872 result.AppendError("empty category name not allowed"); 1873 return; 1874 } 1875 DataVisualization::Categories::Enable(typeCS); 1876 lldb::TypeCategoryImplSP cate; 1877 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) { 1878 if (cate->GetCount() == 0) { 1879 result.AppendWarning("empty category enabled (typo?)"); 1880 } 1881 } 1882 } 1883 } 1884 1885 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1886 DataVisualization::Categories::Enable(m_options.m_language); 1887 1888 result.SetStatus(eReturnStatusSuccessFinishResult); 1889 } 1890 }; 1891 1892 // CommandObjectTypeCategoryDelete 1893 1894 class CommandObjectTypeCategoryDelete : public CommandObjectParsed { 1895 public: 1896 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter) 1897 : CommandObjectParsed(interpreter, "type category delete", 1898 "Delete a category and all associated formatters.", 1899 nullptr) { 1900 CommandArgumentEntry type_arg; 1901 CommandArgumentData type_style_arg; 1902 1903 type_style_arg.arg_type = eArgTypeName; 1904 type_style_arg.arg_repetition = eArgRepeatPlus; 1905 1906 type_arg.push_back(type_style_arg); 1907 1908 m_arguments.push_back(type_arg); 1909 } 1910 1911 ~CommandObjectTypeCategoryDelete() override = default; 1912 1913 protected: 1914 void DoExecute(Args &command, CommandReturnObject &result) override { 1915 const size_t argc = command.GetArgumentCount(); 1916 1917 if (argc < 1) { 1918 result.AppendErrorWithFormat("%s takes 1 or more arg.\n", 1919 m_cmd_name.c_str()); 1920 return; 1921 } 1922 1923 bool success = true; 1924 1925 // the order is not relevant here 1926 for (int i = argc - 1; i >= 0; i--) { 1927 const char *typeA = command.GetArgumentAtIndex(i); 1928 ConstString typeCS(typeA); 1929 1930 if (!typeCS) { 1931 result.AppendError("empty category name not allowed"); 1932 return; 1933 } 1934 if (!DataVisualization::Categories::Delete(typeCS)) 1935 success = false; // keep deleting even if we hit an error 1936 } 1937 if (success) { 1938 result.SetStatus(eReturnStatusSuccessFinishResult); 1939 } else { 1940 result.AppendError("cannot delete one or more categories\n"); 1941 } 1942 } 1943 }; 1944 1945 // CommandObjectTypeCategoryDisable 1946 #define LLDB_OPTIONS_type_category_disable 1947 #include "CommandOptions.inc" 1948 1949 class CommandObjectTypeCategoryDisable : public CommandObjectParsed { 1950 class CommandOptions : public Options { 1951 public: 1952 CommandOptions() = default; 1953 1954 ~CommandOptions() override = default; 1955 1956 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1957 ExecutionContext *execution_context) override { 1958 Status error; 1959 const int short_option = m_getopt_table[option_idx].val; 1960 1961 switch (short_option) { 1962 case 'l': 1963 if (!option_arg.empty()) { 1964 m_language = Language::GetLanguageTypeFromString(option_arg); 1965 if (m_language == lldb::eLanguageTypeUnknown) 1966 error.SetErrorStringWithFormat("unrecognized language '%s'", 1967 option_arg.str().c_str()); 1968 } 1969 break; 1970 default: 1971 llvm_unreachable("Unimplemented option"); 1972 } 1973 1974 return error; 1975 } 1976 1977 void OptionParsingStarting(ExecutionContext *execution_context) override { 1978 m_language = lldb::eLanguageTypeUnknown; 1979 } 1980 1981 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1982 return llvm::ArrayRef(g_type_category_disable_options); 1983 } 1984 1985 // Instance variables to hold the values for command options. 1986 1987 lldb::LanguageType m_language; 1988 }; 1989 1990 CommandOptions m_options; 1991 1992 Options *GetOptions() override { return &m_options; } 1993 1994 public: 1995 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter) 1996 : CommandObjectParsed(interpreter, "type category disable", 1997 "Disable a category as a source of formatters.", 1998 nullptr) { 1999 CommandArgumentEntry type_arg; 2000 CommandArgumentData type_style_arg; 2001 2002 type_style_arg.arg_type = eArgTypeName; 2003 type_style_arg.arg_repetition = eArgRepeatPlus; 2004 2005 type_arg.push_back(type_style_arg); 2006 2007 m_arguments.push_back(type_arg); 2008 } 2009 2010 ~CommandObjectTypeCategoryDisable() override = default; 2011 2012 protected: 2013 void DoExecute(Args &command, CommandReturnObject &result) override { 2014 const size_t argc = command.GetArgumentCount(); 2015 2016 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 2017 result.AppendErrorWithFormat("%s takes arguments and/or a language", 2018 m_cmd_name.c_str()); 2019 return; 2020 } 2021 2022 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 2023 DataVisualization::Categories::DisableStar(); 2024 } else if (argc > 0) { 2025 // the order is not relevant here 2026 for (int i = argc - 1; i >= 0; i--) { 2027 const char *typeA = command.GetArgumentAtIndex(i); 2028 ConstString typeCS(typeA); 2029 2030 if (!typeCS) { 2031 result.AppendError("empty category name not allowed"); 2032 return; 2033 } 2034 DataVisualization::Categories::Disable(typeCS); 2035 } 2036 } 2037 2038 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2039 DataVisualization::Categories::Disable(m_options.m_language); 2040 2041 result.SetStatus(eReturnStatusSuccessFinishResult); 2042 } 2043 }; 2044 2045 // CommandObjectTypeCategoryList 2046 2047 class CommandObjectTypeCategoryList : public CommandObjectParsed { 2048 public: 2049 CommandObjectTypeCategoryList(CommandInterpreter &interpreter) 2050 : CommandObjectParsed(interpreter, "type category list", 2051 "Provide a list of all existing categories.", 2052 nullptr) { 2053 CommandArgumentEntry type_arg; 2054 CommandArgumentData type_style_arg; 2055 2056 type_style_arg.arg_type = eArgTypeName; 2057 type_style_arg.arg_repetition = eArgRepeatOptional; 2058 2059 type_arg.push_back(type_style_arg); 2060 2061 m_arguments.push_back(type_arg); 2062 } 2063 2064 ~CommandObjectTypeCategoryList() override = default; 2065 2066 void 2067 HandleArgumentCompletion(CompletionRequest &request, 2068 OptionElementVector &opt_element_vector) override { 2069 if (request.GetCursorIndex()) 2070 return; 2071 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 2072 GetCommandInterpreter(), lldb::eTypeCategoryNameCompletion, request, 2073 nullptr); 2074 } 2075 2076 protected: 2077 void DoExecute(Args &command, CommandReturnObject &result) override { 2078 const size_t argc = command.GetArgumentCount(); 2079 2080 std::unique_ptr<RegularExpression> regex; 2081 2082 if (argc == 1) { 2083 const char *arg = command.GetArgumentAtIndex(0); 2084 regex = std::make_unique<RegularExpression>(arg); 2085 if (!regex->IsValid()) { 2086 result.AppendErrorWithFormat( 2087 "syntax error in category regular expression '%s'", arg); 2088 return; 2089 } 2090 } else if (argc != 0) { 2091 result.AppendErrorWithFormat("%s takes 0 or one arg.\n", 2092 m_cmd_name.c_str()); 2093 return; 2094 } 2095 2096 DataVisualization::Categories::ForEach( 2097 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool { 2098 if (regex) { 2099 bool escape = true; 2100 if (regex->GetText() == category_sp->GetName()) { 2101 escape = false; 2102 } else if (regex->Execute(category_sp->GetName())) { 2103 escape = false; 2104 } 2105 2106 if (escape) 2107 return true; 2108 } 2109 2110 result.GetOutputStream().Printf( 2111 "Category: %s\n", category_sp->GetDescription().c_str()); 2112 2113 return true; 2114 }); 2115 2116 result.SetStatus(eReturnStatusSuccessFinishResult); 2117 } 2118 }; 2119 2120 // CommandObjectTypeFilterList 2121 2122 class CommandObjectTypeFilterList 2123 : public CommandObjectTypeFormatterList<TypeFilterImpl> { 2124 public: 2125 CommandObjectTypeFilterList(CommandInterpreter &interpreter) 2126 : CommandObjectTypeFormatterList(interpreter, "type filter list", 2127 "Show a list of current filters.") {} 2128 }; 2129 2130 // CommandObjectTypeSynthList 2131 2132 class CommandObjectTypeSynthList 2133 : public CommandObjectTypeFormatterList<SyntheticChildren> { 2134 public: 2135 CommandObjectTypeSynthList(CommandInterpreter &interpreter) 2136 : CommandObjectTypeFormatterList( 2137 interpreter, "type synthetic list", 2138 "Show a list of current synthetic providers.") {} 2139 }; 2140 2141 // CommandObjectTypeFilterDelete 2142 2143 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { 2144 public: 2145 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) 2146 : CommandObjectTypeFormatterDelete( 2147 interpreter, eFormatCategoryItemFilter) {} 2148 2149 ~CommandObjectTypeFilterDelete() override = default; 2150 }; 2151 2152 // CommandObjectTypeSynthDelete 2153 2154 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { 2155 public: 2156 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) 2157 : CommandObjectTypeFormatterDelete( 2158 interpreter, eFormatCategoryItemSynth) {} 2159 2160 ~CommandObjectTypeSynthDelete() override = default; 2161 }; 2162 2163 2164 // CommandObjectTypeFilterClear 2165 2166 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { 2167 public: 2168 CommandObjectTypeFilterClear(CommandInterpreter &interpreter) 2169 : CommandObjectTypeFormatterClear(interpreter, eFormatCategoryItemFilter, 2170 "type filter clear", 2171 "Delete all existing filter.") {} 2172 }; 2173 2174 // CommandObjectTypeSynthClear 2175 2176 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { 2177 public: 2178 CommandObjectTypeSynthClear(CommandInterpreter &interpreter) 2179 : CommandObjectTypeFormatterClear( 2180 interpreter, eFormatCategoryItemSynth, "type synthetic clear", 2181 "Delete all existing synthetic providers.") {} 2182 }; 2183 2184 bool CommandObjectTypeSynthAdd::Execute_HandwritePython( 2185 Args &command, CommandReturnObject &result) { 2186 auto options = std::make_unique<SynthAddOptions>( 2187 m_options.m_skip_pointers, m_options.m_skip_references, 2188 m_options.m_cascade, m_options.m_match_type, m_options.m_category); 2189 2190 for (auto &entry : command.entries()) { 2191 if (entry.ref().empty()) { 2192 result.AppendError("empty typenames not allowed"); 2193 return false; 2194 } 2195 2196 options->m_target_types << std::string(entry.ref()); 2197 } 2198 2199 m_interpreter.GetPythonCommandsFromIOHandler( 2200 " ", // Prompt 2201 *this, // IOHandlerDelegate 2202 options.release()); // Baton for the "io_handler" that will be passed back 2203 // into our IOHandlerDelegate functions 2204 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2205 return result.Succeeded(); 2206 } 2207 2208 bool CommandObjectTypeSynthAdd::Execute_PythonClass( 2209 Args &command, CommandReturnObject &result) { 2210 const size_t argc = command.GetArgumentCount(); 2211 2212 if (argc < 1) { 2213 result.AppendErrorWithFormat("%s takes one or more args.\n", 2214 m_cmd_name.c_str()); 2215 return false; 2216 } 2217 2218 if (m_options.m_class_name.empty() && !m_options.m_input_python) { 2219 result.AppendErrorWithFormat("%s needs either a Python class name or -P to " 2220 "directly input Python code.\n", 2221 m_cmd_name.c_str()); 2222 return false; 2223 } 2224 2225 SyntheticChildrenSP entry; 2226 2227 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren( 2228 SyntheticChildren::Flags() 2229 .SetCascades(m_options.m_cascade) 2230 .SetSkipPointers(m_options.m_skip_pointers) 2231 .SetSkipReferences(m_options.m_skip_references), 2232 m_options.m_class_name.c_str()); 2233 2234 entry.reset(impl); 2235 2236 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2237 2238 if (interpreter && 2239 !interpreter->CheckObjectExists(impl->GetPythonClassName())) 2240 result.AppendWarning("The provided class does not exist - please define it " 2241 "before attempting to use this synthetic provider"); 2242 2243 // now I have a valid provider, let's add it to every type 2244 2245 lldb::TypeCategoryImplSP category; 2246 DataVisualization::Categories::GetCategory( 2247 ConstString(m_options.m_category.c_str()), category); 2248 2249 Status error; 2250 2251 for (auto &arg_entry : command.entries()) { 2252 if (arg_entry.ref().empty()) { 2253 result.AppendError("empty typenames not allowed"); 2254 return false; 2255 } 2256 2257 ConstString typeCS(arg_entry.ref()); 2258 if (!AddSynth(typeCS, entry, m_options.m_match_type, m_options.m_category, 2259 &error)) { 2260 result.AppendError(error.AsCString()); 2261 return false; 2262 } 2263 } 2264 2265 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2266 return result.Succeeded(); 2267 } 2268 2269 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd( 2270 CommandInterpreter &interpreter) 2271 : CommandObjectParsed(interpreter, "type synthetic add", 2272 "Add a new synthetic provider for a type.", nullptr), 2273 IOHandlerDelegateMultiline("DONE"), m_options() { 2274 CommandArgumentEntry type_arg; 2275 CommandArgumentData type_style_arg; 2276 2277 type_style_arg.arg_type = eArgTypeName; 2278 type_style_arg.arg_repetition = eArgRepeatPlus; 2279 2280 type_arg.push_back(type_style_arg); 2281 2282 m_arguments.push_back(type_arg); 2283 } 2284 2285 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 2286 SyntheticChildrenSP entry, 2287 FormatterMatchType match_type, 2288 std::string category_name, 2289 Status *error) { 2290 lldb::TypeCategoryImplSP category; 2291 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 2292 category); 2293 2294 if (match_type == eFormatterMatchExact) { 2295 if (FixArrayTypeNameWithRegex(type_name)) 2296 match_type = eFormatterMatchRegex; 2297 } 2298 2299 // Only check for conflicting filters in the same category if `type_name` is 2300 // an actual type name. Matching a regex string against registered regexes 2301 // doesn't work. 2302 if (match_type == eFormatterMatchExact) { 2303 // It's not generally possible to get a type object here. For example, this 2304 // command can be run before loading any binaries. Do just a best-effort 2305 // name-based lookup here to try to prevent conflicts. 2306 FormattersMatchCandidate candidate_type(type_name, nullptr, TypeImpl(), 2307 FormattersMatchCandidate::Flags()); 2308 if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter, 2309 false)) { 2310 if (error) 2311 error->SetErrorStringWithFormat("cannot add synthetic for type %s when " 2312 "filter is defined in same category!", 2313 type_name.AsCString()); 2314 return false; 2315 } 2316 } 2317 2318 if (match_type == eFormatterMatchRegex) { 2319 RegularExpression typeRX(type_name.GetStringRef()); 2320 if (!typeRX.IsValid()) { 2321 if (error) 2322 error->SetErrorString( 2323 "regex format error (maybe this is not really a regex?)"); 2324 return false; 2325 } 2326 } 2327 2328 if (match_type == eFormatterMatchCallback) { 2329 const char *function_name = type_name.AsCString(); 2330 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2331 if (interpreter && !interpreter->CheckObjectExists(function_name)) { 2332 error->SetErrorStringWithFormat( 2333 "The provided recognizer function \"%s\" does not exist - " 2334 "please define it before attempting to use this summary.\n", 2335 function_name); 2336 return false; 2337 } 2338 } 2339 2340 category->AddTypeSynthetic(type_name.GetStringRef(), match_type, entry); 2341 return true; 2342 } 2343 2344 #define LLDB_OPTIONS_type_filter_add 2345 #include "CommandOptions.inc" 2346 2347 class CommandObjectTypeFilterAdd : public CommandObjectParsed { 2348 private: 2349 class CommandOptions : public Options { 2350 typedef std::vector<std::string> option_vector; 2351 2352 public: 2353 CommandOptions() = default; 2354 2355 ~CommandOptions() override = default; 2356 2357 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2358 ExecutionContext *execution_context) override { 2359 Status error; 2360 const int short_option = m_getopt_table[option_idx].val; 2361 bool success; 2362 2363 switch (short_option) { 2364 case 'C': 2365 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success); 2366 if (!success) 2367 error.SetErrorStringWithFormat("invalid value for cascade: %s", 2368 option_arg.str().c_str()); 2369 break; 2370 case 'c': 2371 m_expr_paths.push_back(std::string(option_arg)); 2372 has_child_list = true; 2373 break; 2374 case 'p': 2375 m_skip_pointers = true; 2376 break; 2377 case 'r': 2378 m_skip_references = true; 2379 break; 2380 case 'w': 2381 m_category = std::string(option_arg); 2382 break; 2383 case 'x': 2384 m_regex = true; 2385 break; 2386 default: 2387 llvm_unreachable("Unimplemented option"); 2388 } 2389 2390 return error; 2391 } 2392 2393 void OptionParsingStarting(ExecutionContext *execution_context) override { 2394 m_cascade = true; 2395 m_skip_pointers = false; 2396 m_skip_references = false; 2397 m_category = "default"; 2398 m_expr_paths.clear(); 2399 has_child_list = false; 2400 m_regex = false; 2401 } 2402 2403 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2404 return llvm::ArrayRef(g_type_filter_add_options); 2405 } 2406 2407 // Instance variables to hold the values for command options. 2408 2409 bool m_cascade; 2410 bool m_skip_references; 2411 bool m_skip_pointers; 2412 bool m_input_python; 2413 option_vector m_expr_paths; 2414 std::string m_category; 2415 bool has_child_list; 2416 bool m_regex; 2417 2418 typedef option_vector::iterator ExpressionPathsIterator; 2419 }; 2420 2421 CommandOptions m_options; 2422 2423 Options *GetOptions() override { return &m_options; } 2424 2425 enum FilterFormatType { eRegularFilter, eRegexFilter }; 2426 2427 bool AddFilter(ConstString type_name, TypeFilterImplSP entry, 2428 FilterFormatType type, std::string category_name, 2429 Status *error) { 2430 lldb::TypeCategoryImplSP category; 2431 DataVisualization::Categories::GetCategory( 2432 ConstString(category_name.c_str()), category); 2433 2434 if (type == eRegularFilter) { 2435 if (FixArrayTypeNameWithRegex(type_name)) 2436 type = eRegexFilter; 2437 } 2438 2439 // Only check for conflicting synthetic child providers in the same category 2440 // if `type_name` is an actual type name. Matching a regex string against 2441 // registered regexes doesn't work. 2442 if (type == eRegularFilter) { 2443 // It's not generally possible to get a type object here. For example, 2444 // this command can be run before loading any binaries. Do just a 2445 // best-effort name-based lookup here to try to prevent conflicts. 2446 FormattersMatchCandidate candidate_type( 2447 type_name, nullptr, TypeImpl(), FormattersMatchCandidate::Flags()); 2448 lldb::SyntheticChildrenSP entry; 2449 if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth, 2450 false)) { 2451 if (error) 2452 error->SetErrorStringWithFormat("cannot add filter for type %s when " 2453 "synthetic is defined in same " 2454 "category!", 2455 type_name.AsCString()); 2456 return false; 2457 } 2458 } 2459 2460 FormatterMatchType match_type = eFormatterMatchExact; 2461 if (type == eRegexFilter) { 2462 match_type = eFormatterMatchRegex; 2463 RegularExpression typeRX(type_name.GetStringRef()); 2464 if (!typeRX.IsValid()) { 2465 if (error) 2466 error->SetErrorString( 2467 "regex format error (maybe this is not really a regex?)"); 2468 return false; 2469 } 2470 } 2471 category->AddTypeFilter(type_name.GetStringRef(), match_type, entry); 2472 return true; 2473 } 2474 2475 public: 2476 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter) 2477 : CommandObjectParsed(interpreter, "type filter add", 2478 "Add a new filter for a type.", nullptr) { 2479 CommandArgumentEntry type_arg; 2480 CommandArgumentData type_style_arg; 2481 2482 type_style_arg.arg_type = eArgTypeName; 2483 type_style_arg.arg_repetition = eArgRepeatPlus; 2484 2485 type_arg.push_back(type_style_arg); 2486 2487 m_arguments.push_back(type_arg); 2488 2489 SetHelpLong( 2490 R"( 2491 The following examples of 'type filter add' refer to this code snippet for context: 2492 2493 class Foo { 2494 int a; 2495 int b; 2496 int c; 2497 int d; 2498 int e; 2499 int f; 2500 int g; 2501 int h; 2502 int i; 2503 } 2504 Foo my_foo; 2505 2506 Adding a simple filter: 2507 2508 (lldb) type filter add --child a --child g Foo 2509 (lldb) frame variable my_foo 2510 2511 )" 2512 "Produces output where only a and g are displayed. Other children of my_foo \ 2513 (b, c, d, e, f, h and i) are available by asking for them explicitly:" 2514 R"( 2515 2516 (lldb) frame variable my_foo.b my_foo.c my_foo.i 2517 2518 )" 2519 "The formatting option --raw on frame variable bypasses the filter, showing \ 2520 all children of my_foo as if no filter was defined:" 2521 R"( 2522 2523 (lldb) frame variable my_foo --raw)"); 2524 } 2525 2526 ~CommandObjectTypeFilterAdd() override = default; 2527 2528 protected: 2529 void DoExecute(Args &command, CommandReturnObject &result) override { 2530 const size_t argc = command.GetArgumentCount(); 2531 2532 if (argc < 1) { 2533 result.AppendErrorWithFormat("%s takes one or more args.\n", 2534 m_cmd_name.c_str()); 2535 return; 2536 } 2537 2538 if (m_options.m_expr_paths.empty()) { 2539 result.AppendErrorWithFormat("%s needs one or more children.\n", 2540 m_cmd_name.c_str()); 2541 return; 2542 } 2543 2544 TypeFilterImplSP entry(new TypeFilterImpl( 2545 SyntheticChildren::Flags() 2546 .SetCascades(m_options.m_cascade) 2547 .SetSkipPointers(m_options.m_skip_pointers) 2548 .SetSkipReferences(m_options.m_skip_references))); 2549 2550 // go through the expression paths 2551 CommandOptions::ExpressionPathsIterator begin, 2552 end = m_options.m_expr_paths.end(); 2553 2554 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 2555 entry->AddExpressionPath(*begin); 2556 2557 // now I have a valid provider, let's add it to every type 2558 2559 lldb::TypeCategoryImplSP category; 2560 DataVisualization::Categories::GetCategory( 2561 ConstString(m_options.m_category.c_str()), category); 2562 2563 Status error; 2564 2565 WarnOnPotentialUnquotedUnsignedType(command, result); 2566 2567 for (auto &arg_entry : command.entries()) { 2568 if (arg_entry.ref().empty()) { 2569 result.AppendError("empty typenames not allowed"); 2570 return; 2571 } 2572 2573 ConstString typeCS(arg_entry.ref()); 2574 if (!AddFilter(typeCS, entry, 2575 m_options.m_regex ? eRegexFilter : eRegularFilter, 2576 m_options.m_category, &error)) { 2577 result.AppendError(error.AsCString()); 2578 return; 2579 } 2580 } 2581 2582 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2583 } 2584 }; 2585 2586 // "type lookup" 2587 #define LLDB_OPTIONS_type_lookup 2588 #include "CommandOptions.inc" 2589 2590 class CommandObjectTypeLookup : public CommandObjectRaw { 2591 protected: 2592 // this function is allowed to do a more aggressive job at guessing languages 2593 // than the expression parser is comfortable with - so leave the original 2594 // call alone and add one that is specific to type lookup 2595 lldb::LanguageType GuessLanguage(StackFrame *frame) { 2596 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; 2597 2598 if (!frame) 2599 return lang_type; 2600 2601 lang_type = frame->GuessLanguage(); 2602 if (lang_type != lldb::eLanguageTypeUnknown) 2603 return lang_type; 2604 2605 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 2606 if (s) 2607 lang_type = s->GetMangled().GuessLanguage(); 2608 2609 return lang_type; 2610 } 2611 2612 class CommandOptions : public OptionGroup { 2613 public: 2614 CommandOptions() = default; 2615 2616 ~CommandOptions() override = default; 2617 2618 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2619 return llvm::ArrayRef(g_type_lookup_options); 2620 } 2621 2622 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 2623 ExecutionContext *execution_context) override { 2624 Status error; 2625 2626 const int short_option = g_type_lookup_options[option_idx].short_option; 2627 2628 switch (short_option) { 2629 case 'h': 2630 m_show_help = true; 2631 break; 2632 2633 case 'l': 2634 m_language = Language::GetLanguageTypeFromString(option_value); 2635 break; 2636 2637 default: 2638 llvm_unreachable("Unimplemented option"); 2639 } 2640 2641 return error; 2642 } 2643 2644 void OptionParsingStarting(ExecutionContext *execution_context) override { 2645 m_show_help = false; 2646 m_language = eLanguageTypeUnknown; 2647 } 2648 2649 // Options table: Required for subclasses of Options. 2650 2651 bool m_show_help = false; 2652 lldb::LanguageType m_language = eLanguageTypeUnknown; 2653 }; 2654 2655 OptionGroupOptions m_option_group; 2656 CommandOptions m_command_options; 2657 2658 public: 2659 CommandObjectTypeLookup(CommandInterpreter &interpreter) 2660 : CommandObjectRaw(interpreter, "type lookup", 2661 "Lookup types and declarations in the current target, " 2662 "following language-specific naming conventions.", 2663 "type lookup <type-specifier>", 2664 eCommandRequiresTarget) { 2665 m_option_group.Append(&m_command_options); 2666 m_option_group.Finalize(); 2667 } 2668 2669 ~CommandObjectTypeLookup() override = default; 2670 2671 Options *GetOptions() override { return &m_option_group; } 2672 2673 llvm::StringRef GetHelpLong() override { 2674 if (!m_cmd_help_long.empty()) 2675 return m_cmd_help_long; 2676 2677 StreamString stream; 2678 Language::ForEach([&](Language *lang) { 2679 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp()) 2680 stream.Printf("%s\n", help); 2681 return true; 2682 }); 2683 2684 m_cmd_help_long = std::string(stream.GetString()); 2685 return m_cmd_help_long; 2686 } 2687 2688 void DoExecute(llvm::StringRef raw_command_line, 2689 CommandReturnObject &result) override { 2690 if (raw_command_line.empty()) { 2691 result.AppendError( 2692 "type lookup cannot be invoked without a type name as argument"); 2693 return; 2694 } 2695 2696 auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 2697 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 2698 2699 OptionsWithRaw args(raw_command_line); 2700 const char *name_of_type = args.GetRawPart().c_str(); 2701 2702 if (args.HasArgs()) 2703 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 2704 exe_ctx)) 2705 return; 2706 2707 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 2708 2709 bool any_found = false; 2710 2711 std::vector<Language *> languages; 2712 2713 bool is_global_search = false; 2714 LanguageType guessed_language = lldb::eLanguageTypeUnknown; 2715 2716 if ((is_global_search = 2717 (m_command_options.m_language == eLanguageTypeUnknown))) { 2718 Language::ForEach([&](Language *lang) { 2719 languages.push_back(lang); 2720 return true; 2721 }); 2722 } else { 2723 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 2724 } 2725 2726 // This is not the most efficient way to do this, but we support very few 2727 // languages so the cost of the sort is going to be dwarfed by the actual 2728 // lookup anyway 2729 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { 2730 guessed_language = GuessLanguage(frame); 2731 if (guessed_language != eLanguageTypeUnknown) { 2732 llvm::sort( 2733 languages.begin(), languages.end(), 2734 [guessed_language](Language *lang1, Language *lang2) -> bool { 2735 if (!lang1 || !lang2) 2736 return false; 2737 LanguageType lt1 = lang1->GetLanguageType(); 2738 LanguageType lt2 = lang2->GetLanguageType(); 2739 if (lt1 == guessed_language) 2740 return true; // make the selected frame's language come first 2741 if (lt2 == guessed_language) 2742 return false; // make the selected frame's language come first 2743 return (lt1 < lt2); // normal comparison otherwise 2744 }); 2745 } 2746 } 2747 2748 bool is_first_language = true; 2749 2750 for (Language *language : languages) { 2751 if (!language) 2752 continue; 2753 2754 if (auto scavenger = language->GetTypeScavenger()) { 2755 Language::TypeScavenger::ResultSet search_results; 2756 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) { 2757 for (const auto &search_result : search_results) { 2758 if (search_result && search_result->IsValid()) { 2759 any_found = true; 2760 search_result->DumpToStream(result.GetOutputStream(), 2761 this->m_command_options.m_show_help); 2762 } 2763 } 2764 } 2765 } 2766 // this is "type lookup SomeName" and we did find a match, so get out 2767 if (any_found && is_global_search) 2768 break; 2769 else if (is_first_language && is_global_search && 2770 guessed_language != lldb::eLanguageTypeUnknown) { 2771 is_first_language = false; 2772 result.GetOutputStream().Printf( 2773 "no type was found in the current language %s matching '%s'; " 2774 "performing a global search across all languages\n", 2775 Language::GetNameForLanguageType(guessed_language), name_of_type); 2776 } 2777 } 2778 2779 if (!any_found) 2780 result.AppendMessageWithFormat("no type was found matching '%s'\n", 2781 name_of_type); 2782 2783 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult 2784 : lldb::eReturnStatusSuccessFinishNoResult); 2785 } 2786 }; 2787 2788 template <typename FormatterType> 2789 class CommandObjectFormatterInfo : public CommandObjectRaw { 2790 public: 2791 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)> 2792 DiscoveryFunction; 2793 CommandObjectFormatterInfo(CommandInterpreter &interpreter, 2794 const char *formatter_name, 2795 DiscoveryFunction discovery_func) 2796 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame), 2797 m_formatter_name(formatter_name ? formatter_name : ""), 2798 m_discovery_function(discovery_func) { 2799 StreamString name; 2800 name.Printf("type %s info", formatter_name); 2801 SetCommandName(name.GetString()); 2802 StreamString help; 2803 help.Printf("This command evaluates the provided expression and shows " 2804 "which %s is applied to the resulting value (if any).", 2805 formatter_name); 2806 SetHelp(help.GetString()); 2807 StreamString syntax; 2808 syntax.Printf("type %s info <expr>", formatter_name); 2809 SetSyntax(syntax.GetString()); 2810 } 2811 2812 ~CommandObjectFormatterInfo() override = default; 2813 2814 protected: 2815 void DoExecute(llvm::StringRef command, 2816 CommandReturnObject &result) override { 2817 TargetSP target_sp = GetDebugger().GetSelectedTarget(); 2818 Thread *thread = GetDefaultThread(); 2819 if (!thread) { 2820 result.AppendError("no default thread"); 2821 return; 2822 } 2823 2824 StackFrameSP frame_sp = 2825 thread->GetSelectedFrame(DoNoSelectMostRelevantFrame); 2826 ValueObjectSP result_valobj_sp; 2827 EvaluateExpressionOptions options; 2828 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( 2829 command, frame_sp.get(), result_valobj_sp, options); 2830 if (expr_result == eExpressionCompleted && result_valobj_sp) { 2831 result_valobj_sp = 2832 result_valobj_sp->GetQualifiedRepresentationIfAvailable( 2833 target_sp->GetPreferDynamicValue(), 2834 target_sp->GetEnableSyntheticValue()); 2835 typename FormatterType::SharedPointer formatter_sp = 2836 m_discovery_function(*result_valobj_sp); 2837 if (formatter_sp) { 2838 std::string description(formatter_sp->GetDescription()); 2839 result.GetOutputStream() 2840 << m_formatter_name << " applied to (" 2841 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2842 << ") " << command << " is: " << description << "\n"; 2843 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 2844 } else { 2845 result.GetOutputStream() 2846 << "no " << m_formatter_name << " applies to (" 2847 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2848 << ") " << command << "\n"; 2849 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 2850 } 2851 } else { 2852 result.AppendError("failed to evaluate expression"); 2853 } 2854 } 2855 2856 private: 2857 std::string m_formatter_name; 2858 DiscoveryFunction m_discovery_function; 2859 }; 2860 2861 class CommandObjectTypeFormat : public CommandObjectMultiword { 2862 public: 2863 CommandObjectTypeFormat(CommandInterpreter &interpreter) 2864 : CommandObjectMultiword( 2865 interpreter, "type format", 2866 "Commands for customizing value display formats.", 2867 "type format [<sub-command-options>] ") { 2868 LoadSubCommand( 2869 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter))); 2870 LoadSubCommand("clear", CommandObjectSP( 2871 new CommandObjectTypeFormatClear(interpreter))); 2872 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete( 2873 interpreter))); 2874 LoadSubCommand( 2875 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter))); 2876 LoadSubCommand( 2877 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>( 2878 interpreter, "format", 2879 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer { 2880 return valobj.GetValueFormat(); 2881 }))); 2882 } 2883 2884 ~CommandObjectTypeFormat() override = default; 2885 }; 2886 2887 class CommandObjectTypeSynth : public CommandObjectMultiword { 2888 public: 2889 CommandObjectTypeSynth(CommandInterpreter &interpreter) 2890 : CommandObjectMultiword( 2891 interpreter, "type synthetic", 2892 "Commands for operating on synthetic type representations.", 2893 "type synthetic [<sub-command-options>] ") { 2894 LoadSubCommand("add", 2895 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter))); 2896 LoadSubCommand( 2897 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter))); 2898 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete( 2899 interpreter))); 2900 LoadSubCommand( 2901 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter))); 2902 LoadSubCommand( 2903 "info", 2904 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>( 2905 interpreter, "synthetic", 2906 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer { 2907 return valobj.GetSyntheticChildren(); 2908 }))); 2909 } 2910 2911 ~CommandObjectTypeSynth() override = default; 2912 }; 2913 2914 class CommandObjectTypeFilter : public CommandObjectMultiword { 2915 public: 2916 CommandObjectTypeFilter(CommandInterpreter &interpreter) 2917 : CommandObjectMultiword(interpreter, "type filter", 2918 "Commands for operating on type filters.", 2919 "type filter [<sub-command-options>] ") { 2920 LoadSubCommand( 2921 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter))); 2922 LoadSubCommand("clear", CommandObjectSP( 2923 new CommandObjectTypeFilterClear(interpreter))); 2924 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete( 2925 interpreter))); 2926 LoadSubCommand( 2927 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter))); 2928 } 2929 2930 ~CommandObjectTypeFilter() override = default; 2931 }; 2932 2933 class CommandObjectTypeCategory : public CommandObjectMultiword { 2934 public: 2935 CommandObjectTypeCategory(CommandInterpreter &interpreter) 2936 : CommandObjectMultiword(interpreter, "type category", 2937 "Commands for operating on type categories.", 2938 "type category [<sub-command-options>] ") { 2939 LoadSubCommand( 2940 "define", 2941 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter))); 2942 LoadSubCommand( 2943 "enable", 2944 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter))); 2945 LoadSubCommand( 2946 "disable", 2947 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter))); 2948 LoadSubCommand( 2949 "delete", 2950 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter))); 2951 LoadSubCommand("list", CommandObjectSP( 2952 new CommandObjectTypeCategoryList(interpreter))); 2953 } 2954 2955 ~CommandObjectTypeCategory() override = default; 2956 }; 2957 2958 class CommandObjectTypeSummary : public CommandObjectMultiword { 2959 public: 2960 CommandObjectTypeSummary(CommandInterpreter &interpreter) 2961 : CommandObjectMultiword( 2962 interpreter, "type summary", 2963 "Commands for editing variable summary display options.", 2964 "type summary [<sub-command-options>] ") { 2965 LoadSubCommand( 2966 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter))); 2967 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear( 2968 interpreter))); 2969 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete( 2970 interpreter))); 2971 LoadSubCommand( 2972 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter))); 2973 LoadSubCommand( 2974 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>( 2975 interpreter, "summary", 2976 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer { 2977 return valobj.GetSummaryFormat(); 2978 }))); 2979 } 2980 2981 ~CommandObjectTypeSummary() override = default; 2982 }; 2983 2984 // CommandObjectType 2985 2986 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) 2987 : CommandObjectMultiword(interpreter, "type", 2988 "Commands for operating on the type system.", 2989 "type [<sub-command-options>]") { 2990 LoadSubCommand("category", 2991 CommandObjectSP(new CommandObjectTypeCategory(interpreter))); 2992 LoadSubCommand("filter", 2993 CommandObjectSP(new CommandObjectTypeFilter(interpreter))); 2994 LoadSubCommand("format", 2995 CommandObjectSP(new CommandObjectTypeFormat(interpreter))); 2996 LoadSubCommand("summary", 2997 CommandObjectSP(new CommandObjectTypeSummary(interpreter))); 2998 LoadSubCommand("synthetic", 2999 CommandObjectSP(new CommandObjectTypeSynth(interpreter))); 3000 LoadSubCommand("lookup", 3001 CommandObjectSP(new CommandObjectTypeLookup(interpreter))); 3002 } 3003 3004 CommandObjectType::~CommandObjectType() = default; 3005