blob: 6c5d27879d362fc378d2d363d582937cbb757e5c [file] [log] [blame]
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +00001//===-- ReproducerInstrumentation.h -----------------------------*- C++ -*-===//
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +00002// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
Jonas Devliegherecdc514e2020-02-17 15:57:45 -08008#ifndef LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H
9#define LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +000010
11#include "lldb/Utility/FileSpec.h"
12#include "lldb/Utility/Log.h"
13#include "lldb/Utility/Logging.h"
14
15#include "llvm/ADT/DenseMap.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/ErrorHandling.h"
18
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +000019#include <map>
Jonas Devlieghere33e3b072020-12-07 20:31:07 -080020#include <thread>
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000021#include <type_traits>
22
23template <typename T,
24 typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000025inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) {
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000026 ss << t;
27}
28
29template <typename T, typename std::enable_if<!std::is_fundamental<T>::value,
30 int>::type = 0>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000031inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) {
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000032 ss << &t;
33}
34
35template <typename T>
Jonas Devlieghere9f6a3082020-04-16 14:02:05 -070036inline void stringify_append(llvm::raw_string_ostream &ss, T *t) {
Jonas Devlieghere9eaf0ab2020-04-16 17:50:56 -070037 ss << reinterpret_cast<void *>(t);
Jonas Devlieghere9f6a3082020-04-16 14:02:05 -070038}
39
40template <typename T>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000041inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) {
Jonas Devlieghere9eaf0ab2020-04-16 17:50:56 -070042 ss << reinterpret_cast<const void *>(t);
Jonas Devlieghere7bc83562019-03-11 20:31:21 +000043}
44
Benjamin Kramer93110c22019-03-08 10:43:56 +000045template <>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000046inline void stringify_append<char>(llvm::raw_string_ostream &ss,
47 const char *t) {
Jonas Devlieghere449ca012019-09-13 19:08:10 +000048 ss << '\"' << t << '\"';
Jonas Devlieghere4aba7bb2019-03-07 23:37:46 +000049}
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000050
Jonas Devlieghere620f5fa2020-01-28 14:47:29 -080051template <>
Jonas Devliegheree9326ed2020-01-28 15:14:40 -080052inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss,
53 const std::nullptr_t &t) {
Jonas Devlieghere620f5fa2020-01-28 14:47:29 -080054 ss << "\"nullptr\"";
55}
56
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000057template <typename Head>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000058inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) {
59 stringify_append(ss, head);
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000060}
61
62template <typename Head, typename... Tail>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000063inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head,
64 const Tail &... tail) {
65 stringify_append(ss, head);
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000066 ss << ", ";
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000067 stringify_helper(ss, tail...);
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000068}
69
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000070template <typename... Ts> inline std::string stringify_args(const Ts &... ts) {
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000071 std::string buffer;
72 llvm::raw_string_ostream ss(buffer);
Jonas Devliegheredb41fe12019-04-23 17:44:40 +000073 stringify_helper(ss, ts...);
Jonas Devlieghere581af8b2019-03-07 22:47:13 +000074 return ss.str();
75}
Jonas Devlieghere58947cf2019-02-06 18:57:42 +000076
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +000077// Define LLDB_REPRO_INSTR_TRACE to trace to stderr instead of LLDB's log
78// infrastructure. This is useful when you need to see traces before the logger
79// is initialized or enabled.
Jonas Devlieghere3c28c0b2019-03-06 01:00:36 +000080// #define LLDB_REPRO_INSTR_TRACE
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +000081
Jonas Devlieghere33e3b072020-12-07 20:31:07 -080082#ifdef LLDB_REPRO_INSTR_TRACE
83inline llvm::raw_ostream &this_thread_id() {
84 size_t tid = std::hash<std::thread::id>{}(std::this_thread::get_id());
85 return llvm::errs().write_hex(tid) << " :: ";
86}
87#endif
88
Jonas Devlieghere58947cf2019-02-06 18:57:42 +000089#define LLDB_REGISTER_CONSTRUCTOR(Class, Signature) \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -070090 R.Register<Class * Signature>(&construct<Class Signature>::record, "", \
91 #Class, #Class, #Signature)
Jonas Devlieghereba108402020-04-14 10:18:50 -070092
Jonas Devlieghere58947cf2019-02-06 18:57:42 +000093#define LLDB_REGISTER_METHOD(Result, Class, Method, Signature) \
Michal Gornyae211ec2019-03-19 17:13:13 +000094 R.Register( \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -070095 &invoke<Result(Class::*) Signature>::method<(&Class::Method)>::record, \
Pavel Labath075e1332019-03-11 15:00:11 +000096 #Result, #Class, #Method, #Signature)
Jonas Devlieghereba108402020-04-14 10:18:50 -070097
Jonas Devlieghere58947cf2019-02-06 18:57:42 +000098#define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -070099 R.Register(&invoke<Result(Class::*) \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700100 Signature const>::method<(&Class::Method)>::record, \
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000101 #Result, #Class, #Method, #Signature)
Jonas Devlieghereba108402020-04-14 10:18:50 -0700102
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000103#define LLDB_REGISTER_STATIC_METHOD(Result, Class, Method, Signature) \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700104 R.Register(&invoke<Result(*) Signature>::method<(&Class::Method)>::record, \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700105 #Result, #Class, #Method, #Signature)
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000106
Jonas Devliegheree687aa82020-04-20 13:20:24 -0700107#define LLDB_REGISTER_CHAR_PTR_METHOD_STATIC(Result, Class, Method) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700108 R.Register( \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700109 &invoke<Result (*)(char *, size_t)>::method<(&Class::Method)>::record, \
Jonas Devliegheree687aa82020-04-20 13:20:24 -0700110 &invoke_char_ptr<Result (*)(char *, \
111 size_t)>::method<(&Class::Method)>::record, \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700112 #Result, #Class, #Method, "(char*, size_t");
Jonas Devlieghereba108402020-04-14 10:18:50 -0700113
Jonas Devliegheree687aa82020-04-20 13:20:24 -0700114#define LLDB_REGISTER_CHAR_PTR_METHOD(Result, Class, Method) \
Jonas Devlieghereba108402020-04-14 10:18:50 -0700115 R.Register(&invoke<Result (Class::*)(char *, size_t)>::method<( \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700116 &Class::Method)>::record, \
Jonas Devliegheree687aa82020-04-20 13:20:24 -0700117 &invoke_char_ptr<Result (Class::*)(char *, size_t)>::method<( \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700118 &Class::Method)>::record, \
Jonas Devlieghereba108402020-04-14 10:18:50 -0700119 #Result, #Class, #Method, "(char*, size_t");
120
Jonas Devliegheree687aa82020-04-20 13:20:24 -0700121#define LLDB_REGISTER_CHAR_PTR_METHOD_CONST(Result, Class, Method) \
Jonas Devlieghereba108402020-04-14 10:18:50 -0700122 R.Register(&invoke<Result (Class::*)(char *, size_t) \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700123 const>::method<(&Class::Method)>::record, \
Jonas Devliegheree687aa82020-04-20 13:20:24 -0700124 &invoke_char_ptr<Result (Class::*)(char *, size_t) \
125 const>::method<(&Class::Method)>::record, \
Jonas Devlieghereba108402020-04-14 10:18:50 -0700126 #Result, #Class, #Method, "(char*, size_t");
Jonas Devlieghere2f025bb2020-02-05 19:41:09 -0800127
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700128#define LLDB_CONSTRUCT_(T, Class, ...) \
129 lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION); \
130 lldb_private::repro::construct<T>::handle(LLDB_GET_INSTRUMENTATION_DATA(), \
131 _recorder, Class, __VA_ARGS__);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000132
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700133#define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700134 LLDB_CONSTRUCT_(Class Signature, this, __VA_ARGS__)
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700135
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000136#define LLDB_RECORD_CONSTRUCTOR_NO_ARGS(Class) \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700137 LLDB_CONSTRUCT_(Class(), this, lldb_private::repro::EmptyArg())
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700138
139#define LLDB_RECORD_(T1, T2, ...) \
140 lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \
141 stringify_args(__VA_ARGS__)); \
Jonas Devlieghereddf81462020-02-04 16:21:31 -0800142 if (lldb_private::repro::InstrumentationData _data = \
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000143 LLDB_GET_INSTRUMENTATION_DATA()) { \
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700144 if (lldb_private::repro::Serializer *_serializer = \
145 _data.GetSerializer()) { \
146 _recorder.Record(*_serializer, _data.GetRegistry(), \
147 &lldb_private::repro::invoke<T1>::method<T2>::record, \
148 __VA_ARGS__); \
149 } else if (lldb_private::repro::Deserializer *_deserializer = \
150 _data.GetDeserializer()) { \
151 if (_recorder.ShouldCapture()) { \
152 return lldb_private::repro::invoke<T1>::method<T2>::replay( \
153 _recorder, *_deserializer, _data.GetRegistry()); \
154 } \
155 } \
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000156 }
157
158#define LLDB_RECORD_METHOD(Result, Class, Method, Signature, ...) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700159 LLDB_RECORD_(Result(Class::*) Signature, (&Class::Method), this, __VA_ARGS__)
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000160
161#define LLDB_RECORD_METHOD_CONST(Result, Class, Method, Signature, ...) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700162 LLDB_RECORD_(Result(Class::*) Signature const, (&Class::Method), this, \
163 __VA_ARGS__)
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000164
165#define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700166 LLDB_RECORD_(Result (Class::*)(), (&Class::Method), this)
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000167
168#define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700169 LLDB_RECORD_(Result (Class::*)() const, (&Class::Method), this)
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000170
171#define LLDB_RECORD_STATIC_METHOD(Result, Class, Method, Signature, ...) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700172 LLDB_RECORD_(Result(*) Signature, (&Class::Method), __VA_ARGS__)
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000173
174#define LLDB_RECORD_STATIC_METHOD_NO_ARGS(Result, Class, Method) \
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700175 LLDB_RECORD_(Result (*)(), (&Class::Method), lldb_private::repro::EmptyArg())
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000176
Jonas Devliegheree687aa82020-04-20 13:20:24 -0700177#define LLDB_RECORD_CHAR_PTR_(T1, T2, StrOut, ...) \
178 lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \
179 stringify_args(__VA_ARGS__)); \
180 if (lldb_private::repro::InstrumentationData _data = \
181 LLDB_GET_INSTRUMENTATION_DATA()) { \
182 if (lldb_private::repro::Serializer *_serializer = \
183 _data.GetSerializer()) { \
184 _recorder.Record(*_serializer, _data.GetRegistry(), \
185 &lldb_private::repro::invoke<T1>::method<(T2)>::record, \
186 __VA_ARGS__); \
187 } else if (lldb_private::repro::Deserializer *_deserializer = \
188 _data.GetDeserializer()) { \
189 if (_recorder.ShouldCapture()) { \
190 return lldb_private::repro::invoke_char_ptr<T1>::method<T2>::replay( \
191 _recorder, *_deserializer, _data.GetRegistry(), StrOut); \
192 } \
193 } \
194 }
195
196#define LLDB_RECORD_CHAR_PTR_METHOD(Result, Class, Method, Signature, StrOut, \
197 ...) \
198 LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature, (&Class::Method), StrOut, \
199 this, __VA_ARGS__)
200
201#define LLDB_RECORD_CHAR_PTR_METHOD_CONST(Result, Class, Method, Signature, \
202 StrOut, ...) \
203 LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature const, (&Class::Method), \
204 StrOut, this, __VA_ARGS__)
205
206#define LLDB_RECORD_CHAR_PTR_STATIC_METHOD(Result, Class, Method, Signature, \
207 StrOut, ...) \
208 LLDB_RECORD_CHAR_PTR_(Result(*) Signature, (&Class::Method), StrOut, \
209 __VA_ARGS__)
210
Jonas Devlieghereddf81462020-02-04 16:21:31 -0800211#define LLDB_RECORD_RESULT(Result) _recorder.RecordResult(Result, true);
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000212
Jonas Devlieghere84e571c2019-03-08 17:50:27 +0000213/// The LLDB_RECORD_DUMMY macro is special because it doesn't actually record
214/// anything. It's used to track API boundaries when we cannot record for
215/// technical reasons.
216#define LLDB_RECORD_DUMMY(Result, Class, Method, Signature, ...) \
Jonas Devliegheree7f10672020-05-27 10:27:44 -0700217 lldb_private::repro::Recorder _recorder;
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700218
Jonas Devlieghereb328dcb2019-10-08 19:17:42 +0000219#define LLDB_RECORD_DUMMY_NO_ARGS(Result, Class, Method) \
Jonas Devliegheree7f10672020-05-27 10:27:44 -0700220 lldb_private::repro::Recorder _recorder;
Jonas Devlieghere84e571c2019-03-08 17:50:27 +0000221
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000222namespace lldb_private {
223namespace repro {
224
Jonas Devlieghere84016982020-01-22 13:22:58 -0800225template <class T>
226struct is_trivially_serializable
227 : std::integral_constant<bool, std::is_fundamental<T>::value ||
228 std::is_enum<T>::value> {};
229
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000230/// Mapping between serialized indices and their corresponding objects.
231///
232/// This class is used during replay to map indices back to in-memory objects.
233///
234/// When objects are constructed, they are added to this mapping using
235/// AddObjectForIndex.
236///
237/// When an object is passed to a function, its index is deserialized and
238/// AddObjectForIndex returns the corresponding object. If there is no object
239/// for the given index, a nullptr is returend. The latter is valid when custom
240/// replay code is in place and the actual object is ignored.
241class IndexToObject {
242public:
243 /// Returns an object as a pointer for the given index or nullptr if not
244 /// present in the map.
245 template <typename T> T *GetObjectForIndex(unsigned idx) {
246 assert(idx != 0 && "Cannot get object for sentinel");
247 void *object = GetObjectForIndexImpl(idx);
248 return static_cast<T *>(object);
249 }
250
251 /// Adds a pointer to an object to the mapping for the given index.
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700252 template <typename T> T *AddObjectForIndex(unsigned idx, T *object) {
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000253 AddObjectForIndexImpl(
254 idx, static_cast<void *>(
255 const_cast<typename std::remove_const<T>::type *>(object)));
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700256 return object;
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000257 }
258
259 /// Adds a reference to an object to the mapping for the given index.
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700260 template <typename T> T &AddObjectForIndex(unsigned idx, T &object) {
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000261 AddObjectForIndexImpl(
262 idx, static_cast<void *>(
263 const_cast<typename std::remove_const<T>::type *>(&object)));
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700264 return object;
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000265 }
266
Jonas Devliegheref78fcd62020-04-10 15:42:28 -0700267 /// Get all objects sorted by their index.
268 std::vector<void *> GetAllObjects() const;
269
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000270private:
271 /// Helper method that does the actual lookup. The void* result is later cast
272 /// by the caller.
273 void *GetObjectForIndexImpl(unsigned idx);
274
275 /// Helper method that does the actual insertion.
276 void AddObjectForIndexImpl(unsigned idx, void *object);
277
278 /// Keeps a mapping between indices and their corresponding object.
279 llvm::DenseMap<unsigned, void *> m_mapping;
280};
281
282/// We need to differentiate between pointers to fundamental and
283/// non-fundamental types. See the corresponding Deserializer::Read method
284/// for the reason why.
285struct PointerTag {};
286struct ReferenceTag {};
287struct ValueTag {};
288struct FundamentalPointerTag {};
289struct FundamentalReferenceTag {};
290
291/// Return the deserialization tag for the given type T.
Lawrence D'Anna9eb13712019-10-09 21:50:49 +0000292template <class T> struct serializer_tag {
Jonas Devlieghere12c185a2020-01-29 21:21:02 -0800293 typedef typename std::conditional<std::is_trivially_copyable<T>::value,
Jonas Devliegheref8c0fcd2020-02-04 13:18:12 -0800294 ValueTag, ReferenceTag>::type type;
Lawrence D'Anna9eb13712019-10-09 21:50:49 +0000295};
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000296template <class T> struct serializer_tag<T *> {
297 typedef
298 typename std::conditional<std::is_fundamental<T>::value,
299 FundamentalPointerTag, PointerTag>::type type;
300};
301template <class T> struct serializer_tag<T &> {
302 typedef typename std::conditional<std::is_fundamental<T>::value,
303 FundamentalReferenceTag, ReferenceTag>::type
304 type;
305};
306
307/// Deserializes data from a buffer. It is used to deserialize function indices
308/// to replay, their arguments and return values.
309///
310/// Fundamental types and strings are read by value. Objects are read by their
311/// index, which get translated by the IndexToObject mapping maintained in
312/// this class.
313///
314/// Additional bookkeeping with regards to the IndexToObject is required to
315/// deserialize objects. When a constructor is run or an object is returned by
316/// value, we need to capture the object and add it to the index together with
317/// its index. This is the job of HandleReplayResult(Void).
318class Deserializer {
319public:
320 Deserializer(llvm::StringRef buffer) : m_buffer(buffer) {}
321
322 /// Returns true when the buffer has unread data.
323 bool HasData(unsigned size) { return size <= m_buffer.size(); }
324
325 /// Deserialize and interpret value as T.
326 template <typename T> T Deserialize() {
Jonas Devlieghere8e21d7b2020-01-28 13:23:36 -0800327 T t = Read<T>(typename serializer_tag<T>::type());
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000328#ifdef LLDB_REPRO_INSTR_TRACE
Jonas Devlieghere8e21d7b2020-01-28 13:23:36 -0800329 llvm::errs() << "Deserializing with " << LLVM_PRETTY_FUNCTION << " -> "
330 << stringify_args(t) << "\n";
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000331#endif
Jonas Devlieghere8e21d7b2020-01-28 13:23:36 -0800332 return t;
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000333 }
334
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700335 template <typename T> const T &HandleReplayResult(const T &t) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800336 CheckSequence(Deserialize<unsigned>());
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000337 unsigned result = Deserialize<unsigned>();
Jonas Devlieghere84016982020-01-22 13:22:58 -0800338 if (is_trivially_serializable<T>::value)
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700339 return t;
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000340 // We need to make a copy as the original object might go out of scope.
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700341 return *m_index_to_object.AddObjectForIndex(result, new T(t));
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000342 }
343
344 /// Store the returned value in the index-to-object mapping.
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700345 template <typename T> T &HandleReplayResult(T &t) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800346 CheckSequence(Deserialize<unsigned>());
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000347 unsigned result = Deserialize<unsigned>();
Jonas Devlieghere84016982020-01-22 13:22:58 -0800348 if (is_trivially_serializable<T>::value)
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700349 return t;
350 // We need to make a copy as the original object might go out of scope.
351 return *m_index_to_object.AddObjectForIndex(result, new T(t));
352 }
353
354 /// Store the returned value in the index-to-object mapping.
355 template <typename T> T *HandleReplayResult(T *t) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800356 CheckSequence(Deserialize<unsigned>());
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700357 unsigned result = Deserialize<unsigned>();
358 if (is_trivially_serializable<T>::value)
359 return t;
360 return m_index_to_object.AddObjectForIndex(result, t);
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000361 }
362
363 /// All returned types are recorded, even when the function returns a void.
364 /// The latter requires special handling.
365 void HandleReplayResultVoid() {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800366 CheckSequence(Deserialize<unsigned>());
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000367 unsigned result = Deserialize<unsigned>();
368 assert(result == 0);
Jonas Devlieghere504be842019-03-06 00:52:48 +0000369 (void)result;
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000370 }
371
Jonas Devliegheref78fcd62020-04-10 15:42:28 -0700372 std::vector<void *> GetAllObjects() const {
373 return m_index_to_object.GetAllObjects();
374 }
375
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800376 void SetExpectedSequence(unsigned sequence) {
377 m_expected_sequence = sequence;
378 }
379
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000380private:
381 template <typename T> T Read(ValueTag) {
382 assert(HasData(sizeof(T)));
383 T t;
384 std::memcpy(reinterpret_cast<char *>(&t), m_buffer.data(), sizeof(T));
385 m_buffer = m_buffer.drop_front(sizeof(T));
386 return t;
387 }
388
389 template <typename T> T Read(PointerTag) {
390 typedef typename std::remove_pointer<T>::type UnderlyingT;
391 return m_index_to_object.template GetObjectForIndex<UnderlyingT>(
392 Deserialize<unsigned>());
393 }
394
395 template <typename T> T Read(ReferenceTag) {
396 typedef typename std::remove_reference<T>::type UnderlyingT;
397 // If this is a reference to a fundamental type we just read its value.
398 return *m_index_to_object.template GetObjectForIndex<UnderlyingT>(
399 Deserialize<unsigned>());
400 }
401
402 /// This method is used to parse references to fundamental types. Because
403 /// they're not recorded in the object table we have serialized their value.
404 /// We read its value, allocate a copy on the heap, and return a pointer to
405 /// the copy.
406 template <typename T> T Read(FundamentalPointerTag) {
407 typedef typename std::remove_pointer<T>::type UnderlyingT;
408 return new UnderlyingT(Deserialize<UnderlyingT>());
409 }
410
411 /// This method is used to parse references to fundamental types. Because
412 /// they're not recorded in the object table we have serialized their value.
413 /// We read its value, allocate a copy on the heap, and return a reference to
414 /// the copy.
415 template <typename T> T Read(FundamentalReferenceTag) {
416 // If this is a reference to a fundamental type we just read its value.
417 typedef typename std::remove_reference<T>::type UnderlyingT;
418 return *(new UnderlyingT(Deserialize<UnderlyingT>()));
419 }
420
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800421 /// Verify that the given sequence number matches what we expect.
422 void CheckSequence(unsigned sequence);
423
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000424 /// Mapping of indices to objects.
425 IndexToObject m_index_to_object;
426
427 /// Buffer containing the serialized data.
428 llvm::StringRef m_buffer;
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800429
430 /// The result's expected sequence number.
431 llvm::Optional<unsigned> m_expected_sequence;
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000432};
433
434/// Partial specialization for C-style strings. We read the string value
435/// instead of treating it as pointer.
436template <> const char *Deserializer::Deserialize<const char *>();
Jonas Devlieghere91aa67b2020-01-29 14:06:20 -0800437template <> const char **Deserializer::Deserialize<const char **>();
Jonas Devliegherea5f1fff2020-02-04 15:09:53 -0800438template <> const uint8_t *Deserializer::Deserialize<const uint8_t *>();
Jonas Devlieghereb453caf2020-02-04 19:00:10 -0800439template <> const void *Deserializer::Deserialize<const void *>();
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000440template <> char *Deserializer::Deserialize<char *>();
Jonas Devlieghereb453caf2020-02-04 19:00:10 -0800441template <> void *Deserializer::Deserialize<void *>();
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000442
443/// Helpers to auto-synthesize function replay code. It deserializes the replay
444/// function's arguments one by one and finally calls the corresponding
445/// function.
446template <typename... Remaining> struct DeserializationHelper;
447
448template <typename Head, typename... Tail>
449struct DeserializationHelper<Head, Tail...> {
450 template <typename Result, typename... Deserialized> struct deserialized {
451 static Result doit(Deserializer &deserializer,
452 Result (*f)(Deserialized..., Head, Tail...),
453 Deserialized... d) {
454 return DeserializationHelper<Tail...>::
455 template deserialized<Result, Deserialized..., Head>::doit(
456 deserializer, f, d..., deserializer.Deserialize<Head>());
457 }
458 };
459};
460
461template <> struct DeserializationHelper<> {
462 template <typename Result, typename... Deserialized> struct deserialized {
463 static Result doit(Deserializer &deserializer, Result (*f)(Deserialized...),
464 Deserialized... d) {
465 return f(d...);
466 }
467 };
468};
469
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000470/// The replayer interface.
471struct Replayer {
Jonas Devliegherefd2433e2021-07-02 11:27:37 -0700472 virtual ~Replayer() = default;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000473 virtual void operator()(Deserializer &deserializer) const = 0;
474};
475
476/// The default replayer deserializes the arguments and calls the function.
477template <typename Signature> struct DefaultReplayer;
478template <typename Result, typename... Args>
479struct DefaultReplayer<Result(Args...)> : public Replayer {
480 DefaultReplayer(Result (*f)(Args...)) : Replayer(), f(f) {}
481
482 void operator()(Deserializer &deserializer) const override {
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700483 Replay(deserializer);
484 }
485
486 Result Replay(Deserializer &deserializer) const {
487 return deserializer.HandleReplayResult(
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000488 DeserializationHelper<Args...>::template deserialized<Result>::doit(
489 deserializer, f));
490 }
491
492 Result (*f)(Args...);
493};
494
495/// Partial specialization for function returning a void type. It ignores the
496/// (absent) return value.
497template <typename... Args>
498struct DefaultReplayer<void(Args...)> : public Replayer {
499 DefaultReplayer(void (*f)(Args...)) : Replayer(), f(f) {}
500
501 void operator()(Deserializer &deserializer) const override {
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700502 Replay(deserializer);
503 }
504
505 void Replay(Deserializer &deserializer) const {
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000506 DeserializationHelper<Args...>::template deserialized<void>::doit(
507 deserializer, f);
508 deserializer.HandleReplayResultVoid();
509 }
510
511 void (*f)(Args...);
512};
513
514/// The registry contains a unique mapping between functions and their ID. The
515/// IDs can be serialized and deserialized to replay a function. Functions need
516/// to be registered with the registry for this to work.
517class Registry {
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000518private:
519 struct SignatureStr {
520 SignatureStr(llvm::StringRef result = {}, llvm::StringRef scope = {},
521 llvm::StringRef name = {}, llvm::StringRef args = {})
522 : result(result), scope(scope), name(name), args(args) {}
523
524 std::string ToString() const;
525
526 llvm::StringRef result;
527 llvm::StringRef scope;
528 llvm::StringRef name;
529 llvm::StringRef args;
530 };
531
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000532public:
533 Registry() = default;
534 virtual ~Registry() = default;
535
536 /// Register a default replayer for a function.
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000537 template <typename Signature>
538 void Register(Signature *f, llvm::StringRef result = {},
539 llvm::StringRef scope = {}, llvm::StringRef name = {},
540 llvm::StringRef args = {}) {
Jonas Devliegherea8f3ae72019-08-14 22:19:23 +0000541 DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(f),
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000542 SignatureStr(result, scope, name, args));
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000543 }
544
545 /// Register a replayer that invokes a custom function with the same
546 /// signature as the replayed function.
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000547 template <typename Signature>
548 void Register(Signature *f, Signature *g, llvm::StringRef result = {},
549 llvm::StringRef scope = {}, llvm::StringRef name = {},
550 llvm::StringRef args = {}) {
Jonas Devliegherea8f3ae72019-08-14 22:19:23 +0000551 DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(g),
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000552 SignatureStr(result, scope, name, args));
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000553 }
554
555 /// Replay functions from a file.
556 bool Replay(const FileSpec &file);
557
558 /// Replay functions from a buffer.
559 bool Replay(llvm::StringRef buffer);
560
Jonas Devliegheref78fcd62020-04-10 15:42:28 -0700561 /// Replay functions from a deserializer.
562 bool Replay(Deserializer &deserializer);
563
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000564 /// Returns the ID for a given function address.
565 unsigned GetID(uintptr_t addr);
566
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700567 /// Get the replayer matching the given ID.
568 Replayer *GetReplayer(unsigned id);
569
570 std::string GetSignature(unsigned id);
571
572 void CheckID(unsigned expected, unsigned actual);
573
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000574protected:
575 /// Register the given replayer for a function (and the ID mapping).
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000576 void DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer,
577 SignatureStr signature);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000578
579private:
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000580 /// Mapping of function addresses to replayers and their ID.
581 std::map<uintptr_t, std::pair<std::unique_ptr<Replayer>, unsigned>>
582 m_replayers;
583
584 /// Mapping of IDs to replayer instances.
Jonas Devlieghere8c436ce2019-02-27 16:40:08 +0000585 std::map<unsigned, std::pair<Replayer *, SignatureStr>> m_ids;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000586};
587
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000588/// Maps an object to an index for serialization. Indices are unique and
589/// incremented for every new object.
590///
591/// Indices start at 1 in order to differentiate with an invalid index (0) in
592/// the serialized buffer.
593class ObjectToIndex {
594public:
595 template <typename T> unsigned GetIndexForObject(T *t) {
Pavel Labath76016ba2019-02-07 13:51:38 +0000596 return GetIndexForObjectImpl(static_cast<const void *>(t));
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000597 }
598
599private:
Pavel Labath76016ba2019-02-07 13:51:38 +0000600 unsigned GetIndexForObjectImpl(const void *object);
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000601
Pavel Labath76016ba2019-02-07 13:51:38 +0000602 llvm::DenseMap<const void *, unsigned> m_mapping;
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000603};
604
605/// Serializes functions, their arguments and their return type to a stream.
606class Serializer {
607public:
608 Serializer(llvm::raw_ostream &stream = llvm::outs()) : m_stream(stream) {}
609
610 /// Recursively serialize all the given arguments.
611 template <typename Head, typename... Tail>
612 void SerializeAll(const Head &head, const Tail &... tail) {
613 Serialize(head);
614 SerializeAll(tail...);
615 }
616
Jonas Devlieghere449ca012019-09-13 19:08:10 +0000617 void SerializeAll() { m_stream.flush(); }
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000618
619private:
620 /// Serialize pointers. We need to differentiate between pointers to
621 /// fundamental types (in which case we serialize its value) and pointer to
622 /// objects (in which case we serialize their index).
623 template <typename T> void Serialize(T *t) {
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800624#ifdef LLDB_REPRO_INSTR_TRACE
Jonas Devlieghere33e3b072020-12-07 20:31:07 -0800625 this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> "
626 << stringify_args(t) << "\n";
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800627#endif
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000628 if (std::is_fundamental<T>::value) {
629 Serialize(*t);
630 } else {
631 unsigned idx = m_tracker.GetIndexForObject(t);
632 Serialize(idx);
633 }
634 }
635
636 /// Serialize references. We need to differentiate between references to
637 /// fundamental types (in which case we serialize its value) and references
638 /// to objects (in which case we serialize their index).
639 template <typename T> void Serialize(T &t) {
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800640#ifdef LLDB_REPRO_INSTR_TRACE
Jonas Devlieghere33e3b072020-12-07 20:31:07 -0800641 this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> "
642 << stringify_args(t) << "\n";
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800643#endif
Jonas Devlieghere84016982020-01-22 13:22:58 -0800644 if (is_trivially_serializable<T>::value) {
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000645 m_stream.write(reinterpret_cast<const char *>(&t), sizeof(T));
646 } else {
647 unsigned idx = m_tracker.GetIndexForObject(&t);
648 Serialize(idx);
649 }
650 }
651
Jonas Devlieghereb453caf2020-02-04 19:00:10 -0800652 void Serialize(const void *v) {
653 // FIXME: Support void*
654 }
655
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000656 void Serialize(void *v) {
657 // FIXME: Support void*
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000658 }
659
660 void Serialize(const char *t) {
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800661#ifdef LLDB_REPRO_INSTR_TRACE
Jonas Devlieghere33e3b072020-12-07 20:31:07 -0800662 this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> "
663 << stringify_args(t) << "\n";
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800664#endif
Jonas Devliegherec62ffb12020-01-31 16:17:28 -0800665 const size_t size = t ? strlen(t) : std::numeric_limits<size_t>::max();
666 Serialize(size);
667 if (t) {
668 m_stream << t;
669 m_stream.write(0x0);
670 }
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000671 }
672
Jonas Devlieghere91aa67b2020-01-29 14:06:20 -0800673 void Serialize(const char **t) {
Jonas Devlieghere446e4e42020-01-29 16:32:41 -0800674 size_t size = 0;
675 if (!t) {
676 Serialize(size);
677 return;
678 }
679
Jonas Devlieghere91aa67b2020-01-29 14:06:20 -0800680 // Compute the size of the array.
681 const char *const *temp = t;
Jonas Devlieghere91aa67b2020-01-29 14:06:20 -0800682 while (*temp++)
683 size++;
684 Serialize(size);
685
686 // Serialize the content of the array.
Jonas Devliegherec62ffb12020-01-31 16:17:28 -0800687 while (*t)
688 Serialize(*t++);
Jonas Devlieghere91aa67b2020-01-29 14:06:20 -0800689 }
690
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000691 /// Serialization stream.
692 llvm::raw_ostream &m_stream;
693
694 /// Mapping of objects to indices.
695 ObjectToIndex m_tracker;
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700696}; // namespace repro
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +0000697
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000698class InstrumentationData {
699public:
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700700 Serializer *GetSerializer() { return m_serializer; }
701 Deserializer *GetDeserializer() { return m_deserializer; }
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000702 Registry &GetRegistry() { return *m_registry; }
703
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700704 operator bool() {
705 return (m_serializer != nullptr || m_deserializer != nullptr) &&
706 m_registry != nullptr;
707 }
708
709 static void Initialize(Serializer &serializer, Registry &registry);
710 static void Initialize(Deserializer &serializer, Registry &registry);
711 static InstrumentationData &Instance();
712
713protected:
714 friend llvm::optional_detail::OptionalStorage<InstrumentationData, true>;
715 friend llvm::Optional<InstrumentationData>;
716
Jonas Devliegherefd2433e2021-07-02 11:27:37 -0700717 InstrumentationData() = default;
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700718 InstrumentationData(Serializer &serializer, Registry &registry)
719 : m_serializer(&serializer), m_deserializer(nullptr),
720 m_registry(&registry) {}
721 InstrumentationData(Deserializer &deserializer, Registry &registry)
722 : m_serializer(nullptr), m_deserializer(&deserializer),
723 m_registry(&registry) {}
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000724
725private:
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700726 static llvm::Optional<InstrumentationData> &InstanceImpl();
727
Jonas Devlieghere9494c512021-06-09 09:25:29 -0700728 Serializer *m_serializer = nullptr;
729 Deserializer *m_deserializer = nullptr;
730 Registry *m_registry = nullptr;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000731};
732
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700733struct EmptyArg {};
734
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000735/// RAII object that records function invocations and their return value.
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000736///
737/// API calls are only captured when the API boundary is crossed. Once we're in
738/// the API layer, and another API function is called, it doesn't need to be
739/// recorded.
740///
741/// When a call is recored, its result is always recorded as well, even if the
742/// function returns a void. For functions that return by value, RecordResult
743/// should be used. Otherwise a sentinel value (0) will be serialized.
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000744///
745/// Because of the functional overlap between logging and recording API calls,
746/// this class is also used for logging.
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000747class Recorder {
748public:
Jonas Devliegheree7f10672020-05-27 10:27:44 -0700749 Recorder();
750 Recorder(llvm::StringRef pretty_func, std::string &&pretty_args = {});
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000751 ~Recorder();
752
753 /// Records a single function call.
754 template <typename Result, typename... FArgs, typename... RArgs>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000755 void Record(Serializer &serializer, Registry &registry, Result (*f)(FArgs...),
756 const RArgs &... args) {
757 m_serializer = &serializer;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000758 if (!ShouldCapture())
759 return;
760
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800761 std::lock_guard<std::mutex> lock(g_mutex);
762 unsigned sequence = GetSequenceNumber();
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000763 unsigned id = registry.GetID(uintptr_t(f));
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000764
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800765#ifdef LLDB_REPRO_INSTR_TRACE
766 Log(id);
767#endif
768
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800769 serializer.SerializeAll(sequence);
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000770 serializer.SerializeAll(id);
771 serializer.SerializeAll(args...);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000772
773 if (std::is_class<typename std::remove_pointer<
774 typename std::remove_reference<Result>::type>::type>::value) {
775 m_result_recorded = false;
776 } else {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800777 serializer.SerializeAll(sequence);
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000778 serializer.SerializeAll(0);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000779 m_result_recorded = true;
780 }
781 }
782
783 /// Records a single function call.
784 template <typename... Args>
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000785 void Record(Serializer &serializer, Registry &registry, void (*f)(Args...),
786 const Args &... args) {
787 m_serializer = &serializer;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000788 if (!ShouldCapture())
789 return;
790
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800791 std::lock_guard<std::mutex> lock(g_mutex);
792 unsigned sequence = GetSequenceNumber();
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000793 unsigned id = registry.GetID(uintptr_t(f));
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000794
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800795#ifdef LLDB_REPRO_INSTR_TRACE
796 Log(id);
797#endif
798
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800799 serializer.SerializeAll(sequence);
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000800 serializer.SerializeAll(id);
801 serializer.SerializeAll(args...);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000802
803 // Record result.
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800804 serializer.SerializeAll(sequence);
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000805 serializer.SerializeAll(0);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000806 m_result_recorded = true;
807 }
808
Jonas Devliegherea3237f82020-04-14 13:28:27 -0700809 /// Specializations for the no-argument methods. These are passed an empty
810 /// dummy argument so the same variadic macro can be used. These methods
811 /// strip the arguments before forwarding them.
812 template <typename Result>
813 void Record(Serializer &serializer, Registry &registry, Result (*f)(),
814 const EmptyArg &arg) {
815 Record(serializer, registry, f);
816 }
817
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000818 /// Record the result of a function call.
Jonas Devlieghere05badc62020-01-30 11:20:15 -0800819 template <typename Result>
820 Result RecordResult(Result &&r, bool update_boundary) {
821 // When recording the result from the LLDB_RECORD_RESULT macro, we need to
822 // update the boundary so we capture the copy constructor. However, when
823 // called to record the this pointer of the (copy) constructor, the
824 // boundary should not be toggled, because it is called from the
825 // LLDB_RECORD_CONSTRUCTOR macro, which might be followed by other API
826 // calls.
827 if (update_boundary)
828 UpdateBoundary();
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000829 if (m_serializer && ShouldCapture()) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800830 std::lock_guard<std::mutex> lock(g_mutex);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000831 assert(!m_result_recorded);
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800832 m_serializer->SerializeAll(GetSequenceNumber());
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000833 m_serializer->SerializeAll(r);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000834 m_result_recorded = true;
835 }
Jonas Devlieghere306809f2019-04-03 21:31:22 +0000836 return std::forward<Result>(r);
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000837 }
838
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700839 template <typename Result, typename T>
840 Result Replay(Deserializer &deserializer, Registry &registry, uintptr_t addr,
841 bool update_boundary) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800842 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700843 unsigned actual_id = registry.GetID(addr);
844 unsigned id = deserializer.Deserialize<unsigned>();
845 registry.CheckID(id, actual_id);
846 return ReplayResult<Result>(
847 static_cast<DefaultReplayer<T> *>(registry.GetReplayer(id))
848 ->Replay(deserializer),
849 update_boundary);
850 }
851
852 void Replay(Deserializer &deserializer, Registry &registry, uintptr_t addr) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800853 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700854 unsigned actual_id = registry.GetID(addr);
855 unsigned id = deserializer.Deserialize<unsigned>();
856 registry.CheckID(id, actual_id);
857 registry.GetReplayer(id)->operator()(deserializer);
858 }
859
860 template <typename Result>
861 Result ReplayResult(Result &&r, bool update_boundary) {
862 if (update_boundary)
863 UpdateBoundary();
864 return std::forward<Result>(r);
865 }
866
867 bool ShouldCapture() { return m_local_boundary; }
868
Jonas Devlieghere58612342020-12-07 20:59:13 -0800869 /// Mark the current thread as a private thread and pretend that everything
870 /// on this thread is behind happening behind the API boundary.
Martin Storsjö7106f582021-10-08 11:41:02 +0300871 static void PrivateThread();
Jonas Devlieghere58612342020-12-07 20:59:13 -0800872
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000873private:
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800874 static unsigned GetNextSequenceNumber() { return g_sequence++; }
875 unsigned GetSequenceNumber() const;
876
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700877 template <typename T> friend struct replay;
Martin Storsjö7106f582021-10-08 11:41:02 +0300878 void UpdateBoundary();
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000879
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000880#ifdef LLDB_REPRO_INSTR_TRACE
Jonas Devlieghere7ac94432020-02-04 16:10:10 -0800881 void Log(unsigned id) {
Jonas Devlieghere33e3b072020-12-07 20:31:07 -0800882 this_thread_id() << "Recording " << id << ": " << m_pretty_func << " ("
883 << m_pretty_args << ")\n";
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000884 }
885#endif
886
Jonas Devlieghere9494c512021-06-09 09:25:29 -0700887 Serializer *m_serializer = nullptr;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000888
889 /// Pretty function for logging.
890 llvm::StringRef m_pretty_func;
Jonas Devliegheredb41fe12019-04-23 17:44:40 +0000891 std::string m_pretty_args;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000892
893 /// Whether this function call was the one crossing the API boundary.
Jonas Devlieghere9494c512021-06-09 09:25:29 -0700894 bool m_local_boundary = false;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000895
896 /// Whether the return value was recorded explicitly.
Jonas Devlieghere9494c512021-06-09 09:25:29 -0700897 bool m_result_recorded = true;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000898
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800899 /// The sequence number for this pair of function and result.
900 unsigned m_sequence;
901
Jonas Devlieghereac25e862020-12-10 09:35:12 -0800902 /// Global mutex to protect concurrent access.
903 static std::mutex g_mutex;
904
905 /// Unique, monotonically increasing sequence number.
906 static std::atomic<unsigned> g_sequence;
Jonas Devlieghere58947cf2019-02-06 18:57:42 +0000907};
908
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -0700909/// To be used as the "Runtime ID" of a constructor. It also invokes the
910/// constructor when called.
911template <typename Signature> struct construct;
912template <typename Class, typename... Args> struct construct<Class(Args...)> {
913 static Class *handle(lldb_private::repro::InstrumentationData data,
914 lldb_private::repro::Recorder &recorder, Class *c,
915 const EmptyArg &) {
916 return handle(data, recorder, c);
917 }
918
919 static Class *handle(lldb_private::repro::InstrumentationData data,
920 lldb_private::repro::Recorder &recorder, Class *c,
921 Args... args) {
922 if (!data)
923 return nullptr;
924
925 if (Serializer *serializer = data.GetSerializer()) {
926 recorder.Record(*serializer, data.GetRegistry(), &record, args...);
927 recorder.RecordResult(c, false);
928 } else if (Deserializer *deserializer = data.GetDeserializer()) {
929 if (recorder.ShouldCapture()) {
930 replay(recorder, *deserializer, data.GetRegistry());
931 }
932 }
933
934 return nullptr;
935 }
936
937 static Class *record(Args... args) { return new Class(args...); }
938
939 static Class *replay(Recorder &recorder, Deserializer &deserializer,
940 Registry &registry) {
941 return recorder.Replay<Class *, Class *(Args...)>(
942 deserializer, registry, uintptr_t(&record), false);
943 }
944};
945
946/// To be used as the "Runtime ID" of a member function. It also invokes the
947/// member function when called.
948template <typename Signature> struct invoke;
949template <typename Result, typename Class, typename... Args>
950struct invoke<Result (Class::*)(Args...)> {
951 template <Result (Class::*m)(Args...)> struct method {
952 static Result record(Class *c, Args... args) { return (c->*m)(args...); }
953
954 static Result replay(Recorder &recorder, Deserializer &deserializer,
955 Registry &registry) {
956 return recorder.Replay<Result, Result(Class *, Args...)>(
957 deserializer, registry, uintptr_t(&record), true);
958 }
959 };
960};
961
962template <typename Class, typename... Args>
963struct invoke<void (Class::*)(Args...)> {
964 template <void (Class::*m)(Args...)> struct method {
965 static void record(Class *c, Args... args) { (c->*m)(args...); }
966 static void replay(Recorder &recorder, Deserializer &deserializer,
967 Registry &registry) {
968 recorder.Replay(deserializer, registry, uintptr_t(&record));
969 }
970 };
971};
972
973template <typename Result, typename Class, typename... Args>
974struct invoke<Result (Class::*)(Args...) const> {
975 template <Result (Class::*m)(Args...) const> struct method {
976 static Result record(Class *c, Args... args) { return (c->*m)(args...); }
977 static Result replay(Recorder &recorder, Deserializer &deserializer,
978 Registry &registry) {
979 return recorder.Replay<Result, Result(Class *, Args...)>(
980 deserializer, registry, uintptr_t(&record), true);
981 }
982 };
983};
984
985template <typename Class, typename... Args>
986struct invoke<void (Class::*)(Args...) const> {
987 template <void (Class::*m)(Args...) const> struct method {
988 static void record(Class *c, Args... args) { return (c->*m)(args...); }
989 static void replay(Recorder &recorder, Deserializer &deserializer,
990 Registry &registry) {
991 recorder.Replay(deserializer, registry, uintptr_t(&record));
992 }
993 };
994};
995
996template <typename Signature> struct replay;
997
998template <typename Result, typename Class, typename... Args>
999struct replay<Result (Class::*)(Args...)> {
1000 template <Result (Class::*m)(Args...)> struct method {};
1001};
1002
1003template <typename Result, typename... Args>
1004struct invoke<Result (*)(Args...)> {
1005 template <Result (*m)(Args...)> struct method {
1006 static Result record(Args... args) { return (*m)(args...); }
1007 static Result replay(Recorder &recorder, Deserializer &deserializer,
1008 Registry &registry) {
1009 return recorder.Replay<Result, Result(Args...)>(deserializer, registry,
1010 uintptr_t(&record), true);
1011 }
1012 };
1013};
1014
1015template <typename... Args> struct invoke<void (*)(Args...)> {
1016 template <void (*m)(Args...)> struct method {
1017 static void record(Args... args) { return (*m)(args...); }
1018 static void replay(Recorder &recorder, Deserializer &deserializer,
1019 Registry &registry) {
1020 recorder.Replay(deserializer, registry, uintptr_t(&record));
1021 }
1022 };
1023};
1024
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001025/// Special handling for functions returning strings as (char*, size_t).
1026/// {
1027
1028/// For inline replay, we ignore the arguments and use the ones from the
1029/// serializer instead. This doesn't work for methods that use a char* and a
1030/// size to return a string. For one these functions have a custom replayer to
1031/// prevent override the input buffer. Furthermore, the template-generated
1032/// deserialization is not easy to hook into.
1033///
1034/// The specializations below hand-implement the serialization logic for the
1035/// inline replay. Instead of using the function from the registry, it uses the
1036/// one passed into the macro.
1037template <typename Signature> struct invoke_char_ptr;
1038template <typename Result, typename Class, typename... Args>
1039struct invoke_char_ptr<Result (Class::*)(Args...) const> {
1040 template <Result (Class::*m)(Args...) const> struct method {
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -07001041 static Result record(Class *c, char *s, size_t l) {
Jonas Devlieghere2f025bb2020-02-05 19:41:09 -08001042 char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char)));
1043 return (c->*m)(buffer, l);
1044 }
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001045
1046 static Result replay(Recorder &recorder, Deserializer &deserializer,
1047 Registry &registry, char *str) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -08001048 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001049 deserializer.Deserialize<unsigned>();
1050 Class *c = deserializer.Deserialize<Class *>();
1051 deserializer.Deserialize<const char *>();
1052 size_t l = deserializer.Deserialize<size_t>();
1053 return recorder.ReplayResult(
1054 std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true);
1055 }
Jonas Devlieghere2f025bb2020-02-05 19:41:09 -08001056 };
1057};
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001058
1059template <typename Signature> struct invoke_char_ptr;
1060template <typename Result, typename Class, typename... Args>
1061struct invoke_char_ptr<Result (Class::*)(Args...)> {
1062 template <Result (Class::*m)(Args...)> struct method {
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -07001063 static Result record(Class *c, char *s, size_t l) {
Jonas Devlieghere2f025bb2020-02-05 19:41:09 -08001064 char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char)));
1065 return (c->*m)(buffer, l);
1066 }
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001067
1068 static Result replay(Recorder &recorder, Deserializer &deserializer,
1069 Registry &registry, char *str) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -08001070 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001071 deserializer.Deserialize<unsigned>();
1072 Class *c = deserializer.Deserialize<Class *>();
1073 deserializer.Deserialize<const char *>();
1074 size_t l = deserializer.Deserialize<size_t>();
1075 return recorder.ReplayResult(
1076 std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true);
1077 }
Jonas Devlieghere2f025bb2020-02-05 19:41:09 -08001078 };
1079};
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001080
1081template <typename Result, typename... Args>
1082struct invoke_char_ptr<Result (*)(Args...)> {
1083 template <Result (*m)(Args...)> struct method {
Jonas Devlieghere950a8aa2020-04-20 09:37:07 -07001084 static Result record(char *s, size_t l) {
Jonas Devlieghereba108402020-04-14 10:18:50 -07001085 char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char)));
1086 return (*m)(buffer, l);
1087 }
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001088
1089 static Result replay(Recorder &recorder, Deserializer &deserializer,
1090 Registry &registry, char *str) {
Jonas Devlieghereac25e862020-12-10 09:35:12 -08001091 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001092 deserializer.Deserialize<unsigned>();
1093 deserializer.Deserialize<const char *>();
1094 size_t l = deserializer.Deserialize<size_t>();
1095 return recorder.ReplayResult(
1096 std::move(deserializer.HandleReplayResult((*m)(str, l))), true);
1097 }
Jonas Devlieghereba108402020-04-14 10:18:50 -07001098 };
1099};
Jonas Devliegheree687aa82020-04-20 13:20:24 -07001100/// }
Jonas Devlieghere2f025bb2020-02-05 19:41:09 -08001101
Jonas Devlieghere494fd8f2019-02-05 18:46:36 +00001102} // namespace repro
1103} // namespace lldb_private
1104
Jonas Devliegherecdc514e2020-02-17 15:57:45 -08001105#endif // LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H