public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/4] jit-reader.h: describe interface implemented by the JIT readers.
@ 2011-07-13 20:24 Sanjoy Das
  2011-07-13 20:24 ` [PATCH 4/4] Activate JIT code unwinder for i386 Sanjoy Das
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Sanjoy Das @ 2011-07-13 20:24 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Generating ELF files in memory is usually too much work for JIT
compilers, since they usually don't have the related routines (as
opposed to a regular static compiler). One way to simplify this is to
have the JIT vendor themselves provide a shared object which is loaded
and used to parse the debug information. This patch exposes a
simplified interface for the debug info parser.

The interface is _simplified_ in the sense that it does not expose all
of GDB's functionality. The idea is that if the user wishes to use GDB
for full-on debugging of generated code, it will probably be simpler
to generate the full DWARF info.

The interface does not expose more than the minimum amount of GDB
internals; both to prevent versioning problems, and to keep writing
the debug-info reader simple.

This patch adds a header file (`jit-reader.h') which can be included
and implemented in a shared object to build a working JIT
debug-reader.

gdb/ChangeLog:

	* jit-reader.h: Add (new) JIT reader interface.
	* jit.c: Include jit-reader.h in source file
	* Makefile.in: Add jit-reader.h to HFILES_NO_SRCDIR.
---
 gdb/ChangeLog    |    6 ++
 gdb/Makefile.in  |    2 +-
 gdb/jit-reader.h |  189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/jit.c        |    4 +
 4 files changed, 200 insertions(+), 1 deletions(-)
 create mode 100644 gdb/jit-reader.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8ed7eaf..e067f04 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
+
+	* jit-reader.h: Add (new) JIT reader interface.
+	* jit.c: Include jit-reader.h in source file
+	* Makefile.in: Add jit-reader.h to HFILES_NO_SRCDIR.
+
 2011-07-12  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	Code cleanup making also optimized out values lazy.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 494f24f..ca2cbcb 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -816,7 +816,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \
 python/python-internal.h python/python.h ravenscar-thread.h record.h \
 solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \
 gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \
