JDevlieghere updated this revision to Diff 257068.
JDevlieghere added a comment.

Rebase + add unit tests


Repository:
  rLLDB LLDB

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77759/new/

https://reviews.llvm.org/D77759

Files:
  lldb/include/lldb/Utility/ReproducerInstrumentation.h
  lldb/source/API/SBDebugger.cpp
  lldb/source/API/SBFileSpec.cpp
  lldb/source/API/SBProcess.cpp
  lldb/source/API/SBStructuredData.cpp
  lldb/source/API/SBThread.cpp
  lldb/unittests/Utility/ReproducerInstrumentationTest.cpp

Index: lldb/unittests/Utility/ReproducerInstrumentationTest.cpp
===================================================================
--- lldb/unittests/Utility/ReproducerInstrumentationTest.cpp
+++ lldb/unittests/Utility/ReproducerInstrumentationTest.cpp
@@ -125,7 +125,7 @@
   int C(float *c);
   float GetC();
   int D(const char *d) const;
-  void GetD(char *buffer, size_t length);
+  size_t GetD(char *buffer, size_t length);
   static void E(double e);
   double GetE();
   static int F();
@@ -248,10 +248,11 @@
   return 2;
 }
 
-void InstrumentedFoo::GetD(char *buffer, size_t length) {
-  LLDB_RECORD_METHOD(void, InstrumentedFoo, GetD, (char *, size_t), buffer,
-                     length);
+size_t InstrumentedFoo::GetD(char *buffer, size_t length) {
+  LLDB_RECORD_CHAR_PTR_METHOD(size_t, InstrumentedFoo, GetD, (char *, size_t),
+                              buffer, "", length);
   ::snprintf(buffer, length, "%s", m_d.c_str());
+  return m_d.size();
 }
 
 void InstrumentedFoo::E(double e) {
@@ -365,7 +366,7 @@
   LLDB_REGISTER_METHOD(int, InstrumentedFoo, GetA, ());
   LLDB_REGISTER_METHOD(int &, InstrumentedFoo, GetB, ());
   LLDB_REGISTER_METHOD(float, InstrumentedFoo, GetC, ());
-  LLDB_REGISTER_METHOD(void, InstrumentedFoo, GetD, (char *, size_t));
+  LLDB_REGISTER_METHOD(size_t, InstrumentedFoo, GetD, (char *, size_t));
   LLDB_REGISTER_METHOD(double, InstrumentedFoo, GetE, ());
   LLDB_REGISTER_METHOD(bool, InstrumentedFoo, GetF, ());
 }
@@ -811,6 +812,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
   }
@@ -837,6 +841,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
   }
@@ -868,6 +875,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
 
@@ -900,6 +910,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
 
@@ -935,6 +948,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
 
@@ -967,6 +983,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
 
@@ -1002,6 +1021,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
 
@@ -1034,6 +1056,9 @@
     EXPECT_EQ(foo.GetA(), 100);
     EXPECT_EQ(foo.GetB(), 200);
     EXPECT_NEAR(foo.GetC(), 300.3, 0.01);
+    char buffer[100];
+    foo.GetD(buffer, 100);
+    EXPECT_STREQ(buffer, "bar");
     EXPECT_NEAR(foo.GetE(), 400.4, 0.01);
     EXPECT_EQ(foo.GetF(), true);
 
Index: lldb/source/API/SBThread.cpp
===================================================================
--- lldb/source/API/SBThread.cpp
+++ lldb/source/API/SBThread.cpp
@@ -312,8 +312,8 @@
 }
 
 size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
-  LLDB_RECORD_METHOD(size_t, SBThread, GetStopDescription, (char *, size_t), "",
-                     dst_len);
+  LLDB_RECORD_CHAR_PTR_METHOD(size_t, SBThread, GetStopDescription,
+                              (char *, size_t), dst, "", dst_len);
 
   std::unique_lock<std::recursive_mutex> lock;
   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
