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