forked from OSchip/llvm-project
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:
parent
0ac2eb7369
commit
80c2a79437
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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]));
|
||||
}
|
|
@ -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]+}} }
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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...
|
||||
}
|
|
@ -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}}
|
|
@ -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]+}} }
|
|
@ -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]+}} }
|
|
@ -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!
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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!
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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!
|
||||
}
|
|
@ -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!
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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]));
|
||||
}
|
|
@ -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]+}} }
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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...
|
||||
}
|
|
@ -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}}
|
|
@ -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]+}} }
|
|
@ -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]+}} }
|
|
@ -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!
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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!
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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!
|
||||
}
|
|
@ -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!
|
||||
}
|
|
@ -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']
|
||||
|
|
Loading…
Reference in New Issue