]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/jit.c
Replace some xmalloc-family functions with XNEW-family ones
[thirdparty/binutils-gdb.git] / gdb / jit.c
index ba4428b800f2ff46e0832f2279c05c35e959d815..10da21daae4520828dfcad567654832c876ed445 100644 (file)
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -1,7 +1,6 @@
 /* Handle JIT code generation in the inferior for GDB, the GNU Debugger.
 
-   Copyright (C) 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 2009-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "defs.h"
 
 #include "jit.h"
+#include "jit-reader.h"
+#include "block.h"
 #include "breakpoint.h"
+#include "command.h"
+#include "dictionary.h"
+#include "filenames.h"
+#include "frame-unwind.h"
+#include "gdbcmd.h"
 #include "gdbcore.h"
+#include "inferior.h"
 #include "observer.h"
 #include "objfiles.h"
+#include "regcache.h"
 #include "symfile.h"
 #include "symtab.h"
 #include "target.h"
-#include "gdb_stat.h"
+#include "gdb-dlfcn.h"
+#include <sys/stat.h>
+#include "gdb_bfd.h"
+
+static const char *jit_reader_dir = NULL;
 
 static const struct objfile_data *jit_objfile_data;
 
@@ -36,31 +48,31 @@ static const char *const jit_break_name = "__jit_debug_register_code";
 
 static const char *const jit_descriptor_name = "__jit_debug_descriptor";
 
-/* This is the address of the JIT descriptor in the inferior.  */
+static const struct program_space_data *jit_program_space_data = NULL;
+
+static void jit_inferior_init (struct gdbarch *gdbarch);
 
-static CORE_ADDR jit_descriptor_addr = 0;
+/* An unwinder is registered for every gdbarch.  This key is used to
+   remember if the unwinder has been registered for a particular
+   gdbarch.  */
 
-/* This is a boolean indicating whether we're currently registering code.  This
-   is used to avoid re-entering the registration code.  We want to check for
-   new JITed every time a new object file is loaded, but we want to avoid
-   checking for new code while we're registering object files for JITed code.
-   Therefore, we flip this variable to 1 before registering new object files,
-   and set it to 0 before returning.  */
+static struct gdbarch_data *jit_gdbarch_data;
 
-static int registering_code = 0;
+/* Non-zero if we want to see trace of jit level stuff.  */
 
-/* Helper cleanup function to clear an integer flag like the one above.  */
+static unsigned int jit_debug = 0;
 
 static void
-clear_int (void *int_addr)
+show_jit_debug (struct ui_file *file, int from_tty,
+               struct cmd_list_element *c, const char *value)
 {
-  *((int *) int_addr) = 0;
+  fprintf_filtered (file, _("JIT debugging is %s.\n"), value);
 }
 
 struct target_buffer
 {
   CORE_ADDR base;
-  size_t size;
+  ULONGEST size;
 };
 
 /* Openning the file is a no-op.  */
@@ -77,7 +89,9 @@ static int
 mem_bfd_iovec_close (struct bfd *abfd, void *stream)
 {
   xfree (stream);
-  return 1;
+
+  /* Zero means success.  */
+  return 0;
 }
 
 /* For reading the file, we just need to pass through to target_read_memory and
@@ -112,6 +126,7 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
 {
   struct target_buffer *buffer = (struct target_buffer*) stream;
 
+  memset (sb, 0, sizeof (struct stat));
   sb->st_size = buffer->size;
   return 0;
 }
@@ -119,26 +134,211 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
 /* Open a BFD from the target's memory.  */
 
 static struct bfd *
-bfd_open_from_target_memory (CORE_ADDR addr, size_t size, char *target)
+bfd_open_from_target_memory (CORE_ADDR addr, ULONGEST size, char *target)
 {
-  const char *filename = xstrdup ("<in-memory>");
-  struct target_buffer *buffer = xmalloc (sizeof (struct target_buffer));
+  struct target_buffer *buffer = XNEW (struct target_buffer);
 
   buffer->base = addr;
   buffer->size = size;
-  return bfd_openr_iovec (filename, target,
-                          mem_bfd_iovec_open,
-                          buffer,
-                          mem_bfd_iovec_pread,
-                          mem_bfd_iovec_close,
-                          mem_bfd_iovec_stat);
+  return gdb_bfd_openr_iovec ("<in-memory>", target,
+                             mem_bfd_iovec_open,
+                             buffer,
+                             mem_bfd_iovec_pread,
+                             mem_bfd_iovec_close,
+                             mem_bfd_iovec_stat);
 }
 
-/* Helper function for reading the global JIT descriptor from remote memory.  */
+/* One reader that has been loaded successfully, and can potentially be used to
+   parse debug info.  */
+
+static struct jit_reader
+{
+  struct gdb_reader_funcs *functions;
+  void *handle;
+} *loaded_jit_reader = NULL;
+
+typedef struct gdb_reader_funcs * (reader_init_fn_type) (void);
+static const char *reader_init_fn_sym = "gdb_init_reader";
+
+/* Try to load FILE_NAME as a JIT debug info reader.  */
+
+static struct jit_reader *
+jit_reader_load (const char *file_name)
+{
+  void *so;
+  reader_init_fn_type *init_fn;
+  struct jit_reader *new_reader = NULL;
+  struct gdb_reader_funcs *funcs = NULL;
+  struct cleanup *old_cleanups;
+
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog, _("Opening shared object %s.\n"),
+                        file_name);
+  so = gdb_dlopen (file_name);
+  old_cleanups = make_cleanup_dlclose (so);
+
+  init_fn = gdb_dlsym (so, reader_init_fn_sym);
+  if (!init_fn)
+    error (_("Could not locate initialization function: %s."),
+          reader_init_fn_sym);
+
+  if (gdb_dlsym (so, "plugin_is_GPL_compatible") == NULL)
+    error (_("Reader not GPL compatible."));
+
+  funcs = init_fn ();
+  if (funcs->reader_version != GDB_READER_INTERFACE_VERSION)
+    error (_("Reader version does not match GDB version."));
+
+  new_reader = XCNEW (struct jit_reader);
+  new_reader->functions = funcs;
+  new_reader->handle = so;
+
+  discard_cleanups (old_cleanups);
+  return new_reader;
+}
+
+/* Provides the jit-reader-load command.  */
 
 static void
