]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/ExecutionEngine/OProfileJIT/OProfileJITEventListener.cpp
1 //===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines a JITEventListener object that uses OProfileWrapper to tell
11 // oprofile about JITted functions, including source line information.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Config/config.h"
16 #include "EventListenerCommon.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/ExecutionEngine/JITEventListener.h"
19 #include "llvm/ExecutionEngine/OProfileWrapper.h"
20 #include "llvm/ExecutionEngine/RuntimeDyld.h"
21 #include "llvm/IR/DebugInfo.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/Errno.h"
26 #include "llvm/Support/raw_ostream.h"
31 using namespace llvm::jitprofiling
;
32 using namespace llvm::object
;
34 #define DEBUG_TYPE "oprofile-jit-event-listener"
38 class OProfileJITEventListener
: public JITEventListener
{
39 std::unique_ptr
<OProfileWrapper
> Wrapper
;
42 std::map
<const char*, OwningBinary
<ObjectFile
>> DebugObjects
;
45 OProfileJITEventListener(std::unique_ptr
<OProfileWrapper
> LibraryWrapper
)
46 : Wrapper(std::move(LibraryWrapper
)) {
50 ~OProfileJITEventListener();
52 void NotifyObjectEmitted(const ObjectFile
&Obj
,
53 const RuntimeDyld::LoadedObjectInfo
&L
) override
;
55 void NotifyFreeingObject(const ObjectFile
&Obj
) override
;
58 void OProfileJITEventListener::initialize() {
59 if (!Wrapper
->op_open_agent()) {
60 const std::string err_str
= sys::StrError();
61 DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str
<< "\n");
63 DEBUG(dbgs() << "Connected to OProfile agent.\n");
67 OProfileJITEventListener::~OProfileJITEventListener() {
68 if (Wrapper
->isAgentAvailable()) {
69 if (Wrapper
->op_close_agent() == -1) {
70 const std::string err_str
= sys::StrError();
71 DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
74 DEBUG(dbgs() << "Disconnected from OProfile agent.\n");
79 void OProfileJITEventListener::NotifyObjectEmitted(
80 const ObjectFile
&Obj
,
81 const RuntimeDyld::LoadedObjectInfo
&L
) {
82 if (!Wrapper
->isAgentAvailable()) {
86 OwningBinary
<ObjectFile
> DebugObjOwner
= L
.getObjectForDebug(Obj
);
87 const ObjectFile
&DebugObj
= *DebugObjOwner
.getBinary();
89 // Use symbol info to iterate functions in the object.
90 for (symbol_iterator I
= DebugObj
.symbol_begin(), E
= DebugObj
.symbol_end();
92 SymbolRef::Type SymType
;
93 if (I
->getType(SymType
)) continue;
94 if (SymType
== SymbolRef::ST_Function
) {
98 if (I
->getName(Name
)) continue;
99 if (I
->getAddress(Addr
)) continue;
100 if (I
->getSize(Size
)) continue;
102 if (Wrapper
->op_write_native_code(Name
.data(), Addr
, (void*)Addr
, Size
)
104 DEBUG(dbgs() << "Failed to tell OProfile about native function "
106 << (void*)Addr
<< "-" << ((char*)Addr
+ Size
) << "]\n");
109 // TODO: support line number info (similar to IntelJITEventListener.cpp)
113 DebugObjects
[Obj
.getData().data()] = std::move(DebugObjOwner
);
116 void OProfileJITEventListener::NotifyFreeingObject(const ObjectFile
&Obj
) {
117 if (Wrapper
->isAgentAvailable()) {
119 // If there was no agent registered when the original object was loaded then
120 // we won't have created a debug object for it, so bail out.
121 if (DebugObjects
.find(Obj
.getData().data()) == DebugObjects
.end())
124 const ObjectFile
&DebugObj
= *DebugObjects
[Obj
.getData().data()].getBinary();
126 // Use symbol info to iterate functions in the object.
127 for (symbol_iterator I
= DebugObj
.symbol_begin(),
128 E
= DebugObj
.symbol_end();
130 SymbolRef::Type SymType
;
131 if (I
->getType(SymType
)) continue;
132 if (SymType
== SymbolRef::ST_Function
) {
134 if (I
->getAddress(Addr
)) continue;
136 if (Wrapper
->op_unload_native_code(Addr
) == -1) {
138 << "Failed to tell OProfile about unload of native function at "
139 << (void*)Addr
<< "\n");
146 DebugObjects
.erase(Obj
.getData().data());
149 } // anonymous namespace.
152 JITEventListener
*JITEventListener::createOProfileJITEventListener() {
153 return new OProfileJITEventListener(llvm::make_unique
<OProfileWrapper
>());