Xray instrumentation / enabling more tests

Summary:
The Unix subdirectory mostly allows only on Linux x86_64 but now we can target x86_64 arch in general.

Patch by David CARLIER

Reviewers: krytarowski, dberris, emaste

Reviewed By: krytarowski, dberris, emaste

Subscribers: emaste, llvm-commits, #sanitizers

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

llvm-svn: 325743
This commit is contained in:
Kamil Rytarowski 2018-02-22 06:08:26 +00:00
parent 0ac2eb7369
commit 80c2a79437
41 changed files with 910 additions and 907 deletions

View File

@ -1,23 +0,0 @@
// Test that the always/never instrument lists apply.
// RUN: echo "fun:main" > %tmp-always.txt
// RUN: echo "fun:__xray*" > %tmp-never.txt
// RUN: %clangxx_xray \
// RUN: -fxray-never-instrument=%tmp-never.txt \
// RUN: -fxray-always-instrument=%tmp-always.txt \
// RUN: %s -o %t
// RUN: %llvm_xray extract -symbolize %t | \
// RUN: FileCheck %s --check-prefix NOINSTR
// RUN: %llvm_xray extract -symbolize %t | \
// RUN: FileCheck %s --check-prefix ALWAYSINSTR
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
// NOINSTR-NOT: {{.*__xray_NeverInstrumented.*}}
int __xray_NeverInstrumented() {
return 0;
}
// ALWAYSINSTR: {{.*function-name:.*main.*}}
int main(int argc, char *argv[]) {
return __xray_NeverInstrumented();
}

View File

@ -1,39 +0,0 @@
// Allow having both the no-arg and arg1 logging implementation live together,
// and be called in the correct cases.
//
// RUN: rm arg0-arg1-logging-* || true
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg0-arg1-logging-" %run %t
//
// TODO: Support these in ARM and PPC
// XFAIL: arm || aarch64 || mips
// UNSUPPORTED: powerpc64le
#include "xray/xray_interface.h"
#include <cassert>
#include <cstdio>
using namespace std;
bool arg0loggercalled = false;
void arg0logger(int32_t, XRayEntryType) { arg0loggercalled = true; }
[[clang::xray_always_instrument]] void arg0fn() { printf("hello, arg0!\n"); }
bool arg1loggercalled = false;
void arg1logger(int32_t, XRayEntryType, uint64_t) { arg1loggercalled = true; }
[[ clang::xray_always_instrument, clang::xray_log_args(1) ]] void
arg1fn(uint64_t arg1) {
printf("hello, arg1!\n");
}
int main(int argc, char *argv[]) {
__xray_set_handler(arg0logger);
__xray_set_handler_arg1(arg1logger);
arg0fn();
arg1fn(0xcafef00d);
__xray_remove_handler_arg1();
__xray_remove_handler();
assert(arg0loggercalled && arg1loggercalled);
}

View File

@ -1,45 +0,0 @@
// 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: rm arg1-logger-* || true
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \
// RUN: xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s
//
// After all that, clean up the XRay log file.
//
// RUN: rm arg1-logger-* || true
//
// At the time of writing, the ARM trampolines weren't written yet.
// XFAIL: arm || aarch64 || mips
// See the mailing list discussion of r296998.
// UNSUPPORTED: powerpc64le
#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 3
__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 3
foo((void *) -1);
// CHECK-NEXT: Arg1: ffffffffffffffff, XRayEntryType 3
}

View File

@ -1,31 +0,0 @@
// Intercept the implicit 'this' argument of class member functions.
//
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm log-args-this-* || true
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=log-args-this-" %run %t
//
// XFAIL: arm || aarch64 || mips
// UNSUPPORTED: powerpc64le
#include "xray/xray_interface.h"
#include <cassert>
class A {
public:
[[clang::xray_always_instrument, clang::xray_log_args(1)]] void f() {
// does nothing.
}
};
volatile uint64_t captured = 0;
void handler(int32_t, XRayEntryType, uint64_t arg1) {
captured = arg1;
}
int main() {
__xray_set_handler_arg1(handler);
A instance;
instance.f();
__xray_remove_handler_arg1();
assert(captured == (uint64_t)&instance);
}

View File

@ -1,16 +0,0 @@
// Check to make sure argv[0] is contained within the (randomised) XRay log file
// name.
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true" %run %t > xray.log.file.name 2>&1
// RUN: ls | FileCheck xray.log.file.name
// RUN: rm xray-log.* xray.log.file.name
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
#include <libgen.h>
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
printf("// CHECK: xray-log.%s.{{.*}}\n", basename(argv[0]));
}

View File

@ -1,51 +0,0 @@
// Check to make sure that we are actually filtering records from the basic mode
// logging implementation.
// RUN: %clangxx_xray -std=c++11 %s -o %t -g
// RUN: rm basic-filtering-* || true
// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true verbosity=1 \
// RUN: xray_logfile_base=basic-filtering- \
// RUN: xray_naive_log_func_duration_threshold_us=1000 \
// RUN: xray_naive_log_max_stack_depth=2" %run %t 2>&1 | \
// RUN: FileCheck %s
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
// RUN: "`ls basic-filtering-* | head -1`" | \
// RUN: FileCheck %s --check-prefix TRACE
// RUN: rm basic-filtering-* || true
//
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include <cstdio>
#include <time.h>
[[clang::xray_always_instrument]] void __attribute__((noinline)) filtered() {
printf("filtered was called.\n");
}
[[clang::xray_always_instrument]] void __attribute__((noinline)) beyond_stack() {
printf("beyond stack was called.\n");
}
[[clang::xray_always_instrument]] void __attribute__((noinline))
always_shows() {
struct timespec sleep;
sleep.tv_nsec = 2000000;
sleep.tv_sec = 0;
struct timespec rem;
while (nanosleep(&sleep, &rem) == -1)
sleep = rem;
printf("always_shows was called.\n");
beyond_stack();
}
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
filtered(); // CHECK: filtered was called.
always_shows(); // CHECK: always_shows was called.
// CHECK: beyond stack was called.
}
// TRACE-NOT: - { type: 0, func-id: {{.*}}, function: {{.*filtered.*}}, {{.*}} }
// TRACE-NOT: - { type: 0, func-id: {{.*}}, function: {{.*beyond_stack.*}}, {{.*}} }
// TRACE-DAG: - { type: 0, func-id: [[FID:[0-9]+]], function: {{.*always_shows.*}}, cpu: {{.*}}, thread: {{.*}}, kind: function-enter, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID]], function: {{.*always_shows.*}}, cpu: {{.*}}, thread: {{.*}}, kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }

View File

