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

Changes to initial PR (#140068):

- Mark failing test as unsupported for powerpc64le, as test failure is
unrelated to PR changes. See
https://github.com/llvm/llvm-project/issues/141598

---

Original description (from #140068)

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@fz-juelich.de>
This commit is contained in:
Jan André Reuter 2025-09-29 17:33:28 +02:00 committed by GitHub
parent c2fbd12f11
commit 637bfb7ea6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 79 additions and 14 deletions

View File

@ -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

View File

@ -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
}