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