Skip to content

[XRay] Add -fxray-default-options to pass build-time defined XRay options #116878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// Set of XRay instrumentation kinds to emit.
XRayInstrSet XRayInstrumentationBundle;

/// Default XRay options. Will be overrided by the XRAY_OPTIONS
/// environment variable during run-time.
std::string XRayDefaultOptions;

std::vector<std::string> DefaultFunctionAttrs;

/// List of dynamic shared object files to be loaded as pass plugins.
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2882,6 +2882,12 @@ defm xray_instrument : BoolFOption<"xray-instrument",
"Generate XRay instrumentation sleds on function entry and exit">,
NegFlag<SetFalse>>;

def fxray_default_options_EQ :
Joined<["-"], "fxray-default-options=">,
Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Default XRay options. Can be overwritten by XRAY_OPTIONS environment variable during run-time.">,
MarshallingInfoString<CodeGenOpts<"XRayDefaultOptions">>;

def fxray_instruction_threshold_EQ :
Joined<["-"], "fxray-instruction-threshold=">,
Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/Instrumentation/XRayPreparation.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/GVN.h"
Expand Down Expand Up @@ -1062,6 +1063,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
});
}

if (!CodeGenOpts.XRayDefaultOptions.empty()) {
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase) { MPM.addPass(XRayPreparationPass()); });
}