+jit_reader_load_command (char *args, int from_tty)
+{
+  char *so_name;
+  struct cleanup *prev_cleanup;
+
+  if (args == NULL)
+    error (_("No reader name provided."));
+
+  if (loaded_jit_reader != NULL)
+    error (_("JIT reader already loaded.  Run jit-reader-unload first."));
+
+  if (IS_ABSOLUTE_PATH (args))
+    so_name = xstrdup (args);
+  else
+    so_name = xstrprintf ("%s%s%s", jit_reader_dir, SLASH_STRING, args);
+  prev_cleanup = make_cleanup (xfree, so_name);
+
+  loaded_jit_reader = jit_reader_load (so_name);
+  do_cleanups (prev_cleanup);
+}
+
+/* Provides the jit-reader-unload command.  */
+
+static void
+jit_reader_unload_command (char *args, int from_tty)
+{
+  if (!loaded_jit_reader)
+    error (_("No JIT reader loaded."));
+
+  loaded_jit_reader->functions->destroy (loaded_jit_reader->functions);
+
+  gdb_dlclose (loaded_jit_reader->handle);
+  xfree (loaded_jit_reader);
+  loaded_jit_reader = NULL;
+}
+
+/* Per-program space structure recording which objfile has the JIT
+   symbols.  */
+
+struct jit_program_space_data
+{
+  /* The objfile.  This is NULL if no objfile holds the JIT
+     symbols.  */
+
+  struct objfile *objfile;
+
+  /* If this program space has __jit_debug_register_code, this is the
+     cached address from the minimal symbol.  This is used to detect
+     relocations requiring the breakpoint to be re-created.  */
+
+  CORE_ADDR cached_code_address;
+
+  /* This is the JIT event breakpoint, or NULL if it has not been
+     set.  */
+
+  struct breakpoint *jit_breakpoint;
+};
+
+/* Per-objfile structure recording the addresses in the program space.
+   This object serves two purposes: for ordinary objfiles, it may
+   cache some symbols related to the JIT interface; and for
+   JIT-created objfiles, it holds some information about the
+   jit_code_entry.  */
+
+struct jit_objfile_data
+{
+  /* Symbol for __jit_debug_register_code.  */
+  struct minimal_symbol *register_code;
+
+  /* Symbol for __jit_debug_descriptor.  */
+  struct minimal_symbol *descriptor;
+
+  /* Address of struct jit_code_entry in this objfile.  This is only
+     non-zero for objfiles that represent code created by the JIT.  */
+  CORE_ADDR addr;
+};
+
+/* Fetch the jit_objfile_data associated with OBJF.  If no data exists
+   yet, make a new structure and attach it.  */
+
+static struct jit_objfile_data *
+get_jit_objfile_data (struct objfile *objf)
+{
+  struct jit_objfile_data *objf_data;
+
+  objf_data = objfile_data (objf, jit_objfile_data);
+  if (objf_data == NULL)
+    {
+      objf_data = XCNEW (struct jit_objfile_data);
+      set_objfile_data (objf, jit_objfile_data, objf_data);
+    }
+
+  return objf_data;
+}
+
+/* Remember OBJFILE has been created for struct jit_code_entry located
+   at inferior address ENTRY.  */
+
+static void
+add_objfile_entry (struct objfile *objfile, CORE_ADDR entry)
+{
+  struct jit_objfile_data *objf_data;
+
+  objf_data = get_jit_objfile_data (objfile);
+  objf_data->addr = entry;
+}
+
+/* Return jit_program_space_data for current program space.  Allocate
+   if not already present.  */
+
+static struct jit_program_space_data *
+get_jit_program_space_data (void)
+{
+  struct jit_program_space_data *ps_data;
+
+  ps_data = program_space_data (current_program_space, jit_program_space_data);
+  if (ps_data == NULL)
+    {
+      ps_data = XCNEW (struct jit_program_space_data);
+      set_program_space_data (current_program_space, jit_program_space_data,
+                             ps_data);
+    }
+
+  return ps_data;
+}
+
+static void
+jit_program_space_data_cleanup (struct program_space *ps, void *arg)
+{
+  xfree (arg);
+}
+
+/* Helper function for reading the global JIT descriptor from remote
+   memory.  Returns 1 if all went well, 0 otherwise.  */
+
+static int
 jit_read_descriptor (struct gdbarch *gdbarch,
-                    struct jit_descriptor *descriptor)
+                    struct jit_descriptor *descriptor,
+                    struct jit_program_space_data *ps_data)
 {
   int err;
   struct type *ptr_type;
@@ -146,6 +346,19 @@ jit_read_descriptor (struct gdbarch *gdbarch,
   int desc_size;
   gdb_byte *desc_buf;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct jit_objfile_data *objf_data;
+
+  if (ps_data->objfile == NULL)
+    return 0;
+  objf_data = get_jit_objfile_data (ps_data->objfile);
+  if (objf_data->descriptor == NULL)
+    return 0;
+
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "jit_read_descriptor, descriptor_addr = %s\n",
+                       paddress (gdbarch, MSYMBOL_VALUE_ADDRESS (ps_data->objfile,
+                                                                 objf_data->descriptor)));
 
   /* Figure out how big the descriptor is on the remote and how to read it.  */
   ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
@@ -154,9 +367,15 @@ jit_read_descriptor (struct gdbarch *gdbarch,
   desc_buf = alloca (desc_size);
 
   /* Read the descriptor.  */
-  err = target_read_memory (jit_descriptor_addr, desc_buf, desc_size);
+  err = target_read_memory (MSYMBOL_VALUE_ADDRESS (ps_data->objfile,
+                                                  objf_data->descriptor),
+                           desc_buf, desc_size);
   if (err)
-    error (_("Unable to read JIT descriptor from remote memory!"));
+    {
+      printf_unfiltered (_("Unable to read JIT descriptor from "
+                          "remote memory\n"));
+      return 0;
+    }
 
   /* Fix the endianness to match the host.  */
   descriptor->version = extract_unsigned_integer (&desc_buf[0], 4, byte_order);
@@ -165,6 +384,8 @@ jit_read_descriptor (struct gdbarch *gdbarch,
   descriptor->relevant_entry = extract_typed_address (&desc_buf[8], ptr_type);
   descriptor->first_entry =
       extract_typed_address (&desc_buf[8 + ptr_size], ptr_type);
+
+  return 1;
 }
 
 /* Helper function for reading a JITed code entry from remote memory.  */
@@ -173,17 +394,24 @@ static void
 jit_read_code_entry (struct gdbarch *gdbarch,
                     CORE_ADDR code_addr, struct jit_code_entry *code_entry)
 {
-  int err;
+  int err, off;
   struct type *ptr_type;
   int ptr_size;
   int entry_size;
+  int align_bytes;
   gdb_byte *entry_buf;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   /* Figure out how big the entry is on the remote and how to read it.  */
   ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
   ptr_size = TYPE_LENGTH (ptr_type);
-  entry_size = 3 * ptr_size + 8;  /* Three pointers and one 64-bit int.  */
+
+  /* Figure out where the longlong value will be.  */
+  align_bytes = gdbarch_long_long_align_bit (gdbarch) / 8;
+  off = 3 * ptr_size;
+  off = (off + (align_bytes - 1)) & ~(align_bytes - 1);
+
+  entry_size = off + 8;  /* Three pointers and one 64-bit int.  */
   entry_buf = alloca (entry_size);
 
   /* Read the entry.  */
@@ -199,30 +427,475 @@ jit_read_code_entry (struct gdbarch *gdbarch,
   code_entry->symfile_addr =
       extract_typed_address (&entry_buf[2 * ptr_size], ptr_type);
   code_entry->symfile_size =
-      extract_unsigned_integer (&entry_buf[3 * ptr_size], 8, byte_order);
+      extract_unsigned_integer (&entry_buf[off], 8, byte_order);
 }
 
-/* This function registers code associated with a JIT code entry.  It uses the
-   pointer and size pair in the entry to read the symbol file from the remote
-   and then calls symbol_file_add_from_local_memory to add it as though it were
-   a symbol file added by the user.  */
+/* Proxy object for building a block.  */
+
+struct gdb_block
+{
+  /* gdb_blocks are linked into a tree structure.  Next points to the
+     next node at the same depth as this block and parent to the
+     parent gdb_block.  */
+  struct gdb_block *next, *parent;
+
+  /* Points to the "real" block that is being built out of this
+     instance.  This block will be added to a blockvector, which will
+     then be added to a symtab.  */
+  struct block *real_block;
+
+  /* The first and last code address corresponding to this block.  */
+  CORE_ADDR begin, end;
+
+  /* The name of this block (if any).  If this is non-NULL, the
+     FUNCTION symbol symbol is set to this value.  */
+  const char *name;
+};
+
+/* Proxy object for building a symtab.  */
+
+struct gdb_symtab
+{
+  /* The list of blocks in this symtab.  These will eventually be
+     converted to real blocks.  */
+  struct gdb_block *blocks;
+
+  /* The number of blocks inserted.  */
+  int nblocks;
+
+  /* A mapping between line numbers to PC.  */
+  struct linetable *linetable;
+
+  /* The source file for this symtab.  */
+  const char *file_name;
+  struct gdb_symtab *next;
+};
+
+/* Proxy object for building an object.  */
+
+struct gdb_object
+{
+  struct gdb_symtab *symtabs;
+};
+
+/* The type of the `private' data passed around by the callback
+   functions.  */
+
+typedef CORE_ADDR jit_dbg_reader_data;
+
+/* The reader calls into this function to read data off the targets
+   address space.  */
+
+static enum gdb_status
+jit_target_read_impl (GDB_CORE_ADDR target_mem, void *gdb_buf, int len)
+{
+  int result = target_read_memory ((CORE_ADDR) target_mem, gdb_buf, len);
+  if (result == 0)
+    return GDB_SUCCESS;
+  else
+    return GDB_FAIL;
+}
+
+/* The reader calls into this function to create a new gdb_object
+   which it can then pass around to the other callbacks.  Right now,
+   all that is required is allocating the memory.  */
+
+static struct gdb_object *
+jit_object_open_impl (struct gdb_symbol_callbacks *cb)
+{
+  /* CB is not required right now, but sometime in the future we might
+     need a handle to it, and we'd like to do that without breaking
+     the ABI.  */
+  return XCNEW (struct gdb_object);
+}
+
+/* Readers call into this function to open a new gdb_symtab, which,
+   again, is passed around to other callbacks.  */
+
+static struct gdb_symtab *
+jit_symtab_open_impl (struct gdb_symbol_callbacks *cb,
+                      struct gdb_object *object,
+                      const char *file_name)
+{
+  struct gdb_symtab *ret;
+
+  /* CB stays unused.  See comment in jit_object_open_impl.  */
+
+  ret = XCNEW (struct gdb_symtab);
+  ret->file_name = file_name ? xstrdup (file_name) : xstrdup ("");
+  ret->next = object->symtabs;
+  object->symtabs = ret;
+  return ret;
+}
+
+/* Returns true if the block corresponding to old should be placed
+   before the block corresponding to new in the final blockvector.  */
+
+static int
+compare_block (const struct gdb_block *const old,
+               const struct gdb_block *const newobj)
+{
+  if (old == NULL)
+    return 1;
+  if (old->begin < newobj->begin)
+    return 1;
+  else if (old->begin == newobj->begin)
+    {
+      if (old->end > newobj->end)
+        return 1;
+      else
+        return 0;
+    }
+  else
+    return 0;
+}
+
+/* Called by readers to open a new gdb_block.  This function also
+   inserts the new gdb_block in the correct place in the corresponding
+   gdb_symtab.  */
+
+static struct gdb_block *
+jit_block_open_impl (struct gdb_symbol_callbacks *cb,
+                     struct gdb_symtab *symtab, struct gdb_block *parent,
+                     GDB_CORE_ADDR begin, GDB_CORE_ADDR end, const char *name)
+{
+  struct gdb_block *block = XCNEW (struct gdb_block);
+
+  block->next = symtab->blocks;
+  block->begin = (CORE_ADDR) begin;
+  block->end = (CORE_ADDR) end;
+  block->name = name ? xstrdup (name) : NULL;
+  block->parent = parent;
+
+  /* Ensure that the blocks are inserted in the correct (reverse of
+     the order expected by blockvector).  */
+  if (compare_block (symtab->blocks, block))
+    {
+      symtab->blocks = block;
+    }
+  else
+    {
+      struct gdb_block *i = symtab->blocks;
+
+      for (;; i = i->next)
+        {
+          /* Guaranteed to terminate, since compare_block (NULL, _)
+             returns 1.  */
+          if (compare_block (i->next, block))
+            {
+              block->next = i->next;
+              i->next = block;
+              break;
+            }
+        }
+    }
+  symtab->nblocks++;
+
+  return block;
+}
+
+/* Readers call this to add a line mapping (from PC to line number) to
+   a gdb_symtab.  */
 
 static void
-jit_register_code (struct gdbarch *gdbarch,
-                  CORE_ADDR entry_addr, struct jit_code_entry *code_entry)
+jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb,
+                                  struct gdb_symtab *stab, int nlines,
+                                  struct gdb_line_mapping *map)
+{
+  int i;
+
+  if (nlines < 1)
+    return;
+
+  stab->linetable = xmalloc (sizeof (struct linetable)
+                             + (nlines - 1) * sizeof (struct linetable_entry));
+  stab->linetable->nitems = nlines;
+  for (i = 0; i < nlines; i++)
+    {
+      stab->linetable->item[i].pc = (CORE_ADDR) map[i].pc;
+      stab->linetable->item[i].line = map[i].line;
+    }
+}
+
+/* Called by readers to close a gdb_symtab.  Does not need to do
+   anything as of now.  */
+
+static void
+jit_symtab_close_impl (struct gdb_symbol_callbacks *cb,
+                       struct gdb_symtab *stab)
+{
+  /* Right now nothing needs to be done here.  We may need to do some
+     cleanup here in the future (again, without breaking the plugin
+     ABI).  */
+}
+
+/* Transform STAB to a proper symtab, and add it it OBJFILE.  */
+
+static void
+finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
+{
+  struct compunit_symtab *cust;
+  struct gdb_block *gdb_block_iter, *gdb_block_iter_tmp;
+  struct block *block_iter;
+  int actual_nblocks, i;
+  size_t blockvector_size;
+  CORE_ADDR begin, end;
+  struct blockvector *bv;
+
+  actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
+
+  cust = allocate_compunit_symtab (objfile, stab->file_name);
+  allocate_symtab (cust, stab->file_name);
+  add_compunit_symtab_to_objfile (cust);
+
+  /* JIT compilers compile in memory.  */
+  COMPUNIT_DIRNAME (cust) = NULL;
+
+  /* Copy over the linetable entry if one was provided.  */
+  if (stab->linetable)
+    {
+      size_t size = ((stab->linetable->nitems - 1)
+                    * sizeof (struct linetable_entry)
+                    + sizeof (struct linetable));
+      SYMTAB_LINETABLE (COMPUNIT_FILETABS (cust))
+       = obstack_alloc (&objfile->objfile_obstack, size);
+      memcpy (SYMTAB_LINETABLE (COMPUNIT_FILETABS (cust)), stab->linetable,
+             size);
+    }
+
+  blockvector_size = (sizeof (struct blockvector)
+                      + (actual_nblocks - 1) * sizeof (struct block *));
+  bv = obstack_alloc (&objfile->objfile_obstack, blockvector_size);
+  COMPUNIT_BLOCKVECTOR (cust) = bv;
+
+  /* (begin, end) will contain the PC range this entire blockvector
+     spans.  */
+  BLOCKVECTOR_MAP (bv) = NULL;
+  begin = stab->blocks->begin;
+  end = stab->blocks->end;
+  BLOCKVECTOR_NBLOCKS (bv) = actual_nblocks;
+
+  /* First run over all the gdb_block objects, creating a real block
+     object for each.  Simultaneously, keep setting the real_block
+     fields.  */
+  for (i = (actual_nblocks - 1), gdb_block_iter = stab->blocks;
+       i >= FIRST_LOCAL_BLOCK;
+       i--, gdb_block_iter = gdb_block_iter->next)
+    {
+      struct block *new_block = allocate_block (&objfile->objfile_obstack);
+      struct symbol *block_name = allocate_symbol (objfile);
+      struct type *block_type = arch_type (get_objfile_arch (objfile),
+                                          TYPE_CODE_VOID,
+                                          1,
+                                          "void");
+
+      BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
+                                                   NULL);
+      /* The address range.  */
+      BLOCK_START (new_block) = (CORE_ADDR) gdb_block_iter->begin;
+      BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end;
+
+      /* The name.  */
+      SYMBOL_DOMAIN (block_name) = VAR_DOMAIN;
+      SYMBOL_ACLASS_INDEX (block_name) = LOC_BLOCK;
+      symbol_set_symtab (block_name, COMPUNIT_FILETABS (cust));
+      SYMBOL_TYPE (block_name) = lookup_function_type (block_type);
+      SYMBOL_BLOCK_VALUE (block_name) = new_block;
+
+      block_name->ginfo.name = obstack_copy0 (&objfile->objfile_obstack,
+                                             gdb_block_iter->name,
+                                             strlen (gdb_block_iter->name));
+
+      BLOCK_FUNCTION (new_block) = block_name;
+
+      BLOCKVECTOR_BLOCK (bv, i) = new_block;
+      if (begin > BLOCK_START (new_block))
+        begin = BLOCK_START (new_block);
+      if (end < BLOCK_END (new_block))
+        end = BLOCK_END (new_block);
+
+      gdb_block_iter->real_block = new_block;
+    }
+
+  /* Now add the special blocks.  */
+  block_iter = NULL;
+  for (i = 0; i < FIRST_LOCAL_BLOCK; i++)
+    {
+      struct block *new_block;
+
+      new_block = (i == GLOBAL_BLOCK
+                  ? allocate_global_block (&objfile->objfile_obstack)
+                  : allocate_block (&objfile->objfile_obstack));
+      BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
+                                                   NULL);
+      BLOCK_SUPERBLOCK (new_block) = block_iter;
+      block_iter = new_block;
+
+      BLOCK_START (new_block) = (CORE_ADDR) begin;
+      BLOCK_END (new_block) = (CORE_ADDR) end;
+
+      BLOCKVECTOR_BLOCK (bv, i) = new_block;
+
+      if (i == GLOBAL_BLOCK)
+       set_block_compunit_symtab (new_block, cust);
+    }
+
+  /* Fill up the superblock fields for the real blocks, using the
+     real_block fields populated earlier.  */
+  for (gdb_block_iter = stab->blocks;
+       gdb_block_iter;
+       gdb_block_iter = gdb_block_iter->next)
+    {
+      if (gdb_block_iter->parent != NULL)
+       {
+         /* If the plugin specifically mentioned a parent block, we
+            use that.  */
+         BLOCK_SUPERBLOCK (gdb_block_iter->real_block) =
+           gdb_block_iter->parent->real_block;
+       }
+      else
+       {
+         /* And if not, we set a default parent block.  */
+         BLOCK_SUPERBLOCK (gdb_block_iter->real_block) =
+           BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+       }
+    }
+
+  /* Free memory.  */
+  gdb_block_iter = stab->blocks;
+
+  for (gdb_block_iter = stab->blocks, gdb_block_iter_tmp = gdb_block_iter->next;
+       gdb_block_iter;
+       gdb_block_iter = gdb_block_iter_tmp)
+    {
+      xfree ((void *) gdb_block_iter->name);
+      xfree (gdb_block_iter);
+    }
+  xfree (stab->linetable);
+  xfree ((char *) stab->file_name);
+  xfree (stab);
+}
+
+/* Called when closing a gdb_objfile.  Converts OBJ to a proper
+   objfile.  */
+
+static void
+jit_object_close_impl (struct gdb_symbol_callbacks *cb,
+                       struct gdb_object *obj)
+{
+  struct gdb_symtab *i, *j;
+  struct objfile *objfile;
+  jit_dbg_reader_data *priv_data;
+
+  priv_data = cb->priv_data;
+
+  objfile = allocate_objfile (NULL, "<< JIT compiled code >>",
+                             OBJF_NOT_FILENAME);
+  objfile->per_bfd->gdbarch = target_gdbarch ();
+
+  terminate_minimal_symbol_table (objfile);
+
+  j = NULL;
+  for (i = obj->symtabs; i; i = j)
+    {
+      j = i->next;
+      finalize_symtab (i, objfile);
+    }
+  add_objfile_entry (objfile, *priv_data);
+  xfree (obj);
+}
+
+/* Try to read CODE_ENTRY using the loaded jit reader (if any).
+   ENTRY_ADDR is the address of the struct jit_code_entry in the
+   inferior address space.  */
+
+static int
+jit_reader_try_read_symtab (struct jit_code_entry *code_entry,
+                            CORE_ADDR entry_addr)
+{
+  void *gdb_mem;
+  int status;
+  jit_dbg_reader_data priv_data;
+  struct gdb_reader_funcs *funcs;
+  struct gdb_symbol_callbacks callbacks =
+    {
+      jit_object_open_impl,
+      jit_symtab_open_impl,
+      jit_block_open_impl,
+      jit_symtab_close_impl,
+      jit_object_close_impl,
+
+      jit_symtab_line_mapping_add_impl,
+      jit_target_read_impl,
+
+      &priv_data
+    };
+
+  priv_data = entry_addr;
+
+  if (!loaded_jit_reader)
+    return 0;
+
+  gdb_mem = xmalloc (code_entry->symfile_size);
+
+  status = 1;
+  TRY
+    {
+      if (target_read_memory (code_entry->symfile_addr, gdb_mem,
+                             code_entry->symfile_size))
+       status = 0;
+    }
+  CATCH (e, RETURN_MASK_ALL)
+    {
+      status = 0;
+    }
+  END_CATCH
+
+  if (status)
+    {
+      funcs = loaded_jit_reader->functions;
+      if (funcs->read (funcs, &callbacks, gdb_mem, code_entry->symfile_size)
+          != GDB_SUCCESS)
+        status = 0;
+    }
+
+  xfree (gdb_mem);
+  if (jit_debug && status == 0)
+    fprintf_unfiltered (gdb_stdlog,
+                        "Could not read symtab using the loaded JIT reader.\n");
+  return status;
+}
+
+/* Try to read CODE_ENTRY using BFD.  ENTRY_ADDR is the address of the
+   struct jit_code_entry in the inferior address space.  */
+
+static void
+jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
+                         CORE_ADDR entry_addr,
+                         struct gdbarch *gdbarch)
 {
   bfd *nbfd;
   struct section_addr_info *sai;
   struct bfd_section *sec;
   struct objfile *objfile;
-  struct cleanup *old_cleanups, *my_cleanups;
+  struct cleanup *old_cleanups;
   int i;
   const struct bfd_arch_info *b;
-  CORE_ADDR *entry_addr_ptr;
+
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "jit_register_code, symfile_addr = %s, "
+                       "symfile_size = %s\n",
+                       paddress (gdbarch, code_entry->symfile_addr),
+                       pulongest (code_entry->symfile_size));
 
   nbfd = bfd_open_from_target_memory (code_entry->symfile_addr,
                                       code_entry->symfile_size, gnutarget);
