[XRay][clang+compiler-rt] Support build-time mode selection
authorDean Michael Berris <dberris@google.com>
Wed, 11 Apr 2018 01:28:25 +0000 (01:28 +0000)
committerDean Michael Berris <dberris@google.com>
Wed, 11 Apr 2018 01:28:25 +0000 (01:28 +0000)
Summary:
This patch implements the `-fxray-modes=` flag which allows users
building with XRay instrumentation to decide which modes to pre-package
into the binary being linked. The default is the status quo, which will
link all the available modes.

For this to work we're also breaking apart the mode implementations
(xray-fdr and xray-basic) from the main xray runtime. This gives more
granular control of which modes are pre-packaged, and picked from
clang's invocation.

This fixes llvm.org/PR37066.

Note that in the future, we may change the default for clang to only
contain the profiling implementation under development in D44620, when
that implementation is ready.

Reviewers: echristo, eizan, chandlerc

Reviewed By: echristo

Subscribers: mgorny, mgrang, cfe-commits, llvm-commits

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

llvm-svn: 329772

clang/include/clang/Driver/Options.td
clang/include/clang/Driver/XRayArgs.h
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Driver/XRayArgs.cpp
clang/test/Driver/XRay/xray-mode-flags.cpp [new file with mode: 0644]
compiler-rt/lib/xray/CMakeLists.txt
compiler-rt/lib/xray/tests/CMakeLists.txt

index a08003b..e2c503b 100644 (file)
@@ -1108,6 +1108,10 @@ def fxray_attr_list :
   JoinedOrSeparate<["-"], "fxray-attr-list=">,
   Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Filename defining the list of functions/types for imbuing XRay attributes.">;
+def fxray_modes :
+  JoinedOrSeparate<["-"], "fxray-modes=">,
+  Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"List of modes to link in by default into XRay instrumented binaries.">;
 
 def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents">, Group<f_Group>,
   Flags<[CC1Option]>,
index 535c030..e4a573e 100644 (file)
@@ -23,6 +23,7 @@ class XRayArgs {
   std::vector<std::string> NeverInstrumentFiles;
   std::vector<std::string> AttrListFiles;
   std::vector<std::string> ExtraDeps;
+  std::vector<std::string> Modes;
   bool XRayInstrument = false;
   int InstructionThreshold = 200;
   bool XRayAlwaysEmitCustomEvents = false;
@@ -35,6 +36,8 @@ public:
                llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
 
   bool needsXRayRt() const { return XRayInstrument && XRayRT; }
+  llvm::ArrayRef<std::string> modeList() const { return Modes; }
+
 };
 
 } // namespace driver
index 6a7f817..dac81ee 100644 (file)
@@ -713,6 +713,8 @@ bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringLis
   if (TC.getXRayArgs().needsXRayRt()) {
     CmdArgs.push_back("-whole-archive");
     CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray", false));
+    for (const auto &Mode : TC.getXRayArgs().modeList())
+      CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode, false));
     CmdArgs.push_back("-no-whole-archive");
     return true;
   }
index cc109d1..bfc5053 100644 (file)
@@ -27,6 +27,7 @@ namespace {
 constexpr char XRayInstrumentOption[] = "-fxray-instrument";
 constexpr char XRayInstructionThresholdOption[] =
     "-fxray-instruction-threshold=";
+constexpr const char *const XRaySupportedModes[] = {"xray-fdr", "xray-basic"};
 } // namespace
 
 XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