@ -1,57 +0,0 @@
// Make sure that we're aligning the stack properly to support handlers that
// expect 16-byte alignment of the stack.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \
// RUN: %run %t 2>&1
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include "xray/xray_interface.h"
#include <stdio.h>
#include <xmmintrin.h>
[[clang::xray_never_instrument]] __attribute__((weak)) __m128 f(__m128 *i) {
return *i;
}
[[clang::xray_always_instrument]] __attribute__((noinline)) void noarg() {
__m128 v = {};
f(&v);
}
[[ clang::xray_always_instrument, clang::xray_log_args(1) ]]
__attribute__((noinline)) void arg1(int) {
__m128 v = {};
f(&v);
}
[[clang::xray_always_instrument]] __attribute__((noinline))
void no_alignment() {}
[[clang::xray_never_instrument]] void noarg_handler(int32_t,
XRayEntryType) {
printf("noarg handler called\n");
__m128 v = {};
f(&v);
}
[[clang::xray_never_instrument]] void arg1_handler(int32_t, XRayEntryType,
uint64_t) {
printf("arg1 handler called\n");
__m128 v = {};
f(&v);
}
int main(int argc, char *argv[]) {
__xray_set_handler(noarg_handler);
__xray_set_handler_arg1(arg1_handler);
__xray_patch();
noarg(); // CHECK: noarg handler called
arg1(argc); // CHECK: arg1 handler called
no_alignment();
__xray_unpatch();
__xray_remove_handler();
__xray_remove_handler_arg1();
noarg();
arg1(argc);
}

View File

@ -1,91 +0,0 @@
// Check that we can patch and unpatch specific function ids.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t | FileCheck %s
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include <set>
#include <cstdio>
#include <cassert>
std::set<int32_t> function_ids;
[[clang::xray_never_instrument]] void coverage_handler(int32_t fid,
XRayEntryType) {
thread_local bool patching = false;
if (patching) return;
patching = true;
function_ids.insert(fid);
__xray_unpatch_function(fid);
patching = false;
}
[[clang::xray_always_instrument]] void baz() {
// do nothing!
}
[[clang::xray_always_instrument]] void bar() {
baz();
}
[[clang::xray_always_instrument]] void foo() {
bar();
}
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
__xray_set_handler(coverage_handler);
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
foo();
assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// print out the function_ids.
printf("first pass.\n");
for (const auto id : function_ids)
printf("patched: %d\n", id);
// CHECK-LABEL: first pass.
// CHECK-DAG: patched: [[F1:.*]]
// CHECK-DAG: patched: [[F2:.*]]
// CHECK-DAG: patched: [[F3:.*]]
// make a copy of the function_ids, then patch them later.
auto called_fns = function_ids;
// clear the function_ids.
function_ids.clear();
// patch the functions we've called before.
for (const auto id : called_fns)
assert(__xray_patch_function(id) == XRayPatchingStatus::SUCCESS);
// then call them again.
foo();
assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// confirm that we've seen the same functions again.
printf("second pass.\n");
for (const auto id : function_ids)
printf("patched: %d\n", id);
// CHECK-LABEL: second pass.
// CHECK-DAG: patched: [[F1]]
// CHECK-DAG: patched: [[F2]]
// CHECK-DAG: patched: [[F3]]
// Now we want to make sure that if we unpatch one, that we're only going to
// see two calls of the coverage_handler.
function_ids.clear();
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
assert(__xray_unpatch_function(1) == XRayPatchingStatus::SUCCESS);
foo();
assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// confirm that we don't see function id one called anymore.
printf("missing 1.\n");
for (const auto id : function_ids)
printf("patched: %d\n", id);
// CHECK-LABEL: missing 1.
// CHECK-NOT: patched: 1
}

View File

@ -1,42 +0,0 @@
// Make sure we're aligning the stack properly when lowering the custom event
// calls.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \
// RUN: %run %t 2>&1
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include <xmmintrin.h>
#include <stdio.h>
#include "xray/xray_interface.h"
[[clang::xray_never_instrument]] __attribute__((weak)) __m128 f(__m128 *i) {
return *i;
}
[[clang::xray_always_instrument]] void foo() {
__xray_customevent(0, 0);
__m128 v = {};
f(&v);
}
[[clang::xray_always_instrument]] void bar() {
__xray_customevent(0, 0);
}
void printer(void* ptr, size_t size) {
printf("handler called\n");
__m128 v = {};
f(&v);
}
int main(int argc, char* argv[]) {
__xray_set_customevent_handler(printer);
__xray_patch();
foo(); // CHECK: handler called
bar(); // CHECK: handler called
__xray_unpatch();
__xray_remove_customevent_handler();
foo();
bar();
}

View File

@ -1,42 +0,0 @@
// Use the clang feature for custom xray event logging.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false xray_logfile_base=custom-event-logging.xray-" %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_xray -std=c++11 -fpic -fpie %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false xray_logfile_base=custom-event-logging.xray-" %run %t 2>&1 | FileCheck %s
// FIXME: Support this in non-x86_64 as well
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include <cstdio>
#include "xray/xray_interface.h"
[[clang::xray_always_instrument]] void foo() {
static constexpr char CustomLogged[] = "hello custom logging!";
printf("before calling the custom logging...\n");
__xray_customevent(CustomLogged, sizeof(CustomLogged));
printf("after calling the custom logging...\n");
}
void myprinter(void* ptr, size_t size) {
printf("%.*s\n", static_cast<int>(size), static_cast<const char*>(ptr));
}
int main() {
foo();
// CHECK: before calling the custom logging...
// CHECK-NEXT: after calling the custom logging...
printf("setting up custom event handler...\n");
// CHECK-NEXT: setting up custom event handler...
__xray_set_customevent_handler(myprinter);
__xray_patch();
// CHECK-NEXT: before calling the custom logging...
foo();
// CHECK-NEXT: hello custom logging!
// CHECK-NEXT: after calling the custom logging...
printf("removing custom event handler...\n");
// CHECK-NEXT: removing custom event handler...
__xray_remove_customevent_handler();
foo();
// CHECK-NEXT: before calling the custom logging...
// CHECK-NEXT: after calling the custom logging...
}

View File

