LLVM  14.0.0git
OProfileJITEventListener.cpp
Go to the documentation of this file.
1 //===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a JITEventListener object that uses OProfileWrapper to tell
10 // oprofile about JITted functions, including source line information.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm-c/ExecutionEngine.h"
16 #include "llvm/Config/config.h"
21 #include "llvm/IR/DebugInfo.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Object/SymbolSize.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/Errno.h"
28 #include <dirent.h>
29 #include <fcntl.h>
30 
31 using namespace llvm;
32 using namespace llvm::object;
33 
34 #define DEBUG_TYPE "oprofile-jit-event-listener"
35 
36 namespace {
37 
38 class OProfileJITEventListener : public JITEventListener {
39  std::unique_ptr<OProfileWrapper> Wrapper;
40 
41  void initialize();
42  std::map<ObjectKey, OwningBinary<ObjectFile>> DebugObjects;
43 
44 public:
45  OProfileJITEventListener(std::unique_ptr<OProfileWrapper> LibraryWrapper)
46  : Wrapper(std::move(LibraryWrapper)) {
47  initialize();
48  }
49 
50  ~OProfileJITEventListener();
51 
52  void notifyObjectLoaded(ObjectKey Key, const ObjectFile &Obj,
53  const RuntimeDyld::LoadedObjectInfo &L) override;
54 
55  void notifyFreeingObject(ObjectKey Key) override;
56 };
57 
59  if (!Wrapper->op_open_agent()) {
60  const std::string err_str = sys::StrError();
61  LLVM_DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str
62  << "\n");
63  } else {
64  LLVM_DEBUG(dbgs() << "Connected to OProfile agent.\n");
65  }
66 }
67 
68 OProfileJITEventListener::~OProfileJITEventListener() {
69  if (Wrapper->isAgentAvailable()) {
70  if (Wrapper->op_close_agent() == -1) {
71  const std::string err_str = sys::StrError();
72  LLVM_DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
73  << err_str << "\n");
74  } else {
75  LLVM_DEBUG(dbgs() << "Disconnected from OProfile agent.\n");
76  }
77  }
78 }
79 
80 void OProfileJITEventListener::notifyObjectLoaded(
81  ObjectKey Key, const ObjectFile &Obj,
83  if (!Wrapper->isAgentAvailable()) {
84  return;
85  }
86 
87  OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj);
88  const ObjectFile &DebugObj = *DebugObjOwner.getBinary();
89  std::unique_ptr<DIContext> Context = DWARFContext::create(DebugObj);
90 
91  // Use symbol info to iterate functions in the object.
92  for (const std::pair<SymbolRef, uint64_t> &P : computeSymbolSizes(DebugObj)) {
93  SymbolRef Sym = P.first;
94  if (!Sym.getType() || *Sym.getType() != SymbolRef::ST_Function)
95  continue;
96 
97  Expected<StringRef> NameOrErr = Sym.getName();
98  if (!NameOrErr)
99  continue;
100  StringRef Name = *NameOrErr;
101  Expected<uint64_t> AddrOrErr = Sym.getAddress();
102  if (!AddrOrErr)
103  continue;
104  uint64_t Addr = *AddrOrErr;
105  uint64_t Size = P.second;
106 
107  if (Wrapper->op_write_native_code(Name.data(), Addr, (void *)Addr, Size) ==
108  -1) {
109  LLVM_DEBUG(dbgs() << "Failed to tell OProfile about native function "
110  << Name << " at [" << (void *)Addr << "-"
111  << ((char *)Addr + Size) << "]\n");
112  continue;
113  }
114 
115  DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
116  size_t i = 0;
117  size_t num_entries = Lines.size();
118  struct debug_line_info *debug_line;
119  debug_line = (struct debug_line_info *)calloc(
120  num_entries, sizeof(struct debug_line_info));
121 
122  for (auto& It : Lines) {
123  debug_line[i].vma = (unsigned long)It.first;
124  debug_line[i].lineno = It.second.Line;
125  debug_line[i].filename =
126  const_cast<char *>(Lines.front().second.FileName.c_str());
127  ++i;
128  }
129 
130  if (Wrapper->op_write_debug_line_info((void *)Addr, num_entries,
131  debug_line) == -1) {
132  LLVM_DEBUG(dbgs() << "Failed to tell OProfiler about debug object at ["
133  << (void *)Addr << "-" << ((char *)Addr + Size)
134  << "]\n");
135  continue;
136  }
137  }
138 
139  DebugObjects[Key] = std::move(DebugObjOwner);
140 }
141 
142 void OProfileJITEventListener::notifyFreeingObject(ObjectKey Key) {
143  if (Wrapper->isAgentAvailable()) {
144 
145  // If there was no agent registered when the original object was loaded then
146  // we won't have created a debug object for it, so bail out.
147  if (DebugObjects.find(Key) == DebugObjects.end())
148  return;
149 
150  const ObjectFile &DebugObj = *DebugObjects[Key].getBinary();
151 
152  // Use symbol info to iterate functions in the object.
153  for (symbol_iterator I = DebugObj.symbol_begin(),
154  E = DebugObj.symbol_end();
155  I != E; ++I) {
156  if (I->getType() && *I->getType() == SymbolRef::ST_Function) {
157  Expected<uint64_t> AddrOrErr = I->getAddress();
158  if (!AddrOrErr)
159  continue;
160  uint64_t Addr = *AddrOrErr;
161 
162  if (Wrapper->op_unload_native_code(Addr) == -1) {
163  LLVM_DEBUG(
164  dbgs()
165  << "Failed to tell OProfile about unload of native function at "
166  << (void *)Addr << "\n");
167  continue;
168  }
169  }
170  }
171  }
172 
173  DebugObjects.erase(Key);
174 }
175 
176 } // anonymous namespace.
177 
178 namespace llvm {
180  return new OProfileJITEventListener(std::make_unique<OProfileWrapper>());
181 }
182 
183 } // namespace llvm
184 
186 {
188 }
llvm::sys::StrError
std::string StrError()
Returns a string representation of the errno value, using whatever thread-safe variant of strerror() ...
Definition: Errno.cpp:31
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
i
i
Definition: README.txt:29
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::DWARFContext::create
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler)
Definition: DWARFContext.cpp:1969
llvm::RuntimeDyld::LoadedObjectInfo::getObjectForDebug
virtual object::OwningBinary< object::ObjectFile > getObjectForDebug(const object::ObjectFile &Obj) const =0
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
Wrapper
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
Definition: AMDGPUAliasAnalysis.cpp:31
llvm::object::OwningBinary::getBinary
T * getBinary()
Definition: Binary.h:227
DWARFContext.h
OProfileWrapper.h
SymbolSize.h
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
initialize
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
Definition: TargetLibraryInfo.cpp:116
RuntimeDyld.h
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::object::SymbolicFile::symbol_end
virtual basic_symbol_iterator symbol_end() const =0
llvm::object
Definition: ObjectFileTransformer.h:18
LLVMCreateOProfileJITEventListener
LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void)
Definition: OProfileJITEventListener.cpp:185
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:481
uint64_t
llvm::object::symbol_iterator
Definition: ObjectFile.h:207
llvm::object::SymbolRef::ST_Function
@ ST_Function
Definition: ObjectFile.h:176
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
DebugInfo.h
I
#define I(x, y, z)
Definition: MD5.cpp:59
ObjectFile.h
llvm::JITEventListener
JITEventListener - Abstract interface for use by the JIT to notify clients about significant events d...
Definition: JITEventListener.h:41
llvm::wrap
LLVMAttributeRef wrap(Attribute Attr)
Definition: Attributes.h:252
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:228
llvm::object::SymbolicFile::symbol_begin
virtual basic_symbol_iterator symbol_begin() const =0
llvm::JITEventListener::createOProfileJITEventListener
static JITEventListener * createOProfileJITEventListener()
Definition: JITEventListener.h:91
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::object::OwningBinary
Definition: RuntimeDyld.h:36
llvm::RuntimeDyld::LoadedObjectInfo
Information about the loaded object.
Definition: RuntimeDyld.h:69
Function.h
ExecutionEngine.h
llvm::object::computeSymbolSizes
std::vector< std::pair< SymbolRef, uint64_t > > computeSymbolSizes(const ObjectFile &O)
Definition: SymbolSize.cpp:50
llvm::object::SymbolRef::getType
Expected< SymbolRef::Type > getType() const
Definition: ObjectFile.h:413
llvm::object::SymbolRef
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: ObjectFile.h:167
raw_ostream.h
llvm::object::SymbolRef::getName
Expected< StringRef > getName() const
Definition: ObjectFile.h:389
MachineFunction.h
LLVMJITEventListenerRef
struct LLVMOpaqueJITEventListener * LLVMJITEventListenerRef
Definition: Types.h:163
Errno.h
llvm::object::SymbolRef::getAddress
Expected< uint64_t > getAddress() const
Returns the symbol virtual address (i.e.
Definition: ObjectFile.h:393
Debug.h
JITEventListener.h