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