1094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/*
2094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * Copyright 2012, The Android Open Source Project
3094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea *
4094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * Licensed under the Apache License, Version 2.0 (the "License");
5094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * you may not use this file except in compliance with the License.
6094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * You may obtain a copy of the License at
7094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea *
8094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea *     http://www.apache.org/licenses/LICENSE-2.0
9094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea *
10094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * Unless required by applicable law or agreed to in writing, software
11094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * distributed under the License is distributed on an "AS IS" BASIS,
12094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * See the License for the specific language governing permissions and
14094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea * limitations under the License.
15094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea */
16094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
17094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// This file contains portions derived from LLVM, with the original copyright
18094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// header below:
19094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//==----- GDBJITRegistrar.cpp - Notify GDB about in-memory object files  ---==//
20094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//
21094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//                     The LLVM Compiler Infrastructure
22094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//
23094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// This file is distributed under the University of Illinois Open Source
24094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// License. See LICENSE.TXT for details.
25094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//
26094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//===----------------------------------------------------------------------===//
27094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//
28094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// This file defines the GDBJITRegistrar object which is used by JIT engines to
29094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// register in-memory object files with GDB for debugging.
30094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//
31094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//===----------------------------------------------------------------------===//
32094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
33c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/ExecutionEngine/GDBJITRegistrar.h"
34c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang
35c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/ADT/DenseMap.h>
36c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/Support/ErrorHandling.h>
37c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/Support/Memory.h>
38c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/Support/Mutex.h>
39c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/Support/MutexGuard.h>
40c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang
41c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/ExecutionEngine/GDBJIT.h"
42094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
43094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea#include <fstream>
44094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
45094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea#ifdef ANDROID_ENGINEERING_BUILD
46094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// Path to write dump output.
47094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// It is expected that a debugger (plugin) sets this
48094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// string to a writeable directory where files (such as JITted object files,
49094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// IR dumps) are to be written. If this variable is 0, no debug dumps
50094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// are generated.
51094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleachar* gDebugDumpDirectory = 0;
52094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea#endif // ANDROID_ENGINEERING_BUILD
53094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
54094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//************************************************************************
55094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// COPIED/ADAPTED FROM llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp
56094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//************************************************************************
57094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// This must be kept in sync with gdb/gdb/jit.h .
58094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleaextern "C" {
59094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
60094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  // We put information about the JITed function in this global, which the
61094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  // debugger reads.  Make sure to specify the version statically, because the
62094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  // debugger checks the version before we can set it during runtime.
63094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  static struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
64094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
65094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
66094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//****************************************************************************
67094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// END COPIED/ADAPTED FROM llvm/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp
68094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea//****************************************************************************
69094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
70094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleanamespace {
71094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
72094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea// Buffer for an in-memory object file in executable memory
73094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleatypedef llvm::DenseMap< const ObjectBuffer*, std::pair<std::size_t, jit_code_entry*> >
74094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  RegisteredObjectBufferMap;
75094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
76094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/// Global access point for the GDB JIT interface designed for use with a
77094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/// singleton toolbox. Handles thread-safe registration and deregistration of
78094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/// object files that are in executable memory managed by the client of this
79094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/// class.
80094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleaclass GDBJITRegistrar {
81094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// A map of in-memory object files that have been registered with the GDB JIT interface.
82094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  RegisteredObjectBufferMap ObjectBufferMap;
83094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
84094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleapublic:
85094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// Instantiates the GDB JIT service.
86094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  GDBJITRegistrar() : ObjectBufferMap() {}
87094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
88094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// Unregisters each object that was previously registered with GDB, and
89094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// releases all internal resources.
90094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  ~GDBJITRegistrar();
91094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
92094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// Creates an entry in the GDB JIT registry for the buffer @p Object,
93094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// which must contain an object file in executable memory with any
94094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// debug information for GDB.
95094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  void registerObject(const ObjectBuffer* Object, std::size_t Size);
96094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
97094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// Removes the internal registration of @p Object, and
98094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// frees associated resources.
99094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// Returns true if @p Object was found in ObjectBufferMap.
100094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  bool deregisterObject(const ObjectBuffer* Object);
101094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
102094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleaprivate:
103094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// Deregister the debug info for the given object file from the debugger
104094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// and delete any temporary copies.  This private method does not remove
105094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  /// the function from Map so that it can be called while iterating over Map.
106094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I);
107094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea};
108094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
109094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/// Lock used to serialize all gdb-jit registration events, since they
110094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/// modify global variables.
111094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleallvm::sys::Mutex JITDebugLock;
112094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
113094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea/// Acquire the lock and do the registration.
114094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleavoid NotifyGDB(jit_code_entry* JITCodeEntry) {
115094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  llvm::MutexGuard locked(JITDebugLock);
116094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
117094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
118094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  // Insert this entry at the head of the list.
119094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  JITCodeEntry->prev_entry = NULL;
120094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  jit_code_entry* NextEntry = __jit_debug_descriptor.first_entry;
121094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  JITCodeEntry->next_entry = NextEntry;
122094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  if (NextEntry != NULL) {
123094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    NextEntry->prev_entry = JITCodeEntry;
124094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
125094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  __jit_debug_descriptor.first_entry = JITCodeEntry;
126094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  __jit_debug_descriptor.relevant_entry = JITCodeEntry;
127094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  __jit_debug_register_code();
128094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
129094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
130094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel MaleaGDBJITRegistrar* RegistrarSingleton() {
131094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  static GDBJITRegistrar* sRegistrar = NULL;
132094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  if (sRegistrar == NULL) {
133094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    // The mutex is here so that it won't slow down access once the registrar
134094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    //   is instantiated
135094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    llvm::MutexGuard locked(JITDebugLock);
136094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    // Check again to be sure another thread didn't create this while we waited
137094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    if (sRegistrar == NULL) {
138094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      sRegistrar = new GDBJITRegistrar;
139094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    }
140094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
141094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  return sRegistrar;
142094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
143094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
144094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel MaleaGDBJITRegistrar::~GDBJITRegistrar() {
145094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  // Free all registered object files.
146094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(), E = ObjectBufferMap.end();
147094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea       I != E; ++I) {
148094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    // Call the private method that doesn't update the map so our iterator
149094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    // doesn't break.
150094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    deregisterObjectInternal(I);
151094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
152094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  ObjectBufferMap.clear();
153094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
154094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
155094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleavoid GDBJITRegistrar::registerObject(const ObjectBuffer* Object, std::size_t Size) {
156094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
157094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  assert(Object && "Attempt to register a null object with a debugger.");
158094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  assert(ObjectBufferMap.find(Object) == ObjectBufferMap.end()
159094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    && "Second attempt to perform debug registration.");
160094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
161094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  jit_code_entry* JITCodeEntry = new jit_code_entry();
162094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
163094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  if (JITCodeEntry == 0) {
164094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    llvm::report_fatal_error("Allocation failed when registering a GDB-JIT entry!\n");
165094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
166094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  else {
167094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    JITCodeEntry->symfile_addr = Object;
168094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    JITCodeEntry->symfile_size = Size;
169094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
170094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    ObjectBufferMap[Object] = std::make_pair(Size, JITCodeEntry);
171094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    NotifyGDB(JITCodeEntry);
172094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
173094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea#ifdef ANDROID_ENGINEERING_BUILD
174094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    if (0 != gDebugDumpDirectory) {
175094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      std::string Filename(gDebugDumpDirectory);
176094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      Filename += "/jit_registered.o";
177094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
178094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      std::ofstream outfile(Filename.c_str(), std::ofstream::binary);
179094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      outfile.write((char*)JITCodeEntry->symfile_addr, JITCodeEntry->symfile_size);
180094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      outfile.close();
181094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    }
182094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea#endif
183094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
184094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
185094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
186094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleabool GDBJITRegistrar::deregisterObject(const ObjectBuffer *Object) {
187094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(Object);
188094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
189094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  if (I != ObjectBufferMap.end()) {
190094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    deregisterObjectInternal(I);
191094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    ObjectBufferMap.erase(I);
192094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    return true;
193094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
194094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  return false;
195094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
196094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
197094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleavoid GDBJITRegistrar::deregisterObjectInternal(
198094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    RegisteredObjectBufferMap::iterator I) {
199094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
200094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  jit_code_entry*& JITCodeEntry = I->second.second;
201094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
202094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  // Acquire the lock and do the unregistration.
203094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  {
204094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    llvm::MutexGuard locked(JITDebugLock);
205094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
206094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
207094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    // Remove the jit_code_entry from the linked list.
208094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    jit_code_entry* PrevEntry = JITCodeEntry->prev_entry;
209094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    jit_code_entry* NextEntry = JITCodeEntry->next_entry;
210094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
211094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    if (NextEntry) {
212094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      NextEntry->prev_entry = PrevEntry;
213094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    }
214094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    if (PrevEntry) {
215094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      PrevEntry->next_entry = NextEntry;
216094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    }
217094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    else {
218094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
219094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea      __jit_debug_descriptor.first_entry = NextEntry;
220094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    }
221094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
222094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    // Tell GDB which entry we removed, and unregister the code.
223094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    __jit_debug_descriptor.relevant_entry = JITCodeEntry;
224094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    __jit_debug_register_code();
225094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
226094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
227094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  delete JITCodeEntry;
228094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  JITCodeEntry = NULL;
229094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
230094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
231094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea} // end namespace
232094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
233094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleavoid registerObjectWithGDB(const ObjectBuffer* Object, std::size_t Size) {
234094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  GDBJITRegistrar* Registrar = RegistrarSingleton();
235094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  if (Registrar) {
236094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    Registrar->registerObject(Object, Size);
237094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
238094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
239094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea
240094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleavoid deregisterObjectWithGDB(const ObjectBuffer* Object) {
241094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  GDBJITRegistrar* Registrar = RegistrarSingleton();
242094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  if (Registrar) {
243094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea    Registrar->deregisterObject(Object);
244094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea  }
245094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea}
246