xray_log_interface.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. //===-- xray_log_interface.h ----------------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file is a part of XRay, a function call tracing system.
  11. //
  12. // APIs for installing a new logging implementation.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. ///
  16. /// XRay allows users to implement their own logging handlers and install them
  17. /// to replace the default runtime-controllable implementation that comes with
  18. /// compiler-rt/xray. The "flight data recorder" (FDR) mode implementation uses
  19. /// this API to install itself in an XRay-enabled binary. See
  20. /// compiler-rt/lib/xray_fdr_logging.{h,cc} for details of that implementation.
  21. ///
  22. /// The high-level usage pattern for these APIs look like the following:
  23. ///
  24. /// // Before we try initializing the log implementation, we must set it as
  25. /// // the log implementation. We provide the function pointers that define
  26. /// // the various initialization, finalization, and other pluggable hooks
  27. /// // that we need.
  28. /// __xray_set_log_impl({...});
  29. ///
  30. /// // Once that's done, we can now initialize the implementation. Each
  31. /// // implementation has a chance to let users customize the implementation
  32. /// // with a struct that their implementation supports. Roughly this might
  33. /// // look like:
  34. /// MyImplementationOptions opts;
  35. /// opts.enable_feature = true;
  36. /// ...
  37. /// auto init_status = __xray_log_init(
  38. /// BufferSize, MaxBuffers, &opts, sizeof opts);
  39. /// if (init_status != XRayLogInitStatus::XRAY_LOG_INITIALIZED) {
  40. /// // deal with the error here, if there is one.
  41. /// }
  42. ///
  43. /// // When the log implementation has had the chance to initialize, we can
  44. /// // now patch the sleds.
  45. /// auto patch_status = __xray_patch();
  46. /// if (patch_status != XRayPatchingStatus::SUCCESS) {
  47. /// // deal with the error here, if it is an error.
  48. /// }
  49. ///
  50. /// // If we want to stop the implementation, we can then finalize it (before
  51. /// // optionally flushing the log).
  52. /// auto fin_status = __xray_log_finalize();
  53. /// if (fin_status != XRayLogInitStatus::XRAY_LOG_FINALIZED) {
  54. /// // deal with the error here, if it is an error.
  55. /// }
  56. ///
  57. /// // We can optionally wait before flushing the log to give other threads a
  58. /// // chance to see that the implementation is already finalized. Also, at
  59. /// // this point we can optionally unpatch the sleds to reduce overheads at
  60. /// // runtime.
  61. /// auto unpatch_status = __xray_unpatch();
  62. /// if (unpatch_status != XRayPatchingStatus::SUCCESS) {
  63. // // deal with the error here, if it is an error.
  64. // }
  65. ///
  66. /// // If there are logs or data to be flushed somewhere, we can do so only
  67. /// // after we've finalized the log. Some implementations may not actually
  68. /// // have anything to log (it might keep the data in memory, or periodically
  69. /// // be logging the data anyway).
  70. /// auto flush_status = __xray_log_flushLog();
  71. /// if (flush_status != XRayLogFlushStatus::XRAY_LOG_FLUSHED) {
  72. /// // deal with the error here, if it is an error.
  73. /// }
  74. ///
  75. ///
  76. /// NOTE: Before calling __xray_patch() again, consider re-initializing the
  77. /// implementation first. Some implementations might stay in an "off" state when
  78. /// they are finalized, while some might be in an invalid/unknown state.
  79. ///
  80. #ifndef XRAY_XRAY_LOG_INTERFACE_H
  81. #define XRAY_XRAY_LOG_INTERFACE_H
  82. #include "xray/xray_interface.h"
  83. #include <stddef.h>
  84. extern "C" {
  85. /// This enum defines the valid states in which the logging implementation can
  86. /// be at.
  87. enum XRayLogInitStatus {
  88. /// The default state is uninitialized, and in case there were errors in the
  89. /// initialization, the implementation MUST return XRAY_LOG_UNINITIALIZED.
  90. XRAY_LOG_UNINITIALIZED = 0,
  91. /// Some implementations support multi-stage init (or asynchronous init), and
  92. /// may return XRAY_LOG_INITIALIZING to signal callers of the API that
  93. /// there's an ongoing initialization routine running. This allows
  94. /// implementations to support concurrent threads attempting to initialize,
  95. /// while only signalling success in one.
  96. XRAY_LOG_INITIALIZING = 1,
  97. /// When an implementation is done initializing, it MUST return
  98. /// XRAY_LOG_INITIALIZED. When users call `__xray_patch()`, they are
  99. /// guaranteed that the implementation installed with
  100. /// `__xray_set_log_impl(...)` has been initialized.
  101. XRAY_LOG_INITIALIZED = 2,
  102. /// Some implementations might support multi-stage finalization (or
  103. /// asynchronous finalization), and may return XRAY_LOG_FINALIZING to signal
  104. /// callers of the API that there's an ongoing finalization routine running.
  105. /// This allows implementations to support concurrent threads attempting to
  106. /// finalize, while only signalling success/completion in one.
  107. XRAY_LOG_FINALIZING = 3,
  108. /// When an implementation is done finalizing, it MUST return
  109. /// XRAY_LOG_FINALIZED. It is up to the implementation to determine what the
  110. /// semantics of a finalized implementation is. Some implementations might
  111. /// allow re-initialization once the log is finalized, while some might always
  112. /// be on (and that finalization is a no-op).
  113. XRAY_LOG_FINALIZED = 4,
  114. };
  115. /// This enum allows an implementation to signal log flushing operations via
  116. /// `__xray_log_flushLog()`, and the state of flushing the log.
  117. enum XRayLogFlushStatus {
  118. XRAY_LOG_NOT_FLUSHING = 0,
  119. XRAY_LOG_FLUSHING = 1,
  120. XRAY_LOG_FLUSHED = 2,
  121. };
  122. /// This enum indicates the installation state of a logging implementation, when
  123. /// associating a mode to a particular logging implementation through
  124. /// `__xray_log_register_impl(...)` or through `__xray_log_select_mode(...`.
  125. enum XRayLogRegisterStatus {
  126. XRAY_REGISTRATION_OK = 0,
  127. XRAY_DUPLICATE_MODE = 1,
  128. XRAY_MODE_NOT_FOUND = 2,
  129. XRAY_INCOMPLETE_IMPL = 3,
  130. };
  131. /// A valid XRay logging implementation MUST provide all of the function
  132. /// pointers in XRayLogImpl when being installed through `__xray_set_log_impl`.
  133. /// To be precise, ALL the functions pointers MUST NOT be nullptr.
  134. struct XRayLogImpl {
  135. /// The log initialization routine provided by the implementation, always
  136. /// provided with the following parameters:
  137. ///
  138. /// - buffer size
  139. /// - maximum number of buffers
  140. /// - a pointer to an argument struct that the implementation MUST handle
  141. /// - the size of the argument struct
  142. ///
  143. /// See XRayLogInitStatus for details on what the implementation MUST return
  144. /// when called.
  145. ///
  146. /// If the implementation needs to install handlers aside from the 0-argument
  147. /// function call handler, it MUST do so in this initialization handler.
  148. ///
  149. /// See xray_interface.h for available handler installation routines.
  150. XRayLogInitStatus (*log_init)(size_t, size_t, void *, size_t);
  151. /// The log finalization routine provided by the implementation.
  152. ///
  153. /// See XRayLogInitStatus for details on what the implementation MUST return
  154. /// when called.
  155. XRayLogInitStatus (*log_finalize)();
  156. /// The 0-argument function call handler. XRay logging implementations MUST
  157. /// always have a handler for function entry and exit events. In case the
  158. /// implementation wants to support arg1 (or other future extensions to XRay
  159. /// logging) those MUST be installed by the installed 'log_init' handler.
  160. ///
  161. /// Because we didn't want to change the ABI of this struct, the arg1 handler
  162. /// may be silently overwritten during initialization as well.
  163. void (*handle_arg0)(int32_t, XRayEntryType);
  164. /// The log implementation provided routine for when __xray_log_flushLog() is
  165. /// called.
  166. ///
  167. /// See XRayLogFlushStatus for details on what the implementation MUST return
  168. /// when called.
  169. XRayLogFlushStatus (*flush_log)();
  170. };
  171. /// This function installs a new logging implementation that XRay will use. In
  172. /// case there are any nullptr members in Impl, XRay will *uninstall any
  173. /// existing implementations*. It does NOT patch the instrumentation sleds.
  174. ///
  175. /// NOTE: This function does NOT attempt to finalize the currently installed
  176. /// implementation. Use with caution.
  177. ///
  178. /// It is guaranteed safe to call this function in the following states:
  179. ///
  180. /// - When the implementation is UNINITIALIZED.
  181. /// - When the implementation is FINALIZED.
  182. /// - When there is no current implementation installed.
  183. ///
  184. /// It is logging implementation defined what happens when this function is
  185. /// called while in any other states.
  186. void __xray_set_log_impl(XRayLogImpl Impl);
  187. /// This function registers a logging implementation against a "mode"
  188. /// identifier. This allows multiple modes to be registered, and chosen at
  189. /// runtime using the same mode identifier through
  190. /// `__xray_log_select_mode(...)`.
  191. ///
  192. /// We treat the Mode identifier as a null-terminated byte string, as the
  193. /// identifier used when retrieving the log impl.
  194. ///
  195. /// Returns:
  196. /// - XRAY_REGISTRATION_OK on success.
  197. /// - XRAY_DUPLICATE_MODE when an implementation is already associated with
  198. /// the provided Mode; does not update the already-registered
  199. /// implementation.
  200. XRayLogRegisterStatus __xray_log_register_mode(const char *Mode,
  201. XRayLogImpl Impl);
  202. /// This function selects the implementation associated with Mode that has been
  203. /// registered through __xray_log_register_mode(...) and installs that
  204. /// implementation (as if through calling __xray_set_log_impl(...)). The same
  205. /// caveats apply to __xray_log_select_mode(...) as with
  206. /// __xray_log_set_log_impl(...).
  207. ///
  208. /// Returns:
  209. /// - XRAY_REGISTRATION_OK on success.
  210. /// - XRAY_MODE_NOT_FOUND if there is no implementation associated with Mode;
  211. /// does not update the currently installed implementation.
  212. XRayLogRegisterStatus __xray_log_select_mode(const char *Mode);
  213. /// This function removes the currently installed implementation. It will also
  214. /// uninstall any handlers that have been previously installed. It does NOT
  215. /// unpatch the instrumentation sleds.
  216. ///
  217. /// NOTE: This function does NOT attempt to finalize the currently installed
  218. /// implementation. Use with caution.
  219. ///
  220. /// It is guaranteed safe to call this function in the following states:
  221. ///
  222. /// - When the implementation is UNINITIALIZED.
  223. /// - When the implementation is FINALIZED.
  224. /// - When there is no current implementation installed.
  225. ///
  226. /// It is logging implementation defined what happens when this function is
  227. /// called while in any other states.
  228. void __xray_remove_log_impl();
  229. /// Invokes the installed implementation initialization routine. See
  230. /// XRayLogInitStatus for what the return values mean.
  231. XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers,
  232. void *Args, size_t ArgsSize);
  233. /// Invokes the installed implementation finalization routine. See
  234. /// XRayLogInitStatus for what the return values mean.
  235. XRayLogInitStatus __xray_log_finalize();
  236. /// Invokes the install implementation log flushing routine. See
  237. /// XRayLogFlushStatus for what the return values mean.
  238. XRayLogFlushStatus __xray_log_flushLog();
  239. } // extern "C"
  240. namespace __xray {
  241. /// Options used by the LLVM XRay FDR logging implementation.
  242. struct FDRLoggingOptions {
  243. bool ReportErrors = false;
  244. int Fd = -1;
  245. };
  246. /// Options used by the LLVM XRay Basic (Naive) logging implementation.
  247. struct BasicLoggingOptions {
  248. int DurationFilterMicros = 0;
  249. size_t MaxStackDepth = 0;
  250. size_t ThreadBufferSize = 0;
  251. };
  252. } // namespace __xray
  253. #endif // XRAY_XRAY_LOG_INTERFACE_H