* hppa-hpux-tdep.c (hppa64_hpux_search_dummy_call_sequence): Use
[deliverable/binutils-gdb.git] / gdb / jit.c
index 6010a36dee55d6dc88a17b450df246c17ea017e9..c1274237259e8aff9220339fc58db760898c3eab 100644 (file)
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -31,6 +31,7 @@
 #include "inferior.h"
 #include "observer.h"
 #include "objfiles.h"
+#include "regcache.h"
 #include "symfile.h"
 #include "symtab.h"
 #include "target.h"
@@ -50,6 +51,12 @@ static const struct inferior_data *jit_inferior_data = NULL;
 
 static void jit_inferior_init (struct gdbarch *gdbarch);
 
+/* An unwinder is registered for every gdbarch.  This key is used to
+   remember if the unwinder has been registered for a particular
+   gdbarch.  */
+
+static struct gdbarch_data *jit_gdbarch_data;
+
 /* Non-zero if we want to see trace of jit level stuff.  */
 
 static int jit_debug = 0;
@@ -232,7 +239,8 @@ struct jit_inferior_data
   CORE_ADDR descriptor_addr;  /* &__jit_debug_descriptor  */
 };
 
-/* Remember a mapping from entry_addr to objfile.  */
+/* 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)
@@ -686,9 +694,7 @@ jit_object_close_impl (struct gdb_symbol_callbacks *cb,
   objfile = allocate_objfile (NULL, 0);
   objfile->gdbarch = target_gdbarch;
 
-  objfile->msymbols = obstack_alloc (&objfile->objfile_obstack,
-                                     sizeof (struct minimal_symbol));
-  memset (objfile->msymbols, 0, sizeof (struct minimal_symbol));
+  terminate_minimal_symbol_table (objfile);
 
   xfree (objfile->name);
   objfile->name = xstrdup ("<< JIT compiled code >>");
@@ -703,10 +709,13 @@ jit_object_close_impl (struct gdb_symbol_callbacks *cb,
   xfree (obj);
 }
 
-/* Try to read CODE_ENTRY using the loaded jit reader (if any).  */
+/* 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)
+jit_reader_try_read_symtab (struct jit_code_entry *code_entry,
+                            CORE_ADDR entry_addr)
 {
   void *gdb_mem;
   int status;
@@ -728,7 +737,7 @@ jit_reader_try_read_symtab (struct jit_code_entry *code_entry)
       &priv_data
     };
 
-  priv_data = code_entry->symfile_addr;
+  priv_data = entry_addr;
 
   if (!loaded_jit_reader)
     return 0;
@@ -758,10 +767,12 @@ jit_reader_try_read_symtab (struct jit_code_entry *code_entry)
   return status;
 }
 
-/* Try to read CODE_ENTRY using BFD.  */
+/* 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;
@@ -825,7 +836,7 @@ JITed symbol file is not an object file, ignoring it.\n"));
   objfile = symbol_file_add_from_bfd (nbfd, 0, sai, OBJF_SHARED, NULL);
 
   do_cleanups (old_cleanups);
-  add_objfile_entry (objfile, code_entry->symfile_addr);
+  add_objfile_entry (objfile, entry_addr);
 }
 
 /* This function registers code associated with a JIT code entry.  It uses the
@@ -848,10 +859,10 @@ jit_register_code (struct gdbarch *gdbarch,
                         paddress (gdbarch, code_entry->symfile_addr),
                         pulongest (code_entry->symfile_size));
 
-  success = jit_reader_try_read_symtab (code_entry);
+  success = jit_reader_try_read_symtab (code_entry, entry_addr);
 
   if (!success)
-    jit_bfd_try_read_symtab (code_entry, gdbarch);
+    jit_bfd_try_read_symtab (code_entry, entry_addr, gdbarch);
 }
 
 /* This function unregisters JITed code and frees the corresponding
@@ -920,6 +931,242 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
   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 = 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_inferior_data *inf_data;
+  struct jit_unwind_private *priv_data;
+  struct jit_dbg_reader *iter;
+  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;
+
+  if (loaded_jit_reader == NULL)
+    return 0;
+
+  funcs = loaded_jit_reader->functions;
+
+  gdb_assert (!*cache);
+
+  *cache = XZALLOC (struct jit_unwind_private);
+  priv_data = *cache;
+  priv_data->registers =
+    XCALLOC (gdbarch_num_regs (get_frame_arch (this_frame)),
+             struct gdb_reg_value *);
+  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 private;
+  struct gdb_frame_id frame_id;
+  struct gdb_reader_funcs *funcs;
+  struct gdb_unwind_callbacks callbacks;
+
+  private.registers = NULL;
+  private.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 = &private;
+
+  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
@@ -933,6 +1180,8 @@ jit_inferior_init (struct gdbarch *gdbarch)
   if (jit_debug)
     fprintf_unfiltered (gdb_stdlog, "jit_inferior_init\n");
 
+  jit_prepend_unwinder (gdbarch);
+
   inf_data = get_jit_inferior_data ();
   if (jit_breakpoint_re_set_internal (gdbarch, inf_data) != 0)
     return;
@@ -1094,6 +1343,19 @@ free_objfile_data (struct objfile *objfile, void *data)
   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;
+
+  data = obstack_alloc (obstack, sizeof (struct jit_gdbarch_data_type));
+  data->unwinder_registered = 0;
+  return data;
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 
 extern void _initialize_jit (void);
@@ -1118,6 +1380,7 @@ _initialize_jit (void)
     register_objfile_data_with_cleanup (NULL, free_objfile_data);
   jit_inferior_data =
     register_inferior_data_with_cleanup (jit_inferior_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, _("\
This page took 0.02644 seconds and 4 git commands to generate.