Index: lldb/source/API/SBStructuredData.cpp
===================================================================
--- lldb/source/API/SBStructuredData.cpp
+++ lldb/source/API/SBStructuredData.cpp
@@ -196,8 +196,8 @@
 }
 
 size_t SBStructuredData::GetStringValue(char *dst, size_t dst_len) const {
-  LLDB_RECORD_METHOD_CONST(size_t, SBStructuredData, GetStringValue,
-                           (char *, size_t), "", dst_len);
+  LLDB_RECORD_CHAR_PTR_METHOD_CONST(size_t, SBStructuredData, GetStringValue,
+                                    (char *, size_t), dst, "", dst_len);
 
   return (m_impl_up ? m_impl_up->GetStringValue(dst, dst_len) : 0);
 }
Index: lldb/source/API/SBProcess.cpp
===================================================================
--- lldb/source/API/SBProcess.cpp
+++ lldb/source/API/SBProcess.cpp
@@ -271,8 +271,8 @@
 }
 
 size_t SBProcess::GetSTDOUT(char *dst, size_t dst_len) const {
-  LLDB_RECORD_METHOD_CONST(size_t, SBProcess, GetSTDOUT, (char *, size_t), "",
-                           dst_len);
+  LLDB_RECORD_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDOUT,
+                                    (char *, size_t), dst, "", dst_len);
 
   size_t bytes_read = 0;
   ProcessSP process_sp(GetSP());
@@ -285,8 +285,8 @@
 }
 
 size_t SBProcess::GetSTDERR(char *dst, size_t dst_len) const {
-  LLDB_RECORD_METHOD_CONST(size_t, SBProcess, GetSTDERR, (char *, size_t), "",
-                           dst_len);
+  LLDB_RECORD_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDERR,
+                                    (char *, size_t), dst, "", dst_len);
 
   size_t bytes_read = 0;
   ProcessSP process_sp(GetSP());
@@ -299,8 +299,8 @@
 }
 
 size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const {
-  LLDB_RECORD_METHOD_CONST(size_t, SBProcess, GetAsyncProfileData,
-                           (char *, size_t), "", dst_len);
+  LLDB_RECORD_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetAsyncProfileData,
+                                    (char *, size_t), dst, "", dst_len);
 
   size_t bytes_read = 0;
   ProcessSP process_sp(GetSP());
Index: lldb/source/API/SBFileSpec.cpp
===================================================================
--- lldb/source/API/SBFileSpec.cpp
+++ lldb/source/API/SBFileSpec.cpp
@@ -143,8 +143,8 @@
 }
 
 uint32_t SBFileSpec::GetPath(char *dst_path, size_t dst_len) const {
-  LLDB_RECORD_METHOD_CONST(uint32_t, SBFileSpec, GetPath, (char *, size_t), "",
-                           dst_len);
+  LLDB_RECORD_CHAR_PTR_METHOD_CONST(uint32_t, SBFileSpec, GetPath,
+                                    (char *, size_t), dst_path, "", dst_len);
 
   uint32_t result = m_opaque_up->GetPath(dst_path, dst_len);
 
Index: lldb/source/API/SBDebugger.cpp
===================================================================
--- lldb/source/API/SBDebugger.cpp
+++ lldb/source/API/SBDebugger.cpp
@@ -596,8 +596,9 @@
 }
 
 bool SBDebugger::GetDefaultArchitecture(char *arch_name, size_t arch_name_len) {
-  LLDB_RECORD_STATIC_METHOD(bool, SBDebugger, GetDefaultArchitecture,
-                            (char *, size_t), "", arch_name_len);
+  LLDB_RECORD_CHAR_PTR_STATIC_METHOD(bool, SBDebugger, GetDefaultArchitecture,
+                                     (char *, size_t), arch_name, "",
+                                     arch_name_len);
 
   if (arch_name && arch_name_len) {
     ArchSpec default_arch = Target::GetDefaultArchitecture();
Index: lldb/include/lldb/Utility/ReproducerInstrumentation.h
===================================================================
--- lldb/include/lldb/Utility/ReproducerInstrumentation.h
+++ lldb/include/lldb/Utility/ReproducerInstrumentation.h
@@ -268,6 +268,78 @@
     }                                                                          \
   }
 