@ -1,103 +0,0 @@
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm fdr-logging-test-* || true
// RUN: rm fdr-unwrite-test-* || true
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false xray_logfile_base=fdr-logging-test- xray_fdr_log=true verbosity=1 xray_fdr_log_func_duration_threshold_us=0" %run %t 2>&1 | FileCheck %s
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false xray_logfile_base=fdr-unwrite-test- xray_fdr_log=true verbosity=1 xray_fdr_log_func_duration_threshold_us=5000" %run %t 2>&1 | FileCheck %s
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t "`ls fdr-logging-test-* | head -1`" | FileCheck %s --check-prefix=TRACE
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t "`ls fdr-unwrite-test-* | head -1`" | FileCheck %s --check-prefix=UNWRITE
// RUN: rm fdr-logging-test-*
// RUN: rm fdr-unwrite-test-*
// FIXME: Make llvm-xray work on non-x86_64 as well.
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include "xray/xray_log_interface.h"
#include <cassert>
#include <chrono>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <thread>
#include <time.h>
constexpr auto kBufferSize = 16384;
constexpr auto kBufferMax = 10;
thread_local uint64_t var = 0;
[[clang::xray_always_instrument]] void __attribute__((noinline)) fC() { ++var; }
[[clang::xray_always_instrument]] void __attribute__((noinline)) fB() { fC(); }
[[clang::xray_always_instrument]] void __attribute__((noinline)) fA() { fB(); }
[[clang::xray_always_instrument, clang::xray_log_args(1)]]
void __attribute__((noinline)) fArg(int) { }
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Options;
std::cout << "Logging before init." << std::endl;
// CHECK: Logging before init.
auto status = __xray_log_init(kBufferSize, kBufferMax, &Options,
sizeof(FDRLoggingOptions));
assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
std::cout << "Init status " << status << std::endl;
// CHECK: Init status {{.*}}
std::cout << "Patching..." << std::endl;
// CHECK: Patching...
__xray_patch();
fA();
fC();
fB();
fA();
fC();
std::thread other_thread([]() {
fC();
fB();
fA();
fArg(1);
});
other_thread.join();
std::cout << "Joined" << std::endl;
// CHECK: Joined
std::cout << "Finalize status " << __xray_log_finalize() << std::endl;
// CHECK: Finalize status {{.*}}
fC();
std::cout << "Main execution var = " << var << std::endl;
// CHECK: Main execution var = 6
std::cout << "Flush status " << __xray_log_flushLog() << std::endl;
// CHECK: Flush status {{.*}}
__xray_unpatch();
return 0;
}
// Check that we're able to see two threads, each entering and exiting fA().
// TRACE-DAG: - { type: 0, func-id: [[FIDA:[0-9]+]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
//
// Do the same as above for fC()
// TRACE-DAG: - { type: 0, func-id: [[FIDC:[0-9]+]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// Do the same as above for fB()
// TRACE-DAG: - { type: 0, func-id: [[FIDB:[0-9]+]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2]], kind: function-enter-arg, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
// Assert that when unwriting is enabled with a high threshold time, all the function records are erased. A CPU switch could erroneously fail this test, but
// is unlikely given the test program.
// Even with a high threshold, arg1 logging is never unwritten.
// UNWRITE: header:
// UNWRITE: records:
// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter-arg, tsc: {{[0-9]+}} }
// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
// UNWRITE-NOT: function-enter
// UNWRITE-NOT: function-{{exit|tail-exit}}

View File

@ -1,38 +0,0 @@
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm fdr-logging-1thr-* || true
// RUN: XRAY_OPTIONS=XRAY_OPTIONS="verbosity=1 patch_premain=true \
// RUN: xray_naive_log=false xray_fdr_log=true \
// RUN: xray_fdr_log_func_duration_threshold_us=0 \
// RUN: xray_logfile_base=fdr-logging-1thr-" %run %t 2>&1
// RUN: %llvm_xray convert --output-format=yaml --symbolize --instr_map=%t \
// RUN: "`ls fdr-logging-1thr-* | head -n1`" | FileCheck %s
// RUN: rm fdr-logging-1thr-*
//
// REQUIRES: x86_64-linux
#include "xray/xray_log_interface.h"
#include <cassert>
constexpr auto kBufferSize = 16384;
constexpr auto kBufferMax = 10;
[[clang::xray_always_instrument]] void __attribute__((noinline)) fn() { }
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Opts;
auto status = __xray_log_init(kBufferSize, kBufferMax, &Opts, sizeof(Opts));
assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
__xray_patch();
fn();
__xray_unpatch();
assert(__xray_log_finalize() == XRAY_LOG_FINALIZED);
assert(__xray_log_flushLog() == XRAY_LOG_FLUSHED);
return 0;
}
// CHECK: records:
// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-exit, tsc: {{[0-9]+}} }

View File

@ -1,67 +0,0 @@
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm fdr-thread-order.* || true
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false \
// RUN: xray_logfile_base=fdr-thread-order. xray_fdr_log=true verbosity=1 \
// RUN: xray_fdr_log_func_duration_threshold_us=0" %run %t 2>&1 | \
// RUN: FileCheck %s
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
// RUN: "`ls fdr-thread-order.* | head -1`"
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
// RUN: "`ls fdr-thread-order.* | head -1`" | \
// RUN: FileCheck %s --check-prefix TRACE
// RUN: rm fdr-thread-order.*
// FIXME: Make llvm-xray work on non-x86_64 as well.
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include "xray/xray_log_interface.h"
#include <atomic>
#include <cassert>
#include <thread>
constexpr auto kBufferSize = 16384;
constexpr auto kBufferMax = 10;
std::atomic<uint64_t> var{0};
[[clang::xray_always_instrument]] void __attribute__((noinline)) f1() {
for (auto i = 0; i < 1 << 20; ++i)
++var;
}
[[clang::xray_always_instrument]] void __attribute__((noinline)) f2() {
for (auto i = 0; i < 1 << 20; ++i)
++var;
}
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Options;
__xray_patch();
assert(__xray_log_init(kBufferSize, kBufferMax, &Options,
sizeof(FDRLoggingOptions)) ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);
std::atomic_thread_fence(std::memory_order_acq_rel);
{
std::thread t1([] { f1(); });
std::thread t2([] { f2(); });
t1.join();
t2.join();
}
std::atomic_thread_fence(std::memory_order_acq_rel);
__xray_log_finalize();
__xray_log_flushLog();
__xray_unpatch();
return var > 0 ? 0 : 1;
// CHECK: {{.*}}XRay: Log file in '{{.*}}'
// CHECK-NOT: Failed
}
// We want to make sure that the order of the function log doesn't matter.
// TRACE-DAG: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID2:[0-9]+]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID1]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID2]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} }

View File

@ -1,22 +0,0 @@
// Check to make sure that we have a log file with a fixed-size.
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true verbosity=1 xray_logfile_base=fixedsize-logging-" %run %t 2>&1 | FileCheck %s
//
// After all that, clean up the output xray log.
//
// RUN: rm fixedsize-logging-*
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
[[clang::xray_always_instrument]] void foo() {
printf("foo() is always instrumented!");
}
int main() {
// CHECK: XRay: Log file in 'fixedsize-logging-{{.*}}'
foo();
// CHECK: foo() is always instrumented!
}

View File

