OProfileWrapper.cpp 6.9 KB

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