Skip to content

Commit

Permalink
[XRay][compiler-rt+docs] Introduce __xray_log_init_mode(...).
Browse files Browse the repository at this point in the history
Summary:
This addresses http://llvm.org/PR36790.

The change Deprecates a number of functions and types in
`include/xray/xray_log_interface.h` to recommend using string-based
configuration of XRay through the __xray_log_init_mode(...) function. In
particular, this deprecates the following:

- `__xray_set_log_impl(...)` -- users should instead use the
`__xray_log_register_mode(...)` and `__xray_log_select_mode(...)` APIs.

- `__xray_log_init(...)` -- users should instead use the
`__xray_log_init_mode(...)` function, which also requires using the
`__xray_log_register_mode(...)` and `__xray_log_select_mode(...)`
functionality.

- `__xray::FDRLoggingOptions` -- in following patches, we'll be
migrating the FDR logging implementations (and tests) to use the
string-based configuration. In later stages we'll remove the
`__xray::FDRLoggingOptions` type, and ask users to migrate to using the
string-based configuration mechanism instead.

- `__xray::BasicLoggingOptions` -- same as `__xray::FDRLoggingOptions`,
we'll be removing this type later and instead rely exclusively on the
string-based configuration API.

We also update the documentation to reflect the new advice and remove
some of the deprecated notes.

Reviewers: eizan, kpw, echristo, pelikan

Reviewed By: kpw

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D46173

llvm-svn: 331503
  • Loading branch information
deanberris committed May 4, 2018
1 parent 131e749 commit f0a6927
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 93 deletions.
82 changes: 59 additions & 23 deletions compiler-rt/include/xray/xray_log_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,29 @@
///
/// The high-level usage pattern for these APIs look like the following:
///
/// // Before we try initializing the log implementation, we must set it as
/// // the log implementation. We provide the function pointers that define
/// // the various initialization, finalization, and other pluggable hooks
/// // that we need.
/// __xray_set_log_impl({...});
///
/// // Once that's done, we can now initialize the implementation. Each
/// // implementation has a chance to let users customize the implementation
/// // with a struct that their implementation supports. Roughly this might
/// // look like:
/// MyImplementationOptions opts;
/// opts.enable_feature = true;
/// ...
/// auto init_status = __xray_log_init(
/// BufferSize, MaxBuffers, &opts, sizeof opts);
/// if (init_status != XRayLogInitStatus::XRAY_LOG_INITIALIZED) {
/// // We choose the mode which we'd like to install, and check whether this
/// // has succeeded. Each mode will have their own set of flags they will
/// // support, outside of the global XRay configuration options that are
/// // defined in the XRAY_OPTIONS environment variable.
/// auto select_status = __xray_log_select_mode("xray-fdr");
/// if (select_status != XRayLogRegisterStatus::XRAY_REGISTRATION_OK) {
/// // This failed, we should not proceed with attempting to initialise
/// // the currently selected mode.
/// return;
/// }
///
/// // Once that's done, we can now attempt to configure the implementation.
/// // To do this, we provide the string flags configuration for the mode.
/// auto config_status = __xray_log_init_mode(
/// "xray-fdr", "verbosity=1 some_flag=1 another_flag=2");
/// if (config_status != XRayLogInitStatus::XRAY_LOG_INITIALIZED) {
/// // deal with the error here, if there is one.
/// }
///
/// // When the log implementation has had the chance to initialize, we can
/// // now patch the sleds.
/// // now patch the instrumentation points. Note that we could have patched
/// // the instrumentation points first, but there's no strict ordering to
/// // these operations.
/// auto patch_status = __xray_patch();
/// if (patch_status != XRayPatchingStatus::SUCCESS) {
/// // deal with the error here, if it is an error.
Expand All @@ -56,12 +58,12 @@
///
/// // We can optionally wait before flushing the log to give other threads a
/// // chance to see that the implementation is already finalized. Also, at
/// // this point we can optionally unpatch the sleds to reduce overheads at
/// // runtime.
/// // this point we can optionally unpatch the instrumentation points to
/// // reduce overheads at runtime.
/// auto unpatch_status = __xray_unpatch();
/// if (unpatch_status != XRayPatchingStatus::SUCCESS) {
// // deal with the error here, if it is an error.
// }
/// // deal with the error here, if it is an error.
/// }
///
/// // If there are logs or data to be flushed somewhere, we can do so only
/// // after we've finalized the log. Some implementations may not actually
Expand Down Expand Up @@ -193,9 +195,13 @@ struct XRayLogImpl {
XRayLogFlushStatus (*flush_log)();
};

