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 void 1773 HandleArgumentCompletion(CompletionRequest &request, 1774 OptionElementVector &opt_element_vector) override { 1775 CommandCompletions::InvokeCommonCompletionCallbacks( 1776 GetCommandInterpreter(), 1777 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1778 } 1779 1780 protected: 1781 bool DoExecute(Args &command, CommandReturnObject &result) override { 1782 const size_t argc = command.GetArgumentCount(); 1783 1784 if (argc < 1) { 1785 result.AppendErrorWithFormat("%s takes 1 or more args.\n", 1786 m_cmd_name.c_str()); 1787 result.SetStatus(eReturnStatusFailed); 1788 return false; 1789 } 1790 1791 for (auto &entry : command.entries()) { 1792 TypeCategoryImplSP category_sp; 1793 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), 1794 category_sp) && 1795 category_sp) { 1796 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 1797 if (m_options.m_define_enabled.GetCurrentValue()) 1798 DataVisualization::Categories::Enable(category_sp, 1799 TypeCategoryMap::Default); 1800 } 1801 } 1802 1803 result.SetStatus(eReturnStatusSuccessFinishResult); 1804 return result.Succeeded(); 1805 } 1806 }; 1807 1808 // CommandObjectTypeCategoryEnable 1809 #define LLDB_OPTIONS_type_category_enable 1810 #include "CommandOptions.inc" 1811 1812 class CommandObjectTypeCategoryEnable : public CommandObjectParsed { 1813 class CommandOptions : public Options { 1814 public: 1815 CommandOptions() : Options() {} 1816 1817 ~CommandOptions() override = default; 1818 1819 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1820 ExecutionContext *execution_context) override { 1821 Status error; 1822 const int short_option = m_getopt_table[option_idx].val; 1823 1824 switch (short_option) { 1825 case 'l': 1826 if (!option_arg.empty()) { 1827 m_language = Language::GetLanguageTypeFromString(option_arg); 1828 if (m_language == lldb::eLanguageTypeUnknown) 1829 error.SetErrorStringWithFormat("unrecognized language '%s'", 1830 option_arg.str().c_str()); 1831 } 1832 break; 1833 default: 1834 llvm_unreachable("Unimplemented option"); 1835 } 1836 1837 return error; 1838 } 1839 1840 void OptionParsingStarting(ExecutionContext *execution_context) override { 1841 m_language = lldb::eLanguageTypeUnknown; 1842 } 1843 1844 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1845 return llvm::makeArrayRef(g_type_category_enable_options); 1846 } 1847 1848 // Instance variables to hold the values for command options. 1849 1850 lldb::LanguageType m_language; 1851 }; 1852 1853 CommandOptions m_options; 1854 1855 Options *GetOptions() override { return &m_options; } 1856 1857 public: 1858 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter) 1859 : CommandObjectParsed(interpreter, "type category enable", 1860 "Enable a category as a source of formatters.", 1861 nullptr), 1862 m_options() { 1863 CommandArgumentEntry type_arg; 1864 CommandArgumentData type_style_arg; 1865 1866 type_style_arg.arg_type = eArgTypeName; 1867 type_style_arg.arg_repetition = eArgRepeatPlus; 1868 1869 type_arg.push_back(type_style_arg); 1870 1871 m_arguments.push_back(type_arg); 1872 } 1873 1874 ~CommandObjectTypeCategoryEnable() override = default; 1875 1876 void 1877 HandleArgumentCompletion(CompletionRequest &request, 1878 OptionElementVector &opt_element_vector) override { 1879 CommandCompletions::InvokeCommonCompletionCallbacks( 1880 GetCommandInterpreter(), 1881 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1882 } 1883 1884 protected: 1885 bool DoExecute(Args &command, CommandReturnObject &result) override { 1886 const size_t argc = command.GetArgumentCount(); 1887 1888 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 1889 result.AppendErrorWithFormat("%s takes arguments and/or a language", 1890 m_cmd_name.c_str()); 1891 result.SetStatus(eReturnStatusFailed); 1892 return false; 1893 } 1894 1895 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 1896 DataVisualization::Categories::EnableStar(); 1897 } else if (argc > 0) { 1898 for (int i = argc - 1; i >= 0; i--) { 1899 const char *typeA = command.GetArgumentAtIndex(i); 1900 ConstString typeCS(typeA); 1901 1902 if (!typeCS) { 1903 result.AppendError("empty category name not allowed"); 1904 result.SetStatus(eReturnStatusFailed); 1905 return false; 1906 } 1907 DataVisualization::Categories::Enable(typeCS); 1908 lldb::TypeCategoryImplSP cate; 1909 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) { 1910 if (cate->GetCount() == 0) { 1911 result.AppendWarning("empty category enabled (typo?)"); 1912 } 1913 } 1914 } 1915 } 1916 1917 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1918 DataVisualization::Categories::Enable(m_options.m_language); 1919 1920 result.SetStatus(eReturnStatusSuccessFinishResult); 1921 return result.Succeeded(); 1922 } 1923 }; 1924 1925 // CommandObjectTypeCategoryDelete 1926 1927 class CommandObjectTypeCategoryDelete : public CommandObjectParsed { 1928 public: 1929 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter) 1930 : CommandObjectParsed(interpreter, "type category delete", 1931 "Delete a category and all associated formatters.", 1932 nullptr) { 1933 CommandArgumentEntry type_arg; 1934 CommandArgumentData type_style_arg; 1935 1936 type_style_arg.arg_type = eArgTypeName; 1937 type_style_arg.arg_repetition = eArgRepeatPlus; 1938 1939 type_arg.push_back(type_style_arg); 1940 1941 m_arguments.push_back(type_arg); 1942 } 1943 1944 ~CommandObjectTypeCategoryDelete() override = default; 1945 1946 void 1947 HandleArgumentCompletion(CompletionRequest &request, 1948 OptionElementVector &opt_element_vector) override { 1949 CommandCompletions::InvokeCommonCompletionCallbacks( 1950 GetCommandInterpreter(), 1951 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1952 } 1953 1954 protected: 1955 bool DoExecute(Args &command, CommandReturnObject &result) override { 1956 const size_t argc = command.GetArgumentCount(); 1957 1958 if (argc < 1) { 1959 result.AppendErrorWithFormat("%s takes 1 or more arg.\n", 1960 m_cmd_name.c_str()); 1961 result.SetStatus(eReturnStatusFailed); 1962 return false; 1963 } 1964 1965 bool success = true; 1966 1967 // the order is not relevant here 1968 for (int i = argc - 1; i >= 0; i--) { 1969 const char *typeA = command.GetArgumentAtIndex(i); 1970 ConstString typeCS(typeA); 1971 1972 if (!typeCS) { 1973 result.AppendError("empty category name not allowed"); 1974 result.SetStatus(eReturnStatusFailed); 1975 return false; 1976 } 1977 if (!DataVisualization::Categories::Delete(typeCS)) 1978 success = false; // keep deleting even if we hit an error 1979 } 1980 if (success) { 1981 result.SetStatus(eReturnStatusSuccessFinishResult); 1982 return result.Succeeded(); 1983 } else { 1984 result.AppendError("cannot delete one or more categories\n"); 1985 result.SetStatus(eReturnStatusFailed); 1986 return false; 1987 } 1988 } 1989 }; 1990 1991 // CommandObjectTypeCategoryDisable 1992 #define LLDB_OPTIONS_type_category_disable 1993 #include "CommandOptions.inc" 1994 1995 class CommandObjectTypeCategoryDisable : public CommandObjectParsed { 1996 class CommandOptions : public Options { 1997 public: 1998 CommandOptions() : Options() {} 1999 2000 ~CommandOptions() override = default; 2001 2002 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2003 ExecutionContext *execution_context) override { 2004 Status error; 2005 const int short_option = m_getopt_table[option_idx].val; 2006 2007 switch (short_option) { 2008 case 'l': 2009 if (!option_arg.empty()) { 2010 m_language = Language::GetLanguageTypeFromString(option_arg); 2011 if (m_language == lldb::eLanguageTypeUnknown) 2012 error.SetErrorStringWithFormat("unrecognized language '%s'", 2013 option_arg.str().c_str()); 2014 } 2015 break; 2016 default: 2017 llvm_unreachable("Unimplemented option"); 2018 } 2019 2020 return error; 2021 } 2022 2023 void OptionParsingStarting(ExecutionContext *execution_context) override { 2024 m_language = lldb::eLanguageTypeUnknown; 2025 } 2026 2027 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2028 return llvm::makeArrayRef(g_type_category_disable_options); 2029 } 2030 2031 // Instance variables to hold the values for command options. 2032 2033 lldb::LanguageType m_language; 2034 }; 2035 2036 CommandOptions m_options; 2037 2038 Options *GetOptions() override { return &m_options; } 2039 2040 public: 2041 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter) 2042 : CommandObjectParsed(interpreter, "type category disable", 2043 "Disable a category as a source of formatters.", 2044 nullptr), 2045 m_options() { 2046 CommandArgumentEntry type_arg; 2047 CommandArgumentData type_style_arg; 2048 2049 type_style_arg.arg_type = eArgTypeName; 2050 type_style_arg.arg_repetition = eArgRepeatPlus; 2051 2052 type_arg.push_back(type_style_arg); 2053 2054 m_arguments.push_back(type_arg); 2055 } 2056 2057 ~CommandObjectTypeCategoryDisable() override = default; 2058 2059 void 2060 HandleArgumentCompletion(CompletionRequest &request, 2061 OptionElementVector &opt_element_vector) override { 2062 CommandCompletions::InvokeCommonCompletionCallbacks( 2063 GetCommandInterpreter(), 2064 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2065 } 2066 2067 protected: 2068 bool DoExecute(Args &command, CommandReturnObject &result) override { 2069 const size_t argc = command.GetArgumentCount(); 2070 2071 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 2072 result.AppendErrorWithFormat("%s takes arguments and/or a language", 2073 m_cmd_name.c_str()); 2074 result.SetStatus(eReturnStatusFailed); 2075 return false; 2076 } 2077 2078 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 2079 DataVisualization::Categories::DisableStar(); 2080 } else if (argc > 0) { 2081 // the order is not relevant here 2082 for (int i = argc - 1; i >= 0; i--) { 2083 const char *typeA = command.GetArgumentAtIndex(i); 2084 ConstString typeCS(typeA); 2085 2086 if (!typeCS) { 2087 result.AppendError("empty category name not allowed"); 2088 result.SetStatus(eReturnStatusFailed); 2089 return false; 2090 } 2091 DataVisualization::Categories::Disable(typeCS); 2092 } 2093 } 2094 2095 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2096 DataVisualization::Categories::Disable(m_options.m_language); 2097 2098 result.SetStatus(eReturnStatusSuccessFinishResult); 2099 return result.Succeeded(); 2100 } 2101 }; 2102 2103 // CommandObjectTypeCategoryList 2104 2105 class CommandObjectTypeCategoryList : public CommandObjectParsed { 2106 public: 2107 CommandObjectTypeCategoryList(CommandInterpreter &interpreter) 2108 : CommandObjectParsed(interpreter, "type category list", 2109 "Provide a list of all existing categories.", 2110 nullptr) { 2111 CommandArgumentEntry type_arg; 2112 CommandArgumentData type_style_arg; 2113 2114 type_style_arg.arg_type = eArgTypeName; 2115 type_style_arg.arg_repetition = eArgRepeatOptional; 2116 2117 type_arg.push_back(type_style_arg); 2118 2119 m_arguments.push_back(type_arg); 2120 } 2121 2122 ~CommandObjectTypeCategoryList() override = default; 2123 2124 void 2125 HandleArgumentCompletion(CompletionRequest &request, 2126 OptionElementVector &opt_element_vector) override { 2127 if (request.GetCursorIndex()) 2128 return; 2129 CommandCompletions::InvokeCommonCompletionCallbacks( 2130 GetCommandInterpreter(), 2131 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2132 } 2133 2134 protected: 2135 bool DoExecute(Args &command, CommandReturnObject &result) override { 2136 const size_t argc = command.GetArgumentCount(); 2137 2138 std::unique_ptr<RegularExpression> regex; 2139 2140 if (argc == 1) { 2141 const char *arg = command.GetArgumentAtIndex(0); 2142 regex = std::make_unique<RegularExpression>( 2143 llvm::StringRef::withNullAsEmpty(arg)); 2144 if (!regex->IsValid()) { 2145 result.AppendErrorWithFormat( 2146 "syntax error in category regular expression '%s'", arg); 2147 result.SetStatus(eReturnStatusFailed); 2148 return false; 2149 } 2150 } else if (argc != 0) { 2151 result.AppendErrorWithFormat("%s takes 0 or one arg.\n", 2152 m_cmd_name.c_str()); 2153 result.SetStatus(eReturnStatusFailed); 2154 return false; 2155 } 2156 2157 DataVisualization::Categories::ForEach( 2158 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool { 2159 if (regex) { 2160 bool escape = true; 2161 if (regex->GetText() == category_sp->GetName()) { 2162 escape = false; 2163 } else if (regex->Execute(llvm::StringRef::withNullAsEmpty( 2164 category_sp->GetName()))) { 2165 escape = false; 2166 } 2167 2168 if (escape) 2169 return true; 2170 } 2171 2172 result.GetOutputStream().Printf( 2173 "Category: %s\n", category_sp->GetDescription().c_str()); 2174 2175 return true; 2176 }); 2177 2178 result.SetStatus(eReturnStatusSuccessFinishResult); 2179 return result.Succeeded(); 2180 } 2181 }; 2182 2183 // CommandObjectTypeFilterList 2184 2185 class CommandObjectTypeFilterList 2186 : public CommandObjectTypeFormatterList<TypeFilterImpl> { 2187 public: 2188 CommandObjectTypeFilterList(CommandInterpreter &interpreter) 2189 : CommandObjectTypeFormatterList(interpreter, "type filter list", 2190 "Show a list of current filters.") {} 2191 }; 2192 2193 #if LLDB_ENABLE_PYTHON 2194 2195 // CommandObjectTypeSynthList 2196 2197 class CommandObjectTypeSynthList 2198 : public CommandObjectTypeFormatterList<SyntheticChildren> { 2199 public: 2200 CommandObjectTypeSynthList(CommandInterpreter &interpreter) 2201 : CommandObjectTypeFormatterList( 2202 interpreter, "type synthetic list", 2203 "Show a list of current synthetic providers.") {} 2204 }; 2205 2206 #endif 2207 2208 // CommandObjectTypeFilterDelete 2209 2210 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { 2211 public: 2212 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) 2213 : CommandObjectTypeFormatterDelete( 2214 interpreter, 2215 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2216 "type filter delete", "Delete an existing filter for a type.") {} 2217 2218 ~CommandObjectTypeFilterDelete() override = default; 2219 }; 2220 2221 #if LLDB_ENABLE_PYTHON 2222 2223 // CommandObjectTypeSynthDelete 2224 2225 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { 2226 public: 2227 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) 2228 : CommandObjectTypeFormatterDelete( 2229 interpreter, 2230 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2231 "type synthetic delete", 2232 "Delete an existing synthetic provider for a type.") {} 2233 2234 ~CommandObjectTypeSynthDelete() override = default; 2235 }; 2236 2237 #endif 2238 2239 // CommandObjectTypeFilterClear 2240 2241 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { 2242 public: 2243 CommandObjectTypeFilterClear(CommandInterpreter &interpreter) 2244 : CommandObjectTypeFormatterClear( 2245 interpreter, 2246 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2247 "type filter clear", "Delete all existing filter.") {} 2248 }; 2249 2250 #if LLDB_ENABLE_PYTHON 2251 // CommandObjectTypeSynthClear 2252 2253 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { 2254 public: 2255 CommandObjectTypeSynthClear(CommandInterpreter &interpreter) 2256 : CommandObjectTypeFormatterClear( 2257 interpreter, 2258 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2259 "type synthetic clear", 2260 "Delete all existing synthetic providers.") {} 2261 }; 2262 2263 bool CommandObjectTypeSynthAdd::Execute_HandwritePython( 2264 Args &command, CommandReturnObject &result) { 2265 SynthAddOptions *options = new SynthAddOptions( 2266 m_options.m_skip_pointers, m_options.m_skip_references, 2267 m_options.m_cascade, m_options.m_regex, m_options.m_category); 2268 2269 for (auto &entry : command.entries()) { 2270 if (entry.ref().empty()) { 2271 result.AppendError("empty typenames not allowed"); 2272 result.SetStatus(eReturnStatusFailed); 2273 return false; 2274 } 2275 2276 options->m_target_types << std::string(entry.ref()); 2277 } 2278 2279 m_interpreter.GetPythonCommandsFromIOHandler( 2280 " ", // Prompt 2281 *this, // IOHandlerDelegate 2282 options); // Baton for the "io_handler" that will be passed back into our 2283 // IOHandlerDelegate functions 2284 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2285 return result.Succeeded(); 2286 } 2287 2288 bool CommandObjectTypeSynthAdd::Execute_PythonClass( 2289 Args &command, CommandReturnObject &result) { 2290 const size_t argc = command.GetArgumentCount(); 2291 2292 if (argc < 1) { 2293 result.AppendErrorWithFormat("%s takes one or more args.\n", 2294 m_cmd_name.c_str()); 2295 result.SetStatus(eReturnStatusFailed); 2296 return false; 2297 } 2298 2299 if (m_options.m_class_name.empty() && !m_options.m_input_python) { 2300 result.AppendErrorWithFormat("%s needs either a Python class name or -P to " 2301 "directly input Python code.\n", 2302 m_cmd_name.c_str()); 2303 result.SetStatus(eReturnStatusFailed); 2304 return false; 2305 } 2306 2307 SyntheticChildrenSP entry; 2308 2309 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren( 2310 SyntheticChildren::Flags() 2311 .SetCascades(m_options.m_cascade) 2312 .SetSkipPointers(m_options.m_skip_pointers) 2313 .SetSkipReferences(m_options.m_skip_references), 2314 m_options.m_class_name.c_str()); 2315 2316 entry.reset(impl); 2317 2318 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2319 2320 if (interpreter && 2321 !interpreter->CheckObjectExists(impl->GetPythonClassName())) 2322 result.AppendWarning("The provided class does not exist - please define it " 2323 "before attempting to use this synthetic provider"); 2324 2325 // now I have a valid provider, let's add it to every type 2326 2327 lldb::TypeCategoryImplSP category; 2328 DataVisualization::Categories::GetCategory( 2329 ConstString(m_options.m_category.c_str()), category); 2330 2331 Status error; 2332 2333 for (auto &arg_entry : command.entries()) { 2334 if (arg_entry.ref().empty()) { 2335 result.AppendError("empty typenames not allowed"); 2336 result.SetStatus(eReturnStatusFailed); 2337 return false; 2338 } 2339 2340 ConstString typeCS(arg_entry.ref()); 2341 if (!AddSynth(typeCS, entry, 2342 m_options.m_regex ? eRegexSynth : eRegularSynth, 2343 m_options.m_category, &error)) { 2344 result.AppendError(error.AsCString()); 2345 result.SetStatus(eReturnStatusFailed); 2346 return false; 2347 } 2348 } 2349 2350 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2351 return result.Succeeded(); 2352 } 2353 2354 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd( 2355 CommandInterpreter &interpreter) 2356 : CommandObjectParsed(interpreter, "type synthetic add", 2357 "Add a new synthetic provider for a type.", nullptr), 2358 IOHandlerDelegateMultiline("DONE"), m_options() { 2359 CommandArgumentEntry type_arg; 2360 CommandArgumentData type_style_arg; 2361 2362 type_style_arg.arg_type = eArgTypeName; 2363 type_style_arg.arg_repetition = eArgRepeatPlus; 2364 2365 type_arg.push_back(type_style_arg); 2366 2367 m_arguments.push_back(type_arg); 2368 } 2369 2370 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 2371 SyntheticChildrenSP entry, 2372 SynthFormatType type, 2373 std::string category_name, 2374 Status *error) { 2375 lldb::TypeCategoryImplSP category; 2376 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 2377 category); 2378 2379 if (type == eRegularSynth) { 2380 if (FixArrayTypeNameWithRegex(type_name)) 2381 type = eRegexSynth; 2382 } 2383 2384 if (category->AnyMatches( 2385 type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2386 false)) { 2387 if (error) 2388 error->SetErrorStringWithFormat("cannot add synthetic for type %s when " 2389 "filter is defined in same category!", 2390 type_name.AsCString()); 2391 return false; 2392 } 2393 2394 if (type == eRegexSynth) { 2395 RegularExpression typeRX(type_name.GetStringRef()); 2396 if (!typeRX.IsValid()) { 2397 if (error) 2398 error->SetErrorString( 2399 "regex format error (maybe this is not really a regex?)"); 2400 return false; 2401 } 2402 2403 category->GetRegexTypeSyntheticsContainer()->Delete(type_name); 2404 category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry); 2405 2406 return true; 2407 } else { 2408 category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry); 2409 return true; 2410 } 2411 } 2412 2413 #endif 2414 #define LLDB_OPTIONS_type_filter_add 2415 #include "CommandOptions.inc" 2416 2417 class CommandObjectTypeFilterAdd : public CommandObjectParsed { 2418 private: 2419 class CommandOptions : public Options { 2420 typedef std::vector<std::string> option_vector; 2421 2422 public: 2423 CommandOptions() : Options() {} 2424 2425 ~CommandOptions() override = default; 2426 2427 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2428 ExecutionContext *execution_context) override { 2429 Status error; 2430 const int short_option = m_getopt_table[option_idx].val; 2431 bool success; 2432 2433 switch (short_option) { 2434 case 'C': 2435 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success); 2436 if (!success) 2437 error.SetErrorStringWithFormat("invalid value for cascade: %s", 2438 option_arg.str().c_str()); 2439 break; 2440 case 'c': 2441 m_expr_paths.push_back(std::string(option_arg)); 2442 has_child_list = true; 2443 break; 2444 case 'p': 2445 m_skip_pointers = true; 2446 break; 2447 case 'r': 2448 m_skip_references = true; 2449 break; 2450 case 'w': 2451 m_category = std::string(option_arg); 2452 break; 2453 case 'x': 2454 m_regex = true; 2455 break; 2456 default: 2457 llvm_unreachable("Unimplemented option"); 2458 } 2459 2460 return error; 2461 } 2462 2463 void OptionParsingStarting(ExecutionContext *execution_context) override { 2464 m_cascade = true; 2465 m_skip_pointers = false; 2466 m_skip_references = false; 2467 m_category = "default"; 2468 m_expr_paths.clear(); 2469 has_child_list = false; 2470 m_regex = false; 2471 } 2472 2473 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2474 return llvm::makeArrayRef(g_type_filter_add_options); 2475 } 2476 2477 // Instance variables to hold the values for command options. 2478 2479 bool m_cascade; 2480 bool m_skip_references; 2481 bool m_skip_pointers; 2482 bool m_input_python; 2483 option_vector m_expr_paths; 2484 std::string m_category; 2485 bool has_child_list; 2486 bool m_regex; 2487 2488 typedef option_vector::iterator ExpressionPathsIterator; 2489 }; 2490 2491 CommandOptions m_options; 2492 2493 Options *GetOptions() override { return &m_options; } 2494 2495 enum FilterFormatType { eRegularFilter, eRegexFilter }; 2496 2497 bool AddFilter(ConstString type_name, TypeFilterImplSP entry, 2498 FilterFormatType type, std::string category_name, 2499 Status *error) { 2500 lldb::TypeCategoryImplSP category; 2501 DataVisualization::Categories::GetCategory( 2502 ConstString(category_name.c_str()), category); 2503 2504 if (type == eRegularFilter) { 2505 if (FixArrayTypeNameWithRegex(type_name)) 2506 type = eRegexFilter; 2507 } 2508 2509 if (category->AnyMatches( 2510 type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2511 false)) { 2512 if (error) 2513 error->SetErrorStringWithFormat("cannot add filter for type %s when " 2514 "synthetic is defined in same " 2515 "category!", 2516 type_name.AsCString()); 2517 return false; 2518 } 2519 2520 if (type == eRegexFilter) { 2521 RegularExpression typeRX(type_name.GetStringRef()); 2522 if (!typeRX.IsValid()) { 2523 if (error) 2524 error->SetErrorString( 2525 "regex format error (maybe this is not really a regex?)"); 2526 return false; 2527 } 2528 2529 category->GetRegexTypeFiltersContainer()->Delete(type_name); 2530 category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry); 2531 2532 return true; 2533 } else { 2534 category->GetTypeFiltersContainer()->Add(std::move(type_name), entry); 2535 return true; 2536 } 2537 } 2538 2539 public: 2540 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter) 2541 : CommandObjectParsed(interpreter, "type filter add", 2542 "Add a new filter for a type.", nullptr), 2543 m_options() { 2544 CommandArgumentEntry type_arg; 2545 CommandArgumentData type_style_arg; 2546 2547 type_style_arg.arg_type = eArgTypeName; 2548 type_style_arg.arg_repetition = eArgRepeatPlus; 2549 2550 type_arg.push_back(type_style_arg); 2551 2552 m_arguments.push_back(type_arg); 2553 2554 SetHelpLong( 2555 R"( 2556 The following examples of 'type filter add' refer to this code snippet for context: 2557 2558 class Foo { 2559 int a; 2560 int b; 2561 int c; 2562 int d; 2563 int e; 2564 int f; 2565 int g; 2566 int h; 2567 int i; 2568 } 2569 Foo my_foo; 2570 2571 Adding a simple filter: 2572 2573 (lldb) type filter add --child a --child g Foo 2574 (lldb) frame variable my_foo 2575 2576 )" 2577 "Produces output where only a and g are displayed. Other children of my_foo \ 2578 (b, c, d, e, f, h and i) are available by asking for them explicitly:" 2579 R"( 2580 2581 (lldb) frame variable my_foo.b my_foo.c my_foo.i 2582 2583 )" 2584 "The formatting option --raw on frame variable bypasses the filter, showing \ 2585 all children of my_foo as if no filter was defined:" 2586 R"( 2587 2588 (lldb) frame variable my_foo --raw)"); 2589 } 2590 2591 ~CommandObjectTypeFilterAdd() override = default; 2592 2593 protected: 2594 bool DoExecute(Args &command, CommandReturnObject &result) override { 2595 const size_t argc = command.GetArgumentCount(); 2596 2597 if (argc < 1) { 2598 result.AppendErrorWithFormat("%s takes one or more args.\n", 2599 m_cmd_name.c_str()); 2600 result.SetStatus(eReturnStatusFailed); 2601 return false; 2602 } 2603 2604 if (m_options.m_expr_paths.empty()) { 2605 result.AppendErrorWithFormat("%s needs one or more children.\n", 2606 m_cmd_name.c_str()); 2607 result.SetStatus(eReturnStatusFailed); 2608 return false; 2609 } 2610 2611 TypeFilterImplSP entry(new TypeFilterImpl( 2612 SyntheticChildren::Flags() 2613 .SetCascades(m_options.m_cascade) 2614 .SetSkipPointers(m_options.m_skip_pointers) 2615 .SetSkipReferences(m_options.m_skip_references))); 2616 2617 // go through the expression paths 2618 CommandOptions::ExpressionPathsIterator begin, 2619 end = m_options.m_expr_paths.end(); 2620 2621 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 2622 entry->AddExpressionPath(*begin); 2623 2624 // now I have a valid provider, let's add it to every type 2625 2626 lldb::TypeCategoryImplSP category; 2627 DataVisualization::Categories::GetCategory( 2628 ConstString(m_options.m_category.c_str()), category); 2629 2630 Status error; 2631 2632 WarnOnPotentialUnquotedUnsignedType(command, result); 2633 2634 for (auto &arg_entry : command.entries()) { 2635 if (arg_entry.ref().empty()) { 2636 result.AppendError("empty typenames not allowed"); 2637 result.SetStatus(eReturnStatusFailed); 2638 return false; 2639 } 2640 2641 ConstString typeCS(arg_entry.ref()); 2642 if (!AddFilter(typeCS, entry, 2643 m_options.m_regex ? eRegexFilter : eRegularFilter, 2644 m_options.m_category, &error)) { 2645 result.AppendError(error.AsCString()); 2646 result.SetStatus(eReturnStatusFailed); 2647 return false; 2648 } 2649 } 2650 2651 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2652 return result.Succeeded(); 2653 } 2654 }; 2655 2656 // "type lookup" 2657 #define LLDB_OPTIONS_type_lookup 2658 #include "CommandOptions.inc" 2659 2660 class CommandObjectTypeLookup : public CommandObjectRaw { 2661 protected: 2662 // this function is allowed to do a more aggressive job at guessing languages 2663 // than the expression parser is comfortable with - so leave the original 2664 // call alone and add one that is specific to type lookup 2665 lldb::LanguageType GuessLanguage(StackFrame *frame) { 2666 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; 2667 2668 if (!frame) 2669 return lang_type; 2670 2671 lang_type = frame->GuessLanguage(); 2672 if (lang_type != lldb::eLanguageTypeUnknown) 2673 return lang_type; 2674 2675 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 2676 if (s) 2677 lang_type = s->GetMangled().GuessLanguage(); 2678 2679 return lang_type; 2680 } 2681 2682 class CommandOptions : public OptionGroup { 2683 public: 2684 CommandOptions() 2685 : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown) {} 2686 2687 ~CommandOptions() override = default; 2688 2689 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2690 return llvm::makeArrayRef(g_type_lookup_options); 2691 } 2692 2693 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 2694 ExecutionContext *execution_context) override { 2695 Status error; 2696 2697 const int short_option = g_type_lookup_options[option_idx].short_option; 2698 2699 switch (short_option) { 2700 case 'h': 2701 m_show_help = true; 2702 break; 2703 2704 case 'l': 2705 m_language = Language::GetLanguageTypeFromString(option_value); 2706 break; 2707 2708 default: 2709 llvm_unreachable("Unimplemented option"); 2710 } 2711 2712 return error; 2713 } 2714 2715 void OptionParsingStarting(ExecutionContext *execution_context) override { 2716 m_show_help = false; 2717 m_language = eLanguageTypeUnknown; 2718 } 2719 2720 // Options table: Required for subclasses of Options. 2721 2722 bool m_show_help; 2723 lldb::LanguageType m_language; 2724 }; 2725 2726 OptionGroupOptions m_option_group; 2727 CommandOptions m_command_options; 2728 2729 public: 2730 CommandObjectTypeLookup(CommandInterpreter &interpreter) 2731 : CommandObjectRaw(interpreter, "type lookup", 2732 "Lookup types and declarations in the current target, " 2733 "following language-specific naming conventions.", 2734 "type lookup <type-specifier>", 2735 eCommandRequiresTarget), 2736 m_option_group(), m_command_options() { 2737 m_option_group.Append(&m_command_options); 2738 m_option_group.Finalize(); 2739 } 2740 2741 ~CommandObjectTypeLookup() override = default; 2742 2743 Options *GetOptions() override { return &m_option_group; } 2744 2745 llvm::StringRef GetHelpLong() override { 2746 if (!m_cmd_help_long.empty()) 2747 return m_cmd_help_long; 2748 2749 StreamString stream; 2750 Language::ForEach([&](Language *lang) { 2751 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp()) 2752 stream.Printf("%s\n", help); 2753 return true; 2754 }); 2755 2756 m_cmd_help_long = std::string(stream.GetString()); 2757 return m_cmd_help_long; 2758 } 2759 2760 bool DoExecute(llvm::StringRef raw_command_line, 2761 CommandReturnObject &result) override { 2762 if (raw_command_line.empty()) { 2763 result.SetError( 2764 "type lookup cannot be invoked without a type name as argument"); 2765 return false; 2766 } 2767 2768 auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 2769 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 2770 2771 OptionsWithRaw args(raw_command_line); 2772 const char *name_of_type = args.GetRawPart().c_str(); 2773 2774 if (args.HasArgs()) 2775 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 2776 exe_ctx)) 2777 return false; 2778 2779 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 2780 2781 bool any_found = false; 2782 2783 std::vector<Language *> languages; 2784 2785 bool is_global_search = false; 2786 LanguageType guessed_language = lldb::eLanguageTypeUnknown; 2787 2788 if ((is_global_search = 2789 (m_command_options.m_language == eLanguageTypeUnknown))) { 2790 Language::ForEach([&](Language *lang) { 2791 languages.push_back(lang); 2792 return true; 2793 }); 2794 } else { 2795 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 2796 } 2797 2798 // This is not the most efficient way to do this, but we support very few 2799 // languages so the cost of the sort is going to be dwarfed by the actual 2800 // lookup anyway 2801 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { 2802 guessed_language = GuessLanguage(frame); 2803 if (guessed_language != eLanguageTypeUnknown) { 2804 llvm::sort( 2805 languages.begin(), languages.end(), 2806 [guessed_language](Language *lang1, Language *lang2) -> bool { 2807 if (!lang1 || !lang2) 2808 return false; 2809 LanguageType lt1 = lang1->GetLanguageType(); 2810 LanguageType lt2 = lang2->GetLanguageType(); 2811 if (lt1 == guessed_language) 2812 return true; // make the selected frame's language come first 2813 if (lt2 == guessed_language) 2814 return false; // make the selected frame's language come first 2815 return (lt1 < lt2); // normal comparison otherwise 2816 }); 2817 } 2818 } 2819 2820 bool is_first_language = true; 2821 2822 for (Language *language : languages) { 2823 if (!language) 2824 continue; 2825 2826 if (auto scavenger = language->GetTypeScavenger()) { 2827 Language::TypeScavenger::ResultSet search_results; 2828 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) { 2829 for (const auto &search_result : search_results) { 2830 if (search_result && search_result->IsValid()) { 2831 any_found = true; 2832 search_result->DumpToStream(result.GetOutputStream(), 2833 this->m_command_options.m_show_help); 2834 } 2835 } 2836 } 2837 } 2838 // this is "type lookup SomeName" and we did find a match, so get out 2839 if (any_found && is_global_search) 2840 break; 2841 else if (is_first_language && is_global_search && 2842 guessed_language != lldb::eLanguageTypeUnknown) { 2843 is_first_language = false; 2844 result.GetOutputStream().Printf( 2845 "no type was found in the current language %s matching '%s'; " 2846 "performing a global search across all languages\n", 2847 Language::GetNameForLanguageType(guessed_language), name_of_type); 2848 } 2849 } 2850 2851 if (!any_found) 2852 result.AppendMessageWithFormat("no type was found matching '%s'\n", 2853 name_of_type); 2854 2855 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult 2856 : lldb::eReturnStatusSuccessFinishNoResult); 2857 return true; 2858 } 2859 }; 2860 2861 template <typename FormatterType> 2862 class CommandObjectFormatterInfo : public CommandObjectRaw { 2863 public: 2864 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)> 2865 DiscoveryFunction; 2866 CommandObjectFormatterInfo(CommandInterpreter &interpreter, 2867 const char *formatter_name, 2868 DiscoveryFunction discovery_func) 2869 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame), 2870 m_formatter_name(formatter_name ? formatter_name : ""), 2871 m_discovery_function(discovery_func) { 2872 StreamString name; 2873 name.Printf("type %s info", formatter_name); 2874 SetCommandName(name.GetString()); 2875 StreamString help; 2876 help.Printf("This command evaluates the provided expression and shows " 2877 "which %s is applied to the resulting value (if any).", 2878 formatter_name); 2879 SetHelp(help.GetString()); 2880 StreamString syntax; 2881 syntax.Printf("type %s info <expr>", formatter_name); 2882 SetSyntax(syntax.GetString()); 2883 } 2884 2885 ~CommandObjectFormatterInfo() override = default; 2886 2887 protected: 2888 bool DoExecute(llvm::StringRef command, 2889 CommandReturnObject &result) override { 2890 TargetSP target_sp = GetDebugger().GetSelectedTarget(); 2891 Thread *thread = GetDefaultThread(); 2892 if (!thread) { 2893 result.AppendError("no default thread"); 2894 result.SetStatus(lldb::eReturnStatusFailed); 2895 return false; 2896 } 2897 2898 StackFrameSP frame_sp = thread->GetSelectedFrame(); 2899 ValueObjectSP result_valobj_sp; 2900 EvaluateExpressionOptions options; 2901 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( 2902 command, frame_sp.get(), result_valobj_sp, options); 2903 if (expr_result == eExpressionCompleted && result_valobj_sp) { 2904 result_valobj_sp = 2905 result_valobj_sp->GetQualifiedRepresentationIfAvailable( 2906 target_sp->GetPreferDynamicValue(), 2907 target_sp->GetEnableSyntheticValue()); 2908 typename FormatterType::SharedPointer formatter_sp = 2909 m_discovery_function(*result_valobj_sp); 2910 if (formatter_sp) { 2911 std::string description(formatter_sp->GetDescription()); 2912 result.GetOutputStream() 2913 << m_formatter_name << " applied to (" 2914 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2915 << ") " << command << " is: " << description << "\n"; 2916 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 2917 } else { 2918 result.GetOutputStream() 2919 << "no " << m_formatter_name << " applies to (" 2920 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2921 << ") " << command << "\n"; 2922 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 2923 } 2924 return true; 2925 } else { 2926 result.AppendError("failed to evaluate expression"); 2927 result.SetStatus(lldb::eReturnStatusFailed); 2928 return false; 2929 } 2930 } 2931 2932 private: 2933 std::string m_formatter_name; 2934 DiscoveryFunction m_discovery_function; 2935 }; 2936 2937 class CommandObjectTypeFormat : public CommandObjectMultiword { 2938 public: 2939 CommandObjectTypeFormat(CommandInterpreter &interpreter) 2940 : CommandObjectMultiword( 2941 interpreter, "type format", 2942 "Commands for customizing value display formats.", 2943 "type format [<sub-command-options>] ") { 2944 LoadSubCommand( 2945 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter))); 2946 LoadSubCommand("clear", CommandObjectSP( 2947 new CommandObjectTypeFormatClear(interpreter))); 2948 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete( 2949 interpreter))); 2950 LoadSubCommand( 2951 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter))); 2952 LoadSubCommand( 2953 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>( 2954 interpreter, "format", 2955 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer { 2956 return valobj.GetValueFormat(); 2957 }))); 2958 } 2959 2960 ~CommandObjectTypeFormat() override = default; 2961 }; 2962 2963 #if LLDB_ENABLE_PYTHON 2964 2965 class CommandObjectTypeSynth : public CommandObjectMultiword { 2966 public: 2967 CommandObjectTypeSynth(CommandInterpreter &interpreter) 2968 : CommandObjectMultiword( 2969 interpreter, "type synthetic", 2970 "Commands for operating on synthetic type representations.", 2971 "type synthetic [<sub-command-options>] ") { 2972 LoadSubCommand("add", 2973 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter))); 2974 LoadSubCommand( 2975 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter))); 2976 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete( 2977 interpreter))); 2978 LoadSubCommand( 2979 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter))); 2980 LoadSubCommand( 2981 "info", 2982 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>( 2983 interpreter, "synthetic", 2984 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer { 2985 return valobj.GetSyntheticChildren(); 2986 }))); 2987 } 2988 2989 ~CommandObjectTypeSynth() override = default; 2990 }; 2991 2992 #endif 2993 2994 class CommandObjectTypeFilter : public CommandObjectMultiword { 2995 public: 2996 CommandObjectTypeFilter(CommandInterpreter &interpreter) 2997 : CommandObjectMultiword(interpreter, "type filter", 2998 "Commands for operating on type filters.", 2999 "type synthetic [<sub-command-options>] ") { 3000 LoadSubCommand( 3001 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter))); 3002 LoadSubCommand("clear", CommandObjectSP( 3003 new CommandObjectTypeFilterClear(interpreter))); 3004 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete( 3005 interpreter))); 3006 LoadSubCommand( 3007 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter))); 3008 } 3009 3010 ~CommandObjectTypeFilter() override = default; 3011 }; 3012 3013 class CommandObjectTypeCategory : public CommandObjectMultiword { 3014 public: 3015 CommandObjectTypeCategory(CommandInterpreter &interpreter) 3016 : CommandObjectMultiword(interpreter, "type category", 3017 "Commands for operating on type categories.", 3018 "type category [<sub-command-options>] ") { 3019 LoadSubCommand( 3020 "define", 3021 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter))); 3022 LoadSubCommand( 3023 "enable", 3024 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter))); 3025 LoadSubCommand( 3026 "disable", 3027 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter))); 3028 LoadSubCommand( 3029 "delete", 3030 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter))); 3031 LoadSubCommand("list", CommandObjectSP( 3032 new CommandObjectTypeCategoryList(interpreter))); 3033 } 3034 3035 ~CommandObjectTypeCategory() override = default; 3036 }; 3037 3038 class CommandObjectTypeSummary : public CommandObjectMultiword { 3039 public: 3040 CommandObjectTypeSummary(CommandInterpreter &interpreter) 3041 : CommandObjectMultiword( 3042 interpreter, "type summary", 3043 "Commands for editing variable summary display options.", 3044 "type summary [<sub-command-options>] ") { 3045 LoadSubCommand( 3046 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter))); 3047 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear( 3048 interpreter))); 3049 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete( 3050 interpreter))); 3051 LoadSubCommand( 3052 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter))); 3053 LoadSubCommand( 3054 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>( 3055 interpreter, "summary", 3056 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer { 3057 return valobj.GetSummaryFormat(); 3058 }))); 3059 } 3060 3061 ~CommandObjectTypeSummary() override = default; 3062 }; 3063 3064 // CommandObjectType 3065 3066 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) 3067 : CommandObjectMultiword(interpreter, "type", 3068 "Commands for operating on the type system.", 3069 "type [<sub-command-options>]") { 3070 LoadSubCommand("category", 3071 CommandObjectSP(new CommandObjectTypeCategory(interpreter))); 3072 LoadSubCommand("filter", 3073 CommandObjectSP(new CommandObjectTypeFilter(interpreter))); 3074 LoadSubCommand("format", 3075 CommandObjectSP(new CommandObjectTypeFormat(interpreter))); 3076 LoadSubCommand("summary", 3077 CommandObjectSP(new CommandObjectTypeSummary(interpreter))); 3078 #if LLDB_ENABLE_PYTHON 3079 LoadSubCommand("synthetic", 3080 CommandObjectSP(new CommandObjectTypeSynth(interpreter))); 3081 #endif 3082 LoadSubCommand("lookup", 3083 CommandObjectSP(new CommandObjectTypeLookup(interpreter))); 3084 } 3085 3086 CommandObjectType::~CommandObjectType() = default; 3087