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