Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/OProfileJIT/OProfileWrapper.cpp
35266 views
//===-- OProfileWrapper.cpp - OProfile JIT API Wrapper implementation -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the interface in OProfileWrapper.h. It is responsible9// for loading the opagent dynamic library when the first call to an op_10// function occurs.11//12//===----------------------------------------------------------------------===//1314#include "llvm/ExecutionEngine/OProfileWrapper.h"15#include "llvm/ADT/SmallString.h"16#include "llvm/Support/Debug.h"17#include "llvm/Support/DynamicLibrary.h"18#include "llvm/Support/Mutex.h"19#include "llvm/Support/raw_ostream.h"20#include <cstring>21#include <dirent.h>22#include <fcntl.h>23#include <mutex>24#include <stddef.h>25#include <sys/stat.h>26#include <unistd.h>2728#define DEBUG_TYPE "oprofile-wrapper"2930namespace {3132// Global mutex to ensure a single thread initializes oprofile agent.33llvm::sys::Mutex OProfileInitializationMutex;3435} // anonymous namespace3637namespace llvm {3839OProfileWrapper::OProfileWrapper()40: Agent(0),41OpenAgentFunc(0),42CloseAgentFunc(0),43WriteNativeCodeFunc(0),44WriteDebugLineInfoFunc(0),45UnloadNativeCodeFunc(0),46MajorVersionFunc(0),47MinorVersionFunc(0),48IsOProfileRunningFunc(0),49Initialized(false) {50}5152bool OProfileWrapper::initialize() {53using namespace llvm;54using namespace llvm::sys;5556std::lock_guard<sys::Mutex> Guard(OProfileInitializationMutex);5758if (Initialized)59return OpenAgentFunc != 0;6061Initialized = true;6263// If the oprofile daemon is not running, don't load the opagent library64if (!isOProfileRunning()) {65LLVM_DEBUG(dbgs() << "OProfile daemon is not detected.\n");66return false;67}6869std::string error;70if(!DynamicLibrary::LoadLibraryPermanently("libopagent.so", &error)) {71LLVM_DEBUG(72dbgs()73<< "OProfile connector library libopagent.so could not be loaded: "74<< error << "\n");75}7677// Get the addresses of the opagent functions78OpenAgentFunc = (op_open_agent_ptr_t)(intptr_t)79DynamicLibrary::SearchForAddressOfSymbol("op_open_agent");80CloseAgentFunc = (op_close_agent_ptr_t)(intptr_t)81DynamicLibrary::SearchForAddressOfSymbol("op_close_agent");82WriteNativeCodeFunc = (op_write_native_code_ptr_t)(intptr_t)83DynamicLibrary::SearchForAddressOfSymbol("op_write_native_code");84WriteDebugLineInfoFunc = (op_write_debug_line_info_ptr_t)(intptr_t)85DynamicLibrary::SearchForAddressOfSymbol("op_write_debug_line_info");86UnloadNativeCodeFunc = (op_unload_native_code_ptr_t)(intptr_t)87DynamicLibrary::SearchForAddressOfSymbol("op_unload_native_code");88MajorVersionFunc = (op_major_version_ptr_t)(intptr_t)89DynamicLibrary::SearchForAddressOfSymbol("op_major_version");90MinorVersionFunc = (op_major_version_ptr_t)(intptr_t)91DynamicLibrary::SearchForAddressOfSymbol("op_minor_version");9293// With missing functions, we can do nothing94if (!OpenAgentFunc95|| !CloseAgentFunc96|| !WriteNativeCodeFunc97|| !WriteDebugLineInfoFunc98|| !UnloadNativeCodeFunc) {99OpenAgentFunc = 0;100CloseAgentFunc = 0;101WriteNativeCodeFunc = 0;102WriteDebugLineInfoFunc = 0;103UnloadNativeCodeFunc = 0;104return false;105}106107return true;108}109110bool OProfileWrapper::isOProfileRunning() {111if (IsOProfileRunningFunc != 0)112return IsOProfileRunningFunc();113return checkForOProfileProcEntry();114}115116bool OProfileWrapper::checkForOProfileProcEntry() {117DIR* ProcDir;118119ProcDir = opendir("/proc");120if (!ProcDir)121return false;122123// Walk the /proc tree looking for the oprofile daemon124struct dirent* Entry;125while (0 != (Entry = readdir(ProcDir))) {126if (Entry->d_type == DT_DIR) {127// Build a path from the current entry name128SmallString<256> CmdLineFName;129raw_svector_ostream(CmdLineFName) << "/proc/" << Entry->d_name130<< "/cmdline";131132// Open the cmdline file133int CmdLineFD = open(CmdLineFName.c_str(), S_IRUSR);134if (CmdLineFD != -1) {135char ExeName[PATH_MAX+1];136char* BaseName = 0;137138// Read the cmdline file139ssize_t NumRead = read(CmdLineFD, ExeName, PATH_MAX+1);140close(CmdLineFD);141ssize_t Idx = 0;142143if (ExeName[0] != '/') {144BaseName = ExeName;145}146147// Find the terminator for the first string148while (Idx < NumRead-1 && ExeName[Idx] != 0) {149Idx++;150}151152// Go back to the last non-null character153Idx--;154155// Find the last path separator in the first string156while (Idx > 0) {157if (ExeName[Idx] == '/') {158BaseName = ExeName + Idx + 1;159break;160}161Idx--;162}163164// Test this to see if it is the oprofile daemon165if (BaseName != 0 && (!strcmp("oprofiled", BaseName) ||166!strcmp("operf", BaseName))) {167// If it is, we're done168closedir(ProcDir);169return true;170}171}172}173}174175// We've looked through all the files and didn't find the daemon176closedir(ProcDir);177return false;178}179180bool OProfileWrapper::op_open_agent() {181if (!Initialized)182initialize();183184if (OpenAgentFunc != 0) {185Agent = OpenAgentFunc();186return Agent != 0;187}188189return false;190}191192int OProfileWrapper::op_close_agent() {193if (!Initialized)194initialize();195196int ret = -1;197if (Agent && CloseAgentFunc) {198ret = CloseAgentFunc(Agent);199if (ret == 0) {200Agent = 0;201}202}203return ret;204}205206bool OProfileWrapper::isAgentAvailable() {207return Agent != 0;208}209210int OProfileWrapper::op_write_native_code(const char* Name,211uint64_t Addr,212void const* Code,213const unsigned int Size) {214if (!Initialized)215initialize();216217if (Agent && WriteNativeCodeFunc)218return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size);219220return -1;221}222223int OProfileWrapper::op_write_debug_line_info(224void const* Code,225size_t NumEntries,226struct debug_line_info const* Info) {227if (!Initialized)228initialize();229230if (Agent && WriteDebugLineInfoFunc)231return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info);232233return -1;234}235236int OProfileWrapper::op_major_version() {237if (!Initialized)238initialize();239240if (Agent && MajorVersionFunc)241return MajorVersionFunc();242243return -1;244}245246int OProfileWrapper::op_minor_version() {247if (!Initialized)248initialize();249250if (Agent && MinorVersionFunc)251return MinorVersionFunc();252253return -1;254}255256int OProfileWrapper::op_unload_native_code(uint64_t Addr) {257if (!Initialized)258initialize();259260if (Agent && UnloadNativeCodeFunc)261return UnloadNativeCodeFunc(Agent, Addr);262263return -1;264}265266} // namespace llvm267268269