LLDB  mainline
ReproducerInstrumentation.h
Go to the documentation of this file.
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>
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>
31 inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) {
32  ss << &t;
33 }
34 
35 template <typename 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>
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>
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>
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 
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_CONSTRUCT_(T, Class, ...) \
78  lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION);
79 
80 #define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \
81  LLDB_CONSTRUCT_(Class Signature, this, __VA_ARGS__)
82 
83 #define LLDB_RECORD_CONSTRUCTOR_NO_ARGS(Class) \
84  LLDB_CONSTRUCT_(Class(), this, lldb_private::repro::EmptyArg())
85 
86 #define LLDB_RECORD_(T1, T2, ...) \
87  lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \
88  stringify_args(__VA_ARGS__));
89 
90 #define LLDB_RECORD_METHOD(Result, Class, Method, Signature, ...) \
91  LLDB_RECORD_(Result(Class::*) Signature, (&Class::Method), this, __VA_ARGS__)
92 
93 #define LLDB_RECORD_METHOD_CONST(Result, Class, Method, Signature, ...) \
94  LLDB_RECORD_(Result(Class::*) Signature const, (&Class::Method), this, \
95  __VA_ARGS__)
96 
97 #define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method) \
98  LLDB_RECORD_(Result (Class::*)(), (&Class::Method), this)
99 
100 #define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method) \
101  LLDB_RECORD_(Result (Class::*)() const, (&Class::Method), this)
102 
103 #define LLDB_RECORD_STATIC_METHOD(Result, Class, Method, Signature, ...) \
104  LLDB_RECORD_(Result(*) Signature, (&Class::Method), __VA_ARGS__)
105 
106 #define LLDB_RECORD_STATIC_METHOD_NO_ARGS(Result, Class, Method) \
107  LLDB_RECORD_(Result (*)(), (&Class::Method), lldb_private::repro::EmptyArg())
108 
109 /// The LLDB_RECORD_DUMMY macro is special because it doesn't actually record
110 /// anything. It's used to track API boundaries when we cannot record for
111 /// technical reasons.
112 #define LLDB_RECORD_DUMMY(Result, Class, Method, Signature, ...) \
113  lldb_private::repro::Recorder _recorder;
114 
115 #define LLDB_RECORD_DUMMY_NO_ARGS(Result, Class, Method) \
116  lldb_private::repro::Recorder _recorder;
117 
118 namespace lldb_private {
119 namespace repro {
120 
121 struct EmptyArg {};
122 
123 /// RAII object that records function invocations and their return value.
124 ///
125 /// API calls are only captured when the API boundary is crossed. Once we're in
126 /// the API layer, and another API function is called, it doesn't need to be
127 /// recorded.
128 ///
129 /// When a call is recored, its result is always recorded as well, even if the
130 /// function returns a void. For functions that return by value, RecordResult
131 /// should be used. Otherwise a sentinel value (0) will be serialized.
132 ///
133 /// Because of the functional overlap between logging and recording API calls,
134 /// this class is also used for logging.
135 class Recorder {
136 public:
137  Recorder();
138  Recorder(llvm::StringRef pretty_func, std::string &&pretty_args = {});
139  ~Recorder();
140 
141 private:
142  void UpdateBoundary();
143 
144  /// Whether this function call was the one crossing the API boundary.
145  bool m_local_boundary = false;
146 };
147 
148 } // namespace repro
149 } // namespace lldb_private
150 
151 #endif // LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H
stringify_helper
void stringify_helper(llvm::raw_string_ostream &ss, const Head &head)
Definition: ReproducerInstrumentation.h:58
Log.h
lldb_private::repro::Recorder::UpdateBoundary
void UpdateBoundary()
Definition: ReproducerInstrumentation.cpp:43
stringify_args
std::string stringify_args(const Ts &... ts)
Definition: ReproducerInstrumentation.h:70
stringify_append
void stringify_append(llvm::raw_string_ostream &ss, const T &t)
Definition: ReproducerInstrumentation.h:25
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::repro::Recorder::m_local_boundary
bool m_local_boundary
Whether this function call was the one crossing the API boundary.
Definition: ReproducerInstrumentation.h:145
lldb_private::repro::EmptyArg
Definition: ReproducerInstrumentation.h:121
lldb_private::repro::Recorder::Recorder
Recorder()
Definition: ReproducerInstrumentation.cpp:22
lldb_private::repro::Recorder::~Recorder
~Recorder()
Definition: ReproducerInstrumentation.cpp:39
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
FileSpec.h
Logging.h
stringify_append< char >
void stringify_append< char >(llvm::raw_string_ostream &ss, const char *t)
Definition: ReproducerInstrumentation.h:46
lldb_private::repro::Recorder
RAII object that records function invocations and their return value.
Definition: ReproducerInstrumentation.h:135