Home | History | Annotate | Download | only in OProfileJIT
      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 
     33 namespace {
     34 
     35 // Global mutex to ensure a single thread initializes oprofile agent.
     36 llvm::sys::Mutex OProfileInitializationMutex;
     37 
     38 } // anonymous namespace
     39 
     40 namespace llvm {
     41 
     42 OProfileWrapper::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 
     55 bool 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 
    112 bool OProfileWrapper::isOProfileRunning() {
    113   if (IsOProfileRunningFunc != 0)
    114     return IsOProfileRunningFunc();
    115   return checkForOProfileProcEntry();
    116 }
    117 
    118 bool 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 
    182 bool 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 
    194 int 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 
    208 bool OProfileWrapper::isAgentAvailable() {
    209   return Agent != 0;
    210 }
    211 
    212 int 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 
    225 int 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 
    238 int OProfileWrapper::op_major_version() {
    239   if (!Initialized)
    240     initialize();
    241 
    242   if (Agent && MajorVersionFunc)
    243     return MajorVersionFunc();
    244 
    245   return -1;
    246 }
    247 
    248 int OProfileWrapper::op_minor_version() {
    249   if (!Initialized)
    250     initialize();
    251 
    252   if (Agent && MinorVersionFunc)
    253     return MinorVersionFunc();
    254 
    255   return -1;
    256 }
    257 
    258 int  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