-gnulib/stddef.in.h inline-frame.h
+gnulib/stddef.in.h inline-frame.h jit-reader.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
diff --git a/gdb/jit-reader.h b/gdb/jit-reader.h
new file mode 100644
index 0000000..15980bd
--- /dev/null
+++ b/gdb/jit-reader.h
@@ -0,0 +1,189 @@
+/* Interface for JIT debug-info readers.
+
+   Copyright (C) 2011
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_JIT_READER_H
+#define GDB_JIT_READER_H
+
+/* Versioning: for the SO to be correctly recognized and loaded, put the macro
+   GDB_JIT_DECLARE_API_VERSION in a source file. */
+
+#define GDB_JIT_INTERFACE_VERSION  1
+#define GDB_JIT_DECLARE_API_VERSION             \
+  extern int __gdbjit_so_api_version (void)     \
+  {                                             \
+    return GDB_JIT_INTERFACE_VERSION;           \
+  }
+
+#define GDB_JIT_SUCCESS          1
+#define GDB_JIT_FAIL             0
+#define GDBJIT_MAX_REGISTER_SIZE 64 /* Mirrors the internal GDB definition. */
+
+struct gdbjit_symtab;
+struct gdbjit_block;
+struct gdbjit_symbol;
+struct gdbjit_symtab_callbacks;
+
+#ifndef __GDB__INTERNAL /* Only defined when being compiled in GDB. */
+typedef long long CORE_ADDR;
+#endif
+
+struct gdbjit_line_mapping
+{
+  int line;
+  CORE_ADDR pc;
+};
+
+typedef struct gdbjit_symtab *(gdbjit_symtab_open)
+  (struct gdbjit_symtab_callbacks *callbacks,
+   const char *file_name);
+
+typedef struct gdbjit_block *(gdbjit_new_block)
+  (struct gdbjit_symtab_callbacks *callbacks, struct gdbjit_symtab *symtab,
+   struct gdbjit_block *parent, CORE_ADDR begin_addr, CORE_ADDR end_addr,
+   const char *name);
+
+typedef void (gdbjit_symtab_close) (struct gdbjit_symtab_callbacks *callbacks,
+                                    struct gdbjit_symtab *symtab);
+
+typedef void (gdbjit_symtab_add_line_mapping)
+(struct gdbjit_symtab_callbacks * callbacks, struct gdbjit_symtab *symtab,
+ int nlines, struct gdbjit_line_mapping *lines);
+
+typedef int (gdbjit_target_read) (CORE_ADDR target_mem, void *gdb_buf, int len);
+
+struct gdbjit_symtab_callbacks {
+  /* Create a new symbol table. A symbol table consists of a forest of block
+     hierachies. Blocks are added by a call to new_block. This needs to be
+     paired with a call to symtab_close.
+
+     An optional FILE_NAME can be passed, which will be associated with the
+     symbol table as the source file from which this code was compiled.
+
+     Returns a new struct gdbjit_symtab which can be further passed to
+     new_block and symtab_close. */
+  gdbjit_symtab_open *symtab_open;
+
+  /* Creates a new block. A block is an optionally named contiguous block of
+     code in memory. Creating a new block automatically adds it to the symbol
+     table in which it is created.
+
+     SYMTAB is the symbol table this block is added to. Each block may have an
+     optionally non-NULL PARENT. BEGIN_ADDR and END_ADDR are the first and last
+     addresses spanned by this piece of compiled code. This block may have an
+     optional NAME, in case it corresponds to a function.
+
+     Returns a gdbjit_block instance, which, at this point, is useless. */
+  gdbjit_new_block *new_block;
+
+  /* Adds PC <-> line number mapping for the symbol table SYMTAB. Pass an array
+     of NLINES gdbjit_line_mapping s in LINES. */
+  gdbjit_symtab_add_line_mapping *add_line_mapping;
+
+  /* Reads LEN bytes of memory from the target's address space, beginning from
+     TARGET_MEM into the buffer GDB_BUF points to. */
+  gdbjit_target_read *target_read;
+
+  /* Closes the symbol table SYMTAB, and add it to the internal GDB list. */
+  gdbjit_symtab_close *symtab_close;
+
+  /* For internal use. */
+  void *private;
+};
+
+/* Denotes a register value. */
+struct gdbjit_reg_value
+{
+  /* Set to non-zero if this register has a valid value. Otherwise 0. */
+  int defined;
+  /* The actual value of the register (this is considered valid only if defined
+     is non-zero). */
+  unsigned char value[GDBJIT_MAX_REGISTER_SIZE];
+};
+
+/* Unique frame identifier. This should remain constant throughout the lifetime
+   of the frame concerned. */
+struct gdbjit_frame_id
+{
+  CORE_ADDR code_address;
+  CORE_ADDR stack_address;
+};
+
+struct gdbjit_unwind_callbacks;
+
+typedef struct gdbjit_reg_value (gdbjit_unwind_reg_get)
+  (struct gdbjit_unwind_callbacks *callback, int regnum);
+
+typedef void (gdbjit_unwind_reg_set) (struct gdbjit_unwind_callbacks *callback,
+                                      int regnum, struct gdbjit_reg_value val);
+
+struct gdbjit_unwind_callbacks
+{
+  /* Gets the current value for the register REGNUM (DWARF numbering). */
+  gdbjit_unwind_reg_get *reg_get;
+
+  /* Sets the previous value of the REGNUM register (i.e. its value in the
+     previous frame) to VAL. */
+  gdbjit_unwind_reg_set *reg_set;
+
+  /* Function to read memory off the inferior process being debugged, as
+     documented in gdbjit_symtab_callbacks. */
+  gdbjit_target_read *target_read;
+
+  /* For internal use. */
+  void *private;
+};
+
+/* Called once for each new inferior program. It should also initialize the
+   private pointer (to which a pointer is passed here) if the it needs one.
+
+   return: GDB_SUCCESS on success, or GDB_JIT_FAIL on error,
+   in which this plugin will be discarded (gdbjit_destroy_reader will not be
+   called in such a case). */
+extern int gdbjit_init_reader (void **private);
+
+/* Called to have the reader try to read a block of memory. PRIVATE is the
+   private pointer, (possibly) initialized by gdbjit_init_reader.
+
+   The function is expected to use CALLBACKS (documented above) to build a
+   symbol table for this particular block of memory (pointed to by MEMORY,
+   already copied from the target address space to GDB's address space).
+   MEMORY_SZ is the size of the block of memory.
+
+   Should return GDB_JIT_SUCESS on success and GDB_JIT_FAIL on error. */
+extern int gdbjit_read_debug_info (void *private,
+                                   struct gdbjit_symtab_callbacks *callbacks,
+                                   CORE_ADDR memory, long memory_sz);
+
+/* Called to unwind one frame. PRIVATE is the private pointer. Expected to use
+   CALLBACKS to unwind the registers to the older frame.
+
+   Should return GDB_JIT_SUCESS for success, GDB_JIT_FAIL for fail. */
+extern int gdbjit_unwind_frame (void *private,
+                                struct gdbjit_unwind_callbacks *callbacks);
+
+/* Called to get a unique identifier for the current stack frame (as reported by
+   callbacks). */
+struct gdbjit_frame_id gdbjit_get_frame_id (void *private, struct
+                                            gdbjit_unwind_callbacks *callbacks);
+
+/* Called once the inferior process exits. */
+extern void gdbjit_destroy_reader (void *private);
+
+#endif
diff --git a/gdb/jit.c b/gdb/jit.c
index eb1bcc7..6c07a57 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -19,7 +19,11 @@
 
 #include "defs.h"
 
+/* To stop jit-reader.h from re-defining CORE_ADDR */
+#define __GDB__INTERNAL
+
 #include "jit.h"
+#include "jit-reader.h"
 #include "breakpoint.h"
 #include "command.h"
 #include "gdbcmd.h"
-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 4/4] Activate JIT code unwinder for i386.
  2011-07-13 20:24 [PATCH 1/4] jit-reader.h: describe interface implemented by the JIT readers Sanjoy Das
@ 2011-07-13 20:24 ` Sanjoy Das
  2011-07-14 17:55   ` Tom Tromey
  2011-07-13 20:52 ` [PATCH 2/4] Add symbol-handling callbacks to the jit-reader interface Sanjoy Das
  2011-07-14  1:39 ` [PATCH 3/4] Add an unwinder for JIT compiled code Sanjoy Das
  2 siblings, 1 reply; 11+ messages in thread
From: Sanjoy Das @ 2011-07-13 20:24 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Registers the (pseudo) unwinder for JIT code for i386. This can probably be extended to other architectures after some testing and review.

gdb/ChangeLog:
	* i386-tdep.c: Activate JIT unwinder for i386.
---
 gdb/ChangeLog   |    4 ++++
 gdb/i386-tdep.c |    4 ++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8485b05..51c0727 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
 2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
 
+	* i386-tdep.c: Activate JIT unwinder for i386.
+
+2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
+
 	* jit.c: Add JIT frame unwinding code.
 	* jit-reader.h: Added jit_prepend_unwinder.
 
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 366d0fa..66626ab 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -30,6 +30,7 @@
 #include "frame-base.h"
 #include "frame-unwind.h"
 #include "inferior.h"
