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