Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/include/xray/xray_log_interface.h
35262 views
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.
10
//
11
// APIs for installing a new logging implementation.
12
//
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
94
95
#include "xray/xray_interface.h"
96
#include <stddef.h>
97
98
extern "C" {
99
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,
106
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,
113
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,
119
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,
126
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,
133
};
134
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,
141
};
142
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,
151
};
152
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:
159
///
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
164
///
165
/// See XRayLogInitStatus for details on what the implementation MUST return
166
/// when called.
167
///
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.
170
///
171
/// See xray_interface.h for available handler installation routines.
172
XRayLogInitStatus (*log_init)(size_t, size_t, void *, size_t);
173
174
/// The log finalization routine provided by the implementation.
175
///
176
/// See XRayLogInitStatus for details on what the implementation MUST return
177
/// when called.
178
XRayLogInitStatus (*log_finalize)();
179
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.
184
///
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);
188
189
/// The log implementation provided routine for when __xray_log_flushLog() is
190
/// called.
191
///
192
/// See XRayLogFlushStatus for details on what the implementation MUST return
193
/// when called.
194
XRayLogFlushStatus (*flush_log)();
195
};
196
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.
200
///
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.
204
///
205
/// NOTE: This function does NOT attempt to finalize the currently installed
206
/// implementation. Use with caution.
207
///
208
/// It is guaranteed safe to call this function in the following states:
209
///
210
/// - When the implementation is UNINITIALIZED.
211
/// - When the implementation is FINALIZED.
212
/// - When there is no current implementation installed.
213
///
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);
217
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(...)`.
222
///
223
/// We treat the Mode identifier as a null-terminated byte string, as the
224
/// identifier used when retrieving the log impl.
225
///
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);
233
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(...).
239
///
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);
245
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();
250
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.
254
///
255
/// NOTE: This function does NOT attempt to finalize the currently installed
256
/// implementation. Use with caution.
257
///
258
/// It is guaranteed safe to call this function in the following states:
259
///
260
/// - When the implementation is UNINITIALIZED.
261
/// - When the implementation is FINALIZED.
262
/// - When there is no current implementation installed.
263
///
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();
267
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);
274
275
/// Invokes the installed initialization routine, which *must* support the
276
/// string based form.
277
///
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:
281
///
282
/// - BufferSize = 0
283
/// - MaxBuffers = 0
284
/// - ArgsSize = 0
285
/// - Args will be the pointer to the character buffer representing the
286
/// configuration.
287
///
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);
291
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);
298
299
/// Invokes the installed implementation finalization routine. See
300
/// XRayLogInitStatus for what the return values mean.
301
XRayLogInitStatus __xray_log_finalize();
302
303
/// Invokes the install implementation log flushing routine. See
304
/// XRayLogFlushStatus for what the return values mean.
305
XRayLogFlushStatus __xray_log_flushLog();
306
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;
313
};
314
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.
319
///
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));
323
324
/// Removes the currently registered buffer iterator function.
325
void __xray_log_remove_buffer_iterator();
326
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:
330
///
331
/// 1) Not modify the data, to avoid running into undefined behaviour.
332
///
333
/// 2) Either know the data layout, or treat the data as raw bytes for later
334
/// interpretation.
335
///
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.
339
///
340
/// Implementations MUST then provide:
341
///
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.
346
///
347
/// 2) Its own means of converting data it holds in memory into an XRayBuffer
348
/// structure.
349
///
350
/// See XRayLogFlushStatus for what the return values mean.
351
///
352
XRayLogFlushStatus __xray_log_process_buffers(void (*Processor)(const char *,
353
XRayBuffer));
354
355
} // extern "C"
356
357
#endif // XRAY_XRAY_LOG_INTERFACE_H
358
359