Home | History | Annotate | Download | only in OProfileJIT
      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