Index: lldb/include/lldb/Utility/ReproducerInstrumentation.h =================================================================== --- lldb/include/lldb/Utility/ReproducerInstrumentation.h +++ lldb/include/lldb/Utility/ReproducerInstrumentation.h @@ -286,6 +286,79 @@ } \ } +#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::method<( \ + &Class::Method)>::doit, \ + this, __VA_ARGS__); \ + } else if (lldb_private::repro::Deserializer *_deserializer = \ + _data.GetDeserializer()) { \ + if (_recorder.ShouldCapture()) { \ + return lldb_private::repro::replay_char_ptr< \ + Result(Class::*) \ + Signature>::method<&Class::Method>::doit(_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:: \ + method_const<(&Class::Method)>::doit, \ + this, __VA_ARGS__); \ + } else if (lldb_private::repro::Deserializer *_deserializer = \ + _data.GetDeserializer()) { \ + if (_recorder.ShouldCapture()) { \ + return lldb_private::repro::replay_char_ptr::method_const<&Class::Method>:: \ + doit(_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(), \ + static_cast(&Class::Method), \ + __VA_ARGS__); \ + } else if (lldb_private::repro::Deserializer *_deserializer = \ + _data.GetDeserializer()) { \ + if (_recorder.ShouldCapture()) { \ + return lldb_private::repro::replay_char_ptr:: \ + method_static<(&Class::Method)>::doit( \ + _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 @@ -1022,6 +1095,74 @@ }; }; +/// 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 struct replay_char_ptr; +template +struct replay_char_ptr { + template struct method_const { + static Result doit(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, llvm::StringRef signature, + char *str) { + unsigned id = deserializer.Deserialize(); + registry.CheckSignature(signature, id); + + Class *c = deserializer.Deserialize(); + deserializer.Deserialize(); + size_t l = deserializer.Deserialize(); + return recorder.ReplayResult( + std::move(deserializer.HandleReplayResult((c->*m)(str, l))), + true); + } + }; +}; +template struct replay_char_ptr; +template +struct replay_char_ptr { + template struct method { + static Result doit(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, llvm::StringRef signature, + char *str) { + unsigned id = deserializer.Deserialize(); + registry.CheckSignature(signature, id); + + Class *c = deserializer.Deserialize(); + deserializer.Deserialize(); + size_t l = deserializer.Deserialize(); + return recorder.ReplayResult( + std::move(deserializer.HandleReplayResult((c->*m)(str, l))), + true); + } + }; +}; +template +struct replay_char_ptr { + template struct method_static { + static Result doit(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, llvm::StringRef signature, + char *str) { + unsigned id = deserializer.Deserialize(); + registry.CheckSignature(signature, id); + + deserializer.Deserialize(); + size_t l = deserializer.Deserialize(); + return recorder.ReplayResult( + std::move(deserializer.HandleReplayResult((*m)(str, l))), + true); + } + }; +}; + template struct char_ptr_redirect; template struct char_ptr_redirect { @@ -1048,6 +1189,7 @@ char *buffer = reinterpret_cast(calloc(l, sizeof(char))); return f(buffer, l); } +/// } } // namespace repro } // namespace lldb_private 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/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/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/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/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 lock; ExecutionContext exe_ctx(m_opaque_sp.get(), lock);