+#define LLDB_RECORD_CHAR_PTR_METHOD(Result, Class, Method, Signature, StrOut,  \
+                                    ...)                                       \
+  lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION,                \
+                                          stringify_args(*this, __VA_ARGS__)); \
+  if (lldb_private::repro::InstrumentationData _data =                         \
+          LLDB_GET_INSTRUMENTATION_DATA()) {                                   \
+    if (lldb_private::repro::Serializer *_serializer =                         \
+            _data.GetSerializer()) {                                           \
+      _recorder.Record(                                                        \
+          *_serializer, _data.GetRegistry(),                                   \
+          &lldb_private::repro::invoke<Result(Class::*) Signature>::method<(   \
+              &Class::Method)>::record,                                        \
+          this, __VA_ARGS__);                                                  \
+    } else if (lldb_private::repro::Deserializer *_deserializer =              \
+                   _data.GetDeserializer()) {                                  \
+      if (_recorder.ShouldCapture()) {                                         \
+        return lldb_private::repro::invoke_char_ptr<Result(                    \
+            Class::*) Signature>::method<&Class::Method>::                     \
+            replay(_recorder, *_deserializer, _data.GetRegistry(),             \
+                   LLVM_PRETTY_FUNCTION, StrOut);                              \
+      }                                                                        \
+    }                                                                          \
+  }
+
+#define LLDB_RECORD_CHAR_PTR_METHOD_CONST(Result, Class, Method, Signature,    \
+                                          StrOut, ...)                         \
+  lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION,                \
+                                          stringify_args(*this, __VA_ARGS__)); \
+  if (lldb_private::repro::InstrumentationData _data =                         \
+          LLDB_GET_INSTRUMENTATION_DATA()) {                                   \
+    if (lldb_private::repro::Serializer *_serializer =                         \
+            _data.GetSerializer()) {                                           \
+      _recorder.Record(                                                        \
+          *_serializer, _data.GetRegistry(),                                   \
+          &lldb_private::repro::invoke<Result(Class::*) Signature const>::     \
+              method_const<(&Class::Method)>::record,                          \
+          this, __VA_ARGS__);                                                  \
+    } else if (lldb_private::repro::Deserializer *_deserializer =              \
+                   _data.GetDeserializer()) {                                  \
+      if (_recorder.ShouldCapture()) {                                         \
+        return lldb_private::repro::invoke_char_ptr<Result(                    \
+            Class::*) Signature const>::method_const<&Class::Method>::         \
+            replay(_recorder, *_deserializer, _data.GetRegistry(),             \
+                   LLVM_PRETTY_FUNCTION, StrOut);                              \
+      }                                                                        \
+    }                                                                          \
+  }
+
+#define LLDB_RECORD_CHAR_PTR_STATIC_METHOD(Result, Class, Method, Signature,   \
+                                           StrOut, ...)                        \
+  lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION,                \
+                                          stringify_args(__VA_ARGS__));        \
+  if (lldb_private::repro::InstrumentationData _data =                         \
+          LLDB_GET_INSTRUMENTATION_DATA()) {                                   \
+    if (lldb_private::repro::Serializer *_serializer =                         \
+            _data.GetSerializer()) {                                           \
+      _recorder.Record(                                                        \
+          *_serializer, _data.GetRegistry(),                                   \
+          lldb_private::repro::invoke<Result(*) Signature>::method_static<(    \
+              &Class::Method)>::record,                                        \
+          __VA_ARGS__);                                                        \
+    } else if (lldb_private::repro::Deserializer *_deserializer =              \
+                   _data.GetDeserializer()) {                                  \
+      if (_recorder.ShouldCapture()) {                                         \
+        return lldb_private::repro::invoke_char_ptr<Result(*) Signature>::     \
+            method_static<(&Class::Method)>::replay(                           \
+                _recorder, *_deserializer, _data.GetRegistry(),                \
+                LLVM_PRETTY_FUNCTION, StrOut);                                 \
+      }                                                                        \
+    }                                                                          \
+  }
+
 #define LLDB_RECORD_RESULT(Result) _recorder.RecordResult(Result, true);
 
 /// The LLDB_RECORD_DUMMY macro is special because it doesn't actually record
