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