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