LLDB mainline
CommandObjectType.cpp
Go to the documentation of this file.
1//===-- CommandObjectType.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CommandObjectType.h"
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/IOHandler.h"
15#include "lldb/Host/Config.h"
27#include "lldb/Symbol/Symbol.h"
30#include "lldb/Target/Target.h"
31#include "lldb/Target/Thread.h"
35
36#include "llvm/ADT/STLExtras.h"
37
38#include <algorithm>
39#include <functional>
40#include <memory>
41
42using namespace lldb;
43using namespace lldb_private;
44
46public:
51 std::string m_category;
52
54 FormatterMatchType match_type, ConstString name,
55 std::string catg)
56 : m_flags(flags), m_match_type(match_type), m_name(name),
57 m_category(catg) {}
58
59 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
60};
61
63public:
69 std::string m_category;
70
71 SynthAddOptions(bool sptr, bool sref, bool casc,
72 FormatterMatchType match_type, std::string catg)
73 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
74 m_match_type(match_type), m_category(catg) {}
75
76 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
77};
78
80 CommandReturnObject &result) {
81 if (command.empty())
82 return false;
83
84 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
85 if (entry.value().ref() != "unsigned")
86 continue;
87 auto next = command.entries()[entry.index() + 1].ref();
88 if (next == "int" || next == "short" || next == "char" || next == "long") {
90 "unsigned %s being treated as two types. if you meant the combined "
91 "type "
92 "name use quotes, as in \"unsigned %s\"\n",
93 next.str().c_str(), next.str().c_str());
94 return true;
95 }
96 }
97 return false;
98}
99
100const char *FormatCategoryToString(FormatCategoryItem item, bool long_name) {
101 switch (item) {
103 return "summary";
105 return "filter";
107 if (long_name)
108 return "synthetic child provider";
109 return "synthetic";
111 return "format";
112 }
113 llvm_unreachable("Fully covered switch above!");
114}
115
116#define LLDB_OPTIONS_type_summary_add
117#include "CommandOptions.inc"
118
121private:
122 class CommandOptions : public Options {
123 public:
125
126 ~CommandOptions() override = default;
127
128 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
129 ExecutionContext *execution_context) override;
130
131 void OptionParsingStarting(ExecutionContext *execution_context) override;
132
133 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
134 return llvm::ArrayRef(g_type_summary_add_options);
135 }
136
137 // Instance variables to hold the values for command options.
138
141 std::string m_format_string;
143 std::string m_python_script;
144 std::string m_python_function;
145 bool m_is_add_script = false;
146 std::string m_category;
147 };
148
150
151 Options *GetOptions() override { return &m_options; }
152
154
155 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
156
157public:
159
160 ~CommandObjectTypeSummaryAdd() override = default;
161
162 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
163 static const char *g_summary_addreader_instructions =
164 "Enter your Python command(s). Type 'DONE' to end.\n"
165 "def function (valobj,internal_dict):\n"
166 " \"\"\"valobj: an SBValue which you want to provide a summary "
167 "for\n"
168 " internal_dict: an LLDB support object not to be used\"\"\"\n";
169
170 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
171 if (output_sp && interactive) {
172 output_sp->PutCString(g_summary_addreader_instructions);
173 output_sp->Flush();
174 }
175 }
176
178 std::string &data) override {
179 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
180
181#if LLDB_ENABLE_PYTHON
183 if (interpreter) {
184 StringList lines;
185 lines.SplitIntoLines(data);
186 if (lines.GetSize() > 0) {
187 ScriptAddOptions *options_ptr =
188 ((ScriptAddOptions *)io_handler.GetUserData());
189 if (options_ptr) {
191 options_ptr); // this will ensure that we get rid of the pointer
192 // when going out of scope
193
195 if (interpreter) {
196 std::string funct_name_str;
197 if (interpreter->GenerateTypeScriptFunction(lines,
198 funct_name_str)) {
199 if (funct_name_str.empty()) {
200 error_sp->Printf("unable to obtain a valid function name from "
201 "the script interpreter.\n");
202 error_sp->Flush();
203 } else {
204 // now I have a valid function name, let's add this as script
205 // for every type in the list
206
207 TypeSummaryImplSP script_format;
208 script_format = std::make_shared<ScriptSummaryFormat>(
209 options->m_flags, funct_name_str.c_str(),
210 lines.CopyList(" ").c_str());
211
213
214 for (const std::string &type_name : options->m_target_types) {
215 AddSummary(ConstString(type_name), script_format,
216 options->m_match_type, options->m_category,
217 &error);
218 if (error.Fail()) {
219 error_sp->Printf("error: %s", error.AsCString());
220 error_sp->Flush();
221 }
222 }
223
224 if (options->m_name) {
226 options->m_name, script_format, &error);
227 if (error.Fail()) {
229 options->m_name, script_format, &error);
230 if (error.Fail()) {
231 error_sp->Printf("error: %s", error.AsCString());
232 error_sp->Flush();
233 }
234 } else {
235 error_sp->Printf("error: %s", error.AsCString());
236 error_sp->Flush();
237 }
238 } else {
239 if (error.AsCString()) {
240 error_sp->Printf("error: %s", error.AsCString());
241 error_sp->Flush();
242 }
243 }
244 }
245 } else {
246 error_sp->Printf("error: unable to generate a function.\n");
247 error_sp->Flush();
248 }
249 } else {
250 error_sp->Printf("error: no script interpreter.\n");
251 error_sp->Flush();
252 }
253 } else {
254 error_sp->Printf("error: internal synchronization information "
255 "missing or invalid.\n");
256 error_sp->Flush();
257 }
258 } else {
259 error_sp->Printf("error: empty function, didn't add python command.\n");
260 error_sp->Flush();
261 }
262 } else {
263 error_sp->Printf(
264 "error: script interpreter missing, didn't add python command.\n");
265 error_sp->Flush();
266 }
267#endif
268 io_handler.SetIsDone(true);
269 }
270
271 bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
272 FormatterMatchType match_type, std::string category,
273 Status *error = nullptr);
274
275 bool AddNamedSummary(ConstString summary_name, lldb::TypeSummaryImplSP entry,
276 Status *error = nullptr);
277
278protected:
279 void DoExecute(Args &command, CommandReturnObject &result) override;
280};
281
283 "Enter your Python command(s). Type 'DONE' to end.\n"
284 "You must define a Python class with these methods:\n"
285 " def __init__(self, valobj, internal_dict):\n"
286 " def num_children(self):\n"
287 " def get_child_at_index(self, index):\n"
288 " def get_child_index(self, name):\n"
289 " def update(self):\n"
290 " '''Optional'''\n"
291 "class synthProvider:\n";
292
293#define LLDB_OPTIONS_type_synth_add
294#include "CommandOptions.inc"
295
298private:
299 class CommandOptions : public Options {
300 public:
301 CommandOptions() = default;
302
303 ~CommandOptions() override = default;
304
305 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
306 ExecutionContext *execution_context) override {
308 const int short_option = m_getopt_table[option_idx].val;
309 bool success;
310
311 switch (short_option) {
312 case 'C':
313 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
314 if (!success)
315 error.SetErrorStringWithFormat("invalid value for cascade: %s",
316 option_arg.str().c_str());
317 break;
318 case 'P':
319 handwrite_python = true;
320 break;
321 case 'l':
322 m_class_name = std::string(option_arg);
323 is_class_based = true;
324 break;
325 case 'p':
326 m_skip_pointers = true;
327 break;
328 case 'r':
329 m_skip_references = true;
330 break;
331 case 'w':
332 m_category = std::string(option_arg);
333 break;
334 case 'x':
336 error.SetErrorString(
337 "can't use --regex and --recognizer-function at the same time");
338 else
340 break;
341 case '\x01':
343 error.SetErrorString(
344 "can't use --regex and --recognizer-function at the same time");
345 else
347 break;
348 default:
349 llvm_unreachable("Unimplemented option");
350 }
351
352 return error;
353 }
354
355 void OptionParsingStarting(ExecutionContext *execution_context) override {
356 m_cascade = true;
357 m_class_name = "";
358 m_skip_pointers = false;
359 m_skip_references = false;
360 m_category = "default";
361 is_class_based = false;
362 handwrite_python = false;
364 }
365
366 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
367 return llvm::ArrayRef(g_type_synth_add_options);
368 }
369
370 // Instance variables to hold the values for command options.
371
375 std::string m_class_name;
377 std::string m_category;
381 };
382
384
385 Options *GetOptions() override { return &m_options; }
386
387 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
388
389 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
390
391protected:
392 void DoExecute(Args &command, CommandReturnObject &result) override {
394
396 Execute_HandwritePython(command, result);
397 else if (m_options.is_class_based)
398 Execute_PythonClass(command, result);
399 else {
400 result.AppendError("must either provide a children list, a Python class "
401 "name, or use -P and type a Python class "
402 "line-by-line");
403 }
404 }
405
406 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
407 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
408 if (output_sp && interactive) {
409 output_sp->PutCString(g_synth_addreader_instructions);
410 output_sp->Flush();
411 }
412 }
413
415 std::string &data) override {
416 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
417
418#if LLDB_ENABLE_PYTHON
420 if (interpreter) {
421 StringList lines;
422 lines.SplitIntoLines(data);
423 if (lines.GetSize() > 0) {
424 SynthAddOptions *options_ptr =
425 ((SynthAddOptions *)io_handler.GetUserData());
426 if (options_ptr) {
428 options_ptr); // this will ensure that we get rid of the pointer
429 // when going out of scope
430
432 if (interpreter) {
433 std::string class_name_str;
434 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
435 if (class_name_str.empty()) {
436 error_sp->Printf(
437 "error: unable to obtain a proper name for the class.\n");
438 error_sp->Flush();
439 } else {
440 // everything should be fine now, let's add the synth provider
441 // class
442
443 SyntheticChildrenSP synth_provider;
444 synth_provider = std::make_shared<ScriptedSyntheticChildren>(
446 .SetCascades(options->m_cascade)
447 .SetSkipPointers(options->m_skip_pointers)
448 .SetSkipReferences(options->m_skip_references),
449 class_name_str.c_str());
450
453 ConstString(options->m_category.c_str()), category);
454
456
457 for (const std::string &type_name : options->m_target_types) {
458 if (!type_name.empty()) {
459 if (AddSynth(ConstString(type_name), synth_provider,
460 options->m_match_type, options->m_category,
461 &error)) {
462 error_sp->Printf("error: %s\n", error.AsCString());
463 error_sp->Flush();
464 break;
465 }
466 } else {
467 error_sp->Printf("error: invalid type name.\n");
468 error_sp->Flush();
469 break;
470 }
471 }
472 }
473 } else {
474 error_sp->Printf("error: unable to generate a class.\n");
475 error_sp->Flush();
476 }
477 } else {
478 error_sp->Printf("error: no script interpreter.\n");
479 error_sp->Flush();
480 }
481 } else {
482 error_sp->Printf("error: internal synchronization data missing.\n");
483 error_sp->Flush();
484 }
485 } else {
486 error_sp->Printf("error: empty function, didn't add python command.\n");
487 error_sp->Flush();
488 }
489 } else {
490 error_sp->Printf(
491 "error: script interpreter missing, didn't add python command.\n");
492 error_sp->Flush();
493 }
494
495#endif
496 io_handler.SetIsDone(true);
497 }
498
499public:
501
502 ~CommandObjectTypeSynthAdd() override = default;
503
504 bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
505 FormatterMatchType match_type, std::string category_name,
506 Status *error);
507};
508
509// CommandObjectTypeFormatAdd
510
511#define LLDB_OPTIONS_type_format_add
512#include "CommandOptions.inc"
513
515private:
517 public:
518 CommandOptions() = default;
519
520 ~CommandOptions() override = default;
521
522 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
523 return llvm::ArrayRef(g_type_format_add_options);
524 }
525
526 void OptionParsingStarting(ExecutionContext *execution_context) override {
527 m_cascade = true;
528 m_skip_pointers = false;
529 m_skip_references = false;
530 m_regex = false;
531 m_category.assign("default");
532 m_custom_type_name.clear();
533 }
534
535 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
536 ExecutionContext *execution_context) override {
538 const int short_option =
539 g_type_format_add_options[option_idx].short_option;
540 bool success;
541
542 switch (short_option) {
543 case 'C':
544 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
545 if (!success)
546 error.SetErrorStringWithFormat("invalid value for cascade: %s",
547 option_value.str().c_str());
548 break;
549 case 'p':
550 m_skip_pointers = true;
551 break;
552 case 'w':
553 m_category.assign(std::string(option_value));
554 break;
555 case 'r':
556 m_skip_references = true;
557 break;
558 case 'x':
559 m_regex = true;
560 break;
561 case 't':
562 m_custom_type_name.assign(std::string(option_value));
563 break;
564 default:
565 llvm_unreachable("Unimplemented option");
566 }
567
568 return error;
569 }
570
571 // Instance variables to hold the values for command options.
572
577 std::string m_category;
579 };
580
584
585 Options *GetOptions() override { return &m_option_group; }
586
587public:
589 : CommandObjectParsed(interpreter, "type format add",
590 "Add a new formatting style for a type.", nullptr),
593
595 R"(
596The following examples of 'type format add' refer to this code snippet for context:
597
598 typedef int Aint;
599 typedef float Afloat;
600 typedef Aint Bint;
601 typedef Afloat Bfloat;
602
603 Aint ix = 5;
604 Bint iy = 5;
605
606 Afloat fx = 3.14;
607 BFloat fy = 3.14;
608
609Adding default formatting:
611(lldb) type format add -f hex AInt
612(lldb) frame variable iy
614)"
615 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
616the one for Aint is used instead."
617 R"(
618
619To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
620
621
622(lldb) type format add -f hex -C no AInt
623
624Similar reasoning applies to this:
625
626(lldb) type format add -f hex -C no float -p
627
628)"
629 " All float values and float references are now formatted as hexadecimal, but not \
630pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
631
632 // Add the "--format" to all options groups
638 }
639
640 ~CommandObjectTypeFormatAdd() override = default;
641
642protected:
643 void DoExecute(Args &command, CommandReturnObject &result) override {
644 const size_t argc = command.GetArgumentCount();
645
646 if (argc < 1) {
647 result.AppendErrorWithFormat("%s takes one or more args.\n",
648 m_cmd_name.c_str());
649 return;
650 }
651
652 const Format format = m_format_options.GetFormat();
653 if (format == eFormatInvalid &&
655 result.AppendErrorWithFormat("%s needs a valid format.\n",
656 m_cmd_name.c_str());
657 return;
658 }
659
660 TypeFormatImplSP entry;
661
663 entry = std::make_shared<TypeFormatImpl_Format>(
664 format, TypeFormatImpl::Flags()
665 .SetCascades(m_command_options.m_cascade)
668 else
669 entry = std::make_shared<TypeFormatImpl_EnumType>(
675
676 // now I have a valid format, let's add it to every type
677
678 TypeCategoryImplSP category_sp;
681 if (!category_sp)
682 return;
683
685
686 for (auto &arg_entry : command.entries()) {
687 if (arg_entry.ref().empty()) {
688 result.AppendError("empty typenames not allowed");
689 return;
690 }
691
694 match_type = eFormatterMatchRegex;
695 RegularExpression typeRX(arg_entry.ref());
696 if (!typeRX.IsValid()) {
697 result.AppendError(
698 "regex format error (maybe this is not really a regex?)");
699 return;
700 }
701 }
702 category_sp->AddTypeFormat(arg_entry.ref(), match_type, entry);
703 }
704
706 }
707};
708
709#define LLDB_OPTIONS_type_formatter_delete
710#include "CommandOptions.inc"
711
713protected:
714 class CommandOptions : public Options {
715 public:
716 CommandOptions() = default;
717
718 ~CommandOptions() override = default;
719
720 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
721 ExecutionContext *execution_context) override {
723 const int short_option = m_getopt_table[option_idx].val;
724
725 switch (short_option) {
726 case 'a':
727 m_delete_all = true;
728 break;
729 case 'w':
730 m_category = std::string(option_arg);
731 break;
732 case 'l':
734 break;
735 default:
736 llvm_unreachable("Unimplemented option");
737 }
738
739 return error;
740 }
741
742 void OptionParsingStarting(ExecutionContext *execution_context) override {
743 m_delete_all = false;
744 m_category = "default";
746 }
747
748 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
749 return llvm::ArrayRef(g_type_formatter_delete_options);
750 }
751
752 // Instance variables to hold the values for command options.
753
755 std::string m_category;
757 };
758
761
762 Options *GetOptions() override { return &m_options; }
763
764 static constexpr const char *g_short_help_template =
765 "Delete an existing %s for a type.";
766
767 static constexpr const char *g_long_help_template =
768 "Delete an existing %s for a type. Unless you specify a "
769 "specific category or all categories, only the "
770 "'default' category is searched. The names must be exactly as "
771 "shown in the 'type %s list' output";
772
773public:
775 FormatCategoryItem formatter_kind)
776 : CommandObjectParsed(interpreter,
777 FormatCategoryToString(formatter_kind, false)),
778 m_formatter_kind(formatter_kind) {
780
781 const char *kind = FormatCategoryToString(formatter_kind, true);
782 const char *short_kind = FormatCategoryToString(formatter_kind, false);
783
784 StreamString s;
786 SetHelp(s.GetData());
787 s.Clear();
788 s.Printf(g_long_help_template, kind, short_kind);
789 SetHelpLong(s.GetData());
790 s.Clear();
791 s.Printf("type %s delete", short_kind);
793 }
794
796
797 void
799 OptionElementVector &opt_element_vector) override {
800 if (request.GetCursorIndex())
801 return;
802
804 [this, &request](const lldb::TypeCategoryImplSP &category_sp) {
805 category_sp->AutoComplete(request, m_formatter_kind);
806 return true;
807 });
808 }
809
810protected:
811 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
812
813 void DoExecute(Args &command, CommandReturnObject &result) override {
814 const size_t argc = command.GetArgumentCount();
815
816 if (argc != 1) {
817 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
818 return;
819 }
820
821 const char *typeA = command.GetArgumentAtIndex(0);
822 ConstString typeCS(typeA);
823
824 if (!typeCS) {
825 result.AppendError("empty typenames not allowed");
826 return;
827 }
828
831 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
832 category_sp->Delete(typeCS, m_formatter_kind);
833 return true;
834 });
836 return;
837 }
838
839 bool delete_category = false;
840 bool extra_deletion = false;
841
845 category);
846 if (category)
847 delete_category = category->Delete(typeCS, m_formatter_kind);
848 extra_deletion = FormatterSpecificDeletion(typeCS);
849 } else {
852 ConstString(m_options.m_category.c_str()), category);
853 if (category)
854 delete_category = category->Delete(typeCS, m_formatter_kind);
855 extra_deletion = FormatterSpecificDeletion(typeCS);
856 }
857
858 if (delete_category || extra_deletion) {
860 } else {
861 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
862 }
863 }
864};
865
866#define LLDB_OPTIONS_type_formatter_clear
867#include "CommandOptions.inc"
868
870private:
871 class CommandOptions : public Options {
872 public:
873 CommandOptions() = default;
874
875 ~CommandOptions() override = default;
876
877 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
878 ExecutionContext *execution_context) override {
880 const int short_option = m_getopt_table[option_idx].val;
881
882 switch (short_option) {
883 case 'a':
884 m_delete_all = true;
885 break;
886 default:
887 llvm_unreachable("Unimplemented option");
888 }
889
890 return error;
891 }
892
893 void OptionParsingStarting(ExecutionContext *execution_context) override {
894 m_delete_all = false;
895 }
896
897 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
898 return llvm::ArrayRef(g_type_formatter_clear_options);
899 }
900
901 // Instance variables to hold the values for command options.
903 };
904
907
908 Options *GetOptions() override { return &m_options; }
909
910public:
912 FormatCategoryItem formatter_kind,
913 const char *name, const char *help)
914 : CommandObjectParsed(interpreter, name, help, nullptr),
915 m_formatter_kind(formatter_kind) {
917 }
918
920
921protected:
923
924 void DoExecute(Args &command, CommandReturnObject &result) override {
927 [this](const TypeCategoryImplSP &category_sp) -> bool {
928 category_sp->Clear(m_formatter_kind);
929 return true;
930 });
931 } else {
933 if (command.GetArgumentCount() > 0) {
934 const char *cat_name = command.GetArgumentAtIndex(0);
935 ConstString cat_nameCS(cat_name);
936 DataVisualization::Categories::GetCategory(cat_nameCS, category);
937 } else {
939 category);
940 }
941 category->Clear(m_formatter_kind);
942 }
943
945
947 }
948};
949
950// CommandObjectTypeFormatDelete
951
953public:
956 interpreter, eFormatCategoryItemFormat) {}
957
958 ~CommandObjectTypeFormatDelete() override = default;
959};
960
961// CommandObjectTypeFormatClear
962
964public:
967 "type format clear",
968 "Delete all existing format styles.") {}
969};
970
971#define LLDB_OPTIONS_type_formatter_list
972#include "CommandOptions.inc"
973
974template <typename FormatterType>
976 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
977
978 class CommandOptions : public Options {
979 public:
981 : Options(), m_category_regex("", ""),
984
985 ~CommandOptions() override = default;
986
987 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
988 ExecutionContext *execution_context) override {
990 const int short_option = m_getopt_table[option_idx].val;
991 switch (short_option) {
992 case 'w':
995 break;
996 case 'l':
998 if (error.Success())
1000 break;
1001 default:
1002 llvm_unreachable("Unimplemented option");
1003 }
1004
1005 return error;
1006 }
1007
1008 void OptionParsingStarting(ExecutionContext *execution_context) override {
1011 }
1012
1013 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1014 return llvm::ArrayRef(g_type_formatter_list_options);
1015 }
1016
1017 // Instance variables to hold the values for command options.
1018
1021 };
1022
1024
1025 Options *GetOptions() override { return &m_options; }
1026
1027public:
1029 const char *name, const char *help)
1030 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1032 }
1033
1035
1036protected:
1038 return false;
1039 }
1040
1041 static bool ShouldListItem(llvm::StringRef s, RegularExpression *regex) {
1042 // If we have a regex, it can match two kinds of results:
1043 // - An item created with that same regex string (exact string match), so
1044 // the user can list it using the same string it used at creation time.
1045 // - Items that match the regex.
1046 // No regex means list everything.
1047 return regex == nullptr || s == regex->GetText() || regex->Execute(s);
1048 }
1049
1050 void DoExecute(Args &command, CommandReturnObject &result) override {
1051 const size_t argc = command.GetArgumentCount();
1052
1053 std::unique_ptr<RegularExpression> category_regex;
1054 std::unique_ptr<RegularExpression> formatter_regex;
1055
1057 category_regex = std::make_unique<RegularExpression>(
1059 if (!category_regex->IsValid()) {
1060 result.AppendErrorWithFormat(
1061 "syntax error in category regular expression '%s'",
1063 return;
1064 }
1065 }
1066
1067 if (argc == 1) {
1068 const char *arg = command.GetArgumentAtIndex(0);
1069 formatter_regex = std::make_unique<RegularExpression>(arg);
1070 if (!formatter_regex->IsValid()) {
1071 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1072 arg);
1073 return;
1074 }
1075 }
1076
1077 bool any_printed = false;
1078
1079 auto category_closure =
1080 [&result, &formatter_regex,
1081 &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
1082 result.GetOutputStream().Printf(
1083 "-----------------------\nCategory: %s%s\n-----------------------\n",
1084 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1085
1087 [&result, &formatter_regex,
1088 &any_printed](const TypeMatcher &type_matcher,
1089 const FormatterSharedPointer &format_sp) -> bool {
1090 if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(),
1091 formatter_regex.get())) {
1092 any_printed = true;
1093 result.GetOutputStream().Printf(
1094 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1095 format_sp->GetDescription().c_str());
1096 }
1097 return true;
1098 };
1099 category->ForEach(print_formatter);
1100 };
1101
1103 lldb::TypeCategoryImplSP category_sp;
1106 if (category_sp)
1107 category_closure(category_sp);
1108 } else {
1110 [&category_regex, &category_closure](
1111 const lldb::TypeCategoryImplSP &category) -> bool {
1112 if (ShouldListItem(category->GetName(), category_regex.get())) {
1113 category_closure(category);
1114 }
1115 return true;
1116 });
1117
1118 any_printed = FormatterSpecificList(result) | any_printed;
1119 }
1120
1121 if (any_printed)
1123 else {
1124 result.GetOutputStream().PutCString("no matching results found.\n");
1126 }
1127 }
1128};
1129
1130// CommandObjectTypeFormatList
1131
1133 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1134public:
1136 : CommandObjectTypeFormatterList(interpreter, "type format list",
1137 "Show a list of current formats.") {}
1138};
1139
1141 uint32_t option_idx, llvm::StringRef option_arg,
1142 ExecutionContext *execution_context) {
1143 Status error;
1144 const int short_option = m_getopt_table[option_idx].val;
1145 bool success;
1146
1147 switch (short_option) {
1148 case 'C':
1149 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1150 if (!success)
1151 error.SetErrorStringWithFormat("invalid value for cascade: %s",
1152 option_arg.str().c_str());
1153 break;
1154 case 'e':
1156 break;
1157 case 'h':
1159 break;
1160 case 'v':
1162 break;
1163 case 'c':
1165 break;
1166 case 's':
1167 m_format_string = std::string(option_arg);
1168 break;
1169 case 'p':
1171 break;
1172 case 'r':
1174 break;
1175 case 'x':
1177 error.SetErrorString(
1178 "can't use --regex and --recognizer-function at the same time");
1179 else
1181 break;
1182 case '\x01':
1184 error.SetErrorString(
1185 "can't use --regex and --recognizer-function at the same time");
1186 else
1188 break;
1189 case 'n':
1190 m_name.SetString(option_arg);
1191 break;
1192 case 'o':
1193 m_python_script = std::string(option_arg);
1194 m_is_add_script = true;
1195 break;
1196 case 'F':
1197 m_python_function = std::string(option_arg);
1198 m_is_add_script = true;
1199 break;
1200 case 'P':
1201 m_is_add_script = true;
1202 break;
1203 case 'w':
1204 m_category = std::string(option_arg);
1205 break;
1206 case 'O':
1208 break;
1209 default:
1210 llvm_unreachable("Unimplemented option");
1211 }
1212
1213 return error;
1214}
1215
1217 ExecutionContext *execution_context) {
1218 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1219 m_flags.SetShowMembersOneLiner(false)
1220 .SetSkipPointers(false)
1221 .SetSkipReferences(false)
1222 .SetHideItemNames(false);
1223
1224 m_match_type = eFormatterMatchExact;
1225 m_name.Clear();
1226 m_python_script = "";
1227 m_python_function = "";
1228 m_format_string = "";
1229 m_is_add_script = false;
1230 m_category = "default";
1231}
1232
1233#if LLDB_ENABLE_PYTHON
1234
1236 Args &command, CommandReturnObject &result) {
1237 const size_t argc = command.GetArgumentCount();
1238
1239 if (argc < 1 && !m_options.m_name) {
1240 result.AppendErrorWithFormat("%s takes one or more args.\n",
1241 m_cmd_name.c_str());
1242 return false;
1243 }
1244
1245 TypeSummaryImplSP script_format;
1246
1248 .empty()) // we have a Python function ready to use
1249 {
1250 const char *funct_name = m_options.m_python_function.c_str();
1251 if (!funct_name || !funct_name[0]) {
1252 result.AppendError("function name empty.\n");
1253 return false;
1254 }
1255
1256 std::string code =
1257 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1258
1259 script_format = std::make_shared<ScriptSummaryFormat>(
1260 m_options.m_flags, funct_name, code.c_str());
1261
1263
1264 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1266 "The provided function \"%s\" does not exist - "
1267 "please define it before attempting to use this summary.\n",
1268 funct_name);
1269 } else if (!m_options.m_python_script
1270 .empty()) // we have a quick 1-line script, just use it
1271 {
1273 if (!interpreter) {
1274 result.AppendError("script interpreter missing - unable to generate "
1275 "function wrapper.\n");
1276 return false;
1277 }
1278 StringList funct_sl;
1279 funct_sl << m_options.m_python_script.c_str();
1280 std::string funct_name_str;
1281 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1282 result.AppendError("unable to generate function wrapper.\n");
1283 return false;
1284 }
1285 if (funct_name_str.empty()) {
1286 result.AppendError(
1287 "script interpreter failed to generate a valid function name.\n");
1288 return false;
1289 }
1290
1291 std::string code = " " + m_options.m_python_script;
1292
1293 script_format = std::make_shared<ScriptSummaryFormat>(
1294 m_options.m_flags, funct_name_str.c_str(), code.c_str());
1295 } else {
1296 // Use an IOHandler to grab Python code from the user
1297 auto options = std::make_unique<ScriptAddOptions>(
1300
1301 for (auto &entry : command.entries()) {
1302 if (entry.ref().empty()) {
1303 result.AppendError("empty typenames not allowed");
1304 return false;
1305 }
1306
1307 options->m_target_types << std::string(entry.ref());
1308 }
1309
1311 " ", // Prompt
1312 *this, // IOHandlerDelegate
1313 options.release()); // Baton for the "io_handler" that will be passed
1314 // back into our IOHandlerDelegate functions
1316
1317 return result.Succeeded();
1318 }
1319
1320 // if I am here, script_format must point to something good, so I can add
1321 // that as a script summary to all interested parties
1322
1323 Status error;
1324
1325 for (auto &entry : command.entries()) {
1326 AddSummary(ConstString(entry.ref()), script_format, m_options.m_match_type,
1328 if (error.Fail()) {
1329 result.AppendError(error.AsCString());
1330 return false;
1331 }
1332 }
1333
1334 if (m_options.m_name) {
1335 AddNamedSummary(m_options.m_name, script_format, &error);
1336 if (error.Fail()) {
1337 result.AppendError(error.AsCString());
1338 result.AppendError("added to types, but not given a name");
1339 return false;
1340 }
1341 }
1342
1343 return result.Succeeded();
1344}
1345
1346#endif
1347
1349 Args &command, CommandReturnObject &result) {
1350 const size_t argc = command.GetArgumentCount();
1351
1352 if (argc < 1 && !m_options.m_name) {
1353 result.AppendErrorWithFormat("%s takes one or more args.\n",
1354 m_cmd_name.c_str());
1355 return false;
1356 }
1357
1359 m_options.m_format_string.empty()) {
1360 result.AppendError("empty summary strings not allowed");
1361 return false;
1362 }
1363
1364 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1365 ? ""
1366 : m_options.m_format_string.c_str());
1367
1368 // ${var%S} is an endless recursion, prevent it
1369 if (strcmp(format_cstr, "${var%S}") == 0) {
1370 result.AppendError("recursive summary not allowed");
1371 return false;
1372 }
1373
1374 std::unique_ptr<StringSummaryFormat> string_format(
1375 new StringSummaryFormat(m_options.m_flags, format_cstr));
1376 if (!string_format) {
1377 result.AppendError("summary creation failed");
1378 return false;
1379 }
1380 if (string_format->m_error.Fail()) {
1381 result.AppendErrorWithFormat("syntax error: %s",
1382 string_format->m_error.AsCString("<unknown>"));
1383 return false;
1384 }
1385 lldb::TypeSummaryImplSP entry(string_format.release());
1386
1387 // now I have a valid format, let's add it to every type
1388 Status error;
1389 for (auto &arg_entry : command.entries()) {
1390 if (arg_entry.ref().empty()) {
1391 result.AppendError("empty typenames not allowed");
1392 return false;
1393 }
1394 ConstString typeCS(arg_entry.ref());
1395
1397 &error);
1398
1399 if (error.Fail()) {
1400 result.AppendError(error.AsCString());
1401 return false;
1402 }
1403 }
1404
1405 if (m_options.m_name) {
1407 if (error.Fail()) {
1408 result.AppendError(error.AsCString());
1409 result.AppendError("added to types, but not given a name");
1410 return false;
1411 }
1412 }
1413
1415 return result.Succeeded();
1416}
1417
1419 CommandInterpreter &interpreter)
1420 : CommandObjectParsed(interpreter, "type summary add",
1421 "Add a new summary style for a type.", nullptr),
1422 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1424
1426 R"(
1427The following examples of 'type summary add' refer to this code snippet for context:
1428
1429 struct JustADemo
1430 {
1431 int* ptr;
1432 float value;
1433 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1434 };
1435 JustADemo demo_instance(42, 3.14);
1436
1437 typedef JustADemo NewDemo;
1438 NewDemo new_demo_instance(42, 3.14);
1439
1440(lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1441
1442 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1443
1444(lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1445
1446 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1447
1448)"
1449 "Alternatively, you could define formatting for all pointers to integers and \
1450rely on that when formatting JustADemo to obtain the same result:"
1451 R"(
1452
1453(lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1454(lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1456)"
1457 "Type summaries are automatically applied to derived typedefs, so the examples \
1458above apply to both JustADemo and NewDemo. The cascade option can be used to \
1459suppress this behavior:"
1460 R"(
1461
1462(lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1463
1464 The summary will now be used for values of JustADemo but not NewDemo.
1465
1466)"
1467 "By default summaries are shown for pointers and references to values of the \
1468specified type. To suppress formatting for pointers use the -p option, or apply \
1469the corresponding -r option to suppress formatting for references:"
1470 R"(
1472(lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1473
1474)"
1475 "One-line summaries including all fields in a type can be inferred without supplying an \
1476explicit summary string by passing the -c option:"
1477 R"(
1478
1479(lldb) type summary add -c JustADemo
1480(lldb) frame variable demo_instance
1481(ptr=<address>, value=3.14)
1482
1483)"
1484 "Type summaries normally suppress the nested display of individual fields. To \
1485supply a summary to supplement the default structure add the -e option:"
1486 R"(
1488(lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1489
1490)"
1491 "Now when displaying JustADemo values the int* is displayed, followed by the \
1492standard LLDB sequence of children, one per line:"
1493 R"(
1494
1495*ptr = 42 {
1496 ptr = <address>
1497 value = 3.14
1498}
1499
1500)"
1501 "You can also add summaries written in Python. These scripts use lldb public API to \
1502gather information from your variables and produce a meaningful summary. To start a \
1503multi-line script use the -P option. The function declaration will be displayed along with \
1504a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1505itself:"
1506 R"(
1507
1508(lldb) type summary add JustADemo -P
1509def function (valobj,internal_dict): """valobj: an SBValue which you want to provide a summary for
1510internal_dict: an LLDB support object not to be used"""
1511 value = valobj.GetChildMemberWithName('value');
1512 return 'My value is ' + value.GetValue();
1513 DONE
1514
1515Alternatively, the -o option can be used when providing a simple one-line Python script:
1516
1517(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1518}
1519
1521 CommandReturnObject &result) {
1522 WarnOnPotentialUnquotedUnsignedType(command, result);
1523
1525#if LLDB_ENABLE_PYTHON
1526 Execute_ScriptSummary(command, result);
1527#else
1528 result.AppendError("python is disabled");
1529#endif
1530 return;
1531 }
1532
1533 Execute_StringSummary(command, result);
1534}
1535
1536static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1537 llvm::StringRef type_name_ref(type_name.GetStringRef());
1538
1539 if (type_name_ref.ends_with("[]")) {
1540 std::string type_name_str(type_name.GetCString());
1541 type_name_str.resize(type_name_str.length() - 2);
1542 if (type_name_str.back() != ' ')
1543 type_name_str.append(" ?\\[[0-9]+\\]");
1544 else
1545 type_name_str.append("\\[[0-9]+\\]");
1546 type_name.SetCString(type_name_str.c_str());
1547 return true;
1548 }
1549 return false;
1550}
1551
1554 Status *error) {
1555 // system named summaries do not exist (yet?)
1557 return true;
1558}
1559
1562 FormatterMatchType match_type,
1563 std::string category_name,
1564 Status *error) {
1565 lldb::TypeCategoryImplSP category;
1567 category);
1569 if (match_type == eFormatterMatchExact) {
1570 if (FixArrayTypeNameWithRegex(type_name))
1572 }
1573
1574 if (match_type == eFormatterMatchRegex) {
1575 match_type = eFormatterMatchRegex;
1576 RegularExpression typeRX(type_name.GetStringRef());
1577 if (!typeRX.IsValid()) {
1578 if (error)
1579 error->SetErrorString(
1580 "regex format error (maybe this is not really a regex?)");
1581 return false;
1582 }
1583 }
1584
1585 if (match_type == eFormatterMatchCallback) {
1586 const char *function_name = type_name.AsCString();
1588 if (interpreter && !interpreter->CheckObjectExists(function_name)) {
1589 error->SetErrorStringWithFormat(
1590 "The provided recognizer function \"%s\" does not exist - "
1591 "please define it before attempting to use this summary.\n",
1592 function_name);
1593 return false;
1595 }
1596 category->AddTypeSummary(type_name.GetStringRef(), match_type, entry);
1597 return true;
1599
1600// CommandObjectTypeSummaryDelete
1601
1603public:
1607
1608 ~CommandObjectTypeSummaryDelete() override = default;
1609
1610protected:
1611 bool FormatterSpecificDeletion(ConstString typeCS) override {
1613 return false;
1615 }
1616};
1617
1619public:
1622 "type summary clear",
1623 "Delete all existing summaries.") {}
1624
1625protected:
1626 void FormatterSpecificDeletion() override {
1628 }
1629};
1631// CommandObjectTypeSummaryList
1632
1634 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1635public:
1637 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1638 "Show a list of current summaries.") {}
1639
1640protected:
1641 bool FormatterSpecificList(CommandReturnObject &result) override {
1643 result.GetOutputStream().Printf("Named summaries:\n");
1645 [&result](const TypeMatcher &type_matcher,
1646 const TypeSummaryImplSP &summary_sp) -> bool {
1647 result.GetOutputStream().Printf(
1648 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1649 summary_sp->GetDescription().c_str());
1650 return true;
1651 });
1652 return true;
1653 }
1654 return false;
1656};
1657
1658// CommandObjectTypeCategoryDefine
1659#define LLDB_OPTIONS_type_category_define
1660#include "CommandOptions.inc"
1661
1663 class CommandOptions : public Options {
1664 public:
1666 : m_define_enabled(false, false),
1668
1669 ~CommandOptions() override = default;
1670
1671 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1672 ExecutionContext *execution_context) override {
1673 Status error;
1674 const int short_option = m_getopt_table[option_idx].val;
1675
1676 switch (short_option) {
1677 case 'e':
1678 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1679 break;
1680 case 'l':
1682 break;
1683 default:
1684 llvm_unreachable("Unimplemented option");
1686
1687 return error;
1688 }
1690 void OptionParsingStarting(ExecutionContext *execution_context) override {
1693 }
1694
1695 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1696 return llvm::ArrayRef(g_type_category_define_options);
1697 }
1698
1699 // Instance variables to hold the values for command options.
1700
1703 };
1704
1705 CommandOptions m_options;
1706
1707 Options *GetOptions() override { return &m_options; }
1708
1709public:
1711 : CommandObjectParsed(interpreter, "type category define",
1712 "Define a new category as a source of formatters.",
1713 nullptr) {
1715 }
1717 ~CommandObjectTypeCategoryDefine() override = default;
1718
1719protected:
1720 void DoExecute(Args &command, CommandReturnObject &result) override {
1721 const size_t argc = command.GetArgumentCount();
1723 if (argc < 1) {
1724 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1725 m_cmd_name.c_str());
1726 return;
1728
1729 for (auto &entry : command.entries()) {
1732 category_sp) &&
1733 category_sp) {
1734 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1738 }
1739 }
1742 }
1743};
1744
1745// CommandObjectTypeCategoryEnable
1746#define LLDB_OPTIONS_type_category_enable
1747#include "CommandOptions.inc"
1748
1750 class CommandOptions : public Options {
1751 public:
1752 CommandOptions() = default;
1753
1754 ~CommandOptions() override = default;
1755
1756 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1757 ExecutionContext *execution_context) override {
1758 Status error;
1759 const int short_option = m_getopt_table[option_idx].val;
1760
1761 switch (short_option) {
1762 case 'l':
1763 if (!option_arg.empty()) {
1766 error.SetErrorStringWithFormat("unrecognized language '%s'",
1767 option_arg.str().c_str());
1768 }
1769 break;
1770 default:
1771 llvm_unreachable("Unimplemented option");
1772 }
1773
1774 return error;
1775 }
1776
1777 void OptionParsingStarting(ExecutionContext *execution_context) override {
1780
1781 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1782 return llvm::ArrayRef(g_type_category_enable_options);
1783 }
1784
1785 // Instance variables to hold the values for command options.
1786
1789
1790 CommandOptions m_options;
1792 Options *GetOptions() override { return &m_options; }
1793
1794public:
1796 : CommandObjectParsed(interpreter, "type category enable",
1797 "Enable a category as a source of formatters.",
1798 nullptr) {
1800 }
1801
1802 ~CommandObjectTypeCategoryEnable() override = default;
1803
1804protected:
1805 void DoExecute(Args &command, CommandReturnObject &result) override {
1806 const size_t argc = command.GetArgumentCount();
1807
1808 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1809 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1810 m_cmd_name.c_str());
1811 return;
1812 }
1813
1814 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1816 } else if (argc > 0) {
1817 for (int i = argc - 1; i >= 0; i--) {
1818 const char *typeA = command.GetArgumentAtIndex(i);
1819 ConstString typeCS(typeA);
1820
1821 if (!typeCS) {
1822 result.AppendError("empty category name not allowed");
1823 return;
1824 }
1828 if (cate->GetCount() == 0) {
1829 result.AppendWarning("empty category enabled (typo?)");
1830 }
1832 }
1834
1837
1839 }
1840};
1841
1842// CommandObjectTypeCategoryDelete
1843
1845public:
1847 : CommandObjectParsed(interpreter, "type category delete",
1848 "Delete a category and all associated formatters.",
1849 nullptr) {
1851 }
1852
1853 ~CommandObjectTypeCategoryDelete() override = default;
1855protected:
1856 void DoExecute(Args &command, CommandReturnObject &result) override {
1857 const size_t argc = command.GetArgumentCount();
1859 if (argc < 1) {
1860 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1861 m_cmd_name.c_str());
1862 return;
1863 }
1865 bool success = true;
1866
1867 // the order is not relevant here
1868 for (int i = argc - 1; i >= 0; i--) {
1869 const char *typeA = command.GetArgumentAtIndex(i);
1870 ConstString typeCS(typeA);
1871
1872 if (!typeCS) {
1873 result.AppendError("empty category name not allowed");
1874 return;
1875 }
1877 success = false; // keep deleting even if we hit an error
1878 }
1879 if (success) {
1881 } else {
1882 result.AppendError("cannot delete one or more categories\n");
1883 }
1884 }
1885};
1886
1887// CommandObjectTypeCategoryDisable
1888#define LLDB_OPTIONS_type_category_disable
1889#include "CommandOptions.inc"
1890
1892 class CommandOptions : public Options {
1893 public:
1894 CommandOptions() = default;
1895
1896 ~CommandOptions() override = default;
1897
1898 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1899 ExecutionContext *execution_context) override {
1900 Status error;
1901 const int short_option = m_getopt_table[option_idx].val;
1902
1903 switch (short_option) {
1904 case 'l':
1905 if (!option_arg.empty()) {
1908 error.SetErrorStringWithFormat("unrecognized language '%s'",
1909 option_arg.str().c_str());
1910 }
1911 break;
1912 default:
1913 llvm_unreachable("Unimplemented option");
1914 }
1915
1916 return error;
1917 }
1919 void OptionParsingStarting(ExecutionContext *execution_context) override {
1921 }
1922
1923 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1924 return llvm::ArrayRef(g_type_category_disable_options);
1926
1927 // Instance variables to hold the values for command options.
1930 };
1931
1932 CommandOptions m_options;
1933
1934 Options *GetOptions() override { return &m_options; }
1935
1936public:
1938 : CommandObjectParsed(interpreter, "type category disable",
1939 "Disable a category as a source of formatters.",
1940 nullptr) {
1942 }
1943
1944 ~CommandObjectTypeCategoryDisable() override = default;
1945
1946protected:
1947 void DoExecute(Args &command, CommandReturnObject &result) override {
1948 const size_t argc = command.GetArgumentCount();
1949
1950 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1951 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1952 m_cmd_name.c_str());
1953 return;
1954 }
1955
1956 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1958 } else if (argc > 0) {
1959 // the order is not relevant here
1960 for (int i = argc - 1; i >= 0; i--) {
1961 const char *typeA = command.GetArgumentAtIndex(i);
1962 ConstString typeCS(typeA);
1963
1964 if (!typeCS) {
1965 result.AppendError("empty category name not allowed");
1966 return;
1967 }
1969 }
1970 }
1971
1974
1976 }
1977};
1978
1979// CommandObjectTypeCategoryList
1980
1982public:
1984 : CommandObjectParsed(interpreter, "type category list",
1985 "Provide a list of all existing categories.",
1986 nullptr) {
1988 }
1989
1990 ~CommandObjectTypeCategoryList() override = default;
1991
1992 void
1994 OptionElementVector &opt_element_vector) override {
1995 if (request.GetCursorIndex())
1996 return;
1999 nullptr);
2000 }
2001
2002protected:
2003 void DoExecute(Args &command, CommandReturnObject &result) override {
2004 const size_t argc = command.GetArgumentCount();
2005
2006 std::unique_ptr<RegularExpression> regex;
2007
2008 if (argc == 1) {
2009 const char *arg = command.GetArgumentAtIndex(0);
2010 regex = std::make_unique<RegularExpression>(arg);
2011 if (!regex->IsValid()) {
2012 result.AppendErrorWithFormat(
2013 "syntax error in category regular expression '%s'", arg);
2014 return;
2016 } else if (argc != 0) {
2017 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2018 m_cmd_name.c_str());
2019 return;
2020 }
2023 [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2024 if (regex) {
2025 bool escape = true;
2026 if (regex->GetText() == category_sp->GetName()) {
2027 escape = false;
2028 } else if (regex->Execute(category_sp->GetName())) {
2029 escape = false;
2030 }
2031
2032 if (escape)
2033 return true;
2034 }
2035
2036 result.GetOutputStream().Printf(
2037 "Category: %s\n", category_sp->GetDescription().c_str());
2038
2039 return true;
2040 });
2041
2043 }
2044};
2046// CommandObjectTypeFilterList
2047
2049 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2050public:
2052 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2053 "Show a list of current filters.") {}
2054};
2055
2056// CommandObjectTypeSynthList
2057
2059 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2060public:
2063 interpreter, "type synthetic list",
2064 "Show a list of current synthetic providers.") {}
2065};
2066
2067// CommandObjectTypeFilterDelete
2068
2070public:
2073 interpreter, eFormatCategoryItemFilter) {}
2074
2075 ~CommandObjectTypeFilterDelete() override = default;
2076};
2077
2078// CommandObjectTypeSynthDelete
2079
2081public:
2084 interpreter, eFormatCategoryItemSynth) {}
2085
2086 ~CommandObjectTypeSynthDelete() override = default;
2087};
2088
2089
2090// CommandObjectTypeFilterClear
2091
2093public:
2096 "type filter clear",
2097 "Delete all existing filter.") {}
2098};
2099
2100// CommandObjectTypeSynthClear
2101
2103public:
2106 interpreter, eFormatCategoryItemSynth, "type synthetic clear",
2107 "Delete all existing synthetic providers.") {}
2108};
2109
2111 Args &command, CommandReturnObject &result) {
2112 auto options = std::make_unique<SynthAddOptions>(
2115
2116 for (auto &entry : command.entries()) {
2117 if (entry.ref().empty()) {
2118 result.AppendError("empty typenames not allowed");
2119 return false;
2120 }
2121
2122 options->m_target_types << std::string(entry.ref());
2123 }
2124
2126 " ", // Prompt
2127 *this, // IOHandlerDelegate
2128 options.release()); // Baton for the "io_handler" that will be passed back
2129 // into our IOHandlerDelegate functions
2131 return result.Succeeded();
2132}
2133
2135 Args &command, CommandReturnObject &result) {
2136 const size_t argc = command.GetArgumentCount();
2137
2138 if (argc < 1) {
2139 result.AppendErrorWithFormat("%s takes one or more args.\n",
2140 m_cmd_name.c_str());
2141 return false;
2142 }
2143
2145 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2146 "directly input Python code.\n",
2147 m_cmd_name.c_str());
2148 return false;
2149 }
2150
2151 SyntheticChildrenSP entry;
2152
2155 .SetCascades(m_options.m_cascade)
2158 m_options.m_class_name.c_str());
2159
2160 entry.reset(impl);
2161
2163
2164 if (interpreter &&
2165 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2166 result.AppendWarning("The provided class does not exist - please define it "
2167 "before attempting to use this synthetic provider");
2168
2169 // now I have a valid provider, let's add it to every type
2170
2171 lldb::TypeCategoryImplSP category;
2173 ConstString(m_options.m_category.c_str()), category);
2174
2175 Status error;
2176
2177 for (auto &arg_entry : command.entries()) {
2178 if (arg_entry.ref().empty()) {
2179 result.AppendError("empty typenames not allowed");
2180 return false;
2181 }
2182
2183 ConstString typeCS(arg_entry.ref());
2184 if (!AddSynth(typeCS, entry, m_options.m_match_type, m_options.m_category,
2185 &error)) {
2186 result.AppendError(error.AsCString());
2187 return false;
2188 }
2189 }
2190
2192 return result.Succeeded();
2193}
2194
2196 CommandInterpreter &interpreter)
2197 : CommandObjectParsed(interpreter, "type synthetic add",
2198 "Add a new synthetic provider for a type.", nullptr),
2199 IOHandlerDelegateMultiline("DONE"), m_options() {
2200 AddSimpleArgumentList(eArgTypeName, eArgRepeatPlus);
2201}
2204 SyntheticChildrenSP entry,
2205 FormatterMatchType match_type,
2206 std::string category_name,
2207 Status *error) {
2210 category);
2211
2212 if (match_type == eFormatterMatchExact) {
2213 if (FixArrayTypeNameWithRegex(type_name))
2214 match_type = eFormatterMatchRegex;
2215 }
2216
2217 // Only check for conflicting filters in the same category if `type_name` is
2218 // an actual type name. Matching a regex string against registered regexes
2219 // doesn't work.
2220 if (match_type == eFormatterMatchExact) {
2221 // It's not generally possible to get a type object here. For example, this
2222 // command can be run before loading any binaries. Do just a best-effort
2223 // name-based lookup here to try to prevent conflicts.
2224 FormattersMatchCandidate candidate_type(type_name, nullptr, TypeImpl(),
2226 if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter,
2227 false)) {
2228 if (error)
2229 error->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2230 "filter is defined in same category!",
2231 type_name.AsCString());
2232 return false;
2233 }
2234 }
2235
2236 if (match_type == eFormatterMatchRegex) {
2237 RegularExpression typeRX(type_name.GetStringRef());
2238 if (!typeRX.IsValid()) {
2239 if (error)
2240 error->SetErrorString(
2241 "regex format error (maybe this is not really a regex?)");
2242 return false;
2243 }
2244 }
2245
2246 if (match_type == eFormatterMatchCallback) {
2247 const char *function_name = type_name.AsCString();
2249 if (interpreter && !interpreter->CheckObjectExists(function_name)) {
2250 error->SetErrorStringWithFormat(
2251 "The provided recognizer function \"%s\" does not exist - "
2252 "please define it before attempting to use this summary.\n",
2253 function_name);
2254 return false;
2255 }
2257
2258 category->AddTypeSynthetic(type_name.GetStringRef(), match_type, entry);
2259 return true;
2260}
2261
2262#define LLDB_OPTIONS_type_filter_add
2263#include "CommandOptions.inc"
2266private:
2267 class CommandOptions : public Options {
2268 typedef std::vector<std::string> option_vector;
2270 public:
2271 CommandOptions() = default;
2272
2273 ~CommandOptions() override = default;
2275 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2276 ExecutionContext *execution_context) override {
2277 Status error;
2278 const int short_option = m_getopt_table[option_idx].val;
2279 bool success;
2281 switch (short_option) {
2282 case 'C':
2283 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2284 if (!success)
2285 error.SetErrorStringWithFormat("invalid value for cascade: %s",
2286 option_arg.str().c_str());
2287 break;
2288 case 'c':
2289 m_expr_paths.push_back(std::string(option_arg));
2290 has_child_list = true;
2291 break;
2292 case 'p':
2293 m_skip_pointers = true;
2294 break;
2295 case 'r':
2296 m_skip_references = true;
2297 break;
2298 case 'w':
2299 m_category = std::string(option_arg);
2300 break;
2301 case 'x':
2302 m_regex = true;
2303 break;
2304 default:
2305 llvm_unreachable("Unimplemented option");
2306 }
2307
2308 return error;
2309 }
2310
2311 void OptionParsingStarting(ExecutionContext *execution_context) override {
2312 m_cascade = true;
2313 m_skip_pointers = false;
2314 m_skip_references = false;
2315 m_category = "default";
2316 m_expr_paths.clear();
2317 has_child_list = false;
2318 m_regex = false;
2319 }
2320
2321 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2322 return llvm::ArrayRef(g_type_filter_add_options);
2323 }
2324
2325 // Instance variables to hold the values for command options.
2326
2327 bool m_cascade;
2328 bool m_skip_references;
2330 bool m_input_python;
2332 std::string m_category;
2333 bool has_child_list;
2334 bool m_regex;
2335
2336 typedef option_vector::iterator ExpressionPathsIterator;
2337 };
2338
2339 CommandOptions m_options;
2340
2341 Options *GetOptions() override { return &m_options; }
2342
2345 bool AddFilter(ConstString type_name, TypeFilterImplSP entry,
2346 FilterFormatType type, std::string category_name,
2348 lldb::TypeCategoryImplSP category;
2350 ConstString(category_name.c_str()), category);
2351
2352 if (type == eRegularFilter) {
2353 if (FixArrayTypeNameWithRegex(type_name))
2354 type = eRegexFilter;
2355 }
2356
2357 // Only check for conflicting synthetic child providers in the same category
2358 // if `type_name` is an actual type name. Matching a regex string against
2359 // registered regexes doesn't work.
2360 if (type == eRegularFilter) {
2361 // It's not generally possible to get a type object here. For example,
2362 // this command can be run before loading any binaries. Do just a
2363 // best-effort name-based lookup here to try to prevent conflicts.
2364 FormattersMatchCandidate candidate_type(
2365 type_name, nullptr, TypeImpl(), FormattersMatchCandidate::Flags());
2367 if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth,
2368 false)) {
2369 if (error)
2370 error->SetErrorStringWithFormat("cannot add filter for type %s when "
2371 "synthetic is defined in same "
2372 "category!",
2373 type_name.AsCString());
2374 return false;
2375 }
2376 }
2377
2379 if (type == eRegexFilter) {
2380 match_type = eFormatterMatchRegex;
2381 RegularExpression typeRX(type_name.GetStringRef());
2382 if (!typeRX.IsValid()) {
2383 if (error)
2384 error->SetErrorString(
2385 "regex format error (maybe this is not really a regex?)");
2386 return false;
2387 }
2388 }
2389 category->AddTypeFilter(type_name.GetStringRef(), match_type, entry);
2390 return true;
2391 }
2392
2393public:
2395 : CommandObjectParsed(interpreter, "type filter add",
2396 "Add a new filter for a type.", nullptr) {
2398
2400 R"(
2401The following examples of 'type filter add' refer to this code snippet for context:
2402
2403 class Foo {
2404 int a;
2405 int b;
2406 int c;
2407 int d;
2408 int e;
2409 int f;
2410 int g;
2411 int h;
2412 int i;
2413 }
2414 Foo my_foo;
2415
2416Adding a simple filter:
2417
2418(lldb) type filter add --child a --child g Foo
2419(lldb) frame variable my_foo
2420
2421)"
2422 "Produces output where only a and g are displayed. Other children of my_foo \
2423(b, c, d, e, f, h and i) are available by asking for them explicitly:"
2424 R"(
2425
2426(lldb) frame variable my_foo.b my_foo.c my_foo.i
2427
2428)"
2429 "The formatting option --raw on frame variable bypasses the filter, showing \
2430all children of my_foo as if no filter was defined:"
2431 R"(
2433(lldb) frame variable my_foo --raw)");
2434 }
2436 ~CommandObjectTypeFilterAdd() override = default;
2437
2438protected:
2439 void DoExecute(Args &command, CommandReturnObject &result) override {
2440 const size_t argc = command.GetArgumentCount();
2441
2442 if (argc < 1) {
2443 result.AppendErrorWithFormat("%s takes one or more args.\n",
2444 m_cmd_name.c_str());
2445 return;
2446 }
2447
2448 if (m_options.m_expr_paths.empty()) {
2449 result.AppendErrorWithFormat("%s needs one or more children.\n",
2450 m_cmd_name.c_str());
2451 return;
2452 }
2453
2456 .SetCascades(m_options.m_cascade)
2460 // go through the expression paths
2462 end = m_options.m_expr_paths.end();
2464 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2465 entry->AddExpressionPath(*begin);
2466
2467 // now I have a valid provider, let's add it to every type
2468
2469 lldb::TypeCategoryImplSP category;
2471 ConstString(m_options.m_category.c_str()), category);
2472
2473 Status error;
2474
2475 WarnOnPotentialUnquotedUnsignedType(command, result);
2476
2477 for (auto &arg_entry : command.entries()) {
2478 if (arg_entry.ref().empty()) {
2479 result.AppendError("empty typenames not allowed");
2480 return;
2481 }
2482
2483 ConstString typeCS(arg_entry.ref());
2484 if (!AddFilter(typeCS, entry,
2487 result.AppendError(error.AsCString());
2488 return;
2490 }
2491
2493 }
2494};
2495
2496// "type lookup"
2497#define LLDB_OPTIONS_type_lookup
2498#include "CommandOptions.inc"
2499
2501protected:
2502 // this function is allowed to do a more aggressive job at guessing languages
2503 // than the expression parser is comfortable with - so leave the original
2504 // call alone and add one that is specific to type lookup
2507
2508 if (!frame)
2509 return lang_type;
2510
2511 lang_type = frame->GuessLanguage();
2512 if (lang_type != lldb::eLanguageTypeUnknown)
2513 return lang_type;
2515 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2516 if (s)
2517 lang_type = s->GetMangled().GuessLanguage();
2519 return lang_type;
2520 }
2521
2522 class CommandOptions : public OptionGroup {
2523 public:
2524 CommandOptions() = default;
2525
2526 ~CommandOptions() override = default;
2527
2528 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2529 return llvm::ArrayRef(g_type_lookup_options);
2530 }
2531
2532 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2533 ExecutionContext *execution_context) override {
2534 Status error;
2535
2536 const int short_option = g_type_lookup_options[option_idx].short_option;
2537
2538 switch (short_option) {
2539 case 'h':
2540 m_show_help = true;
2541 break;
2542
2543 case 'l':
2545 break;
2546
2547 default:
2548 llvm_unreachable("Unimplemented option");
2549 }
2550
2551 return error;
2552 }
2553
2554 void OptionParsingStarting(ExecutionContext *execution_context) override {
2555 m_show_help = false;
2557 }
2558
2559 // Options table: Required for subclasses of Options.
2560
2561 bool m_show_help = false;
2563 };
2564
2566 CommandOptions m_command_options;
2567
2568public:
2570 : CommandObjectRaw(interpreter, "type lookup",
2571 "Lookup types and declarations in the current target, "
2572 "following language-specific naming conventions.",
2573 "type lookup <type-specifier>",
2574 eCommandRequiresTarget) {
2577 }
2578
2579 ~CommandObjectTypeLookup() override = default;
2580
2581 Options *GetOptions() override { return &m_option_group; }
2582
2583 llvm::StringRef GetHelpLong() override {
2584 if (!m_cmd_help_long.empty())
2585 return m_cmd_help_long;
2586
2587 StreamString stream;
2588 Language::ForEach([&](Language *lang) {
2589 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2590 stream.Printf("%s\n", help);
2591 return true;
2592 });
2593
2594 m_cmd_help_long = std::string(stream.GetString());
2595 return m_cmd_help_long;
2596 }
2597
2598 void DoExecute(llvm::StringRef raw_command_line,
2599 CommandReturnObject &result) override {
2600 if (raw_command_line.empty()) {
2601 result.AppendError(
2602 "type lookup cannot be invoked without a type name as argument");
2603 return;
2604 }
2605
2606 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2608
2609 OptionsWithRaw args(raw_command_line);
2610 const char *name_of_type = args.GetRawPart().c_str();
2611
2612 if (args.HasArgs())
2613 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2614 exe_ctx))
2615 return;
2616
2617 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2618
2619 bool any_found = false;
2620
2621 std::vector<Language *> languages;
2622
2623 bool is_global_search = false;
2624 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2625
2626 if ((is_global_search =
2628 Language::ForEach([&](Language *lang) {
2629 languages.push_back(lang);
2630 return true;
2631 });
2632 } else {
2635
2636 // This is not the most efficient way to do this, but we support very few
2637 // languages so the cost of the sort is going to be dwarfed by the actual
2638 // lookup anyway
2639 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
2640 guessed_language = GuessLanguage(frame);
2641 if (guessed_language != eLanguageTypeUnknown) {
2642 llvm::sort(
2643 languages.begin(), languages.end(),
2644 [guessed_language](Language *lang1, Language *lang2) -> bool {
2645 if (!lang1 || !lang2)
2646 return false;
2647 LanguageType lt1 = lang1->GetLanguageType();
2648 LanguageType lt2 = lang2->GetLanguageType();
2649 if (lt1 == guessed_language)
2650 return true; // make the selected frame's language come first
2651 if (lt2 == guessed_language)
2652 return false; // make the selected frame's language come first
2653 return (lt1 < lt2); // normal comparison otherwise
2654 });
2655 }
2656 }
2658 bool is_first_language = true;
2659
2660 for (Language *language : languages) {
2661 if (!language)
2662 continue;
2663
2664 if (auto scavenger = language->GetTypeScavenger()) {
2666 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2667 for (const auto &search_result : search_results) {
2668 if (search_result && search_result->IsValid()) {
2669 any_found = true;
2670 search_result->DumpToStream(result.GetOutputStream(),
2671 this->m_command_options.m_show_help);
2672 }
2673 }
2674 }
2675 }
2676 // this is "type lookup SomeName" and we did find a match, so get out
2677 if (any_found && is_global_search)
2678 break;
2679 else if (is_first_language && is_global_search &&
2680 guessed_language != lldb::eLanguageTypeUnknown) {
2681 is_first_language = false;
2682 result.GetOutputStream().Printf(
2683 "no type was found in the current language %s matching '%s'; "
2684 "performing a global search across all languages\n",
2685 Language::GetNameForLanguageType(guessed_language), name_of_type);
2686 }
2687 }
2688
2689 if (!any_found)
2690 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2691 name_of_type);
2692
2695 }
2696};
2697
2698template <typename FormatterType>
2700public:
2701 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2704 const char *formatter_name,
2705 DiscoveryFunction discovery_func)
2706 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2707 m_formatter_name(formatter_name ? formatter_name : ""),
2708 m_discovery_function(discovery_func) {
2709 StreamString name;
2710 name.Printf("type %s info", formatter_name);
2711 SetCommandName(name.GetString());
2712 StreamString help;
2713 help.Printf("This command evaluates the provided expression and shows "
2714 "which %s is applied to the resulting value (if any).",
2715 formatter_name);
2716 SetHelp(help.GetString());
2717 StreamString syntax;
2718 syntax.Printf("type %s info <expr>", formatter_name);
2719 SetSyntax(syntax.GetString());
2720 }
2721
2722 ~CommandObjectFormatterInfo() override = default;
2723
2724protected:
2725 void DoExecute(llvm::StringRef command,
2726 CommandReturnObject &result) override {
2727 TargetSP target_sp = GetDebugger().GetSelectedTarget();
2728 Thread *thread = GetDefaultThread();
2729 if (!thread) {
2730 result.AppendError("no default thread");
2731 return;
2733
2734 StackFrameSP frame_sp =
2736 ValueObjectSP result_valobj_sp;
2738 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2739 command, frame_sp.get(), result_valobj_sp, options);
2740 if (expr_result == eExpressionCompleted && result_valobj_sp) {
2741 result_valobj_sp =
2742 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2743 target_sp->GetPreferDynamicValue(),
2744 target_sp->GetEnableSyntheticValue());
2745 typename FormatterType::SharedPointer formatter_sp =
2746 m_discovery_function(*result_valobj_sp);
2747 if (formatter_sp) {
2748 std::string description(formatter_sp->GetDescription());
2749 result.GetOutputStream()
2750 << m_formatter_name << " applied to ("
2751 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2752 << ") " << command << " is: " << description << "\n";
2754 } else {
2755 result.GetOutputStream()
2756 << "no " << m_formatter_name << " applies to ("
2757 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2758 << ") " << command << "\n";
2760 }
2761 } else {
2762 result.AppendError("failed to evaluate expression");
2763 }
2764 }
2765
2766private:
2767 std::string m_formatter_name;
2769};
2770
2772public:
2775 interpreter, "type format",
2776 "Commands for customizing value display formats.",
2777 "type format [<sub-command-options>] ") {
2779 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2781 new CommandObjectTypeFormatClear(interpreter)));
2783 interpreter)));
2785 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2788 interpreter, "format",
2790 return valobj.GetValueFormat();
2791 })));
2792 }
2793
2794 ~CommandObjectTypeFormat() override = default;
2795};
2796
2798public:
2801 interpreter, "type synthetic",
2802 "Commands for operating on synthetic type representations.",
2803 "type synthetic [<sub-command-options>] ") {
2804 LoadSubCommand("add",
2807 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2809 interpreter)));
2811 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2813 "info",
2815 interpreter, "synthetic",
2817 return valobj.GetSyntheticChildren();
2818 })));
2819 }
2820
2821 ~CommandObjectTypeSynth() override = default;
2822};
2823
2825public:
2827 : CommandObjectMultiword(interpreter, "type filter",
2828 "Commands for operating on type filters.",
2829 "type filter [<sub-command-options>] ") {
2833 new CommandObjectTypeFilterClear(interpreter)));
2835 interpreter)));
2837 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2838 }
2839
2840 ~CommandObjectTypeFilter() override = default;
2841};
2842
2844public:
2846 : CommandObjectMultiword(interpreter, "type category",
2847 "Commands for operating on type categories.",
2848 "type category [<sub-command-options>] ") {
2850 "define",
2853 "enable",
2856 "disable",
2859 "delete",
2862 new CommandObjectTypeCategoryList(interpreter)));
2863 }
2864
2865 ~CommandObjectTypeCategory() override = default;
2866};
2867
2869public:
2872 interpreter, "type summary",
2873 "Commands for editing variable summary display options.",
2874 "type summary [<sub-command-options>] ") {
2876 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
2878 interpreter)));
2880 interpreter)));
2882 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
2885 interpreter, "summary",
2887 return valobj.GetSummaryFormat();
2888 })));
2889 }
2890
2891 ~CommandObjectTypeSummary() override = default;
2892};
2893
2894// CommandObjectType
2895
2897 : CommandObjectMultiword(interpreter, "type",
2898 "Commands for operating on the type system.",
2899 "type [<sub-command-options>]") {
2900 LoadSubCommand("category",
2901 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
2902 LoadSubCommand("filter",
2903 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
2904 LoadSubCommand("format",
2905 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
2906 LoadSubCommand("summary",
2907 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
2908 LoadSubCommand("synthetic",
2909 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
2910 LoadSubCommand("lookup",
2911 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
2912}
2913
2915
static const char * g_synth_addreader_instructions
static bool WarnOnPotentialUnquotedUnsignedType(Args &command, CommandReturnObject &result)
const char * FormatCategoryToString(FormatCategoryItem item, bool long_name)
static bool FixArrayTypeNameWithRegex(ConstString &type_name)
static llvm::raw_ostream & error(Stream &strm)
~CommandObjectFormatterInfo() override=default
DiscoveryFunction m_discovery_function
void DoExecute(llvm::StringRef command, CommandReturnObject &result) override
std::function< typename FormatterType::SharedPointer(ValueObject &)> DiscoveryFunction
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
~CommandObjectTypeCategoryDefine() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeCategoryDelete() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeCategoryDisable() override=default
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeCategoryEnable() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
~CommandObjectTypeCategoryList() override=default
~CommandObjectTypeCategory() override=default
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
~CommandObjectTypeFilterAdd() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
Options * GetOptions() override
bool AddFilter(ConstString type_name, TypeFilterImplSP entry, FilterFormatType type, std::string category_name, Status *error)
~CommandObjectTypeFilterDelete() override=default
~CommandObjectTypeFilter() override=default
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Options * GetOptions() override
CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
OptionGroupOptions m_option_group
OptionGroupFormat m_format_options
~CommandObjectTypeFormatAdd() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
~CommandObjectTypeFormatDelete() override=default
CommandObjectTypeFormatList(CommandInterpreter &interpreter)
~CommandObjectTypeFormat() override=default
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
CommandObjectTypeFormatterClear(CommandInterpreter &interpreter, FormatCategoryItem formatter_kind, const char *name, const char *help)
~CommandObjectTypeFormatterClear() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
static constexpr const char * g_long_help_template
virtual bool FormatterSpecificDeletion(ConstString typeCS)
static constexpr const char * g_short_help_template
~CommandObjectTypeFormatterDelete() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter, FormatCategoryItem formatter_kind)
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
void DoExecute(Args &command, CommandReturnObject &result) override
FormatterType::SharedPointer FormatterSharedPointer
virtual bool FormatterSpecificList(CommandReturnObject &result)
static bool ShouldListItem(llvm::StringRef s, RegularExpression *regex)
CommandObjectTypeFormatterList(CommandInterpreter &interpreter, const char *name, const char *help)
~CommandObjectTypeFormatterList() override=default
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override
OptionGroupOptions m_option_group
void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override
lldb::LanguageType GuessLanguage(StackFrame *frame)
~CommandObjectTypeLookup() override=default
llvm::StringRef GetHelpLong() override
Options * GetOptions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
CommandOptions(CommandInterpreter &interpreter)
~CommandObjectTypeSummaryAdd() override=default
Options * GetOptions() override
bool Execute_ScriptSummary(Args &command, CommandReturnObject &result)
void DoExecute(Args &command, CommandReturnObject &result) override
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
bool Execute_StringSummary(Args &command, CommandReturnObject &result)
CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter)
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
bool AddNamedSummary(ConstString summary_name, lldb::TypeSummaryImplSP entry, Status *error=nullptr)
bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, FormatterMatchType match_type, std::string category, Status *error=nullptr)
~CommandObjectTypeSummaryDelete() override=default
bool FormatterSpecificDeletion(ConstString typeCS) override
bool FormatterSpecificList(CommandReturnObject &result) override
~CommandObjectTypeSummary() override=default
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
CommandObjectTypeSynthAdd(CommandInterpreter &interpreter)
bool Execute_PythonClass(Args &command, CommandReturnObject &result)
bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry, FormatterMatchType match_type, std::string category_name, Status *error)
Options * GetOptions() override
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeSynthAdd() override=default
bool Execute_HandwritePython(Args &command, CommandReturnObject &result)
~CommandObjectTypeSynthDelete() override=default
~CommandObjectTypeSynth() override=default
std::shared_ptr< ScriptAddOptions > SharedPointer
TypeSummaryImpl::Flags m_flags
ScriptAddOptions(const TypeSummaryImpl::Flags &flags, FormatterMatchType match_type, ConstString name, std::string catg)
FormatterMatchType m_match_type
std::string m_category
FormatterMatchType m_match_type
StringList m_target_types
std::shared_ptr< SynthAddOptions > SharedPointer
SynthAddOptions(bool sptr, bool sref, bool casc, FormatterMatchType match_type, std::string catg)
A command line argument class.
Definition: Args.h:33
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:128
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:263
bool empty() const
Definition: Args.h:118
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
ExecutionContext GetExecutionContext() const
void GetPythonCommandsFromIOHandler(const char *prompt, IOHandlerDelegate &delegate, void *baton=nullptr)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandObjectType(CommandInterpreter &interpreter)
virtual void SetHelpLong(llvm::StringRef str)
void AddSimpleArgumentList(lldb::CommandArgumentType arg_type, ArgumentRepetitionType repetition_type=eArgRepeatPlain)
bool ParseOptionsAndNotify(Args &args, CommandReturnObject &result, OptionGroupOptions &group_options, ExecutionContext &exe_ctx)
ExecutionContext m_exe_ctx
CommandInterpreter & GetCommandInterpreter()
CommandInterpreter & m_interpreter
void SetSyntax(llvm::StringRef str)
void SetCommandName(llvm::StringRef name)
virtual void SetHelp(llvm::StringRef str)
void void AppendError(llvm::StringRef in_string)
void AppendWarningWithFormat(const char *format,...) __attribute__((format(printf
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
void void AppendWarning(llvm::StringRef in_string)
"lldb/Utility/ArgCompletionRequest.h"
A uniqued constant string class.
Definition: ConstString.h:40
void SetCString(const char *cstr)
Set the C string value.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:188
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:197
void SetString(llvm::StringRef s)
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:214
static bool Delete(ConstString category)
static void Disable(ConstString category)
static void ForEach(TypeCategoryMap::ForEachCallback callback)
static void Enable(ConstString category, TypeCategoryMap::Position=TypeCategoryMap::Default)
static bool GetCategory(ConstString category, lldb::TypeCategoryImplSP &entry, bool allow_create=true)
static void Add(ConstString type, const lldb::TypeSummaryImplSP &entry)
static void ForEach(std::function< bool(const TypeMatcher &, const lldb::TypeSummaryImplSP &)> callback)
lldb::TargetSP GetSelectedTarget()
Definition: Debugger.h:193
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
Definition: Debugger.cpp:1649
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
ValueType Clear(ValueType mask=~static_cast< ValueType >(0))
Clear one or more flags.
Definition: Flags.h:61
lldb::StreamFileSP GetErrorStreamFileSP()
Definition: IOHandler.cpp:107
lldb::StreamFileSP GetOutputStreamFileSP()
Definition: IOHandler.cpp:105
void SetIsDone(bool b)
Definition: IOHandler.h:86
std::set< std::unique_ptr< Result > > ResultSet
Definition: Language.h:52
static Language * FindPlugin(lldb::LanguageType language)
Definition: Language.cpp:83
static const char * GetNameForLanguageType(lldb::LanguageType language)
Definition: Language.cpp:265
virtual const char * GetLanguageSpecificTypeLookupHelp()
Definition: Language.cpp:439
static lldb::LanguageType GetLanguageTypeFromString(const char *string)=delete
static void ForEach(std::function< bool(Language *)> callback)
Definition: Language.cpp:130
lldb::LanguageType GuessLanguage() const
Try to guess the language from the mangling.
Definition: Mangled.cpp:381
static const uint32_t OPTION_GROUP_FORMAT
void Append(OptionGroup *group)
Append options from a OptionGroup class.
Definition: Options.cpp:755
Status SetValueFromString(llvm::StringRef value, VarSetOperationType op=eVarSetOperationAssign) override
lldb::LanguageType GetCurrentValue() const
Status SetValueFromString(llvm::StringRef value, VarSetOperationType op=eVarSetOperationAssign) override
llvm::StringRef GetCurrentValueAsRef() const
Status SetCurrentValue(llvm::StringRef value)
A pair of an option list with a 'raw' string as a suffix.
Definition: Args.h:315
A command line option parsing protocol class.
Definition: Options.h:58
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition: Options.cpp:33
std::vector< Option > m_getopt_table
Definition: Options.h:198
bool IsValid() const
Test if this object contains a valid regular expression.
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
llvm::StringRef GetText() const
Access the regular expression text.
virtual bool GenerateTypeScriptFunction(const char *oneliner, std::string &output, const void *name_token=nullptr)
virtual bool GenerateTypeSynthClass(StringList &input, std::string &output, const void *name_token=nullptr)
virtual bool CheckObjectExists(const char *name)
This base class provides an interface to stack frames.
Definition: StackFrame.h:42
const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
Definition: StackFrame.cpp:300
lldb::LanguageType GuessLanguage()
An error handling class.
Definition: Status.h:44
const char * GetData() const
Definition: StreamString.h:43
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
std::string CopyList(const char *item_preamble=nullptr, const char *items_sep="\n") const
Definition: StringList.cpp:198
size_t SplitIntoLines(const std::string &lines)
Definition: StringList.cpp:152
size_t GetSize() const
Definition: StringList.cpp:74
Symbol * symbol
The Symbol for a given query.
Mangled & GetMangled()
Definition: Symbol.h:146
Flags & SetSkipReferences(bool value=true)
Flags & SetSkipPointers(bool value=true)
std::shared_ptr< SyntheticChildren > SharedPointer
lldb::StackFrameSP GetSelectedFrame(SelectMostRelevant select_most_relevant)
Definition: Thread.cpp:265
static const Position Default
Flags & SetCascades(bool value=true)
Definition: TypeFormat.h:55
Flags & SetSkipReferences(bool value=true)
Definition: TypeFormat.h:81
Flags & SetSkipPointers(bool value=true)
Definition: TypeFormat.h:68
std::shared_ptr< TypeFormatImpl > SharedPointer
Definition: TypeFormat.h:112
Class for matching type names.
ConstString GetMatchString() const
Returns the underlying match string for this TypeMatcher.
Flags & SetCascades(bool value=true)
Definition: TypeSummary.h:82
Flags & SetHideEmptyAggregates(bool value=true)
Definition: TypeSummary.h:134
Flags & SetSkipPointers(bool value=true)
Definition: TypeSummary.h:95
Flags & SetHideItemNames(bool value=true)
Definition: TypeSummary.h:173
Flags & SetDontShowChildren(bool value=true)
Definition: TypeSummary.h:121
Flags & SetSkipReferences(bool value=true)
Definition: TypeSummary.h:108
Flags & SetShowMembersOneLiner(bool value=true)
Definition: TypeSummary.h:160
Flags & SetDontShowValue(bool value=true)
Definition: TypeSummary.h:147
std::shared_ptr< TypeSummaryImpl > SharedPointer
Definition: TypeSummary.h:263
lldb::TypeFormatImplSP GetValueFormat()
Definition: ValueObject.h:727
lldb::TypeSummaryImplSP GetSummaryFormat()
Definition: ValueObject.h:712
lldb::SyntheticChildrenSP GetSyntheticChildren()
Definition: ValueObject.h:739
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:111
@ DoNoSelectMostRelevantFrame
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:43
FormatCategoryItem
Format category entry types.
Definition: SBAddress.h:15
@ eTypeCategoryNameCompletion
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:412
std::shared_ptr< lldb_private::TypeSummaryImpl > TypeSummaryImplSP
Definition: lldb-forward.h:463
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
Definition: lldb-forward.h:325
std::shared_ptr< lldb_private::TypeFormatImpl > TypeFormatImplSP
Definition: lldb-forward.h:460
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:472
Format
Display format definitions.
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
FormatterMatchType
Type of match to be performed when looking for a formatter for a data type.
@ eFormatterMatchExact
@ eFormatterMatchRegex
@ eFormatterMatchCallback
ExpressionResults
The results of expression evaluation.
@ eExpressionCompleted
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
Definition: lldb-forward.h:421
std::shared_ptr< lldb_private::SyntheticChildren > SyntheticChildrenSP
Definition: lldb-forward.h:433
std::shared_ptr< lldb_private::TypeCategoryImpl > TypeCategoryImplSP
Definition: lldb-forward.h:451
std::shared_ptr< lldb_private::TypeFilterImpl > TypeFilterImplSP
Definition: lldb-forward.h:456
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:436
static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr)