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 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 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 182bool 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 194int 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 208bool OProfileWrapper::isAgentAvailable() { 209 return Agent != 0; 210} 211 212int 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 225int 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 238int OProfileWrapper::op_major_version() { 239 if (!Initialized) 240 initialize(); 241 242 if (Agent && MajorVersionFunc) 243 return MajorVersionFunc(); 244 245 return -1; 246} 247 248int OProfileWrapper::op_minor_version() { 249 if (!Initialized) 250 initialize(); 251 252 if (Agent && MinorVersionFunc) 253 return MinorVersionFunc(); 254 255 return -1; 256} 257 258int 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