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/CommandOptionArgumentTable.h" 19 #include "lldb/Interpreter/CommandReturnObject.h" 20 #include "lldb/Interpreter/OptionArgParser.h" 21 #include "lldb/Interpreter/OptionGroupFormat.h" 22 #include "lldb/Interpreter/OptionValueBoolean.h" 23 #include "lldb/Interpreter/OptionValueLanguage.h" 24 #include "lldb/Interpreter/OptionValueString.h" 25 #include "lldb/Interpreter/Options.h" 26 #include "lldb/Symbol/Symbol.h" 27 #include "lldb/Target/Language.h" 28 #include "lldb/Target/StackFrame.h" 29 #include "lldb/Target/Target.h" 30 #include "lldb/Target/Thread.h" 31 #include "lldb/Utility/ConstString.h" 32 #include "lldb/Utility/RegularExpression.h" 33 #include "lldb/Utility/StringList.h" 34 35 #include "llvm/ADT/STLExtras.h" 36 37 #include <algorithm> 38 #include <functional> 39 #include <memory> 40 41 #define CHECK_FORMATTER_KIND_MASK(VAL) \ 42 ((m_formatter_kind_mask & (VAL)) == (VAL)) 43 44 using namespace lldb; 45 using namespace lldb_private; 46 47 class ScriptAddOptions { 48 public: 49 TypeSummaryImpl::Flags m_flags; 50 StringList m_target_types; 51 bool m_regex; 52 ConstString m_name; 53 std::string m_category; 54 55 ScriptAddOptions(const TypeSummaryImpl::Flags &flags, bool regx, 56 ConstString name, std::string catg) 57 : m_flags(flags), m_regex(regx), m_name(name), m_category(catg) {} 58 59 typedef std::shared_ptr<ScriptAddOptions> SharedPointer; 60 }; 61 62 class SynthAddOptions { 63 public: 64 bool m_skip_pointers; 65 bool m_skip_references; 66 bool m_cascade; 67 bool m_regex; 68 StringList m_target_types; 69 std::string m_category; 70 71 SynthAddOptions(bool sptr, bool sref, bool casc, bool regx, std::string catg) 72 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc), 73 m_regex(regx), m_category(catg) {} 74 75 typedef std::shared_ptr<SynthAddOptions> SharedPointer; 76 }; 77 78 static bool WarnOnPotentialUnquotedUnsignedType(Args &command, 79 CommandReturnObject &result) { 80 if (command.empty()) 81 return false; 82 83 for (auto entry : llvm::enumerate(command.entries().drop_back())) { 84 if (entry.value().ref() != "unsigned") 85 continue; 86 auto next = command.entries()[entry.index() + 1].ref(); 87 if (next == "int" || next == "short" || next == "char" || next == "long") { 88 result.AppendWarningWithFormat( 89 "unsigned %s being treated as two types. if you meant the combined " 90 "type " 91 "name use quotes, as in \"unsigned %s\"\n", 92 next.str().c_str(), next.str().c_str()); 93 return true; 94 } 95 } 96 return false; 97 } 98 99 #define LLDB_OPTIONS_type_summary_add 100 #include "CommandOptions.inc" 101 102 class CommandObjectTypeSummaryAdd : public CommandObjectParsed, 103 public IOHandlerDelegateMultiline { 104 private: 105 class CommandOptions : public Options { 106 public: 107 CommandOptions(CommandInterpreter &interpreter) {} 108 109 ~CommandOptions() override = default; 110 111 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 112 ExecutionContext *execution_context) override; 113 114 void OptionParsingStarting(ExecutionContext *execution_context) override; 115 116 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 117 return llvm::makeArrayRef(g_type_summary_add_options); 118 } 119 120 // Instance variables to hold the values for command options. 121 122 TypeSummaryImpl::Flags m_flags; 123 bool m_regex; 124 std::string m_format_string; 125 ConstString m_name; 126 std::string m_python_script; 127 std::string m_python_function; 128 bool m_is_add_script; 129 std::string m_category; 130 }; 131 132 CommandOptions m_options; 133 134 Options *GetOptions() override { return &m_options; } 135 136 bool Execute_ScriptSummary(Args &command, CommandReturnObject &result); 137 138 bool Execute_StringSummary(Args &command, CommandReturnObject &result); 139 140 public: 141 enum SummaryFormatType { eRegularSummary, eRegexSummary, eNamedSummary }; 142 143 CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter); 144 145 ~CommandObjectTypeSummaryAdd() override = default; 146 147 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 148 static const char *g_summary_addreader_instructions = 149 "Enter your Python command(s). Type 'DONE' to end.\n" 150 "def function (valobj,internal_dict):\n" 151 " \"\"\"valobj: an SBValue which you want to provide a summary " 152 "for\n" 153 " internal_dict: an LLDB support object not to be used\"\"\"\n"; 154 155 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 156 if (output_sp && interactive) { 157 output_sp->PutCString(g_summary_addreader_instructions); 158 output_sp->Flush(); 159 } 160 } 161 162 void IOHandlerInputComplete(IOHandler &io_handler, 163 std::string &data) override { 164 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); 165 166 #if LLDB_ENABLE_PYTHON 167 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 168 if (interpreter) { 169 StringList lines; 170 lines.SplitIntoLines(data); 171 if (lines.GetSize() > 0) { 172 ScriptAddOptions *options_ptr = 173 ((ScriptAddOptions *)io_handler.GetUserData()); 174 if (options_ptr) { 175 ScriptAddOptions::SharedPointer options( 176 options_ptr); // this will ensure that we get rid of the pointer 177 // when going out of scope 178 179 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 180 if (interpreter) { 181 std::string funct_name_str; 182 if (interpreter->GenerateTypeScriptFunction(lines, 183 funct_name_str)) { 184 if (funct_name_str.empty()) { 185 error_sp->Printf("unable to obtain a valid function name from " 186 "the script interpreter.\n"); 187 error_sp->Flush(); 188 } else { 189 // now I have a valid function name, let's add this as script 190 // for every type in the list 191 192 TypeSummaryImplSP script_format; 193 script_format = std::make_shared<ScriptSummaryFormat>( 194 options->m_flags, funct_name_str.c_str(), 195 lines.CopyList(" ").c_str()); 196 197 Status error; 198 199 for (const std::string &type_name : options->m_target_types) { 200 CommandObjectTypeSummaryAdd::AddSummary( 201 ConstString(type_name), script_format, 202 (options->m_regex 203 ? CommandObjectTypeSummaryAdd::eRegexSummary 204 : CommandObjectTypeSummaryAdd::eRegularSummary), 205 options->m_category, &error); 206 if (error.Fail()) { 207 error_sp->Printf("error: %s", error.AsCString()); 208 error_sp->Flush(); 209 } 210 } 211 212 if (options->m_name) { 213 CommandObjectTypeSummaryAdd::AddSummary( 214 options->m_name, script_format, 215 CommandObjectTypeSummaryAdd::eNamedSummary, 216 options->m_category, &error); 217 if (error.Fail()) { 218 CommandObjectTypeSummaryAdd::AddSummary( 219 options->m_name, script_format, 220 CommandObjectTypeSummaryAdd::eNamedSummary, 221 options->m_category, &error); 222 if (error.Fail()) { 223 error_sp->Printf("error: %s", error.AsCString()); 224 error_sp->Flush(); 225 } 226 } else { 227 error_sp->Printf("error: %s", error.AsCString()); 228 error_sp->Flush(); 229 } 230 } else { 231 if (error.AsCString()) { 232 error_sp->Printf("error: %s", error.AsCString()); 233 error_sp->Flush(); 234 } 235 } 236 } 237 } else { 238 error_sp->Printf("error: unable to generate a function.\n"); 239 error_sp->Flush(); 240 } 241 } else { 242 error_sp->Printf("error: no script interpreter.\n"); 243 error_sp->Flush(); 244 } 245 } else { 246 error_sp->Printf("error: internal synchronization information " 247 "missing or invalid.\n"); 248 error_sp->Flush(); 249 } 250 } else { 251 error_sp->Printf("error: empty function, didn't add python command.\n"); 252 error_sp->Flush(); 253 } 254 } else { 255 error_sp->Printf( 256 "error: script interpreter missing, didn't add python command.\n"); 257 error_sp->Flush(); 258 } 259 #endif 260 io_handler.SetIsDone(true); 261 } 262 263 static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, 264 SummaryFormatType type, std::string category, 265 Status *error = nullptr); 266 267 protected: 268 bool DoExecute(Args &command, CommandReturnObject &result) override; 269 }; 270 271 static const char *g_synth_addreader_instructions = 272 "Enter your Python command(s). Type 'DONE' to end.\n" 273 "You must define a Python class with these methods:\n" 274 " def __init__(self, valobj, internal_dict):\n" 275 " def num_children(self):\n" 276 " def get_child_at_index(self, index):\n" 277 " def get_child_index(self, name):\n" 278 " def update(self):\n" 279 " '''Optional'''\n" 280 "class synthProvider:\n"; 281 282 #define LLDB_OPTIONS_type_synth_add 283 #include "CommandOptions.inc" 284 285 class CommandObjectTypeSynthAdd : public CommandObjectParsed, 286 public IOHandlerDelegateMultiline { 287 private: 288 class CommandOptions : public Options { 289 public: 290 CommandOptions() = default; 291 292 ~CommandOptions() override = default; 293 294 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 295 ExecutionContext *execution_context) override { 296 Status error; 297 const int short_option = m_getopt_table[option_idx].val; 298 bool success; 299 300 switch (short_option) { 301 case 'C': 302 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success); 303 if (!success) 304 error.SetErrorStringWithFormat("invalid value for cascade: %s", 305 option_arg.str().c_str()); 306 break; 307 case 'P': 308 handwrite_python = true; 309 break; 310 case 'l': 311 m_class_name = std::string(option_arg); 312 is_class_based = true; 313 break; 314 case 'p': 315 m_skip_pointers = true; 316 break; 317 case 'r': 318 m_skip_references = true; 319 break; 320 case 'w': 321 m_category = std::string(option_arg); 322 break; 323 case 'x': 324 m_regex = true; 325 break; 326 default: 327 llvm_unreachable("Unimplemented option"); 328 } 329 330 return error; 331 } 332 333 void OptionParsingStarting(ExecutionContext *execution_context) override { 334 m_cascade = true; 335 m_class_name = ""; 336 m_skip_pointers = false; 337 m_skip_references = false; 338 m_category = "default"; 339 is_class_based = false; 340 handwrite_python = false; 341 m_regex = false; 342 } 343 344 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 345 return llvm::makeArrayRef(g_type_synth_add_options); 346 } 347 348 // Instance variables to hold the values for command options. 349 350 bool m_cascade; 351 bool m_skip_references; 352 bool m_skip_pointers; 353 std::string m_class_name; 354 bool m_input_python; 355 std::string m_category; 356 bool is_class_based; 357 bool handwrite_python; 358 bool m_regex; 359 }; 360 361 CommandOptions m_options; 362 363 Options *GetOptions() override { return &m_options; } 364 365 bool Execute_HandwritePython(Args &command, CommandReturnObject &result); 366 367 bool Execute_PythonClass(Args &command, CommandReturnObject &result); 368 369 protected: 370 bool DoExecute(Args &command, CommandReturnObject &result) override { 371 WarnOnPotentialUnquotedUnsignedType(command, result); 372 373 if (m_options.handwrite_python) 374 return Execute_HandwritePython(command, result); 375 else if (m_options.is_class_based) 376 return Execute_PythonClass(command, result); 377 else { 378 result.AppendError("must either provide a children list, a Python class " 379 "name, or use -P and type a Python class " 380 "line-by-line"); 381 return false; 382 } 383 } 384 385 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 386 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 387 if (output_sp && interactive) { 388 output_sp->PutCString(g_synth_addreader_instructions); 389 output_sp->Flush(); 390 } 391 } 392 393 void IOHandlerInputComplete(IOHandler &io_handler, 394 std::string &data) override { 395 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); 396 397 #if LLDB_ENABLE_PYTHON 398 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 399 if (interpreter) { 400 StringList lines; 401 lines.SplitIntoLines(data); 402 if (lines.GetSize() > 0) { 403 SynthAddOptions *options_ptr = 404 ((SynthAddOptions *)io_handler.GetUserData()); 405 if (options_ptr) { 406 SynthAddOptions::SharedPointer options( 407 options_ptr); // this will ensure that we get rid of the pointer 408 // when going out of scope 409 410 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 411 if (interpreter) { 412 std::string class_name_str; 413 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) { 414 if (class_name_str.empty()) { 415 error_sp->Printf( 416 "error: unable to obtain a proper name for the class.\n"); 417 error_sp->Flush(); 418 } else { 419 // everything should be fine now, let's add the synth provider 420 // class 421 422 SyntheticChildrenSP synth_provider; 423 synth_provider = std::make_shared<ScriptedSyntheticChildren>( 424 SyntheticChildren::Flags() 425 .SetCascades(options->m_cascade) 426 .SetSkipPointers(options->m_skip_pointers) 427 .SetSkipReferences(options->m_skip_references), 428 class_name_str.c_str()); 429 430 lldb::TypeCategoryImplSP category; 431 DataVisualization::Categories::GetCategory( 432 ConstString(options->m_category.c_str()), category); 433 434 Status error; 435 436 for (const std::string &type_name : options->m_target_types) { 437 if (!type_name.empty()) { 438 if (!CommandObjectTypeSynthAdd::AddSynth( 439 ConstString(type_name), synth_provider, 440 options->m_regex 441 ? CommandObjectTypeSynthAdd::eRegexSynth 442 : CommandObjectTypeSynthAdd::eRegularSynth, 443 options->m_category, &error)) { 444 error_sp->Printf("error: %s\n", error.AsCString()); 445 error_sp->Flush(); 446 break; 447 } 448 } else { 449 error_sp->Printf("error: invalid type name.\n"); 450 error_sp->Flush(); 451 break; 452 } 453 } 454 } 455 } else { 456 error_sp->Printf("error: unable to generate a class.\n"); 457 error_sp->Flush(); 458 } 459 } else { 460 error_sp->Printf("error: no script interpreter.\n"); 461 error_sp->Flush(); 462 } 463 } else { 464 error_sp->Printf("error: internal synchronization data missing.\n"); 465 error_sp->Flush(); 466 } 467 } else { 468 error_sp->Printf("error: empty function, didn't add python command.\n"); 469 error_sp->Flush(); 470 } 471 } else { 472 error_sp->Printf( 473 "error: script interpreter missing, didn't add python command.\n"); 474 error_sp->Flush(); 475 } 476 477 #endif 478 io_handler.SetIsDone(true); 479 } 480 481 public: 482 enum SynthFormatType { eRegularSynth, eRegexSynth }; 483 484 CommandObjectTypeSynthAdd(CommandInterpreter &interpreter); 485 486 ~CommandObjectTypeSynthAdd() override = default; 487 488 static bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry, 489 SynthFormatType type, std::string category_name, 490 Status *error); 491 }; 492 493 // CommandObjectTypeFormatAdd 494 495 #define LLDB_OPTIONS_type_format_add 496 #include "CommandOptions.inc" 497 498 class CommandObjectTypeFormatAdd : public CommandObjectParsed { 499 private: 500 class CommandOptions : public OptionGroup { 501 public: 502 CommandOptions() = default; 503 504 ~CommandOptions() override = default; 505 506 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 507 return llvm::makeArrayRef(g_type_format_add_options); 508 } 509 510 void OptionParsingStarting(ExecutionContext *execution_context) override { 511 m_cascade = true; 512 m_skip_pointers = false; 513 m_skip_references = false; 514 m_regex = false; 515 m_category.assign("default"); 516 m_custom_type_name.clear(); 517 } 518 519 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 520 ExecutionContext *execution_context) override { 521 Status error; 522 const int short_option = 523 g_type_format_add_options[option_idx].short_option; 524 bool success; 525 526 switch (short_option) { 527 case 'C': 528 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success); 529 if (!success) 530 error.SetErrorStringWithFormat("invalid value for cascade: %s", 531 option_value.str().c_str()); 532 break; 533 case 'p': 534 m_skip_pointers = true; 535 break; 536 case 'w': 537 m_category.assign(std::string(option_value)); 538 break; 539 case 'r': 540 m_skip_references = true; 541 break; 542 case 'x': 543 m_regex = true; 544 break; 545 case 't': 546 m_custom_type_name.assign(std::string(option_value)); 547 break; 548 default: 549 llvm_unreachable("Unimplemented option"); 550 } 551 552 return error; 553 } 554 555 // Instance variables to hold the values for command options. 556 557 bool m_cascade; 558 bool m_skip_references; 559 bool m_skip_pointers; 560 bool m_regex; 561 std::string m_category; 562 std::string m_custom_type_name; 563 }; 564 565 OptionGroupOptions m_option_group; 566 OptionGroupFormat m_format_options; 567 CommandOptions m_command_options; 568 569 Options *GetOptions() override { return &m_option_group; } 570 571 public: 572 CommandObjectTypeFormatAdd(CommandInterpreter &interpreter) 573 : CommandObjectParsed(interpreter, "type format add", 574 "Add a new formatting style for a type.", nullptr), 575 m_format_options(eFormatInvalid) { 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() = default; 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), 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() = default; 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), 918 m_formatter_kind_mask(formatter_kind_mask) { 919 CommandArgumentData category_arg{eArgTypeName, eArgRepeatOptional}; 920 m_arguments.push_back({category_arg}); 921 } 922 923 ~CommandObjectTypeFormatterClear() override = default; 924 925 protected: 926 virtual void FormatterSpecificDeletion() {} 927 928 bool DoExecute(Args &command, CommandReturnObject &result) override { 929 if (m_options.m_delete_all) { 930 DataVisualization::Categories::ForEach( 931 [this](const TypeCategoryImplSP &category_sp) -> bool { 932 category_sp->Clear(m_formatter_kind_mask); 933 return true; 934 }); 935 } else { 936 lldb::TypeCategoryImplSP category; 937 if (command.GetArgumentCount() > 0) { 938 const char *cat_name = command.GetArgumentAtIndex(0); 939 ConstString cat_nameCS(cat_name); 940 DataVisualization::Categories::GetCategory(cat_nameCS, category); 941 } else { 942 DataVisualization::Categories::GetCategory(ConstString(nullptr), 943 category); 944 } 945 category->Clear(m_formatter_kind_mask); 946 } 947 948 FormatterSpecificDeletion(); 949 950 result.SetStatus(eReturnStatusSuccessFinishResult); 951 return result.Succeeded(); 952 } 953 }; 954 955 // CommandObjectTypeFormatDelete 956 957 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete { 958 public: 959 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter) 960 : CommandObjectTypeFormatterDelete( 961 interpreter, 962 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 963 "type format delete", 964 "Delete an existing formatting style for a type.") {} 965 966 ~CommandObjectTypeFormatDelete() override = default; 967 }; 968 969 // CommandObjectTypeFormatClear 970 971 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear { 972 public: 973 CommandObjectTypeFormatClear(CommandInterpreter &interpreter) 974 : CommandObjectTypeFormatterClear( 975 interpreter, 976 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 977 "type format clear", "Delete all existing format styles.") {} 978 }; 979 980 #define LLDB_OPTIONS_type_formatter_list 981 #include "CommandOptions.inc" 982 983 template <typename FormatterType> 984 class CommandObjectTypeFormatterList : public CommandObjectParsed { 985 typedef typename FormatterType::SharedPointer FormatterSharedPointer; 986 987 class CommandOptions : public Options { 988 public: 989 CommandOptions() 990 : Options(), m_category_regex("", ""), 991 m_category_language(lldb::eLanguageTypeUnknown, 992 lldb::eLanguageTypeUnknown) {} 993 994 ~CommandOptions() override = default; 995 996 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 997 ExecutionContext *execution_context) override { 998 Status error; 999 const int short_option = m_getopt_table[option_idx].val; 1000 switch (short_option) { 1001 case 'w': 1002 m_category_regex.SetCurrentValue(option_arg); 1003 m_category_regex.SetOptionWasSet(); 1004 break; 1005 case 'l': 1006 error = m_category_language.SetValueFromString(option_arg); 1007 if (error.Success()) 1008 m_category_language.SetOptionWasSet(); 1009 break; 1010 default: 1011 llvm_unreachable("Unimplemented option"); 1012 } 1013 1014 return error; 1015 } 1016 1017 void OptionParsingStarting(ExecutionContext *execution_context) override { 1018 m_category_regex.Clear(); 1019 m_category_language.Clear(); 1020 } 1021 1022 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1023 return llvm::makeArrayRef(g_type_formatter_list_options); 1024 } 1025 1026 // Instance variables to hold the values for command options. 1027 1028 OptionValueString m_category_regex; 1029 OptionValueLanguage m_category_language; 1030 }; 1031 1032 CommandOptions m_options; 1033 1034 Options *GetOptions() override { return &m_options; } 1035 1036 public: 1037 CommandObjectTypeFormatterList(CommandInterpreter &interpreter, 1038 const char *name, const char *help) 1039 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() { 1040 CommandArgumentEntry type_arg; 1041 CommandArgumentData type_style_arg; 1042 1043 type_style_arg.arg_type = eArgTypeName; 1044 type_style_arg.arg_repetition = eArgRepeatOptional; 1045 1046 type_arg.push_back(type_style_arg); 1047 1048 m_arguments.push_back(type_arg); 1049 } 1050 1051 ~CommandObjectTypeFormatterList() override = default; 1052 1053 protected: 1054 virtual bool FormatterSpecificList(CommandReturnObject &result) { 1055 return false; 1056 } 1057 1058 bool DoExecute(Args &command, CommandReturnObject &result) override { 1059 const size_t argc = command.GetArgumentCount(); 1060 1061 std::unique_ptr<RegularExpression> category_regex; 1062 std::unique_ptr<RegularExpression> formatter_regex; 1063 1064 if (m_options.m_category_regex.OptionWasSet()) { 1065 category_regex = std::make_unique<RegularExpression>( 1066 m_options.m_category_regex.GetCurrentValueAsRef()); 1067 if (!category_regex->IsValid()) { 1068 result.AppendErrorWithFormat( 1069 "syntax error in category regular expression '%s'", 1070 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str()); 1071 return false; 1072 } 1073 } 1074 1075 if (argc == 1) { 1076 const char *arg = command.GetArgumentAtIndex(0); 1077 formatter_regex = std::make_unique<RegularExpression>(arg); 1078 if (!formatter_regex->IsValid()) { 1079 result.AppendErrorWithFormat("syntax error in regular expression '%s'", 1080 arg); 1081 return false; 1082 } 1083 } 1084 1085 bool any_printed = false; 1086 1087 auto category_closure = 1088 [&result, &formatter_regex, 1089 &any_printed](const lldb::TypeCategoryImplSP &category) -> void { 1090 result.GetOutputStream().Printf( 1091 "-----------------------\nCategory: %s%s\n-----------------------\n", 1092 category->GetName(), category->IsEnabled() ? "" : " (disabled)"); 1093 1094 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; 1095 foreach 1096 .SetExact([&result, &formatter_regex, &any_printed]( 1097 const TypeMatcher &type_matcher, 1098 const FormatterSharedPointer &format_sp) -> bool { 1099 if (formatter_regex) { 1100 bool escape = true; 1101 if (type_matcher.CreatedBySameMatchString( 1102 ConstString(formatter_regex->GetText()))) { 1103 escape = false; 1104 } else if (formatter_regex->Execute( 1105 type_matcher.GetMatchString().GetStringRef())) { 1106 escape = false; 1107 } 1108 1109 if (escape) 1110 return true; 1111 } 1112 1113 any_printed = true; 1114 result.GetOutputStream().Printf( 1115 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1116 format_sp->GetDescription().c_str()); 1117 return true; 1118 }); 1119 1120 foreach 1121 .SetWithRegex([&result, &formatter_regex, &any_printed]( 1122 const TypeMatcher &type_matcher, 1123 const FormatterSharedPointer &format_sp) -> bool { 1124 if (formatter_regex) { 1125 bool escape = true; 1126 if (type_matcher.CreatedBySameMatchString( 1127 ConstString(formatter_regex->GetText()))) { 1128 escape = false; 1129 } else if (formatter_regex->Execute( 1130 type_matcher.GetMatchString().GetStringRef())) { 1131 escape = false; 1132 } 1133 1134 if (escape) 1135 return true; 1136 } 1137 1138 any_printed = true; 1139 result.GetOutputStream().Printf( 1140 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1141 format_sp->GetDescription().c_str()); 1142 return true; 1143 }); 1144 1145 category->ForEach(foreach); 1146 }; 1147 1148 if (m_options.m_category_language.OptionWasSet()) { 1149 lldb::TypeCategoryImplSP category_sp; 1150 DataVisualization::Categories::GetCategory( 1151 m_options.m_category_language.GetCurrentValue(), category_sp); 1152 if (category_sp) 1153 category_closure(category_sp); 1154 } else { 1155 DataVisualization::Categories::ForEach( 1156 [&category_regex, &category_closure]( 1157 const lldb::TypeCategoryImplSP &category) -> bool { 1158 if (category_regex) { 1159 bool escape = true; 1160 if (category->GetName() == category_regex->GetText()) { 1161 escape = false; 1162 } else if (category_regex->Execute(category->GetName())) { 1163 escape = false; 1164 } 1165 1166 if (escape) 1167 return true; 1168 } 1169 1170 category_closure(category); 1171 1172 return true; 1173 }); 1174 1175 any_printed = FormatterSpecificList(result) | any_printed; 1176 } 1177 1178 if (any_printed) 1179 result.SetStatus(eReturnStatusSuccessFinishResult); 1180 else { 1181 result.GetOutputStream().PutCString("no matching results found.\n"); 1182 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1183 } 1184 return result.Succeeded(); 1185 } 1186 }; 1187 1188 // CommandObjectTypeFormatList 1189 1190 class CommandObjectTypeFormatList 1191 : public CommandObjectTypeFormatterList<TypeFormatImpl> { 1192 public: 1193 CommandObjectTypeFormatList(CommandInterpreter &interpreter) 1194 : CommandObjectTypeFormatterList(interpreter, "type format list", 1195 "Show a list of current formats.") {} 1196 }; 1197 1198 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( 1199 uint32_t option_idx, llvm::StringRef option_arg, 1200 ExecutionContext *execution_context) { 1201 Status error; 1202 const int short_option = m_getopt_table[option_idx].val; 1203 bool success; 1204 1205 switch (short_option) { 1206 case 'C': 1207 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success)); 1208 if (!success) 1209 error.SetErrorStringWithFormat("invalid value for cascade: %s", 1210 option_arg.str().c_str()); 1211 break; 1212 case 'e': 1213 m_flags.SetDontShowChildren(false); 1214 break; 1215 case 'h': 1216 m_flags.SetHideEmptyAggregates(true); 1217 break; 1218 case 'v': 1219 m_flags.SetDontShowValue(true); 1220 break; 1221 case 'c': 1222 m_flags.SetShowMembersOneLiner(true); 1223 break; 1224 case 's': 1225 m_format_string = std::string(option_arg); 1226 break; 1227 case 'p': 1228 m_flags.SetSkipPointers(true); 1229 break; 1230 case 'r': 1231 m_flags.SetSkipReferences(true); 1232 break; 1233 case 'x': 1234 m_regex = true; 1235 break; 1236 case 'n': 1237 m_name.SetString(option_arg); 1238 break; 1239 case 'o': 1240 m_python_script = std::string(option_arg); 1241 m_is_add_script = true; 1242 break; 1243 case 'F': 1244 m_python_function = std::string(option_arg); 1245 m_is_add_script = true; 1246 break; 1247 case 'P': 1248 m_is_add_script = true; 1249 break; 1250 case 'w': 1251 m_category = std::string(option_arg); 1252 break; 1253 case 'O': 1254 m_flags.SetHideItemNames(true); 1255 break; 1256 default: 1257 llvm_unreachable("Unimplemented option"); 1258 } 1259 1260 return error; 1261 } 1262 1263 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting( 1264 ExecutionContext *execution_context) { 1265 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 1266 m_flags.SetShowMembersOneLiner(false) 1267 .SetSkipPointers(false) 1268 .SetSkipReferences(false) 1269 .SetHideItemNames(false); 1270 1271 m_regex = false; 1272 m_name.Clear(); 1273 m_python_script = ""; 1274 m_python_function = ""; 1275 m_format_string = ""; 1276 m_is_add_script = false; 1277 m_category = "default"; 1278 } 1279 1280 #if LLDB_ENABLE_PYTHON 1281 1282 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( 1283 Args &command, CommandReturnObject &result) { 1284 const size_t argc = command.GetArgumentCount(); 1285 1286 if (argc < 1 && !m_options.m_name) { 1287 result.AppendErrorWithFormat("%s takes one or more args.\n", 1288 m_cmd_name.c_str()); 1289 return false; 1290 } 1291 1292 TypeSummaryImplSP script_format; 1293 1294 if (!m_options.m_python_function 1295 .empty()) // we have a Python function ready to use 1296 { 1297 const char *funct_name = m_options.m_python_function.c_str(); 1298 if (!funct_name || !funct_name[0]) { 1299 result.AppendError("function name empty.\n"); 1300 return false; 1301 } 1302 1303 std::string code = 1304 (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1305 1306 script_format = std::make_shared<ScriptSummaryFormat>( 1307 m_options.m_flags, funct_name, code.c_str()); 1308 1309 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1310 1311 if (interpreter && !interpreter->CheckObjectExists(funct_name)) 1312 result.AppendWarningWithFormat( 1313 "The provided function \"%s\" does not exist - " 1314 "please define it before attempting to use this summary.\n", 1315 funct_name); 1316 } else if (!m_options.m_python_script 1317 .empty()) // we have a quick 1-line script, just use it 1318 { 1319 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1320 if (!interpreter) { 1321 result.AppendError("script interpreter missing - unable to generate " 1322 "function wrapper.\n"); 1323 return false; 1324 } 1325 StringList funct_sl; 1326 funct_sl << m_options.m_python_script.c_str(); 1327 std::string funct_name_str; 1328 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) { 1329 result.AppendError("unable to generate function wrapper.\n"); 1330 return false; 1331 } 1332 if (funct_name_str.empty()) { 1333 result.AppendError( 1334 "script interpreter failed to generate a valid function name.\n"); 1335 return false; 1336 } 1337 1338 std::string code = " " + m_options.m_python_script; 1339 1340 script_format = std::make_shared<ScriptSummaryFormat>( 1341 m_options.m_flags, funct_name_str.c_str(), code.c_str()); 1342 } else { 1343 // Use an IOHandler to grab Python code from the user 1344 auto options = std::make_unique<ScriptAddOptions>( 1345 m_options.m_flags, m_options.m_regex, m_options.m_name, 1346 m_options.m_category); 1347 1348 for (auto &entry : command.entries()) { 1349 if (entry.ref().empty()) { 1350 result.AppendError("empty typenames not allowed"); 1351 return false; 1352 } 1353 1354 options->m_target_types << std::string(entry.ref()); 1355 } 1356 1357 m_interpreter.GetPythonCommandsFromIOHandler( 1358 " ", // Prompt 1359 *this, // IOHandlerDelegate 1360 options.release()); // Baton for the "io_handler" that will be passed 1361 // back into our IOHandlerDelegate functions 1362 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1363 1364 return result.Succeeded(); 1365 } 1366 1367 // if I am here, script_format must point to something good, so I can add 1368 // that as a script summary to all interested parties 1369 1370 Status error; 1371 1372 for (auto &entry : command.entries()) { 1373 CommandObjectTypeSummaryAdd::AddSummary( 1374 ConstString(entry.ref()), script_format, 1375 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1376 m_options.m_category, &error); 1377 if (error.Fail()) { 1378 result.AppendError(error.AsCString()); 1379 return false; 1380 } 1381 } 1382 1383 if (m_options.m_name) { 1384 AddSummary(m_options.m_name, script_format, eNamedSummary, 1385 m_options.m_category, &error); 1386 if (error.Fail()) { 1387 result.AppendError(error.AsCString()); 1388 result.AppendError("added to types, but not given a name"); 1389 return false; 1390 } 1391 } 1392 1393 return result.Succeeded(); 1394 } 1395 1396 #endif 1397 1398 bool CommandObjectTypeSummaryAdd::Execute_StringSummary( 1399 Args &command, CommandReturnObject &result) { 1400 const size_t argc = command.GetArgumentCount(); 1401 1402 if (argc < 1 && !m_options.m_name) { 1403 result.AppendErrorWithFormat("%s takes one or more args.\n", 1404 m_cmd_name.c_str()); 1405 return false; 1406 } 1407 1408 if (!m_options.m_flags.GetShowMembersOneLiner() && 1409 m_options.m_format_string.empty()) { 1410 result.AppendError("empty summary strings not allowed"); 1411 return false; 1412 } 1413 1414 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner() 1415 ? "" 1416 : m_options.m_format_string.c_str()); 1417 1418 // ${var%S} is an endless recursion, prevent it 1419 if (strcmp(format_cstr, "${var%S}") == 0) { 1420 result.AppendError("recursive summary not allowed"); 1421 return false; 1422 } 1423 1424 std::unique_ptr<StringSummaryFormat> string_format( 1425 new StringSummaryFormat(m_options.m_flags, format_cstr)); 1426 if (!string_format) { 1427 result.AppendError("summary creation failed"); 1428 return false; 1429 } 1430 if (string_format->m_error.Fail()) { 1431 result.AppendErrorWithFormat("syntax error: %s", 1432 string_format->m_error.AsCString("<unknown>")); 1433 return false; 1434 } 1435 lldb::TypeSummaryImplSP entry(string_format.release()); 1436 1437 // now I have a valid format, let's add it to every type 1438 Status error; 1439 for (auto &arg_entry : command.entries()) { 1440 if (arg_entry.ref().empty()) { 1441 result.AppendError("empty typenames not allowed"); 1442 return false; 1443 } 1444 ConstString typeCS(arg_entry.ref()); 1445 1446 AddSummary(typeCS, entry, 1447 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1448 m_options.m_category, &error); 1449 1450 if (error.Fail()) { 1451 result.AppendError(error.AsCString()); 1452 return false; 1453 } 1454 } 1455 1456 if (m_options.m_name) { 1457 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, 1458 &error); 1459 if (error.Fail()) { 1460 result.AppendError(error.AsCString()); 1461 result.AppendError("added to types, but not given a name"); 1462 return false; 1463 } 1464 } 1465 1466 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1467 return result.Succeeded(); 1468 } 1469 1470 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd( 1471 CommandInterpreter &interpreter) 1472 : CommandObjectParsed(interpreter, "type summary add", 1473 "Add a new summary style for a type.", nullptr), 1474 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) { 1475 CommandArgumentEntry type_arg; 1476 CommandArgumentData type_style_arg; 1477 1478 type_style_arg.arg_type = eArgTypeName; 1479 type_style_arg.arg_repetition = eArgRepeatPlus; 1480 1481 type_arg.push_back(type_style_arg); 1482 1483 m_arguments.push_back(type_arg); 1484 1485 SetHelpLong( 1486 R"( 1487 The following examples of 'type summary add' refer to this code snippet for context: 1488 1489 struct JustADemo 1490 { 1491 int* ptr; 1492 float value; 1493 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {} 1494 }; 1495 JustADemo demo_instance(42, 3.14); 1496 1497 typedef JustADemo NewDemo; 1498 NewDemo new_demo_instance(42, 3.14); 1499 1500 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo 1501 1502 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42" 1503 1504 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo 1505 1506 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" 1507 1508 )" 1509 "Alternatively, you could define formatting for all pointers to integers and \ 1510 rely on that when formatting JustADemo to obtain the same result:" 1511 R"( 1512 1513 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" 1514 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo 1515 1516 )" 1517 "Type summaries are automatically applied to derived typedefs, so the examples \ 1518 above apply to both JustADemo and NewDemo. The cascade option can be used to \ 1519 suppress this behavior:" 1520 R"( 1521 1522 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no 1523 1524 The summary will now be used for values of JustADemo but not NewDemo. 1525 1526 )" 1527 "By default summaries are shown for pointers and references to values of the \ 1528 specified type. To suppress formatting for pointers use the -p option, or apply \ 1529 the corresponding -r option to suppress formatting for references:" 1530 R"( 1531 1532 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo 1533 1534 )" 1535 "One-line summaries including all fields in a type can be inferred without supplying an \ 1536 explicit summary string by passing the -c option:" 1537 R"( 1538 1539 (lldb) type summary add -c JustADemo 1540 (lldb) frame variable demo_instance 1541 (ptr=<address>, value=3.14) 1542 1543 )" 1544 "Type summaries normally suppress the nested display of individual fields. To \ 1545 supply a summary to supplement the default structure add the -e option:" 1546 R"( 1547 1548 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo 1549 1550 )" 1551 "Now when displaying JustADemo values the int* is displayed, followed by the \ 1552 standard LLDB sequence of children, one per line:" 1553 R"( 1554 1555 *ptr = 42 { 1556 ptr = <address> 1557 value = 3.14 1558 } 1559 1560 )" 1561 "You can also add summaries written in Python. These scripts use lldb public API to \ 1562 gather information from your variables and produce a meaningful summary. To start a \ 1563 multi-line script use the -P option. The function declaration will be displayed along with \ 1564 a comment describing the two arguments. End your script with the word 'DONE' on a line by \ 1565 itself:" 1566 R"( 1567 1568 (lldb) type summary add JustADemo -P 1569 def function (valobj,internal_dict): 1570 """valobj: an SBValue which you want to provide a summary for 1571 internal_dict: an LLDB support object not to be used""" 1572 value = valobj.GetChildMemberWithName('value'); 1573 return 'My value is ' + value.GetValue(); 1574 DONE 1575 1576 Alternatively, the -o option can be used when providing a simple one-line Python script: 1577 1578 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"); 1579 } 1580 1581 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command, 1582 CommandReturnObject &result) { 1583 WarnOnPotentialUnquotedUnsignedType(command, result); 1584 1585 if (m_options.m_is_add_script) { 1586 #if LLDB_ENABLE_PYTHON 1587 return Execute_ScriptSummary(command, result); 1588 #else 1589 result.AppendError("python is disabled"); 1590 return false; 1591 #endif 1592 } 1593 1594 return Execute_StringSummary(command, result); 1595 } 1596 1597 static bool FixArrayTypeNameWithRegex(ConstString &type_name) { 1598 llvm::StringRef type_name_ref(type_name.GetStringRef()); 1599 1600 if (type_name_ref.endswith("[]")) { 1601 std::string type_name_str(type_name.GetCString()); 1602 type_name_str.resize(type_name_str.length() - 2); 1603 if (type_name_str.back() != ' ') 1604 type_name_str.append(" ?\\[[0-9]+\\]"); 1605 else 1606 type_name_str.append("\\[[0-9]+\\]"); 1607 type_name.SetCString(type_name_str.c_str()); 1608 return true; 1609 } 1610 return false; 1611 } 1612 1613 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, 1614 TypeSummaryImplSP entry, 1615 SummaryFormatType type, 1616 std::string category_name, 1617 Status *error) { 1618 lldb::TypeCategoryImplSP category; 1619 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 1620 category); 1621 1622 if (type == eRegularSummary) { 1623 if (FixArrayTypeNameWithRegex(type_name)) 1624 type = eRegexSummary; 1625 } 1626 1627 if (type == eRegexSummary) { 1628 RegularExpression typeRX(type_name.GetStringRef()); 1629 if (!typeRX.IsValid()) { 1630 if (error) 1631 error->SetErrorString( 1632 "regex format error (maybe this is not really a regex?)"); 1633 return false; 1634 } 1635 1636 category->GetRegexTypeSummariesContainer()->Delete(type_name); 1637 category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry); 1638 1639 return true; 1640 } else if (type == eNamedSummary) { 1641 // system named summaries do not exist (yet?) 1642 DataVisualization::NamedSummaryFormats::Add(type_name, entry); 1643 return true; 1644 } else { 1645 category->GetTypeSummariesContainer()->Add(std::move(type_name), entry); 1646 return true; 1647 } 1648 } 1649 1650 // CommandObjectTypeSummaryDelete 1651 1652 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { 1653 public: 1654 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter) 1655 : CommandObjectTypeFormatterDelete( 1656 interpreter, 1657 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1658 "type summary delete", "Delete an existing summary for a type.") {} 1659 1660 ~CommandObjectTypeSummaryDelete() override = default; 1661 1662 protected: 1663 bool FormatterSpecificDeletion(ConstString typeCS) override { 1664 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1665 return false; 1666 return DataVisualization::NamedSummaryFormats::Delete(typeCS); 1667 } 1668 }; 1669 1670 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear { 1671 public: 1672 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter) 1673 : CommandObjectTypeFormatterClear( 1674 interpreter, 1675 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1676 "type summary clear", "Delete all existing summaries.") {} 1677 1678 protected: 1679 void FormatterSpecificDeletion() override { 1680 DataVisualization::NamedSummaryFormats::Clear(); 1681 } 1682 }; 1683 1684 // CommandObjectTypeSummaryList 1685 1686 class CommandObjectTypeSummaryList 1687 : public CommandObjectTypeFormatterList<TypeSummaryImpl> { 1688 public: 1689 CommandObjectTypeSummaryList(CommandInterpreter &interpreter) 1690 : CommandObjectTypeFormatterList(interpreter, "type summary list", 1691 "Show a list of current summaries.") {} 1692 1693 protected: 1694 bool FormatterSpecificList(CommandReturnObject &result) override { 1695 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) { 1696 result.GetOutputStream().Printf("Named summaries:\n"); 1697 DataVisualization::NamedSummaryFormats::ForEach( 1698 [&result](const TypeMatcher &type_matcher, 1699 const TypeSummaryImplSP &summary_sp) -> bool { 1700 result.GetOutputStream().Printf( 1701 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1702 summary_sp->GetDescription().c_str()); 1703 return true; 1704 }); 1705 return true; 1706 } 1707 return false; 1708 } 1709 }; 1710 1711 // CommandObjectTypeCategoryDefine 1712 #define LLDB_OPTIONS_type_category_define 1713 #include "CommandOptions.inc" 1714 1715 class CommandObjectTypeCategoryDefine : public CommandObjectParsed { 1716 class CommandOptions : public Options { 1717 public: 1718 CommandOptions() 1719 : m_define_enabled(false, false), 1720 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {} 1721 1722 ~CommandOptions() override = default; 1723 1724 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1725 ExecutionContext *execution_context) override { 1726 Status error; 1727 const int short_option = m_getopt_table[option_idx].val; 1728 1729 switch (short_option) { 1730 case 'e': 1731 m_define_enabled.SetValueFromString(llvm::StringRef("true")); 1732 break; 1733 case 'l': 1734 error = m_cate_language.SetValueFromString(option_arg); 1735 break; 1736 default: 1737 llvm_unreachable("Unimplemented option"); 1738 } 1739 1740 return error; 1741 } 1742 1743 void OptionParsingStarting(ExecutionContext *execution_context) override { 1744 m_define_enabled.Clear(); 1745 m_cate_language.Clear(); 1746 } 1747 1748 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1749 return llvm::makeArrayRef(g_type_category_define_options); 1750 } 1751 1752 // Instance variables to hold the values for command options. 1753 1754 OptionValueBoolean m_define_enabled; 1755 OptionValueLanguage m_cate_language; 1756 }; 1757 1758 CommandOptions m_options; 1759 1760 Options *GetOptions() override { return &m_options; } 1761 1762 public: 1763 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter) 1764 : CommandObjectParsed(interpreter, "type category define", 1765 "Define a new category as a source of formatters.", 1766 nullptr) { 1767 CommandArgumentEntry type_arg; 1768 CommandArgumentData type_style_arg; 1769 1770 type_style_arg.arg_type = eArgTypeName; 1771 type_style_arg.arg_repetition = eArgRepeatPlus; 1772 1773 type_arg.push_back(type_style_arg); 1774 1775 m_arguments.push_back(type_arg); 1776 } 1777 1778 ~CommandObjectTypeCategoryDefine() override = default; 1779 1780 void 1781 HandleArgumentCompletion(CompletionRequest &request, 1782 OptionElementVector &opt_element_vector) override { 1783 CommandCompletions::InvokeCommonCompletionCallbacks( 1784 GetCommandInterpreter(), 1785 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1786 } 1787 1788 protected: 1789 bool DoExecute(Args &command, CommandReturnObject &result) override { 1790 const size_t argc = command.GetArgumentCount(); 1791 1792 if (argc < 1) { 1793 result.AppendErrorWithFormat("%s takes 1 or more args.\n", 1794 m_cmd_name.c_str()); 1795 return false; 1796 } 1797 1798 for (auto &entry : command.entries()) { 1799 TypeCategoryImplSP category_sp; 1800 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), 1801 category_sp) && 1802 category_sp) { 1803 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 1804 if (m_options.m_define_enabled.GetCurrentValue()) 1805 DataVisualization::Categories::Enable(category_sp, 1806 TypeCategoryMap::Default); 1807 } 1808 } 1809 1810 result.SetStatus(eReturnStatusSuccessFinishResult); 1811 return result.Succeeded(); 1812 } 1813 }; 1814 1815 // CommandObjectTypeCategoryEnable 1816 #define LLDB_OPTIONS_type_category_enable 1817 #include "CommandOptions.inc" 1818 1819 class CommandObjectTypeCategoryEnable : public CommandObjectParsed { 1820 class CommandOptions : public Options { 1821 public: 1822 CommandOptions() = default; 1823 1824 ~CommandOptions() override = default; 1825 1826 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1827 ExecutionContext *execution_context) override { 1828 Status error; 1829 const int short_option = m_getopt_table[option_idx].val; 1830 1831 switch (short_option) { 1832 case 'l': 1833 if (!option_arg.empty()) { 1834 m_language = Language::GetLanguageTypeFromString(option_arg); 1835 if (m_language == lldb::eLanguageTypeUnknown) 1836 error.SetErrorStringWithFormat("unrecognized language '%s'", 1837 option_arg.str().c_str()); 1838 } 1839 break; 1840 default: 1841 llvm_unreachable("Unimplemented option"); 1842 } 1843 1844 return error; 1845 } 1846 1847 void OptionParsingStarting(ExecutionContext *execution_context) override { 1848 m_language = lldb::eLanguageTypeUnknown; 1849 } 1850 1851 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1852 return llvm::makeArrayRef(g_type_category_enable_options); 1853 } 1854 1855 // Instance variables to hold the values for command options. 1856 1857 lldb::LanguageType m_language; 1858 }; 1859 1860 CommandOptions m_options; 1861 1862 Options *GetOptions() override { return &m_options; } 1863 1864 public: 1865 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter) 1866 : CommandObjectParsed(interpreter, "type category enable", 1867 "Enable a category as a source of formatters.", 1868 nullptr) { 1869 CommandArgumentEntry type_arg; 1870 CommandArgumentData type_style_arg; 1871 1872 type_style_arg.arg_type = eArgTypeName; 1873 type_style_arg.arg_repetition = eArgRepeatPlus; 1874 1875 type_arg.push_back(type_style_arg); 1876 1877 m_arguments.push_back(type_arg); 1878 } 1879 1880 ~CommandObjectTypeCategoryEnable() override = default; 1881 1882 void 1883 HandleArgumentCompletion(CompletionRequest &request, 1884 OptionElementVector &opt_element_vector) override { 1885 CommandCompletions::InvokeCommonCompletionCallbacks( 1886 GetCommandInterpreter(), 1887 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1888 } 1889 1890 protected: 1891 bool DoExecute(Args &command, CommandReturnObject &result) override { 1892 const size_t argc = command.GetArgumentCount(); 1893 1894 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 1895 result.AppendErrorWithFormat("%s takes arguments and/or a language", 1896 m_cmd_name.c_str()); 1897 return false; 1898 } 1899 1900 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 1901 DataVisualization::Categories::EnableStar(); 1902 } else if (argc > 0) { 1903 for (int i = argc - 1; i >= 0; i--) { 1904 const char *typeA = command.GetArgumentAtIndex(i); 1905 ConstString typeCS(typeA); 1906 1907 if (!typeCS) { 1908 result.AppendError("empty category name not allowed"); 1909 return false; 1910 } 1911 DataVisualization::Categories::Enable(typeCS); 1912 lldb::TypeCategoryImplSP cate; 1913 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) { 1914 if (cate->GetCount() == 0) { 1915 result.AppendWarning("empty category enabled (typo?)"); 1916 } 1917 } 1918 } 1919 } 1920 1921 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1922 DataVisualization::Categories::Enable(m_options.m_language); 1923 1924 result.SetStatus(eReturnStatusSuccessFinishResult); 1925 return result.Succeeded(); 1926 } 1927 }; 1928 1929 // CommandObjectTypeCategoryDelete 1930 1931 class CommandObjectTypeCategoryDelete : public CommandObjectParsed { 1932 public: 1933 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter) 1934 : CommandObjectParsed(interpreter, "type category delete", 1935 "Delete a category and all associated formatters.", 1936 nullptr) { 1937 CommandArgumentEntry type_arg; 1938 CommandArgumentData type_style_arg; 1939 1940 type_style_arg.arg_type = eArgTypeName; 1941 type_style_arg.arg_repetition = eArgRepeatPlus; 1942 1943 type_arg.push_back(type_style_arg); 1944 1945 m_arguments.push_back(type_arg); 1946 } 1947 1948 ~CommandObjectTypeCategoryDelete() override = default; 1949 1950 void 1951 HandleArgumentCompletion(CompletionRequest &request, 1952 OptionElementVector &opt_element_vector) override { 1953 CommandCompletions::InvokeCommonCompletionCallbacks( 1954 GetCommandInterpreter(), 1955 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1956 } 1957 1958 protected: 1959 bool DoExecute(Args &command, CommandReturnObject &result) override { 1960 const size_t argc = command.GetArgumentCount(); 1961 1962 if (argc < 1) { 1963 result.AppendErrorWithFormat("%s takes 1 or more arg.\n", 1964 m_cmd_name.c_str()); 1965 return false; 1966 } 1967 1968 bool success = true; 1969 1970 // the order is not relevant here 1971 for (int i = argc - 1; i >= 0; i--) { 1972 const char *typeA = command.GetArgumentAtIndex(i); 1973 ConstString typeCS(typeA); 1974 1975 if (!typeCS) { 1976 result.AppendError("empty category name not allowed"); 1977 return false; 1978 } 1979 if (!DataVisualization::Categories::Delete(typeCS)) 1980 success = false; // keep deleting even if we hit an error 1981 } 1982 if (success) { 1983 result.SetStatus(eReturnStatusSuccessFinishResult); 1984 return result.Succeeded(); 1985 } else { 1986 result.AppendError("cannot delete one or more categories\n"); 1987 return false; 1988 } 1989 } 1990 }; 1991 1992 // CommandObjectTypeCategoryDisable 1993 #define LLDB_OPTIONS_type_category_disable 1994 #include "CommandOptions.inc" 1995 1996 class CommandObjectTypeCategoryDisable : public CommandObjectParsed { 1997 class CommandOptions : public Options { 1998 public: 1999 CommandOptions() = default; 2000 2001 ~CommandOptions() override = default; 2002 2003 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2004 ExecutionContext *execution_context) override { 2005 Status error; 2006 const int short_option = m_getopt_table[option_idx].val; 2007 2008 switch (short_option) { 2009 case 'l': 2010 if (!option_arg.empty()) { 2011 m_language = Language::GetLanguageTypeFromString(option_arg); 2012 if (m_language == lldb::eLanguageTypeUnknown) 2013 error.SetErrorStringWithFormat("unrecognized language '%s'", 2014 option_arg.str().c_str()); 2015 } 2016 break; 2017 default: 2018 llvm_unreachable("Unimplemented option"); 2019 } 2020 2021 return error; 2022 } 2023 2024 void OptionParsingStarting(ExecutionContext *execution_context) override { 2025 m_language = lldb::eLanguageTypeUnknown; 2026 } 2027 2028 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2029 return llvm::makeArrayRef(g_type_category_disable_options); 2030 } 2031 2032 // Instance variables to hold the values for command options. 2033 2034 lldb::LanguageType m_language; 2035 }; 2036 2037 CommandOptions m_options; 2038 2039 Options *GetOptions() override { return &m_options; } 2040 2041 public: 2042 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter) 2043 : CommandObjectParsed(interpreter, "type category disable", 2044 "Disable a category as a source of formatters.", 2045 nullptr) { 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 auto options = std::make_unique<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.release()); // Baton for the "io_handler" that will be passed back 2276 // into our 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() = default; 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 CommandArgumentEntry type_arg; 2533 CommandArgumentData type_style_arg; 2534 2535 type_style_arg.arg_type = eArgTypeName; 2536 type_style_arg.arg_repetition = eArgRepeatPlus; 2537 2538 type_arg.push_back(type_style_arg); 2539 2540 m_arguments.push_back(type_arg); 2541 2542 SetHelpLong( 2543 R"( 2544 The following examples of 'type filter add' refer to this code snippet for context: 2545 2546 class Foo { 2547 int a; 2548 int b; 2549 int c; 2550 int d; 2551 int e; 2552 int f; 2553 int g; 2554 int h; 2555 int i; 2556 } 2557 Foo my_foo; 2558 2559 Adding a simple filter: 2560 2561 (lldb) type filter add --child a --child g Foo 2562 (lldb) frame variable my_foo 2563 2564 )" 2565 "Produces output where only a and g are displayed. Other children of my_foo \ 2566 (b, c, d, e, f, h and i) are available by asking for them explicitly:" 2567 R"( 2568 2569 (lldb) frame variable my_foo.b my_foo.c my_foo.i 2570 2571 )" 2572 "The formatting option --raw on frame variable bypasses the filter, showing \ 2573 all children of my_foo as if no filter was defined:" 2574 R"( 2575 2576 (lldb) frame variable my_foo --raw)"); 2577 } 2578 2579 ~CommandObjectTypeFilterAdd() override = default; 2580 2581 protected: 2582 bool DoExecute(Args &command, CommandReturnObject &result) override { 2583 const size_t argc = command.GetArgumentCount(); 2584 2585 if (argc < 1) { 2586 result.AppendErrorWithFormat("%s takes one or more args.\n", 2587 m_cmd_name.c_str()); 2588 return false; 2589 } 2590 2591 if (m_options.m_expr_paths.empty()) { 2592 result.AppendErrorWithFormat("%s needs one or more children.\n", 2593 m_cmd_name.c_str()); 2594 return false; 2595 } 2596 2597 TypeFilterImplSP entry(new TypeFilterImpl( 2598 SyntheticChildren::Flags() 2599 .SetCascades(m_options.m_cascade) 2600 .SetSkipPointers(m_options.m_skip_pointers) 2601 .SetSkipReferences(m_options.m_skip_references))); 2602 2603 // go through the expression paths 2604 CommandOptions::ExpressionPathsIterator begin, 2605 end = m_options.m_expr_paths.end(); 2606 2607 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 2608 entry->AddExpressionPath(*begin); 2609 2610 // now I have a valid provider, let's add it to every type 2611 2612 lldb::TypeCategoryImplSP category; 2613 DataVisualization::Categories::GetCategory( 2614 ConstString(m_options.m_category.c_str()), category); 2615 2616 Status error; 2617 2618 WarnOnPotentialUnquotedUnsignedType(command, result); 2619 2620 for (auto &arg_entry : command.entries()) { 2621 if (arg_entry.ref().empty()) { 2622 result.AppendError("empty typenames not allowed"); 2623 return false; 2624 } 2625 2626 ConstString typeCS(arg_entry.ref()); 2627 if (!AddFilter(typeCS, entry, 2628 m_options.m_regex ? eRegexFilter : eRegularFilter, 2629 m_options.m_category, &error)) { 2630 result.AppendError(error.AsCString()); 2631 return false; 2632 } 2633 } 2634 2635 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2636 return result.Succeeded(); 2637 } 2638 }; 2639 2640 // "type lookup" 2641 #define LLDB_OPTIONS_type_lookup 2642 #include "CommandOptions.inc" 2643 2644 class CommandObjectTypeLookup : public CommandObjectRaw { 2645 protected: 2646 // this function is allowed to do a more aggressive job at guessing languages 2647 // than the expression parser is comfortable with - so leave the original 2648 // call alone and add one that is specific to type lookup 2649 lldb::LanguageType GuessLanguage(StackFrame *frame) { 2650 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; 2651 2652 if (!frame) 2653 return lang_type; 2654 2655 lang_type = frame->GuessLanguage(); 2656 if (lang_type != lldb::eLanguageTypeUnknown) 2657 return lang_type; 2658 2659 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 2660 if (s) 2661 lang_type = s->GetMangled().GuessLanguage(); 2662 2663 return lang_type; 2664 } 2665 2666 class CommandOptions : public OptionGroup { 2667 public: 2668 CommandOptions() = default; 2669 2670 ~CommandOptions() override = default; 2671 2672 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2673 return llvm::makeArrayRef(g_type_lookup_options); 2674 } 2675 2676 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 2677 ExecutionContext *execution_context) override { 2678 Status error; 2679 2680 const int short_option = g_type_lookup_options[option_idx].short_option; 2681 2682 switch (short_option) { 2683 case 'h': 2684 m_show_help = true; 2685 break; 2686 2687 case 'l': 2688 m_language = Language::GetLanguageTypeFromString(option_value); 2689 break; 2690 2691 default: 2692 llvm_unreachable("Unimplemented option"); 2693 } 2694 2695 return error; 2696 } 2697 2698 void OptionParsingStarting(ExecutionContext *execution_context) override { 2699 m_show_help = false; 2700 m_language = eLanguageTypeUnknown; 2701 } 2702 2703 // Options table: Required for subclasses of Options. 2704 2705 bool m_show_help = false; 2706 lldb::LanguageType m_language = eLanguageTypeUnknown; 2707 }; 2708 2709 OptionGroupOptions m_option_group; 2710 CommandOptions m_command_options; 2711 2712 public: 2713 CommandObjectTypeLookup(CommandInterpreter &interpreter) 2714 : CommandObjectRaw(interpreter, "type lookup", 2715 "Lookup types and declarations in the current target, " 2716 "following language-specific naming conventions.", 2717 "type lookup <type-specifier>", 2718 eCommandRequiresTarget) { 2719 m_option_group.Append(&m_command_options); 2720 m_option_group.Finalize(); 2721 } 2722 2723 ~CommandObjectTypeLookup() override = default; 2724 2725 Options *GetOptions() override { return &m_option_group; } 2726 2727 llvm::StringRef GetHelpLong() override { 2728 if (!m_cmd_help_long.empty()) 2729 return m_cmd_help_long; 2730 2731 StreamString stream; 2732 Language::ForEach([&](Language *lang) { 2733 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp()) 2734 stream.Printf("%s\n", help); 2735 return true; 2736 }); 2737 2738 m_cmd_help_long = std::string(stream.GetString()); 2739 return m_cmd_help_long; 2740 } 2741 2742 bool DoExecute(llvm::StringRef raw_command_line, 2743 CommandReturnObject &result) override { 2744 if (raw_command_line.empty()) { 2745 result.AppendError( 2746 "type lookup cannot be invoked without a type name as argument"); 2747 return false; 2748 } 2749 2750 auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 2751 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 2752 2753 OptionsWithRaw args(raw_command_line); 2754 const char *name_of_type = args.GetRawPart().c_str(); 2755 2756 if (args.HasArgs()) 2757 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 2758 exe_ctx)) 2759 return false; 2760 2761 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 2762 2763 bool any_found = false; 2764 2765 std::vector<Language *> languages; 2766 2767 bool is_global_search = false; 2768 LanguageType guessed_language = lldb::eLanguageTypeUnknown; 2769 2770 if ((is_global_search = 2771 (m_command_options.m_language == eLanguageTypeUnknown))) { 2772 Language::ForEach([&](Language *lang) { 2773 languages.push_back(lang); 2774 return true; 2775 }); 2776 } else { 2777 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 2778 } 2779 2780 // This is not the most efficient way to do this, but we support very few 2781 // languages so the cost of the sort is going to be dwarfed by the actual 2782 // lookup anyway 2783 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { 2784 guessed_language = GuessLanguage(frame); 2785 if (guessed_language != eLanguageTypeUnknown) { 2786 llvm::sort( 2787 languages.begin(), languages.end(), 2788 [guessed_language](Language *lang1, Language *lang2) -> bool { 2789 if (!lang1 || !lang2) 2790 return false; 2791 LanguageType lt1 = lang1->GetLanguageType(); 2792 LanguageType lt2 = lang2->GetLanguageType(); 2793 if (lt1 == guessed_language) 2794 return true; // make the selected frame's language come first 2795 if (lt2 == guessed_language) 2796 return false; // make the selected frame's language come first 2797 return (lt1 < lt2); // normal comparison otherwise 2798 }); 2799 } 2800 } 2801 2802 bool is_first_language = true; 2803 2804 for (Language *language : languages) { 2805 if (!language) 2806 continue; 2807 2808 if (auto scavenger = language->GetTypeScavenger()) { 2809 Language::TypeScavenger::ResultSet search_results; 2810 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) { 2811 for (const auto &search_result : search_results) { 2812 if (search_result && search_result->IsValid()) { 2813 any_found = true; 2814 search_result->DumpToStream(result.GetOutputStream(), 2815 this->m_command_options.m_show_help); 2816 } 2817 } 2818 } 2819 } 2820 // this is "type lookup SomeName" and we did find a match, so get out 2821 if (any_found && is_global_search) 2822 break; 2823 else if (is_first_language && is_global_search && 2824 guessed_language != lldb::eLanguageTypeUnknown) { 2825 is_first_language = false; 2826 result.GetOutputStream().Printf( 2827 "no type was found in the current language %s matching '%s'; " 2828 "performing a global search across all languages\n", 2829 Language::GetNameForLanguageType(guessed_language), name_of_type); 2830 } 2831 } 2832 2833 if (!any_found) 2834 result.AppendMessageWithFormat("no type was found matching '%s'\n", 2835 name_of_type); 2836 2837 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult 2838 : lldb::eReturnStatusSuccessFinishNoResult); 2839 return true; 2840 } 2841 }; 2842 2843 template <typename FormatterType> 2844 class CommandObjectFormatterInfo : public CommandObjectRaw { 2845 public: 2846 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)> 2847 DiscoveryFunction; 2848 CommandObjectFormatterInfo(CommandInterpreter &interpreter, 2849 const char *formatter_name, 2850 DiscoveryFunction discovery_func) 2851 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame), 2852 m_formatter_name(formatter_name ? formatter_name : ""), 2853 m_discovery_function(discovery_func) { 2854 StreamString name; 2855 name.Printf("type %s info", formatter_name); 2856 SetCommandName(name.GetString()); 2857 StreamString help; 2858 help.Printf("This command evaluates the provided expression and shows " 2859 "which %s is applied to the resulting value (if any).", 2860 formatter_name); 2861 SetHelp(help.GetString()); 2862 StreamString syntax; 2863 syntax.Printf("type %s info <expr>", formatter_name); 2864 SetSyntax(syntax.GetString()); 2865 } 2866 2867 ~CommandObjectFormatterInfo() override = default; 2868 2869 protected: 2870 bool DoExecute(llvm::StringRef command, 2871 CommandReturnObject &result) override { 2872 TargetSP target_sp = GetDebugger().GetSelectedTarget(); 2873 Thread *thread = GetDefaultThread(); 2874 if (!thread) { 2875 result.AppendError("no default thread"); 2876 return false; 2877 } 2878 2879 StackFrameSP frame_sp = thread->GetSelectedFrame(); 2880 ValueObjectSP result_valobj_sp; 2881 EvaluateExpressionOptions options; 2882 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( 2883 command, frame_sp.get(), result_valobj_sp, options); 2884 if (expr_result == eExpressionCompleted && result_valobj_sp) { 2885 result_valobj_sp = 2886 result_valobj_sp->GetQualifiedRepresentationIfAvailable( 2887 target_sp->GetPreferDynamicValue(), 2888 target_sp->GetEnableSyntheticValue()); 2889 typename FormatterType::SharedPointer formatter_sp = 2890 m_discovery_function(*result_valobj_sp); 2891 if (formatter_sp) { 2892 std::string description(formatter_sp->GetDescription()); 2893 result.GetOutputStream() 2894 << m_formatter_name << " applied to (" 2895 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2896 << ") " << command << " is: " << description << "\n"; 2897 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 2898 } else { 2899 result.GetOutputStream() 2900 << "no " << m_formatter_name << " applies to (" 2901 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2902 << ") " << command << "\n"; 2903 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 2904 } 2905 return true; 2906 } else { 2907 result.AppendError("failed to evaluate expression"); 2908 return false; 2909 } 2910 } 2911 2912 private: 2913 std::string m_formatter_name; 2914 DiscoveryFunction m_discovery_function; 2915 }; 2916 2917 class CommandObjectTypeFormat : public CommandObjectMultiword { 2918 public: 2919 CommandObjectTypeFormat(CommandInterpreter &interpreter) 2920 : CommandObjectMultiword( 2921 interpreter, "type format", 2922 "Commands for customizing value display formats.", 2923 "type format [<sub-command-options>] ") { 2924 LoadSubCommand( 2925 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter))); 2926 LoadSubCommand("clear", CommandObjectSP( 2927 new CommandObjectTypeFormatClear(interpreter))); 2928 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete( 2929 interpreter))); 2930 LoadSubCommand( 2931 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter))); 2932 LoadSubCommand( 2933 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>( 2934 interpreter, "format", 2935 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer { 2936 return valobj.GetValueFormat(); 2937 }))); 2938 } 2939 2940 ~CommandObjectTypeFormat() override = default; 2941 }; 2942 2943 #if LLDB_ENABLE_PYTHON 2944 2945 class CommandObjectTypeSynth : public CommandObjectMultiword { 2946 public: 2947 CommandObjectTypeSynth(CommandInterpreter &interpreter) 2948 : CommandObjectMultiword( 2949 interpreter, "type synthetic", 2950 "Commands for operating on synthetic type representations.", 2951 "type synthetic [<sub-command-options>] ") { 2952 LoadSubCommand("add", 2953 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter))); 2954 LoadSubCommand( 2955 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter))); 2956 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete( 2957 interpreter))); 2958 LoadSubCommand( 2959 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter))); 2960 LoadSubCommand( 2961 "info", 2962 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>( 2963 interpreter, "synthetic", 2964 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer { 2965 return valobj.GetSyntheticChildren(); 2966 }))); 2967 } 2968 2969 ~CommandObjectTypeSynth() override = default; 2970 }; 2971 2972 #endif 2973 2974 class CommandObjectTypeFilter : public CommandObjectMultiword { 2975 public: 2976 CommandObjectTypeFilter(CommandInterpreter &interpreter) 2977 : CommandObjectMultiword(interpreter, "type filter", 2978 "Commands for operating on type filters.", 2979 "type filter [<sub-command-options>] ") { 2980 LoadSubCommand( 2981 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter))); 2982 LoadSubCommand("clear", CommandObjectSP( 2983 new CommandObjectTypeFilterClear(interpreter))); 2984 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete( 2985 interpreter))); 2986 LoadSubCommand( 2987 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter))); 2988 } 2989 2990 ~CommandObjectTypeFilter() override = default; 2991 }; 2992 2993 class CommandObjectTypeCategory : public CommandObjectMultiword { 2994 public: 2995 CommandObjectTypeCategory(CommandInterpreter &interpreter) 2996 : CommandObjectMultiword(interpreter, "type category", 2997 "Commands for operating on type categories.", 2998 "type category [<sub-command-options>] ") { 2999 LoadSubCommand( 3000 "define", 3001 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter))); 3002 LoadSubCommand( 3003 "enable", 3004 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter))); 3005 LoadSubCommand( 3006 "disable", 3007 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter))); 3008 LoadSubCommand( 3009 "delete", 3010 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter))); 3011 LoadSubCommand("list", CommandObjectSP( 3012 new CommandObjectTypeCategoryList(interpreter))); 3013 } 3014 3015 ~CommandObjectTypeCategory() override = default; 3016 }; 3017 3018 class CommandObjectTypeSummary : public CommandObjectMultiword { 3019 public: 3020 CommandObjectTypeSummary(CommandInterpreter &interpreter) 3021 : CommandObjectMultiword( 3022 interpreter, "type summary", 3023 "Commands for editing variable summary display options.", 3024 "type summary [<sub-command-options>] ") { 3025 LoadSubCommand( 3026 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter))); 3027 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear( 3028 interpreter))); 3029 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete( 3030 interpreter))); 3031 LoadSubCommand( 3032 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter))); 3033 LoadSubCommand( 3034 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>( 3035 interpreter, "summary", 3036 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer { 3037 return valobj.GetSummaryFormat(); 3038 }))); 3039 } 3040 3041 ~CommandObjectTypeSummary() override = default; 3042 }; 3043 3044 // CommandObjectType 3045 3046 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) 3047 : CommandObjectMultiword(interpreter, "type", 3048 "Commands for operating on the type system.", 3049 "type [<sub-command-options>]") { 3050 LoadSubCommand("category", 3051 CommandObjectSP(new CommandObjectTypeCategory(interpreter))); 3052 LoadSubCommand("filter", 3053 CommandObjectSP(new CommandObjectTypeFilter(interpreter))); 3054 LoadSubCommand("format", 3055 CommandObjectSP(new CommandObjectTypeFormat(interpreter))); 3056 LoadSubCommand("summary", 3057 CommandObjectSP(new CommandObjectTypeSummary(interpreter))); 3058 #if LLDB_ENABLE_PYTHON 3059 LoadSubCommand("synthetic", 3060 CommandObjectSP(new CommandObjectTypeSynth(interpreter))); 3061 #endif 3062 LoadSubCommand("lookup", 3063 CommandObjectSP(new CommandObjectTypeLookup(interpreter))); 3064 } 3065 3066 CommandObjectType::~CommandObjectType() = default; 3067