@ -1,44 +0,0 @@
// Check that we can turn a function id to a function address, and also get the
// maximum function id for the current binary.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iterator>
#include <set>
[[clang::xray_always_instrument]] void bar(){}
[[clang::xray_always_instrument]] void foo() {
bar();
}
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
assert(__xray_max_function_id() != 0 && "we need xray instrumentation!");
std::set<void *> must_be_instrumented = {reinterpret_cast<void *>(&foo),
reinterpret_cast<void *>(&bar),
reinterpret_cast<void *>(&main)};
std::set<void *> all_instrumented;
for (auto i = __xray_max_function_id(); i != 0; --i) {
auto addr = __xray_function_address(i);
all_instrumented.insert(reinterpret_cast<void *>(addr));
}
assert(all_instrumented.size() == __xray_max_function_id() &&
"each function id must be assigned to a unique function");
std::set<void *> not_instrumented;
std::set_difference(
must_be_instrumented.begin(), must_be_instrumented.end(),
all_instrumented.begin(), all_instrumented.end(),
std::inserter(not_instrumented, not_instrumented.begin()));
assert(
not_instrumented.empty() &&
"we should see all explicitly instrumented functions with function ids");
return not_instrumented.empty() ? 0 : 1;
}

View File

@ -1,59 +0,0 @@
// Check that we can install an implementation associated with a mode.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: %run %t | FileCheck %s
//
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include "xray/xray_log_interface.h"
#include <cassert>
#include <cstdio>
[[clang::xray_never_instrument]] void printing_handler(int32_t fid,
XRayEntryType) {
thread_local volatile bool printing = false;
if (printing)
return;
printing = true;
std::printf("printing %d\n", fid);
printing = false;
}
[[clang::xray_never_instrument]] XRayLogInitStatus
printing_init(size_t, size_t, void *, size_t) {
return XRayLogInitStatus::XRAY_LOG_INITIALIZED;
}
[[clang::xray_never_instrument]] XRayLogInitStatus printing_finalize() {
return XRayLogInitStatus::XRAY_LOG_FINALIZED;
}
[[clang::xray_never_instrument]] XRayLogFlushStatus printing_flush_log() {
return XRayLogFlushStatus::XRAY_LOG_FLUSHED;
}
[[clang::xray_always_instrument]] void callme() { std::printf("called me!\n"); }
static bool unused = [] {
assert(__xray_log_register_mode("custom",
{printing_init, printing_finalize,
printing_handler, printing_flush_log}) ==
XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
return true;
}();
int main(int argc, char **argv) {
assert(__xray_log_select_mode("custom") ==
XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
assert(__xray_log_init(0, 0, nullptr, 0) ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);
// CHECK: printing {{.*}}
callme(); // CHECK: called me!
// CHECK: printing {{.*}}
assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED);
assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
assert(__xray_log_select_mode("not-found") ==
XRayLogRegisterStatus::XRAY_MODE_NOT_FOUND);
}

View File

@ -1,23 +0,0 @@
// Make sure that we don't get the inmemory logging implementation enabled when
// we turn it off via options.
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=false xray_logfile_base=optional-inmemory-log.xray-" %run %t 2>&1 | FileCheck %s
//
// Make sure we clean out the logs in case there was a bug.
//
// RUN: rm -f optional-inmemory-log.xray-*
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
[[clang::xray_always_instrument]] void foo() {
printf("foo() is always instrumented!");
}
int main() {
// CHECK-NOT: XRay: Log file in 'optional-inmemory-log.xray-{{.*}}'
foo();
// CHECK: foo() is always instrumented!
}

View File

@ -1,49 +0,0 @@
// Check that we can patch and un-patch on demand, and that logging gets invoked
// appropriately.
//
// RUN: %clangxx_xray -fxray-instrument -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include <cstdio>
bool called = false;
void test_handler(int32_t fid, XRayEntryType type) {
printf("called: %d, type=%d\n", fid, static_cast<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", static_cast<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", static_cast<int32_t>(status));
// CHECK-NEXT: patching status: 1
always_instrument();
// CHECK-NEXT: always instrumented called
status = __xray_patch();
printf("patching status: %d\n", static_cast<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", static_cast<int32_t>(status));
// CHECK-NEXT: patching status: 1
}

View File

@ -1,38 +0,0 @@
// Test to check if we handle pic code properly.
// RUN: %clangxx_xray -fxray-instrument -std=c++11 -ffunction-sections \
// RUN: -fdata-sections -fpic -fpie -Wl,--gc-sections %s -o %t
// RUN: rm pic-test-logging-* || true
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \
// RUN: xray_logfile_base=pic-test-logging-" %run %t 2>&1 | FileCheck %s
// After all that, clean up the output xray log.
//
// RUN: rm pic-test-logging-* || true
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
[[clang::xray_always_instrument]]
unsigned short foo (unsigned b);
[[clang::xray_always_instrument]]
unsigned short bar (unsigned short a)
{
printf("bar() is always instrumented!\n");
return foo(a);
}
unsigned short foo (unsigned b)
{
printf("foo() is always instrumented!\n");
return b + b + 5;
}
int main ()
{
// CHECK: XRay: Log file in 'pic-test-logging-{{.*}}'
bar(10);
// CHECK: bar() is always instrumented!
// CHECK-NEXT: foo() is always instrumented!
}

View File

@ -1,26 +0,0 @@
// Ensure that we have a quiet startup when we don't have the XRay
// instrumentation sleds.
//
// RUN: %clangxx -std=c++11 %s -o %t %xraylib
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1" %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix NOISY
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=0" %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix QUIET
// RUN: XRAY_OPTIONS="" %run %t 2>&1 | FileCheck %s --check-prefix DEFAULT
//
// FIXME: Understand how to make this work on other platforms
// REQUIRES: built-in-llvm-tree
// REQUIRES: x86_64-linux
#include <iostream>
using namespace std;
int main(int, char**) {
// NOISY: {{.*}}XRay instrumentation map missing. Not initializing XRay.
// QUIET-NOT: {{.*}}XRay instrumentation map missing. Not initializing XRay.
// DEFAULT-NOT: {{.*}}XRay instrumentation map missing. Not initializing XRay.
cout << "Hello, XRay!" << endl;
// NOISY: Hello, XRay!
// QUIET: Hello, XRay!
// DEFAULT: Hello, XRay!
}

View File

@ -0,0 +1,23 @@
// Test that the always/never instrument lists apply.
// RUN: echo "fun:main" > %tmp-always.txt
// RUN: echo "fun:__xray*" > %tmp-never.txt
// RUN: %clangxx_xray \
// RUN: -fxray-never-instrument=%tmp-never.txt \
// RUN: -fxray-always-instrument=%tmp-always.txt \
// RUN: %s -o %t
// RUN: %llvm_xray extract -symbolize %t | \
// RUN: FileCheck %s --check-prefix NOINSTR
// RUN: %llvm_xray extract -symbolize %t | \
// RUN: FileCheck %s --check-prefix ALWAYSINSTR
// REQUIRES: x86_64-target-arch
// REQUIRES: built-in-llvm-tree
// NOINSTR-NOT: {{.*__xray_NeverInstrumented.*}}
int __xray_NeverInstrumented() {
return 0;
}
// ALWAYSINSTR: {{.*function-name:.*main.*}}
int main(int argc, char *argv[]) {
return __xray_NeverInstrumented();
}

View File

@ -0,0 +1,39 @@
// Allow having both the no-arg and arg1 logging implementation live together,
// and be called in the correct cases.
//
// RUN: rm arg0-arg1-logging-* || true
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg0-arg1-logging-" %run %t
//
// TODO: Support these in ARM and PPC
// XFAIL: arm || aarch64 || mips
// UNSUPPORTED: powerpc64le
#include "xray/xray_interface.h"
#include <cassert>
#include <cstdio>
using namespace std;
bool arg0loggercalled = false;
void arg0logger(int32_t, XRayEntryType) { arg0loggercalled = true; }
[[clang::xray_always_instrument]] void arg0fn() { printf("hello, arg0!\n"); }
bool arg1loggercalled = false;
void arg1logger(int32_t, XRayEntryType, uint64_t) { arg1loggercalled = true; }
[[ clang::xray_always_instrument, clang::xray_log_args(1) ]] void
arg1fn(uint64_t arg1) {
printf("hello, arg1!\n");
}
int main(int argc, char *argv[]) {
__xray_set_handler(arg0logger);
__xray_set_handler_arg1(arg1logger);
arg0fn();
arg1fn(0xcafef00d);
__xray_remove_handler_arg1();
__xray_remove_handler();
assert(arg0loggercalled && arg1loggercalled);
}

View File

@ -0,0 +1,45 @@
// 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: rm arg1-logger-* || true
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \
// RUN: xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s
//
// After all that, clean up the XRay log file.
//
// RUN: rm arg1-logger-* || true
//
// At the time of writing, the ARM trampolines weren't written yet.
// XFAIL: arm || aarch64 || mips
// See the mailing list discussion of r296998.
// UNSUPPORTED: powerpc64le
#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 3
__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 3
foo((void *) -1);
// CHECK-NEXT: Arg1: ffffffffffffffff, XRayEntryType 3
}

View File

@ -0,0 +1,31 @@
// Intercept the implicit 'this' argument of class member functions.
//
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm log-args-this-* || true
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=log-args-this-" %run %t
//
// XFAIL: freebsd | arm || aarch64 || mips
// UNSUPPORTED: powerpc64le
#include "xray/xray_interface.h"
#include <cassert>
class A {
public:
[[clang::xray_always_instrument, clang::xray_log_args(1)]] void f() {
// does nothing.
}
};
volatile uint64_t captured = 0;
void handler(int32_t, XRayEntryType, uint64_t arg1) {
captured = arg1;
}
int main() {
__xray_set_handler_arg1(handler);
A instance;
instance.f();
__xray_remove_handler_arg1();
assert(captured == (uint64_t)&instance);
}

View File

@ -0,0 +1,16 @@
// Check to make sure argv[0] is contained within the (randomised) XRay log file
// name.
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true" %run %t > xray.log.file.name 2>&1
// RUN: ls | FileCheck xray.log.file.name
// RUN: rm xray-log.* xray.log.file.name
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
#include <libgen.h>
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
printf("// CHECK: xray-log.%s.{{.*}}\n", basename(argv[0]));
}

