[compiler-rt] r297000 - [XRay] [compiler-rt] Allow logging the first argument of a function call.

Dean Michael Berris via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 5 23:25:41 PST 2017


Author: dberris
Date: Mon Mar  6 01:25:41 2017
New Revision: 297000

URL: http://llvm.org/viewvc/llvm-project?rev=297000&view=rev
Log:
[XRay] [compiler-rt] Allow logging the first argument of a function call.

Summary:
Functions with the LOG_ARGS_ENTRY sled kind at their beginning will be handled
in a way to (optionally) pass their first call argument to your logging handler.

For practical and performance reasons, only the first argument is supported, and
only up to 64 bits.

Reviewers: javed.absar, dberris

Reviewed By: dberris

Subscribers: llvm-commits

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

Added:
    compiler-rt/trunk/test/xray/TestCases/Linux/arg1-logger.cc
Modified:
    compiler-rt/trunk/include/xray/xray_interface.h
    compiler-rt/trunk/lib/xray/xray_AArch64.cc
    compiler-rt/trunk/lib/xray/xray_arm.cc
    compiler-rt/trunk/lib/xray/xray_fdr_logging.cc
    compiler-rt/trunk/lib/xray/xray_interface.cc
    compiler-rt/trunk/lib/xray/xray_interface_internal.h
    compiler-rt/trunk/lib/xray/xray_trampoline_x86_64.S
    compiler-rt/trunk/lib/xray/xray_x86_64.cc

Modified: compiler-rt/trunk/include/xray/xray_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/xray/xray_interface.h?rev=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/include/xray/xray_interface.h (original)
+++ compiler-rt/trunk/include/xray/xray_interface.h Mon Mar  6 01:25:41 2017
@@ -18,7 +18,13 @@
 
 extern "C" {
 
-enum XRayEntryType { ENTRY = 0, EXIT = 1, TAIL = 2 };
+// Synchronize this with AsmPrinter::SledKind in LLVM.
+enum XRayEntryType {
+  ENTRY = 0,
+  EXIT = 1,
+  TAIL = 2,
+  LOG_ARGS_ENTRY = 3,
+};
 
 // Provide a function to invoke for when instrumentation points are hit. This is
 // a user-visible control surface that overrides the default implementation. The
@@ -60,6 +66,17 @@ extern XRayPatchingStatus __xray_patch()
 // Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
 // result values.
 extern XRayPatchingStatus __xray_unpatch();
+
+// Use XRay to log the first argument of each (instrumented) function call.
+// When this function exits, all threads will have observed the effect and
+// start logging their subsequent affected function calls (if patched).
+//
+// Returns 1 on success, 0 on error.
+extern int __xray_set_handler_arg1(void (*)(int32_t, XRayEntryType, uint64_t));
+
+// Disables the XRay handler used to log first arguments of function calls.
+// Returns 1 on success, 0 on error.
+extern int __xray_remove_handler_arg1();
 }
 
 #endif

Modified: compiler-rt/trunk/lib/xray/xray_AArch64.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_AArch64.cc?rev=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_AArch64.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_AArch64.cc Mon Mar  6 01:25:41 2017
@@ -92,8 +92,9 @@ inline static bool patchSled(const bool
 }
 
 bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
-                        const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
-  return patchSled(Enable, FuncId, Sled, __xray_FunctionEntry);
+                        const XRaySledEntry &Sled,
+                        void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {
+  return patchSled(Enable, FuncId, Sled, Trampoline);
 }
 
 bool patchFunctionExit(const bool Enable, const uint32_t FuncId,
@@ -110,3 +111,7 @@ bool patchFunctionTailExit(const bool En
 bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
 
 } // namespace __xray
+
+extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
+  // FIXME: this will have to be implemented in the trampoline assembly file
+}

Modified: compiler-rt/trunk/lib/xray/xray_arm.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_arm.cc?rev=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_arm.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_arm.cc Mon Mar  6 01:25:41 2017
@@ -128,8 +128,9 @@ inline static bool patchSled(const bool
 }
 
 bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
-                        const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
-  return patchSled(Enable, FuncId, Sled, __xray_FunctionEntry);
+                        const XRaySledEntry &Sled,
+                        void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {
+  return patchSled(Enable, FuncId, Sled, Trampoline);
 }
 
 bool patchFunctionExit(const bool Enable, const uint32_t FuncId,
@@ -146,3 +147,7 @@ bool patchFunctionTailExit(const bool En
 bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
 
 } // namespace __xray
+
+extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
+  // FIXME: this will have to be implemented in the trampoline assembly file
+}