-  old_cleanups = make_cleanup_bfd_close (nbfd);
+  if (nbfd == NULL)
+    {
+      puts_unfiltered (_("Error opening JITed symbol file, ignoring it.\n"));
+      return;
+    }
 
   /* Check the format.  NOTE: This initializes important data that GDB uses!
      We would segfault later without this line.  */
@@ -230,7 +903,7 @@ jit_register_code (struct gdbarch *gdbarch,
     {
       printf_unfiltered (_("\
 JITed symbol file is not an object file, ignoring it.\n"));
-      do_cleanups (old_cleanups);
+      gdb_bfd_unref (nbfd);
       return;
     }
 
@@ -245,7 +918,7 @@ JITed symbol file is not an object file, ignoring it.\n"));
      file is generated by the JIT at runtime, it should all of the absolute
      addresses that we care about.  */
   sai = alloc_section_addr_info (bfd_count_sections (nbfd));
-  make_cleanup_free_section_addr_info (sai);
+  old_cleanups = make_cleanup_free_section_addr_info (sai);
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
@@ -257,27 +930,43 @@ JITed symbol file is not an object file, ignoring it.\n"));
         sai->other[i].sectindex = sec->index;
         ++i;
       }
+  sai->num_sections = i;
+
+  /* This call does not take ownership of SAI.  */
+  make_cleanup_bfd_unref (nbfd);
+  objfile = symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd), 0, sai,
+                                     OBJF_SHARED | OBJF_NOT_FILENAME, NULL);
+
+  do_cleanups (old_cleanups);
+  add_objfile_entry (objfile, entry_addr);
+}
 