@@ -51,13 +52,14 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
       }
     } else if (Triple.getOS() == llvm::Triple::FreeBSD ||
                Triple.getOS() == llvm::Triple::OpenBSD) {
-        if (Triple.getArch() != llvm::Triple::x86_64) {
-          D.Diag(diag::err_drv_clang_unsupported)
-              << (std::string(XRayInstrumentOption) + " on " + Triple.str());
-        }
+      if (Triple.getArch() != llvm::Triple::x86_64) {
+        D.Diag(diag::err_drv_clang_unsupported)
+            << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+      }
     } else {
       D.Diag(diag::err_drv_clang_unsupported)
-          << (std::string(XRayInstrumentOption) + " on non-supported target OS");
+          << (std::string(XRayInstrumentOption) +
+              " on non-supported target OS");
     }
     XRayInstrument = true;
     if (const Arg *A =
@@ -108,6 +110,33 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
       } else
         D.Diag(clang::diag::err_drv_no_such_file) << Filename;
     }
+
+    // Get the list of modes we want to support.
+    auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
+    if (SpecifiedModes.empty())
+      llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
+    else
+      for (const auto &Arg : SpecifiedModes) {
+        if (Arg == "none") {
+          Modes.clear();
+          break;
+        }
+        if (Arg == "all") {
+          Modes.clear();
+          llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
+          break;
+        }
+
+        // Parse CSV values for -fxray-modes=...
+        llvm::SmallVector<StringRef, 2> ModeParts;
+        llvm::SplitString(Arg, ModeParts, ",");
+        for (const auto &M : ModeParts)
+          Modes.push_back(M);
+      }
+
+    // Then we want to sort and unique the modes we've collected.
+    std::sort(Modes.begin(), Modes.end());
+    Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
   }
 }
 
@@ -136,7 +165,7 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
     CmdArgs.push_back(Args.MakeArgString(NeverInstrumentOpt));
   }
 
