This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 4/7] Use the loaded reader.


Invoke the loaded JIT debug info reader to parse the registered symbol
files.
---
 gdb/ChangeLog |   12 ++
 gdb/jit.c     |  428 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 410 insertions(+), 30 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 884b51a..bd63356 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
 2011-08-09  Sanjoy Das  <sdas@igalia.com>
 
+	* jit.c (add_objfile_entry, jit_target_read_impl)
+	(jit_object_open_impl, jit_symtab_open_impl, compare_block)
+	(jit_block_open_impl, jit_block_open_impl)
+	(jit_symtab_line_mapping_impl, jit_symtab_close_impl)
+	(finalize_symtab, jit_object_close_impl)
+	(jit_reader_try_read_symtab, jit_bfd_try_read_symtab): New
+	functions.
+	(jit_register_code): Try using the loaded jit reader before
+	resorting to BFD.
+
+2011-08-09  Sanjoy Das  <sdas@igalia.com>
+
 	* jit.c (_initialize_jit): Add commands load-jit-reader and
 	unload-jit-reader.
 	(jit_reader_load): New function.
diff --git a/gdb/jit.c b/gdb/jit.c
index 3f83065..e81a386 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -21,8 +21,11 @@
 
 #include "jit.h"
 #include "jit-reader.h"
+#include "block.h"
 #include "breakpoint.h"
 #include "command.h"
+#include "dictionary.h"
+#include "frame-unwind.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "inferior.h"
@@ -236,9 +239,19 @@ struct jit_inferior_data
 {
   CORE_ADDR breakpoint_addr;  /* &__jit_debug_register_code()  */
   CORE_ADDR descriptor_addr;  /* &__jit_debug_descriptor  */
-  struct objfile *jit_objfile; /* All the JIT symbols will be added to this. */
 };
 
+/* Remember a mapping from entry_addr to objfile.  */
+static void
+add_objfile_entry (struct objfile *objfile, CORE_ADDR entry)
+{
+  CORE_ADDR *entry_addr_ptr;
+
+  entry_addr_ptr = xmalloc (sizeof (CORE_ADDR));
+  *entry_addr_ptr = entry;
+  set_objfile_data (objfile, jit_objfile_data, entry_addr_ptr);
+}
+
 /* Return jit_inferior_data for current inferior.  Allocate if not already
    present.  */
 
