[compiler-rt] r325240 - Add Xray instrumentation support to FreeBSD

Kamil Rytarowski via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 15 06:17:16 PST 2018


Author: kamil
Date: Thu Feb 15 06:17:15 2018
New Revision: 325240

URL: http://llvm.org/viewvc/llvm-project?rev=325240&view=rev
Log:
Add Xray instrumentation support to FreeBSD

Summary:
- Enabling the build.
- Using assembly for the cpuid parts.
- Using thr_self FreeBSD call to get the thread id 

Patch by: David CARLIER

Reviewers: dberris, rnk, krytarowski

Reviewed By: dberris, krytarowski

Subscribers: emaste, stevecheckoway, nglevin, srhines, kubamracek, dberris, mgorny, krytarowski, llvm-commits, #sanitizers

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

Modified:
    compiler-rt/trunk/cmake/config-ix.cmake
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h
    compiler-rt/trunk/lib/xray/tests/CMakeLists.txt
    compiler-rt/trunk/lib/xray/tests/unit/fdr_logging_test.cc
    compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h
    compiler-rt/trunk/lib/xray/xray_flags.inc
    compiler-rt/trunk/lib/xray/xray_inmemory_log.cc
    compiler-rt/trunk/lib/xray/xray_x86_64.cc
    compiler-rt/trunk/lib/xray/xray_x86_64.inc
    compiler-rt/trunk/test/xray/lit.cfg

Modified: compiler-rt/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/config-ix.cmake?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/cmake/config-ix.cmake (original)
+++ compiler-rt/trunk/cmake/config-ix.cmake Thu Feb 15 06:17:15 2018
@@ -597,7 +597,7 @@ else()
 endif()
 
 if (COMPILER_RT_HAS_SANITIZER_COMMON AND XRAY_SUPPORTED_ARCH AND
-    OS_NAME MATCHES "Darwin|Linux")
+    OS_NAME MATCHES "Darwin|Linux|FreeBSD")
   set(COMPILER_RT_HAS_XRAY TRUE)
 else()
   set(COMPILER_RT_HAS_XRAY FALSE)

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_internal_defs.h Thu Feb 15 06:17:15 2018
@@ -98,7 +98,8 @@
 // We can use .preinit_array section on Linux to call sanitizer initialization
 // functions very early in the process startup (unless PIC macro is defined).
 // FIXME: do we have anything like this on Mac?
-#if SANITIZER_LINUX && !SANITIZER_ANDROID && !defined(PIC)
+#if ((SANITIZER_LINUX && !SANITIZER_ANDROID) || \
+  SANITIZER_FREEBSD) && !defined(PIC)
 # define SANITIZER_CAN_USE_PREINIT_ARRAY 1
 // Before Solaris 11.4, .preinit_array is fully supported only with GNU ld.
 // FIXME: Check for those conditions.

Modified: compiler-rt/trunk/lib/xray/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/tests/CMakeLists.txt?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/xray/tests/CMakeLists.txt Thu Feb 15 06:17:15 2018
@@ -15,6 +15,10 @@ set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH
 macro(add_xray_unittest testname)
   cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN})
   if(UNIX AND NOT APPLE)
+    set(CMAKE_DL_LIBS_INIT "")
+    foreach(lib ${CMAKE_DL_LIBS})
+      list(APPEND CMAKE_DL_LIBS_INIT -l${lib})
+    endforeach()
     foreach(arch ${XRAY_TEST_ARCH})
       set(TEST_OBJECTS)
       generate_compiler_rt_tests(TEST_OBJECTS
@@ -25,8 +29,7 @@ macro(add_xray_unittest testname)
         LINK_FLAGS -fxray-instrument
           ${TARGET_LINK_FLAGS}
           -lstdc++ -lm ${CMAKE_THREAD_LIBS_INIT}
-          -lpthread
-          -ldl -lrt)
+          ${CMAKE_DL_LIBS_INIT} -lrt)
       set_target_properties(XRayUnitTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
     endforeach()
   endif()

Modified: compiler-rt/trunk/lib/xray/tests/unit/fdr_logging_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/tests/unit/fdr_logging_test.cc?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/tests/unit/fdr_logging_test.cc (original)
+++ compiler-rt/trunk/lib/xray/tests/unit/fdr_logging_test.cc Thu Feb 15 06:17:15 2018
@@ -10,6 +10,7 @@
 // This file is a part of XRay, a function call tracing system.
 //
 //===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_common.h"
 #include "xray_fdr_logging.h"
 #include "gtest/gtest.h"
 
@@ -154,12 +155,12 @@ TEST(FDRLoggingTest, MultiThreadedCyclin
   // Now we want to create one thread, do some logging, then create another one,
   // in succession and making sure that we're able to get thread records from
   // the latest thread (effectively being able to recycle buffers).
-  std::array<pid_t, 2> Threads;
+  std::array<tid_t, 2> Threads;
   for (uint64_t I = 0; I < 2; ++I) {
     std::thread t{[I, &Threads] {
       fdrLoggingHandleArg0(I + 1, XRayEntryType::ENTRY);
       fdrLoggingHandleArg0(I + 1, XRayEntryType::EXIT);
-      Threads[I] = syscall(SYS_gettid);
+      Threads[I] = __sanitizer::GetTid();
     }};
     t.join();
   }
@@ -192,9 +193,9 @@ TEST(FDRLoggingTest, MultiThreadedCyclin
   ASSERT_EQ(MDR0.RecordKind,
             uint8_t(MetadataRecord::RecordKinds::BufferExtents));
   ASSERT_EQ(MDR1.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer));
-  pid_t Latest = 0;
-  memcpy(&Latest, MDR1.Data, sizeof(pid_t));
-  ASSERT_EQ(Latest, Threads[1]);
+  int32_t Latest = 0;
+  memcpy(&Latest, MDR1.Data, sizeof(int32_t));
+  ASSERT_EQ(Latest, static_cast<int32_t>(Threads[1]));
 }
 
 } // namespace

