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