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 #include "llvm/ADT/SmallString.h" 18 #include "llvm/Support/Debug.h" 19 #include "llvm/Support/DynamicLibrary.h" 20 #include "llvm/Support/Mutex.h" 21 #include "llvm/Support/MutexGuard.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <cstring> 24 #include <dirent.h> 25 #include <fcntl.h> 26 #include <stddef.h> 27 #include <sys/stat.h> 28 #include <unistd.h> 29 30 #define DEBUG_TYPE "oprofile-wrapper" 31 32 namespace { 33 34 // Global mutex to ensure a single thread initializes oprofile agent. 35 llvm::sys::Mutex OProfileInitializationMutex; 36 37 } // anonymous namespace 38 39 namespace llvm { 40 41 OProfileWrapper::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 54 bool 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 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