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