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