/// DEPRECATED: Use the mode registration workflow instead with
/// __xray_log_register_mode(...) and __xray_log_select_mode(...). See the
/// documentation for those function.
///
/// This function installs a new logging implementation that XRay will use. In
/// case there are any nullptr members in Impl, XRay will *uninstall any
/// existing implementations*. It does NOT patch the instrumentation sleds.
/// existing implementations*. It does NOT patch the instrumentation points.
///
/// NOTE: This function does NOT attempt to finalize the currently installed
/// implementation. Use with caution.
Expand Down Expand Up @@ -245,7 +251,7 @@ const char *__xray_log_get_current_mode();

/// This function removes the currently installed implementation. It will also
/// uninstall any handlers that have been previously installed. It does NOT
/// unpatch the instrumentation sleds.
/// unpatch the instrumentation points.
///
/// NOTE: This function does NOT attempt to finalize the currently installed
/// implementation. Use with caution.
Expand All @@ -260,11 +266,37 @@ const char *__xray_log_get_current_mode();
/// called while in any other states.
void __xray_remove_log_impl();

/// DEPRECATED: Use __xray_log_init_mode() instead, and provide all the options
/// in string form.
/// Invokes the installed implementation initialization routine. See
/// XRayLogInitStatus for what the return values mean.
XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers,
void *Args, size_t ArgsSize);

/// Invokes the installed initialization routine, which *must* support the
/// string based form.
///
/// NOTE: When this API is used, we still invoke the installed initialization
/// routine, but we will call it with the following convention to signal that we
/// are using the string form:
///
/// - BufferSize = 0
/// - MaxBuffers = 0
/// - ArgsSize = 0
/// - Args will be the pointer to the character buffer representing the
/// configuration.
///
/// FIXME: Updating the XRayLogImpl struct is an ABI breaking change. When we
/// are ready to make a breaking change, we should clean this up appropriately.
XRayLogInitStatus __xray_log_init_mode(const char *Mode, const char *Config);

/// Like __xray_log_init_mode(...) this version allows for providing
/// configurations that might have non-null-terminated strings. This will
/// operate similarly to __xray_log_init_mode, with the exception that
/// |ArgsSize| will be what |ConfigSize| is.
XRayLogInitStatus __xray_log_init_mode_bin(const char *Mode, const char *Config,
size_t ConfigSize);