View File

@ -0,0 +1,51 @@
// Check to make sure that we are actually filtering records from the basic mode
// logging implementation.
// RUN: %clangxx_xray -std=c++11 %s -o %t -g
// RUN: rm basic-filtering-* || true
// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true verbosity=1 \
// RUN: xray_logfile_base=basic-filtering- \
// RUN: xray_naive_log_func_duration_threshold_us=1000 \
// RUN: xray_naive_log_max_stack_depth=2" %run %t 2>&1 | \
// RUN: FileCheck %s
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
// RUN: "`ls basic-filtering-* | head -1`" | \
// RUN: FileCheck %s --check-prefix TRACE
// RUN: rm basic-filtering-* || true
//
// REQUIRES: x86_64-target-arch
// REQUIRES: built-in-llvm-tree
#include <cstdio>
#include <time.h>
[[clang::xray_always_instrument]] void __attribute__((noinline)) filtered() {
printf("filtered was called.\n");
}
[[clang::xray_always_instrument]] void __attribute__((noinline)) beyond_stack() {
printf("beyond stack was called.\n");
}
[[clang::xray_always_instrument]] void __attribute__((noinline))
always_shows() {
struct timespec sleep;
sleep.tv_nsec = 2000000;
sleep.tv_sec = 0;
struct timespec rem;
while (nanosleep(&sleep, &rem) == -1)
sleep = rem;
printf("always_shows was called.\n");
beyond_stack();
}
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
filtered(); // CHECK: filtered was called.
always_shows(); // CHECK: always_shows was called.
// CHECK: beyond stack was called.
}
// TRACE-NOT: - { type: 0, func-id: {{.*}}, function: {{.*filtered.*}}, {{.*}} }
// TRACE-NOT: - { type: 0, func-id: {{.*}}, function: {{.*beyond_stack.*}}, {{.*}} }
// TRACE-DAG: - { type: 0, func-id: [[FID:[0-9]+]], function: {{.*always_shows.*}}, cpu: {{.*}}, thread: {{.*}}, kind: function-enter, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID]], function: {{.*always_shows.*}}, cpu: {{.*}}, thread: {{.*}}, kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }

View File

@ -0,0 +1,57 @@
// Make sure that we're aligning the stack properly to support handlers that
// expect 16-byte alignment of the stack.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \
// RUN: %run %t 2>&1
// REQUIRES: x86_64-target-arch
// REQUIRES: built-in-llvm-tree
#include "xray/xray_interface.h"
#include <stdio.h>
#include <xmmintrin.h>
[[clang::xray_never_instrument]] __attribute__((weak)) __m128 f(__m128 *i) {
return *i;
}
[[clang::xray_always_instrument]] __attribute__((noinline)) void noarg() {
__m128 v = {};
f(&v);
}
[[ clang::xray_always_instrument, clang::xray_log_args(1) ]]
__attribute__((noinline)) void arg1(int) {
__m128 v = {};
f(&v);
}
[[clang::xray_always_instrument]] __attribute__((noinline))
void no_alignment() {}
[[clang::xray_never_instrument]] void noarg_handler(int32_t,
XRayEntryType) {
printf("noarg handler called\n");
__m128 v = {};
f(&v);
}
[[clang::xray_never_instrument]] void arg1_handler(int32_t, XRayEntryType,
uint64_t) {
printf("arg1 handler called\n");
__m128 v = {};
f(&v);
}
int main(int argc, char *argv[]) {
__xray_set_handler(noarg_handler);
__xray_set_handler_arg1(arg1_handler);
__xray_patch();
noarg(); // CHECK: noarg handler called
arg1(argc); // CHECK: arg1 handler called
no_alignment();
__xray_unpatch();
__xray_remove_handler();
__xray_remove_handler_arg1();
noarg();
arg1(argc);
}