+#include "jit.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "gdbtypes.h"
@@ -7330,6 +7331,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      CFI info will be used if it is available.  */
   dwarf2_append_unwinders (gdbarch);
 
+  /* JIT reader pseudo-unwinder. */
+  jit_prepend_unwinder (gdbarch);
+
   frame_base_set_default (gdbarch, &i386_frame_base);
 
   /* Pseudo registers may be changed by amd64_init_abi.  */
-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 2/4] Add symbol-handling callbacks to the jit-reader interface.
  2011-07-13 20:24 [PATCH 1/4] jit-reader.h: describe interface implemented by the JIT readers Sanjoy Das
  2011-07-13 20:24 ` [PATCH 4/4] Activate JIT code unwinder for i386 Sanjoy Das
@ 2011-07-13 20:52 ` Sanjoy Das
  2011-07-14  1:39 ` [PATCH 3/4] Add an unwinder for JIT compiled code Sanjoy Das
  2 siblings, 0 replies; 11+ messages in thread
From: Sanjoy Das @ 2011-07-13 20:52 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Implements the callbacks in `struct gdbjit_symtab_callbacks'. This
will allow the JIT debug info reader to be able to parse the debug
info and actually push the symbols into GDB.

gdb/ChangeLog:

	* jit.c: Add symbol handling callbacks for the JIT reader
interface.
---
 gdb/ChangeLog |    4 +
 gdb/jit.c     |  518 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 471 insertions(+), 51 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e067f04..ac207d1 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
 2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
 
+	* jit.c: Add symbol handling callbacks for the JIT reader interface.
+
+2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
+
 	* jit-reader.h: Add (new) JIT reader interface.
 	* jit.c: Include jit-reader.h in source file
 	* Makefile.in: Add jit-reader.h to HFILES_NO_SRCDIR.
diff --git a/gdb/jit.c b/gdb/jit.c
index 6c07a57..2899469 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -24,8 +24,10 @@
 
 #include "jit.h"
 #include "jit-reader.h"
+#include "block.h"
 #include "breakpoint.h"
 #include "command.h"
+#include "dictionary.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "inferior.h"
@@ -34,8 +36,11 @@
 #include "symfile.h"
 #include "symtab.h"
 #include "target.h"
+#include "gdb_dirent.h"
 #include "gdb_stat.h"
 
+#include <dlfcn.h>
+
 static const struct objfile_data *jit_objfile_data;
 
 static const char *const jit_break_name = "__jit_debug_register_code";
@@ -50,6 +55,115 @@ static void jit_inferior_init (struct gdbarch *gdbarch);
 
 static int jit_debug = 0;
 
+/* The environment variable we poke at to get the file name of the shared object
+   to load. */
+
+static const char *jit_dbg_reader_so_name_env = "JIT_DEBUG_READER";
+
+/* Symbols (and the corresponding types) to be loaded from the shared object
+   supposed to do the debug-info parsing. */
+typedef int (jit_init_reader_fn) (void **);
+static const char *jit_init_reader_sym = "gdbjit_init_reader";
+
+typedef int (jit_read_debug_info_fn) (void *, struct gdbjit_symtab_callbacks *,
+                                      void *mem, long sz);
+static const char *jit_read_debug_info_sym = "gdbjit_read_debug_info";
+
+typedef int (jit_unwind_frame_fn) (void *, struct gdbjit_unwind_callbacks *);
+static const char *jit_unwind_frame_sym = "gdbjit_unwind_frame";
+
+typedef void (jit_destroy_reader_fn) (void *);
+static const char *jit_destroy_reader_sym = "gdbjit_destroy_reader";
+
+typedef struct gdbjit_frame_id (jit_get_frame_id_fn) (void *, struct
+                                                     gdbjit_unwind_callbacks *);
+static const char *jit_get_frame_id_sym = "gdbjit_get_frame_id";
+
+static const char *jit_so_api_version_sym = "__gdbjit_so_api_version";
+
+struct jit_dbg_reader
+{
+  jit_init_reader_fn *init;
+  jit_read_debug_info_fn *read;
+  jit_unwind_frame_fn *unwind;
+  jit_get_frame_id_fn *get_frame_id;
+  jit_destroy_reader_fn *destroy;
+
+  void *handle, *private_data;
+};
+
+static struct jit_dbg_reader *
+jit_dbg_reader_load (void)
+{
+  /* Check if a reader has been provided. */
+  const char *file_name = getenv (jit_dbg_reader_so_name_env);
+  void *handle = NULL;
+  int (*jit_reader_so_api_version) (void) = NULL;
+  struct jit_dbg_reader *reader = NULL;
+  
+  if (file_name == NULL)
+    return NULL;
+
+  handle = dlopen (file_name, RTLD_NOW);
+  if (!handle)
+    goto cleanup;
+
+  reader = XZALLOC (struct jit_dbg_reader);
+  reader->init = dlsym (handle, jit_init_reader_sym);
+  reader->handle = handle;
+
+  if (!reader->init)
+    goto cleanup;
+
+  reader->read = dlsym (handle, jit_read_debug_info_sym);
+  if (!reader->read)
+    goto cleanup;
+
+  reader->unwind = dlsym (handle, jit_unwind_frame_sym);
+  if (!reader->unwind)
+    goto cleanup;
+
+  reader->get_frame_id = dlsym (handle, jit_get_frame_id_sym);
+  if (!reader->get_frame_id)
+    goto cleanup;
+
+  reader->destroy = dlsym (handle, jit_destroy_reader_sym);
+  if (!reader->destroy)
+    goto cleanup;
+
+  jit_reader_so_api_version = dlsym (handle, jit_so_api_version_sym);
+  if (!jit_reader_so_api_version ||
+      jit_reader_so_api_version () != GDB_JIT_INTERFACE_VERSION)
+    {
+      goto cleanup;
+    }
+
+  if (reader->init (&reader->private_data) != GDB_JIT_SUCCESS)
+    goto cleanup;
+
+  return reader;
+
+ cleanup:
+  xfree (reader);
+  if (handle)
+    {
+      dlclose (handle);
+      fprintf (stderr, "Could not load reader object %s\n", file_name);
+    }
+  else /* also report why the shared object could not be loaded */
+    fprintf (stderr, "Could not load reader object %s (%s)\n", file_name,
+             dlerror());
+  return NULL;
+}
+
+static void
+jit_dbg_reader_destroy (struct jit_dbg_reader *reader)
+{
+  if (reader)
+    reader->destroy (reader->private_data);
+  xfree (reader);
+}
+
 static void
 show_jit_debug (struct ui_file *file, int from_tty,
 		struct cmd_list_element *c, const char *value)
