LLVM API Documentation
00001 //===-- OProfileWrapper.cpp - OProfile JIT API Wrapper implementation -----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the interface in OProfileWrapper.h. It is responsible 00011 // for loading the opagent dynamic library when the first call to an op_ 00012 // function occurs. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "llvm/ExecutionEngine/OProfileWrapper.h" 00017 #include "llvm/ADT/SmallString.h" 00018 #include "llvm/Support/Debug.h" 00019 #include "llvm/Support/DynamicLibrary.h" 00020 #include "llvm/Support/Mutex.h" 00021 #include "llvm/Support/MutexGuard.h" 00022 #include "llvm/Support/raw_ostream.h" 00023 #include <cstring> 00024 #include <dirent.h> 00025 #include <fcntl.h> 00026 #include <sstream> 00027 #include <stddef.h> 00028 #include <sys/stat.h> 00029 #include <unistd.h> 00030 00031 #define DEBUG_TYPE "oprofile-wrapper" 00032 00033 namespace { 00034 00035 // Global mutex to ensure a single thread initializes oprofile agent. 00036 llvm::sys::Mutex OProfileInitializationMutex; 00037 00038 } // anonymous namespace 00039 00040 namespace llvm { 00041 00042 OProfileWrapper::OProfileWrapper() 00043 : Agent(0), 00044 OpenAgentFunc(0), 00045 CloseAgentFunc(0), 00046 WriteNativeCodeFunc(0), 00047 WriteDebugLineInfoFunc(0), 00048 UnloadNativeCodeFunc(0), 00049 MajorVersionFunc(0), 00050 MinorVersionFunc(0), 00051 IsOProfileRunningFunc(0), 00052 Initialized(false) { 00053 } 00054 00055 bool OProfileWrapper::initialize() { 00056 using namespace llvm; 00057 using namespace llvm::sys; 00058 00059 MutexGuard Guard(OProfileInitializationMutex); 00060 00061 if (Initialized) 00062 return OpenAgentFunc != 0; 00063 00064 Initialized = true; 00065 00066 // If the oprofile daemon is not running, don't load the opagent library 00067 if (!isOProfileRunning()) { 00068 DEBUG(dbgs() << "OProfile daemon is not detected.\n"); 00069 return false; 00070 } 00071 00072 std::string error; 00073 if(!DynamicLibrary::LoadLibraryPermanently("libopagent.so", &error)) { 00074 DEBUG(dbgs() 00075 << "OProfile connector library libopagent.so could not be loaded: " 00076 << error << "\n"); 00077 } 00078 00079 // Get the addresses of the opagent functions 00080 OpenAgentFunc = (op_open_agent_ptr_t)(intptr_t) 00081 DynamicLibrary::SearchForAddressOfSymbol("op_open_agent"); 00082 CloseAgentFunc = (op_close_agent_ptr_t)(intptr_t) 00083 DynamicLibrary::SearchForAddressOfSymbol("op_close_agent"); 00084 WriteNativeCodeFunc = (op_write_native_code_ptr_t)(intptr_t) 00085 DynamicLibrary::SearchForAddressOfSymbol("op_write_native_code"); 00086 WriteDebugLineInfoFunc = (op_write_debug_line_info_ptr_t)(intptr_t) 00087 DynamicLibrary::SearchForAddressOfSymbol("op_write_debug_line_info"); 00088 UnloadNativeCodeFunc = (op_unload_native_code_ptr_t)(intptr_t) 00089 DynamicLibrary::SearchForAddressOfSymbol("op_unload_native_code"); 00090 MajorVersionFunc = (op_major_version_ptr_t)(intptr_t) 00091 DynamicLibrary::SearchForAddressOfSymbol("op_major_version"); 00092 MinorVersionFunc = (op_major_version_ptr_t)(intptr_t) 00093 DynamicLibrary::SearchForAddressOfSymbol("op_minor_version"); 00094 00095 // With missing functions, we can do nothing 00096 if (!OpenAgentFunc 00097 || !CloseAgentFunc 00098 || !WriteNativeCodeFunc 00099 || !WriteDebugLineInfoFunc 00100 || !UnloadNativeCodeFunc) { 00101 OpenAgentFunc = 0; 00102 CloseAgentFunc = 0; 00103 WriteNativeCodeFunc = 0; 00104 WriteDebugLineInfoFunc = 0; 00105 UnloadNativeCodeFunc = 0; 00106 return false; 00107 } 00108 00109 return true; 00110 } 00111 00112 bool OProfileWrapper::isOProfileRunning() { 00113 if (IsOProfileRunningFunc != 0) 00114 return IsOProfileRunningFunc(); 00115 return checkForOProfileProcEntry(); 00116 } 00117 00118 bool OProfileWrapper::checkForOProfileProcEntry() { 00119 DIR* ProcDir; 00120 00121 ProcDir = opendir("/proc"); 00122 if (!ProcDir) 00123 return false; 00124 00125 // Walk the /proc tree looking for the oprofile daemon 00126 struct dirent* Entry; 00127 while (0 != (Entry = readdir(ProcDir))) { 00128 if (Entry->d_type == DT_DIR) { 00129 // Build a path from the current entry name 00130 SmallString<256> CmdLineFName; 00131 raw_svector_ostream(CmdLineFName) << "/proc/" << Entry->d_name 00132 << "/cmdline"; 00133 00134 // Open the cmdline file 00135 int CmdLineFD = open(CmdLineFName.c_str(), S_IRUSR); 00136 if (CmdLineFD != -1) { 00137 char ExeName[PATH_MAX+1]; 00138 char* BaseName = 0; 00139 00140 // Read the cmdline file 00141 ssize_t NumRead = read(CmdLineFD, ExeName, PATH_MAX+1); 00142 close(CmdLineFD); 00143 ssize_t Idx = 0; 00144 00145 if (ExeName[0] != '/') { 00146 BaseName = ExeName; 00147 } 00148 00149 // Find the terminator for the first string 00150 while (Idx < NumRead-1 && ExeName[Idx] != 0) { 00151 Idx++; 00152 } 00153 00154 // Go back to the last non-null character 00155 Idx--; 00156 00157 // Find the last path separator in the first string 00158 while (Idx > 0) { 00159 if (ExeName[Idx] == '/') { 00160 BaseName = ExeName + Idx + 1; 00161 break; 00162 } 00163 Idx--; 00164 } 00165 00166 // Test this to see if it is the oprofile daemon 00167 if (BaseName != 0 && (!strcmp("oprofiled", BaseName) || 00168 !strcmp("operf", BaseName))) { 00169 // If it is, we're done 00170 closedir(ProcDir); 00171 return true; 00172 } 00173 } 00174 } 00175 } 00176 00177 // We've looked through all the files and didn't find the daemon 00178 closedir(ProcDir); 00179 return false; 00180 } 00181 00182 bool OProfileWrapper::op_open_agent() { 00183 if (!Initialized) 00184 initialize(); 00185 00186 if (OpenAgentFunc != 0) { 00187 Agent = OpenAgentFunc(); 00188 return Agent != 0; 00189 } 00190 00191 return false; 00192 } 00193 00194 int OProfileWrapper::op_close_agent() { 00195 if (!Initialized) 00196 initialize(); 00197 00198 int ret = -1; 00199 if (Agent && CloseAgentFunc) { 00200 ret = CloseAgentFunc(Agent); 00201 if (ret == 0) { 00202 Agent = 0; 00203 } 00204 } 00205 return ret; 00206 } 00207 00208 bool OProfileWrapper::isAgentAvailable() { 00209 return Agent != 0; 00210 } 00211 00212 int OProfileWrapper::op_write_native_code(const char* Name, 00213 uint64_t Addr, 00214 void const* Code, 00215 const unsigned int Size) { 00216 if (!Initialized) 00217 initialize(); 00218 00219 if (Agent && WriteNativeCodeFunc) 00220 return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size); 00221 00222 return -1; 00223 } 00224 00225 int OProfileWrapper::op_write_debug_line_info( 00226 void const* Code, 00227 size_t NumEntries, 00228 struct debug_line_info const* Info) { 00229 if (!Initialized) 00230 initialize(); 00231 00232 if (Agent && WriteDebugLineInfoFunc) 00233 return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info); 00234 00235 return -1; 00236 } 00237 00238 int OProfileWrapper::op_major_version() { 00239 if (!Initialized) 00240 initialize(); 00241 00242 if (Agent && MajorVersionFunc) 00243 return MajorVersionFunc(); 00244 00245 return -1; 00246 } 00247 00248 int OProfileWrapper::op_minor_version() { 00249 if (!Initialized) 00250 initialize(); 00251 00252 if (Agent && MinorVersionFunc) 00253 return MinorVersionFunc(); 00254 00255 return -1; 00256 } 00257 00258 int OProfileWrapper::op_unload_native_code(uint64_t Addr) { 00259 if (!Initialized) 00260 initialize(); 00261 00262 if (Agent && UnloadNativeCodeFunc) 00263 return UnloadNativeCodeFunc(Agent, Addr); 00264 00265 return -1; 00266 } 00267 00268 } // namespace llvm