Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp
35266 views
1
//===-- OProfileWrapper.cpp - OProfile JIT API Wrapper implementation -----===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the interface in OProfileWrapper.h. It is responsible
10
// for loading the opagent dynamic library when the first call to an op_
11
// function occurs.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "llvm/ExecutionEngine/OProfileWrapper.h"
16
#include "llvm/ADT/SmallString.h"
17
#include "llvm/Support/Debug.h"
18
#include "llvm/Support/DynamicLibrary.h"
19
#include "llvm/Support/Mutex.h"
20
#include "llvm/Support/raw_ostream.h"
21
#include <cstring>
22
#include <dirent.h>
23
#include <fcntl.h>
24
#include <mutex>
25
#include <stddef.h>
26
#include <sys/stat.h>
27
#include <unistd.h>
28
29
#define DEBUG_TYPE "oprofile-wrapper"
30
31
namespace {
32
33
// Global mutex to ensure a single thread initializes oprofile agent.
34
llvm::sys::Mutex OProfileInitializationMutex;
35
36
} // anonymous namespace
37
38
namespace llvm {
39
40
OProfileWrapper::OProfileWrapper()
41
: Agent(0),
42
OpenAgentFunc(0),
43
CloseAgentFunc(0),
44
WriteNativeCodeFunc(0),
45
WriteDebugLineInfoFunc(0),
46
UnloadNativeCodeFunc(0),
47
MajorVersionFunc(0),
48
MinorVersionFunc(0),
49
IsOProfileRunningFunc(0),
50
Initialized(false) {
51
}
52
53
bool OProfileWrapper::initialize() {
54
using namespace llvm;
55
using namespace llvm::sys;
56
57
std::lock_guard<sys::Mutex> Guard(OProfileInitializationMutex);
58
59
if (Initialized)
60
return OpenAgentFunc != 0;
61
62
Initialized = true;
63
64
// If the oprofile daemon is not running, don't load the opagent library
65
if (!isOProfileRunning()) {
66
LLVM_DEBUG(dbgs() << "OProfile daemon is not detected.\n");
67
return false;
68
}
69
70
std::string error;
71
if(!DynamicLibrary::LoadLibraryPermanently("libopagent.so", &error)) {
72
LLVM_DEBUG(
73
dbgs()
74
<< "OProfile connector library libopagent.so could not be loaded: "
75
<< error << "\n");
76
}
77
78
// Get the addresses of the opagent functions
79
OpenAgentFunc = (op_open_agent_ptr_t)(intptr_t)
80
DynamicLibrary::SearchForAddressOfSymbol("op_open_agent");
81
CloseAgentFunc = (op_close_agent_ptr_t)(intptr_t)
82
DynamicLibrary::SearchForAddressOfSymbol("op_close_agent");
83
WriteNativeCodeFunc = (op_write_native_code_ptr_t)(intptr_t)
84
DynamicLibrary::SearchForAddressOfSymbol("op_write_native_code");
85
WriteDebugLineInfoFunc = (op_write_debug_line_info_ptr_t)(intptr_t)
86
DynamicLibrary::SearchForAddressOfSymbol("op_write_debug_line_info");
87
UnloadNativeCodeFunc = (op_unload_native_code_ptr_t)(intptr_t)
88
DynamicLibrary::SearchForAddressOfSymbol("op_unload_native_code");
89
MajorVersionFunc = (op_major_version_ptr_t)(intptr_t)
90
DynamicLibrary::SearchForAddressOfSymbol("op_major_version");
91
MinorVersionFunc = (op_major_version_ptr_t)(intptr_t)
92
DynamicLibrary::SearchForAddressOfSymbol("op_minor_version");
93
94
// With missing functions, we can do nothing
95
if (!OpenAgentFunc
96
|| !CloseAgentFunc
97
|| !WriteNativeCodeFunc
98
|| !WriteDebugLineInfoFunc
99
|| !UnloadNativeCodeFunc) {
100
OpenAgentFunc = 0;
101
CloseAgentFunc = 0;
102
WriteNativeCodeFunc = 0;
103
WriteDebugLineInfoFunc = 0;
104
UnloadNativeCodeFunc = 0;
105
return false;
106
}
107
108
return true;
109
}
110
111
bool OProfileWrapper::isOProfileRunning() {
112
if (IsOProfileRunningFunc != 0)
113
return IsOProfileRunningFunc();
114
return checkForOProfileProcEntry();
115
}
116
117
bool OProfileWrapper::checkForOProfileProcEntry() {
118
DIR* ProcDir;
119
120
ProcDir = opendir("/proc");
121
if (!ProcDir)
122
return false;
123
124
// Walk the /proc tree looking for the oprofile daemon
125
struct dirent* Entry;
126
while (0 != (Entry = readdir(ProcDir))) {
127
if (Entry->d_type == DT_DIR) {
128
// Build a path from the current entry name
129
SmallString<256> CmdLineFName;
130
raw_svector_ostream(CmdLineFName) << "/proc/" << Entry->d_name
131
<< "/cmdline";
132
133
// Open the cmdline file
134
int CmdLineFD = open(CmdLineFName.c_str(), S_IRUSR);
135
if (CmdLineFD != -1) {
136
char ExeName[PATH_MAX+1];
137
char* BaseName = 0;
138
139
// Read the cmdline file
140
ssize_t NumRead = read(CmdLineFD, ExeName, PATH_MAX+1);
141
close(CmdLineFD);
142
ssize_t Idx = 0;
143
144
if (ExeName[0] != '/') {
145
BaseName = ExeName;
146
}
147
148
// Find the terminator for the first string
149
while (Idx < NumRead-1 && ExeName[Idx] != 0) {
150
Idx++;
151
}
152
153
// Go back to the last non-null character
154
Idx--;
155
156
// Find the last path separator in the first string
157
while (Idx > 0) {
158
if (ExeName[Idx] == '/') {
159
BaseName = ExeName + Idx + 1;
160
break;
161
}
162
Idx--;
163
}
164
165
// Test this to see if it is the oprofile daemon
166
if (BaseName != 0 && (!strcmp("oprofiled", BaseName) ||
167
!strcmp("operf", BaseName))) {
168
// If it is, we're done
169
closedir(ProcDir);
170
return true;
171
}
172
}
173
}
174
}
175
176
// We've looked through all the files and didn't find the daemon
177
closedir(ProcDir);
178
return false;
179
}
180
181
bool OProfileWrapper::op_open_agent() {
182
if (!Initialized)
183
initialize();
184
185
if (OpenAgentFunc != 0) {
186
Agent = OpenAgentFunc();
187
return Agent != 0;
188
}
189
190
return false;
191
}
192
193
int OProfileWrapper::op_close_agent() {
194
if (!Initialized)
195
initialize();
196
197
int ret = -1;
198
if (Agent && CloseAgentFunc) {
199
ret = CloseAgentFunc(Agent);
200
if (ret == 0) {
201
Agent = 0;
202
}
203
}
204
return ret;
205
}
206
207
bool OProfileWrapper::isAgentAvailable() {
208
return Agent != 0;
209
}
210
211
int OProfileWrapper::op_write_native_code(const char* Name,
212
uint64_t Addr,
213
void const* Code,
214
const unsigned int Size) {
215
if (!Initialized)
216
initialize();
217
218
if (Agent && WriteNativeCodeFunc)
219
return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size);
220
221
return -1;
222
}
223
224
int OProfileWrapper::op_write_debug_line_info(
225
void const* Code,
226
size_t NumEntries,
227
struct debug_line_info const* Info) {
228
if (!Initialized)
229
initialize();
230
231
if (Agent && WriteDebugLineInfoFunc)
232
return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info);
233
234
return -1;
235
}
236
237
int OProfileWrapper::op_major_version() {
238
if (!Initialized)
239
initialize();
240
241
if (Agent && MajorVersionFunc)
242
return MajorVersionFunc();
243
244
return -1;
245
}
246
247
int OProfileWrapper::op_minor_version() {
248
if (!Initialized)
249
initialize();
250
251
if (Agent && MinorVersionFunc)
252
return MinorVersionFunc();
253
254
return -1;
255
}
256
257
int OProfileWrapper::op_unload_native_code(uint64_t Addr) {
258
if (!Initialized)
259
initialize();
260
261
if (Agent && UnloadNativeCodeFunc)
262
return UnloadNativeCodeFunc(Agent, Addr);
263
264
return -1;
265
}
266
267
} // namespace llvm
268
269