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