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