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