@@ -140,6 +254,9 @@ struct jit_inferior_data
 {
   CORE_ADDR breakpoint_addr;  /* &__jit_debug_register_code()  */
   CORE_ADDR descriptor_addr;  /* &__jit_debug_descriptor  */
+  struct jit_dbg_reader *reader; /* If a debug info reader was found. */
+  struct objfile *jit_objfile;   /* The object file where all the JIT symbols
+                                    will be added. */
 };
 
 /* Return jit_inferior_data for current inferior.  Allocate if not already
@@ -238,6 +355,282 @@ jit_read_code_entry (struct gdbarch *gdbarch,
       extract_unsigned_integer (&entry_buf[3 * ptr_size], 8, byte_order);
 }
 
+struct gdbjit_block
+{
+  struct gdbjit_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;
+};
+
+struct gdbjit_symtab
+{
+  struct gdbjit_block *blocks;
+  struct linetable *linetable;
+  int nblocks;
+
+  const char *file_name;
+};
+
+struct jit_dbg_reader_data
+{
+  struct objfile **objf;
+};
+
+static int
+jit_target_read_impl (CORE_ADDR target_mem, void *gdb_buf, int len)
+{
+  return target_read_memory (target_mem, gdb_buf, len);
+}
+
+static struct gdbjit_symtab *
+jit_symtab_open_impl (struct gdbjit_symtab_callbacks *cb, const char *file_name)
+{
+  struct gdbjit_symtab *ret = XZALLOC (struct gdbjit_symtab);
+  ret->file_name = xstrdup (file_name);
+  return ret;
+}
+
+/* Returns true if the block corrensponding to old should be placed before the
+   block corrensponding to new in the final blockvector. */
+static int
+compare_block (struct gdbjit_block *old, struct gdbjit_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 gdbjit_block *
+jit_new_block_impl (struct gdbjit_symtab_callbacks *cb,
+                    struct gdbjit_symtab *symtab,
+                    struct gdbjit_block *parent,
+                    CORE_ADDR begin, CORE_ADDR end, const char *name)
+{
+  struct gdbjit_block *block = XZALLOC (struct gdbjit_block);
+
+  (void) cb;
+
+  block->next = symtab->blocks;
+  block->begin = begin;
+  block->end = 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 gdbjit_block *i = symtab->blocks;
+
+      for (;; i = i->next)
+        {
+          /* Guranteed 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_symtab_add_line_mapping_impl (struct gdbjit_symtab_callbacks *cb,
+                                  struct gdbjit_symtab *stab,
+                                  int nlines,
+                                  struct gdbjit_line_mapping *map)
+{
+  int i;
+  /* Must copy */
+  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 = map[i].pc;
+      stab->linetable->item [i].line = map[i].line;
+    }
+}
+
+static void
+jit_symtab_close_impl (struct gdbjit_symtab_callbacks *cb,
+                       struct gdbjit_symtab *stab)
+{
+  struct jit_dbg_reader_data *dat = cb->private;
+  struct symtab *symtab;
+  struct gdbjit_block *blck_iter, *blck_iter_tmp;
+  struct block *block_iter;
+  struct objfile *objfile;
+  int actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks, i;
+  CORE_ADDR begin, end;
+
+  if (*dat->objf == NULL)
+    {
+       objfile = allocate_objfile (NULL, 0);
+      *dat->objf = objfile;
+      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");
+    }
+  else
+    objfile = *dat->objf;
+  
+  symtab = allocate_symtab (stab->file_name, objfile);
+  symtab->dirname = NULL; /* JIT compilers compile in memory */
+
+  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;
+  }
+
+  symtab->blockvector = obstack_alloc (&objfile->objfile_obstack,
+                                       (sizeof (struct blockvector)
+                                        + (actual_nblocks - 1) *
+                                        sizeof (struct block *)));
+
+  /* (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;
+
+  for (i = (actual_nblocks - 1), blck_iter = stab->blocks;
+       i >= FIRST_LOCAL_BLOCK; i--)
+    {
+      struct block *bl = allocate_block (&objfile->objfile_obstack);
+      struct symbol *block_name = obstack_alloc (&objfile->objfile_obstack,
+                                                 sizeof (struct symbol));
+
+      BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack, NULL);
+      BLOCK_START (bl) = blck_iter->begin;
+      BLOCK_END (bl) = blck_iter->end;
+      BLOCK_FUNCTION (bl) = block_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) = bl;
+
+      block_name->ginfo.name = obstack_alloc (&objfile->objfile_obstack,
+			                                        1 + strlen (blck_iter->name));
+      strcpy (block_name->ginfo.name, blck_iter->name);
+      BLOCK_FUNCTION (bl) = block_name;
+ 
+      BLOCKVECTOR_BLOCK (symtab->blockvector, i) = bl;
+      if (begin < (long) blck_iter->begin)
+        begin = (long) blck_iter->begin;
+      if (end > (long) blck_iter->end)
+        end = (long) blck_iter->end;
+    }
+
+  blck_iter = blck_iter->next;
+
+  /* Now add the special blocks. */
+  block_iter = NULL;
+  for (i = 0; i < FIRST_LOCAL_BLOCK; i++)
+    {
+      struct block *bl = allocate_block (&objfile->objfile_obstack);
+      BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack, NULL);
+      BLOCK_SUPERBLOCK (bl) = block_iter;
+      block_iter = bl;
+
+      BLOCK_START (bl) = begin;
+      BLOCK_END (bl) = end;
+
+      BLOCKVECTOR_BLOCK (symtab->blockvector, i) = bl;
+    }
+
+  /* Fill up the superblock fields. */
+  for (blck_iter = stab->blocks; blck_iter; blck_iter = blck_iter->next)
+    {
+      if (blck_iter->parent != NULL)
+        BLOCK_SUPERBLOCK (blck_iter->real_block) =
+          blck_iter->parent->real_block;
+    }
+
+  /* Free memory. */
+  blck_iter = stab->blocks;
+  for (blck_iter = stab->blocks, blck_iter_tmp = blck_iter->next;
+       blck_iter; blck_iter = blck_iter_tmp)
+    {
+      xfree (blck_iter);
+    }
+}
+
+static int
+jit_try_read_symtab (struct jit_inferior_data *inf_data,
+                     CORE_ADDR target_mem, long sz)
+{
+  void *gdb_mem;
+  int status = 0;
+  struct jit_dbg_reader *i;
+  struct jit_dbg_reader_data priv_data;
+  struct gdbjit_symtab_callbacks callbacks =
+    {
+      jit_symtab_open_impl,
+      jit_new_block_impl,
+      jit_symtab_add_line_mapping_impl,
+      jit_target_read_impl,
+      jit_symtab_close_impl,
+
+      &priv_data
+    };
+
+  if (!inf_data->reader)
+    return 0;
+
+  priv_data.objf = &inf_data->jit_objfile;
+
+  gdb_mem = xmalloc (sz);
+  if (target_read_memory (target_mem, gdb_mem, sz))
+    {
+      status = 0;
+      goto cleanup;
+    }
+
+  status = inf_data->reader->read (inf_data->reader->private_data, &callbacks,
+                                   gdb_mem, sz) == GDB_JIT_SUCCESS;
+
+ cleanup:
+  xfree (gdb_mem);
+  return status;
+}
+
 /* 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
@@ -247,14 +640,9 @@ static void
 jit_register_code (struct gdbarch *gdbarch,
 		   CORE_ADDR entry_addr, struct jit_code_entry *code_entry)
 {
-  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;
+  int i, success;
+  struct jit_inferior_data *inf_data = get_jit_inferior_data ();
 
   if (jit_debug)
     fprintf_unfiltered (gdb_stdlog,
@@ -263,53 +651,68 @@ jit_register_code (struct gdbarch *gdbarch,
 			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);
-
-  /* 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))
+  if (jit_try_read_symtab (inf_data, code_entry->symfile_addr,
+                           code_entry->symfile_size))
     {
-      printf_unfiltered (_("\
+      objfile = inf_data->jit_objfile;
+    }
+  else
+    {
+      struct cleanup *old_cleanups;
+      bfd *nbfd;
+      struct section_addr_info *sai;
+      struct bfd_section *sec;
+      const struct bfd_arch_info *b;
+      CORE_ADDR *entry_addr_ptr;
+      
+      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.  */
+      if (!bfd_check_format (nbfd, bfd_object))
+        {
+          printf_unfiltered (_("\
 JITed symbol file is not an object file, ignoring it.\n"));
-      do_cleanups (old_cleanups);
-      return;
+          do_cleanups (old_cleanups);
+          return;
+        }
+
+      /* Check bfd arch.  */
+      b = gdbarch_bfd_arch_info (gdbarch);
+      if (b->compatible (b, bfd_get_arch_info (nbfd)) != b)
+        warning (_("JITed object file architecture %s is not compatible "
+                   "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.  */
+      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.  */
+            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;
+            ++i;
+          }
+
+      /* 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);
     }
-
-  /* Check bfd arch.  */
-  b = gdbarch_bfd_arch_info (gdbarch);
-  if (b->compatible (b, bfd_get_arch_info (nbfd)) != b)
-    warning (_("JITed object file architecture %s is not compatible "
-               "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.  */
-  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.  */
-        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;
-        ++i;
-      }
-
-  /* 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);
 }
 
 /* This function unregisters JITed code and frees the corresponding
@@ -395,6 +798,8 @@ jit_inferior_init (struct gdbarch *gdbarch)
   if (jit_breakpoint_re_set_internal (gdbarch, inf_data) != 0)
     return;
 
+  inf_data->reader = jit_dbg_reader_load ();
+
   if (inf_data->descriptor_addr == 0)
     {
       struct minimal_symbol *desc_symbol;
@@ -474,6 +879,11 @@ jit_reset_inferior_data_and_breakpoints (void)
   /* Remove any existing JIT breakpoint(s).  */
   remove_jit_event_breakpoints ();
 
+  /* Destroy JIT reader objects. */
+  jit_dbg_reader_destroy (inf_data->reader);
+  if (inf_data->jit_objfile)
+    free_objfile (inf_data->jit_objfile);
+
   jit_inferior_init (target_gdbarch);
 }
 
@@ -494,6 +904,12 @@ jit_inferior_exit_hook (struct inferior *inf)
 {
   struct objfile *objf;
   struct objfile *temp;
+  struct jit_inferior_data *inf_data;
+
+ inf_data = inferior_data (inf, jit_inferior_data);
+ jit_dbg_reader_destroy (inf_data->reader);
+ if (inf_data->jit_objfile)
+   free_objfile (inf_data->jit_objfile);
 
   ALL_OBJFILES_SAFE (objf, temp)
     if (objfile_data (objf, jit_objfile_data) != NULL)
-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 3/4] Add an unwinder for JIT compiled code.
  2011-07-13 20:24 [PATCH 1/4] jit-reader.h: describe interface implemented by the JIT readers Sanjoy Das
  2011-07-13 20:24 ` [PATCH 4/4] Activate JIT code unwinder for i386 Sanjoy Das
  2011-07-13 20:52 ` [PATCH 2/4] Add symbol-handling callbacks to the jit-reader interface Sanjoy Das
@ 2011-07-14  1:39 ` Sanjoy Das
  2011-07-14 21:05   ` Tom Tromey
  2 siblings, 1 reply; 11+ messages in thread
From: Sanjoy Das @ 2011-07-14  1:39 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Add a (pseudo) unwinder which proxies back everything to the unwinder registered by the JIT debug info reader.

gdb/ChangeLog:

	* jit.c: Add JIT frame unwinding code.
	* jit-reader.h: Added jit_prepend_unwinder.
---
 gdb/ChangeLog |    5 ++
 gdb/jit.c     |  150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/jit.h     |    2 +
 3 files changed, 157 insertions(+), 0 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ac207d1..8485b05 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
 
+	* jit.c: Add JIT frame unwinding code.
+	* jit-reader.h: Added jit_prepend_unwinder.
+
+2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
+
 	* jit.c: Add symbol handling callbacks for the JIT reader interface.
 
 2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
diff --git a/gdb/jit.c b/gdb/jit.c
index 2899469..03a3d0b 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -28,6 +28,7 @@
 #include "breakpoint.h"
 #include "command.h"
 #include "dictionary.h"
+#include "frame-unwind.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "inferior.h"
@@ -781,6 +782,149 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
   return 0;
 }
 