Modified: compiler-rt/trunk/lib/xray/xray_fdr_logging.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_fdr_logging.cc?rev=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_fdr_logging.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_fdr_logging.cc Mon Mar  6 01:25:41 2017
@@ -494,6 +494,7 @@ void fdrLoggingHandleArg0(int32_t FuncId
 
   switch (Entry) {
   case XRayEntryType::ENTRY:
+  case XRayEntryType::LOG_ARGS_ENTRY:
     FuncRecord.RecordKind = uint8_t(FunctionRecord::RecordKinds::FunctionEnter);
     break;
   case XRayEntryType::EXIT:

Modified: compiler-rt/trunk/lib/xray/xray_interface.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface.cc?rev=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_interface.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_interface.cc Mon Mar  6 01:25:41 2017
@@ -48,6 +48,9 @@ static const int16_t cSledLength = 8;
 // This is the function to call when we encounter the entry or exit sleds.
 std::atomic<void (*)(int32_t, XRayEntryType)> XRayPatchedFunction{nullptr};
 
+// This is the function to call from the arg1-enabled sleds/trampolines.
+std::atomic<void (*)(int32_t, XRayEntryType, uint64_t)> XRayArgLogger{nullptr};
+
 // MProtectHelper is an RAII wrapper for calls to mprotect(...) that will undo
 // any successful mprotect(...) changes. This is used to make a page writeable
 // and executable, and upon destruction if it was successful in doing so returns
@@ -185,7 +188,7 @@ XRayPatchingStatus controlPatching(bool
     bool Success = false;
     switch (Sled.Kind) {
     case XRayEntryType::ENTRY:
-      Success = patchFunctionEntry(Enable, FuncId, Sled);
+      Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry);
       break;
     case XRayEntryType::EXIT:
       Success = patchFunctionExit(Enable, FuncId, Sled);
@@ -193,6 +196,9 @@ XRayPatchingStatus controlPatching(bool
     case XRayEntryType::TAIL:
       Success = patchFunctionTailExit(Enable, FuncId, Sled);
       break;
+    case XRayEntryType::LOG_ARGS_ENTRY:
+      Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry);
+      break;
     default:
       Report("Unsupported sled kind: %d\n", int(Sled.Kind));
       continue;
@@ -211,3 +217,16 @@ XRayPatchingStatus __xray_patch() XRAY_N
 XRayPatchingStatus __xray_unpatch() XRAY_NEVER_INSTRUMENT {
   return controlPatching(false);
 }
+
+int __xray_set_handler_arg1(void (*Handler)(int32_t, XRayEntryType, uint64_t))
+{
+  if (!XRayInitialized.load(std::memory_order_acquire)) {
+    return 0;
+  }
+  // A relaxed write might not be visible even if the current thread gets
+  // scheduled on a different CPU/NUMA node.  We need to wait for everyone to
+  // have this handler installed for consistency of collected data across CPUs.
+  XRayArgLogger.store(Handler, std::memory_order_release);
+  return 1;
+}
+int __xray_remove_handler_arg1() { return __xray_set_handler_arg1(nullptr); }

Modified: compiler-rt/trunk/lib/xray/xray_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface_internal.h?rev=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_interface_internal.h (original)
+++ compiler-rt/trunk/lib/xray/xray_interface_internal.h Mon Mar  6 01:25:41 2017
@@ -49,7 +49,7 @@ struct XRaySledMap {
 };
 
 bool patchFunctionEntry(bool Enable, uint32_t FuncId,
-                        const XRaySledEntry &Sled);
+                        const XRaySledEntry &Sled, void (*Trampoline)());
 bool patchFunctionExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled);
 bool patchFunctionTailExit(bool Enable, uint32_t FuncId,
                            const XRaySledEntry &Sled);
@@ -62,6 +62,7 @@ extern "C" {
 extern void __xray_FunctionEntry();
 extern void __xray_FunctionExit();
 extern void __xray_FunctionTailExit();
+extern void __xray_ArgLoggerEntry();
 }
 
 #endif

Modified: compiler-rt/trunk/lib/xray/xray_trampoline_x86_64.S
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_trampoline_x86_64.S?rev=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_trampoline_x86_64.S (original)
+++ compiler-rt/trunk/lib/xray/xray_trampoline_x86_64.S Mon Mar  6 01:25:41 2017
@@ -53,6 +53,9 @@
 
 	.text
 	.file "xray_trampoline_x86.S"
+
+//===----------------------------------------------------------------------===//
+
 	.globl __xray_FunctionEntry
 	.align 16, 0x90
 	.type __xray_FunctionEntry, at function
@@ -81,6 +84,8 @@ __xray_FunctionEntry:
 	.size __xray_FunctionEntry, .Ltmp1-__xray_FunctionEntry
 	.cfi_endproc
 
+//===----------------------------------------------------------------------===//
+
 	.globl __xray_FunctionExit
 	.align 16, 0x90
 	.type __xray_FunctionExit, at function
@@ -117,6 +122,8 @@ __xray_FunctionExit:
 	.size __xray_FunctionExit, .Ltmp3-__xray_FunctionExit
 	.cfi_endproc
 
+//===----------------------------------------------------------------------===//
+
 	.global __xray_FunctionTailExit
 	.align 16, 0x90
 	.type __xray_FunctionTailExit, at function
@@ -145,3 +152,39 @@ __xray_FunctionTailExit:
 .Ltmp5:
 	.size __xray_FunctionTailExit, .Ltmp5-__xray_FunctionTailExit
 	.cfi_endproc
+
+//===----------------------------------------------------------------------===//
+
+	.globl __xray_ArgLoggerEntry
+	.align 16, 0x90
+	.type __xray_ArgLoggerEntry, at function
+__xray_ArgLoggerEntry:
+	.cfi_startproc
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	SAVE_REGISTERS
+
+	// Again, these function pointer loads must be atomic; MOV is fine.
+	movq	_ZN6__xray13XRayArgLoggerE(%rip), %rax
+	testq	%rax, %rax
+	jne	.Larg1entryLog
+
+	// If [arg1 logging handler] not set, defer to no-arg logging.
+	movq	_ZN6__xray19XRayPatchedFunctionE(%rip), %rax
+	testq	%rax, %rax
+	je	.Larg1entryFail
+
+.Larg1entryLog:
+	movq	%rdi, %rdx	// first argument will become the third
+	xorq	%rsi, %rsi	// XRayEntryType::ENTRY into the second
+	movl	%r10d, %edi	// 32-bit function ID becomes the first
+	callq	*%rax
+
+.Larg1entryFail:
+	RESTORE_REGISTERS
+	popq	%rbp
+	retq
+
+.Larg1entryEnd:
+	.size __xray_ArgLoggerEntry, .Larg1entryEnd-__xray_ArgLoggerEntry
+	.cfi_endproc

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=297000&r1=296999&r2=297000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_x86_64.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_x86_64.cc Mon Mar  6 01:25:41 2017
@@ -82,7 +82,8 @@ static constexpr int64_t MinOffset{std::
 static constexpr int64_t MaxOffset{std::numeric_limits<int32_t>::max()};
 
 bool patchFunctionEntry(const bool Enable, const uint32_t FuncId,
-                        const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
+                        const XRaySledEntry &Sled,
+                        void (*Trampoline)()) XRAY_NEVER_INSTRUMENT {
   // Here we do the dance of replacing the following sled:
   //
   // xray_sled_n:
@@ -103,13 +104,12 @@ bool patchFunctionEntry(const bool Enabl
   // 4. Do an atomic write over the jmp instruction for the "mov r10d"
   // opcode and first operand.
   //
-  // Prerequisite is to compute the relative offset to the
-  // __xray_FunctionEntry function's address.
-  int64_t TrampolineOffset = reinterpret_cast<int64_t>(__xray_FunctionEntry) -
+  // Prerequisite is to compute the relative offset to the trampoline's address.
+  int64_t TrampolineOffset = reinterpret_cast<int64_t>(Trampoline) -
                              (static_cast<int64_t>(Sled.Address) + 11);
   if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {
     Report("XRay Entry trampoline (%p) too far from sled (%p)\n",
-           __xray_FunctionEntry, reinterpret_cast<void *>(Sled.Address));
+           Trampoline, reinterpret_cast<void *>(Sled.Address));
     return false;
   }
   if (Enable) {

Added: compiler-rt/trunk/test/xray/TestCases/Linux/arg1-logger.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/TestCases/Linux/arg1-logger.cc?rev=297000&view=auto
==============================================================================
--- compiler-rt/trunk/test/xray/TestCases/Linux/arg1-logger.cc (added)
+++ compiler-rt/trunk/test/xray/TestCases/Linux/arg1-logger.cc Mon Mar  6 01:25:41 2017
@@ -0,0 +1,41 @@
+// Check that we can get the first function argument logged
+// using a custom logging function.
+//
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s
+//
+// After all that, clean up the XRay log file.
+//
+// RUN: rm arg1-logger-*
+//
+// At the time of writing, the ARM trampolines weren't written yet.
+// XFAIL: arm || aarch64
+
+#include "xray/xray_interface.h"
+
+#include <cinttypes>
+#include <cstdio>
+
+void arg1logger(int32_t fn, XRayEntryType t, uint64_t a1) {
+  printf("Arg1: %" PRIx64 ", XRayEntryType %u\n", a1, t);
+}
+
+[[clang::xray_always_instrument, clang::xray_log_args(1)]] void foo(void *) {}
+
+int main() {
+  // CHECK: XRay: Log file in 'arg1-logger-{{.*}}'
+
+  __xray_set_handler_arg1(arg1logger);
+  foo(nullptr);
+  // CHECK: Arg1: 0, XRayEntryType 0
+
+  __xray_remove_handler_arg1();
+  foo((void *) 0xBADC0DE);
+  // nothing expected to see here
+
+  __xray_set_handler_arg1(arg1logger);
+  foo((void *) 0xDEADBEEFCAFE);
+  // CHECK-NEXT: Arg1: deadbeefcafe, XRayEntryType 0
+  foo((void *) -1);
+  // CHECK-NEXT: Arg1: ffffffffffffffff, XRayEntryType 0
+}




More information about the llvm-commits mailing list