@@ -116,6 +116,9 @@ static constexpr OptionEnumValues ReproducerSignalType() {
116
116
#define LLDB_OPTIONS_reproducer_xcrash
117
117
#include " CommandOptions.inc"
118
118
119
+ #define LLDB_OPTIONS_reproducer_verify
120
+ #include " CommandOptions.inc"
121
+
119
122
template <typename T>
120
123
llvm::Expected<T> static ReadFromYAML (StringRef filename) {
121
124
auto error_or_file = MemoryBuffer::getFile (filename);
@@ -134,6 +137,38 @@ llvm::Expected<T> static ReadFromYAML(StringRef filename) {
134
137
return t;
135
138
}
136
139
140
+ static void SetError (CommandReturnObject &result, Error err) {
141
+ result.GetErrorStream ().Printf (" error: %s\n " ,
142
+ toString (std::move (err)).c_str ());
143
+ result.SetStatus (eReturnStatusFailed);
144
+ }
145
+
146
+ // / Create a loader from the given path if specified. Otherwise use the current
147
+ // / loader used for replay.
148
+ static Loader *
149
+ GetLoaderFromPathOrCurrent (llvm::Optional<Loader> &loader_storage,
150
+ CommandReturnObject &result,
151
+ FileSpec reproducer_path) {
152
+ if (reproducer_path) {
153
+ loader_storage.emplace (reproducer_path);
154
+ Loader *loader = &(*loader_storage);
155
+ if (Error err = loader->LoadIndex ()) {
156
+ // This is a hard error and will set the result to eReturnStatusFailed.
157
+ SetError (result, std::move (err));
158
+ return nullptr ;
159
+ }
160
+ return loader;
161
+ }
162
+
163
+ if (Loader *loader = Reproducer::Instance ().GetLoader ())
164
+ return loader;
165
+
166
+ // This is a soft error because this is expected to fail during capture.
167
+ result.SetError (" Not specifying a reproducer is only support during replay." );
168
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
169
+ return nullptr ;
170
+ }
171
+
137
172
class CommandObjectReproducerGenerate : public CommandObjectParsed {
138
173
public:
139
174
CommandObjectReproducerGenerate (CommandInterpreter &interpreter)
@@ -312,12 +347,6 @@ class CommandObjectReproducerStatus : public CommandObjectParsed {
312
347
}
313
348
};
314
349
315
- static void SetError (CommandReturnObject &result, Error err) {
316
- result.GetErrorStream ().Printf (" error: %s\n " ,
317
- toString (std::move (err)).c_str ());
318
- result.SetStatus (eReturnStatusFailed);
319
- }
320
-
321
350
class CommandObjectReproducerDump : public CommandObjectParsed {
322
351
public:
323
352
CommandObjectReproducerDump (CommandInterpreter &interpreter)
@@ -382,29 +411,11 @@ class CommandObjectReproducerDump : public CommandObjectParsed {
382
411
return false ;
383
412
}
384
413
385
- // If no reproducer path is specified, use the loader currently used for
386
- // replay. Otherwise create a new loader just for dumping.
387
414
llvm::Optional<Loader> loader_storage;
388
- Loader *loader = nullptr ;
389
- if (!m_options.file ) {
390
- loader = Reproducer::Instance ().GetLoader ();
391
- if (loader == nullptr ) {
392
- result.SetError (
393
- " Not specifying a reproducer is only support during replay." );
394
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
395
- return false ;
396
- }
397
- } else {
398
- loader_storage.emplace (m_options.file );
399
- loader = &(*loader_storage);
400
- if (Error err = loader->LoadIndex ()) {
401
- SetError (result, std::move (err));
402
- return false ;
403
- }
404
- }
405
-
406
- // If we get here we should have a valid loader.
407
- assert (loader);
415
+ Loader *loader =
416
+ GetLoaderFromPathOrCurrent (loader_storage, result, m_options.file );
417
+ if (!loader)
418
+ return false ;
408
419
409
420
switch (m_options.provider ) {
410
421
case eReproducerProviderFiles: {
@@ -583,6 +594,101 @@ class CommandObjectReproducerDump : public CommandObjectParsed {
583
594
CommandOptions m_options;
584
595
};
585
596
597
+ class CommandObjectReproducerVerify : public CommandObjectParsed {
598
+ public:
599
+ CommandObjectReproducerVerify (CommandInterpreter &interpreter)
600
+ : CommandObjectParsed(interpreter, " reproducer verify" ,
601
+ " Verify the contents of a reproducer. "
602
+ " If no reproducer is specified during replay, it "
603
+ " verifies the content of the current reproducer." ,
604
+ nullptr ) {}
605
+
606
+ ~CommandObjectReproducerVerify () override = default ;
607
+
608
+ Options *GetOptions () override { return &m_options; }
609
+
610
+ class CommandOptions : public Options {
611
+ public:
612
+ CommandOptions () : Options(), file() {}
613
+
614
+ ~CommandOptions () override = default ;
615
+
616
+ Status SetOptionValue (uint32_t option_idx, StringRef option_arg,
617
+ ExecutionContext *execution_context) override {
618
+ Status error;
619
+ const int short_option = m_getopt_table[option_idx].val ;
620
+
621
+ switch (short_option) {
622
+ case ' f' :
623
+ file.SetFile (option_arg, FileSpec::Style::native);
624
+ FileSystem::Instance ().Resolve (file);
625
+ break ;
626
+ default :
627
+ llvm_unreachable (" Unimplemented option" );
628
+ }
629
+
630
+ return error;
631
+ }
632
+
633
+ void OptionParsingStarting (ExecutionContext *execution_context) override {
634
+ file.Clear ();
635
+ }
636
+
637
+ ArrayRef<OptionDefinition> GetDefinitions () override {
638
+ return makeArrayRef (g_reproducer_verify_options);
639
+ }
640
+
641
+ FileSpec file;
642
+ };
643
+
644
+ protected:
645
+ bool DoExecute (Args &command, CommandReturnObject &result) override {
646
+ if (!command.empty ()) {
647
+ result.AppendErrorWithFormat (" '%s' takes no arguments" ,
648
+ m_cmd_name.c_str ());
649
+ return false ;
650
+ }
651
+
652
+ llvm::Optional<Loader> loader_storage;
653
+ Loader *loader =
654
+ GetLoaderFromPathOrCurrent (loader_storage, result, m_options.file );
655
+ if (!loader)
656
+ return false ;
657
+
658
+ bool errors = false ;
659
+ auto error_callback = [&](llvm::StringRef error) {
660
+ errors = true ;
661
+ result.AppendError (error);
662
+ };
663
+
664
+ bool warnings = false ;
665
+ auto warning_callback = [&](llvm::StringRef warning) {
666
+ warnings = true ;
667
+ result.AppendWarning (warning);
668
+ };
669
+
670
+ auto note_callback = [&](llvm::StringRef warning) {
671
+ result.AppendMessage (warning);
672
+ };
673
+
674
+ Verifier verifier (loader);
675
+ verifier.Verify (error_callback, warning_callback, note_callback);
676
+
677
+ if (warnings || errors) {
678
+ result.AppendMessage (" reproducer verification failed" );
679
+ result.SetStatus (eReturnStatusFailed);
680
+ } else {
681
+ result.AppendMessage (" reproducer verification succeeded" );
682
+ result.SetStatus (eReturnStatusSuccessFinishResult);
683
+ }
684
+
685
+ return result.Succeeded ();
686
+ }
687
+
688
+ private:
689
+ CommandOptions m_options;
690
+ };
691
+
586
692
CommandObjectReproducer::CommandObjectReproducer (
587
693
CommandInterpreter &interpreter)
588
694
: CommandObjectMultiword(
@@ -605,6 +711,8 @@ CommandObjectReproducer::CommandObjectReproducer(
605
711
new CommandObjectReproducerStatus (interpreter)));
606
712
LoadSubCommand (" dump" ,
607
713
CommandObjectSP (new CommandObjectReproducerDump (interpreter)));
714
+ LoadSubCommand (" verify" , CommandObjectSP (
715
+ new CommandObjectReproducerVerify (interpreter)));
608
716
LoadSubCommand (" xcrash" , CommandObjectSP (
609
717
new CommandObjectReproducerXCrash (interpreter)));
610
718
}
0 commit comments