+struct jit_unwind_private {
+  struct gdbjit_reg_value *registers;
+  struct frame_info *this_frame;
+};
+
+static void
+jit_unwind_reg_set_impl (struct gdbjit_unwind_callbacks *cb, int regnum,
+                         struct gdbjit_reg_value value)
+{
+  struct jit_unwind_private *priv = cb->private;
+  int gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, regnum);
+  priv->registers[gdb_reg] = value;
+}
+
+static struct gdbjit_reg_value
+jit_unwind_reg_get_impl (struct gdbjit_unwind_callbacks *cb, int regnum)
+{
+  struct jit_unwind_private *priv = cb->private;
+  struct gdbjit_reg_value val;
+  int gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, regnum);
+  val.defined = frame_register_read (priv->this_frame, gdb_reg, val.value);
+  return val;
+}
+
+static int
+jit_frame_sniffer (const struct frame_unwind *self,
+                   struct frame_info *this_frame, void **cache)
+{
+  /* First look up the PC, and check if the code address has been registered or
+     not. */
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  struct jit_inferior_data *inf_data = get_jit_inferior_data ();
+  struct jit_unwind_private *priv_data;
+  struct jit_dbg_reader *iter;
+  struct gdbjit_unwind_callbacks callbacks =
+    {
+      jit_unwind_reg_get_impl,
+      jit_unwind_reg_set_impl,
+      jit_target_read_impl
+    };
+
+  if (inf_data->reader == NULL)
+    return 0;
+
+  /* All the unwinding happens here, and the unwound registers are written to
+     this block of memory, which we then sneakily read back in
+     jit_frame_prev_register. */
+  if (!*cache)
+    {
+      *cache = XZALLOC (struct jit_unwind_private);
+      priv_data = *cache;
+      priv_data->registers = XCALLOC (gdbarch_num_regs (target_gdbarch),
+                                      struct gdbjit_reg_value);
+      priv_data->this_frame = this_frame;
+    }
+  else
+    {
+      priv_data = *cache;
+      priv_data->this_frame = this_frame;
+    }
+
+  callbacks.private = priv_data;
+  
+  /* Try to coax  the provided unwinder to unwind the stack, and hope it
+     succeeds. */
+  if (inf_data->reader->unwind (inf_data->reader->private_data, &callbacks)
+      == GDB_JIT_SUCCESS)
+    return 1;
+  xfree (priv_data->registers);
+  xfree (priv_data);
+  *cache = NULL;
+
+  return 0;
+}
+
+static enum unwind_stop_reason
+jit_frame_unwind_stop_reason (struct frame_info *this_frame, void **cache)
+{
+  return UNWIND_NO_REASON;
+}
+
+static void
+jit_frame_this_id (struct frame_info *this_frame, void **cache,
+                   struct frame_id *this_id)
+{
+  struct jit_inferior_data *inf_data = get_jit_inferior_data ();
+  struct jit_unwind_private private =
+    {
+      NULL,
+      this_frame
+    };
+  struct gdbjit_frame_id frame_id;
+  struct gdbjit_unwind_callbacks callbacks =
+    {
+      jit_unwind_reg_get_impl,
+      NULL,
+      jit_target_read_impl,
+
+      &private
+    };
+
+  frame_id = inf_data->reader->get_frame_id (inf_data->reader->private_data,
+                                             &callbacks);
+  *this_id = frame_id_build (frame_id.stack_address, frame_id.code_address);
+}
+
+static struct value *
+jit_frame_prev_register (struct frame_info *this_frame, void **cache, int reg)
+{
+  struct jit_unwind_private *priv = *cache;
+  struct gdbjit_reg_value value;
+
+  if (priv == NULL)
+    return frame_unwind_got_optimized (this_frame, reg);
+
+  value = priv->registers[reg];
+  if (value.defined)
+    return frame_unwind_got_bytes (this_frame, reg, value.value);
+  else
+    return frame_unwind_got_optimized (this_frame, reg);
+}
+
+static void
+jit_dealloc_cache (struct frame_info *this_frame, void *cache)
+{
+  (void) this_frame;
+
+  xfree (cache);
+}
+
+/* Simply relays everything back to the unwinder registered by the jit debug
+   info reader.*/
+static const struct frame_unwind jit_frame_unwind =
+{
+  NORMAL_FRAME,
+  jit_frame_unwind_stop_reason,
+  jit_frame_this_id,
+  jit_frame_prev_register,
+  NULL,
+  jit_frame_sniffer,
+  jit_dealloc_cache
+};
+
 /* Register any already created translations.  */
 
 static void