@@ -1028,6 +1100,68 @@
   };
 };
 
+/// Special handling for functions returning strings as (char*, size_t).
+/// {
+
+/// For inline replay, we ignore the arguments and use the ones from the
+/// serializer instead. This doesn't work for methods that use a char* and a
+/// size to return a string. For one these functions have a custom replayer to
+/// prevent override the input buffer. Furthermore, the template-generated
+/// deserialization is not easy to hook into.
+///
+/// The specializations below hand-implement the serialization logic for the
+/// inline replay. Instead of using the function from the registry, it uses the
+/// one passed into the macro.
+template <typename Signature> struct invoke_char_ptr;
+template <typename Result, typename Class, typename... Args>
+struct invoke_char_ptr<Result (Class::*)(Args...) const> {
+  template <Result (Class::*m)(Args...) const> struct method_const {
+    static Result replay(Recorder &recorder, Deserializer &deserializer,
+                         Registry &registry, llvm::StringRef signature,
+                         char *str) {
+      deserializer.Deserialize<unsigned>();
+      Class *c = deserializer.Deserialize<Class *>();
+      deserializer.Deserialize<const char *>();
+      size_t l = deserializer.Deserialize<size_t>();
+      return recorder.ReplayResult<Result>(
+          std::move(deserializer.HandleReplayResult<Result>((c->*m)(str, l))),
+          true);
+    }
+  };
+};
+template <typename Signature> struct invoke_char_ptr;
+template <typename Result, typename Class, typename... Args>
+struct invoke_char_ptr<Result (Class::*)(Args...)> {
+  template <Result (Class::*m)(Args...)> struct method {
+    static Result replay(Recorder &recorder, Deserializer &deserializer,
+                         Registry &registry, llvm::StringRef signature,
+                         char *str) {
+      deserializer.Deserialize<unsigned>();
+      Class *c = deserializer.Deserialize<Class *>();
+      deserializer.Deserialize<const char *>();
+      size_t l = deserializer.Deserialize<size_t>();
+      return recorder.ReplayResult<Result>(
+          std::move(deserializer.HandleReplayResult<Result>((c->*m)(str, l))),
+          true);
+    }
+  };
+};
+template <typename Result, typename... Args>
+struct invoke_char_ptr<Result (*)(Args...)> {
+  template <Result (*m)(Args...)> struct method_static {
+    static Result replay(Recorder &recorder, Deserializer &deserializer,
+                         Registry &registry, llvm::StringRef signature,
+                         char *str) {
+      deserializer.Deserialize<unsigned>();
+      deserializer.Deserialize<const char *>();
+      size_t l = deserializer.Deserialize<size_t>();
+      return recorder.ReplayResult<Result>(
+          std::move(deserializer.HandleReplayResult<Result>((*m)(str, l))),
+          true);
+    }
+  };
+};
+
 template <typename Signature> struct char_ptr_redirect;
 template <typename Result, typename Class>
 struct char_ptr_redirect<Result (Class::*)(char *, size_t) const> {
@@ -1057,6 +1191,8 @@
   };
 };
 
+/// }
+
 } // namespace repro
 } // namespace lldb_private
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to