View File

@ -0,0 +1,91 @@
// Check that we can patch and unpatch specific function ids.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t | FileCheck %s
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include <set>
#include <cstdio>
#include <cassert>
std::set<int32_t> function_ids;
[[clang::xray_never_instrument]] void coverage_handler(int32_t fid,
XRayEntryType) {
thread_local bool patching = false;
if (patching) return;
patching = true;
function_ids.insert(fid);
__xray_unpatch_function(fid);
patching = false;
}
[[clang::xray_always_instrument]] void baz() {
// do nothing!
}
[[clang::xray_always_instrument]] void bar() {
baz();
}
[[clang::xray_always_instrument]] void foo() {
bar();
}
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
__xray_set_handler(coverage_handler);
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
foo();
assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// print out the function_ids.
printf("first pass.\n");
for (const auto id : function_ids)
printf("patched: %d\n", id);
// CHECK-LABEL: first pass.
// CHECK-DAG: patched: [[F1:.*]]
// CHECK-DAG: patched: [[F2:.*]]
// CHECK-DAG: patched: [[F3:.*]]
// make a copy of the function_ids, then patch them later.
auto called_fns = function_ids;
// clear the function_ids.
function_ids.clear();
// patch the functions we've called before.
for (const auto id : called_fns)
assert(__xray_patch_function(id) == XRayPatchingStatus::SUCCESS);
// then call them again.
foo();
assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// confirm that we've seen the same functions again.
printf("second pass.\n");
for (const auto id : function_ids)
printf("patched: %d\n", id);
// CHECK-LABEL: second pass.
// CHECK-DAG: patched: [[F1]]
// CHECK-DAG: patched: [[F2]]
// CHECK-DAG: patched: [[F3]]
// Now we want to make sure that if we unpatch one, that we're only going to
// see two calls of the coverage_handler.
function_ids.clear();
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
assert(__xray_unpatch_function(1) == XRayPatchingStatus::SUCCESS);
foo();
assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// confirm that we don't see function id one called anymore.
printf("missing 1.\n");
for (const auto id : function_ids)
printf("patched: %d\n", id);
// CHECK-LABEL: missing 1.
// CHECK-NOT: patched: 1
}

View File

@ -0,0 +1,42 @@
// Make sure we're aligning the stack properly when lowering the custom event
// calls.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \
// RUN: %run %t 2>&1
// REQUIRES: x86_64-target-arch
// REQUIRES: built-in-llvm-tree
#include <xmmintrin.h>
#include <stdio.h>
#include "xray/xray_interface.h"
[[clang::xray_never_instrument]] __attribute__((weak)) __m128 f(__m128 *i) {
return *i;
}
[[clang::xray_always_instrument]] void foo() {
__xray_customevent(0, 0);
__m128 v = {};
f(&v);
}
[[clang::xray_always_instrument]] void bar() {
__xray_customevent(0, 0);
}
void printer(void* ptr, size_t size) {
printf("handler called\n");
__m128 v = {};
f(&v);
}
int main(int argc, char* argv[]) {
__xray_set_customevent_handler(printer);
__xray_patch();
foo(); // CHECK: handler called
bar(); // CHECK: handler called
__xray_unpatch();
__xray_remove_customevent_handler();
foo();
bar();
}

View File

@ -0,0 +1,42 @@
// Use the clang feature for custom xray event logging.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false xray_logfile_base=custom-event-logging.xray-" %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_xray -std=c++11 -fpic -fpie %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false xray_logfile_base=custom-event-logging.xray-" %run %t 2>&1 | FileCheck %s
// FIXME: Support this in non-x86_64 as well
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include <cstdio>
#include "xray/xray_interface.h"
[[clang::xray_always_instrument]] void foo() {
static constexpr char CustomLogged[] = "hello custom logging!";
printf("before calling the custom logging...\n");
__xray_customevent(CustomLogged, sizeof(CustomLogged));
printf("after calling the custom logging...\n");
}
void myprinter(void* ptr, size_t size) {
printf("%.*s\n", static_cast<int>(size), static_cast<const char*>(ptr));
}
int main() {
foo();
// CHECK: before calling the custom logging...
// CHECK-NEXT: after calling the custom logging...
printf("setting up custom event handler...\n");
// CHECK-NEXT: setting up custom event handler...
__xray_set_customevent_handler(myprinter);
__xray_patch();
// CHECK-NEXT: before calling the custom logging...
foo();
// CHECK-NEXT: hello custom logging!
// CHECK-NEXT: after calling the custom logging...
printf("removing custom event handler...\n");
// CHECK-NEXT: removing custom event handler...
__xray_remove_customevent_handler();
foo();
// CHECK-NEXT: before calling the custom logging...
// CHECK-NEXT: after calling the custom logging...
}

View File

