@@ -333,6 +333,7 @@ class Deserializer {
333
333
}
334
334
335
335
template <typename T> const T &HandleReplayResult (const T &t) {
336
+ CheckSequence (Deserialize<unsigned >());
336
337
unsigned result = Deserialize<unsigned >();
337
338
if (is_trivially_serializable<T>::value)
338
339
return t;
@@ -342,6 +343,7 @@ class Deserializer {
342
343
343
344
// / Store the returned value in the index-to-object mapping.
344
345
template <typename T> T &HandleReplayResult (T &t) {
346
+ CheckSequence (Deserialize<unsigned >());
345
347
unsigned result = Deserialize<unsigned >();
346
348
if (is_trivially_serializable<T>::value)
347
349
return t;
@@ -351,6 +353,7 @@ class Deserializer {
351
353
352
354
// / Store the returned value in the index-to-object mapping.
353
355
template <typename T> T *HandleReplayResult (T *t) {
356
+ CheckSequence (Deserialize<unsigned >());
354
357
unsigned result = Deserialize<unsigned >();
355
358
if (is_trivially_serializable<T>::value)
356
359
return t;
@@ -360,6 +363,7 @@ class Deserializer {
360
363
// / All returned types are recorded, even when the function returns a void.
361
364
// / The latter requires special handling.
362
365
void HandleReplayResultVoid () {
366
+ CheckSequence (Deserialize<unsigned >());
363
367
unsigned result = Deserialize<unsigned >();
364
368
assert (result == 0 );
365
369
(void )result;
@@ -369,6 +373,10 @@ class Deserializer {
369
373
return m_index_to_object.GetAllObjects ();
370
374
}
371
375
376
+ void SetExpectedSequence (unsigned sequence) {
377
+ m_expected_sequence = sequence;
378
+ }
379
+
372
380
private:
373
381
template <typename T> T Read (ValueTag) {
374
382
assert (HasData (sizeof (T)));
@@ -410,11 +418,17 @@ class Deserializer {
410
418
return *(new UnderlyingT (Deserialize<UnderlyingT>()));
411
419
}
412
420
421
+ // / Verify that the given sequence number matches what we expect.
422
+ void CheckSequence (unsigned sequence);
423
+
413
424
// / Mapping of indices to objects.
414
425
IndexToObject m_index_to_object;
415
426
416
427
// / Buffer containing the serialized data.
417
428
llvm::StringRef m_buffer;
429
+
430
+ // / The result's expected sequence number.
431
+ llvm::Optional<unsigned > m_expected_sequence;
418
432
};
419
433
420
434
// / Partial specialization for C-style strings. We read the string value
@@ -745,19 +759,23 @@ class Recorder {
745
759
if (!ShouldCapture ())
746
760
return ;
747
761
762
+ std::lock_guard<std::mutex> lock (g_mutex);
763
+ unsigned sequence = GetSequenceNumber ();
748
764
unsigned id = registry.GetID (uintptr_t (f));
749
765
750
766
#ifdef LLDB_REPRO_INSTR_TRACE
751
767
Log (id);
752
768
#endif
753
769
770
+ serializer.SerializeAll (sequence);
754
771
serializer.SerializeAll (id);
755
772
serializer.SerializeAll (args...);
756
773
757
774
if (std::is_class<typename std::remove_pointer<
758
775
typename std::remove_reference<Result>::type>::type>::value) {
759
776
m_result_recorded = false ;
760
777
} else {
778
+ serializer.SerializeAll (sequence);
761
779
serializer.SerializeAll (0 );
762
780
m_result_recorded = true ;
763
781
}
@@ -771,16 +789,20 @@ class Recorder {
771
789
if (!ShouldCapture ())
772
790
return ;
773
791
792
+ std::lock_guard<std::mutex> lock (g_mutex);
793
+ unsigned sequence = GetSequenceNumber ();
774
794
unsigned id = registry.GetID (uintptr_t (f));
775
795
776
796
#ifdef LLDB_REPRO_INSTR_TRACE
777
797
Log (id);
778
798
#endif
779
799
800
+ serializer.SerializeAll (sequence);
780
801
serializer.SerializeAll (id);
781
802
serializer.SerializeAll (args...);
782
803
783
804
// Record result.
805
+ serializer.SerializeAll (sequence);
784
806
serializer.SerializeAll (0 );
785
807
m_result_recorded = true ;
786
808
}
@@ -806,7 +828,9 @@ class Recorder {
806
828
if (update_boundary)
807
829
UpdateBoundary ();
808
830
if (m_serializer && ShouldCapture ()) {
831
+ std::lock_guard<std::mutex> lock (g_mutex);
809
832
assert (!m_result_recorded);
833
+ m_serializer->SerializeAll (GetSequenceNumber ());
810
834
m_serializer->SerializeAll (r);
811
835
m_result_recorded = true ;
812
836
}
@@ -816,6 +840,7 @@ class Recorder {
816
840
template <typename Result, typename T>
817
841
Result Replay (Deserializer &deserializer, Registry ®istry, uintptr_t addr,
818
842
bool update_boundary) {
843
+ deserializer.SetExpectedSequence (deserializer.Deserialize <unsigned >());
819
844
unsigned actual_id = registry.GetID (addr);
820
845
unsigned id = deserializer.Deserialize <unsigned >();
821
846
registry.CheckID (id, actual_id);
@@ -826,6 +851,7 @@ class Recorder {
826
851
}
827
852
828
853
void Replay (Deserializer &deserializer, Registry ®istry, uintptr_t addr) {
854
+ deserializer.SetExpectedSequence (deserializer.Deserialize <unsigned >());
829
855
unsigned actual_id = registry.GetID (addr);
830
856
unsigned id = deserializer.Deserialize <unsigned >();
831
857
registry.CheckID (id, actual_id);
@@ -846,6 +872,9 @@ class Recorder {
846
872
static void PrivateThread () { g_global_boundary = true ; }
847
873
848
874
private:
875
+ static unsigned GetNextSequenceNumber () { return g_sequence++; }
876
+ unsigned GetSequenceNumber () const ;
877
+
849
878
template <typename T> friend struct replay ;
850
879
void UpdateBoundary () {
851
880
if (m_local_boundary)
@@ -871,8 +900,17 @@ class Recorder {
871
900
// / Whether the return value was recorded explicitly.
872
901
bool m_result_recorded;
873
902
903
+ // / The sequence number for this pair of function and result.
904
+ unsigned m_sequence;
905
+
874
906
// / Whether we're currently across the API boundary.
875
907
static thread_local bool g_global_boundary;
908
+
909
+ // / Global mutex to protect concurrent access.
910
+ static std::mutex g_mutex;
911
+
912
+ // / Unique, monotonically increasing sequence number.
913
+ static std::atomic<unsigned > g_sequence;
876
914
};
877
915
878
916
// / To be used as the "Runtime ID" of a constructor. It also invokes the
@@ -1014,6 +1052,7 @@ struct invoke_char_ptr<Result (Class::*)(Args...) const> {
1014
1052
1015
1053
static Result replay (Recorder &recorder, Deserializer &deserializer,
1016
1054
Registry ®istry, char *str) {
1055
+ deserializer.SetExpectedSequence (deserializer.Deserialize <unsigned >());
1017
1056
deserializer.Deserialize <unsigned >();
1018
1057
Class *c = deserializer.Deserialize <Class *>();
1019
1058
deserializer.Deserialize <const char *>();
@@ -1035,6 +1074,7 @@ struct invoke_char_ptr<Result (Class::*)(Args...)> {
1035
1074
1036
1075
static Result replay (Recorder &recorder, Deserializer &deserializer,
1037
1076
Registry ®istry, char *str) {
1077
+ deserializer.SetExpectedSequence (deserializer.Deserialize <unsigned >());
1038
1078
deserializer.Deserialize <unsigned >();
1039
1079
Class *c = deserializer.Deserialize <Class *>();
1040
1080
deserializer.Deserialize <const char *>();
@@ -1055,6 +1095,7 @@ struct invoke_char_ptr<Result (*)(Args...)> {
1055
1095
1056
1096
static Result replay (Recorder &recorder, Deserializer &deserializer,
1057
1097
Registry ®istry, char *str) {
1098
+ deserializer.SetExpectedSequence (deserializer.Deserialize <unsigned >());
1058
1099
deserializer.Deserialize <unsigned >();
1059
1100
deserializer.Deserialize <const char *>();
1060
1101
size_t l = deserializer.Deserialize <size_t >();
0 commit comments