1 //===-- ReproducerInstrumentation.h -----------------------------*- C++ -*-===//
2 // 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
8 #ifndef LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H
9 #define LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H
10
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
19 #include <map>
20 #include <thread>
21 #include <type_traits>
22
23 template <typename T,
24 typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0>
stringify_append(llvm::raw_string_ostream & ss,const T & t)25 inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) {
26 ss << t;
27 }
28
29 template <typename T, typename std::enable_if<!std::is_fundamental<T>::value,
30 int>::type = 0>
stringify_append(llvm::raw_string_ostream & ss,const T & t)31 inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) {
32 ss << &t;
33 }
34
35 template <typename T>
stringify_append(llvm::raw_string_ostream & ss,T * t)36 inline void stringify_append(llvm::raw_string_ostream &ss, T *t) {
37 ss << reinterpret_cast<void *>(t);
38 }
39
40 template <typename T>
stringify_append(llvm::raw_string_ostream & ss,const T * t)41 inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) {
42 ss << reinterpret_cast<const void *>(t);
43 }
44
45 template <>
46 inline void stringify_append<char>(llvm::raw_string_ostream &ss,
47 const char *t) {
48 ss << '\"' << t << '\"';
49 }
50
51 template <>
52 inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss,
53 const std::nullptr_t &t) {
54 ss << "\"nullptr\"";
55 }
56
57 template <typename Head>
stringify_helper(llvm::raw_string_ostream & ss,const Head & head)58 inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) {
59 stringify_append(ss, head);
60 }
61
62 template <typename Head, typename... Tail>
stringify_helper(llvm::raw_string_ostream & ss,const Head & head,const Tail &...tail)63 inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head,
64 const Tail &... tail) {
65 stringify_append(ss, head);
66 ss << ", ";
67 stringify_helper(ss, tail...);
68 }
69
stringify_args(const Ts &...ts)70 template <typename... Ts> inline std::string stringify_args(const Ts &... ts) {
71 std::string buffer;
72 llvm::raw_string_ostream ss(buffer);
73 stringify_helper(ss, ts...);
74 return ss.str();
75 }
76
77 // 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.
80 // #define LLDB_REPRO_INSTR_TRACE
81
82 #ifdef LLDB_REPRO_INSTR_TRACE
this_thread_id()83 inline 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
89 #define LLDB_REGISTER_CONSTRUCTOR(Class, Signature) \
90 R.Register<Class * Signature>(&construct<Class Signature>::record, "", \
91 #Class, #Class, #Signature)
92
93 #define LLDB_REGISTER_METHOD(Result, Class, Method, Signature) \
94 R.Register( \
95 &invoke<Result(Class::*) Signature>::method<(&Class::Method)>::record, \
96 #Result, #Class, #Method, #Signature)
97
98 #define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature) \
99 R.Register(&invoke<Result(Class::*) \
100 Signature const>::method<(&Class::Method)>::record, \
101 #Result, #Class, #Method, #Signature)
102
103 #define LLDB_REGISTER_STATIC_METHOD(Result, Class, Method, Signature) \
104 R.Register(&invoke<Result(*) Signature>::method<(&Class::Method)>::record, \
105 #Result, #Class, #Method, #Signature)
106
107 #define LLDB_REGISTER_CHAR_PTR_METHOD_STATIC(Result, Class, Method) \
108 R.Register( \
109 &invoke<Result (*)(char *, size_t)>::method<(&Class::Method)>::record, \
110 &invoke_char_ptr<Result (*)(char *, \
111 size_t)>::method<(&Class::Method)>::record, \
112 #Result, #Class, #Method, "(char*, size_t");
113
114 #define LLDB_REGISTER_CHAR_PTR_METHOD(Result, Class, Method) \
115 R.Register(&invoke<Result (Class::*)(char *, size_t)>::method<( \
116 &Class::Method)>::record, \
117 &invoke_char_ptr<Result (Class::*)(char *, size_t)>::method<( \
118 &Class::Method)>::record, \
119 #Result, #Class, #Method, "(char*, size_t");
120
121 #define LLDB_REGISTER_CHAR_PTR_METHOD_CONST(Result, Class, Method) \
122 R.Register(&invoke<Result (Class::*)(char *, size_t) \
123 const>::method<(&Class::Method)>::record, \
124 &invoke_char_ptr<Result (Class::*)(char *, size_t) \
125 const>::method<(&Class::Method)>::record, \
126 #Result, #Class, #Method, "(char*, size_t");
127
128 #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__);
132
133 #define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \
134 LLDB_CONSTRUCT_(Class Signature, this, __VA_ARGS__)
135
136 #define LLDB_RECORD_CONSTRUCTOR_NO_ARGS(Class) \
137 LLDB_CONSTRUCT_(Class(), this, lldb_private::repro::EmptyArg())
138
139 #define LLDB_RECORD_(T1, T2, ...) \
140 lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \
141 stringify_args(__VA_ARGS__)); \
142 if (lldb_private::repro::InstrumentationData _data = \
143 LLDB_GET_INSTRUMENTATION_DATA()) { \
144 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 } \
156 }
157
158 #define LLDB_RECORD_METHOD(Result, Class, Method, Signature, ...) \
159 LLDB_RECORD_(Result(Class::*) Signature, (&Class::Method), this, __VA_ARGS__)
160
161 #define LLDB_RECORD_METHOD_CONST(Result, Class, Method, Signature, ...) \
162 LLDB_RECORD_(Result(Class::*) Signature const, (&Class::Method), this, \
163 __VA_ARGS__)
164
165 #define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method) \
166 LLDB_RECORD_(Result (Class::*)(), (&Class::Method), this)
167
168 #define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method) \
169 LLDB_RECORD_(Result (Class::*)() const, (&Class::Method), this)
170
171 #define LLDB_RECORD_STATIC_METHOD(Result, Class, Method, Signature, ...) \
172 LLDB_RECORD_(Result(*) Signature, (&Class::Method), __VA_ARGS__)
173
174 #define LLDB_RECORD_STATIC_METHOD_NO_ARGS(Result, Class, Method) \
175 LLDB_RECORD_(Result (*)(), (&Class::Method), lldb_private::repro::EmptyArg())
176
177 #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
211 #define LLDB_RECORD_RESULT(Result) _recorder.RecordResult(Result, true);
212
213 /// 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, ...) \
217 lldb_private::repro::Recorder _recorder;
218
219 #define LLDB_RECORD_DUMMY_NO_ARGS(Result, Class, Method) \
220 lldb_private::repro::Recorder _recorder;
221
222 namespace lldb_private {
223 namespace repro {
224
225 template <class T>
226 struct is_trivially_serializable
227 : std::integral_constant<bool, std::is_fundamental<T>::value ||
228 std::is_enum<T>::value> {};
229
230 /// 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.
241 class IndexToObject {
242 public:
243 /// Returns an object as a pointer for the given index or nullptr if not
244 /// present in the map.
GetObjectForIndex(unsigned idx)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.
AddObjectForIndex(unsigned idx,T * object)252 template <typename T> T *AddObjectForIndex(unsigned idx, T *object) {
253 AddObjectForIndexImpl(
254 idx, static_cast<void *>(
255 const_cast<typename std::remove_const<T>::type *>(object)));
256 return object;
257 }
258
259 /// Adds a reference to an object to the mapping for the given index.
AddObjectForIndex(unsigned idx,T & object)260 template <typename T> T &AddObjectForIndex(unsigned idx, T &object) {
261 AddObjectForIndexImpl(
262 idx, static_cast<void *>(
263 const_cast<typename std::remove_const<T>::type *>(&object)));
264 return object;
265 }
266
267 /// Get all objects sorted by their index.
268 std::vector<void *> GetAllObjects() const;
269
270 private:
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.
285 struct PointerTag {};
286 struct ReferenceTag {};
287 struct ValueTag {};
288 struct FundamentalPointerTag {};
289 struct FundamentalReferenceTag {};
290
291 /// Return the deserialization tag for the given type T.
292 template <class T> struct serializer_tag {
293 typedef typename std::conditional<std::is_trivially_copyable<T>::value,
294 ValueTag, ReferenceTag>::type type;
295 };
296 template <class T> struct serializer_tag<T *> {
297 typedef
298 typename std::conditional<std::is_fundamental<T>::value,
299 FundamentalPointerTag, PointerTag>::type type;
300 };
301 template <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).
318 class Deserializer {
319 public:
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() {
327 T t = Read<T>(typename serializer_tag<T>::type());
328 #ifdef LLDB_REPRO_INSTR_TRACE
329 llvm::errs() << "Deserializing with " << LLVM_PRETTY_FUNCTION << " -> "
330 << stringify_args(t) << "\n";
331 #endif
332 return t;
333 }
334
335 template <typename T> const T &HandleReplayResult(const T &t) {
336 CheckSequence(Deserialize<unsigned>());
337 unsigned result = Deserialize<unsigned>();
338 if (is_trivially_serializable<T>::value)
339 return t;
340 // We need to make a copy as the original object might go out of scope.
341 return *m_index_to_object.AddObjectForIndex(result, new T(t));
342 }
343
344 /// Store the returned value in the index-to-object mapping.
345 template <typename T> T &HandleReplayResult(T &t) {
346 CheckSequence(Deserialize<unsigned>());
347 unsigned result = Deserialize<unsigned>();
348 if (is_trivially_serializable<T>::value)
349 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) {
356 CheckSequence(Deserialize<unsigned>());
357 unsigned result = Deserialize<unsigned>();
358 if (is_trivially_serializable<T>::value)
359 return t;
360 return m_index_to_object.AddObjectForIndex(result, t);
361 }
362
363 /// All returned types are recorded, even when the function returns a void.
364 /// The latter requires special handling.
365 void HandleReplayResultVoid() {
366 CheckSequence(Deserialize<unsigned>());
367 unsigned result = Deserialize<unsigned>();
368 assert(result == 0);
369 (void)result;
370 }
371
372 std::vector<void *> GetAllObjects() const {
373 return m_index_to_object.GetAllObjects();
374 }
375
376 void SetExpectedSequence(unsigned sequence) {
377 m_expected_sequence = sequence;
378 }
379
380 private:
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
421 /// Verify that the given sequence number matches what we expect.
422 void CheckSequence(unsigned sequence);
423
424 /// Mapping of indices to objects.
425 IndexToObject m_index_to_object;
426
427 /// Buffer containing the serialized data.
428 llvm::StringRef m_buffer;
429
430 /// The result's expected sequence number.
431 llvm::Optional<unsigned> m_expected_sequence;
432 };
433
434 /// Partial specialization for C-style strings. We read the string value
435 /// instead of treating it as pointer.
436 template <> const char *Deserializer::Deserialize<const char *>();
437 template <> const char **Deserializer::Deserialize<const char **>();
438 template <> const uint8_t *Deserializer::Deserialize<const uint8_t *>();
439 template <> const void *Deserializer::Deserialize<const void *>();
440 template <> char *Deserializer::Deserialize<char *>();
441 template <> void *Deserializer::Deserialize<void *>();
442
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.
446 template <typename... Remaining> struct DeserializationHelper;
447
448 template <typename Head, typename... Tail>
449 struct 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
461 template <> 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
470 /// The replayer interface.
471 struct Replayer {
472 virtual ~Replayer() = default;
473 virtual void operator()(Deserializer &deserializer) const = 0;
474 };
475
476 /// The default replayer deserializes the arguments and calls the function.
477 template <typename Signature> struct DefaultReplayer;
478 template <typename Result, typename... Args>
479 struct DefaultReplayer<Result(Args...)> : public Replayer {
480 DefaultReplayer(Result (*f)(Args...)) : Replayer(), f(f) {}
481
482 void operator()(Deserializer &deserializer) const override {
483 Replay(deserializer);
484 }
485
486 Result Replay(Deserializer &deserializer) const {
487 return deserializer.HandleReplayResult(
488 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.
497 template <typename... Args>
498 struct DefaultReplayer<void(Args...)> : public Replayer {
499 DefaultReplayer(void (*f)(Args...)) : Replayer(), f(f) {}
500
501 void operator()(Deserializer &deserializer) const override {
502 Replay(deserializer);
503 }
504
505 void Replay(Deserializer &deserializer) const {
506 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.
517 class Registry {
518 private:
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
532 public:
533 Registry() = default;
534 virtual ~Registry() = default;
535
536 /// Register a default replayer for a function.
537 template <typename Signature>
538 void Register(Signature *f, llvm::StringRef result = {},
539 llvm::StringRef scope = {}, llvm::StringRef name = {},
540 llvm::StringRef args = {}) {
541 DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(f),
542 SignatureStr(result, scope, name, args));
543 }
544
545 /// Register a replayer that invokes a custom function with the same
546 /// signature as the replayed function.
547 template <typename Signature>
548 void Register(Signature *f, Signature *g, llvm::StringRef result = {},
549 llvm::StringRef scope = {}, llvm::StringRef name = {},
550 llvm::StringRef args = {}) {
551 DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(g),
552 SignatureStr(result, scope, name, args));
553 }
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
561 /// Replay functions from a deserializer.
562 bool Replay(Deserializer &deserializer);
563
564 /// Returns the ID for a given function address.
565 unsigned GetID(uintptr_t addr);
566
567 /// 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
574 protected:
575 /// Register the given replayer for a function (and the ID mapping).
576 void DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer,
577 SignatureStr signature);
578
579 private:
580 /// 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.
585 std::map<unsigned, std::pair<Replayer *, SignatureStr>> m_ids;
586 };
587
588 /// 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.
593 class ObjectToIndex {
594 public:
595 template <typename T> unsigned GetIndexForObject(T *t) {
596 return GetIndexForObjectImpl(static_cast<const void *>(t));
597 }
598
599 private:
600 unsigned GetIndexForObjectImpl(const void *object);
601
602 llvm::DenseMap<const void *, unsigned> m_mapping;
603 };
604
605 /// Serializes functions, their arguments and their return type to a stream.
606 class Serializer {
607 public:
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
617 void SerializeAll() { m_stream.flush(); }
618
619 private:
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) {
624 #ifdef LLDB_REPRO_INSTR_TRACE
625 this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> "
626 << stringify_args(t) << "\n";
627 #endif
628 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) {
640 #ifdef LLDB_REPRO_INSTR_TRACE
641 this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> "
642 << stringify_args(t) << "\n";
643 #endif
644 if (is_trivially_serializable<T>::value) {
645 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
652 void Serialize(const void *v) {
653 // FIXME: Support void*
654 }
655
656 void Serialize(void *v) {
657 // FIXME: Support void*
658 }
659
660 void Serialize(const char *t) {
661 #ifdef LLDB_REPRO_INSTR_TRACE
662 this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> "
663 << stringify_args(t) << "\n";
664 #endif
665 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 }
671 }
672
673 void Serialize(const char **t) {
674 size_t size = 0;
675 if (!t) {
676 Serialize(size);
677 return;
678 }
679
680 // Compute the size of the array.
681 const char *const *temp = t;
682 while (*temp++)
683 size++;
684 Serialize(size);
685
686 // Serialize the content of the array.
687 while (*t)
688 Serialize(*t++);
689 }
690
691 /// Serialization stream.
692 llvm::raw_ostream &m_stream;
693
694 /// Mapping of objects to indices.
695 ObjectToIndex m_tracker;
696 }; // namespace repro
697
698 class InstrumentationData {
699 public:
700 Serializer *GetSerializer() { return m_serializer; }
701 Deserializer *GetDeserializer() { return m_deserializer; }
702 Registry &GetRegistry() { return *m_registry; }
703
704 operator bool() {
705 return (m_serializer != nullptr || m_deserializer != nullptr) &&
706 m_registry != nullptr;
707 }
708
709 static void Initialize(Serializer &serializer, Registry ®istry);
710 static void Initialize(Deserializer &serializer, Registry ®istry);
711 static InstrumentationData &Instance();
712
713 protected:
714 friend llvm::optional_detail::OptionalStorage<InstrumentationData, true>;
715 friend llvm::Optional<InstrumentationData>;
716
717 InstrumentationData() = default;
718 InstrumentationData(Serializer &serializer, Registry ®istry)
719 : m_serializer(&serializer), m_deserializer(nullptr),
720 m_registry(®istry) {}
721 InstrumentationData(Deserializer &deserializer, Registry ®istry)
722 : m_serializer(nullptr), m_deserializer(&deserializer),
723 m_registry(®istry) {}
724
725 private:
726 static llvm::Optional<InstrumentationData> &InstanceImpl();
727
728 Serializer *m_serializer = nullptr;
729 Deserializer *m_deserializer = nullptr;
730 Registry *m_registry = nullptr;
731 };
732
733 struct EmptyArg {};
734
735 /// RAII object that records function invocations and their return value.
736 ///
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.
744 ///
745 /// Because of the functional overlap between logging and recording API calls,
746 /// this class is also used for logging.
747 class Recorder {
748 public:
749 Recorder();
750 Recorder(llvm::StringRef pretty_func, std::string &&pretty_args = {});
751 ~Recorder();
752
753 /// Records a single function call.
754 template <typename Result, typename... FArgs, typename... RArgs>
755 void Record(Serializer &serializer, Registry ®istry, Result (*f)(FArgs...),
756 const RArgs &... args) {
757 m_serializer = &serializer;
758 if (!ShouldCapture())
759 return;
760
761 std::lock_guard<std::mutex> lock(g_mutex);
762 unsigned sequence = GetSequenceNumber();
763 unsigned id = registry.GetID(uintptr_t(f));
764
765 #ifdef LLDB_REPRO_INSTR_TRACE
766 Log(id);
767 #endif
768
769 serializer.SerializeAll(sequence);
770 serializer.SerializeAll(id);
771 serializer.SerializeAll(args...);
772
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 {
777 serializer.SerializeAll(sequence);
778 serializer.SerializeAll(0);
779 m_result_recorded = true;
780 }
781 }
782
783 /// Records a single function call.
784 template <typename... Args>
785 void Record(Serializer &serializer, Registry ®istry, void (*f)(Args...),
786 const Args &... args) {
787 m_serializer = &serializer;
788 if (!ShouldCapture())
789 return;
790
791 std::lock_guard<std::mutex> lock(g_mutex);
792 unsigned sequence = GetSequenceNumber();
793 unsigned id = registry.GetID(uintptr_t(f));
794
795 #ifdef LLDB_REPRO_INSTR_TRACE
796 Log(id);
797 #endif
798
799 serializer.SerializeAll(sequence);
800 serializer.SerializeAll(id);
801 serializer.SerializeAll(args...);
802
803 // Record result.
804 serializer.SerializeAll(sequence);
805 serializer.SerializeAll(0);
806 m_result_recorded = true;
807 }
808
809 /// 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 ®istry, Result (*f)(),
814 const EmptyArg &arg) {
815 Record(serializer, registry, f);
816 }
817
818 /// Record the result of a function call.
819 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();
829 if (m_serializer && ShouldCapture()) {
830 std::lock_guard<std::mutex> lock(g_mutex);
831 assert(!m_result_recorded);
832 m_serializer->SerializeAll(GetSequenceNumber());
833 m_serializer->SerializeAll(r);
834 m_result_recorded = true;
835 }
836 return std::forward<Result>(r);
837 }
838
839 template <typename Result, typename T>
840 Result Replay(Deserializer &deserializer, Registry ®istry, uintptr_t addr,
841 bool update_boundary) {
842 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
843 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 ®istry, uintptr_t addr) {
853 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
854 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
869 /// Mark the current thread as a private thread and pretend that everything
870 /// on this thread is behind happening behind the API boundary.
871 static void PrivateThread() { g_global_boundary = true; }
872
873 private:
874 static unsigned GetNextSequenceNumber() { return g_sequence++; }
875 unsigned GetSequenceNumber() const;
876
877 template <typename T> friend struct replay;
878 void UpdateBoundary() {
879 if (m_local_boundary)
880 g_global_boundary = false;
881 }
882
883 #ifdef LLDB_REPRO_INSTR_TRACE
884 void Log(unsigned id) {
885 this_thread_id() << "Recording " << id << ": " << m_pretty_func << " ("
886 << m_pretty_args << ")\n";
887 }
888 #endif
889
890 Serializer *m_serializer = nullptr;
891
892 /// Pretty function for logging.
893 llvm::StringRef m_pretty_func;
894 std::string m_pretty_args;
895
896 /// Whether this function call was the one crossing the API boundary.
897 bool m_local_boundary = false;
898
899 /// Whether the return value was recorded explicitly.
900 bool m_result_recorded = true;
901
902 /// The sequence number for this pair of function and result.
903 unsigned m_sequence;
904
905 /// Whether we're currently across the API boundary.
906 static thread_local bool g_global_boundary;
907
908 /// Global mutex to protect concurrent access.
909 static std::mutex g_mutex;
910
911 /// Unique, monotonically increasing sequence number.
912 static std::atomic<unsigned> g_sequence;
913 };
914
915 /// To be used as the "Runtime ID" of a constructor. It also invokes the
916 /// constructor when called.
917 template <typename Signature> struct construct;
918 template <typename Class, typename... Args> struct construct<Class(Args...)> {
919 static Class *handle(lldb_private::repro::InstrumentationData data,
920 lldb_private::repro::Recorder &recorder, Class *c,
921 const EmptyArg &) {
922 return handle(data, recorder, c);
923 }
924
925 static Class *handle(lldb_private::repro::InstrumentationData data,
926 lldb_private::repro::Recorder &recorder, Class *c,
927 Args... args) {
928 if (!data)
929 return nullptr;
930
931 if (Serializer *serializer = data.GetSerializer()) {
932 recorder.Record(*serializer, data.GetRegistry(), &record, args...);
933 recorder.RecordResult(c, false);
934 } else if (Deserializer *deserializer = data.GetDeserializer()) {
935 if (recorder.ShouldCapture()) {
936 replay(recorder, *deserializer, data.GetRegistry());
937 }
938 }
939
940 return nullptr;
941 }
942
943 static Class *record(Args... args) { return new Class(args...); }
944
945 static Class *replay(Recorder &recorder, Deserializer &deserializer,
946 Registry ®istry) {
947 return recorder.Replay<Class *, Class *(Args...)>(
948 deserializer, registry, uintptr_t(&record), false);
949 }
950 };
951
952 /// To be used as the "Runtime ID" of a member function. It also invokes the
953 /// member function when called.
954 template <typename Signature> struct invoke;
955 template <typename Result, typename Class, typename... Args>
956 struct invoke<Result (Class::*)(Args...)> {
957 template <Result (Class::*m)(Args...)> struct method {
958 static Result record(Class *c, Args... args) { return (c->*m)(args...); }
959
960 static Result replay(Recorder &recorder, Deserializer &deserializer,
961 Registry ®istry) {
962 return recorder.Replay<Result, Result(Class *, Args...)>(
963 deserializer, registry, uintptr_t(&record), true);
964 }
965 };
966 };
967
968 template <typename Class, typename... Args>
969 struct invoke<void (Class::*)(Args...)> {
970 template <void (Class::*m)(Args...)> struct method {
971 static void record(Class *c, Args... args) { (c->*m)(args...); }
972 static void replay(Recorder &recorder, Deserializer &deserializer,
973 Registry ®istry) {
974 recorder.Replay(deserializer, registry, uintptr_t(&record));
975 }
976 };
977 };
978
979 template <typename Result, typename Class, typename... Args>
980 struct invoke<Result (Class::*)(Args...) const> {
981 template <Result (Class::*m)(Args...) const> struct method {
982 static Result record(Class *c, Args... args) { return (c->*m)(args...); }
983 static Result replay(Recorder &recorder, Deserializer &deserializer,
984 Registry ®istry) {
985 return recorder.Replay<Result, Result(Class *, Args...)>(
986 deserializer, registry, uintptr_t(&record), true);
987 }
988 };
989 };
990
991 template <typename Class, typename... Args>
992 struct invoke<void (Class::*)(Args...) const> {
993 template <void (Class::*m)(Args...) const> struct method {
994 static void record(Class *c, Args... args) { return (c->*m)(args...); }
995 static void replay(Recorder &recorder, Deserializer &deserializer,
996 Registry ®istry) {
997 recorder.Replay(deserializer, registry, uintptr_t(&record));
998 }
999 };
1000 };
1001
1002 template <typename Signature> struct replay;
1003
1004 template <typename Result, typename Class, typename... Args>
1005 struct replay<Result (Class::*)(Args...)> {
1006 template <Result (Class::*m)(Args...)> struct method {};
1007 };
1008
1009 template <typename Result, typename... Args>
1010 struct invoke<Result (*)(Args...)> {
1011 template <Result (*m)(Args...)> struct method {
1012 static Result record(Args... args) { return (*m)(args...); }
1013 static Result replay(Recorder &recorder, Deserializer &deserializer,
1014 Registry ®istry) {
1015 return recorder.Replay<Result, Result(Args...)>(deserializer, registry,
1016 uintptr_t(&record), true);
1017 }
1018 };
1019 };
1020
1021 template <typename... Args> struct invoke<void (*)(Args...)> {
1022 template <void (*m)(Args...)> struct method {
1023 static void record(Args... args) { return (*m)(args...); }
1024 static void replay(Recorder &recorder, Deserializer &deserializer,
1025 Registry ®istry) {
1026 recorder.Replay(deserializer, registry, uintptr_t(&record));
1027 }
1028 };
1029 };
1030
1031 /// Special handling for functions returning strings as (char*, size_t).
1032 /// {
1033
1034 /// For inline replay, we ignore the arguments and use the ones from the
1035 /// serializer instead. This doesn't work for methods that use a char* and a
1036 /// size to return a string. For one these functions have a custom replayer to
1037 /// prevent override the input buffer. Furthermore, the template-generated
1038 /// deserialization is not easy to hook into.
1039 ///
1040 /// The specializations below hand-implement the serialization logic for the
1041 /// inline replay. Instead of using the function from the registry, it uses the
1042 /// one passed into the macro.
1043 template <typename Signature> struct invoke_char_ptr;
1044 template <typename Result, typename Class, typename... Args>
1045 struct invoke_char_ptr<Result (Class::*)(Args...) const> {
1046 template <Result (Class::*m)(Args...) const> struct method {
1047 static Result record(Class *c, char *s, size_t l) {
1048 char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char)));
1049 return (c->*m)(buffer, l);
1050 }
1051
1052 static Result replay(Recorder &recorder, Deserializer &deserializer,
1053 Registry ®istry, char *str) {
1054 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
1055 deserializer.Deserialize<unsigned>();
1056 Class *c = deserializer.Deserialize<Class *>();
1057 deserializer.Deserialize<const char *>();
1058 size_t l = deserializer.Deserialize<size_t>();
1059 return recorder.ReplayResult(
1060 std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true);
1061 }
1062 };
1063 };
1064
1065 template <typename Signature> struct invoke_char_ptr;
1066 template <typename Result, typename Class, typename... Args>
1067 struct invoke_char_ptr<Result (Class::*)(Args...)> {
1068 template <Result (Class::*m)(Args...)> struct method {
1069 static Result record(Class *c, char *s, size_t l) {
1070 char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char)));
1071 return (c->*m)(buffer, l);
1072 }
1073
1074 static Result replay(Recorder &recorder, Deserializer &deserializer,
1075 Registry ®istry, char *str) {
1076 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
1077 deserializer.Deserialize<unsigned>();
1078 Class *c = deserializer.Deserialize<Class *>();
1079 deserializer.Deserialize<const char *>();
1080 size_t l = deserializer.Deserialize<size_t>();
1081 return recorder.ReplayResult(
1082 std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true);
1083 }
1084 };
1085 };
1086
1087 template <typename Result, typename... Args>
1088 struct invoke_char_ptr<Result (*)(Args...)> {
1089 template <Result (*m)(Args...)> struct method {
1090 static Result record(char *s, size_t l) {
1091 char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char)));
1092 return (*m)(buffer, l);
1093 }
1094
1095 static Result replay(Recorder &recorder, Deserializer &deserializer,
1096 Registry ®istry, char *str) {
1097 deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>());
1098 deserializer.Deserialize<unsigned>();
1099 deserializer.Deserialize<const char *>();
1100 size_t l = deserializer.Deserialize<size_t>();
1101 return recorder.ReplayResult(
1102 std::move(deserializer.HandleReplayResult((*m)(str, l))), true);
1103 }
1104 };
1105 };
1106 /// }
1107
1108 } // namespace repro
1109 } // namespace lldb_private
1110
1111 #endif // LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H
1112