1234285Sdim//===-- OProfileWrapper.cpp - OProfile JIT API Wrapper implementation -----===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This file implements the interface in OProfileWrapper.h. It is responsible 11234285Sdim// for loading the opagent dynamic library when the first call to an op_ 12234285Sdim// function occurs. 13234285Sdim// 14234285Sdim//===----------------------------------------------------------------------===// 15234285Sdim 16234285Sdim#include "llvm/ExecutionEngine/OProfileWrapper.h" 17276479Sdim#include "llvm/ADT/SmallString.h" 18234285Sdim#include "llvm/Support/Debug.h" 19234285Sdim#include "llvm/Support/DynamicLibrary.h" 20234285Sdim#include "llvm/Support/Mutex.h" 21234285Sdim#include "llvm/Support/MutexGuard.h" 22276479Sdim#include "llvm/Support/raw_ostream.h" 23261991Sdim#include <cstring> 24261991Sdim#include <dirent.h> 25261991Sdim#include <fcntl.h> 26234285Sdim#include <sstream> 27234285Sdim#include <stddef.h> 28234285Sdim#include <sys/stat.h> 29249423Sdim#include <unistd.h> 30234285Sdim 31276479Sdim#define DEBUG_TYPE "oprofile-wrapper" 32276479Sdim 33234285Sdimnamespace { 34234285Sdim 35234285Sdim// Global mutex to ensure a single thread initializes oprofile agent. 36234285Sdimllvm::sys::Mutex OProfileInitializationMutex; 37234285Sdim 38234285Sdim} // anonymous namespace 39234285Sdim 40234285Sdimnamespace llvm { 41234285Sdim 42234285SdimOProfileWrapper::OProfileWrapper() 43234285Sdim: Agent(0), 44234285Sdim OpenAgentFunc(0), 45234285Sdim CloseAgentFunc(0), 46234285Sdim WriteNativeCodeFunc(0), 47234285Sdim WriteDebugLineInfoFunc(0), 48234285Sdim UnloadNativeCodeFunc(0), 49234285Sdim MajorVersionFunc(0), 50234285Sdim MinorVersionFunc(0), 51234285Sdim IsOProfileRunningFunc(0), 52234285Sdim Initialized(false) { 53234285Sdim} 54234285Sdim 55234285Sdimbool OProfileWrapper::initialize() { 56234285Sdim using namespace llvm; 57234285Sdim using namespace llvm::sys; 58234285Sdim 59234285Sdim MutexGuard Guard(OProfileInitializationMutex); 60234285Sdim 61234285Sdim if (Initialized) 62234285Sdim return OpenAgentFunc != 0; 63234285Sdim 64234285Sdim Initialized = true; 65234285Sdim 66234285Sdim // If the oprofile daemon is not running, don't load the opagent library 67234285Sdim if (!isOProfileRunning()) { 68234285Sdim DEBUG(dbgs() << "OProfile daemon is not detected.\n"); 69234285Sdim return false; 70234285Sdim } 71234285Sdim 72234285Sdim std::string error; 73234285Sdim if(!DynamicLibrary::LoadLibraryPermanently("libopagent.so", &error)) { 74234285Sdim DEBUG(dbgs() 75234285Sdim << "OProfile connector library libopagent.so could not be loaded: " 76234285Sdim << error << "\n"); 77234285Sdim } 78234285Sdim 79234285Sdim // Get the addresses of the opagent functions 80234285Sdim OpenAgentFunc = (op_open_agent_ptr_t)(intptr_t) 81234285Sdim DynamicLibrary::SearchForAddressOfSymbol("op_open_agent"); 82234285Sdim CloseAgentFunc = (op_close_agent_ptr_t)(intptr_t) 83234285Sdim DynamicLibrary::SearchForAddressOfSymbol("op_close_agent"); 84234285Sdim WriteNativeCodeFunc = (op_write_native_code_ptr_t)(intptr_t) 85234285Sdim DynamicLibrary::SearchForAddressOfSymbol("op_write_native_code"); 86234285Sdim WriteDebugLineInfoFunc = (op_write_debug_line_info_ptr_t)(intptr_t) 87234285Sdim DynamicLibrary::SearchForAddressOfSymbol("op_write_debug_line_info"); 88234285Sdim UnloadNativeCodeFunc = (op_unload_native_code_ptr_t)(intptr_t) 89234285Sdim DynamicLibrary::SearchForAddressOfSymbol("op_unload_native_code"); 90234285Sdim MajorVersionFunc = (op_major_version_ptr_t)(intptr_t) 91234285Sdim DynamicLibrary::SearchForAddressOfSymbol("op_major_version"); 92234285Sdim MinorVersionFunc = (op_major_version_ptr_t)(intptr_t) 93234285Sdim DynamicLibrary::SearchForAddressOfSymbol("op_minor_version"); 94234285Sdim 95234285Sdim // With missing functions, we can do nothing 96234285Sdim if (!OpenAgentFunc 97234285Sdim || !CloseAgentFunc 98234285Sdim || !WriteNativeCodeFunc 99234285Sdim || !WriteDebugLineInfoFunc 100234285Sdim || !UnloadNativeCodeFunc) { 101234285Sdim OpenAgentFunc = 0; 102234285Sdim CloseAgentFunc = 0; 103234285Sdim WriteNativeCodeFunc = 0; 104234285Sdim WriteDebugLineInfoFunc = 0; 105234285Sdim UnloadNativeCodeFunc = 0; 106234285Sdim return false; 107234285Sdim } 108234285Sdim 109234285Sdim return true; 110234285Sdim} 111234285Sdim 112234285Sdimbool OProfileWrapper::isOProfileRunning() { 113234285Sdim if (IsOProfileRunningFunc != 0) 114234285Sdim return IsOProfileRunningFunc(); 115234285Sdim return checkForOProfileProcEntry(); 116234285Sdim} 117234285Sdim 118234285Sdimbool OProfileWrapper::checkForOProfileProcEntry() { 119234285Sdim DIR* ProcDir; 120234285Sdim 121234285Sdim ProcDir = opendir("/proc"); 122234285Sdim if (!ProcDir) 123234285Sdim return false; 124234285Sdim 125234285Sdim // Walk the /proc tree looking for the oprofile daemon 126234285Sdim struct dirent* Entry; 127234285Sdim while (0 != (Entry = readdir(ProcDir))) { 128234285Sdim if (Entry->d_type == DT_DIR) { 129234285Sdim // Build a path from the current entry name 130234285Sdim SmallString<256> CmdLineFName; 131234285Sdim raw_svector_ostream(CmdLineFName) << "/proc/" << Entry->d_name 132234285Sdim << "/cmdline"; 133234285Sdim 134234285Sdim // Open the cmdline file 135234285Sdim int CmdLineFD = open(CmdLineFName.c_str(), S_IRUSR); 136234285Sdim if (CmdLineFD != -1) { 137234285Sdim char ExeName[PATH_MAX+1]; 138234285Sdim char* BaseName = 0; 139234285Sdim 140234285Sdim // Read the cmdline file 141234285Sdim ssize_t NumRead = read(CmdLineFD, ExeName, PATH_MAX+1); 142234285Sdim close(CmdLineFD); 143234285Sdim ssize_t Idx = 0; 144234285Sdim 145261991Sdim if (ExeName[0] != '/') { 146261991Sdim BaseName = ExeName; 147261991Sdim } 148261991Sdim 149234285Sdim // Find the terminator for the first string 150234285Sdim while (Idx < NumRead-1 && ExeName[Idx] != 0) { 151234285Sdim Idx++; 152234285Sdim } 153234285Sdim 154234285Sdim // Go back to the last non-null character 155234285Sdim Idx--; 156234285Sdim 157234285Sdim // Find the last path separator in the first string 158234285Sdim while (Idx > 0) { 159234285Sdim if (ExeName[Idx] == '/') { 160234285Sdim BaseName = ExeName + Idx + 1; 161234285Sdim break; 162234285Sdim } 163234285Sdim Idx--; 164234285Sdim } 165234285Sdim 166234285Sdim // Test this to see if it is the oprofile daemon 167261991Sdim if (BaseName != 0 && (!strcmp("oprofiled", BaseName) || 168261991Sdim !strcmp("operf", BaseName))) { 169234285Sdim // If it is, we're done 170234285Sdim closedir(ProcDir); 171234285Sdim return true; 172234285Sdim } 173234285Sdim } 174234285Sdim } 175234285Sdim } 176234285Sdim 177234285Sdim // We've looked through all the files and didn't find the daemon 178234285Sdim closedir(ProcDir); 179234285Sdim return false; 180234285Sdim} 181234285Sdim 182234285Sdimbool OProfileWrapper::op_open_agent() { 183234285Sdim if (!Initialized) 184234285Sdim initialize(); 185234285Sdim 186234285Sdim if (OpenAgentFunc != 0) { 187234285Sdim Agent = OpenAgentFunc(); 188234285Sdim return Agent != 0; 189234285Sdim } 190234285Sdim 191234285Sdim return false; 192234285Sdim} 193234285Sdim 194234285Sdimint OProfileWrapper::op_close_agent() { 195234285Sdim if (!Initialized) 196234285Sdim initialize(); 197234285Sdim 198234285Sdim int ret = -1; 199234285Sdim if (Agent && CloseAgentFunc) { 200234285Sdim ret = CloseAgentFunc(Agent); 201234285Sdim if (ret == 0) { 202234285Sdim Agent = 0; 203234285Sdim } 204234285Sdim } 205234285Sdim return ret; 206234285Sdim} 207234285Sdim 208234285Sdimbool OProfileWrapper::isAgentAvailable() { 209234285Sdim return Agent != 0; 210234285Sdim} 211234285Sdim 212234285Sdimint OProfileWrapper::op_write_native_code(const char* Name, 213234285Sdim uint64_t Addr, 214234285Sdim void const* Code, 215234285Sdim const unsigned int Size) { 216234285Sdim if (!Initialized) 217234285Sdim initialize(); 218234285Sdim 219234285Sdim if (Agent && WriteNativeCodeFunc) 220234285Sdim return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size); 221234285Sdim 222234285Sdim return -1; 223234285Sdim} 224234285Sdim 225234285Sdimint OProfileWrapper::op_write_debug_line_info( 226234285Sdim void const* Code, 227234285Sdim size_t NumEntries, 228234285Sdim struct debug_line_info const* Info) { 229234285Sdim if (!Initialized) 230234285Sdim initialize(); 231234285Sdim 232234285Sdim if (Agent && WriteDebugLineInfoFunc) 233234285Sdim return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info); 234234285Sdim 235234285Sdim return -1; 236234285Sdim} 237234285Sdim 238234285Sdimint OProfileWrapper::op_major_version() { 239234285Sdim if (!Initialized) 240234285Sdim initialize(); 241234285Sdim 242234285Sdim if (Agent && MajorVersionFunc) 243234285Sdim return MajorVersionFunc(); 244234285Sdim 245234285Sdim return -1; 246234285Sdim} 247234285Sdim 248234285Sdimint OProfileWrapper::op_minor_version() { 249234285Sdim if (!Initialized) 250234285Sdim initialize(); 251234285Sdim 252234285Sdim if (Agent && MinorVersionFunc) 253234285Sdim return MinorVersionFunc(); 254234285Sdim 255234285Sdim return -1; 256234285Sdim} 257234285Sdim 258234285Sdimint OProfileWrapper::op_unload_native_code(uint64_t Addr) { 259234285Sdim if (!Initialized) 260234285Sdim initialize(); 261234285Sdim 262234285Sdim if (Agent && UnloadNativeCodeFunc) 263234285Sdim return UnloadNativeCodeFunc(Agent, Addr); 264234285Sdim 265234285Sdim return -1; 266234285Sdim} 267234285Sdim 268234285Sdim} // namespace llvm 269