@ -0,0 +1,103 @@
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm fdr-logging-test-* || true
// RUN: rm fdr-unwrite-test-* || true
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false xray_logfile_base=fdr-logging-test- xray_fdr_log=true verbosity=1 xray_fdr_log_func_duration_threshold_us=0" %run %t 2>&1 | FileCheck %s
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false xray_logfile_base=fdr-unwrite-test- xray_fdr_log=true verbosity=1 xray_fdr_log_func_duration_threshold_us=5000" %run %t 2>&1 | FileCheck %s
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t "`ls fdr-logging-test-* | head -1`" | FileCheck %s --check-prefix=TRACE
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t "`ls fdr-unwrite-test-* | head -1`" | FileCheck %s --check-prefix=UNWRITE
// RUN: rm fdr-logging-test-*
// RUN: rm fdr-unwrite-test-*
// FIXME: Make llvm-xray work on non-x86_64 as well.
// REQUIRES: x86_64-target-arch
// REQUIRES: built-in-llvm-tree
#include "xray/xray_log_interface.h"
#include <cassert>
#include <chrono>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <thread>
#include <time.h>
constexpr auto kBufferSize = 16384;
constexpr auto kBufferMax = 10;
thread_local uint64_t var = 0;
[[clang::xray_always_instrument]] void __attribute__((noinline)) fC() { ++var; }
[[clang::xray_always_instrument]] void __attribute__((noinline)) fB() { fC(); }
[[clang::xray_always_instrument]] void __attribute__((noinline)) fA() { fB(); }
[[clang::xray_always_instrument, clang::xray_log_args(1)]]
void __attribute__((noinline)) fArg(int) { }
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Options;
std::cout << "Logging before init." << std::endl;
// CHECK: Logging before init.
auto status = __xray_log_init(kBufferSize, kBufferMax, &Options,
sizeof(FDRLoggingOptions));
assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
std::cout << "Init status " << status << std::endl;
// CHECK: Init status {{.*}}
std::cout << "Patching..." << std::endl;
// CHECK: Patching...
__xray_patch();
fA();
fC();
fB();
fA();
fC();
std::thread other_thread([]() {
fC();
fB();
fA();
fArg(1);
});
other_thread.join();
std::cout << "Joined" << std::endl;
// CHECK: Joined
std::cout << "Finalize status " << __xray_log_finalize() << std::endl;
// CHECK: Finalize status {{.*}}
fC();
std::cout << "Main execution var = " << var << std::endl;
// CHECK: Main execution var = 6
std::cout << "Flush status " << __xray_log_flushLog() << std::endl;
// CHECK: Flush status {{.*}}
__xray_unpatch();
return 0;
}
// Check that we're able to see two threads, each entering and exiting fA().
// TRACE-DAG: - { type: 0, func-id: [[FIDA:[0-9]+]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
//
// Do the same as above for fC()
// TRACE-DAG: - { type: 0, func-id: [[FIDC:[0-9]+]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// Do the same as above for fB()
// TRACE-DAG: - { type: 0, func-id: [[FIDB:[0-9]+]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2]], kind: function-enter-arg, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
// Assert that when unwriting is enabled with a high threshold time, all the function records are erased. A CPU switch could erroneously fail this test, but
// is unlikely given the test program.
// Even with a high threshold, arg1 logging is never unwritten.
// UNWRITE: header:
// UNWRITE: records:
// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter-arg, tsc: {{[0-9]+}} }
// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
// UNWRITE-NOT: function-enter
// UNWRITE-NOT: function-{{exit|tail-exit}}

View File

@ -0,0 +1,38 @@
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm fdr-logging-1thr-* || true
// RUN: XRAY_OPTIONS=XRAY_OPTIONS="verbosity=1 patch_premain=true \
// RUN: xray_naive_log=false xray_fdr_log=true \
// RUN: xray_fdr_log_func_duration_threshold_us=0 \
// RUN: xray_logfile_base=fdr-logging-1thr-" %run %t 2>&1
// RUN: %llvm_xray convert --output-format=yaml --symbolize --instr_map=%t \
// RUN: "`ls fdr-logging-1thr-* | head -n1`" | FileCheck %s
// RUN: rm fdr-logging-1thr-*
//
// REQUIRES: x86_64-target-arch
#include "xray/xray_log_interface.h"
#include <cassert>
constexpr auto kBufferSize = 16384;
constexpr auto kBufferMax = 10;
[[clang::xray_always_instrument]] void __attribute__((noinline)) fn() { }
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Opts;
auto status = __xray_log_init(kBufferSize, kBufferMax, &Opts, sizeof(Opts));
assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
__xray_patch();
fn();
__xray_unpatch();
assert(__xray_log_finalize() == XRAY_LOG_FINALIZED);
assert(__xray_log_flushLog() == XRAY_LOG_FLUSHED);
return 0;
}
// CHECK: records:
// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-exit, tsc: {{[0-9]+}} }

View File

@ -0,0 +1,67 @@
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm fdr-thread-order.* || true
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false \
// RUN: xray_logfile_base=fdr-thread-order. xray_fdr_log=true verbosity=1 \
// RUN: xray_fdr_log_func_duration_threshold_us=0" %run %t 2>&1 | \
// RUN: FileCheck %s
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
// RUN: "`ls fdr-thread-order.* | head -1`"
// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
// RUN: "`ls fdr-thread-order.* | head -1`" | \
// RUN: FileCheck %s --check-prefix TRACE
// RUN: rm fdr-thread-order.*
// FIXME: Make llvm-xray work on non-x86_64 as well.
// REQUIRES: x86_64-target-arch
// REQUIRES: built-in-llvm-tree
#include "xray/xray_log_interface.h"
#include <atomic>
#include <cassert>
#include <thread>
constexpr auto kBufferSize = 16384;
constexpr auto kBufferMax = 10;
std::atomic<uint64_t> var{0};
[[clang::xray_always_instrument]] void __attribute__((noinline)) f1() {
for (auto i = 0; i < 1 << 20; ++i)
++var;
}
[[clang::xray_always_instrument]] void __attribute__((noinline)) f2() {
for (auto i = 0; i < 1 << 20; ++i)
++var;
}
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Options;
__xray_patch();
assert(__xray_log_init(kBufferSize, kBufferMax, &Options,
sizeof(FDRLoggingOptions)) ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);
std::atomic_thread_fence(std::memory_order_acq_rel);
{
std::thread t1([] { f1(); });
std::thread t2([] { f2(); });
t1.join();
t2.join();
}
std::atomic_thread_fence(std::memory_order_acq_rel);
__xray_log_finalize();
__xray_log_flushLog();
__xray_unpatch();
return var > 0 ? 0 : 1;
// CHECK: {{.*}}XRay: Log file in '{{.*}}'
// CHECK-NOT: Failed
}
// We want to make sure that the order of the function log doesn't matter.
// TRACE-DAG: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID2:[0-9]+]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID1]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID2]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} }

View File

@ -0,0 +1,22 @@
// Check to make sure that we have a log file with a fixed-size.
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true verbosity=1 xray_logfile_base=fixedsize-logging-" %run %t 2>&1 | FileCheck %s
//
// After all that, clean up the output xray log.
//
// RUN: rm fixedsize-logging-*
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
[[clang::xray_always_instrument]] void foo() {
printf("foo() is always instrumented!");
}
int main() {
// CHECK: XRay: Log file in 'fixedsize-logging-{{.*}}'
foo();
// CHECK: foo() is always instrumented!
}

View File