-  /* Raise this flag while we register code so we won't trigger any
-     re-registration.  */
-  registering_code = 1;
-  my_cleanups = make_cleanup (clear_int, &registering_code);
+/* This function registers code associated with a JIT code entry.  It uses the
+   pointer and size pair in the entry to read the symbol file from the remote
+   and then calls symbol_file_add_from_local_memory to add it as though it were
+   a symbol file added by the user.  */
 
-  /* This call takes ownership of sai.  */
-  objfile = symbol_file_add_from_bfd (nbfd, 0, sai, OBJF_SHARED);
+static void
+jit_register_code (struct gdbarch *gdbarch,
+                   CORE_ADDR entry_addr, struct jit_code_entry *code_entry)
+{
+  int success;
 
-  /* Clear the registering_code flag.  */
-  do_cleanups (my_cleanups);
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog,
+                        "jit_register_code, symfile_addr = %s, "
+                        "symfile_size = %s\n",
+                        paddress (gdbarch, code_entry->symfile_addr),
+                        pulongest (code_entry->symfile_size));
 
-  /* Remember a mapping from entry_addr to objfile.  */
-  entry_addr_ptr = xmalloc (sizeof (CORE_ADDR));
-  *entry_addr_ptr = entry_addr;
-  set_objfile_data (objfile, jit_objfile_data, entry_addr_ptr);
+  success = jit_reader_try_read_symtab (code_entry, entry_addr);
 
