1 //===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===// 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 defines a JITEventListener object that uses OProfileWrapper to tell 11 // oprofile about JITted functions, including source line information. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Config/config.h" 16 #include "llvm/CodeGen/MachineFunction.h" 17 #include "llvm/ExecutionEngine/JITEventListener.h" 18 #include "llvm/ExecutionEngine/OProfileWrapper.h" 19 #include "llvm/ExecutionEngine/RuntimeDyld.h" 20 #include "llvm/IR/DebugInfo.h" 21 #include "llvm/IR/Function.h" 22 #include "llvm/Object/ObjectFile.h" 23 #include "llvm/Support/Debug.h" 24 #include "llvm/Support/Errno.h" 25 #include "llvm/Support/raw_ostream.h" 26 #include <dirent.h> 27 #include <fcntl.h> 28 29 using namespace llvm; 30 using namespace llvm::object; 31 32 #define DEBUG_TYPE "oprofile-jit-event-listener" 33 34 namespace { 35 36 class OProfileJITEventListener : public JITEventListener { 37 std::unique_ptr<OProfileWrapper> Wrapper; 38 39 void initialize(); 40 std::map<const char*, OwningBinary<ObjectFile>> DebugObjects; 41 42 public: 43 OProfileJITEventListener(std::unique_ptr<OProfileWrapper> LibraryWrapper) 44 : Wrapper(std::move(LibraryWrapper)) { 45 initialize(); 46 } 47 48 ~OProfileJITEventListener(); 49 50 void NotifyObjectEmitted(const ObjectFile &Obj, 51 const RuntimeDyld::LoadedObjectInfo &L) override; 52 53 void NotifyFreeingObject(const ObjectFile &Obj) override; 54 }; 55 56 void OProfileJITEventListener::initialize() { 57 if (!Wrapper->op_open_agent()) { 58 const std::string err_str = sys::StrError(); 59 DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n"); 60 } else { 61 DEBUG(dbgs() << "Connected to OProfile agent.\n"); 62 } 63 } 64 65 OProfileJITEventListener::~OProfileJITEventListener() { 66 if (Wrapper->isAgentAvailable()) { 67 if (Wrapper->op_close_agent() == -1) { 68 const std::string err_str = sys::StrError(); 69 DEBUG(dbgs() << "Failed to disconnect from OProfile agent: " 70 << err_str << "\n"); 71 } else { 72 DEBUG(dbgs() << "Disconnected from OProfile agent.\n"); 73 } 74 } 75 } 76 77 void OProfileJITEventListener::NotifyObjectEmitted( 78 const ObjectFile &Obj, 79 const RuntimeDyld::LoadedObjectInfo &L) { 80 if (!Wrapper->isAgentAvailable()) { 81 return; 82 } 83 84 OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj); 85 const ObjectFile &DebugObj = *DebugObjOwner.getBinary(); 86 87 // Use symbol info to iterate functions in the object. 88 for (symbol_iterator I = DebugObj.symbol_begin(), E = DebugObj.symbol_end(); 89 I != E; ++I) { 90 SymbolRef::Type SymType; 91 if (I->getType(SymType)) continue; 92 if (SymType == SymbolRef::ST_Function) { 93 StringRef Name; 94 uint64_t Addr; 95 uint64_t Size; 96 if (I->getName(Name)) continue; 97 if (I->getAddress(Addr)) continue; 98 if (I->getSize(Size)) continue; 99 100 if (Wrapper->op_write_native_code(Name.data(), Addr, (void*)Addr, Size) 101 == -1) { 102 DEBUG(dbgs() << "Failed to tell OProfile about native function " 103 << Name << " at [" 104 << (void*)Addr << "-" << ((char*)Addr + Size) << "]\n"); 105 continue; 106 } 107 // TODO: support line number info (similar to IntelJITEventListener.cpp) 108 } 109 } 110 111 DebugObjects[Obj.getData().data()] = std::move(DebugObjOwner); 112 } 113 114 void OProfileJITEventListener::NotifyFreeingObject(const ObjectFile &Obj) { 115 if (Wrapper->isAgentAvailable()) { 116 117 // If there was no agent registered when the original object was loaded then 118 // we won't have created a debug object for it, so bail out. 119 if (DebugObjects.find(Obj.getData().data()) == DebugObjects.end()) 120 return; 121 122 const ObjectFile &DebugObj = *DebugObjects[Obj.getData().data()].getBinary(); 123 124 // Use symbol info to iterate functions in the object. 125 for (symbol_iterator I = DebugObj.symbol_begin(), 126 E = DebugObj.symbol_end(); 127 I != E; ++I) { 128 SymbolRef::Type SymType; 129 if (I->getType(SymType)) continue; 130 if (SymType == SymbolRef::ST_Function) { 131 uint64_t Addr; 132 if (I->getAddress(Addr)) continue; 133 134 if (Wrapper->op_unload_native_code(Addr) == -1) { 135 DEBUG(dbgs() 136 << "Failed to tell OProfile about unload of native function at " 137 << (void*)Addr << "\n"); 138 continue; 139 } 140 } 141 } 142 } 143 144 DebugObjects.erase(Obj.getData().data()); 145 } 146 147 } // anonymous namespace. 148 149 namespace llvm { 150 JITEventListener *JITEventListener::createOProfileJITEventListener() { 151 return new OProfileJITEventListener(llvm::make_unique<OProfileWrapper>()); 152 } 153 154 } // namespace llvm 155 156