Home | History | Annotate | Download | only in xray
      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 
     83 #include "xray/xray_interface.h"
     84 #include <stddef.h>
     85 
     86 extern "C" {
     87 
     88 /// This enum defines the valid states in which the logging implementation can
     89 /// be at.
     90 enum XRayLogInitStatus {
     91   /// The default state is uninitialized, and in case there were errors in the
     92   /// initialization, the implementation MUST return XRAY_LOG_UNINITIALIZED.
     93   XRAY_LOG_UNINITIALIZED = 0,
     94 
     95   /// Some implementations support multi-stage init (or asynchronous init), and
     96   /// may return XRAY_LOG_INITIALIZING to signal callers of the API that
     97   /// there's an ongoing initialization routine running. This allows
     98   /// implementations to support concurrent threads attempting to initialize,
     99   /// while only signalling success in one.
    100   XRAY_LOG_INITIALIZING = 1,
    101 
    102   /// When an implementation is done initializing, it MUST return
    103   /// XRAY_LOG_INITIALIZED. When users call `__xray_patch()`, they are
    104   /// guaranteed that the implementation installed with
    105   /// `__xray_set_log_impl(...)` has been initialized.
    106   XRAY_LOG_INITIALIZED = 2,
    107 
    108   /// Some implementations might support multi-stage finalization (or
    109   /// asynchronous finalization), and may return XRAY_LOG_FINALIZING to signal
    110   /// callers of the API that there's an ongoing finalization routine running.
    111   /// This allows implementations to support concurrent threads attempting to
    112   /// finalize, while only signalling success/completion in one.
    113   XRAY_LOG_FINALIZING = 3,
    114 
    115   /// When an implementation is done finalizing, it MUST return
    116   /// XRAY_LOG_FINALIZED. It is up to the implementation to determine what the
    117   /// semantics of a finalized implementation is. Some implementations might
    118   /// allow re-initialization once the log is finalized, while some might always
    119   /// be on (and that finalization is a no-op).
    120   XRAY_LOG_FINALIZED = 4,
    121 };
    122 
    123 /// This enum allows an implementation to signal log flushing operations via
    124 /// `__xray_log_flushLog()`, and the state of flushing the log.
    125 enum XRayLogFlushStatus {
    126   XRAY_LOG_NOT_FLUSHING = 0,
    127   XRAY_LOG_FLUSHING = 1,
    128   XRAY_LOG_FLUSHED = 2,
    129 };
    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 
    152   /// The log finalization routine provided by the implementation.
    153   ///
    154   /// See XRayLogInitStatus for details on what the implementation MUST return
    155   /// when called.
    156   XRayLogInitStatus (*log_finalize)();
    157 
    158   /// The 0-argument function call handler. XRay logging implementations MUST
    159   /// always have a handler for function entry and exit events. In case the
    160   /// implementation wants to support arg1 (or other future extensions to XRay
    161   /// logging) those MUST be installed by the installed 'log_init' handler.
    162   ///
    163   /// Because we didn't want to change the ABI of this struct, the arg1 handler
    164   /// may be silently overwritten during initialization as well.
    165   void (*handle_arg0)(int32_t, XRayEntryType);
    166 
    167   /// The log implementation provided routine for when __xray_log_flushLog() is
    168   /// called.
    169   ///
    170   /// See XRayLogFlushStatus for details on what the implementation MUST return
    171   /// when called.
    172   XRayLogFlushStatus (*flush_log)();
    173 };
    174 
    175 /// This function installs a new logging implementation that XRay will use. In
    176 /// case there are any nullptr members in Impl, XRay will *uninstall any
    177 /// existing implementations*. It does NOT patch the instrumentation sleds.
    178 ///
    179 /// NOTE: This function does NOT attempt to finalize the currently installed
    180 /// implementation. Use with caution.
    181 ///
    182 /// It is guaranteed safe to call this function in the following states:
    183 ///
    184 ///   - When the implementation is UNINITIALIZED.
    185 ///   - When the implementation is FINALIZED.
    186 ///   - When there is no current implementation installed.
    187 ///
    188 /// It is logging implementation defined what happens when this function is
    189 /// called while in any other states.
    190 void __xray_set_log_impl(XRayLogImpl Impl);
    191 
    192 /// This function removes the currently installed implementation. It will also
    193 /// uninstall any handlers that have been previously installed. It does NOT
    194 /// unpatch the instrumentation sleds.
    195 ///
    196 /// NOTE: This function does NOT attempt to finalize the currently installed
    197 /// implementation. Use with caution.
    198 ///
    199 /// It is guaranteed safe to call this function in the following states:
    200 ///
    201 ///   - When the implementation is UNINITIALIZED.
    202 ///   - When the implementation is FINALIZED.
    203 ///   - When there is no current implementation installed.
    204 ///
    205 /// It is logging implementation defined what happens when this function is
    206 /// called while in any other states.
    207 void __xray_remove_log_impl();
    208 
    209 /// Invokes the installed implementation initialization routine. See
    210 /// XRayLogInitStatus for what the return values mean.
    211 XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers,
    212                                   void *Args, size_t ArgsSize);
    213 
    214 /// Invokes the installed implementation finalization routine. See
    215 /// XRayLogInitStatus for what the return values mean.
    216 XRayLogInitStatus __xray_log_finalize();
    217 
    218 /// Invokes the install implementation log flushing routine. See
    219 /// XRayLogFlushStatus for what the return values mean.
    220 XRayLogFlushStatus __xray_log_flushLog();
    221 
    222 } // extern "C"
    223 
    224 namespace __xray {
    225 
    226 // Options used by the LLVM XRay FDR implementation.
    227 struct FDRLoggingOptions {
    228   bool ReportErrors = false;
    229   int Fd = -1;
    230 };
    231 
    232 } // namespace __xray
    233 
    234 #endif // XRAY_XRAY_LOG_INTERFACE_H
    235