Skip to content

Commit e1c81d1

Browse files
committedJul 20, 2016
[compiler-rt] [XRay] Basic initialization and flag definition for XRay runtime
Summary: This patch implements the initialisation and patching routines for the XRay runtime, along with the necessary trampolines for function entry/exit handling. For now we only define the basic hooks for allowing an implementation to define a handler that gets run on function entry/exit. We expose a minimal API for controlling the behaviour of the runtime (patching, cleanup, and setting the handler to invoke when instrumenting). Depends on D19904 Reviewers: echristo, kcc, rnk Subscribers: rnk, mehdi_amini, llvm-commits Differential Revision: https://reviews.llvm.org/D21612 llvm-svn: 276117
1 parent 080dcf7 commit e1c81d1

13 files changed

+632
-1
lines changed
 

‎compiler-rt/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON)
3737
mark_as_advanced(COMPILER_RT_BUILD_BUILTINS)
3838
option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON)
3939
mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS)
40+
option(COMPILER_RT_BUILD_XRAY "Build xray" ON)
41+
mark_as_advanced(COMPILER_RT_BUILD_XRAY)
4042

4143
if (COMPILER_RT_STANDALONE_BUILD)
4244
if (NOT LLVM_CONFIG_PATH)

‎compiler-rt/cmake/config-ix.cmake

+5
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64})
161161
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64})
162162
set(ALL_ESAN_SUPPORTED_ARCH ${X86_64})
163163
set(ALL_SCUDO_SUPPORTED_ARCH ${X86_64})
164+
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
164165

165166
if(APPLE)
166167
include(CompilerRTDarwinUtils)
@@ -350,6 +351,9 @@ if(APPLE)
350351
list_intersect(SCUDO_SUPPORTED_ARCH
351352
ALL_SCUDO_SUPPORTED_ARCH
352353
SANITIZER_COMMON_SUPPORTED_ARCH)
354+
list_intersect(XRAY_SUPPORTED_ARCH
355+
ALL_XRAY_SUPPORTED_ARCH
356+
SANITIZER_COMMON_SUPPORTED_ARCH)
353357
else()
354358
# Architectures supported by compiler-rt libraries.
355359
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
@@ -373,6 +377,7 @@ else()
373377
filter_available_targets(ESAN_SUPPORTED_ARCH ${ALL_ESAN_SUPPORTED_ARCH})
374378
filter_available_targets(SCUDO_SUPPORTED_ARCH
375379
${ALL_SCUDO_SUPPORTED_ARCH})
380+
filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH})
376381
endif()
377382

378383
if (MSVC)

‎compiler-rt/include/CMakeLists.txt

+12-1
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@ set(SANITIZER_HEADERS
1010
sanitizer/msan_interface.h
1111
sanitizer/tsan_interface_atomic.h)
1212

13+
set(XRAY_HEADERS
14+
xray/xray_interface.h)
15+
16+
set(COMPILER_RT_HEADERS
17+
${SANITIZER_HEADERS}
18+
${XRAY_HEADERS})
19+
1320
set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include)
1421

