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