Modified: compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h (original)
+++ compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h Thu Feb 15 06:17:15 2018
@@ -54,7 +54,7 @@ namespace __xray_fdr_internal {
 
 /// Writes the new buffer record and wallclock time that begin a buffer for the
 /// current thread.
-static void writeNewBufferPreamble(pid_t Tid, timespec TS);
+static void writeNewBufferPreamble(tid_t Tid, timespec TS);
 
 /// Writes a Function Record to the buffer associated with the current thread.
 static void writeFunctionRecord(int FuncId, uint32_t TSCDelta,
@@ -185,7 +185,7 @@ public:
 
 } // namespace
 
-static void writeNewBufferPreamble(pid_t Tid,
+static void writeNewBufferPreamble(tid_t Tid,
                                    timespec TS) XRAY_NEVER_INSTRUMENT {
   static constexpr int InitRecordsCount = 2;
   auto &TLD = getThreadLocalData();
@@ -195,11 +195,12 @@ static void writeNewBufferPreamble(pid_t
     // buffer, associated with a particular thread, with a new CPU.  For the
     // data, we have 15 bytes to squeeze as much information as we can.  At this
     // point we only write down the following bytes:
-    //   - Thread ID (pid_t, 4 bytes)
+    //   - Thread ID (tid_t, cast to 4 bytes type due to Darwin being 8 bytes)
     auto &NewBuffer = Metadata[0];
     NewBuffer.Type = uint8_t(RecordType::Metadata);
     NewBuffer.RecordKind = uint8_t(MetadataRecord::RecordKinds::NewBuffer);
-    std::memcpy(&NewBuffer.Data, &Tid, sizeof(pid_t));
+    int32_t tid = static_cast<int32_t>(Tid);
+    std::memcpy(&NewBuffer.Data, &tid, sizeof(tid));
   }
 
   // Also write the WalltimeMarker record.
@@ -236,7 +237,7 @@ inline void setupNewBuffer(int (*wall_cl
   auto &TLD = getThreadLocalData();
   auto &B = TLD.Buffer;
   TLD.RecordPtr = static_cast<char *>(B.Data);
-  pid_t Tid = syscall(SYS_gettid);
+  tid_t Tid = __sanitizer::GetTid();
   timespec TS{0, 0};
   // This is typically clock_gettime, but callers have injection ability.
   wall_clock_reader(CLOCK_MONOTONIC, &TS);

Modified: compiler-rt/trunk/lib/xray/xray_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.inc?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_flags.inc (original)
+++ compiler-rt/trunk/lib/xray/xray_flags.inc Thu Feb 15 06:17:15 2018
@@ -31,7 +31,7 @@ XRAY_FLAG(int, xray_naive_log_func_durat
           "microseconds than this threshold.")
 XRAY_FLAG(int, xray_naive_log_max_stack_depth, 64,
           "Naive logging will keep track of at most this deep a call stack, "
-          "any more and the recordings will be droppped.")
+          "any more and the recordings will be dropped.")
 XRAY_FLAG(int, xray_naive_log_thread_buffer_size, 1024,
           "The number of entries to keep on a per-thread buffer.")
 

Modified: compiler-rt/trunk/lib/xray/xray_inmemory_log.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_inmemory_log.cc?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_inmemory_log.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_inmemory_log.cc Thu Feb 15 06:17:15 2018
@@ -60,7 +60,7 @@ struct alignas(64) ThreadLocalData {
   size_t StackSize = 0;
   size_t StackEntries = 0;
   int Fd = -1;
-  pid_t TID = 0;
+  tid_t TID = 0;
 };
 
 static pthread_key_t PThreadKey;

Modified: compiler-rt/trunk/lib/xray/xray_x86_64.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_x86_64.cc?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_x86_64.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_x86_64.cc Thu Feb 15 06:17:15 2018
@@ -3,6 +3,10 @@
 #include "xray_defs.h"
 #include "xray_interface_internal.h"
 
+#if SANITIZER_FREEBSD
+#include <sys/sysctl.h>
+#endif
+
 #include <atomic>
 #include <cstdint>
 #include <errno.h>
@@ -14,6 +18,7 @@
 
 namespace __xray {
 
+#if SANITIZER_LINUX
 static std::pair<ssize_t, bool>
 retryingReadSome(int Fd, char *Begin, char *End) XRAY_NEVER_INSTRUMENT {
   auto BytesToRead = std::distance(Begin, End);
@@ -71,6 +76,24 @@ uint64_t getTSCFrequency() XRAY_NEVER_IN
   }
   return TSCFrequency == -1 ? 0 : static_cast<uint64_t>(TSCFrequency);
 }
+#elif SANITIZER_FREEBSD
+uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
+    long long TSCFrequency = -1;
+    size_t tscfreqsz = sizeof(TSCFrequency);
+
+    if (sysctlbyname("machdep.tsc_freq", &TSCFrequency, &tscfreqsz,
+        NULL, 0) != -1) {
+        return static_cast<uint64_t>(TSCFrequency);
+    } else {
+      Report("Unable to determine CPU frequency for TSC accounting.\n");
+    }
+
+    return 0;
+    
+}
+#else
+#error "Platform not supported"
+#endif
 
 static constexpr uint8_t CallOpCode = 0xe8;
 static constexpr uint16_t MovR10Seq = 0xba41;
@@ -259,7 +282,8 @@ bool probeRequiredCPUFeatures() XRAY_NEV
   // We check whether rdtscp support is enabled. According to the x86_64 manual,
   // level should be set at 0x80000001, and we should have a look at bit 27 in
   // EDX. That's 0x8000000 (or 1u << 27).
-  __get_cpuid(0x80000001, &EAX, &EBX, &ECX, &EDX);
+  __asm__ __volatile__("cpuid" : "=a"(EAX), "=b"(EBX), "=c"(ECX), "=d"(EDX)
+    : "0"(0x80000001));
   if (!(EDX & (1u << 27))) {
     Report("Missing rdtscp support.\n");
     return false;

Modified: compiler-rt/trunk/lib/xray/xray_x86_64.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_x86_64.inc?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_x86_64.inc (original)
+++ compiler-rt/trunk/lib/xray/xray_x86_64.inc Thu Feb 15 06:17:15 2018
@@ -21,9 +21,10 @@ namespace __xray {
 
 ALWAYS_INLINE uint64_t readTSC(uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
   unsigned LongCPU;
-  uint64_t TSC = __rdtscp(&LongCPU);
+  unsigned long Rax, Rdx;
+  __asm__ __volatile__("rdtscp\n" : "=a"(Rax), "=d"(Rdx), "=c"(LongCPU) ::);
   CPU = LongCPU;
-  return TSC;
+  return (Rdx << 32) + Rax;
 }
 
 uint64_t getTSCFrequency();

Modified: compiler-rt/trunk/test/xray/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/lit.cfg?rev=325240&r1=325239&r2=325240&view=diff
==============================================================================
--- compiler-rt/trunk/test/xray/lit.cfg (original)
+++ compiler-rt/trunk/test/xray/lit.cfg Thu Feb 15 06:17:15 2018
@@ -20,6 +20,13 @@ def build_invocation(compile_flags):
 llvm_xray = os.path.join(config.llvm_tools_dir, 'llvm-xray')
 
 # Setup substitutions.
+xraylib_flags = '-lm -pthread -lrt'
+if config.host_os == 'Linux':
+  xraylib_flags += ' -ldl'
+
+xraylib_flags += ' -L%s -Wl,-whole-archive -lclang_rt.xray-%s '
+'-Wl,-no-whole-archive'
+  
 config.substitutions.append(
     ('%clang ', build_invocation([config.target_cflags])))
 config.substitutions.append(
@@ -33,14 +40,13 @@ config.substitutions.append(
     ('%llvm_xray', llvm_xray))
 config.substitutions.append(
     ('%xraylib',
-        ('-lm -lpthread -ldl -lrt -L%s '
-         '-Wl,-whole-archive -lclang_rt.xray-%s -Wl,-no-whole-archive')
+        (xraylib_flags)
         % (config.compiler_rt_libdir, config.host_arch)))
 
 # Default test suffixes.
 config.suffixes = ['.c', '.cc', '.cpp']
 
-if config.host_os not in ['Linux']:
+if config.host_os not in ['Linux', 'FreeBSD']:
   config.unsupported = True
 elif '64' not in config.host_arch:
   if 'arm' in config.host_arch:




More information about the llvm-commits mailing list