Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -148,13 +148,20 @@ /// \brief Paths to the XRay "always instrument" files specifying which /// objects (files, functions, variables) should be imbued with the XRay /// "always instrument" attribute. + /// WARNING: This is a deprecated field and will go away in the future. std::vector XRayAlwaysInstrumentFiles; /// \brief Paths to the XRay "never instrument" files specifying which /// objects (files, functions, variables) should be imbued with the XRay /// "never instrument" attribute. + /// WARNING: This is a deprecated field and will go away in the future. std::vector XRayNeverInstrumentFiles; + /// \brief Paths to the XRay attribute list files, specifying which objects + /// (files, functions, variables) should be imbued with the appropriate XRay + /// attribute(s). + std::vector XRayAttrListFiles; + clang::ObjCRuntime ObjCRuntime; std::string ObjCConstantStringClass; Index: clang/include/clang/Basic/XRayLists.h =================================================================== --- clang/include/clang/Basic/XRayLists.h +++ clang/include/clang/Basic/XRayLists.h @@ -26,12 +26,13 @@ class XRayFunctionFilter { std::unique_ptr AlwaysInstrument; std::unique_ptr NeverInstrument; + std::unique_ptr AttrList; SourceManager &SM; public: XRayFunctionFilter(ArrayRef AlwaysInstrumentPaths, ArrayRef NeverInstrumentPaths, - SourceManager &SM); + ArrayRef AttrListPaths, SourceManager &SM); enum class ImbueAttribute { NONE, Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1095,11 +1095,15 @@ def fxray_always_instrument : JoinedOrSeparate<["-"], "fxray-always-instrument=">, Group, Flags<[CC1Option]>, - HelpText<"Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">; + HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">; def fxray_never_instrument : JoinedOrSeparate<["-"], "fxray-never-instrument=">, Group, Flags<[CC1Option]>, - HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; + HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; +def fxray_attr_list : + JoinedOrSeparate<["-"], "fxray-attr-list=">, + Group, Flags<[CC1Option]>, + HelpText<"Filename defining the list of functions/types for imbuing XRay attributes.">; def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents">, Group, Flags<[CC1Option]>, Index: clang/include/clang/Driver/XRayArgs.h =================================================================== --- clang/include/clang/Driver/XRayArgs.h +++ clang/include/clang/Driver/XRayArgs.h @@ -21,6 +21,7 @@ class XRayArgs { std::vector AlwaysInstrumentFiles; std::vector NeverInstrumentFiles; + std::vector AttrListFiles; std::vector ExtraDeps; bool XRayInstrument = false; int InstructionThreshold = 200; Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -788,7 +788,8 @@ SubstTemplateTemplateParmPacks(this_()), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, - LangOpts.XRayNeverInstrumentFiles, SM)), + LangOpts.XRayNeverInstrumentFiles, + LangOpts.XRayAttrListFiles, SM)), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) { Index: clang/lib/Basic/XRayLists.cpp =================================================================== --- clang/lib/Basic/XRayLists.cpp +++ clang/lib/Basic/XRayLists.cpp @@ -16,24 +16,32 @@ XRayFunctionFilter::XRayFunctionFilter( ArrayRef AlwaysInstrumentPaths, - ArrayRef NeverInstrumentPaths, SourceManager &SM) + ArrayRef NeverInstrumentPaths, + ArrayRef AttrListPaths, SourceManager &SM) : AlwaysInstrument( llvm::SpecialCaseList::createOrDie(AlwaysInstrumentPaths)), NeverInstrument(llvm::SpecialCaseList::createOrDie(NeverInstrumentPaths)), - SM(SM) {} + AttrList(llvm::SpecialCaseList::createOrDie(AttrListPaths)), SM(SM) {} XRayFunctionFilter::ImbueAttribute XRayFunctionFilter::shouldImbueFunction(StringRef FunctionName) const { // First apply the always instrument list, than if it isn't an "always" see // whether it's treated as a "never" instrument function. + // TODO: Remove these as they're deprecated; use the AttrList exclusively. if (AlwaysInstrument->inSection("xray_always_instrument", "fun", FunctionName, - "arg1")) + "arg1") || + AttrList->inSection("always", "fun", FunctionName, "arg1")) return ImbueAttribute::ALWAYS_ARG1; if (AlwaysInstrument->inSection("xray_always_instrument", "fun", - FunctionName)) + FunctionName) || + AttrList->inSection("always", "fun", FunctionName)) return ImbueAttribute::ALWAYS; - if (NeverInstrument->inSection("xray_never_instrument", "fun", FunctionName)) + + if (NeverInstrument->inSection("xray_never_instrument", "fun", + FunctionName) || + AttrList->inSection("never", "fun", FunctionName)) return ImbueAttribute::NEVER; + return ImbueAttribute::NONE; } @@ -41,10 +49,12 @@ XRayFunctionFilter::shouldImbueFunctionsInFile(StringRef Filename, StringRef Category) const { if (AlwaysInstrument->inSection("xray_always_instrument", "src", Filename, - Category)) + Category) || + AttrList->inSection("always", "src", Filename, Category)) return ImbueAttribute::ALWAYS; if (NeverInstrument->inSection("xray_never_instrument", "src", Filename, - Category)) + Category) || + AttrList->inSection("never", "src", Filename, Category)) return ImbueAttribute::NEVER; return ImbueAttribute::NONE; } Index: clang/lib/Driver/XRayArgs.cpp =================================================================== --- clang/lib/Driver/XRayArgs.cpp +++ clang/lib/Driver/XRayArgs.cpp @@ -99,6 +99,15 @@ } else D.Diag(clang::diag::err_drv_no_such_file) << Filename; } + + for (const auto &Filename : + Args.getAllArgValues(options::OPT_fxray_attr_list)) { + if (llvm::sys::fs::exists(Filename)) { + AttrListFiles.push_back(Filename); + ExtraDeps.push_back(Filename); + } else + D.Diag(clang::diag::err_drv_no_such_file) << Filename; + } } } @@ -127,6 +136,12 @@ CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt)); } + for (const auto&AttrFile : AttrListFiles) { + SmallString<64> AttrListFileOpt("-fxray-attr-list="); + AttrListFileOpt += AttrFile; + CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt)); + } + for (const auto &Dep : ExtraDeps) { SmallString<64> ExtraDepOpt("-fdepfile-entry="); ExtraDepOpt += Dep; Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -2640,6 +2640,7 @@ Args.getAllArgValues(OPT_fxray_always_instrument); Opts.XRayNeverInstrumentFiles = Args.getAllArgValues(OPT_fxray_never_instrument); + Opts.XRayAttrListFiles = Args.getAllArgValues(OPT_fxray_attr_list); // -fallow-editor-placeholders Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); Index: clang/test/CodeGen/xray-always-instrument.cpp =================================================================== --- clang/test/CodeGen/xray-always-instrument.cpp +++ clang/test/CodeGen/xray-always-instrument.cpp @@ -1,6 +1,14 @@ // RUN: echo "fun:*foo*" > %t.always-instrument // RUN: echo "src:*xray-always-instrument.cpp" >> %t.always-instrument -// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s -triple x86_64-unknown-linux-gnu | FileCheck %s +// RUN: echo "[always]" > %t.xray-attrlist +// RUN: echo "fun:*foo*" >> %t.xray-attrlist +// RUN: echo "src:*xray-always-instrument.cpp" >> %t.xray-attrlist +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \ +// RUN: -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \ +// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s void foo() {} Index: clang/test/CodeGen/xray-attr-list.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/xray-attr-list.cpp @@ -0,0 +1,19 @@ +// RUN: echo "[always]" > %t.xray-attrlist +// RUN: echo "fun:*always*" >> %t.xray-attrlist +// RUN: echo "[never]" >> %t.xray-attrlist +// RUN: echo "fun:*never*" >> %t.xray-attrlist +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \ +// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s + +void always() {} +void never() {} +[[clang::xray_never_instrument]] void alwaysNever() {} +[[clang::xray_always_instrument]] void neverAlways() {} + +// CHECK: define void @_Z6alwaysv() #[[ALWAYSATTR:[0-9]+]] { +// CHECK: define void @_Z5neverv() #[[NEVERATTR:[0-9]+]] { +// CHECK: define void @_Z11alwaysNeverv() #[[NEVERATTR]] { +// CHECK: define void @_Z11neverAlwaysv() #[[ALWAYSATTR]] { +// CHECK: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}} +// CHECK: attributes #[[NEVERATTR]] = {{.*}} "function-instrument"="xray-never" {{.*}} Index: clang/test/CodeGen/xray-imbue-arg1.cpp =================================================================== --- clang/test/CodeGen/xray-imbue-arg1.cpp +++ clang/test/CodeGen/xray-imbue-arg1.cpp @@ -1,5 +1,12 @@ // RUN: echo "fun:*arg1*=arg1" >> %t.always-instrument -// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s -triple x86_64-unknown-linux-gnu | FileCheck %s +// RUN: echo "[always]" > %t.xray-attrlist +// RUN: echo "fun:*arg1*=arg1" >> %t.xray-attrlist +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \ +// RUN: -fxray-always-instrument=%t.always-instrument -emit-llvm -o - %s \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \ +// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s void foo() {} Index: clang/test/CodeGen/xray-never-instrument.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/xray-never-instrument.cpp @@ -0,0 +1,24 @@ +// RUN: echo "fun:*foo*" > %t.never-instrument +// RUN: echo "src:*xray-never-instrument.cpp" >> %t.never-instrument +// RUN: echo "[never]" > %t.xray-attrlist +// RUN: echo "fun:*foo*" >> %t.xray-attrlist +// RUN: echo "src:*xray-never-instrument.cpp" >> %t.xray-attrlist +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \ +// RUN: -fxray-never-instrument=%t.never-instrument -emit-llvm -o - %s \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 \ +// RUN: -fxray-attr-list=%t.xray-attrlist -emit-llvm -o - %s \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck %s + +void foo() {} + +[[clang::xray_always_instrument]] void bar() {} + +void baz() {} + +// CHECK: define void @_Z3foov() #[[NEVERATTR:[0-9]+]] { +// CHECK: define void @_Z3barv() #[[ALWAYSATTR:[0-9]+]] { +// CHECK: define void @_Z3bazv() #[[NEVERATTR:[0-9]+]] { +// CHECK: attributes #[[NEVERATTR]] = {{.*}} "function-instrument"="xray-never" {{.*}} +// CHECK: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}} + Index: llvm/docs/XRay.rst =================================================================== --- llvm/docs/XRay.rst +++ llvm/docs/XRay.rst @@ -117,6 +117,27 @@ ; ... } +Special Case File +----------------- + +Attributes can be imbued through the use of special case files instead of +adding them to the original source files. You can use this to mark certain +functions and classes to be never, always, or instrumented with first-argument +logging from a file. The file's format is described below: + +.. code-block:: bash + + # Comments are supported + [always] + fun:always_instrument + fun:log_arg1=arg1 # Log the first argument for the function + + [never] + fun:never_instrument + +These files can be provided through the ``-fxray-attr-list=`` flag to clang. +You may have multiple files loaded through multiple instances of the flag. + XRay Runtime Library -------------------- Index: llvm/docs/XRayExample.rst =================================================================== --- llvm/docs/XRayExample.rst +++ llvm/docs/XRayExample.rst @@ -178,22 +178,22 @@ To use this feature, you can define one file for the functions to always instrument, and another for functions to never instrument. The format of these files are exactly the same as the SanitizerLists files that control similar -things for the sanitizer implementations. For example, we can have two -different files like below: +things for the sanitizer implementations. For example: :: - # always-instrument.txt + # xray-attr-list.txt # always instrument functions that match the following filters: + [always] fun:main - # never-instrument.txt # never instrument functions that match the following filters: + [never] fun:__cxx_* -Given the above two files we can re-build by providing those two files as -arguments to clang as ``-fxray-always-instrument=always-instrument.txt`` or -``-fxray-never-instrument=never-instrument.txt``. +Given the file above we can re-build by providing it to the +``-fxray-attr-list=`` flag to clang. You can have multiple files, each defining +different sets of attribute sets, to be cobined into a single list by clang. The XRay stack tool -------------------