-  for (const auto&AttrFile : AttrListFiles) {
+  for (const auto& AttrFile : AttrListFiles) {
     SmallString<64> AttrListFileOpt("-fxray-attr-list=");
     AttrListFileOpt += AttrFile;
     CmdArgs.push_back(Args.MakeArgString(AttrListFileOpt));
diff --git a/clang/test/Driver/XRay/xray-mode-flags.cpp b/clang/test/Driver/XRay/xray-mode-flags.cpp
new file mode 100644 (file)
index 0000000..b592e15
--- /dev/null
@@ -0,0 +1,21 @@
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=xray-fdr %s -### \
+// RUN:     2>&1 | FileCheck --check-prefix FDR %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=xray-basic %s \
+// RUN:     -### 2>&1 | FileCheck --check-prefix BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=all -### %s \
+// RUN:     2>&1 | FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument \
+// RUN:     -fxray-modes=xray-fdr,xray-basic -### %s 2>&1 | \
+// RUN:     FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument \
+// RUN:     -fxray-modes=xray-fdr -fxray-modes=xray-basic -### %s 2>&1 | \
+// RUN:     FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -### %s \
+// RUN:     2>&1 | FileCheck --check-prefixes FDR,BASIC %s
+// RUN: %clang -v -o /dev/null -fxray-instrument -fxray-modes=none -### %s \
+// RUN:     2>&1 | FileCheck --check-prefixes NONE %s
+
+// BASIC: libclang_rt.xray-basic
+// FDR: libclang_rt.xray-fdr
+// NONE-NOT: libclang_rt.xray-basic
+// NONE-NOT: libclang_rt.xray-fdr
index 5547600..7f5683d 100644 (file)
@@ -2,15 +2,20 @@
 
 # XRay runtime library implementation files.
 set(XRAY_SOURCES
-  xray_inmemory_log.cc
   xray_init.cc
   xray_flags.cc
   xray_interface.cc
-  xray_buffer_queue.cc
   xray_log_interface.cc
-  xray_fdr_logging.cc
   xray_utils.cc)
 
+# XRay mode implementation files.
+set(XRAY_FDR_MODE_SOURCES
+  xray_buffer_queue.cc
+  xray_fdr_logging.cc)
+
+set(XRAY_BASIC_MODE_SOURCES
+  xray_inmemory_log.cc)
+
 set(x86_64_SOURCES
     xray_x86_64.cc
     xray_trampoline_x86_64.S)
@@ -60,7 +65,6 @@ append_list_if(
 add_compiler_rt_component(xray)
 
 set(XRAY_COMMON_RUNTIME_OBJECT_LIBS
-    RTXray
     RTSanitizerCommon
     RTSanitizerCommonLibc)
 
@@ -77,6 +81,18 @@ if (APPLE)
     SOURCES ${x86_64_SOURCES}
     CFLAGS ${XRAY_CFLAGS}
     DEFS ${XRAY_COMMON_DEFINITIONS})
+  add_compiler_rt_object_libraries(RTXrayFDR
+    OS ${XRAY_SUPPORTED_OS}
+    ARCHS ${XRAY_SUPPORTED_ARCH}
+    SOURCES ${XRAY_FDR_MODE_SOURCES}
+    CFLAGS ${XRAY_CFLAGS}
+    DEFS ${XRAY_COMMON_DEFINITIONS})
+  add_compiler_rt_object_libraries(RTXrayBASIC
+    OS ${XRAY_SUPPORTED_OS}
+    ARCHS ${XRAY_SUPPORTED_ARCH}
+    SOURCES ${XRAY_BASIC_MODE_SOURCES}
+    CFLAGS ${XRAY_CFLAGS}
+    DEFS ${XRAY_COMMON_DEFINITIONS})
 
   # We only support running on osx for now.
   add_compiler_rt_runtime(clang_rt.xray
@@ -91,20 +107,64 @@ if (APPLE)
     LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
     LINK_LIBS ${XRAY_LINK_LIBS}
     PARENT_TARGET xray)
+  add_compiler_rt_runtime(clang_rt.xray-fdr
+    STATIC
+    OS ${XRAY_SUPPORTED_OS}
+    ARCHS ${XRAY_SUPPORTED_ARCH}
+    OBJECT_LIBS RTXrayFDR
+    CFLAGS ${XRAY_CFLAGS}
+    DEFS ${XRAY_COMMON_DEFINITIONS}
+    LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
+    LINK_LIBS ${XRAY_LINK_LIBS}
+    PARENT_TARGET xray)
+  add_compiler_rt_runtime(clang_rt.xray-basic
+    STATIC
+    OS ${XRAY_SUPPORTED_OS}
+    ARCHS ${XRAY_SUPPORTED_ARCH}
+    OBJECT_LIBS RTXrayBASIC
+    CFLAGS ${XRAY_CFLAGS}
+    DEFS ${XRAY_COMMON_DEFINITIONS}
+    LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
+    LINK_LIBS ${XRAY_LINK_LIBS}
+    PARENT_TARGET xray)
 else()
 foreach(arch ${XRAY_SUPPORTED_ARCH})
   if(CAN_TARGET_${arch})
     add_compiler_rt_object_libraries(RTXray
       ARCHS ${arch}
-      SOURCES ${XRAY_SOURCES} CFLAGS ${XRAY_CFLAGS}
+      SOURCES ${XRAY_SOURCES} ${${arch}_SOURCES} CFLAGS ${XRAY_CFLAGS}
       DEFS ${XRAY_COMMON_DEFINITIONS})
+    add_compiler_rt_object_libraries(RTXrayFDR
+      ARCHS ${arch}
+      SOURCES ${XRAY_FDR_MODE_SOURCES} CFLAGS ${XRAY_CFLAGS}
+      DEFS ${XRAY_COMMON_DEFINITIONS})
+    add_compiler_rt_object_libraries(RTXrayBASIC
+      ARCHS ${arch}
+      SOURCES ${XRAY_BASIC_MODE_SOURCES} CFLAGS ${XRAY_CFLAGS}
+      DEFS ${XRAY_COMMON_DEFINITIONS})
+
     add_compiler_rt_runtime(clang_rt.xray
      STATIC
      ARCHS ${arch}
-     SOURCES ${${arch}_SOURCES}
      CFLAGS ${XRAY_CFLAGS}
      DEFS ${XRAY_COMMON_DEFINITIONS}
-     OBJECT_LIBS ${XRAY_COMMON_RUNTIME_OBJECT_LIBS}
+     OBJECT_LIBS ${XRAY_COMMON_RUNTIME_OBJECT_LIBS} RTXray
+     PARENT_TARGET xray)
+   # FDR Mode runtime
+   add_compiler_rt_runtime(clang_rt.xray-fdr
+     STATIC
+     ARCHS ${arch}
+     CFLAGS ${XRAY_CFLAGS}
+     DEFS ${XRAY_COMMON_DEFINITIONS}
+     OBJECT_LIBS RTXrayFDR
+     PARENT_TARGET xray)
+   # Basic Mode runtime
+   add_compiler_rt_runtime(clang_rt.xray-basic
+     STATIC
+     ARCHS ${arch}
+     CFLAGS ${XRAY_CFLAGS}
+     DEFS ${XRAY_COMMON_DEFINITIONS}
+     OBJECT_LIBS RTXrayBASIC
      PARENT_TARGET xray)
   endif()
 endforeach()
index b73c15b..0d419a1 100644 (file)
@@ -17,6 +17,22 @@ set(XRAY_UNITTEST_CFLAGS
   -I${COMPILER_RT_SOURCE_DIR}/lib/xray
   -I${COMPILER_RT_SOURCE_DIR}/lib)
 
+macro(add_xray_lib library)
+  add_library(${library} STATIC ${ARGN})
+  set_target_properties(${library} PROPERTIES
+    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+    FOLDER "Compiler-RT Runtime tests")
+endmacro()
+
+function(get_xray_lib_for_arch arch lib)
+  if(APPLE)
+    set(tgt_name "RTXRay.test.osx")
+  else()
+    set(tgt_name "RTXRay.test.${arch}")
+  endif()
+  set(${lib} "${tgt_name}" PARENT_SCOPE)
+endfunction()
+
 set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH})
 macro(add_xray_unittest testname)
   cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN})
