1 /* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // This file contains portions derived from LLVM, with the original copyright 18 // header below: 19 //==----- GDBJITRegistrar.cpp - Notify GDB about in-memory object files ---==// 20 // 21 // The LLVM Compiler Infrastructure 22 // 23 // This file is distributed under the University of Illinois Open Source 24 // License. See LICENSE.TXT for details. 25 // 26 //===----------------------------------------------------------------------===// 27 // 28 // This file defines the GDBJITRegistrar object which is used by JIT engines to 29 // register in-memory object files with GDB for debugging. 30 // 31 //===----------------------------------------------------------------------===// 32 33 #include "GDBJITRegistrar.h" 34 #include "llvm/ADT/DenseMap.h" 35 #include "GDBJIT.h" 36 #include "llvm/Support/Memory.h" 37 #include "llvm/Support/MutexGuard.h" 38 #include "llvm/Support/Mutex.h" 39 #include "llvm/Support/ErrorHandling.h" 40 41 #include <fstream> 42 43 #ifdef ANDROID_ENGINEERING_BUILD 44 // Path to write dump output. 45 // It is expected that a debugger (plugin) sets this 46 // string to a writeable directory where files (such as JITted object files, 47 // IR dumps) are to be written. If this variable is 0, no debug dumps 48 // are generated. 49 char* gDebugDumpDirectory = 0; 50 #endif // ANDROID_ENGINEERING_BUILD 51 52 //************************************************************************ 53 // COPIED/ADAPTED FROM llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp 54 //************************************************************************ 55 // This must be kept in sync with gdb/gdb/jit.h . 56 extern "C" { 57 58 // We put information about the JITed function in this global, which the 59 // debugger reads. Make sure to specify the version statically, because the 60 // debugger checks the version before we can set it during runtime. 61 static struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; 62 63 } 64 //**************************************************************************** 65 // END COPIED/ADAPTED FROM llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp 66 //**************************************************************************** 67 68 namespace { 69 70 // Buffer for an in-memory object file in executable memory 71 typedef llvm::DenseMap< const ObjectBuffer*, std::pair<std::size_t, jit_code_entry*> > 72 RegisteredObjectBufferMap; 73 74 /// Global access point for the GDB JIT interface designed for use with a 75 /// singleton toolbox. Handles thread-safe registration and deregistration of 76 /// object files that are in executable memory managed by the client of this 77 /// class. 78 class GDBJITRegistrar { 79 /// A map of in-memory object files that have been registered with the GDB JIT interface. 80 RegisteredObjectBufferMap ObjectBufferMap; 81 82 public: 83 /// Instantiates the GDB JIT service. 84 GDBJITRegistrar() : ObjectBufferMap() {} 85 86 /// Unregisters each object that was previously registered with GDB, and 87 /// releases all internal resources. 88 ~GDBJITRegistrar(); 89 90 /// Creates an entry in the GDB JIT registry for the buffer @p Object, 91 /// which must contain an object file in executable memory with any 92 /// debug information for GDB. 93 void registerObject(const ObjectBuffer* Object, std::size_t Size); 94 95 /// Removes the internal registration of @p Object, and 96 /// frees associated resources. 97 /// Returns true if @p Object was found in ObjectBufferMap. 98 bool deregisterObject(const ObjectBuffer* Object); 99 100 private: 101 /// Deregister the debug info for the given object file from the debugger 102 /// and delete any temporary copies. This private method does not remove 103 /// the function from Map so that it can be called while iterating over Map. 104 void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I); 105 }; 106 107 /// Lock used to serialize all gdb-jit registration events, since they 108 /// modify global variables. 109 llvm::sys::Mutex JITDebugLock; 110 111 /// Acquire the lock and do the registration. 112 void NotifyGDB(jit_code_entry* JITCodeEntry) { 113 llvm::MutexGuard locked(JITDebugLock); 114 __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; 115 116 // Insert this entry at the head of the list. 117 JITCodeEntry->prev_entry = NULL; 118 jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry; 119 JITCodeEntry->next_entry = NextEntry; 120 if (NextEntry != NULL) { 121 NextEntry->prev_entry = JITCodeEntry; 122 } 123 __jit_debug_descriptor.first_entry = JITCodeEntry; 124 __jit_debug_descriptor.relevant_entry = JITCodeEntry; 125 __jit_debug_register_code(); 126 } 127 128 GDBJITRegistrar* RegistrarSingleton() { 129 static GDBJITRegistrar* sRegistrar = NULL; 130 if (sRegistrar == NULL) { 131 // The mutex is here so that it won't slow down access once the registrar 132 // is instantiated 133 llvm::MutexGuard locked(JITDebugLock); 134 // Check again to be sure another thread didn't create this while we waited 135 if (sRegistrar == NULL) { 136 sRegistrar = new GDBJITRegistrar; 137 } 138 } 139 return sRegistrar; 140 } 141 142 GDBJITRegistrar::~GDBJITRegistrar() { 143 // Free all registered object files. 144 for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end(); 145 I != E; ++I) { 146 // Call the private method that doesn't update the map so our iterator 147 // doesn't break. 148 deregisterObjectInternal(I); 149 } 150 ObjectBufferMap.clear(); 151 } 152 153 void GDBJITRegistrar::registerObject(const ObjectBuffer* Object, std::size_t Size) { 154 155 assert(Object && "Attempt to register a null object with a debugger."); 156 assert(ObjectBufferMap.find(Object) == ObjectBufferMap.end() 157 && "Second attempt to perform debug registration."); 158 159 jit_code_entry* JITCodeEntry = new jit_code_entry(); 160 161 if (JITCodeEntry == 0) { 162 llvm::report_fatal_error("Allocation failed when registering a GDB-JIT entry!\n"); 163 } 164 else { 165 JITCodeEntry->symfile_addr = Object; 166 JITCodeEntry->symfile_size = Size; 167 168 ObjectBufferMap[Object] = std::make_pair(Size, JITCodeEntry); 169 NotifyGDB(JITCodeEntry); 170 171 #ifdef ANDROID_ENGINEERING_BUILD 172 if (0 != gDebugDumpDirectory) { 173 std::string Filename(gDebugDumpDirectory); 174 Filename += "/jit_registered.o"; 175 176 std::ofstream outfile(Filename.c_str(), std::ofstream::binary); 177 outfile.write((char*)JITCodeEntry->symfile_addr, JITCodeEntry->symfile_size); 178 outfile.close(); 179 } 180 #endif 181 } 182 } 183 184 bool GDBJITRegistrar::deregisterObject(const ObjectBuffer *Object) { 185 RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Object); 186 187 if (I != ObjectBufferMap.end()) { 188 deregisterObjectInternal(I); 189 ObjectBufferMap.erase(I); 190 return true; 191 } 192 return false; 193 } 194 195 void GDBJITRegistrar::deregisterObjectInternal( 196 RegisteredObjectBufferMap::iterator I) { 197 198 jit_code_entry*& JITCodeEntry = I->second.second; 199 200 // Acquire the lock and do the unregistration. 201 { 202 llvm::MutexGuard locked(JITDebugLock); 203 __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; 204 205 // Remove the jit_code_entry from the linked list. 206 jit_code_entry* PrevEntry = JITCodeEntry->prev_entry; 207 jit_code_entry* NextEntry = JITCodeEntry->next_entry; 208 209 if (NextEntry) { 210 NextEntry->prev_entry = PrevEntry; 211 } 212 if (PrevEntry) { 213 PrevEntry->next_entry = NextEntry; 214 } 215 else { 216 assert(__jit_debug_descriptor.first_entry == JITCodeEntry); 217 __jit_debug_descriptor.first_entry = NextEntry; 218 } 219 220 // Tell GDB which entry we removed, and unregister the code. 221 __jit_debug_descriptor.relevant_entry = JITCodeEntry; 222 __jit_debug_register_code(); 223 } 224 225 delete JITCodeEntry; 226 JITCodeEntry = NULL; 227 } 228 229 } // end namespace 230 231 void registerObjectWithGDB(const ObjectBuffer* Object, std::size_t Size) { 232 GDBJITRegistrar* Registrar = RegistrarSingleton(); 233 if (Registrar) { 234 Registrar->registerObject(Object, Size); 235 } 236 } 237 238 void deregisterObjectWithGDB(const ObjectBuffer* Object) { 239 GDBJITRegistrar* Registrar = RegistrarSingleton(); 240 if (Registrar) { 241 Registrar->deregisterObject(Object); 242 } 243 } 244