LLVM API Documentation
00001 //===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines a JITEventListener object that uses OProfileWrapper to tell 00011 // oprofile about JITted functions, including source line information. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/Config/config.h" 00016 #include "llvm/ExecutionEngine/JITEventListener.h" 00017 00018 #include "llvm/IR/DebugInfo.h" 00019 #include "llvm/IR/Function.h" 00020 #include "llvm/CodeGen/MachineFunction.h" 00021 #include "llvm/ExecutionEngine/ObjectImage.h" 00022 #include "llvm/ExecutionEngine/OProfileWrapper.h" 00023 #include "llvm/Object/ObjectFile.h" 00024 #include "llvm/Support/Debug.h" 00025 #include "llvm/Support/raw_ostream.h" 00026 #include "llvm/Support/Errno.h" 00027 #include "EventListenerCommon.h" 00028 00029 #include <dirent.h> 00030 #include <fcntl.h> 00031 00032 using namespace llvm; 00033 using namespace llvm::jitprofiling; 00034 00035 #define DEBUG_TYPE "oprofile-jit-event-listener" 00036 00037 namespace { 00038 00039 class OProfileJITEventListener : public JITEventListener { 00040 OProfileWrapper& Wrapper; 00041 00042 void initialize(); 00043 00044 public: 00045 OProfileJITEventListener(OProfileWrapper& LibraryWrapper) 00046 : Wrapper(LibraryWrapper) { 00047 initialize(); 00048 } 00049 00050 ~OProfileJITEventListener(); 00051 00052 virtual void NotifyFunctionEmitted(const Function &F, 00053 void *FnStart, size_t FnSize, 00054 const JITEvent_EmittedFunctionDetails &Details); 00055 00056 virtual void NotifyFreeingMachineCode(void *OldPtr); 00057 00058 virtual void NotifyObjectEmitted(const ObjectImage &Obj); 00059 00060 virtual void NotifyFreeingObject(const ObjectImage &Obj); 00061 }; 00062 00063 void OProfileJITEventListener::initialize() { 00064 if (!Wrapper.op_open_agent()) { 00065 const std::string err_str = sys::StrError(); 00066 DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n"); 00067 } else { 00068 DEBUG(dbgs() << "Connected to OProfile agent.\n"); 00069 } 00070 } 00071 00072 OProfileJITEventListener::~OProfileJITEventListener() { 00073 if (Wrapper.isAgentAvailable()) { 00074 if (Wrapper.op_close_agent() == -1) { 00075 const std::string err_str = sys::StrError(); 00076 DEBUG(dbgs() << "Failed to disconnect from OProfile agent: " 00077 << err_str << "\n"); 00078 } else { 00079 DEBUG(dbgs() << "Disconnected from OProfile agent.\n"); 00080 } 00081 } 00082 } 00083 00084 static debug_line_info LineStartToOProfileFormat( 00085 const MachineFunction &MF, FilenameCache &Filenames, 00086 uintptr_t Address, DebugLoc Loc) { 00087 debug_line_info Result; 00088 Result.vma = Address; 00089 Result.lineno = Loc.getLine(); 00090 Result.filename = Filenames.getFilename( 00091 Loc.getScope(MF.getFunction()->getContext())); 00092 DEBUG(dbgs() << "Mapping " << reinterpret_cast<void*>(Result.vma) << " to " 00093 << Result.filename << ":" << Result.lineno << "\n"); 00094 return Result; 00095 } 00096 00097 // Adds the just-emitted function to the symbol table. 00098 void OProfileJITEventListener::NotifyFunctionEmitted( 00099 const Function &F, void *FnStart, size_t FnSize, 00100 const JITEvent_EmittedFunctionDetails &Details) { 00101 assert(F.hasName() && FnStart != 0 && "Bad symbol to add"); 00102 if (Wrapper.op_write_native_code(F.getName().data(), 00103 reinterpret_cast<uint64_t>(FnStart), 00104 FnStart, FnSize) == -1) { 00105 DEBUG(dbgs() << "Failed to tell OProfile about native function " 00106 << F.getName() << " at [" 00107 << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); 00108 return; 00109 } 00110 00111 if (!Details.LineStarts.empty()) { 00112 // Now we convert the line number information from the address/DebugLoc 00113 // format in Details to the address/filename/lineno format that OProfile 00114 // expects. Note that OProfile 0.9.4 has a bug that causes it to ignore 00115 // line numbers for addresses above 4G. 00116 FilenameCache Filenames; 00117 std::vector<debug_line_info> LineInfo; 00118 LineInfo.reserve(1 + Details.LineStarts.size()); 00119 00120 DebugLoc FirstLoc = Details.LineStarts[0].Loc; 00121 assert(!FirstLoc.isUnknown() 00122 && "LineStarts should not contain unknown DebugLocs"); 00123 MDNode *FirstLocScope = FirstLoc.getScope(F.getContext()); 00124 DISubprogram FunctionDI = getDISubprogram(FirstLocScope); 00125 if (FunctionDI.Verify()) { 00126 // If we have debug info for the function itself, use that as the line 00127 // number of the first several instructions. Otherwise, after filling 00128 // LineInfo, we'll adjust the address of the first line number to point at 00129 // the start of the function. 00130 debug_line_info line_info; 00131 line_info.vma = reinterpret_cast<uintptr_t>(FnStart); 00132 line_info.lineno = FunctionDI.getLineNumber(); 00133 line_info.filename = Filenames.getFilename(FirstLocScope); 00134 LineInfo.push_back(line_info); 00135 } 00136 00137 for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator 00138 I = Details.LineStarts.begin(), E = Details.LineStarts.end(); 00139 I != E; ++I) { 00140 LineInfo.push_back(LineStartToOProfileFormat( 00141 *Details.MF, Filenames, I->Address, I->Loc)); 00142 } 00143 00144 // In case the function didn't have line info of its own, adjust the first 00145 // line info's address to include the start of the function. 00146 LineInfo[0].vma = reinterpret_cast<uintptr_t>(FnStart); 00147 00148 if (Wrapper.op_write_debug_line_info(FnStart, LineInfo.size(), 00149 &*LineInfo.begin()) == -1) { 00150 DEBUG(dbgs() 00151 << "Failed to tell OProfile about line numbers for native function " 00152 << F.getName() << " at [" 00153 << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); 00154 } 00155 } 00156 } 00157 00158 // Removes the being-deleted function from the symbol table. 00159 void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) { 00160 assert(FnStart && "Invalid function pointer"); 00161 if (Wrapper.op_unload_native_code(reinterpret_cast<uint64_t>(FnStart)) == -1) { 00162 DEBUG(dbgs() 00163 << "Failed to tell OProfile about unload of native function at " 00164 << FnStart << "\n"); 00165 } 00166 } 00167 00168 void OProfileJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { 00169 if (!Wrapper.isAgentAvailable()) { 00170 return; 00171 } 00172 00173 // Use symbol info to iterate functions in the object. 00174 for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); 00175 I != E; ++I) { 00176 object::SymbolRef::Type SymType; 00177 if (I->getType(SymType)) continue; 00178 if (SymType == object::SymbolRef::ST_Function) { 00179 StringRef Name; 00180 uint64_t Addr; 00181 uint64_t Size; 00182 if (I->getName(Name)) continue; 00183 if (I->getAddress(Addr)) continue; 00184 if (I->getSize(Size)) continue; 00185 00186 if (Wrapper.op_write_native_code(Name.data(), Addr, (void*)Addr, Size) 00187 == -1) { 00188 DEBUG(dbgs() << "Failed to tell OProfile about native function " 00189 << Name << " at [" 00190 << (void*)Addr << "-" << ((char*)Addr + Size) << "]\n"); 00191 continue; 00192 } 00193 // TODO: support line number info (similar to IntelJITEventListener.cpp) 00194 } 00195 } 00196 } 00197 00198 void OProfileJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { 00199 if (!Wrapper.isAgentAvailable()) { 00200 return; 00201 } 00202 00203 // Use symbol info to iterate functions in the object. 00204 for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); 00205 I != E; ++I) { 00206 object::SymbolRef::Type SymType; 00207 if (I->getType(SymType)) continue; 00208 if (SymType == object::SymbolRef::ST_Function) { 00209 uint64_t Addr; 00210 if (I->getAddress(Addr)) continue; 00211 00212 if (Wrapper.op_unload_native_code(Addr) == -1) { 00213 DEBUG(dbgs() 00214 << "Failed to tell OProfile about unload of native function at " 00215 << (void*)Addr << "\n"); 00216 continue; 00217 } 00218 } 00219 } 00220 } 00221 00222 } // anonymous namespace. 00223 00224 namespace llvm { 00225 JITEventListener *JITEventListener::createOProfileJITEventListener() { 00226 static std::unique_ptr<OProfileWrapper> JITProfilingWrapper( 00227 new OProfileWrapper); 00228 return new OProfileJITEventListener(*JITProfilingWrapper); 00229 } 00230 00231 // for testing 00232 JITEventListener *JITEventListener::createOProfileJITEventListener( 00233 OProfileWrapper* TestImpl) { 00234 return new OProfileJITEventListener(*TestImpl); 00235 } 00236 00237 } // namespace llvm 00238