@@ -960,6 +1104,12 @@ jit_event_handler (struct gdbarch *gdbarch)
     }
 }
 
+void
+jit_prepend_unwinder (struct gdbarch *gdbarch)
+{
+  frame_unwind_prepend_unwinder (gdbarch, &jit_frame_unwind);
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 
 extern void _initialize_jit (void);
diff --git a/gdb/jit.h b/gdb/jit.h
index 73a1414..9dd8f5a 100644
--- a/gdb/jit.h
+++ b/gdb/jit.h
@@ -80,4 +80,6 @@ extern void jit_breakpoint_re_set (void);
 
 extern void jit_event_handler (struct gdbarch *gdbarch);
 
+extern void jit_prepend_unwinder (struct gdbarch *gdbarch);
+
 #endif /* JIT_H */
-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] Activate JIT code unwinder for i386.
  2011-07-13 20:24 ` [PATCH 4/4] Activate JIT code unwinder for i386 Sanjoy Das
@ 2011-07-14 17:55   ` Tom Tromey
  2011-07-14 17:58     ` Sanjoy Das
  0 siblings, 1 reply; 11+ messages in thread
From: Tom Tromey @ 2011-07-14 17:55 UTC (permalink / raw)
  To: Sanjoy Das; +Cc: gdb-patches

>>>>> "Sanjoy" == Sanjoy Das <sanjoy@playingwithpointers.com> writes:

Sanjoy> Registers the (pseudo) unwinder for JIT code for i386. This can
Sanjoy> probably be extended to other architectures after some testing
Sanjoy> and review.

This doesn't seem to be different from the earlier version of this
patch; which Mark K. said should probably be changed to put the JIT
unwinders after the DWARF ones.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] Activate JIT code unwinder for i386.
  2011-07-14 17:55   ` Tom Tromey