@@ -27,6 +43,7 @@ macro(add_xray_unittest testname)
     endforeach()
     foreach(arch ${XRAY_TEST_ARCH})
       set(TEST_OBJECTS)
+      get_xray_lib_for_arch(${arch} XRAY_RUNTIME_LIBS)
       generate_compiler_rt_tests(TEST_OBJECTS
         XRayUnitTests "${testname}-${arch}-Test" "${arch}"
         SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE}
@@ -35,17 +52,25 @@ macro(add_xray_unittest testname)
         # the build/test cycle.
         COMPILE_DEPS ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE}
         ${XRAY_HEADERS} ${XRAY_IMPL_FILES}
-        DEPS gtest xray llvm-xray
+        RUNTIME "${XRAY_RUNTIME_LIBS}"
+        DEPS gtest xray
         CFLAGS ${XRAY_UNITTEST_CFLAGS}
-        LINK_FLAGS -fxray-instrument
-          ${TARGET_LINK_FLAGS}
+        LINK_FLAGS ${TARGET_LINK_FLAGS}
           -lstdc++ -lm ${CMAKE_THREAD_LIBS_INIT}
           ${CMAKE_DL_LIBS_INIT} -lrt)
-      set_target_properties(XRayUnitTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+      set_target_properties(XRayUnitTests
+        PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
     endforeach()
   endif()
 endmacro()
 
 if(COMPILER_RT_CAN_EXECUTE_TESTS)
+  foreach(arch ${XRAY_SUPPORTED_ARCH})
+    add_xray_lib("RTXRay.test.${arch}"
+      $<TARGET_OBJECTS:RTXray.${arch}>
+      $<TARGET_OBJECTS:RTXrayFDR.${arch}>
+      $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
+      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
+  endforeach()
   add_subdirectory(unit)
 endif()