1522
# Copy compiler-rt headers to the build tree.
1623
set(out_files)
17-
foreach( f ${SANITIZER_HEADERS} )
24+
foreach( f ${COMPILER_RT_HEADERS} )
1825
set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} )
1926
set( dst ${output_dir}/${f} )
2027
add_custom_command(OUTPUT ${dst}
@@ -32,3 +39,7 @@ set_target_properties(compiler-rt-headers PROPERTIES FOLDER "Compiler-RT Misc")
3239
install(FILES ${SANITIZER_HEADERS}
3340
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
3441
DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/sanitizer)
42+
# Install xray headers.
43+
install(FILES ${XRAY_HEADERS}
44+
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
45+
DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/xray)
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===-- xray_interface.h ----------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file is a part of XRay, a dynamic runtime instrumentation system.
11+
//
12+
// APIs for controlling XRay functionality explicitly.
13+
//===----------------------------------------------------------------------===//
14+
#ifndef XRAY_XRAY_INTERFACE_H
15+
#define XRAY_XRAY_INTERFACE_H
16+
17+
#include <cstdint>
18+
19+
extern "C" {
20+
21+
enum XRayEntryType { ENTRY = 0, EXIT = 1 };
22+
23+
// Provide a function to invoke for when instrumentation points are hit. This is
24+
// a user-visible control surface that overrides the default implementation. The
25+
// function provided should take the following arguments:
26+
//
27+
// - function id: an identifier that indicates the id of a function; this id
28+
// is generated by xray; the mapping between the function id
29+
// and the actual function pointer is available through
30+
// __xray_table.
31+
// - entry type: identifies what kind of instrumentation point was encountered
32+
// (function entry, function exit, etc.). See the enum
33+
// XRayEntryType for more details.
34+
//
35+
// Returns 1 on success, 0 on error.
36+
extern int __xray_set_handler(void (*entry)(int32_t, XRayEntryType));
37+
38+
// This removes whatever the currently provided handler is. Returns 1 on
39+
// success, 0 on error.
40+
extern int __xray_remove_handler();
41+
42+
enum XRayPatchingStatus {
43+
NOT_INITIALIZED = 0,
44+
NOTIFIED = 1,
45+
ONGOING = 2,
46+
FAILED = 3
47+
};
48+
49+
// This tells XRay to patch the instrumentation points. This is an asynchronous
50+
// process, and returns the following status in specific cases:
51+
//
52+
// - 0 : XRay is not initialized.
53+
// - 1 : We've done the notification.
54+
// - 2 : Patching / un-patching is on-going.
55+
extern XRayPatchingStatus __xray_patch();
56+
57+
// Reverses the effect of __xray_patch(). This is an asynchronous process, and
58+
// returns the following status in specific cases.
59+
//
60+
// - 0 : XRay is not initialized.
61+
// - 1 : We've done the notification.
62+
// - 2 : Patching / un-patching is on-going.
63+
extern int __xray_unpatch();
64+
}
65+
66+
#endif

‎compiler-rt/lib/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,7 @@ if(COMPILER_RT_BUILD_SANITIZERS)
5757
add_subdirectory(scudo)
5858
endif()
5959
endif()
60+
61+
if(COMPILER_RT_BUILD_XRAY)
62+
add_subdirectory(xray)
63+
endif()

‎compiler-rt/lib/xray/CMakeLists.txt

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Build for the XRay runtime support library.
2+
3+
set(XRAY_SOURCES
4+
xray_init.cc
5+
xray_interface.cc
6+
xray_flags.cc
7+
)
8+
9+
set(x86_64_SOURCES
10+
xray_trampoline_x86.S
11+
${XRAY_SOURCES})
12+
13+
include_directories(..)
14+
include_directories(../../include)
15+
16+
set(XRAY_CFLAGS ${SANITIZER_COMMON_CFLAGS})
17+
18+
set(XRAY_COMMON_DEFINITIONS XRAY_HAS_EXCEPTIONS=1)
19+
20+
add_compiler_rt_object_libraries(RTXray
21+
ARCHS ${XRAY_SUPPORTED_ARCH}
22+
SOURCES ${XRAY_SOURCES} CFLAGS ${XRAY_CFLAGS}
23+
DEFS ${XRAY_COMMON_DEFINITIONS})
24+
25+
add_custom_target(xray)
26+
set(XRAY_COMMON_RUNTIME_OBJECT_LIBS
27+
RTSanitizerCommon
28+
RTSanitizerCommonLibc)
29+
30+
foreach (arch ${XRAY_SUPPORTED_ARCH})
31+
if (CAN_TARGET_${arch})
32+
add_compiler_rt_runtime(clang_rt.xray
33+
STATIC
34+
ARCHS ${arch}
35+
SOURCES ${${arch}_SOURCES}
36+
CFLAGS ${XRAY_CFLAGS}
37+
DEFS ${XRAY_COMMON_DEFINITIONS}
38+
OBJECT_LIBS ${XRAY_COMMON_RUNTIME_OBJECT_LIBS}
39+
PARENT_TARGET xray)
40+
endif ()
41+
endforeach()
42+
43+
add_dependencies(compiler-rt xray)
44+
45+
# if(COMPILER_RT_INCLUDE_TESTS)
46+
# add_subdirectory(tests)
47+
# endif()

‎compiler-rt/lib/xray/xray_flags.cc

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===-- xray_flags.cc -------------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file is a part of XRay, a dynamic runtime instrumentation system.
11+
//
12+
// XRay flag parsing logic.
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "xray_flags.h"
16+
#include "sanitizer_common/sanitizer_common.h"
17+
#include "sanitizer_common/sanitizer_flag_parser.h"
18+
#include "sanitizer_common/sanitizer_libc.h"
19+
20+
using namespace __sanitizer;
21+
22+
namespace __xray {
23+
24+
Flags xray_flags_dont_use_directly; // use via flags().
25+
26+
void Flags::SetDefaults() {
27+
#define XRAY_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
28+
#include "xray_flags.inc"
29+
#undef XRAY_FLAG
30+
}
31+
32+
static void RegisterXRayFlags(FlagParser *P, Flags *F) {
33+
#define XRAY_FLAG(Type, Name, DefaultValue, Description) \
34+
RegisterFlag(P, #Name, Description, &F->Name);
35+
#include "xray_flags.inc"
36+
#undef XRAY_FLAG
37+
}
38+
39+
void InitializeFlags() {
40+
SetCommonFlagsDefaults();
41+
auto *F = flags();
42+
F->SetDefaults();
43+
44+
FlagParser XRayParser;
45+
RegisterXRayFlags(&XRayParser, F);
46+
RegisterCommonFlags(&XRayParser);
47+
48+
// Override from command line.
49+
XRayParser.ParseString(GetEnv("XRAY_OPTIONS"));
50+
51+
InitializeCommonFlags();
52+
53+
if (Verbosity())
54+
ReportUnrecognizedFlags();
55+
56+
if (common_flags()->help) {
57+
XRayParser.PrintFlagDescriptions();
58+
}
59+
}
60+
61+
} // namespace __xray

‎compiler-rt/lib/xray/xray_flags.h

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===-- xray_flags.h -------------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file is a part of XRay, a dynamic runtime instruementation system.
11+
//
12+
// XRay runtime flags.
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef XRAY_FLAGS_H
16+
#define XRAY_FLAGS_H
17+
18+
#include "sanitizer_common/sanitizer_flag_parser.h"
19+
20+
namespace __xray {
21+
22+
struct Flags {
23+
#define XRAY_FLAG(Type, Name, DefaultValue, Description) Type Name;
24+
#include "xray_flags.inc"
25+
#undef XRAY_FLAG
26+
27+
void SetDefaults();
28+
};
29+
30+
extern Flags xray_flags_dont_use_directly;
31+
inline Flags *flags() { return &xray_flags_dont_use_directly; }
32+
33+
void InitializeFlags();
34+
35+
} // namespace __xray
36+
37+
#endif // XRAY_FLAGS_H

‎compiler-rt/lib/xray/xray_flags.inc

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===-- xray_flags.inc ------------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// XRay runtime flags.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
#ifndef XRAY_FLAG
14+
#error "Define XRAY_FLAG prior to including this file!"
15+
#endif
16+
17+
XRAY_FLAG(bool, patch_premain, true,
18+
"Whether to patch instrumentation points before main.")

‎compiler-rt/lib/xray/xray_init.cc

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//===-- xray_init.cc --------------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file is a part of XRay, a dynamic runtime instrumentation system.
11+
//
12+
// XRay initialisation logic.
13+
//===----------------------------------------------------------------------===//
14+
15+
#include <atomic>
16+
#include <fcntl.h>
17+
#include <strings.h>
18+
#include <unistd.h>
19+
20+
#include "sanitizer_common/sanitizer_common.h"
21+
#include "xray_flags.h"
22+
#include "xray_interface_internal.h"
23+
#include "llvm/Support/ELF.h"
24+
25+
extern "C" {
26+
extern void __xray_init();
27+
extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));
28+
extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));
29+
}
30+
31+
using namespace __xray;
32+
33+
// We initialize some global variables that pertain to specific sections of XRay
34+
// data structures in the binary. We do this for the current process using
35+
// /proc/curproc/map and make sure that we're able to get it. We signal failure
36+
// via a global atomic boolean to indicate whether we've initialized properly.
37+
//
38+
std::atomic<bool> XRayInitialized{false};
39+
40+
// This should always be updated before XRayInitialized is updated.
41+
std::atomic<__xray::XRaySledMap> XRayInstrMap{};
42+
43+
// __xray_init() will do the actual loading of the current process' memory map
44+
// and then proceed to look for the .xray_instr_map section/segment.
45+
void __xray_init() {
46+
InitializeFlags();
47+
if (__start_xray_instr_map == nullptr) {
48+
Report("XRay instrumentation map missing. Not initializing XRay.\n");
49+
return;
50+
}
51+
52+
// Now initialize the XRayInstrMap global struct with the address of the
53+
// entries, reinterpreted as an array of XRaySledEntry objects. We use the
54+
// virtual pointer we have from the section to provide us the correct
55+
// information.
56+
__xray::XRaySledMap SledMap{};
57+
SledMap.Sleds = __start_xray_instr_map;
58+
SledMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;
59+
XRayInstrMap.store(SledMap, std::memory_order_release);
60+
XRayInitialized.store(true, std::memory_order_release);
61+
62+
// FIXME: Check the flag/environment before patching.
63+
if (flags()->patch_premain)
64+
__xray_patch();
65+
}
66+
67+
__attribute__((section(".preinit_array"),
68+
used)) void (*__local_xray_preinit)(void) = __xray_init;

0 commit comments

Comments
 (0)