@ 2011-07-14 17:58     ` Sanjoy Das
  0 siblings, 0 replies; 11+ messages in thread
From: Sanjoy Das @ 2011-07-14 17:58 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi!

Thanks for the feedback; I'll get started on fixing the problems.

And no, I have not done anything regarding copyright assignment.

-- 
Sanjoy Das
http://playingwithpointers.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/4] Add an unwinder for JIT compiled code.
  2011-07-14  1:39 ` [PATCH 3/4] Add an unwinder for JIT compiled code Sanjoy Das
@ 2011-07-14 21:05   ` Tom Tromey
  0 siblings, 0 replies; 11+ messages in thread
From: Tom Tromey @ 2011-07-14 21:05 UTC (permalink / raw)
  To: Sanjoy Das; +Cc: gdb-patches

>>>>> "Sanjoy" == Sanjoy Das <sanjoy@playingwithpointers.com> writes:

Sanjoy> 	* jit-reader.h: Added jit_prepend_unwinder.

This mentions the wrong file.

Otherwise this one seems pretty good, though again, I would appreciate
further reviews by others.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] Activate JIT code unwinder for i386.
  2011-07-06  2:38     ` Sanjoy Das
@ 2011-07-06  2:46       ` Mark Kettenis
  0 siblings, 0 replies; 11+ messages in thread
From: Mark Kettenis @ 2011-07-06  2:46 UTC (permalink / raw)
  To: sanjoy; +Cc: gdb-patches

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 453 bytes --]

> From: Sanjoy Das <sanjoy@playingwithpointers.com>
> Date: Wed, 6 Jul 2011 08:01:34 +0530
> 
> > What's your motivation for putting the JIT unwinder at that spot in
> > the list of unwinders?  I'd put it behind the DWARF CFI unwinders
> > since those are the ones that most people will hit.
> >
> 
> I'll fix that before the next iteration.

Well, if you have a good reason to prepend it, that's ok.  But if not,
then yes, I think it's the way to go.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] Activate JIT code unwinder for i386.
  2011-07-05 15:34   ` Mark Kettenis
@ 2011-07-06  2:38     ` Sanjoy Das
  2011-07-06  2:46       ` Mark Kettenis
  0 siblings, 1 reply; 11+ messages in thread
From: Sanjoy Das @ 2011-07-06  2:38 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

