-Wpointer-sign: gdb_byte -> char.
[binutils-gdb.git] / gdb / jit.c
index b4294e841689180e835bcde644c66717ad277075..6fc8524f54fcc8ab905b2d297107a09969f45545 100644 (file)
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -49,7 +49,7 @@ static const char *const jit_break_name = "__jit_debug_register_code";
 
 static const char *const jit_descriptor_name = "__jit_debug_descriptor";
 
-static const struct inferior_data *jit_inferior_data = NULL;
+static const struct program_space_data *jit_program_space_data = NULL;
 
 static void jit_inferior_init (struct gdbarch *gdbarch);
 
@@ -90,7 +90,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
@@ -234,18 +236,33 @@ jit_reader_unload_command (char *args, int from_tty)
   loaded_jit_reader = NULL;
 }
 
-/* Per-inferior structure recording which objfile has the JIT
+/* Per-program space structure recording which objfile has the JIT
    symbols.  */
 
-struct jit_inferior_data
+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 inferior.  */
+/* 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
 {
@@ -255,7 +272,8 @@ struct jit_objfile_data
   /* Symbol for __jit_debug_descriptor.  */
   struct minimal_symbol *descriptor;
 
-  /* Address of struct jit_code_entry in this objfile.  */
+  /* 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;
 };
 
@@ -289,28 +307,27 @@ add_objfile_entry (struct objfile *objfile, CORE_ADDR entry)
   objf_data->addr = entry;
 }
 
-/* Return jit_inferior_data for current inferior.  Allocate if not already
-   present.  */
+/* Return jit_program_space_data for current program space.  Allocate
+   if not already present.  */
 
-static struct jit_inferior_data *
-get_jit_inferior_data (void)
+static struct jit_program_space_data *
+get_jit_program_space_data (void)
 {
-  struct inferior *inf;
-  struct jit_inferior_data *inf_data;
+  struct jit_program_space_data *ps_data;
 
-  inf = current_inferior ();
-  inf_data = inferior_data (inf, jit_inferior_data);
-  if (inf_data == NULL)
+  ps_data = program_space_data (current_program_space, jit_program_space_data);
+  if (ps_data == NULL)
     {
-      inf_data = XZALLOC (struct jit_inferior_data);
-      set_inferior_data (inf, jit_inferior_data, inf_data);
+      ps_data = XZALLOC (struct jit_program_space_data);
+      set_program_space_data (current_program_space, jit_program_space_data,
+                             ps_data);
     }
 
-  return inf_data;
+  return ps_data;
 }
 
 static void
-jit_inferior_data_cleanup (struct inferior *inf, void *arg)
+jit_program_space_data_cleanup (struct program_space *ps, void *arg)
 {
   xfree (arg);
 }
@@ -321,7 +338,7 @@ jit_inferior_data_cleanup (struct inferior *inf, void *arg)
 static int
 jit_read_descriptor (struct gdbarch *gdbarch,
                     struct jit_descriptor *descriptor,
-                    struct jit_inferior_data *inf_data)
+                    struct jit_program_space_data *ps_data)
 {
   int err;
   struct type *ptr_type;
@@ -331,9 +348,9 @@ jit_read_descriptor (struct gdbarch *gdbarch,
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct jit_objfile_data *objf_data;
 
-  if (inf_data->objfile == NULL)
+  if (ps_data->objfile == NULL)
     return 0;
-  objf_data = get_jit_objfile_data (inf_data->objfile);
+  objf_data = get_jit_objfile_data (ps_data->objfile);
   if (objf_data->descriptor == NULL)
     return 0;
 
@@ -662,8 +679,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
        i--, gdb_block_iter = gdb_block_iter->next)
     {
       struct block *new_block = allocate_block (&objfile->objfile_obstack);
-      struct symbol *block_name = obstack_alloc (&objfile->objfile_obstack,
-                                                 sizeof (struct symbol));
+      struct symbol *block_name = allocate_symbol (objfile);
       struct type *block_type = arch_type (get_objfile_arch (objfile),
                                           TYPE_CODE_VOID,
                                           1,
@@ -676,9 +692,8 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
       BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end;
 
       /* The name.  */
-      memset (block_name, 0, sizeof (struct symbol));
       SYMBOL_DOMAIN (block_name) = VAR_DOMAIN;
-      SYMBOL_CLASS (block_name) = LOC_BLOCK;
+      SYMBOL_ACLASS_INDEX (block_name) = LOC_BLOCK;
       SYMBOL_SYMTAB (block_name) = symtab;
       SYMBOL_TYPE (block_name) = lookup_function_type (block_type);
       SYMBOL_BLOCK_VALUE (block_name) = new_block;
@@ -908,6 +923,7 @@ 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);
@@ -926,9 +942,7 @@ static void
 jit_register_code (struct gdbarch *gdbarch,
                    CORE_ADDR entry_addr, struct jit_code_entry *code_entry)
 {
-  int i, success;
-  const struct bfd_arch_info *b;
-  struct jit_inferior_data *inf_data = get_jit_inferior_data ();
+  int success;
 
   if (jit_debug)
     fprintf_unfiltered (gdb_stdlog,
@@ -970,46 +984,83 @@ jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
   return NULL;
 }
 
+/* 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_inferior_data *inf_data)
+                               struct jit_program_space_data *ps_data)
 {
-  struct minimal_symbol *reg_symbol, *desc_symbol;
-  struct objfile *objf;
+  struct bound_minimal_symbol reg_symbol;
+  struct minimal_symbol *desc_symbol;
   struct jit_objfile_data *objf_data;
+  CORE_ADDR addr;
 
-  if (inf_data->objfile != NULL)
-    return 0;
-
-  /* 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, &objf);
-  if (reg_symbol == NULL || SYMBOL_VALUE_ADDRESS (reg_symbol) == 0)
-    return 1;
-
-  desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, objf);
-  if (desc_symbol == NULL || SYMBOL_VALUE_ADDRESS (desc_symbol) == 0)
-    return 1;
-
-  objf_data = get_jit_objfile_data (objf);
-  objf_data->register_code = reg_symbol;
-  objf_data->descriptor = desc_symbol;
-
-  inf_data->objfile = objf;
+  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
+         || SYMBOL_VALUE_ADDRESS (reg_symbol.minsym) == 0)
+       return 1;
+
+      desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL,
+                                          reg_symbol.objfile);
+      if (desc_symbol == NULL || SYMBOL_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;
+
+      ps_data->objfile = reg_symbol.objfile;
+    }
+  else
+    objf_data = get_jit_objfile_data (ps_data->objfile);
 
-  jit_inferior_init (gdbarch);
+  addr = SYMBOL_VALUE_ADDRESS (objf_data->register_code);
 
   if (jit_debug)
     fprintf_unfiltered (gdb_stdlog,
                        "jit_breakpoint_re_set_internal, "
                        "breakpoint_addr = %s\n",
-                       paddress (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol)));
+                       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.  */
-  create_jit_event_breakpoint (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol));
+  ps_data->cached_code_address = addr;
+  ps_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr);
 
   return 0;
 }