-  discard_cleanups (old_cleanups);
+  if (!success)
+    jit_bfd_try_read_symtab (code_entry, entry_addr, gdbarch);
 }
 
-/* This function unregisters JITed code and frees the corresponding objfile.  */
+/* This function unregisters JITed code and frees the corresponding
+   objfile.  */
 
 static void
 jit_unregister_code (struct objfile *objfile)
@@ -291,68 +980,367 @@ static struct objfile *
 jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
 {
   struct objfile *objf;
-  CORE_ADDR *objf_entry_addr;
 
   ALL_OBJFILES (objf)
     {
-      objf_entry_addr = (CORE_ADDR *) objfile_data (objf, jit_objfile_data);
-      if (objf_entry_addr != NULL && *objf_entry_addr == entry_addr)
+      struct jit_objfile_data *objf_data;
+
+      objf_data = objfile_data (objf, jit_objfile_data);
+      if (objf_data != NULL && objf_data->addr == entry_addr)
         return objf;
     }
   return NULL;
 }
 
-/* (Re-)Initialize the jit breakpoint handler, and register any already
-   created translations.  */
+/* This is called when a breakpoint is deleted.  It updates the
+   inferior's cache, if needed.  */
+
+static void
+jit_breakpoint_deleted (struct breakpoint *b)
+{
+  struct bp_location *iter;
+
+  if (b->type != bp_jit_event)
+    return;
+
+  for (iter = b->loc; iter != NULL; iter = iter->next)
+    {
+      struct jit_program_space_data *ps_data;
+
+      ps_data = program_space_data (iter->pspace, jit_program_space_data);
+      if (ps_data != NULL && ps_data->jit_breakpoint == iter->owner)
+       {
+         ps_data->cached_code_address = 0;
+         ps_data->jit_breakpoint = NULL;
+       }
+    }
+}
+
+/* (Re-)Initialize the jit breakpoint if necessary.
+   Return 0 on success.  */
+
+static int
+jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
+                               struct jit_program_space_data *ps_data)
+{
+  struct bound_minimal_symbol reg_symbol;
+  struct bound_minimal_symbol desc_symbol;
+  struct jit_objfile_data *objf_data;
+  CORE_ADDR addr;
+
+  if (ps_data->objfile == NULL)
+    {
+      /* Lookup the registration symbol.  If it is missing, then we
+        assume we are not attached to a JIT.  */
+      reg_symbol = lookup_minimal_symbol_and_objfile (jit_break_name);
+      if (reg_symbol.minsym == NULL
+         || BMSYMBOL_VALUE_ADDRESS (reg_symbol) == 0)
+       return 1;
+
+      desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL,
+                                          reg_symbol.objfile);
+      if (desc_symbol.minsym == NULL
+         || BMSYMBOL_VALUE_ADDRESS (desc_symbol) == 0)
+       return 1;
+
+      objf_data = get_jit_objfile_data (reg_symbol.objfile);
+      objf_data->register_code = reg_symbol.minsym;
+      objf_data->descriptor = desc_symbol.minsym;
+
+      ps_data->objfile = reg_symbol.objfile;
+    }
+  else
+    objf_data = get_jit_objfile_data (ps_data->objfile);
+
+  addr = MSYMBOL_VALUE_ADDRESS (ps_data->objfile, objf_data->register_code);
+
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "jit_breakpoint_re_set_internal, "
+                       "breakpoint_addr = %s\n",
+                       paddress (gdbarch, addr));
+
+  if (ps_data->cached_code_address == addr)
+    return 1;
+
+  /* Delete the old breakpoint.  */
+  if (ps_data->jit_breakpoint != NULL)
+    delete_breakpoint (ps_data->jit_breakpoint);
+
+  /* Put a breakpoint in the registration symbol.  */
+  ps_data->cached_code_address = addr;
+  ps_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr);
+
+  return 0;
+}
+
+/* The private data passed around in the frame unwind callback
+   functions.  */
+
+struct jit_unwind_private
+{
+  /* Cached register values.  See jit_frame_sniffer to see how this
+     works.  */
+  struct gdb_reg_value **registers;
+
+  /* The frame being unwound.  */
+  struct frame_info *this_frame;
+};
+
+/* Sets the value of a particular register in this frame.  */
+
+static void
+jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int dwarf_regnum,
+                         struct gdb_reg_value *value)
+{
+  struct jit_unwind_private *priv;
+  int gdb_reg;
+
+  priv = cb->priv_data;
+
+  gdb_reg = gdbarch_dwarf2_reg_to_regnum (get_frame_arch (priv->this_frame),
+                                          dwarf_regnum);
+  if (gdb_reg == -1)
+    {
+      if (jit_debug)
+        fprintf_unfiltered (gdb_stdlog,
+                            _("Could not recognize DWARF regnum %d"),
+                            dwarf_regnum);
+      return;
+    }
+
+  gdb_assert (priv->registers);
+  priv->registers[gdb_reg] = value;
+}
+
+static void
+reg_value_free_impl (struct gdb_reg_value *value)
+{
+  xfree (value);
+}
+
+/* Get the value of register REGNUM in the previous frame.  */
+
+static struct gdb_reg_value *
+jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum)
+{
+  struct jit_unwind_private *priv;
+  struct gdb_reg_value *value;
+  int gdb_reg, size;
+  struct gdbarch *frame_arch;
+
+  priv = cb->priv_data;
+  frame_arch = get_frame_arch (priv->this_frame);
+
+  gdb_reg = gdbarch_dwarf2_reg_to_regnum (frame_arch, regnum);
+  size = register_size (frame_arch, gdb_reg);
+  value = xmalloc (sizeof (struct gdb_reg_value) + size - 1);
+  value->defined = deprecated_frame_register_read (priv->this_frame, gdb_reg,
+                                                  value->value);
+  value->size = size;
+  value->free = reg_value_free_impl;
+  return value;
+}
+
+/* gdb_reg_value has a free function, which must be called on each
+   saved register value.  */
+
+static void
+jit_dealloc_cache (struct frame_info *this_frame, void *cache)
+{
+  struct jit_unwind_private *priv_data = cache;
+  struct gdbarch *frame_arch;
+  int i;
+
+  gdb_assert (priv_data->registers);
+  frame_arch = get_frame_arch (priv_data->this_frame);
+
+  for (i = 0; i < gdbarch_num_regs (frame_arch); i++)
+    if (priv_data->registers[i] && priv_data->registers[i]->free)
+      priv_data->registers[i]->free (priv_data->registers[i]);
+
+  xfree (priv_data->registers);
+  xfree (priv_data);
+}
+
+/* The frame sniffer for the pseudo unwinder.
+
+   While this is nominally a frame sniffer, in the case where the JIT
+   reader actually recognizes the frame, it does a lot more work -- it
+   unwinds the frame and saves the corresponding register values in
+   the cache.  jit_frame_prev_register simply returns the saved
+   register values.  */
+
+static int
+jit_frame_sniffer (const struct frame_unwind *self,
+                   struct frame_info *this_frame, void **cache)
+{
+  struct jit_unwind_private *priv_data;
+  struct gdb_unwind_callbacks callbacks;
+  struct gdb_reader_funcs *funcs;
+
+  callbacks.reg_get = jit_unwind_reg_get_impl;
+  callbacks.reg_set = jit_unwind_reg_set_impl;
+  callbacks.target_read = jit_target_read_impl;
+
+  if (loaded_jit_reader == NULL)
+    return 0;
+
+  funcs = loaded_jit_reader->functions;
+
+  gdb_assert (!*cache);
+
+  *cache = XCNEW (struct jit_unwind_private);
+  priv_data = *cache;
+  priv_data->registers =
+    XCNEWVEC (struct gdb_reg_value *,        
+             gdbarch_num_regs (get_frame_arch (this_frame)));
+  priv_data->this_frame = this_frame;
+
+  callbacks.priv_data = priv_data;
+
+  /* Try to coax the provided unwinder to unwind the stack */
+  if (funcs->unwind (funcs, &callbacks) == GDB_SUCCESS)
+    {
+      if (jit_debug)
+        fprintf_unfiltered (gdb_stdlog, _("Successfully unwound frame using "
+                                          "JIT reader.\n"));
+      return 1;
+    }
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog, _("Could not unwind frame using "
+                                      "JIT reader.\n"));
+
+  jit_dealloc_cache (this_frame, *cache);
+  *cache = NULL;
+
+  return 0;
+}
+
+
+/* The frame_id function for the pseudo unwinder.  Relays the call to
+   the loaded plugin.  */
+
+static void
+jit_frame_this_id (struct frame_info *this_frame, void **cache,
+                   struct frame_id *this_id)
+{
+  struct jit_unwind_private priv;
+  struct gdb_frame_id frame_id;
+  struct gdb_reader_funcs *funcs;
+  struct gdb_unwind_callbacks callbacks;
+
+  priv.registers = NULL;
+  priv.this_frame = this_frame;
+
+  /* We don't expect the frame_id function to set any registers, so we
+     set reg_set to NULL.  */
+  callbacks.reg_get = jit_unwind_reg_get_impl;
+  callbacks.reg_set = NULL;
+  callbacks.target_read = jit_target_read_impl;
+  callbacks.priv_data = &priv;
+
+  gdb_assert (loaded_jit_reader);
+  funcs = loaded_jit_reader->functions;
+
+  frame_id = funcs->get_frame_id (funcs, &callbacks);
+  *this_id = frame_id_build (frame_id.stack_address, frame_id.code_address);
+}
+
+/* Pseudo unwinder function.  Reads the previously fetched value for
+   the register from the cache.  */
+
+static struct value *
+jit_frame_prev_register (struct frame_info *this_frame, void **cache, int reg)
+{
+  struct jit_unwind_private *priv = *cache;
+  struct gdb_reg_value *value;
+
+  if (priv == NULL)
+    return frame_unwind_got_optimized (this_frame, reg);
+
+  gdb_assert (priv->registers);
+  value = priv->registers[reg];
+  if (value && value->defined)
+    return frame_unwind_got_bytes (this_frame, reg, value->value);
+  else
+    return frame_unwind_got_optimized (this_frame, reg);
+}
+
+/* Relay everything back to the unwinder registered by the JIT debug
+   info reader.*/
+
+static const struct frame_unwind jit_frame_unwind =
+{
+  NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
+  jit_frame_this_id,
+  jit_frame_prev_register,
+  NULL,
+  jit_frame_sniffer,
+  jit_dealloc_cache
+};
+
+
+/* This is the information that is stored at jit_gdbarch_data for each
+   architecture.  */
+
+struct jit_gdbarch_data_type
+{
+  /* Has the (pseudo) unwinder been prepended? */
+  int unwinder_registered;
+};
+
+/* Check GDBARCH and prepend the pseudo JIT unwinder if needed.  */
+
+static void
+jit_prepend_unwinder (struct gdbarch *gdbarch)
+{
+  struct jit_gdbarch_data_type *data;
+
+  data = gdbarch_data (gdbarch, jit_gdbarch_data);
+  if (!data->unwinder_registered)
+    {
+      frame_unwind_prepend_unwinder (gdbarch, &jit_frame_unwind);
+      data->unwinder_registered = 1;
+    }
+}
+
+/* Register any already created translations.  */
 
 static void
 jit_inferior_init (struct gdbarch *gdbarch)
 {
-  struct minimal_symbol *reg_symbol;
-  struct minimal_symbol *desc_symbol;
-  CORE_ADDR reg_addr;
   struct jit_descriptor descriptor;
   struct jit_code_entry cur_entry;
+  struct jit_program_space_data *ps_data;
   CORE_ADDR cur_entry_addr;
-  struct cleanup *old_cleanups;
 
-  /* When we register code, GDB resets its breakpoints in case symbols have
-     changed.  That in turn calls this handler, which makes us look for new
-     code again.  To avoid being re-entered, we check this flag.  */
-  if (registering_code)
-    return;
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog, "jit_inferior_init\n");
 
