[compiler-rt] Reapply "[compiler-rt][XRay] Make xray_interface.h C compliant" (PR #141728)

Jan André Reuter via llvm-commits llvm-commits at lists.llvm.org
Wed May 28 01:53:50 PDT 2025


https://github.com/Thyre updated https://github.com/llvm/llvm-project/pull/141728

>From 20a0363ebc1bbd363327d001fe89452f4df1c999 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Andr=C3=A9=20Reuter?= <j.reuter at fz-juelich.de>
Date: Thu, 15 May 2025 16:32:52 +0200
Subject: [PATCH] [compiler-rt][XRay] Make xray_interface.h C compliant
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The XRay interface header uses no C++ specific features aside from using
the std namespace and including the C++ variant of C headers. Yet, these
changes prevent using `xray_interface.h` in external tools relying on C
for different reasons. Make this header C compliant by using C headers,
removing the std namespace from std::size_t and guard `extern "C"`.

To make sure that further changes to not break the interface
accidentially, port one test from C++ to C. This requires the C23
standard to officially support the attribute syntax used in this test
case.

Note that this only resolves this issue for `xray_interface.h`.
`xray_records.h` is also not C compliant, but requires more work to
port.

Fixes #139902

Signed-off-by: Jan André Reuter <j.reuter at fz-juelich.de>
---
 compiler-rt/include/xray/xray_interface.h     | 37 +++++++-----
 .../TestCases/Posix/patching-unpatching.c     | 56 +++++++++++++++++++
 2 files changed, 79 insertions(+), 14 deletions(-)
 create mode 100644 compiler-rt/test/xray/TestCases/Posix/patching-unpatching.c

diff --git a/compiler-rt/include/xray/xray_interface.h b/compiler-rt/include/xray/xray_interface.h
index 675ea0cbc48c8..3ef8ee348540f 100644
--- a/compiler-rt/include/xray/xray_interface.h
+++ b/compiler-rt/include/xray/xray_interface.h
@@ -1,4 +1,4 @@
-//===- xray_interface.h -----------------------------------------*- C++ -*-===//
+//===- xray_interface.h ---------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -14,10 +14,17 @@
 #ifndef XRAY_XRAY_INTERFACE_H
 #define XRAY_XRAY_INTERFACE_H
 
+#ifdef __cplusplus
 #include <cstddef>
 #include <cstdint>
+#else
+#include <stddef.h>
+#include <stdint.h>
+#endif
 
+#ifdef __cplusplus
 extern "C" {
+#endif
 
 /// Synchronize this with AsmPrinter::SledKind in LLVM.
 enum XRayEntryType {
@@ -49,7 +56,7 @@ enum XRayEntryType {
 /// achieved by marking them all with: __attribute__((xray_never_instrument))
 ///
 /// Returns 1 on success, 0 on error.
-extern int __xray_set_handler(void (*entry)(int32_t, XRayEntryType));
+extern int __xray_set_handler(void (*entry)(int32_t, enum XRayEntryType));
 
 /// This removes whatever the currently provided handler is. Returns 1 on
 /// success, 0 on error.
@@ -60,7 +67,7 @@ extern int __xray_remove_handler();
 /// start logging their subsequent affected function calls (if patched).
 ///
 /// Returns 1 on success, 0 on error.
-extern int __xray_set_handler_arg1(void (*entry)(int32_t, XRayEntryType,
+extern int __xray_set_handler_arg1(void (*entry)(int32_t, enum XRayEntryType,
                                                  uint64_t));
 
 /// Disables the XRay handler used to log first arguments of function calls.
@@ -68,7 +75,7 @@ extern int __xray_set_handler_arg1(void (*entry)(int32_t, XRayEntryType,
 extern int __xray_remove_handler_arg1();
 
 /// Provide a function to invoke when XRay encounters a custom event.
-extern int __xray_set_customevent_handler(void (*entry)(void *, std::size_t));
+extern int __xray_set_customevent_handler(void (*entry)(void *, size_t));
 
 /// This removes whatever the currently provided custom event handler is.
 /// Returns 1 on success, 0 on error.
@@ -95,39 +102,39 @@ enum XRayPatchingStatus {
 
 /// This tells XRay to patch the instrumentation points in all currently loaded
 /// objects. See XRayPatchingStatus for possible result values.
-extern XRayPatchingStatus __xray_patch();
+extern enum XRayPatchingStatus __xray_patch();
 
 /// This tells XRay to patch the instrumentation points in the given object.
 /// See XRayPatchingStatus for possible result values.
-extern XRayPatchingStatus __xray_patch_object(int32_t ObjId);
+extern enum XRayPatchingStatus __xray_patch_object(int32_t ObjId);
 
 /// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
 /// result values.
-extern XRayPatchingStatus __xray_unpatch();
+extern enum XRayPatchingStatus __xray_unpatch();
 
 /// Reverses the effect of __xray_patch_object. See XRayPatchingStatus for
 /// possible result values.
-extern XRayPatchingStatus __xray_unpatch_object(int32_t ObjId);
+extern enum XRayPatchingStatus __xray_unpatch_object(int32_t ObjId);
 
 /// This unpacks the given (packed) function id and patches
 /// the corresponding function.  See XRayPatchingStatus for possible
 /// result values.
-extern XRayPatchingStatus __xray_patch_function(int32_t FuncId);
+extern enum XRayPatchingStatus __xray_patch_function(int32_t FuncId);
 
 /// This patches a specific function in the given object. See XRayPatchingStatus
 /// for possible result values.
-extern XRayPatchingStatus __xray_patch_function_in_object(int32_t FuncId,
-                                                          int32_t ObjId);
+extern enum XRayPatchingStatus __xray_patch_function_in_object(int32_t FuncId,
+                                                               int32_t ObjId);
 
 /// This unpacks the given (packed) function id and unpatches
 /// the corresponding function. See XRayPatchingStatus for possible
 /// result values.
-extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId);
+extern enum XRayPatchingStatus __xray_unpatch_function(int32_t FuncId);
 
 /// This unpatches a specific function in the given object.
 /// See XRayPatchingStatus for possible result values.
-extern XRayPatchingStatus __xray_unpatch_function_in_object(int32_t FuncId,
-                                                            int32_t ObjId);
+extern enum XRayPatchingStatus __xray_unpatch_function_in_object(int32_t FuncId,
+                                                                 int32_t ObjId);
 
 /// This function unpacks the given (packed) function id and returns the address
 /// of the corresponding function. We return 0 if we encounter any error, even
@@ -173,6 +180,8 @@ extern int32_t __xray_pack_id(int32_t FuncId, int32_t ObjId);
 /// Calling __xray_init() more than once is safe across multiple threads.
 extern void __xray_init();
 
+#ifdef __cplusplus
 } // end extern "C"
+#endif
 
 #endif // XRAY_XRAY_INTERFACE_H
diff --git a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching.c b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching.c
new file mode 100644
index 0000000000000..2dbc68142dbc5
--- /dev/null
+++ b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching.c
@@ -0,0 +1,56 @@
+// Check that we can patch and un-patch on demand, and that logging gets invoked
+// appropriately.
+//
+// Do not run on powerpc64le, as linking XRay with C compiler causes linker error
+// due to std::__throw_system_error(int) being present in XRay libraries.
+// See https://github.com/llvm/llvm-project/issues/141598
+//
+// RUN: %clang_xray -fxray-instrument -std=c23 %s -o %t
+// RUN: env XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
+// RUN: %clang_xray -fxray-instrument -fno-xray-function-index -std=c23 %s -o %t
+// RUN: env XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
+
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target=powerpc64le-{{.*}}
+
+#include "xray/xray_interface.h"
+
+#include <stdio.h>
+
+bool called = false;
+
+void test_handler(int32_t fid, enum XRayEntryType type) {
+  printf("called: %d, type=%d\n", fid, (int32_t)(type));
+  called = true;
+}
+
+[[clang::xray_always_instrument]] void always_instrument() {
+  printf("always instrumented called\n");
+}
+
+int main() {
+  __xray_set_handler(test_handler);
+  always_instrument();
+  // CHECK: always instrumented called
+  auto status = __xray_patch();
+  printf("patching status: %d\n", (int32_t)status);
+  // CHECK-NEXT: patching status: 1
+  always_instrument();
+  // CHECK-NEXT: called: {{.*}}, type=0
+  // CHECK-NEXT: always instrumented called
+  // CHECK-NEXT: called: {{.*}}, type=1
+  status = __xray_unpatch();
+  printf("patching status: %d\n", (int32_t)status);
+  // CHECK-NEXT: patching status: 1
+  always_instrument();
+  // CHECK-NEXT: always instrumented called
+  status = __xray_patch();
+  printf("patching status: %d\n", (int32_t)status);
+  // CHECK-NEXT: patching status: 1
+  __xray_remove_handler();
+  always_instrument();
+  // CHECK-NEXT: always instrumented called
+  status = __xray_unpatch();
+  printf("patching status: %d\n", (int32_t)status);
+  // CHECK-NEXT: patching status: 1
+}



More information about the llvm-commits mailing list