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