>
> What's your motivation for putting the JIT unwinder at that spot in
> the list of unwinders?  I'd put it behind the DWARF CFI unwinders
> since those are the ones that most people will hit.
>

I'll fix that before the next iteration.

-- 
Regards,

Sanjoy Das.

http://playingwithpointers.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] Activate JIT code unwinder for i386.
  2011-07-05  6:27 ` [PATCH 4/4] Activate JIT code unwinder for i386 Sanjoy Das
@ 2011-07-05 15:34   ` Mark Kettenis
  2011-07-06  2:38     ` Sanjoy Das
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Kettenis @ 2011-07-05 15:34 UTC (permalink / raw)
  To: sanjoy; +Cc: gdb-patches, sanjoy

> From: Sanjoy Das <sanjoy@playingwithpointers.com>
> Date: Tue,  5 Jul 2011 12:01:29 +0530
> 
> Registers the (pseudo) unwinder for JIT code for i386. This can
> probably be expanded to other architectures after some testing and
> review.

What's your motivation for putting the JIT unwinder at that spot in
the list of unwinders?  I'd put it behind the DWARF CFI unwinders
since those are the ones that most people will hit.

> gdb/ChangeLog:
> 	* i386-tdep.c: Activate JIT unwinder for i386.
> ---
>  gdb/ChangeLog   |    4 ++++
>  gdb/i386-tdep.c |    4 ++++
>  2 files changed, 8 insertions(+), 0 deletions(-)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 306a0a5..1f0bd19 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,9 @@
>  2011-07-04  Sanjoy Das  <sanjoy@playingwithpointers.com>
>  
> +	* i386-tdep.c: Activate JIT unwinder for i386.
> +
> +2011-07-04  Sanjoy Das  <sanjoy@playingwithpointers.com>
> +
>  	* jit.c: Add JIT frame unwinding code.
>  	* jit-reader.h: Added jit_prepend_unwinder.
>  
> diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
> index 366d0fa..66626ab 100644
> --- a/gdb/i386-tdep.c
> +++ b/gdb/i386-tdep.c
> @@ -30,6 +30,7 @@
>  #include "frame-base.h"
>  #include "frame-unwind.h"
>  #include "inferior.h"
> +#include "jit.h"
>  #include "gdbcmd.h"
>  #include "gdbcore.h"
>  #include "gdbtypes.h"
> @@ -7330,6 +7331,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>       CFI info will be used if it is available.  */
>    dwarf2_append_unwinders (gdbarch);
>  
> +  /* JIT reader pseudo-unwinder. */
> +  jit_prepend_unwinder (gdbarch);
> +
>    frame_base_set_default (gdbarch, &i386_frame_base);
>  
>    /* Pseudo registers may be changed by amd64_init_abi.  */
> -- 
> 1.7.5.3
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 4/4] Activate JIT code unwinder for i386.
  2011-07-05  6:27 [PATCH 1/4] jit-reader.h: describe interface implemented by the JIT readers Sanjoy Das
@ 2011-07-05  6:27 ` Sanjoy Das
  2011-07-05 15:34   ` Mark Kettenis
  0 siblings, 1 reply; 11+ messages in thread
From: Sanjoy Das @ 2011-07-05  6:27 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Registers the (pseudo) unwinder for JIT code for i386. This can probably be expanded to other architectures after some testing and review.

gdb/ChangeLog:
	* i386-tdep.c: Activate JIT unwinder for i386.
---
 gdb/ChangeLog   |    4 ++++
 gdb/i386-tdep.c |    4 ++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 306a0a5..1f0bd19 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
 2011-07-04  Sanjoy Das  <sanjoy@playingwithpointers.com>
 
+	* i386-tdep.c: Activate JIT unwinder for i386.
+
+2011-07-04  Sanjoy Das  <sanjoy@playingwithpointers.com>
+
 	* jit.c: Add JIT frame unwinding code.
 	* jit-reader.h: Added jit_prepend_unwinder.
 
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 366d0fa..66626ab 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -30,6 +30,7 @@
 #include "frame-base.h"
 #include "frame-unwind.h"
 #include "inferior.h"
+#include "jit.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
 #include "gdbtypes.h"
@@ -7330,6 +7331,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      CFI info will be used if it is available.  */
   dwarf2_append_unwinders (gdbarch);
 
+  /* JIT reader pseudo-unwinder. */
+  jit_prepend_unwinder (gdbarch);
+
   frame_base_set_default (gdbarch, &i386_frame_base);
 
   /* Pseudo registers may be changed by amd64_init_abi.  */
-- 
1.7.5.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-07-14 17:55 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-13 20:24 [PATCH 1/4] jit-reader.h: describe interface implemented by the JIT readers Sanjoy Das
2011-07-13 20:24 ` [PATCH 4/4] Activate JIT code unwinder for i386 Sanjoy Das
2011-07-14 17:55   ` Tom Tromey
2011-07-14 17:58     ` Sanjoy Das
2011-07-13 20:52 ` [PATCH 2/4] Add symbol-handling callbacks to the jit-reader interface Sanjoy Das
2011-07-14  1:39 ` [PATCH 3/4] Add an unwinder for JIT compiled code Sanjoy Das
2011-07-14 21:05   ` Tom Tromey
  -- strict thread matches above, loose matches on Subject: below --
2011-07-05  6:27 [PATCH 1/4] jit-reader.h: describe interface implemented by the JIT readers Sanjoy Das
2011-07-05  6:27 ` [PATCH 4/4] Activate JIT code unwinder for i386 Sanjoy Das
2011-07-05 15:34   ` Mark Kettenis
2011-07-06  2:38     ` Sanjoy Das
2011-07-06  2:46       ` Mark Kettenis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).