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 = false; 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 = false; 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 static bool ShouldListItem(llvm::StringRef s, RegularExpression *regex) { 1059 // If we have a regex, it can match two kinds of results: 1060 // - An item created with that same regex string (exact string match), so 1061 // the user can list it using the same string it used at creation time. 1062 // - Items that match the regex. 1063 // No regex means list everything. 1064 return regex == nullptr || s == regex->GetText() || regex->Execute(s); 1065 } 1066 1067 bool DoExecute(Args &command, CommandReturnObject &result) override { 1068 const size_t argc = command.GetArgumentCount(); 1069 1070 std::unique_ptr<RegularExpression> category_regex; 1071 std::unique_ptr<RegularExpression> formatter_regex; 1072 1073 if (m_options.m_category_regex.OptionWasSet()) { 1074 category_regex = std::make_unique<RegularExpression>( 1075 m_options.m_category_regex.GetCurrentValueAsRef()); 1076 if (!category_regex->IsValid()) { 1077 result.AppendErrorWithFormat( 1078 "syntax error in category regular expression '%s'", 1079 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str()); 1080 return false; 1081 } 1082 } 1083 1084 if (argc == 1) { 1085 const char *arg = command.GetArgumentAtIndex(0); 1086 formatter_regex = std::make_unique<RegularExpression>(arg); 1087 if (!formatter_regex->IsValid()) { 1088 result.AppendErrorWithFormat("syntax error in regular expression '%s'", 1089 arg); 1090 return false; 1091 } 1092 } 1093 1094 bool any_printed = false; 1095 1096 auto category_closure = 1097 [&result, &formatter_regex, 1098 &any_printed](const lldb::TypeCategoryImplSP &category) -> void { 1099 result.GetOutputStream().Printf( 1100 "-----------------------\nCategory: %s%s\n-----------------------\n", 1101 category->GetName(), category->IsEnabled() ? "" : " (disabled)"); 1102 1103 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; 1104 foreach 1105 .SetExact([&result, &formatter_regex, &any_printed]( 1106 const TypeMatcher &type_matcher, 1107 const FormatterSharedPointer &format_sp) -> bool { 1108 if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(), 1109 formatter_regex.get())) { 1110 any_printed = true; 1111 result.GetOutputStream().Printf( 1112 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1113 format_sp->GetDescription().c_str()); 1114 } 1115 return true; 1116 }); 1117 1118 foreach 1119 .SetWithRegex([&result, &formatter_regex, &any_printed]( 1120 const TypeMatcher &type_matcher, 1121 const FormatterSharedPointer &format_sp) -> bool { 1122 if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(), 1123 formatter_regex.get())) { 1124 any_printed = true; 1125 result.GetOutputStream().Printf( 1126 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1127 format_sp->GetDescription().c_str()); 1128 } 1129 return true; 1130 }); 1131 1132 category->ForEach(foreach); 1133 }; 1134 1135 if (m_options.m_category_language.OptionWasSet()) { 1136 lldb::TypeCategoryImplSP category_sp; 1137 DataVisualization::Categories::GetCategory( 1138 m_options.m_category_language.GetCurrentValue(), category_sp); 1139 if (category_sp) 1140 category_closure(category_sp); 1141 } else { 1142 DataVisualization::Categories::ForEach( 1143 [&category_regex, &category_closure]( 1144 const lldb::TypeCategoryImplSP &category) -> bool { 1145 if (ShouldListItem(category->GetName(), category_regex.get())) { 1146 category_closure(category); 1147 } 1148 return true; 1149 }); 1150 1151 any_printed = FormatterSpecificList(result) | any_printed; 1152 } 1153 1154 if (any_printed) 1155 result.SetStatus(eReturnStatusSuccessFinishResult); 1156 else { 1157 result.GetOutputStream().PutCString("no matching results found.\n"); 1158 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1159 } 1160 return result.Succeeded(); 1161 } 1162 }; 1163 1164 // CommandObjectTypeFormatList 1165 1166 class CommandObjectTypeFormatList 1167 : public CommandObjectTypeFormatterList<TypeFormatImpl> { 1168 public: 1169 CommandObjectTypeFormatList(CommandInterpreter &interpreter) 1170 : CommandObjectTypeFormatterList(interpreter, "type format list", 1171 "Show a list of current formats.") {} 1172 }; 1173 1174 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( 1175 uint32_t option_idx, llvm::StringRef option_arg, 1176 ExecutionContext *execution_context) { 1177 Status error; 1178 const int short_option = m_getopt_table[option_idx].val; 1179 bool success; 1180 1181 switch (short_option) { 1182 case 'C': 1183 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success)); 1184 if (!success) 1185 error.SetErrorStringWithFormat("invalid value for cascade: %s", 1186 option_arg.str().c_str()); 1187 break; 1188 case 'e': 1189 m_flags.SetDontShowChildren(false); 1190 break; 1191 case 'h': 1192 m_flags.SetHideEmptyAggregates(true); 1193 break; 1194 case 'v': 1195 m_flags.SetDontShowValue(true); 1196 break; 1197 case 'c': 1198 m_flags.SetShowMembersOneLiner(true); 1199 break; 1200 case 's': 1201 m_format_string = std::string(option_arg); 1202 break; 1203 case 'p': 1204 m_flags.SetSkipPointers(true); 1205 break; 1206 case 'r': 1207 m_flags.SetSkipReferences(true); 1208 break; 1209 case 'x': 1210 m_regex = true; 1211 break; 1212 case 'n': 1213 m_name.SetString(option_arg); 1214 break; 1215 case 'o': 1216 m_python_script = std::string(option_arg); 1217 m_is_add_script = true; 1218 break; 1219 case 'F': 1220 m_python_function = std::string(option_arg); 1221 m_is_add_script = true; 1222 break; 1223 case 'P': 1224 m_is_add_script = true; 1225 break; 1226 case 'w': 1227 m_category = std::string(option_arg); 1228 break; 1229 case 'O': 1230 m_flags.SetHideItemNames(true); 1231 break; 1232 default: 1233 llvm_unreachable("Unimplemented option"); 1234 } 1235 1236 return error; 1237 } 1238 1239 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting( 1240 ExecutionContext *execution_context) { 1241 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 1242 m_flags.SetShowMembersOneLiner(false) 1243 .SetSkipPointers(false) 1244 .SetSkipReferences(false) 1245 .SetHideItemNames(false); 1246 1247 m_regex = false; 1248 m_name.Clear(); 1249 m_python_script = ""; 1250 m_python_function = ""; 1251 m_format_string = ""; 1252 m_is_add_script = false; 1253 m_category = "default"; 1254 } 1255 1256 #if LLDB_ENABLE_PYTHON 1257 1258 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( 1259 Args &command, CommandReturnObject &result) { 1260 const size_t argc = command.GetArgumentCount(); 1261 1262 if (argc < 1 && !m_options.m_name) { 1263 result.AppendErrorWithFormat("%s takes one or more args.\n", 1264 m_cmd_name.c_str()); 1265 return false; 1266 } 1267 1268 TypeSummaryImplSP script_format; 1269 1270 if (!m_options.m_python_function 1271 .empty()) // we have a Python function ready to use 1272 { 1273 const char *funct_name = m_options.m_python_function.c_str(); 1274 if (!funct_name || !funct_name[0]) { 1275 result.AppendError("function name empty.\n"); 1276 return false; 1277 } 1278 1279 std::string code = 1280 (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1281 1282 script_format = std::make_shared<ScriptSummaryFormat>( 1283 m_options.m_flags, funct_name, code.c_str()); 1284 1285 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1286 1287 if (interpreter && !interpreter->CheckObjectExists(funct_name)) 1288 result.AppendWarningWithFormat( 1289 "The provided function \"%s\" does not exist - " 1290 "please define it before attempting to use this summary.\n", 1291 funct_name); 1292 } else if (!m_options.m_python_script 1293 .empty()) // we have a quick 1-line script, just use it 1294 { 1295 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1296 if (!interpreter) { 1297 result.AppendError("script interpreter missing - unable to generate " 1298 "function wrapper.\n"); 1299 return false; 1300 } 1301 StringList funct_sl; 1302 funct_sl << m_options.m_python_script.c_str(); 1303 std::string funct_name_str; 1304 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) { 1305 result.AppendError("unable to generate function wrapper.\n"); 1306 return false; 1307 } 1308 if (funct_name_str.empty()) { 1309 result.AppendError( 1310 "script interpreter failed to generate a valid function name.\n"); 1311 return false; 1312 } 1313 1314 std::string code = " " + m_options.m_python_script; 1315 1316 script_format = std::make_shared<ScriptSummaryFormat>( 1317 m_options.m_flags, funct_name_str.c_str(), code.c_str()); 1318 } else { 1319 // Use an IOHandler to grab Python code from the user 1320 auto options = std::make_unique<ScriptAddOptions>( 1321 m_options.m_flags, m_options.m_regex, m_options.m_name, 1322 m_options.m_category); 1323 1324 for (auto &entry : command.entries()) { 1325 if (entry.ref().empty()) { 1326 result.AppendError("empty typenames not allowed"); 1327 return false; 1328 } 1329 1330 options->m_target_types << std::string(entry.ref()); 1331 } 1332 1333 m_interpreter.GetPythonCommandsFromIOHandler( 1334 " ", // Prompt 1335 *this, // IOHandlerDelegate 1336 options.release()); // Baton for the "io_handler" that will be passed 1337 // back into our IOHandlerDelegate functions 1338 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1339 1340 return result.Succeeded(); 1341 } 1342 1343 // if I am here, script_format must point to something good, so I can add 1344 // that as a script summary to all interested parties 1345 1346 Status error; 1347 1348 for (auto &entry : command.entries()) { 1349 CommandObjectTypeSummaryAdd::AddSummary( 1350 ConstString(entry.ref()), script_format, 1351 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1352 m_options.m_category, &error); 1353 if (error.Fail()) { 1354 result.AppendError(error.AsCString()); 1355 return false; 1356 } 1357 } 1358 1359 if (m_options.m_name) { 1360 AddSummary(m_options.m_name, script_format, eNamedSummary, 1361 m_options.m_category, &error); 1362 if (error.Fail()) { 1363 result.AppendError(error.AsCString()); 1364 result.AppendError("added to types, but not given a name"); 1365 return false; 1366 } 1367 } 1368 1369 return result.Succeeded(); 1370 } 1371 1372 #endif 1373 1374 bool CommandObjectTypeSummaryAdd::Execute_StringSummary( 1375 Args &command, CommandReturnObject &result) { 1376 const size_t argc = command.GetArgumentCount(); 1377 1378 if (argc < 1 && !m_options.m_name) { 1379 result.AppendErrorWithFormat("%s takes one or more args.\n", 1380 m_cmd_name.c_str()); 1381 return false; 1382 } 1383 1384 if (!m_options.m_flags.GetShowMembersOneLiner() && 1385 m_options.m_format_string.empty()) { 1386 result.AppendError("empty summary strings not allowed"); 1387 return false; 1388 } 1389 1390 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner() 1391 ? "" 1392 : m_options.m_format_string.c_str()); 1393 1394 // ${var%S} is an endless recursion, prevent it 1395 if (strcmp(format_cstr, "${var%S}") == 0) { 1396 result.AppendError("recursive summary not allowed"); 1397 return false; 1398 } 1399 1400 std::unique_ptr<StringSummaryFormat> string_format( 1401 new StringSummaryFormat(m_options.m_flags, format_cstr)); 1402 if (!string_format) { 1403 result.AppendError("summary creation failed"); 1404 return false; 1405 } 1406 if (string_format->m_error.Fail()) { 1407 result.AppendErrorWithFormat("syntax error: %s", 1408 string_format->m_error.AsCString("<unknown>")); 1409 return false; 1410 } 1411 lldb::TypeSummaryImplSP entry(string_format.release()); 1412 1413 // now I have a valid format, let's add it to every type 1414 Status error; 1415 for (auto &arg_entry : command.entries()) { 1416 if (arg_entry.ref().empty()) { 1417 result.AppendError("empty typenames not allowed"); 1418 return false; 1419 } 1420 ConstString typeCS(arg_entry.ref()); 1421 1422 AddSummary(typeCS, entry, 1423 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1424 m_options.m_category, &error); 1425 1426 if (error.Fail()) { 1427 result.AppendError(error.AsCString()); 1428 return false; 1429 } 1430 } 1431 1432 if (m_options.m_name) { 1433 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, 1434 &error); 1435 if (error.Fail()) { 1436 result.AppendError(error.AsCString()); 1437 result.AppendError("added to types, but not given a name"); 1438 return false; 1439 } 1440 } 1441 1442 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1443 return result.Succeeded(); 1444 } 1445 1446 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd( 1447 CommandInterpreter &interpreter) 1448 : CommandObjectParsed(interpreter, "type summary add", 1449 "Add a new summary style for a type.", nullptr), 1450 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) { 1451 CommandArgumentEntry type_arg; 1452 CommandArgumentData type_style_arg; 1453 1454 type_style_arg.arg_type = eArgTypeName; 1455 type_style_arg.arg_repetition = eArgRepeatPlus; 1456 1457 type_arg.push_back(type_style_arg); 1458 1459 m_arguments.push_back(type_arg); 1460 1461 SetHelpLong( 1462 R"( 1463 The following examples of 'type summary add' refer to this code snippet for context: 1464 1465 struct JustADemo 1466 { 1467 int* ptr; 1468 float value; 1469 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {} 1470 }; 1471 JustADemo demo_instance(42, 3.14); 1472 1473 typedef JustADemo NewDemo; 1474 NewDemo new_demo_instance(42, 3.14); 1475 1476 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo 1477 1478 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42" 1479 1480 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo 1481 1482 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" 1483 1484 )" 1485 "Alternatively, you could define formatting for all pointers to integers and \ 1486 rely on that when formatting JustADemo to obtain the same result:" 1487 R"( 1488 1489 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" 1490 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo 1491 1492 )" 1493 "Type summaries are automatically applied to derived typedefs, so the examples \ 1494 above apply to both JustADemo and NewDemo. The cascade option can be used to \ 1495 suppress this behavior:" 1496 R"( 1497 1498 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no 1499 1500 The summary will now be used for values of JustADemo but not NewDemo. 1501 1502 )" 1503 "By default summaries are shown for pointers and references to values of the \ 1504 specified type. To suppress formatting for pointers use the -p option, or apply \ 1505 the corresponding -r option to suppress formatting for references:" 1506 R"( 1507 1508 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo 1509 1510 )" 1511 "One-line summaries including all fields in a type can be inferred without supplying an \ 1512 explicit summary string by passing the -c option:" 1513 R"( 1514 1515 (lldb) type summary add -c JustADemo 1516 (lldb) frame variable demo_instance 1517 (ptr=<address>, value=3.14) 1518 1519 )" 1520 "Type summaries normally suppress the nested display of individual fields. To \ 1521 supply a summary to supplement the default structure add the -e option:" 1522 R"( 1523 1524 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo 1525 1526 )" 1527 "Now when displaying JustADemo values the int* is displayed, followed by the \ 1528 standard LLDB sequence of children, one per line:" 1529 R"( 1530 1531 *ptr = 42 { 1532 ptr = <address> 1533 value = 3.14 1534 } 1535 1536 )" 1537 "You can also add summaries written in Python. These scripts use lldb public API to \ 1538 gather information from your variables and produce a meaningful summary. To start a \ 1539 multi-line script use the -P option. The function declaration will be displayed along with \ 1540 a comment describing the two arguments. End your script with the word 'DONE' on a line by \ 1541 itself:" 1542 R"( 1543 1544 (lldb) type summary add JustADemo -P 1545 def function (valobj,internal_dict): 1546 """valobj: an SBValue which you want to provide a summary for 1547 internal_dict: an LLDB support object not to be used""" 1548 value = valobj.GetChildMemberWithName('value'); 1549 return 'My value is ' + value.GetValue(); 1550 DONE 1551 1552 Alternatively, the -o option can be used when providing a simple one-line Python script: 1553 1554 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"); 1555 } 1556 1557 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command, 1558 CommandReturnObject &result) { 1559 WarnOnPotentialUnquotedUnsignedType(command, result); 1560 1561 if (m_options.m_is_add_script) { 1562 #if LLDB_ENABLE_PYTHON 1563 return Execute_ScriptSummary(command, result); 1564 #else 1565 result.AppendError("python is disabled"); 1566 return false; 1567 #endif 1568 } 1569 1570 return Execute_StringSummary(command, result); 1571 } 1572 1573 static bool FixArrayTypeNameWithRegex(ConstString &type_name) { 1574 llvm::StringRef type_name_ref(type_name.GetStringRef()); 1575 1576 if (type_name_ref.endswith("[]")) { 1577 std::string type_name_str(type_name.GetCString()); 1578 type_name_str.resize(type_name_str.length() - 2); 1579 if (type_name_str.back() != ' ') 1580 type_name_str.append(" ?\\[[0-9]+\\]"); 1581 else 1582 type_name_str.append("\\[[0-9]+\\]"); 1583 type_name.SetCString(type_name_str.c_str()); 1584 return true; 1585 } 1586 return false; 1587 } 1588 1589 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, 1590 TypeSummaryImplSP entry, 1591 SummaryFormatType type, 1592 std::string category_name, 1593 Status *error) { 1594 lldb::TypeCategoryImplSP category; 1595 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 1596 category); 1597 1598 if (type == eRegularSummary) { 1599 if (FixArrayTypeNameWithRegex(type_name)) 1600 type = eRegexSummary; 1601 } 1602 1603 if (type == eRegexSummary) { 1604 RegularExpression typeRX(type_name.GetStringRef()); 1605 if (!typeRX.IsValid()) { 1606 if (error) 1607 error->SetErrorString( 1608 "regex format error (maybe this is not really a regex?)"); 1609 return false; 1610 } 1611 1612 category->GetRegexTypeSummariesContainer()->Delete(type_name); 1613 category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry); 1614 1615 return true; 1616 } else if (type == eNamedSummary) { 1617 // system named summaries do not exist (yet?) 1618 DataVisualization::NamedSummaryFormats::Add(type_name, entry); 1619 return true; 1620 } else { 1621 category->GetTypeSummariesContainer()->Add(std::move(type_name), entry); 1622 return true; 1623 } 1624 } 1625 1626 // CommandObjectTypeSummaryDelete 1627 1628 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { 1629 public: 1630 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter) 1631 : CommandObjectTypeFormatterDelete( 1632 interpreter, 1633 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1634 "type summary delete", "Delete an existing summary for a type.") {} 1635 1636 ~CommandObjectTypeSummaryDelete() override = default; 1637 1638 protected: 1639 bool FormatterSpecificDeletion(ConstString typeCS) override { 1640 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1641 return false; 1642 return DataVisualization::NamedSummaryFormats::Delete(typeCS); 1643 } 1644 }; 1645 1646 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear { 1647 public: 1648 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter) 1649 : CommandObjectTypeFormatterClear( 1650 interpreter, 1651 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1652 "type summary clear", "Delete all existing summaries.") {} 1653 1654 protected: 1655 void FormatterSpecificDeletion() override { 1656 DataVisualization::NamedSummaryFormats::Clear(); 1657 } 1658 }; 1659 1660 // CommandObjectTypeSummaryList 1661 1662 class CommandObjectTypeSummaryList 1663 : public CommandObjectTypeFormatterList<TypeSummaryImpl> { 1664 public: 1665 CommandObjectTypeSummaryList(CommandInterpreter &interpreter) 1666 : CommandObjectTypeFormatterList(interpreter, "type summary list", 1667 "Show a list of current summaries.") {} 1668 1669 protected: 1670 bool FormatterSpecificList(CommandReturnObject &result) override { 1671 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) { 1672 result.GetOutputStream().Printf("Named summaries:\n"); 1673 DataVisualization::NamedSummaryFormats::ForEach( 1674 [&result](const TypeMatcher &type_matcher, 1675 const TypeSummaryImplSP &summary_sp) -> bool { 1676 result.GetOutputStream().Printf( 1677 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1678 summary_sp->GetDescription().c_str()); 1679 return true; 1680 }); 1681 return true; 1682 } 1683 return false; 1684 } 1685 }; 1686 1687 // CommandObjectTypeCategoryDefine 1688 #define LLDB_OPTIONS_type_category_define 1689 #include "CommandOptions.inc" 1690 1691 class CommandObjectTypeCategoryDefine : public CommandObjectParsed { 1692 class CommandOptions : public Options { 1693 public: 1694 CommandOptions() 1695 : m_define_enabled(false, false), 1696 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {} 1697 1698 ~CommandOptions() override = default; 1699 1700 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1701 ExecutionContext *execution_context) override { 1702 Status error; 1703 const int short_option = m_getopt_table[option_idx].val; 1704 1705 switch (short_option) { 1706 case 'e': 1707 m_define_enabled.SetValueFromString(llvm::StringRef("true")); 1708 break; 1709 case 'l': 1710 error = m_cate_language.SetValueFromString(option_arg); 1711 break; 1712 default: 1713 llvm_unreachable("Unimplemented option"); 1714 } 1715 1716 return error; 1717 } 1718 1719 void OptionParsingStarting(ExecutionContext *execution_context) override { 1720 m_define_enabled.Clear(); 1721 m_cate_language.Clear(); 1722 } 1723 1724 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1725 return llvm::makeArrayRef(g_type_category_define_options); 1726 } 1727 1728 // Instance variables to hold the values for command options. 1729 1730 OptionValueBoolean m_define_enabled; 1731 OptionValueLanguage m_cate_language; 1732 }; 1733 1734 CommandOptions m_options; 1735 1736 Options *GetOptions() override { return &m_options; } 1737 1738 public: 1739 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter) 1740 : CommandObjectParsed(interpreter, "type category define", 1741 "Define a new category as a source of formatters.", 1742 nullptr) { 1743 CommandArgumentEntry type_arg; 1744 CommandArgumentData type_style_arg; 1745 1746 type_style_arg.arg_type = eArgTypeName; 1747 type_style_arg.arg_repetition = eArgRepeatPlus; 1748 1749 type_arg.push_back(type_style_arg); 1750 1751 m_arguments.push_back(type_arg); 1752 } 1753 1754 ~CommandObjectTypeCategoryDefine() override = default; 1755 1756 void 1757 HandleArgumentCompletion(CompletionRequest &request, 1758 OptionElementVector &opt_element_vector) override { 1759 CommandCompletions::InvokeCommonCompletionCallbacks( 1760 GetCommandInterpreter(), 1761 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1762 } 1763 1764 protected: 1765 bool DoExecute(Args &command, CommandReturnObject &result) override { 1766 const size_t argc = command.GetArgumentCount(); 1767 1768 if (argc < 1) { 1769 result.AppendErrorWithFormat("%s takes 1 or more args.\n", 1770 m_cmd_name.c_str()); 1771 return false; 1772 } 1773 1774 for (auto &entry : command.entries()) { 1775 TypeCategoryImplSP category_sp; 1776 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), 1777 category_sp) && 1778 category_sp) { 1779 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 1780 if (m_options.m_define_enabled.GetCurrentValue()) 1781 DataVisualization::Categories::Enable(category_sp, 1782 TypeCategoryMap::Default); 1783 } 1784 } 1785 1786 result.SetStatus(eReturnStatusSuccessFinishResult); 1787 return result.Succeeded(); 1788 } 1789 }; 1790 1791 // CommandObjectTypeCategoryEnable 1792 #define LLDB_OPTIONS_type_category_enable 1793 #include "CommandOptions.inc" 1794 1795 class CommandObjectTypeCategoryEnable : public CommandObjectParsed { 1796 class CommandOptions : public Options { 1797 public: 1798 CommandOptions() = default; 1799 1800 ~CommandOptions() override = default; 1801 1802 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1803 ExecutionContext *execution_context) override { 1804 Status error; 1805 const int short_option = m_getopt_table[option_idx].val; 1806 1807 switch (short_option) { 1808 case 'l': 1809 if (!option_arg.empty()) { 1810 m_language = Language::GetLanguageTypeFromString(option_arg); 1811 if (m_language == lldb::eLanguageTypeUnknown) 1812 error.SetErrorStringWithFormat("unrecognized language '%s'", 1813 option_arg.str().c_str()); 1814 } 1815 break; 1816 default: 1817 llvm_unreachable("Unimplemented option"); 1818 } 1819 1820 return error; 1821 } 1822 1823 void OptionParsingStarting(ExecutionContext *execution_context) override { 1824 m_language = lldb::eLanguageTypeUnknown; 1825 } 1826 1827 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1828 return llvm::makeArrayRef(g_type_category_enable_options); 1829 } 1830 1831 // Instance variables to hold the values for command options. 1832 1833 lldb::LanguageType m_language; 1834 }; 1835 1836 CommandOptions m_options; 1837 1838 Options *GetOptions() override { return &m_options; } 1839 1840 public: 1841 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter) 1842 : CommandObjectParsed(interpreter, "type category enable", 1843 "Enable a category as a source of formatters.", 1844 nullptr) { 1845 CommandArgumentEntry type_arg; 1846 CommandArgumentData type_style_arg; 1847 1848 type_style_arg.arg_type = eArgTypeName; 1849 type_style_arg.arg_repetition = eArgRepeatPlus; 1850 1851 type_arg.push_back(type_style_arg); 1852 1853 m_arguments.push_back(type_arg); 1854 } 1855 1856 ~CommandObjectTypeCategoryEnable() override = default; 1857 1858 void 1859 HandleArgumentCompletion(CompletionRequest &request, 1860 OptionElementVector &opt_element_vector) override { 1861 CommandCompletions::InvokeCommonCompletionCallbacks( 1862 GetCommandInterpreter(), 1863 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1864 } 1865 1866 protected: 1867 bool DoExecute(Args &command, CommandReturnObject &result) override { 1868 const size_t argc = command.GetArgumentCount(); 1869 1870 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 1871 result.AppendErrorWithFormat("%s takes arguments and/or a language", 1872 m_cmd_name.c_str()); 1873 return false; 1874 } 1875 1876 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 1877 DataVisualization::Categories::EnableStar(); 1878 } else if (argc > 0) { 1879 for (int i = argc - 1; i >= 0; i--) { 1880 const char *typeA = command.GetArgumentAtIndex(i); 1881 ConstString typeCS(typeA); 1882 1883 if (!typeCS) { 1884 result.AppendError("empty category name not allowed"); 1885 return false; 1886 } 1887 DataVisualization::Categories::Enable(typeCS); 1888 lldb::TypeCategoryImplSP cate; 1889 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) { 1890 if (cate->GetCount() == 0) { 1891 result.AppendWarning("empty category enabled (typo?)"); 1892 } 1893 } 1894 } 1895 } 1896 1897 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1898 DataVisualization::Categories::Enable(m_options.m_language); 1899 1900 result.SetStatus(eReturnStatusSuccessFinishResult); 1901 return result.Succeeded(); 1902 } 1903 }; 1904 1905 // CommandObjectTypeCategoryDelete 1906 1907 class CommandObjectTypeCategoryDelete : public CommandObjectParsed { 1908 public: 1909 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter) 1910 : CommandObjectParsed(interpreter, "type category delete", 1911 "Delete a category and all associated formatters.", 1912 nullptr) { 1913 CommandArgumentEntry type_arg; 1914 CommandArgumentData type_style_arg; 1915 1916 type_style_arg.arg_type = eArgTypeName; 1917 type_style_arg.arg_repetition = eArgRepeatPlus; 1918 1919 type_arg.push_back(type_style_arg); 1920 1921 m_arguments.push_back(type_arg); 1922 } 1923 1924 ~CommandObjectTypeCategoryDelete() override = default; 1925 1926 void 1927 HandleArgumentCompletion(CompletionRequest &request, 1928 OptionElementVector &opt_element_vector) override { 1929 CommandCompletions::InvokeCommonCompletionCallbacks( 1930 GetCommandInterpreter(), 1931 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1932 } 1933 1934 protected: 1935 bool DoExecute(Args &command, CommandReturnObject &result) override { 1936 const size_t argc = command.GetArgumentCount(); 1937 1938 if (argc < 1) { 1939 result.AppendErrorWithFormat("%s takes 1 or more arg.\n", 1940 m_cmd_name.c_str()); 1941 return false; 1942 } 1943 1944 bool success = true; 1945 1946 // the order is not relevant here 1947 for (int i = argc - 1; i >= 0; i--) { 1948 const char *typeA = command.GetArgumentAtIndex(i); 1949 ConstString typeCS(typeA); 1950 1951 if (!typeCS) { 1952 result.AppendError("empty category name not allowed"); 1953 return false; 1954 } 1955 if (!DataVisualization::Categories::Delete(typeCS)) 1956 success = false; // keep deleting even if we hit an error 1957 } 1958 if (success) { 1959 result.SetStatus(eReturnStatusSuccessFinishResult); 1960 return result.Succeeded(); 1961 } else { 1962 result.AppendError("cannot delete one or more categories\n"); 1963 return false; 1964 } 1965 } 1966 }; 1967 1968 // CommandObjectTypeCategoryDisable 1969 #define LLDB_OPTIONS_type_category_disable 1970 #include "CommandOptions.inc" 1971 1972 class CommandObjectTypeCategoryDisable : public CommandObjectParsed { 1973 class CommandOptions : public Options { 1974 public: 1975 CommandOptions() = default; 1976 1977 ~CommandOptions() override = default; 1978 1979 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1980 ExecutionContext *execution_context) override { 1981 Status error; 1982 const int short_option = m_getopt_table[option_idx].val; 1983 1984 switch (short_option) { 1985 case 'l': 1986 if (!option_arg.empty()) { 1987 m_language = Language::GetLanguageTypeFromString(option_arg); 1988 if (m_language == lldb::eLanguageTypeUnknown) 1989 error.SetErrorStringWithFormat("unrecognized language '%s'", 1990 option_arg.str().c_str()); 1991 } 1992 break; 1993 default: 1994 llvm_unreachable("Unimplemented option"); 1995 } 1996 1997 return error; 1998 } 1999 2000 void OptionParsingStarting(ExecutionContext *execution_context) override { 2001 m_language = lldb::eLanguageTypeUnknown; 2002 } 2003 2004 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2005 return llvm::makeArrayRef(g_type_category_disable_options); 2006 } 2007 2008 // Instance variables to hold the values for command options. 2009 2010 lldb::LanguageType m_language; 2011 }; 2012 2013 CommandOptions m_options; 2014 2015 Options *GetOptions() override { return &m_options; } 2016 2017 public: 2018 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter) 2019 : CommandObjectParsed(interpreter, "type category disable", 2020 "Disable a category as a source of formatters.", 2021 nullptr) { 2022 CommandArgumentEntry type_arg; 2023 CommandArgumentData type_style_arg; 2024 2025 type_style_arg.arg_type = eArgTypeName; 2026 type_style_arg.arg_repetition = eArgRepeatPlus; 2027 2028 type_arg.push_back(type_style_arg); 2029 2030 m_arguments.push_back(type_arg); 2031 } 2032 2033 ~CommandObjectTypeCategoryDisable() override = default; 2034 2035 void 2036 HandleArgumentCompletion(CompletionRequest &request, 2037 OptionElementVector &opt_element_vector) override { 2038 CommandCompletions::InvokeCommonCompletionCallbacks( 2039 GetCommandInterpreter(), 2040 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2041 } 2042 2043 protected: 2044 bool DoExecute(Args &command, CommandReturnObject &result) override { 2045 const size_t argc = command.GetArgumentCount(); 2046 2047 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 2048 result.AppendErrorWithFormat("%s takes arguments and/or a language", 2049 m_cmd_name.c_str()); 2050 return false; 2051 } 2052 2053 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 2054 DataVisualization::Categories::DisableStar(); 2055 } else if (argc > 0) { 2056 // the order is not relevant here 2057 for (int i = argc - 1; i >= 0; i--) { 2058 const char *typeA = command.GetArgumentAtIndex(i); 2059 ConstString typeCS(typeA); 2060 2061 if (!typeCS) { 2062 result.AppendError("empty category name not allowed"); 2063 return false; 2064 } 2065 DataVisualization::Categories::Disable(typeCS); 2066 } 2067 } 2068 2069 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2070 DataVisualization::Categories::Disable(m_options.m_language); 2071 2072 result.SetStatus(eReturnStatusSuccessFinishResult); 2073 return result.Succeeded(); 2074 } 2075 }; 2076 2077 // CommandObjectTypeCategoryList 2078 2079 class CommandObjectTypeCategoryList : public CommandObjectParsed { 2080 public: 2081 CommandObjectTypeCategoryList(CommandInterpreter &interpreter) 2082 : CommandObjectParsed(interpreter, "type category list", 2083 "Provide a list of all existing categories.", 2084 nullptr) { 2085 CommandArgumentEntry type_arg; 2086 CommandArgumentData type_style_arg; 2087 2088 type_style_arg.arg_type = eArgTypeName; 2089 type_style_arg.arg_repetition = eArgRepeatOptional; 2090 2091 type_arg.push_back(type_style_arg); 2092 2093 m_arguments.push_back(type_arg); 2094 } 2095 2096 ~CommandObjectTypeCategoryList() override = default; 2097 2098 void 2099 HandleArgumentCompletion(CompletionRequest &request, 2100 OptionElementVector &opt_element_vector) override { 2101 if (request.GetCursorIndex()) 2102 return; 2103 CommandCompletions::InvokeCommonCompletionCallbacks( 2104 GetCommandInterpreter(), 2105 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2106 } 2107 2108 protected: 2109 bool DoExecute(Args &command, CommandReturnObject &result) override { 2110 const size_t argc = command.GetArgumentCount(); 2111 2112 std::unique_ptr<RegularExpression> regex; 2113 2114 if (argc == 1) { 2115 const char *arg = command.GetArgumentAtIndex(0); 2116 regex = std::make_unique<RegularExpression>(arg); 2117 if (!regex->IsValid()) { 2118 result.AppendErrorWithFormat( 2119 "syntax error in category regular expression '%s'", arg); 2120 return false; 2121 } 2122 } else if (argc != 0) { 2123 result.AppendErrorWithFormat("%s takes 0 or one arg.\n", 2124 m_cmd_name.c_str()); 2125 return false; 2126 } 2127 2128 DataVisualization::Categories::ForEach( 2129 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool { 2130 if (regex) { 2131 bool escape = true; 2132 if (regex->GetText() == category_sp->GetName()) { 2133 escape = false; 2134 } else if (regex->Execute(category_sp->GetName())) { 2135 escape = false; 2136 } 2137 2138 if (escape) 2139 return true; 2140 } 2141 2142 result.GetOutputStream().Printf( 2143 "Category: %s\n", category_sp->GetDescription().c_str()); 2144 2145 return true; 2146 }); 2147 2148 result.SetStatus(eReturnStatusSuccessFinishResult); 2149 return result.Succeeded(); 2150 } 2151 }; 2152 2153 // CommandObjectTypeFilterList 2154 2155 class CommandObjectTypeFilterList 2156 : public CommandObjectTypeFormatterList<TypeFilterImpl> { 2157 public: 2158 CommandObjectTypeFilterList(CommandInterpreter &interpreter) 2159 : CommandObjectTypeFormatterList(interpreter, "type filter list", 2160 "Show a list of current filters.") {} 2161 }; 2162 2163 #if LLDB_ENABLE_PYTHON 2164 2165 // CommandObjectTypeSynthList 2166 2167 class CommandObjectTypeSynthList 2168 : public CommandObjectTypeFormatterList<SyntheticChildren> { 2169 public: 2170 CommandObjectTypeSynthList(CommandInterpreter &interpreter) 2171 : CommandObjectTypeFormatterList( 2172 interpreter, "type synthetic list", 2173 "Show a list of current synthetic providers.") {} 2174 }; 2175 2176 #endif 2177 2178 // CommandObjectTypeFilterDelete 2179 2180 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { 2181 public: 2182 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) 2183 : CommandObjectTypeFormatterDelete( 2184 interpreter, 2185 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2186 "type filter delete", "Delete an existing filter for a type.") {} 2187 2188 ~CommandObjectTypeFilterDelete() override = default; 2189 }; 2190 2191 #if LLDB_ENABLE_PYTHON 2192 2193 // CommandObjectTypeSynthDelete 2194 2195 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { 2196 public: 2197 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) 2198 : CommandObjectTypeFormatterDelete( 2199 interpreter, 2200 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2201 "type synthetic delete", 2202 "Delete an existing synthetic provider for a type.") {} 2203 2204 ~CommandObjectTypeSynthDelete() override = default; 2205 }; 2206 2207 #endif 2208 2209 // CommandObjectTypeFilterClear 2210 2211 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { 2212 public: 2213 CommandObjectTypeFilterClear(CommandInterpreter &interpreter) 2214 : CommandObjectTypeFormatterClear( 2215 interpreter, 2216 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2217 "type filter clear", "Delete all existing filter.") {} 2218 }; 2219 2220 #if LLDB_ENABLE_PYTHON 2221 // CommandObjectTypeSynthClear 2222 2223 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { 2224 public: 2225 CommandObjectTypeSynthClear(CommandInterpreter &interpreter) 2226 : CommandObjectTypeFormatterClear( 2227 interpreter, 2228 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2229 "type synthetic clear", 2230 "Delete all existing synthetic providers.") {} 2231 }; 2232 2233 bool CommandObjectTypeSynthAdd::Execute_HandwritePython( 2234 Args &command, CommandReturnObject &result) { 2235 auto options = std::make_unique<SynthAddOptions>( 2236 m_options.m_skip_pointers, m_options.m_skip_references, 2237 m_options.m_cascade, m_options.m_regex, m_options.m_category); 2238 2239 for (auto &entry : command.entries()) { 2240 if (entry.ref().empty()) { 2241 result.AppendError("empty typenames not allowed"); 2242 return false; 2243 } 2244 2245 options->m_target_types << std::string(entry.ref()); 2246 } 2247 2248 m_interpreter.GetPythonCommandsFromIOHandler( 2249 " ", // Prompt 2250 *this, // IOHandlerDelegate 2251 options.release()); // Baton for the "io_handler" that will be passed back 2252 // into our IOHandlerDelegate functions 2253 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2254 return result.Succeeded(); 2255 } 2256 2257 bool CommandObjectTypeSynthAdd::Execute_PythonClass( 2258 Args &command, CommandReturnObject &result) { 2259 const size_t argc = command.GetArgumentCount(); 2260 2261 if (argc < 1) { 2262 result.AppendErrorWithFormat("%s takes one or more args.\n", 2263 m_cmd_name.c_str()); 2264 return false; 2265 } 2266 2267 if (m_options.m_class_name.empty() && !m_options.m_input_python) { 2268 result.AppendErrorWithFormat("%s needs either a Python class name or -P to " 2269 "directly input Python code.\n", 2270 m_cmd_name.c_str()); 2271 return false; 2272 } 2273 2274 SyntheticChildrenSP entry; 2275 2276 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren( 2277 SyntheticChildren::Flags() 2278 .SetCascades(m_options.m_cascade) 2279 .SetSkipPointers(m_options.m_skip_pointers) 2280 .SetSkipReferences(m_options.m_skip_references), 2281 m_options.m_class_name.c_str()); 2282 2283 entry.reset(impl); 2284 2285 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2286 2287 if (interpreter && 2288 !interpreter->CheckObjectExists(impl->GetPythonClassName())) 2289 result.AppendWarning("The provided class does not exist - please define it " 2290 "before attempting to use this synthetic provider"); 2291 2292 // now I have a valid provider, let's add it to every type 2293 2294 lldb::TypeCategoryImplSP category; 2295 DataVisualization::Categories::GetCategory( 2296 ConstString(m_options.m_category.c_str()), category); 2297 2298 Status error; 2299 2300 for (auto &arg_entry : command.entries()) { 2301 if (arg_entry.ref().empty()) { 2302 result.AppendError("empty typenames not allowed"); 2303 return false; 2304 } 2305 2306 ConstString typeCS(arg_entry.ref()); 2307 if (!AddSynth(typeCS, entry, 2308 m_options.m_regex ? eRegexSynth : eRegularSynth, 2309 m_options.m_category, &error)) { 2310 result.AppendError(error.AsCString()); 2311 return false; 2312 } 2313 } 2314 2315 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2316 return result.Succeeded(); 2317 } 2318 2319 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd( 2320 CommandInterpreter &interpreter) 2321 : CommandObjectParsed(interpreter, "type synthetic add", 2322 "Add a new synthetic provider for a type.", nullptr), 2323 IOHandlerDelegateMultiline("DONE"), m_options() { 2324 CommandArgumentEntry type_arg; 2325 CommandArgumentData type_style_arg; 2326 2327 type_style_arg.arg_type = eArgTypeName; 2328 type_style_arg.arg_repetition = eArgRepeatPlus; 2329 2330 type_arg.push_back(type_style_arg); 2331 2332 m_arguments.push_back(type_arg); 2333 } 2334 2335 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 2336 SyntheticChildrenSP entry, 2337 SynthFormatType type, 2338 std::string category_name, 2339 Status *error) { 2340 lldb::TypeCategoryImplSP category; 2341 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 2342 category); 2343 2344 if (type == eRegularSynth) { 2345 if (FixArrayTypeNameWithRegex(type_name)) 2346 type = eRegexSynth; 2347 } 2348 2349 if (category->AnyMatches( 2350 type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2351 false)) { 2352 if (error) 2353 error->SetErrorStringWithFormat("cannot add synthetic for type %s when " 2354 "filter is defined in same category!", 2355 type_name.AsCString()); 2356 return false; 2357 } 2358 2359 if (type == eRegexSynth) { 2360 RegularExpression typeRX(type_name.GetStringRef()); 2361 if (!typeRX.IsValid()) { 2362 if (error) 2363 error->SetErrorString( 2364 "regex format error (maybe this is not really a regex?)"); 2365 return false; 2366 } 2367 2368 category->GetRegexTypeSyntheticsContainer()->Delete(type_name); 2369 category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry); 2370 2371 return true; 2372 } else { 2373 category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry); 2374 return true; 2375 } 2376 } 2377 2378 #endif 2379 #define LLDB_OPTIONS_type_filter_add 2380 #include "CommandOptions.inc" 2381 2382 class CommandObjectTypeFilterAdd : public CommandObjectParsed { 2383 private: 2384 class CommandOptions : public Options { 2385 typedef std::vector<std::string> option_vector; 2386 2387 public: 2388 CommandOptions() = default; 2389 2390 ~CommandOptions() override = default; 2391 2392 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2393 ExecutionContext *execution_context) override { 2394 Status error; 2395 const int short_option = m_getopt_table[option_idx].val; 2396 bool success; 2397 2398 switch (short_option) { 2399 case 'C': 2400 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success); 2401 if (!success) 2402 error.SetErrorStringWithFormat("invalid value for cascade: %s", 2403 option_arg.str().c_str()); 2404 break; 2405 case 'c': 2406 m_expr_paths.push_back(std::string(option_arg)); 2407 has_child_list = true; 2408 break; 2409 case 'p': 2410 m_skip_pointers = true; 2411 break; 2412 case 'r': 2413 m_skip_references = true; 2414 break; 2415 case 'w': 2416 m_category = std::string(option_arg); 2417 break; 2418 case 'x': 2419 m_regex = true; 2420 break; 2421 default: 2422 llvm_unreachable("Unimplemented option"); 2423 } 2424 2425 return error; 2426 } 2427 2428 void OptionParsingStarting(ExecutionContext *execution_context) override { 2429 m_cascade = true; 2430 m_skip_pointers = false; 2431 m_skip_references = false; 2432 m_category = "default"; 2433 m_expr_paths.clear(); 2434 has_child_list = false; 2435 m_regex = false; 2436 } 2437 2438 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2439 return llvm::makeArrayRef(g_type_filter_add_options); 2440 } 2441 2442 // Instance variables to hold the values for command options. 2443 2444 bool m_cascade; 2445 bool m_skip_references; 2446 bool m_skip_pointers; 2447 bool m_input_python; 2448 option_vector m_expr_paths; 2449 std::string m_category; 2450 bool has_child_list; 2451 bool m_regex; 2452 2453 typedef option_vector::iterator ExpressionPathsIterator; 2454 }; 2455 2456 CommandOptions m_options; 2457 2458 Options *GetOptions() override { return &m_options; } 2459 2460 enum FilterFormatType { eRegularFilter, eRegexFilter }; 2461 2462 bool AddFilter(ConstString type_name, TypeFilterImplSP entry, 2463 FilterFormatType type, std::string category_name, 2464 Status *error) { 2465 lldb::TypeCategoryImplSP category; 2466 DataVisualization::Categories::GetCategory( 2467 ConstString(category_name.c_str()), category); 2468 2469 if (type == eRegularFilter) { 2470 if (FixArrayTypeNameWithRegex(type_name)) 2471 type = eRegexFilter; 2472 } 2473 2474 if (category->AnyMatches( 2475 type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2476 false)) { 2477 if (error) 2478 error->SetErrorStringWithFormat("cannot add filter for type %s when " 2479 "synthetic is defined in same " 2480 "category!", 2481 type_name.AsCString()); 2482 return false; 2483 } 2484 2485 if (type == eRegexFilter) { 2486 RegularExpression typeRX(type_name.GetStringRef()); 2487 if (!typeRX.IsValid()) { 2488 if (error) 2489 error->SetErrorString( 2490 "regex format error (maybe this is not really a regex?)"); 2491 return false; 2492 } 2493 2494 category->GetRegexTypeFiltersContainer()->Delete(type_name); 2495 category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry); 2496 2497 return true; 2498 } else { 2499 category->GetTypeFiltersContainer()->Add(std::move(type_name), entry); 2500 return true; 2501 } 2502 } 2503 2504 public: 2505 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter) 2506 : CommandObjectParsed(interpreter, "type filter add", 2507 "Add a new filter for a type.", nullptr) { 2508 CommandArgumentEntry type_arg; 2509 CommandArgumentData type_style_arg; 2510 2511 type_style_arg.arg_type = eArgTypeName; 2512 type_style_arg.arg_repetition = eArgRepeatPlus; 2513 2514 type_arg.push_back(type_style_arg); 2515 2516 m_arguments.push_back(type_arg); 2517 2518 SetHelpLong( 2519 R"( 2520 The following examples of 'type filter add' refer to this code snippet for context: 2521 2522 class Foo { 2523 int a; 2524 int b; 2525 int c; 2526 int d; 2527 int e; 2528 int f; 2529 int g; 2530 int h; 2531 int i; 2532 } 2533 Foo my_foo; 2534 2535 Adding a simple filter: 2536 2537 (lldb) type filter add --child a --child g Foo 2538 (lldb) frame variable my_foo 2539 2540 )" 2541 "Produces output where only a and g are displayed. Other children of my_foo \ 2542 (b, c, d, e, f, h and i) are available by asking for them explicitly:" 2543 R"( 2544 2545 (lldb) frame variable my_foo.b my_foo.c my_foo.i 2546 2547 )" 2548 "The formatting option --raw on frame variable bypasses the filter, showing \ 2549 all children of my_foo as if no filter was defined:" 2550 R"( 2551 2552 (lldb) frame variable my_foo --raw)"); 2553 } 2554 2555 ~CommandObjectTypeFilterAdd() override = default; 2556 2557 protected: 2558 bool DoExecute(Args &command, CommandReturnObject &result) override { 2559 const size_t argc = command.GetArgumentCount(); 2560 2561 if (argc < 1) { 2562 result.AppendErrorWithFormat("%s takes one or more args.\n", 2563 m_cmd_name.c_str()); 2564 return false; 2565 } 2566 2567 if (m_options.m_expr_paths.empty()) { 2568 result.AppendErrorWithFormat("%s needs one or more children.\n", 2569 m_cmd_name.c_str()); 2570 return false; 2571 } 2572 2573 TypeFilterImplSP entry(new TypeFilterImpl( 2574 SyntheticChildren::Flags() 2575 .SetCascades(m_options.m_cascade) 2576 .SetSkipPointers(m_options.m_skip_pointers) 2577 .SetSkipReferences(m_options.m_skip_references))); 2578 2579 // go through the expression paths 2580 CommandOptions::ExpressionPathsIterator begin, 2581 end = m_options.m_expr_paths.end(); 2582 2583 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 2584 entry->AddExpressionPath(*begin); 2585 2586 // now I have a valid provider, let's add it to every type 2587 2588 lldb::TypeCategoryImplSP category; 2589 DataVisualization::Categories::GetCategory( 2590 ConstString(m_options.m_category.c_str()), category); 2591 2592 Status error; 2593 2594 WarnOnPotentialUnquotedUnsignedType(command, result); 2595 2596 for (auto &arg_entry : command.entries()) { 2597 if (arg_entry.ref().empty()) { 2598 result.AppendError("empty typenames not allowed"); 2599 return false; 2600 } 2601 2602 ConstString typeCS(arg_entry.ref()); 2603 if (!AddFilter(typeCS, entry, 2604 m_options.m_regex ? eRegexFilter : eRegularFilter, 2605 m_options.m_category, &error)) { 2606 result.AppendError(error.AsCString()); 2607 return false; 2608 } 2609 } 2610 2611 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2612 return result.Succeeded(); 2613 } 2614 }; 2615 2616 // "type lookup" 2617 #define LLDB_OPTIONS_type_lookup 2618 #include "CommandOptions.inc" 2619 2620 class CommandObjectTypeLookup : public CommandObjectRaw { 2621 protected: 2622 // this function is allowed to do a more aggressive job at guessing languages 2623 // than the expression parser is comfortable with - so leave the original 2624 // call alone and add one that is specific to type lookup 2625 lldb::LanguageType GuessLanguage(StackFrame *frame) { 2626 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; 2627 2628 if (!frame) 2629 return lang_type; 2630 2631 lang_type = frame->GuessLanguage(); 2632 if (lang_type != lldb::eLanguageTypeUnknown) 2633 return lang_type; 2634 2635 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 2636 if (s) 2637 lang_type = s->GetMangled().GuessLanguage(); 2638 2639 return lang_type; 2640 } 2641 2642 class CommandOptions : public OptionGroup { 2643 public: 2644 CommandOptions() = default; 2645 2646 ~CommandOptions() override = default; 2647 2648 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2649 return llvm::makeArrayRef(g_type_lookup_options); 2650 } 2651 2652 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 2653 ExecutionContext *execution_context) override { 2654 Status error; 2655 2656 const int short_option = g_type_lookup_options[option_idx].short_option; 2657 2658 switch (short_option) { 2659 case 'h': 2660 m_show_help = true; 2661 break; 2662 2663 case 'l': 2664 m_language = Language::GetLanguageTypeFromString(option_value); 2665 break; 2666 2667 default: 2668 llvm_unreachable("Unimplemented option"); 2669 } 2670 2671 return error; 2672 } 2673 2674 void OptionParsingStarting(ExecutionContext *execution_context) override { 2675 m_show_help = false; 2676 m_language = eLanguageTypeUnknown; 2677 } 2678 2679 // Options table: Required for subclasses of Options. 2680 2681 bool m_show_help = false; 2682 lldb::LanguageType m_language = eLanguageTypeUnknown; 2683 }; 2684 2685 OptionGroupOptions m_option_group; 2686 CommandOptions m_command_options; 2687 2688 public: 2689 CommandObjectTypeLookup(CommandInterpreter &interpreter) 2690 : CommandObjectRaw(interpreter, "type lookup", 2691 "Lookup types and declarations in the current target, " 2692 "following language-specific naming conventions.", 2693 "type lookup <type-specifier>", 2694 eCommandRequiresTarget) { 2695 m_option_group.Append(&m_command_options); 2696 m_option_group.Finalize(); 2697 } 2698 2699 ~CommandObjectTypeLookup() override = default; 2700 2701 Options *GetOptions() override { return &m_option_group; } 2702 2703 llvm::StringRef GetHelpLong() override { 2704 if (!m_cmd_help_long.empty()) 2705 return m_cmd_help_long; 2706 2707 StreamString stream; 2708 Language::ForEach([&](Language *lang) { 2709 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp()) 2710 stream.Printf("%s\n", help); 2711 return true; 2712 }); 2713 2714 m_cmd_help_long = std::string(stream.GetString()); 2715 return m_cmd_help_long; 2716 } 2717 2718 bool DoExecute(llvm::StringRef raw_command_line, 2719 CommandReturnObject &result) override { 2720 if (raw_command_line.empty()) { 2721 result.AppendError( 2722 "type lookup cannot be invoked without a type name as argument"); 2723 return false; 2724 } 2725 2726 auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 2727 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 2728 2729 OptionsWithRaw args(raw_command_line); 2730 const char *name_of_type = args.GetRawPart().c_str(); 2731 2732 if (args.HasArgs()) 2733 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 2734 exe_ctx)) 2735 return false; 2736 2737 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 2738 2739 bool any_found = false; 2740 2741 std::vector<Language *> languages; 2742 2743 bool is_global_search = false; 2744 LanguageType guessed_language = lldb::eLanguageTypeUnknown; 2745 2746 if ((is_global_search = 2747 (m_command_options.m_language == eLanguageTypeUnknown))) { 2748 Language::ForEach([&](Language *lang) { 2749 languages.push_back(lang); 2750 return true; 2751 }); 2752 } else { 2753 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 2754 } 2755 2756 // This is not the most efficient way to do this, but we support very few 2757 // languages so the cost of the sort is going to be dwarfed by the actual 2758 // lookup anyway 2759 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { 2760 guessed_language = GuessLanguage(frame); 2761 if (guessed_language != eLanguageTypeUnknown) { 2762 llvm::sort( 2763 languages.begin(), languages.end(), 2764 [guessed_language](Language *lang1, Language *lang2) -> bool { 2765 if (!lang1 || !lang2) 2766 return false; 2767 LanguageType lt1 = lang1->GetLanguageType(); 2768 LanguageType lt2 = lang2->GetLanguageType(); 2769 if (lt1 == guessed_language) 2770 return true; // make the selected frame's language come first 2771 if (lt2 == guessed_language) 2772 return false; // make the selected frame's language come first 2773 return (lt1 < lt2); // normal comparison otherwise 2774 }); 2775 } 2776 } 2777 2778 bool is_first_language = true; 2779 2780 for (Language *language : languages) { 2781 if (!language) 2782 continue; 2783 2784 if (auto scavenger = language->GetTypeScavenger()) { 2785 Language::TypeScavenger::ResultSet search_results; 2786 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) { 2787 for (const auto &search_result : search_results) { 2788 if (search_result && search_result->IsValid()) { 2789 any_found = true; 2790 search_result->DumpToStream(result.GetOutputStream(), 2791 this->m_command_options.m_show_help); 2792 } 2793 } 2794 } 2795 } 2796 // this is "type lookup SomeName" and we did find a match, so get out 2797 if (any_found && is_global_search) 2798 break; 2799 else if (is_first_language && is_global_search && 2800 guessed_language != lldb::eLanguageTypeUnknown) { 2801 is_first_language = false; 2802 result.GetOutputStream().Printf( 2803 "no type was found in the current language %s matching '%s'; " 2804 "performing a global search across all languages\n", 2805 Language::GetNameForLanguageType(guessed_language), name_of_type); 2806 } 2807 } 2808 2809 if (!any_found) 2810 result.AppendMessageWithFormat("no type was found matching '%s'\n", 2811 name_of_type); 2812 2813 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult 2814 : lldb::eReturnStatusSuccessFinishNoResult); 2815 return true; 2816 } 2817 }; 2818 2819 template <typename FormatterType> 2820 class CommandObjectFormatterInfo : public CommandObjectRaw { 2821 public: 2822 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)> 2823 DiscoveryFunction; 2824 CommandObjectFormatterInfo(CommandInterpreter &interpreter, 2825 const char *formatter_name, 2826 DiscoveryFunction discovery_func) 2827 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame), 2828 m_formatter_name(formatter_name ? formatter_name : ""), 2829 m_discovery_function(discovery_func) { 2830 StreamString name; 2831 name.Printf("type %s info", formatter_name); 2832 SetCommandName(name.GetString()); 2833 StreamString help; 2834 help.Printf("This command evaluates the provided expression and shows " 2835 "which %s is applied to the resulting value (if any).", 2836 formatter_name); 2837 SetHelp(help.GetString()); 2838 StreamString syntax; 2839 syntax.Printf("type %s info <expr>", formatter_name); 2840 SetSyntax(syntax.GetString()); 2841 } 2842 2843 ~CommandObjectFormatterInfo() override = default; 2844 2845 protected: 2846 bool DoExecute(llvm::StringRef command, 2847 CommandReturnObject &result) override { 2848 TargetSP target_sp = GetDebugger().GetSelectedTarget(); 2849 Thread *thread = GetDefaultThread(); 2850 if (!thread) { 2851 result.AppendError("no default thread"); 2852 return false; 2853 } 2854 2855 StackFrameSP frame_sp = thread->GetSelectedFrame(); 2856 ValueObjectSP result_valobj_sp; 2857 EvaluateExpressionOptions options; 2858 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( 2859 command, frame_sp.get(), result_valobj_sp, options); 2860 if (expr_result == eExpressionCompleted && result_valobj_sp) { 2861 result_valobj_sp = 2862 result_valobj_sp->GetQualifiedRepresentationIfAvailable( 2863 target_sp->GetPreferDynamicValue(), 2864 target_sp->GetEnableSyntheticValue()); 2865 typename FormatterType::SharedPointer formatter_sp = 2866 m_discovery_function(*result_valobj_sp); 2867 if (formatter_sp) { 2868 std::string description(formatter_sp->GetDescription()); 2869 result.GetOutputStream() 2870 << m_formatter_name << " applied to (" 2871 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2872 << ") " << command << " is: " << description << "\n"; 2873 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 2874 } else { 2875 result.GetOutputStream() 2876 << "no " << m_formatter_name << " applies to (" 2877 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2878 << ") " << command << "\n"; 2879 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 2880 } 2881 return true; 2882 } else { 2883 result.AppendError("failed to evaluate expression"); 2884 return false; 2885 } 2886 } 2887 2888 private: 2889 std::string m_formatter_name; 2890 DiscoveryFunction m_discovery_function; 2891 }; 2892 2893 class CommandObjectTypeFormat : public CommandObjectMultiword { 2894 public: 2895 CommandObjectTypeFormat(CommandInterpreter &interpreter) 2896 : CommandObjectMultiword( 2897 interpreter, "type format", 2898 "Commands for customizing value display formats.", 2899 "type format [<sub-command-options>] ") { 2900 LoadSubCommand( 2901 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter))); 2902 LoadSubCommand("clear", CommandObjectSP( 2903 new CommandObjectTypeFormatClear(interpreter))); 2904 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete( 2905 interpreter))); 2906 LoadSubCommand( 2907 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter))); 2908 LoadSubCommand( 2909 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>( 2910 interpreter, "format", 2911 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer { 2912 return valobj.GetValueFormat(); 2913 }))); 2914 } 2915 2916 ~CommandObjectTypeFormat() override = default; 2917 }; 2918 2919 #if LLDB_ENABLE_PYTHON 2920 2921 class CommandObjectTypeSynth : public CommandObjectMultiword { 2922 public: 2923 CommandObjectTypeSynth(CommandInterpreter &interpreter) 2924 : CommandObjectMultiword( 2925 interpreter, "type synthetic", 2926 "Commands for operating on synthetic type representations.", 2927 "type synthetic [<sub-command-options>] ") { 2928 LoadSubCommand("add", 2929 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter))); 2930 LoadSubCommand( 2931 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter))); 2932 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete( 2933 interpreter))); 2934 LoadSubCommand( 2935 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter))); 2936 LoadSubCommand( 2937 "info", 2938 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>( 2939 interpreter, "synthetic", 2940 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer { 2941 return valobj.GetSyntheticChildren(); 2942 }))); 2943 } 2944 2945 ~CommandObjectTypeSynth() override = default; 2946 }; 2947 2948 #endif 2949 2950 class CommandObjectTypeFilter : public CommandObjectMultiword { 2951 public: 2952 CommandObjectTypeFilter(CommandInterpreter &interpreter) 2953 : CommandObjectMultiword(interpreter, "type filter", 2954 "Commands for operating on type filters.", 2955 "type filter [<sub-command-options>] ") { 2956 LoadSubCommand( 2957 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter))); 2958 LoadSubCommand("clear", CommandObjectSP( 2959 new CommandObjectTypeFilterClear(interpreter))); 2960 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete( 2961 interpreter))); 2962 LoadSubCommand( 2963 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter))); 2964 } 2965 2966 ~CommandObjectTypeFilter() override = default; 2967 }; 2968 2969 class CommandObjectTypeCategory : public CommandObjectMultiword { 2970 public: 2971 CommandObjectTypeCategory(CommandInterpreter &interpreter) 2972 : CommandObjectMultiword(interpreter, "type category", 2973 "Commands for operating on type categories.", 2974 "type category [<sub-command-options>] ") { 2975 LoadSubCommand( 2976 "define", 2977 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter))); 2978 LoadSubCommand( 2979 "enable", 2980 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter))); 2981 LoadSubCommand( 2982 "disable", 2983 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter))); 2984 LoadSubCommand( 2985 "delete", 2986 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter))); 2987 LoadSubCommand("list", CommandObjectSP( 2988 new CommandObjectTypeCategoryList(interpreter))); 2989 } 2990 2991 ~CommandObjectTypeCategory() override = default; 2992 }; 2993 2994 class CommandObjectTypeSummary : public CommandObjectMultiword { 2995 public: 2996 CommandObjectTypeSummary(CommandInterpreter &interpreter) 2997 : CommandObjectMultiword( 2998 interpreter, "type summary", 2999 "Commands for editing variable summary display options.", 3000 "type summary [<sub-command-options>] ") { 3001 LoadSubCommand( 3002 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter))); 3003 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear( 3004 interpreter))); 3005 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete( 3006 interpreter))); 3007 LoadSubCommand( 3008 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter))); 3009 LoadSubCommand( 3010 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>( 3011 interpreter, "summary", 3012 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer { 3013 return valobj.GetSummaryFormat(); 3014 }))); 3015 } 3016 3017 ~CommandObjectTypeSummary() override = default; 3018 }; 3019 3020 // CommandObjectType 3021 3022 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) 3023 : CommandObjectMultiword(interpreter, "type", 3024 "Commands for operating on the type system.", 3025 "type [<sub-command-options>]") { 3026 LoadSubCommand("category", 3027 CommandObjectSP(new CommandObjectTypeCategory(interpreter))); 3028 LoadSubCommand("filter", 3029 CommandObjectSP(new CommandObjectTypeFilter(interpreter))); 3030 LoadSubCommand("format", 3031 CommandObjectSP(new CommandObjectTypeFormat(interpreter))); 3032 LoadSubCommand("summary", 3033 CommandObjectSP(new CommandObjectTypeSummary(interpreter))); 3034 #if LLDB_ENABLE_PYTHON 3035 LoadSubCommand("synthetic", 3036 CommandObjectSP(new CommandObjectTypeSynth(interpreter))); 3037 #endif 3038 LoadSubCommand("lookup", 3039 CommandObjectSP(new CommandObjectTypeLookup(interpreter))); 3040 } 3041 3042 CommandObjectType::~CommandObjectType() = default; 3043