Path: blob/main/contrib/llvm-project/compiler-rt/include/xray/xray_log_interface.h
35262 views
//===-- xray_log_interface.h ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of XRay, a function call tracing system.9//10// APIs for installing a new logging implementation.11//12//===----------------------------------------------------------------------===//13///14/// XRay allows users to implement their own logging handlers and install them15/// to replace the default runtime-controllable implementation that comes with16/// compiler-rt/xray. The "flight data recorder" (FDR) mode implementation uses17/// this API to install itself in an XRay-enabled binary. See18/// compiler-rt/lib/xray_fdr_logging.{h,cc} for details of that implementation.19///20/// The high-level usage pattern for these APIs look like the following:21///22/// // We choose the mode which we'd like to install, and check whether this23/// // has succeeded. Each mode will have their own set of flags they will24/// // support, outside of the global XRay configuration options that are25/// // defined in the XRAY_OPTIONS environment variable.26/// auto select_status = __xray_log_select_mode("xray-fdr");27/// if (select_status != XRayLogRegisterStatus::XRAY_REGISTRATION_OK) {28/// // This failed, we should not proceed with attempting to initialise29/// // the currently selected mode.30/// return;31/// }32///33/// // Once that's done, we can now attempt to configure the implementation.34/// // To do this, we provide the string flags configuration for the mode.35/// auto config_status = __xray_log_init_mode(36/// "xray-fdr", "verbosity=1 some_flag=1 another_flag=2");37/// if (config_status != XRayLogInitStatus::XRAY_LOG_INITIALIZED) {38/// // deal with the error here, if there is one.39/// }40///41/// // When the log implementation has had the chance to initialize, we can42/// // now patch the instrumentation points. Note that we could have patched43/// // the instrumentation points first, but there's no strict ordering to44/// // these operations.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 (before51/// // 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 a58/// // chance to see that the implementation is already finalized. Also, at59/// // this point we can optionally unpatch the instrumentation points to60/// // reduce overheads at 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 only67/// // after we've finalized the log. Some implementations may not actually68/// // have anything to log (it might keep the data in memory, or periodically69/// // 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/// // Alternatively, we can go through the buffers ourselves without76/// // relying on the implementations' flushing semantics (if the77/// // implementation supports exporting this data directly).78/// auto MyBufferProcessor = +[](const char* mode, XRayBuffer buffer) {79/// // Check the "mode" to see if it's something we know how to handle...80/// // and/or do something with an XRayBuffer instance.81/// };82/// auto process_status = __xray_log_process_buffers(MyBufferProcessor);83/// if (process_status != XRayLogFlushStatus::XRAY_LOG_FLUSHED) {84/// // deal with the error here, if it is an error.85/// }86///87/// NOTE: Before calling __xray_patch() again, consider re-initializing the88/// implementation first. Some implementations might stay in an "off" state when89/// they are finalized, while some might be in an invalid/unknown state.90///91#ifndef XRAY_XRAY_LOG_INTERFACE_H92#define XRAY_XRAY_LOG_INTERFACE_H9394#include "xray/xray_interface.h"95#include <stddef.h>9697extern "C" {9899/// This enum defines the valid states in which the logging implementation can100/// be at.101enum XRayLogInitStatus {102/// The default state is uninitialized, and in case there were errors in the103/// initialization, the implementation MUST return XRAY_LOG_UNINITIALIZED.104XRAY_LOG_UNINITIALIZED = 0,105106/// Some implementations support multi-stage init (or asynchronous init), and107/// may return XRAY_LOG_INITIALIZING to signal callers of the API that108/// there's an ongoing initialization routine running. This allows109/// implementations to support concurrent threads attempting to initialize,110/// while only signalling success in one.111XRAY_LOG_INITIALIZING = 1,112113/// When an implementation is done initializing, it MUST return114/// XRAY_LOG_INITIALIZED. When users call `__xray_patch()`, they are115/// guaranteed that the implementation installed with116/// `__xray_set_log_impl(...)` has been initialized.117XRAY_LOG_INITIALIZED = 2,118119/// Some implementations might support multi-stage finalization (or120/// asynchronous finalization), and may return XRAY_LOG_FINALIZING to signal121/// callers of the API that there's an ongoing finalization routine running.122/// This allows implementations to support concurrent threads attempting to123/// finalize, while only signalling success/completion in one.124XRAY_LOG_FINALIZING = 3,125126/// When an implementation is done finalizing, it MUST return127/// XRAY_LOG_FINALIZED. It is up to the implementation to determine what the128/// semantics of a finalized implementation is. Some implementations might129/// allow re-initialization once the log is finalized, while some might always130/// be on (and that finalization is a no-op).131XRAY_LOG_FINALIZED = 4,132};133134/// This enum allows an implementation to signal log flushing operations via135/// `__xray_log_flushLog()`, and the state of flushing the log.136enum XRayLogFlushStatus {137XRAY_LOG_NOT_FLUSHING = 0,138XRAY_LOG_FLUSHING = 1,139XRAY_LOG_FLUSHED = 2,140};141142/// This enum indicates the installation state of a logging implementation, when143/// associating a mode to a particular logging implementation through144/// `__xray_log_register_impl(...)` or through `__xray_log_select_mode(...`.145enum XRayLogRegisterStatus {146XRAY_REGISTRATION_OK = 0,147XRAY_DUPLICATE_MODE = 1,148XRAY_MODE_NOT_FOUND = 2,149XRAY_INCOMPLETE_IMPL = 3,150};151152/// A valid XRay logging implementation MUST provide all of the function153/// pointers in XRayLogImpl when being installed through `__xray_set_log_impl`.154/// To be precise, ALL the functions pointers MUST NOT be nullptr.155struct XRayLogImpl {156/// The log initialization routine provided by the implementation, always157/// provided with the following parameters:158///159/// - buffer size (unused)160/// - maximum number of buffers (unused)161/// - a pointer to an argument struct that the implementation MUST handle162/// - the size of the argument struct163///164/// See XRayLogInitStatus for details on what the implementation MUST return165/// when called.166///167/// If the implementation needs to install handlers aside from the 0-argument168/// function call handler, it MUST do so in this initialization handler.169///170/// See xray_interface.h for available handler installation routines.171XRayLogInitStatus (*log_init)(size_t, size_t, void *, size_t);172173/// The log finalization routine provided by the implementation.174///175/// See XRayLogInitStatus for details on what the implementation MUST return176/// when called.177XRayLogInitStatus (*log_finalize)();178179/// The 0-argument function call handler. XRay logging implementations MUST180/// always have a handler for function entry and exit events. In case the181/// implementation wants to support arg1 (or other future extensions to XRay182/// logging) those MUST be installed by the installed 'log_init' handler.183///184/// Because we didn't want to change the ABI of this struct, the arg1 handler185/// may be silently overwritten during initialization as well.186void (*handle_arg0)(int32_t, XRayEntryType);187188/// The log implementation provided routine for when __xray_log_flushLog() is189/// called.190///191/// See XRayLogFlushStatus for details on what the implementation MUST return192/// when called.193XRayLogFlushStatus (*flush_log)();194};195196/// DEPRECATED: Use the mode registration workflow instead with197/// __xray_log_register_mode(...) and __xray_log_select_mode(...). See the198/// documentation for those function.199///200/// This function installs a new logging implementation that XRay will use. In201/// case there are any nullptr members in Impl, XRay will *uninstall any202/// existing implementations*. It does NOT patch the instrumentation points.203///204/// NOTE: This function does NOT attempt to finalize the currently installed205/// implementation. Use with caution.206///207/// It is guaranteed safe to call this function in the following states:208///209/// - When the implementation is UNINITIALIZED.210/// - When the implementation is FINALIZED.211/// - When there is no current implementation installed.212///213/// It is logging implementation defined what happens when this function is214/// called while in any other states.215void __xray_set_log_impl(XRayLogImpl Impl);216217/// This function registers a logging implementation against a "mode"218/// identifier. This allows multiple modes to be registered, and chosen at219/// runtime using the same mode identifier through220/// `__xray_log_select_mode(...)`.221///222/// We treat the Mode identifier as a null-terminated byte string, as the223/// identifier used when retrieving the log impl.224///225/// Returns:226/// - XRAY_REGISTRATION_OK on success.227/// - XRAY_DUPLICATE_MODE when an implementation is already associated with228/// the provided Mode; does not update the already-registered229/// implementation.230XRayLogRegisterStatus __xray_log_register_mode(const char *Mode,231XRayLogImpl Impl);232233/// This function selects the implementation associated with Mode that has been234/// registered through __xray_log_register_mode(...) and installs that235/// implementation (as if through calling __xray_set_log_impl(...)). The same236/// caveats apply to __xray_log_select_mode(...) as with237/// __xray_log_set_log_impl(...).238///239/// Returns:240/// - XRAY_REGISTRATION_OK on success.241/// - XRAY_MODE_NOT_FOUND if there is no implementation associated with Mode;242/// does not update the currently installed implementation.243XRayLogRegisterStatus __xray_log_select_mode(const char *Mode);244245/// Returns an identifier for the currently selected XRay mode chosen through246/// the __xray_log_select_mode(...) function call. Returns nullptr if there is247/// no currently installed mode.248const char *__xray_log_get_current_mode();249250/// This function removes the currently installed implementation. It will also251/// uninstall any handlers that have been previously installed. It does NOT252/// unpatch the instrumentation points.253///254/// NOTE: This function does NOT attempt to finalize the currently installed255/// implementation. Use with caution.256///257/// It is guaranteed safe to call this function in the following states:258///259/// - When the implementation is UNINITIALIZED.260/// - When the implementation is FINALIZED.261/// - When there is no current implementation installed.262///263/// It is logging implementation defined what happens when this function is264/// called while in any other states.265void __xray_remove_log_impl();266267/// DEPRECATED: Use __xray_log_init_mode() instead, and provide all the options268/// in string form.269/// Invokes the installed implementation initialization routine. See270/// XRayLogInitStatus for what the return values mean.271XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers,272void *Args, size_t ArgsSize);273274/// Invokes the installed initialization routine, which *must* support the275/// string based form.276///277/// NOTE: When this API is used, we still invoke the installed initialization278/// routine, but we will call it with the following convention to signal that we279/// are using the string form:280///281/// - BufferSize = 0282/// - MaxBuffers = 0283/// - ArgsSize = 0284/// - Args will be the pointer to the character buffer representing the285/// configuration.286///287/// FIXME: Updating the XRayLogImpl struct is an ABI breaking change. When we288/// are ready to make a breaking change, we should clean this up appropriately.289XRayLogInitStatus __xray_log_init_mode(const char *Mode, const char *Config);290291/// Like __xray_log_init_mode(...) this version allows for providing292/// configurations that might have non-null-terminated strings. This will293/// operate similarly to __xray_log_init_mode, with the exception that294/// |ArgsSize| will be what |ConfigSize| is.295XRayLogInitStatus __xray_log_init_mode_bin(const char *Mode, const char *Config,296size_t ConfigSize);297298/// Invokes the installed implementation finalization routine. See299/// XRayLogInitStatus for what the return values mean.300XRayLogInitStatus __xray_log_finalize();301302/// Invokes the install implementation log flushing routine. See303/// XRayLogFlushStatus for what the return values mean.304XRayLogFlushStatus __xray_log_flushLog();305306/// An XRayBuffer represents a section of memory which can be treated by log307/// processing functions as bytes stored in the logging implementation's308/// buffers.309struct XRayBuffer {310const void *Data;311size_t Size;312};313314/// Registers an iterator function which takes an XRayBuffer argument, then315/// returns another XRayBuffer function representing the next buffer. When the316/// Iterator function returns an empty XRayBuffer (Data = nullptr, Size = 0),317/// this signifies the end of the buffers.318///319/// The first invocation of this Iterator function will always take an empty320/// XRayBuffer (Data = nullptr, Size = 0).321void __xray_log_set_buffer_iterator(XRayBuffer (*Iterator)(XRayBuffer));322323/// Removes the currently registered buffer iterator function.324void __xray_log_remove_buffer_iterator();325326/// Invokes the provided handler to process data maintained by the logging327/// handler. This API will be provided raw access to the data available in328/// memory from the logging implementation. The callback function must:329///330/// 1) Not modify the data, to avoid running into undefined behaviour.331///332/// 2) Either know the data layout, or treat the data as raw bytes for later333/// interpretation.334///335/// This API is best used in place of the `__xray_log_flushLog()` implementation336/// above to enable the caller to provide an alternative means of extracting the337/// data from the XRay implementation.338///339/// Implementations MUST then provide:340///341/// 1) A function that will return an XRayBuffer. Functions that return an342/// "empty" XRayBuffer signifies that there are no more buffers to be343/// processed. This function should be registered through the344/// `__xray_log_set_buffer_iterator(...)` function.345///346/// 2) Its own means of converting data it holds in memory into an XRayBuffer347/// structure.348///349/// See XRayLogFlushStatus for what the return values mean.350///351XRayLogFlushStatus __xray_log_process_buffers(void (*Processor)(const char *,352XRayBuffer));353354} // extern "C"355356#endif // XRAY_XRAY_LOG_INTERFACE_H357358359