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