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 265