-  /* Lookup the registration symbol.  If it is missing, then we assume we are
-     not attached to a JIT.  */
-  reg_symbol = lookup_minimal_symbol (jit_break_name, NULL, NULL);
-  if (reg_symbol == NULL)
-    return;
-  reg_addr = SYMBOL_VALUE_ADDRESS (reg_symbol);
-  if (reg_addr == 0)
-    return;
+  jit_prepend_unwinder (gdbarch);
 
-  /* Lookup the descriptor symbol and cache the addr.  If it is missing, we
-     assume we are not attached to a JIT and return early.  */
-  desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, NULL);
-  if (desc_symbol == NULL)
-    return;
-  jit_descriptor_addr = SYMBOL_VALUE_ADDRESS (desc_symbol);
-  if (jit_descriptor_addr == 0)
+  ps_data = get_jit_program_space_data ();
+  if (jit_breakpoint_re_set_internal (gdbarch, ps_data) != 0)
     return;
 
-  /* Read the descriptor so we can check the version number and load any already
-     JITed functions.  */
-  jit_read_descriptor (gdbarch, &descriptor);
+  /* Read the descriptor so we can check the version number and load
+     any already JITed functions.  */
+  if (!jit_read_descriptor (gdbarch, &descriptor, ps_data))
+    return;
 
   /* Check that the version number agrees with that we support.  */
   if (descriptor.version != 1)
