1*0b57cec5SDimitry Andric //===-- xray_log_interface.h ----------------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file is a part of XRay, a function call tracing system. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric // APIs for installing a new logging implementation. 12*0b57cec5SDimitry Andric // 13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14*0b57cec5SDimitry Andric /// 15*0b57cec5SDimitry Andric /// XRay allows users to implement their own logging handlers and install them 16*0b57cec5SDimitry Andric /// to replace the default runtime-controllable implementation that comes with 17*0b57cec5SDimitry Andric /// compiler-rt/xray. The "flight data recorder" (FDR) mode implementation uses 18*0b57cec5SDimitry Andric /// this API to install itself in an XRay-enabled binary. See 19*0b57cec5SDimitry Andric /// compiler-rt/lib/xray_fdr_logging.{h,cc} for details of that implementation. 20*0b57cec5SDimitry Andric /// 21*0b57cec5SDimitry Andric /// The high-level usage pattern for these APIs look like the following: 22*0b57cec5SDimitry Andric /// 23*0b57cec5SDimitry Andric /// // We choose the mode which we'd like to install, and check whether this 24*0b57cec5SDimitry Andric /// // has succeeded. Each mode will have their own set of flags they will 25*0b57cec5SDimitry Andric /// // support, outside of the global XRay configuration options that are 26*0b57cec5SDimitry Andric /// // defined in the XRAY_OPTIONS environment variable. 27*0b57cec5SDimitry Andric /// auto select_status = __xray_log_select_mode("xray-fdr"); 28*0b57cec5SDimitry Andric /// if (select_status != XRayLogRegisterStatus::XRAY_REGISTRATION_OK) { 29*0b57cec5SDimitry Andric /// // This failed, we should not proceed with attempting to initialise 30*0b57cec5SDimitry Andric /// // the currently selected mode. 31*0b57cec5SDimitry Andric /// return; 32*0b57cec5SDimitry Andric /// } 33*0b57cec5SDimitry Andric /// 34*0b57cec5SDimitry Andric /// // Once that's done, we can now attempt to configure the implementation. 35*0b57cec5SDimitry Andric /// // To do this, we provide the string flags configuration for the mode. 36*0b57cec5SDimitry Andric /// auto config_status = __xray_log_init_mode( 37*0b57cec5SDimitry Andric /// "xray-fdr", "verbosity=1 some_flag=1 another_flag=2"); 38*0b57cec5SDimitry Andric /// if (config_status != XRayLogInitStatus::XRAY_LOG_INITIALIZED) { 39*0b57cec5SDimitry Andric /// // deal with the error here, if there is one. 40*0b57cec5SDimitry Andric /// } 41*0b57cec5SDimitry Andric /// 42*0b57cec5SDimitry Andric /// // When the log implementation has had the chance to initialize, we can 43*0b57cec5SDimitry Andric /// // now patch the instrumentation points. Note that we could have patched 44*0b57cec5SDimitry Andric /// // the instrumentation points first, but there's no strict ordering to 45*0b57cec5SDimitry Andric /// // these operations. 46*0b57cec5SDimitry Andric /// auto patch_status = __xray_patch(); 47*0b57cec5SDimitry Andric /// if (patch_status != XRayPatchingStatus::SUCCESS) { 48*0b57cec5SDimitry Andric /// // deal with the error here, if it is an error. 49*0b57cec5SDimitry Andric /// } 50*0b57cec5SDimitry Andric /// 51*0b57cec5SDimitry Andric /// // If we want to stop the implementation, we can then finalize it (before 52*0b57cec5SDimitry Andric /// // optionally flushing the log). 53*0b57cec5SDimitry Andric /// auto fin_status = __xray_log_finalize(); 54*0b57cec5SDimitry Andric /// if (fin_status != XRayLogInitStatus::XRAY_LOG_FINALIZED) { 55*0b57cec5SDimitry Andric /// // deal with the error here, if it is an error. 56*0b57cec5SDimitry Andric /// } 57*0b57cec5SDimitry Andric /// 58*0b57cec5SDimitry Andric /// // We can optionally wait before flushing the log to give other threads a 59*0b57cec5SDimitry Andric /// // chance to see that the implementation is already finalized. Also, at 60*0b57cec5SDimitry Andric /// // this point we can optionally unpatch the instrumentation points to 61*0b57cec5SDimitry Andric /// // reduce overheads at runtime. 62*0b57cec5SDimitry Andric /// auto unpatch_status = __xray_unpatch(); 63*0b57cec5SDimitry Andric /// if (unpatch_status != XRayPatchingStatus::SUCCESS) { 64*0b57cec5SDimitry Andric /// // deal with the error here, if it is an error. 65*0b57cec5SDimitry Andric /// } 66*0b57cec5SDimitry Andric /// 67*0b57cec5SDimitry Andric /// // If there are logs or data to be flushed somewhere, we can do so only 68*0b57cec5SDimitry Andric /// // after we've finalized the log. Some implementations may not actually 69*0b57cec5SDimitry Andric /// // have anything to log (it might keep the data in memory, or periodically 70*0b57cec5SDimitry Andric /// // be logging the data anyway). 71*0b57cec5SDimitry Andric /// auto flush_status = __xray_log_flushLog(); 72*0b57cec5SDimitry Andric /// if (flush_status != XRayLogFlushStatus::XRAY_LOG_FLUSHED) { 73*0b57cec5SDimitry Andric /// // deal with the error here, if it is an error. 74*0b57cec5SDimitry Andric /// } 75*0b57cec5SDimitry Andric /// 76*0b57cec5SDimitry Andric /// // Alternatively, we can go through the buffers ourselves without 77*0b57cec5SDimitry Andric /// // relying on the implementations' flushing semantics (if the 78*0b57cec5SDimitry Andric /// // implementation supports exporting this data directly). 79*0b57cec5SDimitry Andric /// auto MyBufferProcessor = +[](const char* mode, XRayBuffer buffer) { 80*0b57cec5SDimitry Andric /// // Check the "mode" to see if it's something we know how to handle... 81*0b57cec5SDimitry Andric /// // and/or do something with an XRayBuffer instance. 82*0b57cec5SDimitry Andric /// }; 83*0b57cec5SDimitry Andric /// auto process_status = __xray_log_process_buffers(MyBufferProcessor); 84*0b57cec5SDimitry Andric /// if (process_status != XRayLogFlushStatus::XRAY_LOG_FLUSHED) { 85*0b57cec5SDimitry Andric /// // deal with the error here, if it is an error. 86*0b57cec5SDimitry Andric /// } 87*0b57cec5SDimitry Andric /// 88*0b57cec5SDimitry Andric /// NOTE: Before calling __xray_patch() again, consider re-initializing the 89*0b57cec5SDimitry Andric /// implementation first. Some implementations might stay in an "off" state when 90*0b57cec5SDimitry Andric /// they are finalized, while some might be in an invalid/unknown state. 91*0b57cec5SDimitry Andric /// 92*0b57cec5SDimitry Andric #ifndef XRAY_XRAY_LOG_INTERFACE_H 93*0b57cec5SDimitry Andric #define XRAY_XRAY_LOG_INTERFACE_H 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric #include "xray/xray_interface.h" 96*0b57cec5SDimitry Andric #include <stddef.h> 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric extern "C" { 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric /// This enum defines the valid states in which the logging implementation can 101*0b57cec5SDimitry Andric /// be at. 102*0b57cec5SDimitry Andric enum XRayLogInitStatus { 103*0b57cec5SDimitry Andric /// The default state is uninitialized, and in case there were errors in the 104*0b57cec5SDimitry Andric /// initialization, the implementation MUST return XRAY_LOG_UNINITIALIZED. 105*0b57cec5SDimitry Andric XRAY_LOG_UNINITIALIZED = 0, 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric /// Some implementations support multi-stage init (or asynchronous init), and 108*0b57cec5SDimitry Andric /// may return XRAY_LOG_INITIALIZING to signal callers of the API that 109*0b57cec5SDimitry Andric /// there's an ongoing initialization routine running. This allows 110*0b57cec5SDimitry Andric /// implementations to support concurrent threads attempting to initialize, 111*0b57cec5SDimitry Andric /// while only signalling success in one. 112*0b57cec5SDimitry Andric XRAY_LOG_INITIALIZING = 1, 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric /// When an implementation is done initializing, it MUST return 115*0b57cec5SDimitry Andric /// XRAY_LOG_INITIALIZED. When users call `__xray_patch()`, they are 116*0b57cec5SDimitry Andric /// guaranteed that the implementation installed with 117*0b57cec5SDimitry Andric /// `__xray_set_log_impl(...)` has been initialized. 118*0b57cec5SDimitry Andric XRAY_LOG_INITIALIZED = 2, 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric /// Some implementations might support multi-stage finalization (or 121*0b57cec5SDimitry Andric /// asynchronous finalization), and may return XRAY_LOG_FINALIZING to signal 122*0b57cec5SDimitry Andric /// callers of the API that there's an ongoing finalization routine running. 123*0b57cec5SDimitry Andric /// This allows implementations to support concurrent threads attempting to 124*0b57cec5SDimitry Andric /// finalize, while only signalling success/completion in one. 125*0b57cec5SDimitry Andric XRAY_LOG_FINALIZING = 3, 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric /// When an implementation is done finalizing, it MUST return 128*0b57cec5SDimitry Andric /// XRAY_LOG_FINALIZED. It is up to the implementation to determine what the 129*0b57cec5SDimitry Andric /// semantics of a finalized implementation is. Some implementations might 130*0b57cec5SDimitry Andric /// allow re-initialization once the log is finalized, while some might always 131*0b57cec5SDimitry Andric /// be on (and that finalization is a no-op). 132*0b57cec5SDimitry Andric XRAY_LOG_FINALIZED = 4, 133*0b57cec5SDimitry Andric }; 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric /// This enum allows an implementation to signal log flushing operations via 136*0b57cec5SDimitry Andric /// `__xray_log_flushLog()`, and the state of flushing the log. 137*0b57cec5SDimitry Andric enum XRayLogFlushStatus { 138*0b57cec5SDimitry Andric XRAY_LOG_NOT_FLUSHING = 0, 139*0b57cec5SDimitry Andric XRAY_LOG_FLUSHING = 1, 140*0b57cec5SDimitry Andric XRAY_LOG_FLUSHED = 2, 141*0b57cec5SDimitry Andric }; 142*0b57cec5SDimitry Andric 143*0b57cec5SDimitry Andric /// This enum indicates the installation state of a logging implementation, when 144*0b57cec5SDimitry Andric /// associating a mode to a particular logging implementation through 145*0b57cec5SDimitry Andric /// `__xray_log_register_impl(...)` or through `__xray_log_select_mode(...`. 146*0b57cec5SDimitry Andric enum XRayLogRegisterStatus { 147*0b57cec5SDimitry Andric XRAY_REGISTRATION_OK = 0, 148*0b57cec5SDimitry Andric XRAY_DUPLICATE_MODE = 1, 149*0b57cec5SDimitry Andric XRAY_MODE_NOT_FOUND = 2, 150*0b57cec5SDimitry Andric XRAY_INCOMPLETE_IMPL = 3, 151*0b57cec5SDimitry Andric }; 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric /// A valid XRay logging implementation MUST provide all of the function 154*0b57cec5SDimitry Andric /// pointers in XRayLogImpl when being installed through `__xray_set_log_impl`. 155*0b57cec5SDimitry Andric /// To be precise, ALL the functions pointers MUST NOT be nullptr. 156*0b57cec5SDimitry Andric struct XRayLogImpl { 157*0b57cec5SDimitry Andric /// The log initialization routine provided by the implementation, always 158*0b57cec5SDimitry Andric /// provided with the following parameters: 159*0b57cec5SDimitry Andric /// 160*0b57cec5SDimitry Andric /// - buffer size (unused) 161*0b57cec5SDimitry Andric /// - maximum number of buffers (unused) 162*0b57cec5SDimitry Andric /// - a pointer to an argument struct that the implementation MUST handle 163*0b57cec5SDimitry Andric /// - the size of the argument struct 164*0b57cec5SDimitry Andric /// 165*0b57cec5SDimitry Andric /// See XRayLogInitStatus for details on what the implementation MUST return 166*0b57cec5SDimitry Andric /// when called. 167*0b57cec5SDimitry Andric /// 168*0b57cec5SDimitry Andric /// If the implementation needs to install handlers aside from the 0-argument 169*0b57cec5SDimitry Andric /// function call handler, it MUST do so in this initialization handler. 170*0b57cec5SDimitry Andric /// 171*0b57cec5SDimitry Andric /// See xray_interface.h for available handler installation routines. 172*0b57cec5SDimitry Andric XRayLogInitStatus (*log_init)(size_t, size_t, void *, size_t); 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric /// The log finalization routine provided by the implementation. 175*0b57cec5SDimitry Andric /// 176*0b57cec5SDimitry Andric /// See XRayLogInitStatus for details on what the implementation MUST return 177*0b57cec5SDimitry Andric /// when called. 178*0b57cec5SDimitry Andric XRayLogInitStatus (*log_finalize)(); 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric /// The 0-argument function call handler. XRay logging implementations MUST 181*0b57cec5SDimitry Andric /// always have a handler for function entry and exit events. In case the 182*0b57cec5SDimitry Andric /// implementation wants to support arg1 (or other future extensions to XRay 183*0b57cec5SDimitry Andric /// logging) those MUST be installed by the installed 'log_init' handler. 184*0b57cec5SDimitry Andric /// 185*0b57cec5SDimitry Andric /// Because we didn't want to change the ABI of this struct, the arg1 handler 186*0b57cec5SDimitry Andric /// may be silently overwritten during initialization as well. 187*0b57cec5SDimitry Andric void (*handle_arg0)(int32_t, XRayEntryType); 188*0b57cec5SDimitry Andric 189*0b57cec5SDimitry Andric /// The log implementation provided routine for when __xray_log_flushLog() is 190*0b57cec5SDimitry Andric /// called. 191*0b57cec5SDimitry Andric /// 192*0b57cec5SDimitry Andric /// See XRayLogFlushStatus for details on what the implementation MUST return 193*0b57cec5SDimitry Andric /// when called. 194*0b57cec5SDimitry Andric XRayLogFlushStatus (*flush_log)(); 195*0b57cec5SDimitry Andric }; 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric /// DEPRECATED: Use the mode registration workflow instead with 198*0b57cec5SDimitry Andric /// __xray_log_register_mode(...) and __xray_log_select_mode(...). See the 199*0b57cec5SDimitry Andric /// documentation for those function. 200*0b57cec5SDimitry Andric /// 201*0b57cec5SDimitry Andric /// This function installs a new logging implementation that XRay will use. In 202*0b57cec5SDimitry Andric /// case there are any nullptr members in Impl, XRay will *uninstall any 203*0b57cec5SDimitry Andric /// existing implementations*. It does NOT patch the instrumentation points. 204*0b57cec5SDimitry Andric /// 205*0b57cec5SDimitry Andric /// NOTE: This function does NOT attempt to finalize the currently installed 206*0b57cec5SDimitry Andric /// implementation. Use with caution. 207*0b57cec5SDimitry Andric /// 208*0b57cec5SDimitry Andric /// It is guaranteed safe to call this function in the following states: 209*0b57cec5SDimitry Andric /// 210*0b57cec5SDimitry Andric /// - When the implementation is UNINITIALIZED. 211*0b57cec5SDimitry Andric /// - When the implementation is FINALIZED. 212*0b57cec5SDimitry Andric /// - When there is no current implementation installed. 213*0b57cec5SDimitry Andric /// 214*0b57cec5SDimitry Andric /// It is logging implementation defined what happens when this function is 215*0b57cec5SDimitry Andric /// called while in any other states. 216*0b57cec5SDimitry Andric void __xray_set_log_impl(XRayLogImpl Impl); 217*0b57cec5SDimitry Andric 218*0b57cec5SDimitry Andric /// This function registers a logging implementation against a "mode" 219*0b57cec5SDimitry Andric /// identifier. This allows multiple modes to be registered, and chosen at 220*0b57cec5SDimitry Andric /// runtime using the same mode identifier through 221*0b57cec5SDimitry Andric /// `__xray_log_select_mode(...)`. 222*0b57cec5SDimitry Andric /// 223*0b57cec5SDimitry Andric /// We treat the Mode identifier as a null-terminated byte string, as the 224*0b57cec5SDimitry Andric /// identifier used when retrieving the log impl. 225*0b57cec5SDimitry Andric /// 226*0b57cec5SDimitry Andric /// Returns: 227*0b57cec5SDimitry Andric /// - XRAY_REGISTRATION_OK on success. 228*0b57cec5SDimitry Andric /// - XRAY_DUPLICATE_MODE when an implementation is already associated with 229*0b57cec5SDimitry Andric /// the provided Mode; does not update the already-registered 230*0b57cec5SDimitry Andric /// implementation. 231*0b57cec5SDimitry Andric XRayLogRegisterStatus __xray_log_register_mode(const char *Mode, 232*0b57cec5SDimitry Andric XRayLogImpl Impl); 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric /// This function selects the implementation associated with Mode that has been 235*0b57cec5SDimitry Andric /// registered through __xray_log_register_mode(...) and installs that 236*0b57cec5SDimitry Andric /// implementation (as if through calling __xray_set_log_impl(...)). The same 237*0b57cec5SDimitry Andric /// caveats apply to __xray_log_select_mode(...) as with 238*0b57cec5SDimitry Andric /// __xray_log_set_log_impl(...). 239*0b57cec5SDimitry Andric /// 240*0b57cec5SDimitry Andric /// Returns: 241*0b57cec5SDimitry Andric /// - XRAY_REGISTRATION_OK on success. 242*0b57cec5SDimitry Andric /// - XRAY_MODE_NOT_FOUND if there is no implementation associated with Mode; 243*0b57cec5SDimitry Andric /// does not update the currently installed implementation. 244*0b57cec5SDimitry Andric XRayLogRegisterStatus __xray_log_select_mode(const char *Mode); 245*0b57cec5SDimitry Andric 246*0b57cec5SDimitry Andric /// Returns an identifier for the currently selected XRay mode chosen through 247*0b57cec5SDimitry Andric /// the __xray_log_select_mode(...) function call. Returns nullptr if there is 248*0b57cec5SDimitry Andric /// no currently installed mode. 249*0b57cec5SDimitry Andric const char *__xray_log_get_current_mode(); 250*0b57cec5SDimitry Andric 251*0b57cec5SDimitry Andric /// This function removes the currently installed implementation. It will also 252*0b57cec5SDimitry Andric /// uninstall any handlers that have been previously installed. It does NOT 253*0b57cec5SDimitry Andric /// unpatch the instrumentation points. 254*0b57cec5SDimitry Andric /// 255*0b57cec5SDimitry Andric /// NOTE: This function does NOT attempt to finalize the currently installed 256*0b57cec5SDimitry Andric /// implementation. Use with caution. 257*0b57cec5SDimitry Andric /// 258*0b57cec5SDimitry Andric /// It is guaranteed safe to call this function in the following states: 259*0b57cec5SDimitry Andric /// 260*0b57cec5SDimitry Andric /// - When the implementation is UNINITIALIZED. 261*0b57cec5SDimitry Andric /// - When the implementation is FINALIZED. 262*0b57cec5SDimitry Andric /// - When there is no current implementation installed. 263*0b57cec5SDimitry Andric /// 264*0b57cec5SDimitry Andric /// It is logging implementation defined what happens when this function is 265*0b57cec5SDimitry Andric /// called while in any other states. 266*0b57cec5SDimitry Andric void __xray_remove_log_impl(); 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andric /// DEPRECATED: Use __xray_log_init_mode() instead, and provide all the options 269*0b57cec5SDimitry Andric /// in string form. 270*0b57cec5SDimitry Andric /// Invokes the installed implementation initialization routine. See 271*0b57cec5SDimitry Andric /// XRayLogInitStatus for what the return values mean. 272*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers, 273*0b57cec5SDimitry Andric void *Args, size_t ArgsSize); 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric /// Invokes the installed initialization routine, which *must* support the 276*0b57cec5SDimitry Andric /// string based form. 277*0b57cec5SDimitry Andric /// 278*0b57cec5SDimitry Andric /// NOTE: When this API is used, we still invoke the installed initialization 279*0b57cec5SDimitry Andric /// routine, but we will call it with the following convention to signal that we 280*0b57cec5SDimitry Andric /// are using the string form: 281*0b57cec5SDimitry Andric /// 282*0b57cec5SDimitry Andric /// - BufferSize = 0 283*0b57cec5SDimitry Andric /// - MaxBuffers = 0 284*0b57cec5SDimitry Andric /// - ArgsSize = 0 285*0b57cec5SDimitry Andric /// - Args will be the pointer to the character buffer representing the 286*0b57cec5SDimitry Andric /// configuration. 287*0b57cec5SDimitry Andric /// 288*0b57cec5SDimitry Andric /// FIXME: Updating the XRayLogImpl struct is an ABI breaking change. When we 289*0b57cec5SDimitry Andric /// are ready to make a breaking change, we should clean this up appropriately. 290*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_init_mode(const char *Mode, const char *Config); 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric /// Like __xray_log_init_mode(...) this version allows for providing 293*0b57cec5SDimitry Andric /// configurations that might have non-null-terminated strings. This will 294*0b57cec5SDimitry Andric /// operate similarly to __xray_log_init_mode, with the exception that 295*0b57cec5SDimitry Andric /// |ArgsSize| will be what |ConfigSize| is. 296*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_init_mode_bin(const char *Mode, const char *Config, 297*0b57cec5SDimitry Andric size_t ConfigSize); 298*0b57cec5SDimitry Andric 299*0b57cec5SDimitry Andric /// Invokes the installed implementation finalization routine. See 300*0b57cec5SDimitry Andric /// XRayLogInitStatus for what the return values mean. 301*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_finalize(); 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric /// Invokes the install implementation log flushing routine. See 304*0b57cec5SDimitry Andric /// XRayLogFlushStatus for what the return values mean. 305*0b57cec5SDimitry Andric XRayLogFlushStatus __xray_log_flushLog(); 306*0b57cec5SDimitry Andric 307*0b57cec5SDimitry Andric /// An XRayBuffer represents a section of memory which can be treated by log 308*0b57cec5SDimitry Andric /// processing functions as bytes stored in the logging implementation's 309*0b57cec5SDimitry Andric /// buffers. 310*0b57cec5SDimitry Andric struct XRayBuffer { 311*0b57cec5SDimitry Andric const void *Data; 312*0b57cec5SDimitry Andric size_t Size; 313*0b57cec5SDimitry Andric }; 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric /// Registers an iterator function which takes an XRayBuffer argument, then 316*0b57cec5SDimitry Andric /// returns another XRayBuffer function representing the next buffer. When the 317*0b57cec5SDimitry Andric /// Iterator function returns an empty XRayBuffer (Data = nullptr, Size = 0), 318*0b57cec5SDimitry Andric /// this signifies the end of the buffers. 319*0b57cec5SDimitry Andric /// 320*0b57cec5SDimitry Andric /// The first invocation of this Iterator function will always take an empty 321*0b57cec5SDimitry Andric /// XRayBuffer (Data = nullptr, Size = 0). 322*0b57cec5SDimitry Andric void __xray_log_set_buffer_iterator(XRayBuffer (*Iterator)(XRayBuffer)); 323*0b57cec5SDimitry Andric 324*0b57cec5SDimitry Andric /// Removes the currently registered buffer iterator function. 325*0b57cec5SDimitry Andric void __xray_log_remove_buffer_iterator(); 326*0b57cec5SDimitry Andric 327*0b57cec5SDimitry Andric /// Invokes the provided handler to process data maintained by the logging 328*0b57cec5SDimitry Andric /// handler. This API will be provided raw access to the data available in 329*0b57cec5SDimitry Andric /// memory from the logging implementation. The callback function must: 330*0b57cec5SDimitry Andric /// 331*0b57cec5SDimitry Andric /// 1) Not modify the data, to avoid running into undefined behaviour. 332*0b57cec5SDimitry Andric /// 333*0b57cec5SDimitry Andric /// 2) Either know the data layout, or treat the data as raw bytes for later 334*0b57cec5SDimitry Andric /// interpretation. 335*0b57cec5SDimitry Andric /// 336*0b57cec5SDimitry Andric /// This API is best used in place of the `__xray_log_flushLog()` implementation 337*0b57cec5SDimitry Andric /// above to enable the caller to provide an alternative means of extracting the 338*0b57cec5SDimitry Andric /// data from the XRay implementation. 339*0b57cec5SDimitry Andric /// 340*0b57cec5SDimitry Andric /// Implementations MUST then provide: 341*0b57cec5SDimitry Andric /// 342*0b57cec5SDimitry Andric /// 1) A function that will return an XRayBuffer. Functions that return an 343*0b57cec5SDimitry Andric /// "empty" XRayBuffer signifies that there are no more buffers to be 344*0b57cec5SDimitry Andric /// processed. This function should be registered through the 345*0b57cec5SDimitry Andric /// `__xray_log_set_buffer_iterator(...)` function. 346*0b57cec5SDimitry Andric /// 347*0b57cec5SDimitry Andric /// 2) Its own means of converting data it holds in memory into an XRayBuffer 348*0b57cec5SDimitry Andric /// structure. 349*0b57cec5SDimitry Andric /// 350*0b57cec5SDimitry Andric /// See XRayLogFlushStatus for what the return values mean. 351*0b57cec5SDimitry Andric /// 352*0b57cec5SDimitry Andric XRayLogFlushStatus __xray_log_process_buffers(void (*Processor)(const char *, 353*0b57cec5SDimitry Andric XRayBuffer)); 354*0b57cec5SDimitry Andric 355*0b57cec5SDimitry Andric } // extern "C" 356*0b57cec5SDimitry Andric 357*0b57cec5SDimitry Andric #endif // XRAY_XRAY_LOG_INTERFACE_H 358