@@ -1115,13 +1166,10 @@ static int
 jit_frame_sniffer (const struct frame_unwind *self,
                    struct frame_info *this_frame, void **cache)
 {
-  struct jit_inferior_data *inf_data;
   struct jit_unwind_private *priv_data;
   struct gdb_unwind_callbacks callbacks;
   struct gdb_reader_funcs *funcs;
 
-  inf_data = get_jit_inferior_data ();
-
   callbacks.reg_get = jit_unwind_reg_get_impl;
   callbacks.reg_set = jit_unwind_reg_set_impl;
   callbacks.target_read = jit_target_read_impl;
@@ -1256,7 +1304,7 @@ jit_inferior_init (struct gdbarch *gdbarch)
 {
   struct jit_descriptor descriptor;
   struct jit_code_entry cur_entry;
-  struct jit_inferior_data *inf_data;
+  struct jit_program_space_data *ps_data;
   CORE_ADDR cur_entry_addr;
 
   if (jit_debug)
@@ -1264,13 +1312,13 @@ jit_inferior_init (struct gdbarch *gdbarch)
 
   jit_prepend_unwinder (gdbarch);
 
-  inf_data = get_jit_inferior_data ();
-  if (jit_breakpoint_re_set_internal (gdbarch, inf_data) != 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.  */
-  if (!jit_read_descriptor (gdbarch, &descriptor, inf_data))
+  if (!jit_read_descriptor (gdbarch, &descriptor, ps_data))
     return;
 
   /* Check that the version number agrees with that we support.  */
@@ -1314,7 +1362,7 @@ void
 jit_breakpoint_re_set (void)
 {
   jit_breakpoint_re_set_internal (target_gdbarch (),
-                                 get_jit_inferior_data ());
+                                 get_jit_program_space_data ());
 }
 
 /* This function cleans up any code entries left over when the
@@ -1346,7 +1394,8 @@ jit_event_handler (struct gdbarch *gdbarch)
   struct objfile *objf;
 
   /* Read the descriptor from remote memory.  */
-  if (!jit_read_descriptor (gdbarch, &descriptor, get_jit_inferior_data ()))
+  if (!jit_read_descriptor (gdbarch, &descriptor,
+                           get_jit_program_space_data ()))
     return;
   entry_addr = descriptor.relevant_entry;
 
@@ -1375,7 +1424,7 @@ jit_event_handler (struct gdbarch *gdbarch)
     }
 }
 
-/* Called to free the data allocated to the jit_inferior_data slot.  */
+/* Called to free the data allocated to the jit_program_space_data slot.  */
 
 static void
 free_objfile_data (struct objfile *objfile, void *data)
@@ -1384,10 +1433,11 @@ free_objfile_data (struct objfile *objfile, void *data)
 
   if (objf_data->register_code != NULL)
     {
-      struct jit_inferior_data *inf_data = get_jit_inferior_data ();
+      struct jit_program_space_data *ps_data;
 
-      if (inf_data->objfile == objfile)
-       inf_data->objfile = NULL;
+      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);
@@ -1424,10 +1474,13 @@ _initialize_jit (void)
                             &setdebuglist, &showdebuglist);
 
   observer_attach_inferior_exit (jit_inferior_exit_hook);
+  observer_attach_breakpoint_deleted (jit_breakpoint_deleted);
+
   jit_objfile_data =
     register_objfile_data_with_cleanup (NULL, free_objfile_data);
-  jit_inferior_data =
-    register_inferior_data_with_cleanup (NULL, jit_inferior_data_cleanup);
+  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 ())
     {