blob: dca48603cfc11f44db9a3e3b2aff4fd8f16c1b55 [file] [log] [blame]
Eli Bendersky61b18512012-03-13 08:33:15 +00001//===-- OProfileWrapper.cpp - OProfile JIT API Wrapper implementation -----===//
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 implements the interface in OProfileWrapper.h. It is responsible
11// for loading the opagent dynamic library when the first call to an op_
12// function occurs.
13//
14//===----------------------------------------------------------------------===//
15
Eli Bendersky61b18512012-03-13 08:33:15 +000016#define DEBUG_TYPE "oprofile-wrapper"
Bill Wendlingdd778b22013-08-21 21:14:19 +000017#include "llvm/ExecutionEngine/OProfileWrapper.h"
Eli Bendersky61b18512012-03-13 08:33:15 +000018#include "llvm/Support/Debug.h"
19#include "llvm/Support/raw_ostream.h"
20#include "llvm/Support/DynamicLibrary.h"
21#include "llvm/Support/Mutex.h"
22#include "llvm/Support/MutexGuard.h"
23#include "llvm/ADT/SmallString.h"
Eli Bendersky61b18512012-03-13 08:33:15 +000024#include <cstring>
Eli Bendersky61b18512012-03-13 08:33:15 +000025#include <dirent.h>
Eli Bendersky61b18512012-03-13 08:33:15 +000026#include <fcntl.h>
Bill Wendlingdd778b22013-08-21 21:14:19 +000027#include <sstream>
28#include <stddef.h>
29#include <sys/stat.h>
Will Schmidtdf5b3302013-02-07 20:43:33 +000030#include <unistd.h>
Eli Bendersky61b18512012-03-13 08:33:15 +000031
32namespace {
33
34// Global mutex to ensure a single thread initializes oprofile agent.
35llvm::sys::Mutex OProfileInitializationMutex;
36
37} // anonymous namespace
38
39namespace llvm {
40
41OProfileWrapper::OProfileWrapper()
42: Agent(0),
43 OpenAgentFunc(0),
44 CloseAgentFunc(0),
45 WriteNativeCodeFunc(0),
46 WriteDebugLineInfoFunc(0),
47 UnloadNativeCodeFunc(0),
48 MajorVersionFunc(0),
49 MinorVersionFunc(0),
50 IsOProfileRunningFunc(0),
51 Initialized(false) {
52}
53
54bool OProfileWrapper::initialize() {
55 using namespace llvm;
56 using namespace llvm::sys;
57
58 MutexGuard Guard(OProfileInitializationMutex);
59
60 if (Initialized)
61 return OpenAgentFunc != 0;
62
63 Initialized = true;
64
65 // If the oprofile daemon is not running, don't load the opagent library
66 if (!isOProfileRunning()) {
67 DEBUG(dbgs() << "OProfile daemon is not detected.\n");
68 return false;
69 }
70
71 std::string error;
72 if(!DynamicLibrary::LoadLibraryPermanently("libopagent.so", &error)) {
73 DEBUG(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
111bool OProfileWrapper::isOProfileRunning() {
112 if (IsOProfileRunningFunc != 0)
113 return IsOProfileRunningFunc();
114 return checkForOProfileProcEntry();
115}
116
117bool 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 // Find the terminator for the first string
145 while (Idx < NumRead-1 && ExeName[Idx] != 0) {
146 Idx++;
147 }
148
149 // Go back to the last non-null character
150 Idx--;
151
152 // Find the last path separator in the first string
153 while (Idx > 0) {
154 if (ExeName[Idx] == '/') {
155 BaseName = ExeName + Idx + 1;
156 break;
157 }
158 Idx--;
159 }
160
161 // Test this to see if it is the oprofile daemon
162 if (BaseName != 0 && !strcmp("oprofiled", BaseName)) {
163 // If it is, we're done
164 closedir(ProcDir);
165 return true;
166 }
167 }
168 }
169 }
170
171 // We've looked through all the files and didn't find the daemon
172 closedir(ProcDir);
173 return false;
174}
175
176bool OProfileWrapper::op_open_agent() {
177 if (!Initialized)
178 initialize();
179
180 if (OpenAgentFunc != 0) {
181 Agent = OpenAgentFunc();
182 return Agent != 0;
183 }
184
185 return false;
186}
187
188int OProfileWrapper::op_close_agent() {
189 if (!Initialized)
190 initialize();
191
192 int ret = -1;
193 if (Agent && CloseAgentFunc) {
194 ret = CloseAgentFunc(Agent);
195 if (ret == 0) {
196 Agent = 0;
197 }
198 }
199 return ret;
200}
201
202bool OProfileWrapper::isAgentAvailable() {
203 return Agent != 0;
204}
205
206int OProfileWrapper::op_write_native_code(const char* Name,
207 uint64_t Addr,
208 void const* Code,
209 const unsigned int Size) {
210 if (!Initialized)
211 initialize();
212
213 if (Agent && WriteNativeCodeFunc)
214 return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size);
215
216 return -1;
217}
218
219int OProfileWrapper::op_write_debug_line_info(
220 void const* Code,
221 size_t NumEntries,
222 struct debug_line_info const* Info) {
223 if (!Initialized)
224 initialize();
225
226 if (Agent && WriteDebugLineInfoFunc)
227 return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info);
228
229 return -1;
230}
231
232int OProfileWrapper::op_major_version() {
233 if (!Initialized)
234 initialize();
235
236 if (Agent && MajorVersionFunc)
237 return MajorVersionFunc();
238
239 return -1;
240}
241
242int OProfileWrapper::op_minor_version() {
243 if (!Initialized)
244 initialize();
245
246 if (Agent && MinorVersionFunc)
247 return MinorVersionFunc();
248
249 return -1;
250}
251
252int OProfileWrapper::op_unload_native_code(uint64_t Addr) {
253 if (!Initialized)
254 initialize();
255
256 if (Agent && UnloadNativeCodeFunc)
257 return UnloadNativeCodeFunc(Agent, Addr);
258
259 return -1;
260}
261
262} // namespace llvm