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