@ -0,0 +1,44 @@
// Check that we can turn a function id to a function address, and also get the
// maximum function id for the current binary.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iterator>
#include <set>
[[clang::xray_always_instrument]] void bar(){}
[[clang::xray_always_instrument]] void foo() {
bar();
}
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
assert(__xray_max_function_id() != 0 && "we need xray instrumentation!");
std::set<void *> must_be_instrumented = {reinterpret_cast<void *>(&foo),
reinterpret_cast<void *>(&bar),
reinterpret_cast<void *>(&main)};
std::set<void *> all_instrumented;
for (auto i = __xray_max_function_id(); i != 0; --i) {
auto addr = __xray_function_address(i);
all_instrumented.insert(reinterpret_cast<void *>(addr));
}
assert(all_instrumented.size() == __xray_max_function_id() &&
"each function id must be assigned to a unique function");
std::set<void *> not_instrumented;
std::set_difference(
must_be_instrumented.begin(), must_be_instrumented.end(),
all_instrumented.begin(), all_instrumented.end(),
std::inserter(not_instrumented, not_instrumented.begin()));
assert(
not_instrumented.empty() &&
"we should see all explicitly instrumented functions with function ids");
return not_instrumented.empty() ? 0 : 1;
}

View File

@ -0,0 +1,59 @@
// Check that we can install an implementation associated with a mode.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: %run %t | FileCheck %s
//
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include "xray/xray_log_interface.h"
#include <cassert>
#include <cstdio>
[[clang::xray_never_instrument]] void printing_handler(int32_t fid,
XRayEntryType) {
thread_local volatile bool printing = false;
if (printing)
return;
printing = true;
std::printf("printing %d\n", fid);
printing = false;
}
[[clang::xray_never_instrument]] XRayLogInitStatus
printing_init(size_t, size_t, void *, size_t) {
return XRayLogInitStatus::XRAY_LOG_INITIALIZED;
}
[[clang::xray_never_instrument]] XRayLogInitStatus printing_finalize() {
return XRayLogInitStatus::XRAY_LOG_FINALIZED;
}
[[clang::xray_never_instrument]] XRayLogFlushStatus printing_flush_log() {
return XRayLogFlushStatus::XRAY_LOG_FLUSHED;
}
[[clang::xray_always_instrument]] void callme() { std::printf("called me!\n"); }
static bool unused = [] {
assert(__xray_log_register_mode("custom",
{printing_init, printing_finalize,
printing_handler, printing_flush_log}) ==
XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
return true;
}();
int main(int argc, char **argv) {
assert(__xray_log_select_mode("custom") ==
XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
assert(__xray_log_init(0, 0, nullptr, 0) ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);
// CHECK: printing {{.*}}
callme(); // CHECK: called me!
// CHECK: printing {{.*}}
assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED);
assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
assert(__xray_log_select_mode("not-found") ==
XRayLogRegisterStatus::XRAY_MODE_NOT_FOUND);
}

View File

@ -0,0 +1,23 @@
// Make sure that we don't get the inmemory logging implementation enabled when
// we turn it off via options.
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=false xray_logfile_base=optional-inmemory-log.xray-" %run %t 2>&1 | FileCheck %s
//
// Make sure we clean out the logs in case there was a bug.
//
// RUN: rm -f optional-inmemory-log.xray-*
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
[[clang::xray_always_instrument]] void foo() {
printf("foo() is always instrumented!");
}
int main() {
// CHECK-NOT: XRay: Log file in 'optional-inmemory-log.xray-{{.*}}'
foo();
// CHECK: foo() is always instrumented!
}

View File

@ -0,0 +1,49 @@
// Check that we can patch and un-patch on demand, and that logging gets invoked
// appropriately.
//
// RUN: %clangxx_xray -fxray-instrument -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include "xray/xray_interface.h"
#include <cstdio>
bool called = false;
void test_handler(int32_t fid, XRayEntryType type) {
printf("called: %d, type=%d\n", fid, static_cast<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", static_cast<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", static_cast<int32_t>(status));
// CHECK-NEXT: patching status: 1
always_instrument();
// CHECK-NEXT: always instrumented called
status = __xray_patch();
printf("patching status: %d\n", static_cast<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", static_cast<int32_t>(status));
// CHECK-NEXT: patching status: 1
}

View File

@ -0,0 +1,38 @@
// Test to check if we handle pic code properly.
// RUN: %clangxx_xray -fxray-instrument -std=c++11 -ffunction-sections \
// RUN: -fdata-sections -fpic -fpie -Wl,--gc-sections %s -o %t
// RUN: rm pic-test-logging-* || true
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \
// RUN: xray_logfile_base=pic-test-logging-" %run %t 2>&1 | FileCheck %s
// After all that, clean up the output xray log.
//
// RUN: rm pic-test-logging-* || true
// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
[[clang::xray_always_instrument]]
unsigned short foo (unsigned b);
[[clang::xray_always_instrument]]
unsigned short bar (unsigned short a)
{
printf("bar() is always instrumented!\n");
return foo(a);
}
unsigned short foo (unsigned b)
{
printf("foo() is always instrumented!\n");
return b + b + 5;
}
int main ()
{
// CHECK: XRay: Log file in 'pic-test-logging-{{.*}}'
bar(10);
// CHECK: bar() is always instrumented!
// CHECK-NEXT: foo() is always instrumented!
}

View File

@ -0,0 +1,26 @@
// Ensure that we have a quiet startup when we don't have the XRay
// instrumentation sleds.
//
// RUN: %clangxx -std=c++11 %s -o %t %xraylib
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1" %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix NOISY
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=0" %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix QUIET
// RUN: XRAY_OPTIONS="" %run %t 2>&1 | FileCheck %s --check-prefix DEFAULT
//
// FIXME: Understand how to make this work on other platforms
// REQUIRES: built-in-llvm-tree
// REQUIRES: x86_64-target-arch
#include <iostream>
using namespace std;
int main(int, char**) {
// NOISY: {{.*}}XRay instrumentation map missing. Not initializing XRay.
// QUIET-NOT: {{.*}}XRay instrumentation map missing. Not initializing XRay.
// DEFAULT-NOT: {{.*}}XRay instrumentation map missing. Not initializing XRay.
cout << "Hello, XRay!" << endl;
// NOISY: Hello, XRay!
// QUIET: Hello, XRay!
// DEFAULT: Hello, XRay!
}

View File

@ -18,6 +18,9 @@ def build_invocation(compile_flags):
# Assume that llvm-xray is in the config.llvm_tools_dir.
llvm_xray = os.path.join(config.llvm_tools_dir, 'llvm-xray')
host_arch = config.host_arch
if host_arch == 'amd64':
host_arch = 'x86_64'
# Setup substitutions.
if config.host_os == "Linux":
@ -40,7 +43,7 @@ config.substitutions.append(
('%xraylib',
('-lm -lpthread %s -lrt -L%s '
'-Wl,-whole-archive -lclang_rt.xray-%s -Wl,-no-whole-archive')
% (libdl_flag, config.compiler_rt_libdir, config.host_arch)))
% (libdl_flag, config.compiler_rt_libdir, host_arch)))
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp']