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 <stddef.h>
     27 #include <sys/stat.h>
     28 #include <unistd.h>
     29 
     30 #define DEBUG_TYPE "oprofile-wrapper"
     31 
     32 namespace {
     33 
     34 // Global mutex to ensure a single thread initializes oprofile agent.
     35 llvm::sys::Mutex OProfileInitializationMutex;
     36 
     37 } // anonymous namespace
     38 
     39 namespace llvm {
     40 
     41 OProfileWrapper::OProfileWrapper()
     42 : Agent(0),
     43   OpenAgentFunc(0),
     44   CloseAgentFunc(0),
     45   WriteNativeCodeFunc(0),
     46   WriteDebugLineInfoFunc(0),
     47   UnloadNativeCodeFunc(0),
     48   MajorVersionFunc(0),
     49   MinorVersionFunc(0),
     50   IsOProfileRunningFunc(0),
     51   Initialized(false) {
     52 }
     53 
     54 bool OProfileWrapper::initialize() {
     55   using namespace llvm;
     56   using namespace llvm::sys;
     57 
     58   MutexGuard Guard(OProfileInitializationMutex);
     59 
     60   if (Initialized)
     61     return OpenAgentFunc != 0;
     62 
     63   Initialized = true;
     64 
     65   // If the oprofile daemon is not running, don't load the opagent library
     66   if (!isOProfileRunning()) {
     67     DEBUG(dbgs() << "OProfile daemon is not detected.\n");
     68     return false;
     69   }
     70 
     71   std::string error;
     72   if(!DynamicLibrary::LoadLibraryPermanently("libopagent.so", &error)) {
     73     DEBUG(dbgs()
     74             << "OProfile connector library libopagent.so could not be loaded: "
     75             << error << "\n");
     76   }
     77 
     78   // Get the addresses of the opagent functions
     79   OpenAgentFunc = (op_open_agent_ptr_t)(intptr_t)
     80           DynamicLibrary::SearchForAddressOfSymbol("op_open_agent");
     81   CloseAgentFunc = (op_close_agent_ptr_t)(intptr_t)
     82           DynamicLibrary::SearchForAddressOfSymbol("op_close_agent");
     83   WriteNativeCodeFunc = (op_write_native_code_ptr_t)(intptr_t)
     84           DynamicLibrary::SearchForAddressOfSymbol("op_write_native_code");
     85   WriteDebugLineInfoFunc = (op_write_debug_line_info_ptr_t)(intptr_t)
     86           DynamicLibrary::SearchForAddressOfSymbol("op_write_debug_line_info");
     87   UnloadNativeCodeFunc = (op_unload_native_code_ptr_t)(intptr_t)
     88           DynamicLibrary::SearchForAddressOfSymbol("op_unload_native_code");
     89   MajorVersionFunc = (op_major_version_ptr_t)(intptr_t)
     90           DynamicLibrary::SearchForAddressOfSymbol("op_major_version");
     91   MinorVersionFunc = (op_major_version_ptr_t)(intptr_t)
     92           DynamicLibrary::SearchForAddressOfSymbol("op_minor_version");
     93 
     94   // With missing functions, we can do nothing
     95   if (!OpenAgentFunc
     96       || !CloseAgentFunc
     97       || !WriteNativeCodeFunc
     98       || !WriteDebugLineInfoFunc
     99       || !UnloadNativeCodeFunc) {
    100     OpenAgentFunc = 0;
    101     CloseAgentFunc = 0;
    102     WriteNativeCodeFunc = 0;
    103     WriteDebugLineInfoFunc = 0;
    104     UnloadNativeCodeFunc = 0;
    105     return false;
    106   }
    107 
    108   return true;
    109 }
    110 
    111 bool OProfileWrapper::isOProfileRunning() {
    112   if (IsOProfileRunningFunc != 0)
    113     return IsOProfileRunningFunc();
    114   return checkForOProfileProcEntry();
    115 }
    116 
    117 bool OProfileWrapper::checkForOProfileProcEntry() {
    118   DIR* ProcDir;
    119 
    120   ProcDir = opendir("/proc");
    121   if (!ProcDir)
    122     return false;
    123 
    124   // Walk the /proc tree looking for the oprofile daemon
    125   struct dirent* Entry;
    126   while (0 != (Entry = readdir(ProcDir))) {
    127     if (Entry->d_type == DT_DIR) {
    128       // Build a path from the current entry name
    129       SmallString<256> CmdLineFName;
    130       raw_svector_ostream(CmdLineFName) << "/proc/" << Entry->d_name
    131                                         << "/cmdline";
    132 
    133       // Open the cmdline file
    134       int CmdLineFD = open(CmdLineFName.c_str(), S_IRUSR);
    135       if (CmdLineFD != -1) {
    136         char    ExeName[PATH_MAX+1];
    137         char*   BaseName = 0;
    138 
    139         // Read the cmdline file
    140         ssize_t NumRead = read(CmdLineFD, ExeName, PATH_MAX+1);
    141         close(CmdLineFD);
    142         ssize_t Idx = 0;
    143 
    144         if (ExeName[0] != '/') {
    145           BaseName = ExeName;
    146         }
    147 
    148         // Find the terminator for the first string
    149         while (Idx < NumRead-1 && ExeName[Idx] != 0) {
    150           Idx++;
    151         }
    152 
    153         // Go back to the last non-null character
    154         Idx--;
    155 
    156         // Find the last path separator in the first string
    157         while (Idx > 0) {
    158           if (ExeName[Idx] == '/') {
    159             BaseName = ExeName + Idx + 1;
    160             break;
    161           }
    162           Idx--;
    163         }
    164 
    165         // Test this to see if it is the oprofile daemon
    166         if (BaseName != 0 && (!strcmp("oprofiled", BaseName) ||
    167                               !strcmp("operf", BaseName))) {
    168           // If it is, we're done
    169           closedir(ProcDir);
    170           return true;
    171         }
    172       }
    173     }
    174   }
    175 
    176   // We've looked through all the files and didn't find the daemon
    177   closedir(ProcDir);
    178   return false;
    179 }
    180 
    181 bool OProfileWrapper::op_open_agent() {
    182   if (!Initialized)
    183     initialize();
    184 
    185   if (OpenAgentFunc != 0) {
    186     Agent = OpenAgentFunc();
    187     return Agent != 0;
    188   }
    189 
    190   return false;
    191 }
    192 
    193 int OProfileWrapper::op_close_agent() {
    194   if (!Initialized)
    195     initialize();
    196 
    197   int ret = -1;
    198   if (Agent && CloseAgentFunc) {
    199     ret = CloseAgentFunc(Agent);
    200     if (ret == 0) {
    201       Agent = 0;
    202     }
    203   }
    204   return ret;
    205 }
    206 
    207 bool OProfileWrapper::isAgentAvailable() {
    208   return Agent != 0;
    209 }
    210 
    211 int OProfileWrapper::op_write_native_code(const char* Name,
    212                                           uint64_t Addr,
    213                                           void const* Code,
    214                                           const unsigned int Size) {
    215   if (!Initialized)
    216     initialize();
    217 
    218   if (Agent && WriteNativeCodeFunc)
    219     return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size);
    220 
    221   return -1;
    222 }
    223 
    224 int OProfileWrapper::op_write_debug_line_info(
    225   void const* Code,
    226   size_t NumEntries,
    227   struct debug_line_info const* Info) {
    228   if (!Initialized)
    229     initialize();
    230 
    231   if (Agent && WriteDebugLineInfoFunc)
    232     return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info);
    233 
    234   return -1;
    235 }
    236 
    237 int OProfileWrapper::op_major_version() {
    238   if (!Initialized)
    239     initialize();
    240 
    241   if (Agent && MajorVersionFunc)
    242     return MajorVersionFunc();
    243 
    244   return -1;
    245 }
    246 
    247 int OProfileWrapper::op_minor_version() {
    248   if (!Initialized)
    249     initialize();
    250 
    251   if (Agent && MinorVersionFunc)
    252     return MinorVersionFunc();
    253 
    254   return -1;
    255 }
    256 
    257 int  OProfileWrapper::op_unload_native_code(uint64_t Addr) {
    258   if (!Initialized)
    259     initialize();
    260 
    261   if (Agent && UnloadNativeCodeFunc)
    262     return UnloadNativeCodeFunc(Agent, Addr);
    263 
    264   return -1;
    265 }
    266 
    267 } // namespace llvm
    268