JDevlieghere updated this revision to Diff 258172. JDevlieghere added a comment.
Remove duplication similar to D77602 <https://reviews.llvm.org/D77602>. Honestly, at this point I'm not convinced that the difference between active and passive replay warrants special handling. Other than the slightly different macros, which are unfortunate but OTOH also a good indicator that something special is happening, there's not that much more to support active/passive replay than there is for the generic case. 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 @@ -131,7 +131,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(); @@ -254,10 +254,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) { @@ -371,7 +372,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); } @@ -836,6 +840,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); } @@ -917,6 +924,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); @@ -948,6 +958,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); @@ -982,6 +995,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); @@ -1013,6 +1029,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); @@ -1047,6 +1066,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); @@ -1078,6 +1100,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); @@ -1448,7 +1448,7 @@ LLDB_REGISTER_METHOD(lldb::SBThread, SBThread, GetCurrentExceptionBacktrace, ()); LLDB_REGISTER_METHOD(bool, SBThread, SafeToCallFunctions, ()); - LLDB_REGISTER_CHAR_PTR_REDIRECT(size_t, SBThread, GetStopDescription); + LLDB_REGISTER_CHAR_PTR_METHOD(size_t, SBThread, GetStopDescription); } } 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); } @@ -236,8 +236,7 @@ (uint64_t)); LLDB_REGISTER_METHOD_CONST(double, SBStructuredData, GetFloatValue, (double)); LLDB_REGISTER_METHOD_CONST(bool, SBStructuredData, GetBooleanValue, (bool)); - LLDB_REGISTER_CHAR_PTR_REDIRECT_CONST(size_t, SBStructuredData, - GetStringValue); + LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBStructuredData, GetStringValue); } } // namespace repro 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()); @@ -1440,9 +1440,9 @@ GetMemoryRegions, ()); LLDB_REGISTER_METHOD(lldb::SBProcessInfo, SBProcess, GetProcessInfo, ()); - LLDB_REGISTER_CHAR_PTR_REDIRECT_CONST(size_t, SBProcess, GetSTDOUT); - LLDB_REGISTER_CHAR_PTR_REDIRECT_CONST(size_t, SBProcess, GetSTDERR); - LLDB_REGISTER_CHAR_PTR_REDIRECT_CONST(size_t, SBProcess, GetAsyncProfileData); + LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDOUT); + LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDERR); + LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetAsyncProfileData); } } 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); @@ -216,7 +216,7 @@ LLDB_REGISTER_METHOD_CONST(bool, SBFileSpec, GetDescription, (lldb::SBStream &)); LLDB_REGISTER_METHOD(void, SBFileSpec, AppendPathComponent, (const char *)); - LLDB_REGISTER_CHAR_PTR_REDIRECT_CONST(uint32_t, SBFileSpec, GetPath); + LLDB_REGISTER_CHAR_PTR_METHOD_CONST(uint32_t, SBFileSpec, GetPath); } } 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(); @@ -1656,8 +1657,8 @@ FileSP)>::method<&SBDebugger::SetErrorFile>::record, &SetFileRedirect); - LLDB_REGISTER_CHAR_PTR_REDIRECT_STATIC(bool, SBDebugger, - GetDefaultArchitecture); + LLDB_REGISTER_CHAR_PTR_METHOD_STATIC(bool, SBDebugger, + GetDefaultArchitecture); LLDB_REGISTER_CONSTRUCTOR(SBDebugger, ()); LLDB_REGISTER_CONSTRUCTOR(SBDebugger, (const lldb::DebuggerSP &)); Index: lldb/include/lldb/Utility/ReproducerInstrumentation.h =================================================================== --- lldb/include/lldb/Utility/ReproducerInstrumentation.h +++ lldb/include/lldb/Utility/ReproducerInstrumentation.h @@ -92,25 +92,25 @@ R.Register(&invoke<Result(*) Signature>::method<(&Class::Method)>::record, \ #Result, #Class, #Method, #Signature) -#define LLDB_REGISTER_CHAR_PTR_REDIRECT_STATIC(Result, Class, Method) \ +#define LLDB_REGISTER_CHAR_PTR_METHOD_STATIC(Result, Class, Method) \ R.Register( \ &invoke<Result (*)(char *, size_t)>::method<(&Class::Method)>::record, \ - &char_ptr_redirect<Result (*)(char *, size_t)>::method<( \ - &Class::Method)>::record, \ + &invoke_char_ptr<Result (*)(char *, \ + size_t)>::method<(&Class::Method)>::record, \ #Result, #Class, #Method, "(char*, size_t"); -#define LLDB_REGISTER_CHAR_PTR_REDIRECT(Result, Class, Method) \ +#define LLDB_REGISTER_CHAR_PTR_METHOD(Result, Class, Method) \ R.Register(&invoke<Result (Class::*)(char *, size_t)>::method<( \ &Class::Method)>::record, \ - &char_ptr_redirect<Result (Class::*)(char *, size_t)>::method<( \ + &invoke_char_ptr<Result (Class::*)(char *, size_t)>::method<( \ &Class::Method)>::record, \ #Result, #Class, #Method, "(char*, size_t"); -#define LLDB_REGISTER_CHAR_PTR_REDIRECT_CONST(Result, Class, Method) \ +#define LLDB_REGISTER_CHAR_PTR_METHOD_CONST(Result, Class, Method) \ R.Register(&invoke<Result (Class::*)(char *, size_t) \ const>::method<(&Class::Method)>::record, \ - &char_ptr_redirect<Result (Class::*)(char *, size_t) \ - const>::method<(&Class::Method)>::record, \ + &invoke_char_ptr<Result (Class::*)(char *, size_t) \ + const>::method<(&Class::Method)>::record, \ #Result, #Class, #Method, "(char*, size_t"); #define LLDB_CONSTRUCT_(T, Class, ...) \ @@ -162,6 +162,40 @@ #define LLDB_RECORD_STATIC_METHOD_NO_ARGS(Result, Class, Method) \ LLDB_RECORD_(Result (*)(), (&Class::Method), lldb_private::repro::EmptyArg()) +#define LLDB_RECORD_CHAR_PTR_(T1, T2, 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<T1>::method<(T2)>::record, \ + __VA_ARGS__); \ + } else if (lldb_private::repro::Deserializer *_deserializer = \ + _data.GetDeserializer()) { \ + if (_recorder.ShouldCapture()) { \ + return lldb_private::repro::invoke_char_ptr<T1>::method<T2>::replay( \ + _recorder, *_deserializer, _data.GetRegistry(), StrOut); \ + } \ + } \ + } + +#define LLDB_RECORD_CHAR_PTR_METHOD(Result, Class, Method, Signature, StrOut, \ + ...) \ + LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature, (&Class::Method), StrOut, \ + this, __VA_ARGS__) + +#define LLDB_RECORD_CHAR_PTR_METHOD_CONST(Result, Class, Method, Signature, \ + StrOut, ...) \ + LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature const, (&Class::Method), \ + StrOut, this, __VA_ARGS__) + +#define LLDB_RECORD_CHAR_PTR_STATIC_METHOD(Result, Class, Method, Signature, \ + StrOut, ...) \ + LLDB_RECORD_CHAR_PTR_(Result(*) Signature, (&Class::Method), StrOut, \ + __VA_ARGS__) + #define LLDB_RECORD_RESULT(Result) _recorder.RecordResult(Result, true); /// The LLDB_RECORD_DUMMY macro is special because it doesn't actually record @@ -924,34 +958,82 @@ }; }; -template <typename Signature> struct char_ptr_redirect; -template <typename Result, typename Class> -struct char_ptr_redirect<Result (Class::*)(char *, size_t) const> { - template <Result (Class::*m)(char *, size_t) const> struct method { +/// 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 { static Result record(Class *c, char *s, size_t l) { char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); return (c->*m)(buffer, l); } + + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, 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 Class> -struct char_ptr_redirect<Result (Class::*)(char *, size_t)> { - template <Result (Class::*m)(char *, size_t)> struct method { + +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 record(Class *c, char *s, size_t l) { char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); return (c->*m)(buffer, l); } + + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, 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> -struct char_ptr_redirect<Result (*)(char *, size_t)> { - template <Result (*m)(char *, size_t)> struct method { + +template <typename Result, typename... Args> +struct invoke_char_ptr<Result (*)(Args...)> { + template <Result (*m)(Args...)> struct method { static Result record(char *s, size_t l) { char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); return (*m)(buffer, l); } + + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, 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); + } }; }; +/// } } // namespace repro } // namespace lldb_private
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits