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 
     18 #define DEBUG_TYPE "oprofile-wrapper"
     19 #include "llvm/Support/Debug.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 #include "llvm/Support/DynamicLibrary.h"
     22 #include "llvm/Support/Mutex.h"
     23 #include "llvm/Support/MutexGuard.h"
     24 #include "llvm/ADT/SmallString.h"
     25 
     26 #include <sstream>
     27 #include <cstring>
     28 #include <stddef.h>
     29 #include <dirent.h>
     30 #include <sys/stat.h>
     31 #include <fcntl.h>
     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         // Find the terminator for the first string
    146         while (Idx < NumRead-1 && ExeName[Idx] != 0) {
    147           Idx++;
    148         }
    149 
    150         // Go back to the last non-null character
    151         Idx--;
    152 
    153         // Find the last path separator in the first string
    154         while (Idx > 0) {
    155           if (ExeName[Idx] == '/') {
    156             BaseName = ExeName + Idx + 1;
    157             break;
    158           }
    159           Idx--;
    160         }
    161 
    162         // Test this to see if it is the oprofile daemon
    163         if (BaseName != 0 && !strcmp("oprofiled", BaseName)) {
    164           // If it is, we're done
    165           closedir(ProcDir);
    166           return true;
    167         }
    168       }
    169     }
    170   }
    171 
    172   // We've looked through all the files and didn't find the daemon
    173   closedir(ProcDir);
    174   return false;
    175 }
    176 
    177 bool OProfileWrapper::op_open_agent() {
    178   if (!Initialized)
    179     initialize();
    180 
    181   if (OpenAgentFunc != 0) {
    182     Agent = OpenAgentFunc();
    183     return Agent != 0;
    184   }
    185 
    186   return false;
    187 }
    188 
    189 int OProfileWrapper::op_close_agent() {
    190   if (!Initialized)
    191     initialize();
    192 
    193   int ret = -1;
    194   if (Agent && CloseAgentFunc) {
    195     ret = CloseAgentFunc(Agent);
    196     if (ret == 0) {
    197       Agent = 0;
    198     }
    199   }
    200   return ret;
    201 }
    202 
    203 bool OProfileWrapper::isAgentAvailable() {
    204   return Agent != 0;
    205 }
    206 
    207 int OProfileWrapper::op_write_native_code(const char* Name,
    208                                           uint64_t Addr,
    209                                           void const* Code,
    210                                           const unsigned int Size) {
    211   if (!Initialized)
    212     initialize();
    213 
    214   if (Agent && WriteNativeCodeFunc)
    215     return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size);
    216 
    217   return -1;
    218 }
    219 
    220 int OProfileWrapper::op_write_debug_line_info(
    221   void const* Code,
    222   size_t NumEntries,
    223   struct debug_line_info const* Info) {
    224   if (!Initialized)
    225     initialize();
    226 
    227   if (Agent && WriteDebugLineInfoFunc)
    228     return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info);
    229 
    230   return -1;
    231 }
    232 
    233 int OProfileWrapper::op_major_version() {
    234   if (!Initialized)
    235     initialize();
    236 
    237   if (Agent && MajorVersionFunc)
    238     return MajorVersionFunc();
    239 
    240   return -1;
    241 }
    242 
    243 int OProfileWrapper::op_minor_version() {
    244   if (!Initialized)
    245     initialize();
    246 
    247   if (Agent && MinorVersionFunc)
    248     return MinorVersionFunc();
    249 
    250   return -1;
    251 }
    252 
    253 int  OProfileWrapper::op_unload_native_code(uint64_t Addr) {
    254   if (!Initialized)
    255     initialize();
    256 
    257   if (Agent && UnloadNativeCodeFunc)
    258     return UnloadNativeCodeFunc(Agent, Addr);
    259 
    260   return -1;
    261 }
    262 
    263 } // namespace llvm
    264