-    error (_("Unsupported JIT protocol version in descriptor!"));
-
-  /* Put a breakpoint in the registration symbol.  */
-  create_jit_event_breakpoint (gdbarch, reg_addr);
+    {
+      printf_unfiltered (_("Unsupported JIT protocol version %ld "
+                          "in descriptor (expected 1)\n"),
+                        (long) descriptor.version);
+      return;
+    }
 
-  /* If we've attached to a running program, we need to check the descriptor to
-     register any functions that were already generated.  */
+  /* If we've attached to a running program, we need to check the descriptor
+     to register any functions that were already generated.  */
   for (cur_entry_addr = descriptor.first_entry;
        cur_entry_addr != 0;
        cur_entry_addr = cur_entry.next_entry)
@@ -373,7 +1361,7 @@ jit_inferior_init (struct gdbarch *gdbarch)
 void
 jit_inferior_created_hook (void)
 {
-  jit_inferior_init (target_gdbarch);
+  jit_inferior_init (target_gdbarch ());
 }
 
 /* Exported routine to call to re-set the jit breakpoints,
@@ -382,34 +1370,28 @@ jit_inferior_created_hook (void)
 void
 jit_breakpoint_re_set (void)
 {
-  jit_inferior_init (target_gdbarch);
+  jit_breakpoint_re_set_internal (target_gdbarch (),
+                                 get_jit_program_space_data ());
 }
 
-/* Wrapper to match the observer function pointer prototype.  */
+/* This function cleans up any code entries left over when the
+   inferior exits.  We get left over code when the inferior exits
+   without unregistering its code, for example when it crashes.  */
 
 static void