if (CodeGenOpts.FatLTO) {
MPM.addPass(PB.buildFatLTODefaultPipeline(
Level, PrepareForThinLTO,
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,14 @@ CodeGenModule::CodeGenModule(ASTContext &C,
if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters",
CodeGenOpts.NumRegisterParameters);

// Insert XRay default options if it hasn't been done.
if (CodeGenOpts.XRayInstrumentFunctions &&
!CodeGenOpts.XRayDefaultOptions.empty() &&
!getModule().getModuleFlag("xray-default-opts"))
getModule().addModuleFlag(
llvm::Module::Error, "xray-default-opts",
llvm::MDString::get(LLVMContext, CodeGenOpts.XRayDefaultOptions));
}

CodeGenModule::~CodeGenModule() {}
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/XRayArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
Args.addOptInFlag(CmdArgs, options::OPT_fxray_shared,
options::OPT_fno_xray_shared);

if (const Arg *A = Args.getLastArg(options::OPT_fxray_default_options_EQ))
A->render(Args, CmdArgs);

if (const Arg *A =
Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) {
int Value;
Expand Down
7 changes: 7 additions & 0 deletions clang/test/CodeGen/xray-default-options.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %clang_cc1 -fxray-instrument -fxray-default-options='patch_premain=true,xray_mode=xray-basic' \
// RUN: -std=c11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s

void justAFunction() {
}

// CHECK: !{{[0-9]+}} = !{i32 1, !"xray-default-opts", !"patch_premain=true,xray_mode=xray-basic"}
1 change: 1 addition & 0 deletions compiler-rt/lib/xray/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(XRAY_SOURCES
xray_flags.cpp
xray_interface.cpp
xray_log_interface.cpp
xray_options_var.cpp
xray_utils.cpp
)

Expand Down
4 changes: 4 additions & 0 deletions compiler-rt/lib/xray/xray_flags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ void initializeFlags() XRAY_NEVER_INSTRUMENT {
const char *XRayCompileFlags = useCompilerDefinedFlags();
XRayParser.ParseString(XRayCompileFlags);

// Override from compile-time options.
if (XRAY_OPTIONS_VAR[0] != 0)
XRayParser.ParseString(XRAY_OPTIONS_VAR);

// Override from environment variables.
XRayParser.ParseStringFromEnv("XRAY_OPTIONS");

Expand Down
6 changes: 6 additions & 0 deletions compiler-rt/lib/xray/xray_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#include "sanitizer_common/sanitizer_flag_parser.h"
#include "sanitizer_common/sanitizer_internal_defs.h"

#define XRAY_OPTIONS_VAR __llvm_xray_options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem useful to introduce a capitalized alias XRAY_OPTIONS_VAR.

If a TU doesn't include xray_flags.h, the compiled code will reference XRAY_OPTIONS_VAR.


extern "C" {
extern char XRAY_OPTIONS_VAR[1];
}

namespace __xray {

struct Flags {
Expand Down
24 changes: 24 additions & 0 deletions compiler-rt/lib/xray/xray_options_var.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*===----- xray_options_var.cpp - XRay option variable setup -------------===*\
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

//

|*
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|* See https://llvm.org/LICENSE.txt for license information.
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|*
\*===----------------------------------------------------------------------===*/

#include "xray_flags.h"

// FIXME: Generalize these. See lib/profile/InstrProfilingPort.h and
// include/profile/InstrProfData.inc
#define COMPILER_RT_VISIBILITY __attribute__((visibility("hidden")))
#define COMPILER_RT_WEAK __attribute__((weak))

extern "C" {
/* char __llvm_xray_options[1]
*
* The runtime should only provide its own definition of this symbol when the
* user has not specified one. Set this up by moving the runtime's copy of this
* symbol to an object file within the archive.
*/
COMPILER_RT_WEAK COMPILER_RT_VISIBILITY char XRAY_OPTIONS_VAR[1] = {0};
}
12 changes: 12 additions & 0 deletions compiler-rt/test/xray/TestCases/Posix/default-options.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// RUN: %clang_xray -g -fxray-default-options='patch_premain=true:verbosity=1:xray_mode=xray-basic' -o %t %s
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lld/test/ELF style // RUN: rm -fr %t && mkdir %t && cd %t seems better

// RUN: rm -f xray-log.default-options.*
// RUN: %run %t 2>&1 | FileCheck %s
// RUN: rm -f xray-log.default-options.*
//
// REQUIRES: target={{(aarch64|loongarch64|x86_64)-.*}}
// REQUIRES: built-in-llvm-tree
__attribute__((xray_always_instrument)) void always() {}

int main() { always(); }

// CHECK: =={{[0-9].*}}==XRay: Log file in '{{.*}}'
15 changes: 14 additions & 1 deletion llvm/docs/XRay.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ Also by default the filename of the XRay trace is ``xray-log.XXXXXX`` where the
``XXXXXX`` part is randomly generated.

These options can be controlled through the ``XRAY_OPTIONS`` environment
variable, where we list down the options and their defaults below.
variable during program run-time, where we list down the options and their
defaults below.

+-------------------+-----------------+---------------+------------------------+
| Option | Type | Default | Description |
Expand All @@ -177,6 +178,18 @@ variable, where we list down the options and their defaults below.
| | | | level. |
+-------------------+-----------------+---------------+------------------------+

In addition to environment variable, you can also use ``-fxray-default-options``
to specify default XRay options during program build time.

For example, programs built with the following flags automatically use
'patch_premain=true,xray_mode=basic' by default even without setting ``XRAY_OPTIONS``.

::

clang -fxray-instrument -fxray-default-options='patch_premain=true,xray_mode=basic' ...

Note that you still can override options designated by ``-fxray-default-options``
using ``XRAY_OPTIONS`` during run-time.

If you choose to not use the default logging implementation that comes with the
XRay runtime and/or control when/how the XRay instrumentation runs, you may use
Expand Down
24 changes: 24 additions & 0 deletions llvm/include/llvm/Transforms/Instrumentation/XRayPreparation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===- XRayPreparation.h - Preparation for XRay instrumentation -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This Pass does some IR-level preparations (e.g. inserting global variable
// that carries default options, if there is any) for XRay instrumentation.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_XRAYPREPARATION_H
#define LLVM_TRANSFORMS_INSTRUMENTATION_XRAYPREPARATION_H

#include "llvm/IR/PassManager.h"

namespace llvm {
struct XRayPreparationPass : public PassInfoMixin<XRayPreparationPass> {
PreservedAnalyses run(Module &, ModuleAnalysisManager &);
};
} // namespace llvm
#endif
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/Instrumentation/XRayPreparation.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar/ADCE.h"
#include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ MODULE_PASS("tsan-module", ModuleThreadSanitizerPass())
MODULE_PASS("verify", VerifierPass())
MODULE_PASS("view-callgraph", CallGraphViewerPass())
MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass())
MODULE_PASS("xray-preparation", XRayPreparationPass())
#undef MODULE_PASS

#ifndef MODULE_PASS_WITH_PARAMS
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Instrumentation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ add_llvm_component_library(LLVMInstrumentation
ThreadSanitizer.cpp
HWAddressSanitizer.cpp
RealtimeSanitizer.cpp
XRayPreparation.cpp

ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
Expand Down
49 changes: 49 additions & 0 deletions llvm/lib/Transforms/Instrumentation/XRayPreparation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===- XRayPreparation.cpp - Preparation for XRay instrumentation -------- ===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This Pass does some IR-level preparations (e.g. inserting global variable
// that carries default options, if there is any) for XRay instrumentation.
//
//===---------------------------------------------------------------------===//

#include "llvm/Transforms/Instrumentation/XRayPreparation.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/TargetParser/Triple.h"

using namespace llvm;

static void createXRayDefaultOptionsVar(Module &M, StringRef DefaultOptions) {
Constant *DefaultOptionsConst =
ConstantDataArray::getString(M.getContext(), DefaultOptions, true);
// This global variable will be passed into XRay's compiler-rt and used as
// the initial set of XRay options.
GlobalVariable *DefaultOptsVar = new GlobalVariable(
M, DefaultOptionsConst->getType(), true, GlobalValue::WeakAnyLinkage,
DefaultOptionsConst, "__llvm_xray_options");
DefaultOptsVar->setVisibility(GlobalValue::HiddenVisibility);
Triple TT(M.getTargetTriple());
if (TT.supportsCOMDAT()) {
DefaultOptsVar->setLinkage(GlobalValue::ExternalLinkage);
DefaultOptsVar->setComdat(M.getOrInsertComdat("__llvm_xray_options"));
}
}

PreservedAnalyses XRayPreparationPass::run(Module &M,
ModuleAnalysisManager &MAM) {
// XRay default options.
if (const auto *DefaultOpts =
dyn_cast_or_null<MDString>(M.getModuleFlag("xray-default-opts"))) {
createXRayDefaultOptionsVar(M, DefaultOpts->getString());
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
}

return PreservedAnalyses::all();
}
10 changes: 10 additions & 0 deletions llvm/test/CodeGen/X86/xray-default-options.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
; RUN: opt -S -p xray-preparation < %s | FileCheck %s

target triple = "x86_64-unknown-linux-gnu"

; CHECK: $__llvm_xray_options = comdat any
; CHECK: @__llvm_xray_options = hidden constant [40 x i8] c"patch_premain=true,xray_mode=xray-basic\00", comdat

!llvm.module.flags = !{!0}

!0 = !{i32 1, !"xray-default-opts", !"patch_premain=true,xray_mode=xray-basic"}
Loading