brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.6 KiB · 2e91b7e Raw
358 lines · c
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-exception6//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 them16/// to replace the default runtime-controllable implementation that comes with17/// compiler-rt/xray. The "flight data recorder" (FDR) mode implementation uses18/// this API to install itself in an XRay-enabled binary. See19/// 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 this24///   // has succeeded. Each mode will have their own set of flags they will25///   // support, outside of the global XRay configuration options that are26///   // 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 initialise30///     // 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 can43///   // now patch the instrumentation points. Note that we could have patched44///   // the instrumentation points first, but there's no strict ordering to45///   // 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 (before52///   // 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 a59///   // chance to see that the implementation is already finalized. Also, at60///   // this point we can optionally unpatch the instrumentation points to61///   // 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 only68///   // after we've finalized the log. Some implementations may not actually69///   // have anything to log (it might keep the data in memory, or periodically70///   // 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 without77///   // relying on the implementations' flushing semantics (if the78///   // 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 the89/// implementation first. Some implementations might stay in an "off" state when90/// they are finalized, while some might be in an invalid/unknown state.91///92#ifndef XRAY_XRAY_LOG_INTERFACE_H93#define XRAY_XRAY_LOG_INTERFACE_H94 95#include "xray/xray_interface.h"96#include <stddef.h>97 98extern "C" {99 100/// This enum defines the valid states in which the logging implementation can101/// be at.102enum XRayLogInitStatus {103  /// The default state is uninitialized, and in case there were errors in the104  /// initialization, the implementation MUST return XRAY_LOG_UNINITIALIZED.105  XRAY_LOG_UNINITIALIZED = 0,106 107  /// Some implementations support multi-stage init (or asynchronous init), and108  /// may return XRAY_LOG_INITIALIZING to signal callers of the API that109  /// there's an ongoing initialization routine running. This allows110  /// 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 return115  /// XRAY_LOG_INITIALIZED. When users call `__xray_patch()`, they are116  /// guaranteed that the implementation installed with117  /// `__xray_set_log_impl(...)` has been initialized.118  XRAY_LOG_INITIALIZED = 2,119 120  /// Some implementations might support multi-stage finalization (or121  /// asynchronous finalization), and may return XRAY_LOG_FINALIZING to signal122  /// callers of the API that there's an ongoing finalization routine running.123  /// This allows implementations to support concurrent threads attempting to124  /// finalize, while only signalling success/completion in one.125  XRAY_LOG_FINALIZING = 3,126 127  /// When an implementation is done finalizing, it MUST return128  /// XRAY_LOG_FINALIZED. It is up to the implementation to determine what the129  /// semantics of a finalized implementation is. Some implementations might130  /// allow re-initialization once the log is finalized, while some might always131  /// 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 via136/// `__xray_log_flushLog()`, and the state of flushing the log.137enum 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, when144/// associating a mode to a particular logging implementation through145/// `__xray_log_register_impl(...)` or through `__xray_log_select_mode(...`.146enum 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 function154/// pointers in XRayLogImpl when being installed through `__xray_set_log_impl`.155/// To be precise, ALL the functions pointers MUST NOT be nullptr.156struct XRayLogImpl {157  /// The log initialization routine provided by the implementation, always158  /// 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 handle163  ///   - the size of the argument struct164  ///165  /// See XRayLogInitStatus for details on what the implementation MUST return166  /// when called.167  ///168  /// If the implementation needs to install handlers aside from the 0-argument169  /// 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 return177  /// when called.178  XRayLogInitStatus (*log_finalize)();179 180  /// The 0-argument function call handler. XRay logging implementations MUST181  /// always have a handler for function entry and exit events. In case the182  /// implementation wants to support arg1 (or other future extensions to XRay183  /// 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 handler186  /// 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() is190  /// called.191  ///192  /// See XRayLogFlushStatus for details on what the implementation MUST return193  /// when called.194  XRayLogFlushStatus (*flush_log)();195};196 197/// DEPRECATED: Use the mode registration workflow instead with198/// __xray_log_register_mode(...) and __xray_log_select_mode(...). See the199/// documentation for those function.200///201/// This function installs a new logging implementation that XRay will use. In202/// case there are any nullptr members in Impl, XRay will *uninstall any203/// existing implementations*. It does NOT patch the instrumentation points.204///205/// NOTE: This function does NOT attempt to finalize the currently installed206/// 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 is215/// called while in any other states.216void __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 at220/// runtime using the same mode identifier through221/// `__xray_log_select_mode(...)`.222///223/// We treat the Mode identifier as a null-terminated byte string, as the224/// 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 with229///     the provided Mode; does not update the already-registered230///     implementation.231XRayLogRegisterStatus __xray_log_register_mode(const char *Mode,232                                               XRayLogImpl Impl);233 234/// This function selects the implementation associated with Mode that has been235/// registered through __xray_log_register_mode(...) and installs that236/// implementation (as if through calling __xray_set_log_impl(...)). The same237/// caveats apply to __xray_log_select_mode(...) as with238/// __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.244XRayLogRegisterStatus __xray_log_select_mode(const char *Mode);245 246/// Returns an identifier for the currently selected XRay mode chosen through247/// the __xray_log_select_mode(...) function call. Returns nullptr if there is248/// no currently installed mode.249const char *__xray_log_get_current_mode();250 251/// This function removes the currently installed implementation. It will also252/// uninstall any handlers that have been previously installed. It does NOT253/// unpatch the instrumentation points.254///255/// NOTE: This function does NOT attempt to finalize the currently installed256/// 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 is265/// called while in any other states.266void __xray_remove_log_impl();267 268/// DEPRECATED: Use __xray_log_init_mode() instead, and provide all the options269/// in string form.270/// Invokes the installed implementation initialization routine. See271/// XRayLogInitStatus for what the return values mean.272XRayLogInitStatus __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 the276/// string based form.277///278/// NOTE: When this API is used, we still invoke the installed initialization279/// routine, but we will call it with the following convention to signal that we280/// are using the string form:281///282/// - BufferSize = 0283/// - MaxBuffers = 0284/// - ArgsSize = 0285/// - Args will be the pointer to the character buffer representing the286///   configuration.287///288/// FIXME: Updating the XRayLogImpl struct is an ABI breaking change. When we289/// are ready to make a breaking change, we should clean this up appropriately.290XRayLogInitStatus __xray_log_init_mode(const char *Mode, const char *Config);291 292/// Like __xray_log_init_mode(...) this version allows for providing293/// configurations that might have non-null-terminated strings. This will294/// operate similarly to __xray_log_init_mode, with the exception that295/// |ArgsSize| will be what |ConfigSize| is.296XRayLogInitStatus __xray_log_init_mode_bin(const char *Mode, const char *Config,297                                           size_t ConfigSize);298 299/// Invokes the installed implementation finalization routine. See300/// XRayLogInitStatus for what the return values mean.301XRayLogInitStatus __xray_log_finalize();302 303/// Invokes the install implementation log flushing routine. See304/// XRayLogFlushStatus for what the return values mean.305XRayLogFlushStatus __xray_log_flushLog();306 307/// An XRayBuffer represents a section of memory which can be treated by log308/// processing functions as bytes stored in the logging implementation's309/// buffers.310struct XRayBuffer {311  const void *Data;312  size_t Size;313};314 315/// Registers an iterator function which takes an XRayBuffer argument, then316/// returns another XRayBuffer function representing the next buffer. When the317/// 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 empty321/// XRayBuffer (Data = nullptr, Size = 0).322void __xray_log_set_buffer_iterator(XRayBuffer (*Iterator)(XRayBuffer));323 324/// Removes the currently registered buffer iterator function.325void __xray_log_remove_buffer_iterator();326 327/// Invokes the provided handler to process data maintained by the logging328/// handler. This API will be provided raw access to the data available in329/// 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 later334///    interpretation.335///336/// This API is best used in place of the `__xray_log_flushLog()` implementation337/// above to enable the caller to provide an alternative means of extracting the338/// data from the XRay implementation.339///340/// Implementations MUST then provide:341///342/// 1) A function that will return an XRayBuffer. Functions that return an343///    "empty" XRayBuffer signifies that there are no more buffers to be344///    processed. This function should be registered through the345///    `__xray_log_set_buffer_iterator(...)` function.346///347/// 2) Its own means of converting data it holds in memory into an XRayBuffer348///    structure.349///350/// See XRayLogFlushStatus for what the return values mean.351///352XRayLogFlushStatus __xray_log_process_buffers(void (*Processor)(const char *,353                                                                XRayBuffer));354 355} // extern "C"356 357#endif // XRAY_XRAY_LOG_INTERFACE_H358