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 33namespace { 34 35// Global mutex to ensure a single thread initializes oprofile agent. 36llvm::sys::Mutex OProfileInitializationMutex; 37 38} // anonymous namespace 39 40namespace llvm { 41 42OProfileWrapper::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 55bool 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 112bool OProfileWrapper::isOProfileRunning() { 113 if (IsOProfileRunningFunc != 0) 114 return IsOProfileRunningFunc(); 115 return checkForOProfileProcEntry(); 116} 117 118bool 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 177bool 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 189int 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 203bool OProfileWrapper::isAgentAvailable() { 204 return Agent != 0; 205} 206 207int 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 220int 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 233int OProfileWrapper::op_major_version() { 234 if (!Initialized) 235 initialize(); 236 237 if (Agent && MajorVersionFunc) 238 return MajorVersionFunc(); 239 240 return -1; 241} 242 243int OProfileWrapper::op_minor_version() { 244 if (!Initialized) 245 initialize(); 246 247 if (Agent && MinorVersionFunc) 248 return MinorVersionFunc(); 249 250 return -1; 251} 252 253int 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