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 
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