@@ -335,37 +348,369 @@ jit_read_code_entry (struct gdbarch *gdbarch,
       extract_unsigned_integer (&entry_buf[3 * ptr_size], 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;
+  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. */
+struct jit_dbg_reader_data
+{
+  CORE_ADDR entry_address;
+};
+
+/* 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;
+}
+
+static struct gdb_object *
+jit_object_open_impl (struct gdb_symbol_callbacks *cb)
+{
+  return XZALLOC (struct gdb_object);
+}
+
+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 = XZALLOC (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 corrensponding to old should be placed
+   before the block corresponding to new in the final blockvector. */
+static int
+compare_block (struct gdb_block *old, struct gdb_block *new)
+{
+  if (old == NULL)
+    return 1;
+  if (old->begin < new->begin)
+    return 1;
+  else if (old->begin == new->begin)
+    {
+      if (old->end > new->end)
+        return 1;
+      else
+        return 0;
+    }
+  else
+    return 0;
+}
+
+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 = XZALLOC (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;
+}
 
 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)
+    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;
+    }
+}
+
+static void
+jit_symtab_close_impl (struct gdb_symbol_callbacks *cb, struct gdb_symtab *stab)
+{
+}
+
+/* Transform STAB to a proper symtab, and add it it OBJFILE. */
+static void
+finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
 {
+  struct symtab *symtab;
+  struct gdb_block *gdb_block_iter, *gdb_block_iter_tmp;
+  struct block *block_iter;
+  int actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks, i, blockvector_size;
+  CORE_ADDR begin, end;
+
+  symtab = allocate_symtab (stab->file_name, objfile);
+  symtab->dirname = NULL; /* JIT compilers compile in memory */
+
+  /* Copy over the linetable entry if one was provided. */
+  if (stab->linetable)
+    {
+      int size = (stab->linetable->nitems - 1) *
+        sizeof (struct linetable_entry) + sizeof (struct linetable);
+      LINETABLE (symtab) = obstack_alloc (&objfile->objfile_obstack, size);
+      memcpy (LINETABLE (symtab), stab->linetable, size);
+    }
+  else
+    {
+      LINETABLE (symtab) = NULL;
+    }
+
+  blockvector_size = (sizeof (struct blockvector) +
+                      (actual_nblocks - 1) * sizeof (struct block *));
+  symtab->blockvector = obstack_alloc (&objfile->objfile_obstack,
+                                       blockvector_size);
+
+  /* (begin, end) will contain the PC range this entire blockvector spans. */
+  symtab->primary = 1;
+  BLOCKVECTOR_MAP (symtab->blockvector) = NULL;
+  begin = stab->blocks->begin;
+  end = stab->blocks->end;
+  BLOCKVECTOR_NBLOCKS (symtab->blockvector) = 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 = obstack_alloc (&objfile->objfile_obstack,
+                                                 sizeof (struct symbol));
+
+      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. */
+      memset (block_name, 0, sizeof (struct symbol));
+      SYMBOL_DOMAIN (block_name) = VAR_DOMAIN;
+      SYMBOL_CLASS (block_name) = LOC_BLOCK;
+      block_name->symtab = symtab;
+      SYMBOL_BLOCK_VALUE (block_name) = new_block;
+      block_name->ginfo.name = obstack_alloc (&objfile->objfile_obstack, 1 +
+                                              strlen (gdb_block_iter->name));
+      strcpy (block_name->ginfo.name, gdb_block_iter->name);
+      BLOCK_FUNCTION (new_block) = block_name;
+
+      BLOCKVECTOR_BLOCK (symtab->blockvector, 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 = 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 (symtab->blockvector, i) = new_block;
+    }
+
+  /* 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)
+        BLOCK_SUPERBLOCK (gdb_block_iter->real_block) =
+          gdb_block_iter->parent->real_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);
+}
+
+/* Convert 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 = NULL;
+  struct objfile *objfile = allocate_objfile (NULL, 0);
+  struct jit_dbg_reader_data *priv_data = cb->priv_data;
+
+  objfile->gdbarch = target_gdbarch;
+  objfile->msymbols = obstack_alloc (&objfile->objfile_obstack,
+                                     sizeof (struct minimal_symbol));
+  objfile->msymbols[0].ginfo.name = NULL;
+  objfile->msymbols[0].ginfo.value.address = 0;
+  objfile->name = xstrdup ("JIT");
+
+  for (i = obj->symtabs; i; i = j)
+    {
+      j = i->next;
+      finalize_symtab (i, objfile);
+    }
+  add_objfile_entry (objfile, priv_data->entry_address);
+  xfree (obj);
+}
+
+/* Try to read CODE_ENTRY using the loaded jit reader (if any). */
+static int
+jit_reader_try_read_symtab (struct jit_code_entry *code_entry)
+{
+  void *gdb_mem;
+  int status = 0;
+  struct jit_dbg_reader *i;
+  struct 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_address = code_entry->symfile_addr;
+
+  if (!loaded_jit_reader)
+    return 0;
+
+  gdb_mem = xmalloc (code_entry->symfile_size);
+  if (target_read_memory (code_entry->symfile_addr, gdb_mem,
+                          code_entry->symfile_size))
+    {
+      status = 0;
+      goto cleanup;
+    }
+
+  funcs = loaded_jit_reader->functions;
+  if (funcs->read (funcs, &callbacks, gdb_mem, code_entry->symfile_size)
+      == GDB_SUCCESS)
+    {
+      status = 1;
+      goto cleanup;
+    }
+
+ cleanup:
+  xfree (gdb_mem);
+  return status;
+}
+
+/* Try to read CODE_ENTRY using BFD. */
+static void
+jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
+                         struct gdbarch *gdbarch)
+{
+  struct cleanup *old_cleanups;
+  struct objfile *objfile;
   bfd *nbfd;
   struct section_addr_info *sai;
   struct bfd_section *sec;
-  struct objfile *objfile;
-  struct cleanup *old_cleanups, *my_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));
+  int i;
 
   nbfd = bfd_open_from_target_memory (code_entry->symfile_addr,
                                       code_entry->symfile_size, gnutarget);
   old_cleanups = make_cleanup_bfd_close (nbfd);
 
-  /* Check the format.  NOTE: This initializes important data that GDB uses!
-     We would segfault later without this line.  */
+  /* Check the format.  NOTE: This initializes important data that GDB
+     uses!  We would segfault later without this line.  */
   if (!bfd_check_format (nbfd, bfd_object))
     {
       printf_unfiltered (_("\
@@ -381,17 +726,17 @@ JITed symbol file is not an object file, ignoring it.\n"));
                "with target architecture %s."), bfd_get_arch_info
              (nbfd)->printable_name, b->printable_name);
 
-  /* Read the section address information out of the symbol file.  Since the
-     file is generated by the JIT at runtime, it should all of the absolute
-     addresses that we care about.  */
+  /* Read the section address information out of the symbol file.
+     Since the 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);
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
       {
-        /* We assume that these virtual addresses are absolute, and do not
-           treat them as offsets.  */
+        /* We assume that these virtual addresses are absolute, and do
+           not treat them as offsets.  */
         sai->other[i].addr = bfd_get_section_vma (nbfd, sec);
         sai->other[i].name = xstrdup (bfd_get_section_name (nbfd, sec));
         sai->other[i].sectindex = sec->index;
@@ -401,12 +746,34 @@ JITed symbol file is not an object file, ignoring it.\n"));
   /* This call takes ownership of sai.  */
   objfile = symbol_file_add_from_bfd (nbfd, 0, sai, OBJF_SHARED, NULL);
 
-  /* 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);
-
   discard_cleanups (old_cleanups);
+  add_objfile_entry (objfile, code_entry->symfile_addr);
+}
+
+/* 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.  */
+
+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 ();
+
+  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));
+
+  success = jit_reader_try_read_symtab (code_entry);
+
+  if (!success)
+    jit_bfd_try_read_symtab (code_entry, gdbarch);
 }
 
 /* This function unregisters JITed code and frees the corresponding
@@ -415,6 +782,7 @@ JITed symbol file is not an object file, ignoring it.\n"));
 static void
 jit_unregister_code (struct objfile *objfile)
 {
+  xfree (objfile_data (objfile, jit_objfile_data));
   free_objfile (objfile);
 }
 
-- 
1.7.5.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]