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 <sstream> 27 #include <stddef.h> 28 #include <sys/stat.h> 29 #include <unistd.h> 30 31 #define DEBUG_TYPE "oprofile-wrapper" 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 if (ExeName[0] != '/') { 146 BaseName = ExeName; 147 } 148 149 // Find the terminator for the first string 150 while (Idx < NumRead-1 && ExeName[Idx] != 0) { 151 Idx++; 152 } 153 154 // Go back to the last non-null character 155 Idx--; 156 157 // Find the last path separator in the first string 158 while (Idx > 0) { 159 if (ExeName[Idx] == '/') { 160 BaseName = ExeName + Idx + 1; 161 break; 162 } 163 Idx--; 164 } 165 166 // Test this to see if it is the oprofile daemon 167 if (BaseName != 0 && (!strcmp("oprofiled", BaseName) || 168 !strcmp("operf", BaseName))) { 169 // If it is, we're done 170 closedir(ProcDir); 171 return true; 172 } 173 } 174 } 175 } 176 177 // We've looked through all the files and didn't find the daemon 178 closedir(ProcDir); 179 return false; 180 } 181 182 bool OProfileWrapper::op_open_agent() { 183 if (!Initialized) 184 initialize(); 185 186 if (OpenAgentFunc != 0) { 187 Agent = OpenAgentFunc(); 188 return Agent != 0; 189 } 190 191 return false; 192 } 193 194 int OProfileWrapper::op_close_agent() { 195 if (!Initialized) 196 initialize(); 197 198 int ret = -1; 199 if (Agent && CloseAgentFunc) { 200 ret = CloseAgentFunc(Agent); 201 if (ret == 0) { 202 Agent = 0; 203 } 204 } 205 return ret; 206 } 207 208 bool OProfileWrapper::isAgentAvailable() { 209 return Agent != 0; 210 } 211 212 int OProfileWrapper::op_write_native_code(const char* Name, 213 uint64_t Addr, 214 void const* Code, 215 const unsigned int Size) { 216 if (!Initialized) 217 initialize(); 218 219 if (Agent && WriteNativeCodeFunc) 220 return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size); 221 222 return -1; 223 } 224 225 int OProfileWrapper::op_write_debug_line_info( 226 void const* Code, 227 size_t NumEntries, 228 struct debug_line_info const* Info) { 229 if (!Initialized) 230 initialize(); 231 232 if (Agent && WriteDebugLineInfoFunc) 233 return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info); 234 235 return -1; 236 } 237 238 int OProfileWrapper::op_major_version() { 239 if (!Initialized) 240 initialize(); 241 242 if (Agent && MajorVersionFunc) 243 return MajorVersionFunc(); 244 245 return -1; 246 } 247 248 int OProfileWrapper::op_minor_version() { 249 if (!Initialized) 250 initialize(); 251 252 if (Agent && MinorVersionFunc) 253 return MinorVersionFunc(); 254 255 return -1; 256 } 257 258 int OProfileWrapper::op_unload_native_code(uint64_t Addr) { 259 if (!Initialized) 260 initialize(); 261 262 if (Agent && UnloadNativeCodeFunc) 263 return UnloadNativeCodeFunc(Agent, Addr); 264 265 return -1; 266 } 267 268 } // namespace llvm 269