/// Invokes the installed implementation finalization routine. See
/// XRayLogInitStatus for what the return values mean.
XRayLogInitStatus __xray_log_finalize();
Expand Down Expand Up @@ -325,12 +357,16 @@ XRayLogFlushStatus __xray_log_process_buffers(void (*Processor)(const char *,

namespace __xray {

/// DEPRECATED: Use __xray_log_init_mode(...) instead, and provide flag
/// configuration strings to set the options instead.
/// Options used by the LLVM XRay FDR logging implementation.
struct FDRLoggingOptions {
bool ReportErrors = false;
int Fd = -1;
};

/// DEPRECATED: Use __xray_log_init_mode(...) instead, and provide flag
/// configuration strings to set the options instead.
/// Options used by the LLVM XRay Basic (Naive) logging implementation.
struct BasicLoggingOptions {
int DurationFilterMicros = 0;
Expand Down
41 changes: 41 additions & 0 deletions compiler-rt/lib/xray/xray_log_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,47 @@ XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers,
return GlobalXRayImpl->log_init(BufferSize, MaxBuffers, Args, ArgsSize);
}

XRayLogInitStatus __xray_log_init_mode(const char *Mode, const char *Config)
XRAY_NEVER_INSTRUMENT {
__sanitizer::SpinMutexLock Guard(&XRayImplMutex);
if (!GlobalXRayImpl)
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;

if (Config == nullptr)
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;

// Check first whether the current mode is the same as what we expect.
if (CurrentMode == nullptr || internal_strcmp(CurrentMode->Mode, Mode) != 0)
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;

// Here we do some work to coerce the pointer we're provided, so that
// the implementations that still take void* pointers can handle the
// data provided in the Config argument.
return GlobalXRayImpl->log_init(
0, 0, const_cast<void *>(static_cast<const void *>(Config)), 0);
}

XRayLogInitStatus
__xray_log_init_mode_bin(const char *Mode, const char *Config,
size_t ConfigSize) XRAY_NEVER_INSTRUMENT {
__sanitizer::SpinMutexLock Guard(&XRayImplMutex);
if (!GlobalXRayImpl)
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;

if (Config == nullptr)
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;

// Check first whether the current mode is the same as what we expect.
if (CurrentMode == nullptr || internal_strcmp(CurrentMode->Mode, Mode) != 0)
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;

// Here we do some work to coerce the pointer we're provided, so that
// the implementations that still take void* pointers can handle the
// data provided in the Config argument.
return GlobalXRayImpl->log_init(
0, 0, const_cast<void *>(static_cast<const void *>(Config)), ConfigSize);
}

XRayLogInitStatus __xray_log_finalize() XRAY_NEVER_INSTRUMENT {
__sanitizer::SpinMutexLock Guard(&XRayImplMutex);
if (!GlobalXRayImpl)
Expand Down
29 changes: 21 additions & 8 deletions compiler-rt/test/xray/TestCases/Posix/logging-modes.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Check that we can install an implementation associated with a mode.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: rm xray-log.logging-modes* || true
// RUN: %clangxx_xray -std=c++11 %s -o %t -fxray-modes=none
// RUN: %run %t | FileCheck %s
//
// UNSUPPORTED: target-is-mips64,target-is-mips64el
Expand Down Expand Up @@ -31,8 +32,18 @@
assert(false && "Invalid buffer provided.");
}

static constexpr char Options[] = "additional_flags";

[[clang::xray_never_instrument]] XRayLogInitStatus
printing_init(size_t, size_t, void *, size_t) {
printing_init(size_t BufferSize, size_t MaxBuffers, void *Config,
size_t ArgsSize) {
// We require that the printing init is called through the
// __xray_log_init_mode(...) implementation, and that the promised contract is
// enforced.
assert(BufferSize == 0);
assert(MaxBuffers == 0);
assert(Config != nullptr);
assert(ArgsSize == 0 || ArgsSize == sizeof(Options));
__xray_log_set_buffer_iterator(next_buffer);
return XRayLogInitStatus::XRAY_LOG_INITIALIZED;
}
Expand All @@ -52,23 +63,25 @@ static auto buffer_counter = 0;

void process_buffer(const char *, XRayBuffer) { ++buffer_counter; }

static bool unused = [] {
int main(int argc, char **argv) {
assert(__xray_log_register_mode("custom",
{printing_init, printing_finalize,
printing_handler, printing_flush_log}) ==
XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
return true;
}();

int main(int argc, char **argv) {
assert(__xray_log_select_mode("custom") ==
XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
assert(__xray_log_get_current_mode() != nullptr);
std::string current_mode = __xray_log_get_current_mode();
assert(current_mode == "custom");
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
assert(__xray_log_init(0, 0, nullptr, 0) ==
assert(__xray_log_init_mode("custom", "flags_config_here=true") ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);

// Also test that we can use the "binary" version of the
// __xray_log_niit_mode(...) API.
assert(__xray_log_init_mode_bin("custom", Options, sizeof(Options)) ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);

// CHECK: printing {{.*}}
callme(); // CHECK: called me!
// CHECK: printing {{.*}}
Expand Down

0 comments on commit f0a6927

Please sign in to comment.