-jit_inferior_created_observer (struct target_ops *objfile, int from_tty)
-{
-  jit_inferior_init (target_gdbarch);
-}
-
-/* This function cleans up any code entries left over when the inferior exits.
-   We get left over code when the inferior exits without unregistering its code,
-   for example when it crashes.  */
-
-static void
-jit_inferior_exit_hook (int pid)
+jit_inferior_exit_hook (struct inferior *inf)
 {
   struct objfile *objf;
   struct objfile *temp;
 
-  /* We need to reset the descriptor addr so that next time we load up the
-     inferior we look for it again.  */
-  jit_descriptor_addr = 0;
-
   ALL_OBJFILES_SAFE (objf, temp)
-    if (objfile_data (objf, jit_objfile_data) != NULL)
-      jit_unregister_code (objf);
+    {
+      struct jit_objfile_data *objf_data = objfile_data (objf,
+                                                        jit_objfile_data);
+
+      if (objf_data != NULL && objf_data->addr != 0)
+       jit_unregister_code (objf);
+    }
 }
 
 void
@@ -421,10 +1403,12 @@ jit_event_handler (struct gdbarch *gdbarch)
   struct objfile *objf;
 
   /* Read the descriptor from remote memory.  */
-  jit_read_descriptor (gdbarch, &descriptor);
+  if (!jit_read_descriptor (gdbarch, &descriptor,
+                           get_jit_program_space_data ()))
+    return;
   entry_addr = descriptor.relevant_entry;
 
-  /* Do the corresponding action. */
+  /* Do the corresponding action.  */
   switch (descriptor.action_flag)
     {
     case JIT_NOACTION:
@@ -436,7 +1420,8 @@ jit_event_handler (struct gdbarch *gdbarch)
     case JIT_UNREGISTER:
       objf = jit_find_objf_with_entry_addr (entry_addr);
       if (objf == NULL)
-       printf_unfiltered (_("Unable to find JITed code entry at address: %s\n"),
+       printf_unfiltered (_("Unable to find JITed code "
+                            "entry at address: %s\n"),
                           paddress (gdbarch, entry_addr));
       else
         jit_unregister_code (objf);
@@ -448,6 +1433,39 @@ jit_event_handler (struct gdbarch *gdbarch)
     }
 }
 
+/* Called to free the data allocated to the jit_program_space_data slot.  */
+
+static void
+free_objfile_data (struct objfile *objfile, void *data)
+{
+  struct jit_objfile_data *objf_data = data;
+
+  if (objf_data->register_code != NULL)
+    {
+      struct jit_program_space_data *ps_data;
+
+      ps_data = program_space_data (objfile->pspace, jit_program_space_data);
+      if (ps_data != NULL && ps_data->objfile == objfile)
+       ps_data->objfile = NULL;
+    }
+
+  xfree (data);
+}
+
+/* Initialize the jit_gdbarch_data slot with an instance of struct
+   jit_gdbarch_data_type */
+
+static void *
+jit_gdbarch_data_init (struct obstack *obstack)
+{
+  struct jit_gdbarch_data_type *data =
+    XOBNEW (obstack, struct jit_gdbarch_data_type);
+
+  data->unwinder_registered = 0;
+
+  return data;
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 
 extern void _initialize_jit (void);
@@ -455,7 +1473,36 @@ extern void _initialize_jit (void);
 void
 _initialize_jit (void)
 {
-  observer_attach_inferior_created (jit_inferior_created_observer);
+  jit_reader_dir = relocate_gdb_directory (JIT_READER_DIR,
+                                           JIT_READER_DIR_RELOCATABLE);
+  add_setshow_zuinteger_cmd ("jit", class_maintenance, &jit_debug,
+                            _("Set JIT debugging."),
+                            _("Show JIT debugging."),
+                            _("When non-zero, JIT debugging is enabled."),
+                            NULL,
+                            show_jit_debug,
+                            &setdebuglist, &showdebuglist);
+
   observer_attach_inferior_exit (jit_inferior_exit_hook);
-  jit_objfile_data = register_objfile_data ();
+  observer_attach_breakpoint_deleted (jit_breakpoint_deleted);
+
+  jit_objfile_data =
+    register_objfile_data_with_cleanup (NULL, free_objfile_data);
+  jit_program_space_data =
+    register_program_space_data_with_cleanup (NULL,
+                                             jit_program_space_data_cleanup);
+  jit_gdbarch_data = gdbarch_data_register_pre_init (jit_gdbarch_data_init);
+  if (is_dl_available ())
+    {
+      add_com ("jit-reader-load", no_class, jit_reader_load_command, _("\
+Load FILE as debug info reader and unwinder for JIT compiled code.\n\
+Usage: jit-reader-load FILE\n\
+Try to load file FILE as a debug info reader (and unwinder) for\n\
+JIT compiled code.  The file is loaded from " JIT_READER_DIR ",\n\
+relocated relative to the GDB executable if required."));
+      add_com ("jit-reader-unload", no_class, jit_reader_unload_command, _("\
+Unload the currently loaded JIT debug info reader.\n\
+Usage: jit-reader-unload FILE\n\n\
+Do \"help jit-reader-load\" for info on loading debug info readers."));
+    }
 }