Skip to content

Commit 17a586e

Browse files
committedJul 29, 2016
[compiler-rt][XRay] Address follow-up comments to initial interface and initialisation code
This addresses some comments from D21612, which contains the following changes: - Update __xray_patch() and __xray_unpatch() API documentation to not imply asynchrony. - Introduce a scope cleanup mechanism to make sure we can roll-back changes to the XRayPatching global atomic. - Introduce a few more comments for potential extension points for other platforms (for the implementation details of patching and un-patching). Reviewers: eugenis, rnk, kcc, echristo, majnemer Subscribers: llvm-commits, mehdi_amini Differential Revision: https://reviews.llvm.org/D22911 llvm-svn: 277124
1 parent 8129255 commit 17a586e

File tree

3 files changed

+54
-24
lines changed

3 files changed

+54
-24
lines changed
 

‎compiler-rt/include/xray/xray_interface.h

+7-15
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,18 @@ extern int __xray_remove_handler();
4141

4242
enum XRayPatchingStatus {
4343
NOT_INITIALIZED = 0,
44-
NOTIFIED = 1,
44+
SUCCESS = 1,
4545
ONGOING = 2,
46-
FAILED = 3
46+
FAILED = 3,
4747
};
4848

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.
49+
// This tells XRay to patch the instrumentation points. See XRayPatchingStatus
50+
// for possible result values.
5551
extern XRayPatchingStatus __xray_patch();
5652

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();
53+
// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
54+
// result values.
55+
extern XRayPatchingStatus __xray_unpatch();
6456
}
6557

6658
#endif

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

+7-5
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,20 @@
2222
#include "xray_interface_internal.h"
2323

2424
extern "C" {
25-
extern void __xray_init();
25+
void __xray_init();
2626
extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));
2727
extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));
2828
}
2929

3030
using namespace __xray;
3131

32-
// We initialize some global variables that pertain to specific sections of XRay
33-
// data structures in the binary. We do this for the current process using
34-
// /proc/curproc/map and make sure that we're able to get it. We signal failure
35-
// via a global atomic boolean to indicate whether we've initialized properly.
32+
// When set to 'true' this means the XRay runtime has been initialised. We use
33+
// the weak symbols defined above (__start_xray_inst_map and
34+
// __stop_xray_instr_map) to initialise the instrumentation map that XRay uses
35+
// for runtime patching/unpatching of instrumentation points.
3636
//
37+
// FIXME: Support DSO instrumentation maps too. The current solution only works
38+
// for statically linked executables.
3739
std::atomic<bool> XRayInitialized{false};
3840

3941
// This should always be updated before XRayInitialized is updated.

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

+40-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414
//===----------------------------------------------------------------------===//
1515

1616
#include "xray_interface_internal.h"
17+
1718
#include <atomic>
1819
#include <cstdint>
1920
#include <cstdio>
2021
#include <errno.h>
2122
#include <limits>
2223
#include <sys/mman.h>
2324

25+
#include "sanitizer_common/sanitizer_common.h"
26+
2427
namespace __xray {
2528

2629
// This is the function to call when we encounter the entry or exit sleds.
@@ -83,8 +86,25 @@ std::atomic<bool> XRayPatching{false};
8386

8487
using namespace __xray;
8588

89+
// FIXME: Figure out whether we can move this class to sanitizer_common instead
90+
// as a generic "scope guard".
91+
template <class Function> class CleanupInvoker {
92+
Function Fn;
93+
94+
public:
95+
explicit CleanupInvoker(Function Fn) : Fn(Fn) {}
96+
CleanupInvoker(const CleanupInvoker &) = default;
97+
CleanupInvoker(CleanupInvoker &&) = default;
98+
CleanupInvoker &operator=(const CleanupInvoker &) = delete;
99+
CleanupInvoker &operator=(CleanupInvoker &&) = delete;
100+
~CleanupInvoker() { Fn(); }
101+
};
102+
103+
template <class Function> CleanupInvoker<Function> ScopeCleanup(Function Fn) {
104+
return CleanupInvoker<Function>{Fn};
105+
}
106+
86107
XRayPatchingStatus __xray_patch() {
87-
// FIXME: Make this happen asynchronously. For now just do this sequentially.
88108
if (!XRayInitialized.load(std::memory_order_acquire))
89109
return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.
90110

@@ -95,6 +115,13 @@ XRayPatchingStatus __xray_patch() {
95115
return XRayPatchingStatus::ONGOING; // Already patching.
96116
}
97117

118+
bool PatchingSuccess = false;
119+
auto XRayPatchingStatusResetter = ScopeCleanup([&PatchingSuccess] {
120+
if (!PatchingSuccess) {
121+
XRayPatching.store(false, std::memory_order_release);
122+
}
123+
});
124+
98125
// Step 1: Compute the function id, as a unique identifier per function in the
99126
// instrumentation map.
100127
XRaySledMap InstrMap = XRayInstrMap.load(std::memory_order_acquire);
@@ -131,6 +158,7 @@ XRayPatchingStatus __xray_patch() {
131158
static constexpr int64_t MinOffset{std::numeric_limits<int32_t>::min()};
132159
static constexpr int64_t MaxOffset{std::numeric_limits<int32_t>::max()};
133160
if (Sled.Kind == XRayEntryType::ENTRY) {
161+
// FIXME: Implement this in a more extensible manner, per-platform.
134162
// Here we do the dance of replacing the following sled:
135163
//
136164
// xray_sled_n:
@@ -157,7 +185,10 @@ XRayPatchingStatus __xray_patch() {
157185
reinterpret_cast<int64_t>(__xray_FunctionEntry) -
158186
(static_cast<int64_t>(Sled.Address) + 11);
159187
if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {
160-
// FIXME: Print out an error here.
188+
Report("XRay Entry trampoline (%p) too far from sled (%p); distance = "
189+
"%ld\n",
190+
__xray_FunctionEntry, reinterpret_cast<void *>(Sled.Address),
191+
TrampolineOffset);
161192
continue;
162193
}
163194
*reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId;
@@ -169,6 +200,7 @@ XRayPatchingStatus __xray_patch() {
169200
}
170201

171202
if (Sled.Kind == XRayEntryType::EXIT) {
203+
// FIXME: Implement this in a more extensible manner, per-platform.
172204
// Here we do the dance of replacing the following sled:
173205
//
174206
// xray_sled_n:
@@ -193,7 +225,10 @@ XRayPatchingStatus __xray_patch() {
193225
reinterpret_cast<int64_t>(__xray_FunctionExit) -
194226
(static_cast<int64_t>(Sled.Address) + 11);
195227
if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {
196-
// FIXME: Print out an error here.
228+
Report("XRay Exit trampoline (%p) too far from sled (%p); distance = "
229+
"%ld\n",
230+
__xray_FunctionExit, reinterpret_cast<void *>(Sled.Address),
231+
TrampolineOffset);
197232
continue;
198233
}
199234
*reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId;
@@ -205,5 +240,6 @@ XRayPatchingStatus __xray_patch() {
205240
}
206241
}
207242
XRayPatching.store(false, std::memory_order_release);
208-
return XRayPatchingStatus::NOTIFIED;
243+
PatchingSuccess = true;
244+
return XRayPatchingStatus::SUCCESS;
209245
}

0 commit comments

Comments
 (0)
Please sign in to comment.