LLVM API Documentation

OProfileWrapper.cpp
Go to the documentation of this file.
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