Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 2/7] Relocatable directory for loading JIT readers.
  2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
@ 2011-08-24 18:57 ` Sanjoy Das
  2011-08-24 18:57 ` [PATCH 6/7] New JIT unwinder Sanjoy Das
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Add a new directory `jit_reader_dir' to jit.c, which is relocated
during initialization.  The value of the directory can be set by using
--with-jit-reader-dir on configure and defaults to `${libdir}/gdb'.
---
 gdb/config.in    |    6 ++++++
 gdb/configure    |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/configure.ac |    4 ++++
 gdb/jit.c        |    4 ++++
 4 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/gdb/config.in b/gdb/config.in
index c1d7c68..b1aef82 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -982,3 +982,9 @@
 
 /* Define as `fork' if `vfork' does not work. */
 #undef vfork
+
+/* The directory from which JIT readers should be loaded. */
+#undef JIT_READER_DIR
+
+/* Define if JIT_READER_DIR should be relocated when GDB is moved. */
+#undef JIT_READER_DIR_RELOCATABLE
diff --git a/gdb/configure b/gdb/configure
index 31469f2..c6dfbf7 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -666,6 +666,7 @@ python_prog_path
 LTLIBEXPAT
 LIBEXPAT
 HAVE_LIBEXPAT
+JIT_READER_DIR
 TARGET_PTR
 READLINE_TEXI_INCFLAG
 READLINE_CFLAGS
@@ -964,6 +965,7 @@ with_zlib
 with_libiconv_prefix
 with_iconv_bin
 with_system_readline
+with_jit_reader_dir
 with_expat
 with_gnu_ld
 enable_rpath
@@ -1664,6 +1666,8 @@ Optional Packages:
                           search for libiconv in DIR/include and DIR/lib
   --with-iconv-bin=PATH   specify where to find the iconv program
   --with-system-readline  use installed readline library
+  --with-jit-reader-dir=PATH
+                          directory to load the JIT readers from
   --with-expat            include expat support (auto/yes/no)
   --with-gnu-ld           assume the C compiler uses GNU ld default=no
   --with-libexpat-prefix[=DIR]  search for libexpat in DIR/include and DIR/lib
@@ -9931,6 +9935,53 @@ ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
 
 
 
+
+# Check whether --with-jit-reader-dir was given.
+if test "${with_jit_reader_dir+set}" = set; then :
+  withval=$with_jit_reader_dir;
+    JIT_READER_DIR=$withval
+else
+  JIT_READER_DIR=${libdir}/gdb
+fi
+
+
+  test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+  test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+  ac_define_dir=`eval echo $JIT_READER_DIR`
+  ac_define_dir=`eval echo $ac_define_dir`
+
+cat >>confdefs.h <<_ACEOF
+#define JIT_READER_DIR "$ac_define_dir"
+_ACEOF
+
+
+
+
+  if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then
+     if test "x$prefix" = xNONE; then
+     	test_prefix=/usr/local
+     else
+	test_prefix=$prefix
+     fi
+  else
+     test_prefix=$exec_prefix
+  fi
+  value=0
+  case ${ac_define_dir} in
+     "${test_prefix}"|"${test_prefix}/"*|\
+	'${exec_prefix}'|'${exec_prefix}/'*)
+     value=1
+     ;;
+  esac
+
+cat >>confdefs.h <<_ACEOF
+#define JIT_READER_DIR_RELOCATABLE $value
+_ACEOF
+
+
+
+
+
 # Check whether --with-expat was given.
 if test "${with_expat+set}" = set; then :
   withval=$with_expat;
diff --git a/gdb/configure.ac b/gdb/configure.ac
index abeb251..ee73e9b 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -595,6 +595,10 @@ fi
 AC_SUBST(TARGET_PTR)
 AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
 
+GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
+                [directory to load the JIT readers from],
+                [${libdir}/gdb])
+
 AC_ARG_WITH(expat,
   AS_HELP_STRING([--with-expat], [include expat support (auto/yes/no)]),
   [], [with_expat=auto])
diff --git a/gdb/jit.c b/gdb/jit.c
index e3bb81a..cab27a9 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -33,6 +33,8 @@
 #include "target.h"
 #include "gdb_stat.h"
 
+static const char *jit_reader_dir = NULL;
+
 static const struct objfile_data *jit_objfile_data;
 
 static const char *const jit_break_name = "__jit_debug_register_code";
@@ -548,6 +550,8 @@ extern void _initialize_jit (void);
 void
 _initialize_jit (void)
 {
+  jit_reader_dir = relocate_gdb_directory (JIT_READER_DIR,
+                                           JIT_READER_DIR_RELOCATABLE);
   add_setshow_zinteger_cmd ("jit", class_maintenance, &jit_debug,
 			    _("Set JIT debugging."),
 			    _("Show JIT debugging."),
-- 
1.7.5.4


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

* [PATCH 6/7] New JIT unwinder.
  2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
  2011-08-24 18:57 ` [PATCH 2/7] Relocatable directory for loading JIT readers Sanjoy Das
@ 2011-08-24 18:57 ` Sanjoy Das
  2011-08-24 19:04   ` Jan Kratochvil
  2011-08-24 18:57 ` [PATCH 7/7] Documentation Sanjoy Das
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Introduce a "proxy unwinder", whcih will pass down all calls to the
functions the JIT reader provides.
---
 gdb/jit.c |  265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 265 insertions(+), 0 deletions(-)

diff --git a/gdb/jit.c b/gdb/jit.c
index b4f1830..ce52d44 100644
--- 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"
@@ -49,6 +50,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;
@@ -893,6 +900,248 @@ 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;
+
+  gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, dwarf_regnum);
+  if (gdb_reg == -1)
+    {
+      if (jit_debug)
+        fprintf_unfiltered (gdb_stdlog,
+                            _("Could not recognize DWARF regnum %d"),
+                            dwarf_regnum);
+      return;
+    }
+
+  priv = cb->priv_data;
+  gdb_assert (priv->registers);
+  priv->registers[gdb_reg] = value;
+}
+
+/* Passed in the `free' field of a gdb_reg_value. */
+
+static void
+free_reg_value_impl (struct gdb_reg_value *reg_value)
+{
+  xfree (reg_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;
+
+  priv = cb->priv_data;
+  gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, regnum);
+  size = register_size (target_gdbarch, 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 = free_reg_value_impl;
+  return value;
+}
+
+/* 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"));
+
+  xfree (priv_data->registers);
+  xfree (priv_data);
+  *cache = NULL;
+
+  return 0;
+}
+
+/* Also for the pseudo unwinder. */
+
+static enum unwind_stop_reason
+jit_frame_unwind_stop_reason (struct frame_info *this_frame, void **cache)
+{
+  return default_frame_unwind_stop_reason (this_frame, cache);
+}
+
+/* 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);
+}
+
+/* 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;
+  int i;
+
+  gdb_assert (priv_data->registers);
+
+  for (i = 0; i < gdbarch_num_regs (target_gdbarch); 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);
+}
+
+/* Relay 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
+};
+
+
+/* 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
@@ -906,6 +1155,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;
@@ -1066,6 +1317,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);
@@ -1090,6 +1354,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);
   add_com ("jit-reader-load", no_class, jit_reader_load_command, _("\
 Load FILE as debug info reader and unwinder for JIT compiled code.\n\
 Try to load file FILE as a debug info reader (and unwinder) for\n\
-- 
1.7.5.4


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

* [PATCH 7/7] Documentation.
  2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
  2011-08-24 18:57 ` [PATCH 2/7] Relocatable directory for loading JIT readers Sanjoy Das
  2011-08-24 18:57 ` [PATCH 6/7] New JIT unwinder Sanjoy Das
@ 2011-08-24 18:57 ` Sanjoy Das
  2011-08-24 20:14   ` Eli Zaretskii
  2011-08-24 18:57 ` [PATCH 5/7] Use the loaded reader Sanjoy Das
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Add some basic documentation to gdb.texinfo about the new JIT reader
functionality. Most of the actual documentation is still in
jit-reader.h.
---
 gdb/doc/gdb.texinfo |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 117 insertions(+), 0 deletions(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6e7bf52..429fc87 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -30950,6 +30950,7 @@ out about additional code.
 * Declarations::                Relevant C struct declarations
 * Registering Code::            Steps to register code
 * Unregistering Code::          Steps to unregister code
+* Custom Debug Info::           Emit debug information in a custom format
 @end menu
 
 @node Declarations
@@ -31046,6 +31047,122 @@ Set @code{action_flag} to @code{JIT_UNREGISTER} and call
 If the JIT frees or recompiles code without unregistering it, then @value{GDBN}
 and the JIT will leak the memory used for the associated symbol files.
 
+@node Custom Debug Info
+@section Custom Debug Info
+@cindex custom JIT debug info
+@cindex JIT debug info reader
+
+Generating debug information in platform-native file formats (like ELF
+or COFF) may be an overkill for JIT compilers; especially if all the
+debug info is used for is displaying a meaningful backtrace.  The
+issue can be resolved by having the JIT writers decide on a debug info
+format and also provide a reader that parses the debug info generated
+by the JIT compiler.  This section gives a brief overview on writing
+such a parser.  More specific details can be found in the source file
+@file{gdb/jit-reader.in}, which is also installed as a header at
+@file{@var{includedir}/gdb/jit-reader.h} for easy inclusion.
+
+The reader is implemented as a shared object.  Two new @value{GDBN}
+commands, @code{load-jit-reader} and @code{unload-jit-reader} are
+provided, to be used to load and unload the readers from a
+preconfigured directory.  Once loaded, the shared object is used the
+parse the debug information emitted by the JIT compiler.
+
+@menu
+* Using JIT Debug Info Readers::       How to use supplied readers correctly
+* Writing JIT Debug Info Readers::     Creating a debug-info reader
+@end menu
+
+@node Using JIT Debug Info Readers
+@subsection Using JIT Debug Info Readers
+@kindex load-jit-reader
+@kindex unload-jit-reader
+
+Readers can be loaded and unloaded using the @code{load-jit-reader}
+and @code{unload-jit-reader} commands.
+
+@table @code
+@item load-jit-reader @var{reader-name}
+
+Load the JIT reader named @var{reader-name}.  On a UNIX system, this
+will usually result load @file{@var{libdir}/gdb/@var{reader-name}},
+where @var{libdir} is the system library directory, usually
+@file{/usr/local/lib}.  Only one reader can be active at a time;
+trying to load a second reader when one is already loaded will result
+in @value{GDBN} reporting an error.  A new JIT reader can be loaded by
+first unloading the current one using @code{unload-jit-reader} and
+then invoking @code{load-jit-reader}.
+
+@item unload-jit-reader
+
+Unload the currently loaded JIT reader.
+
+@end table
+
+@node Writing JIT Debug Info Readers
+@subsection Writing JIT Debug Info Readers
+
+As mentioned, a reader is essentially a shared object conforming to a
+certain ABI.  This ABI is described in @file{jit-reader.h}.
+
+@file{jit-reader.h} defines the structures, macros and functions
+required to write a reader.  It is installed (along with
+@value{GDBN}), in @file{@var{includedir}/gdb} where @var{includedir} is
+the system include directory.
+
+Readers need to be released under a GPL compatible license.  A reader
+can be declared as released under such a license by placing the macro
+@code{GDB_DECLARE_GPL_COMPATIBLE_READER} in a source file.
+
+The entry point for readers is the symbol @code{gdb_init_reader},
+which is expected to be a function with the prototype
+
+@findex gdb_init_reader
+@smallexample
+extern struct gdb_reader_funcs *gdb_init_reader (void);
+@end smallexample
+
+@cindex @code{struct gdb_reader_funcs}
+
+@code{struct gdb_reader_funcs} contains a set of pointers to callback
+functions.  These functions are executed to read the debug info
+generated by the JIT compiler (@code{read}), to unwind stack frames
+(@code{unwind}) and to create canonical frame IDs
+(@code{get_Frame_id}).  It also has a callback that is called when the
+reader is being unloaded (@code{destroy}).  The struct looks like this
+
+@smallexample
+struct gdb_reader_funcs
+@{
+  /* Must be set to GDB_READER_INTERFACE_VERSION */
+
+  int reader_version;
+
+  /* For use by the reader. */
+
+  void *priv_data;
+
+  gdb_read_debug_info *read;
+  gdb_unwind_frame *unwind;
+  gdb_get_frame_id *get_frame_id;
+  gdb_destroy_reader *destroy;
+@};
+@end smallexample
+
+@cindex @code{struct gdb_symbol_callbacks}
+@cindex @code{struct gdb_unwind_callbacks}
+
+The callbacks are provided with another set of callbacks by
+@value{GDBN} to do their job.  For @code{read}, these callbacks are
+passed in a @code{struct gdb_symbol_callbacks} and for @code{unwind}
+and @code{get_frame_id}, in a @code{struct gdb_unwind_callbacks}.
+@code{struct gdb_symbol_callbacks} has callbacks to create new object
+files and new symbol tables inside those object files.  @code{struct
+gdb_unwind_callbacks} has callbacks to read registers off the current
+frame and to write out the values of the registers in the previous
+frame.  Both have a callback (@code{target_read}) to read bytes off the
+target's address space.
+
 @node GDB Bugs
 @chapter Reporting Bugs in @value{GDBN}
 @cindex bugs in @value{GDBN}
-- 
1.7.5.4


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

* [PATCH 5/7] Use the loaded reader.
  2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
                   ` (2 preceding siblings ...)
  2011-08-24 18:57 ` [PATCH 7/7] Documentation Sanjoy Das
@ 2011-08-24 18:57 ` Sanjoy Das
  2011-08-24 18:57 ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Invoke the loaded JIT debug info reader to parse the registered symbol
files.
---
 gdb/jit.c |  494 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 464 insertions(+), 30 deletions(-)

diff --git a/gdb/jit.c b/gdb/jit.c
index f813625..b4f1830 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"
@@ -118,6 +121,7 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
 
 /* One reader that has been loaded successfully, and can potentially be used to
    parse debug info. */
+
 static struct jit_reader
 {
   struct gdb_reader_funcs *functions;
@@ -232,6 +236,18 @@ struct jit_inferior_data
   CORE_ADDR descriptor_addr;  /* &__jit_debug_descriptor  */
 };
 
+/* 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.  */
 
@@ -328,37 +344,424 @@ 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;
+}
+
+/* The reader calls into this function to create a new gdb_object
+   which it can then pass around to the other callbacks. Right now,
+   all that is required is allocating the memory. */
+
+static struct gdb_object *
+jit_object_open_impl (struct gdb_symbol_callbacks *cb)
+{
+  return XZALLOC (struct gdb_object);
+}
+
+/* Readers call into this function to open a new gdb_symtab, which,
+   again, is passed around to other callbacks. */
+
+static struct gdb_symtab *
+jit_symtab_open_impl (struct gdb_symbol_callbacks *cb,
+                      struct gdb_object *object,
+                      const char *file_name)
+{
+  struct gdb_symtab *ret;
+
+  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 corresponding 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;
+}
+
+/* Called by readers to open a new gdb_block. This function also
+   inserts the new gdb_block in the correct place in the corresponding
+   gdb_symtab. */
+
+static struct gdb_block *
+jit_block_open_impl (struct gdb_symbol_callbacks *cb,
+                     struct gdb_symtab *symtab, struct gdb_block *parent,
+                     GDB_CORE_ADDR begin, GDB_CORE_ADDR end, const char *name)
+{
+  struct gdb_block *block = 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;
+}
+
+/* Readers call this to add a line mapping (from PC to line number) to
+   a gdb_symtab. */
 
 static void
-jit_register_code (struct gdbarch *gdbarch,
-		   CORE_ADDR entry_addr, struct jit_code_entry *code_entry)
+jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb,
+                                  struct gdb_symtab *stab, int nlines,
+                                  struct gdb_line_mapping *map)
 {
+  int i;
+
+  if (nlines < 1)
+    return;
+
+  stab->linetable = xmalloc (sizeof (struct linetable)
+                             + (nlines - 1) * sizeof (struct linetable_entry));
+  stab->linetable->nitems = nlines;
+  for (i = 0; i < nlines; i++)
+    {
+      stab->linetable->item [i].pc = (CORE_ADDR) map[i].pc;
+      stab->linetable->item [i].line = map[i].line;
+    }
+}
+
+/* Called by readers to close a gdb_symtab. Does not need to do
+   anything as of now. */
+
+static void
+jit_symtab_close_impl (struct gdb_symbol_callbacks *cb,
+                       struct gdb_symtab *stab)
+{
+}
+
+/* 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, i, blockvector_size;
+  CORE_ADDR begin, end;
+
+  actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
+
+  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;
+      SYMBOL_SYMTAB (block_name) = symtab;
+      SYMBOL_BLOCK_VALUE (block_name) = new_block;
+
+      block_name->ginfo.name = obsavestring (gdb_block_iter->name,
+                                             strlen (gdb_block_iter->name),
+                                             &objfile->objfile_obstack);
+
+      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);
+}
+
+/* Called when closing a gdb_objfile. Converts OBJ to a proper objfile. */
+
+static void
+jit_object_close_impl (struct gdb_symbol_callbacks *cb,
+                       struct gdb_object *obj)
+{
+  struct gdb_symtab *i, *j;
+  struct objfile *objfile;
+  struct jit_dbg_reader_data *priv_data;
+
+  priv_data = cb->priv_data;
+
+  objfile = allocate_objfile (NULL, 0);
+  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;
+
+  xfree (objfile->name);
+  objfile->name = xstrdup ("<< JIT compiled code >>");
+
+  j = NULL;
+  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 (_("\
@@ -374,17 +777,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;
@@ -394,12 +797,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
@@ -633,6 +1058,14 @@ jit_event_handler (struct gdbarch *gdbarch)
     }
 }
 
+/* Called to free the data allocated to the jit_inferior_data slot. */
+
+static void
+free_objfile_data (struct objfile *objfile, void *data)
+{
+  xfree (data);
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 
 extern void _initialize_jit (void);
@@ -653,7 +1086,8 @@ _initialize_jit (void)
   observer_attach_inferior_created (jit_inferior_created_observer);
   observer_attach_inferior_exit (jit_inferior_exit_hook);
   observer_attach_executable_changed (jit_executable_changed_observer);
-  jit_objfile_data = register_objfile_data ();
+  jit_objfile_data =
+    register_objfile_data_with_cleanup (NULL,free_objfile_data);
   jit_inferior_data =
     register_inferior_data_with_cleanup (jit_inferior_data_cleanup);
   add_com ("jit-reader-load", no_class, jit_reader_load_command, _("\
-- 
1.7.5.4


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

* [PATCH 4/7] New commands for loading and unloading a reader.
  2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
                   ` (5 preceding siblings ...)
  2011-08-24 18:57 ` [PATCH 1/7] Introduce jit-reader.in and modify build system Sanjoy Das
@ 2011-08-24 18:57 ` Sanjoy Das
  6 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

Introduces two new GDB commands - `load-jit-reader' and
`unload-jit-reader'.
---
 gdb/jit.c |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 102 insertions(+), 1 deletions(-)

diff --git a/gdb/jit.c b/gdb/jit.c
index cab27a9..f813625 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -31,6 +31,7 @@
 #include "symfile.h"
 #include "symtab.h"
 #include "target.h"
+#include "gdb-dlfcn.h"
 #include "gdb_stat.h"
 
 static const char *jit_reader_dir = NULL;
@@ -115,6 +116,96 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
   return 0;
 }
 
+/* One reader that has been loaded successfully, and can potentially be used to
+   parse debug info. */
+static struct jit_reader
+{
+  struct gdb_reader_funcs *functions;
+} *loaded_jit_reader = NULL;
+
+typedef struct gdb_reader_funcs * (reader_init_fn_type) (void);
+static const char *reader_init_fn_sym = "gdb_init_reader";
+
+/* Try to load FILE_NAME as a JIT debug info reader. */
+
+static struct jit_reader *
+jit_reader_load (const char *file_name)
+{
+  void *so;
+  reader_init_fn_type *init_fn;
+  struct jit_reader *new_reader = NULL;
+  struct gdb_reader_funcs *funcs = NULL;
+  struct cleanup *old_cleanups;
+
+  if (jit_debug)
+    fprintf_unfiltered (gdb_stdlog, _("Opening shared object %s.\n"),
+                        file_name);
+  so = gdb_dlopen (file_name);
+  old_cleanups = make_cleanup_dlclose (so);
+
+  init_fn = gdb_dlsym (so, reader_init_fn_sym);
+  if (!init_fn)
+    error(_("Could not locate initialization function: %s."),
+          reader_init_fn_sym);
+
+  if (gdb_dlsym (so, "plugin_is_GPL_compatible") == NULL)
+    error(_("Reader not GPL compatible."));
+
+  funcs = init_fn ();
+  if (funcs->reader_version != GDB_READER_INTERFACE_VERSION)
+    error(_("Reader version does not match GDB version."));
+
+  new_reader = XZALLOC (struct jit_reader);
+  new_reader->functions = funcs;
+
+  discard_cleanups (old_cleanups);
+  return new_reader;
+}
+
+/* Provides the jit-reader-load command. */
+
+static void
+jit_reader_load_command (char *args, int from_tty)
+{
+  char so_name[PATH_MAX];
+  int len;
+
+  if (args == NULL)
+    {
+      error (_("No reader name provided."));
+      return;
+    }
+
+  if (loaded_jit_reader != NULL)
+    {
+      error (_("JIT reader already loaded.  Run jit-reader-unload first."));
+      return;
+    }
+
+  len = strlen (jit_reader_dir);
+  strcpy(so_name, jit_reader_dir);
+  so_name[len] = '/';
+  so_name[len + 1] = 0;
+
+  strncat (so_name, args, PATH_MAX - (len + 1));
+  loaded_jit_reader = jit_reader_load (so_name);
+}
+
+/* Provides the jit-reader-unload command. */
+
+static void
+jit_reader_unload_command (char *args, int from_tty)
+{
+  if (!loaded_jit_reader)
+    {
+      error(_("No JIT reader loaded."));
+      return;
+    }
+  loaded_jit_reader->functions->destroy (loaded_jit_reader->functions);
+  free (loaded_jit_reader);
+  loaded_jit_reader = NULL;
+}
+
 /* Open a BFD from the target's memory.  */
 
 static struct bfd *
@@ -535,7 +626,6 @@ jit_event_handler (struct gdbarch *gdbarch)
 			   paddress (gdbarch, entry_addr));
       else
         jit_unregister_code (objf);
-
       break;
     default:
       error (_("Unknown action_flag value in JIT descriptor!"));
@@ -566,4 +656,15 @@ _initialize_jit (void)
   jit_objfile_data = register_objfile_data ();
   jit_inferior_data =
     register_inferior_data_with_cleanup (jit_inferior_data_cleanup);
+  add_com ("jit-reader-load", no_class, jit_reader_load_command, _("\
+Load FILE as debug info reader and unwinder for JIT compiled code.\n\
+Try to load file FILE as a debug info reader (and unwinder) for\n\
+JIT compiled code. The file is loaded from\n\
+" JIT_READER_DIR ", relocated \n\
+relative to the GDB executable if required.\n\
+Usage is `jit-reader-load FILE`."));
+  add_com ("jit-reader-unload", no_class, jit_reader_unload_command, _("\
+Unload the currently loaded JIT debug info reader.\n\
+See jit-reader-load for how to load JIT debug readers.\n\
+"));
 }
-- 
1.7.5.4


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

* [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
                   ` (3 preceding siblings ...)
  2011-08-24 18:57 ` [PATCH 5/7] Use the loaded reader Sanjoy Das
@ 2011-08-24 18:57 ` Sanjoy Das
  2011-08-29 10:03   ` Pedro Alves
  2011-08-24 18:57 ` [PATCH 1/7] Introduce jit-reader.in and modify build system Sanjoy Das
  2011-08-24 18:57 ` [PATCH 4/7] New commands for loading and unloading a reader Sanjoy Das
  6 siblings, 1 reply; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

gdb-dlfcn.h and gdb-dlfcn.c are added, which implement the (cross
platform) functions gdb_dlopen, gdb_dlsym and gdb_dlclose. They should
work correctly on POSIX and windows systems.
---
 gdb/Makefile.in  |    6 ++--
 gdb/config.in    |    3 ++
 gdb/configure    |   46 ++++++++++++++++++++++++++
 gdb/configure.ac |    2 +
 gdb/gdb-dlfcn.c  |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb-dlfcn.h  |   46 ++++++++++++++++++++++++++
 6 files changed, 195 insertions(+), 3 deletions(-)
 create mode 100644 gdb/gdb-dlfcn.c
 create mode 100644 gdb/gdb-dlfcn.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c7276dd..dfddc48 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -739,7 +739,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \
 	regset.c sol-thread.c windows-termcap.c \
 	common/common-utils.c common/xml-utils.c \
-	common/ptid.c common/buffer.c
+	common/ptid.c common/buffer.c gdb-dlfcn.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -820,7 +820,7 @@ 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 \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h
+common/linux-osdata.h gdb-dlfcn.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o gcore.o \
 	jit.o progspace.o \
-	common-utils.o buffer.o ptid.o
+	common-utils.o buffer.o ptid.o gdb-dlfcn.o
 
 TSOBS = inflow.o
 
diff --git a/gdb/config.in b/gdb/config.in
index b1aef82..89c0eb4 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -988,3 +988,6 @@
 
 /* Define if JIT_READER_DIR should be relocated when GDB is moved. */
 #undef JIT_READER_DIR_RELOCATABLE
+
+/* Define if -ldl will work. */
+#undef HAVE_LIBDL
diff --git a/gdb/configure b/gdb/configure
index c6dfbf7..b7753bf 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9934,6 +9934,52 @@ fi
 ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+
 
 
 # Check whether --with-jit-reader-dir was given.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index ee73e9b..0ce5ac0 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -595,6 +595,8 @@ fi
 AC_SUBST(TARGET_PTR)
 AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
 
+AC_CHECK_LIB([dl], [dlopen], [], [], [])
+
 GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
                 [directory to load the JIT readers from],
                 [${libdir}/gdb])
diff --git a/gdb/gdb-dlfcn.c b/gdb/gdb-dlfcn.c
new file mode 100644
index 0000000..34c58d7
--- /dev/null
+++ b/gdb/gdb-dlfcn.c
@@ -0,0 +1,95 @@
+/* Platform independent shared object routines for GDB.
+
+   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/>.  */
+
+#include "gdb-dlfcn.h"
+
+#include "defs.h"
+
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
+#elif __MINGW32__
+#include <windows.h>
+#else
+/* Unsupported configuration.  See Eg. gdb_dlopen for details.  */
+#error API to load shared library missing (Eg. libdl)
+#endif
+
+void *
+gdb_dlopen (const char *filename)
+{
+  void *result;
+#ifdef HAVE_LIBDL
+  result = dlopen (filename, RTLD_NOW);
+#elif __MINGW32__
+  result = (void *) LoadLibrary (filename);
+#endif
+  if (result != NULL)
+    return result;
+
+#ifdef HAVE_LIBDL
+  error (_("Could not load %s: %s"), filename, dlerror());
+#else
+  {
+    LPVOID buffer;
+    DWORD dw;
+
+    dw = GetLastError();
+
+    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                   FORMAT_MESSAGE_IGNORE_INSERTS,
+                   NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   (LPTSTR) &buffer
+                   0, NULL);
+
+    error (_("Could not load %s: %s"), filename, (char *) buffer);
+  }
+#endif
+}
+
+void *
+gdb_dlsym (void *handle, const char *symbol)
+{
+#ifdef HAVE_LIBDL
+  return dlsym (handle, symbol);
+#elif __MINGW32__
+  return (void *) GetProcAddress (handle, symbol);
+#endif
+}
+
+int
+gdb_dlclose (void *handle)
+{
+#ifdef HAVE_LIBDL
+  return dlclose (handle);
+#elif __MINGW32__
+  return !((int) FreeLibrary (handle));
+#endif
+}
+
+static void
+do_dlclose_cleanup (void *handle)
+{
+  gdb_dlclose (handle);
+}
+
+struct cleanup *
+make_cleanup_dlclose (void *handle)
+{
+  return make_cleanup (do_dlclose_cleanup, handle);
+}
diff --git a/gdb/gdb-dlfcn.h b/gdb/gdb-dlfcn.h
new file mode 100644
index 0000000..df6c05c
--- /dev/null
+++ b/gdb/gdb-dlfcn.h
@@ -0,0 +1,46 @@
+/* Platform independent shared object routines for GDB.
+
+   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_DLFCN_H
+#define GDB_DLFCN_H
+
+#include "defs.h"
+
+/* Load the dynamic library file named FILENAME, and return a handle
+   for that dynamic library. Return NULL if the loading fails for any
+   reason.  */
+
+void *gdb_dlopen (const char *filename);
+
+/* Return the address of the symbol named SYMBOL inside the shared
+   library whose handle is HANDLE. Return NULL when the symbol could
+   not be found. */
+
+void *gdb_dlsym (void *handle, const char *symbol);
+
+/* Install a cleanup routine which closes the handle HANDLE. */
+
+struct cleanup *make_cleanup_dlclose (void *handle);
+
+/* Cleanup the shared object pointed to by HANDLE. Return 0 on success
+   and nonzero on failure. */
+
+int gdb_dlclose (void *handle);
+
+#endif /* GDB_DLFCN_H */
-- 
1.7.5.4


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

* JIT Debug Info Reader (re-roll)
@ 2011-08-24 18:57 Sanjoy Das
  2011-08-24 18:57 ` [PATCH 2/7] Relocatable directory for loading JIT readers Sanjoy Das
                   ` (6 more replies)
  0 siblings, 7 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches

This is another iteration of the JIT reader series.  I have not
included the ChangeLog entries, since they get hard to rebase -- I'll
add them once the patches are ready to be merged.

The directory from which JIT readers are loaded from is now set using
--with-jit-reader-dir and is relocated at runtime.

[PATCH 1/7] Introduce jit-reader.in and modify build system.
[PATCH 2/7] Relocatable directory for loading JIT readers.
[PATCH 3/7] Platform agnostic dynamic loading code.
[PATCH 4/7] New commands for loading and unloading a reader.
[PATCH 5/7] Use the loaded reader.
[PATCH 6/7] New JIT unwinder.
[PATCH 7/7] Documentation.


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

* [PATCH 1/7] Introduce jit-reader.in and modify build system.
  2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
                   ` (4 preceding siblings ...)
  2011-08-24 18:57 ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
@ 2011-08-24 18:57 ` Sanjoy Das
  2011-08-24 18:57 ` [PATCH 4/7] New commands for loading and unloading a reader Sanjoy Das
  6 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 18:57 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

jit-reader.in will host the interface to be implemented and the API to
be used by the reader.  The file needs to be processed by ./configure
to produce `jit.reader.h'; so that GDB_CORE_ADDR is defined correctly.

This commit arranges for `jit-reader.h' to be installed in the global
include directory.
---
 gdb/Makefile.in   |   13 ++-
 gdb/configure     |  124 +++++++++++++++++++
 gdb/configure.ac  |   22 ++++
 gdb/jit-reader.in |  350 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/jit.c         |    1 +
 5 files changed, 506 insertions(+), 4 deletions(-)
 create mode 100644 gdb/jit-reader.in

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index bd00644..c7276dd 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -824,7 +824,7 @@ common/linux-osdata.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
-HFILES_WITH_SRCDIR = ../bfd/bfd.h
+HFILES_WITH_SRCDIR = ../bfd/bfd.h jit-reader.h
 
 
 # GDB "info" files, which should be included in their entirety
@@ -941,7 +941,7 @@ DISTSTUFF = $(YYFILES)
 
 
 # All generated files which can be included by another file.
-generated_files = config.h observer.h observer.inc ada-lex.c \
+generated_files = config.h observer.h observer.inc ada-lex.c jit-reader.h \
 	$(GNULIB_H) $(NAT_GENERATED_FILES)
 
 .c.o:
@@ -1026,7 +1026,9 @@ install-only: $(CONFIG_INSTALL)
 		$(SHELL) $(srcdir)/../mkinstalldirs \
 			$(DESTDIR)$(man1dir) ; \
 		$(INSTALL_DATA) $(srcdir)/gdb.1 \
-			$(DESTDIR)$(man1dir)/$$transformed_name.1
+			$(DESTDIR)$(man1dir)/$$transformed_name.1 ; \
+		$(SHELL) $(srcdir)/../mkinstalldirs $(includedir)/gdb ; \
+		$(INSTALL_DATA) jit-reader.h $(includedir)/gdb/jit-reader.h
 	@$(MAKE) DO=install "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
 .PHONY: install-tui
 install-tui:
@@ -1254,7 +1256,7 @@ distclean: clean
 	rm -f gdbserver/config.status gdbserver/config.log
 	rm -f gdbserver/tm.h gdbserver/xm.h gdbserver/nm.h
 	rm -f gdbserver/Makefile gdbserver/config.cache
-	rm -f nm.h config.status config.h stamp-h .gdbinit
+	rm -f nm.h config.status config.h stamp-h .gdbinit jit-reader.h
 	rm -f y.output yacc.acts yacc.tmp y.tab.h
 	rm -f config.log config.cache
 	rm -f Makefile
@@ -1320,6 +1322,9 @@ data-directory/Makefile: data-directory/Makefile.in config.status @frags@
 	  CONFIG_LINKS= \
 	  $(SHELL) config.status
 
+jit-reader.h: $(srcdir)/jit-reader.in
+	$(SHELL) config.status $@
+
 config.h: stamp-h ; @true
 stamp-h: $(srcdir)/config.in config.status
 	CONFIG_HEADERS=config.h:config.in \
diff --git a/gdb/configure b/gdb/configure
index ac143e4..31469f2 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -666,6 +666,7 @@ python_prog_path
 LTLIBEXPAT
 LIBEXPAT
 HAVE_LIBEXPAT
+TARGET_PTR
 READLINE_TEXI_INCFLAG
 READLINE_CFLAGS
 READLINE_DEPS
@@ -9807,6 +9808,128 @@ fi
 
 
 
+# Generate jit-reader.h
+
+# This is typedeffed to GDB_CORE_ADDR in jit-reader.h
+TARGET_PTR=
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5
+$as_echo_n "checking size of unsigned long long... " >&6; }
+if test "${ac_cv_sizeof_unsigned_long_long+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned_long_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (unsigned long long)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_unsigned_long_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5
+$as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5
+$as_echo_n "checking size of unsigned long... " >&6; }
+if test "${ac_cv_sizeof_unsigned_long+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (unsigned long)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_unsigned_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5
+$as_echo "$ac_cv_sizeof_unsigned_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned __int128" >&5
+$as_echo_n "checking size of unsigned __int128... " >&6; }
+if test "${ac_cv_sizeof_unsigned___int128+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned __int128))" "ac_cv_sizeof_unsigned___int128"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned___int128" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (unsigned __int128)
+See \`config.log' for more details." "$LINENO" 5; }; }
+   else
+     ac_cv_sizeof_unsigned___int128=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned___int128" >&5
+$as_echo "$ac_cv_sizeof_unsigned___int128" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED___INT128 $ac_cv_sizeof_unsigned___int128
+_ACEOF
+
+
+
+if test "x${ac_cv_sizeof_unsigned_long}" = "x8"; then
+  TARGET_PTR="unsigned long"
+elif test "x${ac_cv_sizeof_unsigned_long_long}" = "x8"; then
+  TARGET_PTR="unsigned long long"
+elif test "x${ac_cv_sizeof_unsigned___int128}" = "x16"; then
+  TARGET_PTR="unsigned __int128"
+else
+  TARGET_PTR="unsigned long"
+fi
+
+
+ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
+
+
 
 # Check whether --with-expat was given.
 if test "${with_expat+set}" = set; then :
@@ -16717,6 +16840,7 @@ do
     "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;;
     "depdir") CONFIG_COMMANDS="$CONFIG_COMMANDS depdir" ;;
     "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "jit-reader.h") CONFIG_FILES="$CONFIG_FILES jit-reader.h:jit-reader.in" ;;
     "$ac_config_links_1") CONFIG_LINKS="$CONFIG_LINKS $ac_config_links_1" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     ".gdbinit") CONFIG_FILES="$CONFIG_FILES .gdbinit:gdbinit.in" ;;
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 8c12a44..abeb251 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -573,6 +573,28 @@ AC_SUBST(READLINE_DEPS)
 AC_SUBST(READLINE_CFLAGS)
 AC_SUBST(READLINE_TEXI_INCFLAG)
 
+# Generate jit-reader.h
+
+# This is typedeffed to GDB_CORE_ADDR in jit-reader.h
+TARGET_PTR=
+
+AC_CHECK_SIZEOF(unsigned long long)
+AC_CHECK_SIZEOF(unsigned long)
+AC_CHECK_SIZEOF(unsigned __int128)
+
+if test "x${ac_cv_sizeof_unsigned_long}" = "x8"; then
+  TARGET_PTR="unsigned long"
+elif test "x${ac_cv_sizeof_unsigned_long_long}" = "x8"; then
+  TARGET_PTR="unsigned long long"
+elif test "x${ac_cv_sizeof_unsigned___int128}" = "x16"; then
+  TARGET_PTR="unsigned __int128"
+else
+  TARGET_PTR="unsigned long"
+fi
+
+AC_SUBST(TARGET_PTR)
+AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
+
 AC_ARG_WITH(expat,
   AS_HELP_STRING([--with-expat], [include expat support (auto/yes/no)]),
   [], [with_expat=auto])
diff --git a/gdb/jit-reader.in b/gdb/jit-reader.in
new file mode 100644
index 0000000..f9af324
--- /dev/null
+++ b/gdb/jit-reader.in
@@ -0,0 +1,350 @@
+/* JIT declarations for GDB, the GNU Debugger.
+
+   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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Versioning information. See gdb_reader_funcs */
+
+#define GDB_READER_INTERFACE_VERSION 1
+
+/* Readers must be released under a GPL compatible license. To declare
+   that the reader is indeed released under a GPL compatible license,
+   invoke the macro GDB_DECLARE_GPL_COMPATIBLE in a source file. */
+
+#ifdef __cplusplus
+#define GDB_DECLARE_GPL_COMPATIBLE_READER       \
+  extern "C" {                                  \
+  extern int plugin_is_GPL_compatible (void)    \
+  {                                             \
+    return 0;                                   \
+  }                                             \
+  }
+
+#else
+
+#define GDB_DECLARE_GPL_COMPATIBLE_READER
+  extern int plugin_is_GPL_compatible (void)    \
+  {                                             \
+    return 0;                                   \
+  }
+
+#endif
+
+/* Represents an address on the target system. */
+
+typedef @TARGET_PTR@ GDB_CORE_ADDR;
+
+/* Return status codes. */
+
+enum gdb_status {
+  GDB_FAIL = 0,
+  GDB_SUCCESS = 1
+};
+
+struct gdb_object;
+struct gdb_symtab;
+struct gdb_block;
+struct gdb_symbol_callbacks;
+
+/* An array of these are used to represent a map from code addresses to line
+   numbers in the source file. */
+
+struct gdb_line_mapping
+{
+  int line;
+  GDB_CORE_ADDR pc;
+};
+
+/* Create a new GDB code object. Each code object can have one or more
+   symbol tables, each representing a compiled source file. */
+
+typedef struct gdb_object *(gdb_object_open) (struct gdb_symbol_callbacks *cb);
+
+/* The callback used to create new symbol table.  CB is the
+   gdb_symbol_callbacks which the structure is part of.  FILE_NAME is
+   an (optionally NULL) file name to associate with this new symbol
+   table.
+
+   Returns a new instance to gdb_symtab that can later be passed to
+   gdb_block_new, gdb_symtab_add_line_mapping and gdb_symtab_close. */
+
+typedef struct gdb_symtab *(gdb_symtab_open) (struct gdb_symbol_callbacks *cb,
+                                              struct gdb_object *obj,
+                                              const char *file_name);
+
+/* Creates a new block in a given symbol table. A symbol table is a
+   forest of blocks, each block representing an code address range and
+   a corresponding (optionally NULL) NAME. In case the block
+   corresponds to a function, the NAME passed should be the name of
+   the function.
+
+   If the new block to be created is a child of (i.e. is nested in)
+   another block, the parent block can be passed in PARENT. SYMTAB is
+   the symbol table the new block is to belong in. BEGIN, END is the
+   code address range the block corresponds to.
+
+   Returns a new instance of gdb_block, which, as of now, has no
+   use. Note that the gdb_block returned must not be freed by the
+   caller. */
+
+typedef struct gdb_block *(gdb_block_open) (struct gdb_symbol_callbacks *cb,
+                                            struct gdb_symtab *symtab,
+                                            struct gdb_block *parent,
+                                            GDB_CORE_ADDR begin,
+                                            GDB_CORE_ADDR end,
+                                            const char *name);
+
+/* Adds a PC to line number mapping for the symbol table
+   SYMTAB. NLINES is the number of elements in LINES, each element
+   corresponding to one (PC, line) pair. */
+
+typedef void (gdb_symtab_add_line_mapping) (struct gdb_symbol_callbacks *cb,
+                                            struct gdb_symtab *symtab,
+                                            int nlines,
+                                            struct gdb_line_mapping *lines);
+
+/* Close the symtab SYMTAB. This signals to GDB that no more blocks
+   will be opened on this symtab. */
+
+typedef void (gdb_symtab_close) (struct gdb_symbol_callbacks *cb,
+                                 struct gdb_symtab *symtab);
+
+
+/* Closes the gdb_object OBJ and adds the emitted information into
+   GDB's internal structures. Once this is done, the debug information
+   will be picked up and used; this will usually be the last operation
+   in gdb_read_debug_info. */
+
+typedef void (gdb_object_close) (struct gdb_symbol_callbacks *cb,
+                                 struct gdb_object *obj);
+
+/* Reads LEN bytes from TARGET_MEM in the target's virtual address
+   space into GDB_BUF.
+
+   Returns GDB_FAIL on failure, and GDB_SUCCESS on success. */
+
+typedef enum gdb_status (gdb_target_read) (GDB_CORE_ADDR target_mem,
+                                           void *gdb_buf, int len);
+
+/* The list of callbacks that are passed to read. These callbacks are
+   to be used to construct the symbol table. The functions have been
+   described above. */
+
+struct gdb_symbol_callbacks
+{
+  gdb_object_open *object_open;
+  gdb_symtab_open *symtab_open;
+  gdb_block_open *block_open;
+  gdb_symtab_close *symtab_close;
+  gdb_object_close *object_close;
+
+  gdb_symtab_add_line_mapping *line_mapping_add;
+  gdb_target_read *target_read;
+
+  /* For internal use by GDB. */
+
+  void *priv_data;
+};
+
+/* Forward declaration. */
+
+struct gdb_reg_value;
+
+/* A function of this type is used to free a gdb_reg_value. See the
+   comment on `free' in struct gdb_reg_value. */
+
+typedef void (gdb_reg_value_free) (struct gdb_reg_value *);
+
+/* Denotes the value of a register. */
+
+struct gdb_reg_value
+{
+  /* The size of the register in bytes. The reader need not set this
+     field. This will be set for (defined) register values being read
+     from GDB using reg_get. */
+
+  int size;
+
+  /* Set to non-zero if the value for the register is known. The
+     registers for which the reader does not call reg_set are also
+     assumed to be undefined */
+
+  int defined;
+
+  /* Since gdb_reg_value is a variable sized structure, it will
+     usually be allocated on the heap. This function is expected to
+     contain the corresponding "free" function.
+
+     When a pointer to gdb_reg_value is being sent from GDB to the
+     reader (via gdb_unwind_reg_get), the reader is expected to call
+     this function (with the same gdb_reg_value as argument) once it
+     is done with the value.
+
+     When the function sends the a gdb_reg_value to GDB (via
+     gdb_unwind_reg_set), it is expected to set this field to point to
+     an appropriate cleanup routine (or to NULL if no cleanup is
+     required). */
+
+  gdb_reg_value_free *free;
+
+  /* The value of the register. */
+
+  unsigned char value[1];
+};
+
+/* get_frame_id in gdb_reader_funcs is to return a gdb_frame_id
+   corresponding to the current frame. The registers corresponding to
+   the current frame can be read using reg_get. Calling get_frame_id
+   on a particular frame should return the same gdb_frame_id
+   throughout its lifetime (i.e. till before it gets unwound). One way
+   to do this is by having the CODE_ADDRESS point to the function's
+   first instruction and STACK_ADDRESS point to the value of the stack
+   pointer when entering the function. */
+
+struct gdb_frame_id
+{
+  GDB_CORE_ADDR code_address;
+  GDB_CORE_ADDR stack_address;
+};
+
+/* Forward declaration. */
+
+struct gdb_unwind_callbacks;
+
+/* Returns the value of a particular register in the current
+   frame. The current frame is the frame that needs to be unwound into
+   the outer (earlier) frame.
+
+   CB is the struct gdb_unwind_callbacks * the callback belongs
+   to. REGNUM is the DWARF register number of the register that needs
+   to be unwound.
+
+   Returns the gdb_reg_value corresponding to the register
+   requested. In case the value of the register has been optimized
+   away or otherwise unavailable, the defined flag in the returned
+   gdb_reg_value will be zero. */
+
+typedef struct gdb_reg_value *(gdb_unwind_reg_get)
+                              (struct gdb_unwind_callbacks *cb, int regnum);
+
+/* Sets the previous value of a particular register. REGNUM is the
+   (DWARF) register number whose value is to be set. VAL is the value
+   the register is to be set to.
+
+   VAL is *not* copied, so the memory allocated to it cannot be
+   reused. Once GDB no longer needs the value, it is deallocated using
+   the FREE function (see gdb_reg_value).
+
+   A register can also be "set" to an undefined value by setting the
+   defined in VAL to zero. */
+
+typedef void (gdb_unwind_reg_set) (struct gdb_unwind_callbacks *cb, int regnum,
+                                   struct gdb_reg_value *val);
+
+/* This struct is passed to unwind in gdb_reader_funcs, and is to be
+   used to unwind the current frame (current being the frame whose
+   registers can be read using reg_get) into the earlier frame. The
+   functions have been described above. */
+
+struct gdb_unwind_callbacks
+{
+  gdb_unwind_reg_get *reg_get;
+  gdb_unwind_reg_set *reg_set;
+  gdb_target_read *target_read;
+
+  /* For internal use by GDB. */
+
+  void *priv_data;
+};
+
+/* Forward declaration. */
+
+struct gdb_reader_funcs;
+
+/* Parse the debug info off a block of memory, pointed to by MEMORY
+   (already copied to GDB's address space) and MEMORY_SZ bytes long.
+   The implementation has to use the functions in CB to actually emit
+   the parsed data into GDB. SELF is the same structure returned by
+   gdb_init_reader.
+
+   Return GDB_FAIL on failure and GDB_SUCCESS on success. */
+
+typedef enum gdb_status (gdb_read_debug_info) (struct gdb_reader_funcs *self,
+                                               struct gdb_symbol_callbacks *cb,
+                                               void *memory, long memory_sz);
+
+/* Unwind the current frame, CB is the set of unwind callbacks that
+   are to be used to do this.
+
+   Return GDB_FAIL on failure and GDB_SUCCESS on success. */
+
+typedef enum gdb_status (gdb_unwind_frame) (struct gdb_reader_funcs *self,
+                                            struct gdb_unwind_callbacks *cb);
+
+/* Return the frame ID corresponding to the current frame, using C to
+   read the current register values. See the comment on struct
+   gdb_frame_id. */
+
+typedef struct gdb_frame_id (gdb_get_frame_id) (struct gdb_reader_funcs *self,
+                                                struct gdb_unwind_callbacks *c);
+
+/* Called when a reader is being unloaded. This function should also
+   free SELF, if required. */
+
+typedef void (gdb_destroy_reader) (struct gdb_reader_funcs *self);
+
+/* Called when the reader is loaded. Must either return a properly
+   populated gdb_reader_funcs or NULL. The memory allocated for the
+   gdb_reader_funcs is to be managed by the reader itself (i.e. if it
+   is allocated from the heap, it must also be freed in
+   gdb_destroy_reader).  */
+
+extern struct gdb_reader_funcs *gdb_init_reader (void);
+
+/* Pointer to the functions which implement the reader's
+   functionality. The individual functions have been documented above.
+
+   None of the fields are optional. */
+
+struct gdb_reader_funcs
+{
+  /* Must be set to GDB_READER_INTERFACE_VERSION */
+
+  int reader_version;
+
+  /* For use by the reader. */
+
+  void *priv_data;
+
+  gdb_read_debug_info *read;
+  gdb_unwind_frame *unwind;
+  gdb_get_frame_id *get_frame_id;
+  gdb_destroy_reader *destroy;
+};
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/gdb/jit.c b/gdb/jit.c
index eb1bcc7..e3bb81a 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -20,6 +20,7 @@
 #include "defs.h"
 
 #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] 20+ messages in thread

* Re: [PATCH 6/7] New JIT unwinder.
  2011-08-24 18:57 ` [PATCH 6/7] New JIT unwinder Sanjoy Das
@ 2011-08-24 19:04   ` Jan Kratochvil
  2011-08-24 19:08     ` Sanjoy Das
  0 siblings, 1 reply; 20+ messages in thread
From: Jan Kratochvil @ 2011-08-24 19:04 UTC (permalink / raw)
  To: Sanjoy Das; +Cc: gdb-patches

On Wed, 24 Aug 2011 21:01:06 +0200, Sanjoy Das wrote:
> Introduce a "proxy unwinder", whcih will pass down all calls to the
> functions the JIT reader provides.

Still incorrect assumptions target_gdbarch == get_frame_arch (frame).
You should use get_frame_arch (frame) instead.

While it currently affects only SPU if GDB supports one day across-RPC (remote
procedure calls in general) debugging it woule be also a problem.

OTOH I guess there are probably already some places not conforming to this.


Thanks,
Jan


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

* Re: [PATCH 6/7] New JIT unwinder.
  2011-08-24 19:04   ` Jan Kratochvil
@ 2011-08-24 19:08     ` Sanjoy Das
  0 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-24 19:08 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Thursday 25 August 2011 12:34 AM, Jan Kratochvil wrote:
> On Wed, 24 Aug 2011 21:01:06 +0200, Sanjoy Das wrote:
>> Introduce a "proxy unwinder", whcih will pass down all calls to the
>> functions the JIT reader provides.
> 
> Still incorrect assumptions target_gdbarch == get_frame_arch (frame).
> You should use get_frame_arch (frame) instead.
> 
> While it currently affects only SPU if GDB supports one day across-RPC (remote
> procedure calls in general) debugging it woule be also a problem.
> 
> OTOH I guess there are probably already some places not conforming to this.
> 
> 
> Thanks,
> Jan

Sorry, will correct.

-- 
Sanjoy Das
http://playingwithpointers.com


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

* Re: [PATCH 7/7] Documentation.
  2011-08-24 18:57 ` [PATCH 7/7] Documentation Sanjoy Das
@ 2011-08-24 20:14   ` Eli Zaretskii
  0 siblings, 0 replies; 20+ messages in thread
From: Eli Zaretskii @ 2011-08-24 20:14 UTC (permalink / raw)
  To: Sanjoy Das; +Cc: gdb-patches

> From: Sanjoy Das <sanjoy@playingwithpointers.com>
> Cc: Sanjoy Das <sanjoy@playingwithpointers.com>
> Date: Thu, 25 Aug 2011 00:31:07 +0530
> 
> Add some basic documentation to gdb.texinfo about the new JIT reader
> functionality. Most of the actual documentation is still in
> jit-reader.h.

OK, thanks.


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

* Re: [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-24 18:57 ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
@ 2011-08-29 10:03   ` Pedro Alves
  2011-08-29 12:54     ` Sanjoy Das
  0 siblings, 1 reply; 20+ messages in thread
From: Pedro Alves @ 2011-08-29 10:03 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

On Wednesday 24 August 2011 20:01:03, Sanjoy Das wrote:
> +
> +#ifdef HAVE_LIBDL
> +#include <dlfcn.h>
> +#elif __MINGW32__
> +#include <windows.h>
> +#else
> +/* Unsupported configuration.  See Eg. gdb_dlopen for details.  */
> +#error API to load shared library missing (Eg. libdl)
> +#endif

This isn't correct.  There are platforms where dlopen & friends are
in the C library, and don't need or have -ldl/libdl.

-- 
Pedro Alves


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

* Re: [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-29 10:03   ` Pedro Alves
@ 2011-08-29 12:54     ` Sanjoy Das
  2011-08-29 14:22       ` Pedro Alves
  0 siblings, 1 reply; 20+ messages in thread
From: Sanjoy Das @ 2011-08-29 12:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Hi Pedro!

> This isn't correct.  There are platforms where dlopen & friends are
> in the C library, and don't need or have -ldl/libdl.


Does it make more sense to have an AC_CHECK_HEADERS for dlfcn.h then?
Of course, the AC_CHECK_LIB will have to stay, since we'd want to add
-ldl if required.

Thanks!

-- 
Sanjoy Das
http://playingwithpointers.com


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

* Re: [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-29 12:54     ` Sanjoy Das
@ 2011-08-29 14:22       ` Pedro Alves
  2011-08-30  6:01         ` Sanjoy Das
  0 siblings, 1 reply; 20+ messages in thread
From: Pedro Alves @ 2011-08-29 14:22 UTC (permalink / raw)
  To: Sanjoy Das; +Cc: gdb-patches

On Monday 29 August 2011 13:58:39, Sanjoy Das wrote:
> Hi Pedro!
> 
> > This isn't correct.  There are platforms where dlopen & friends are
> > in the C library, and don't need or have -ldl/libdl.
> 
> 
> Does it make more sense to have an AC_CHECK_HEADERS for dlfcn.h then?
> Of course, the AC_CHECK_LIB will have to stay, since we'd want to add
> -ldl if required.

Checking for dlfcn.h sounds like a good idea, but I think AC_SEARCH_LIBS
instead of AC_CHECK_LIB would be a bit more bullet proof, to still check
for being able to call/link dlopen.

-- 
Pedro Alves


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

* Re: [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-29 14:22       ` Pedro Alves
@ 2011-08-30  6:01         ` Sanjoy Das
  2011-08-30 18:40           ` Tom Tromey
  0 siblings, 1 reply; 20+ messages in thread
From: Sanjoy Das @ 2011-08-30  6:01 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 79 bytes --]

Hi!

Does this look OK?

Thanks!
-- 
Sanjoy Das
http://playingwithpointers.com

[-- Attachment #2: 0003-Platform-agnostic-dynamic-loading-code.patch --]
[-- Type: text/x-diff, Size: 9900 bytes --]

From 42e170b4b42d3135dd377b181f9e878b7fd9658e Mon Sep 17 00:00:00 2001
From: Sanjoy Das <sanjoy@playingwithpointers.com>
Date: Wed, 24 Aug 2011 22:38:05 +0530
Subject: [PATCH 3/7] Platform agnostic dynamic loading code.

gdb-dlfcn.h and gdb-dlfcn.c are added, which implement the (cross
platform) functions gdb_dlopen, gdb_dlsym and gdb_dlclose. They should
work correctly on POSIX and windows systems.

gdb/ChangeLog:
	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
	system.
	* gdb/config.in: Add new #define HAVE_DLFCN_H.
	* gdb/configure.ac: Add check for dlopen and for dlfcn.h
	* gdb/configure: Re-generated by autoconf.
---
 gdb/ChangeLog    |    8 ++++
 gdb/Makefile.in  |    6 ++--
 gdb/config.in    |    3 ++
 gdb/configure    |   69 +++++++++++++++++++++++++++++++++++++++
 gdb/configure.ac |    3 ++
 gdb/gdb-dlfcn.c  |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb-dlfcn.h  |   46 ++++++++++++++++++++++++++
 7 files changed, 227 insertions(+), 3 deletions(-)
 create mode 100644 gdb/gdb-dlfcn.c
 create mode 100644 gdb/gdb-dlfcn.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3196016..995599c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2011-08-27  Sanjoy Das  <sdas@igalia.com>
 
+    	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
+    	system.
+    	* gdb/config.in: Add new #define HAVE_DLFCN_H.
+    	* gdb/configure.ac: Add check for dlopen and for dlfcn.h
+    	* gdb/configure: Re-generated by autoconf.
+
+2011-08-27  Sanjoy Das  <sdas@igalia.com>
+
 	* gdb/config.in: Add new #defines: JIT_READER_DIR and
 	JIT_READER_DIR_RELOCATABLE.
 	* gdb/configure.ac: New GDB directory entry for jit-reader-dir.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index b277597..732b8f0 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -739,7 +739,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \
 	regset.c sol-thread.c windows-termcap.c \
 	common/common-utils.c common/xml-utils.c \
-	common/ptid.c common/buffer.c
+	common/ptid.c common/buffer.c gdb-dlfcn.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -820,7 +820,7 @@ 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 \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h
+common/linux-osdata.h gdb-dlfcn.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o gcore.o \
 	jit.o progspace.o \
-	common-utils.o buffer.o ptid.o
+	common-utils.o buffer.o ptid.o gdb-dlfcn.o
 
 TSOBS = inflow.o
 
diff --git a/gdb/config.in b/gdb/config.in
index 27a4e2c..4af4e69 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -988,3 +988,6 @@
 
 /* Define if JIT_READER_DIR should be relocated when GDB is moved.  */
 #undef JIT_READER_DIR_RELOCATABLE
+
+/* Define if the platform has dlfcn.h.  */
+#undef HAVE_DLFCN_H
diff --git a/gdb/configure b/gdb/configure
index c6dfbf7..3e68336 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9934,6 +9934,75 @@ fi
 ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if test "${ac_cv_search_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_dlopen+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_dlopen+set}" = set; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
 
 
 # Check whether --with-jit-reader-dir was given.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index ee73e9b..6b4e13c 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -595,6 +595,9 @@ fi
 AC_SUBST(TARGET_PTR)
 AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
 
+AC_SEARCH_LIBS(dlopen, dl)
+AC_CHECK_HEADERS([dlfcn.h])
+
 GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
                 [directory to load the JIT readers from],
                 [${libdir}/gdb])
diff --git a/gdb/gdb-dlfcn.c b/gdb/gdb-dlfcn.c
new file mode 100644
index 0000000..d5d244d
--- /dev/null
+++ b/gdb/gdb-dlfcn.c
@@ -0,0 +1,95 @@
+/* Platform independent shared object routines for GDB.
+
+   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/>.  */
+
+#include "gdb-dlfcn.h"
+
+#include "defs.h"
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#elif __MINGW32__
+#include <windows.h>
+#else
+/* Unsupported configuration.  See Eg. gdb_dlopen for details.  */
+#error API to load shared library missing (Eg. libdl)
+#endif
+
+void *
+gdb_dlopen (const char *filename)
+{
+  void *result;
+#ifdef HAVE_DLFCN_H
+  result = dlopen (filename, RTLD_NOW);
+#elif __MINGW32__
+  result = (void *) LoadLibrary (filename);
+#endif
+  if (result != NULL)
+    return result;
+
+#ifdef HAVE_DLFCN_H
+  error (_("Could not load %s: %s"), filename, dlerror());
+#else
+  {
+    LPVOID buffer;
+    DWORD dw;
+
+    dw = GetLastError();
+
+    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                   FORMAT_MESSAGE_IGNORE_INSERTS,
+                   NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   (LPTSTR) &buffer
+                   0, NULL);
+
+    error (_("Could not load %s: %s"), filename, (char *) buffer);
+  }
+#endif
+}
+
+void *
+gdb_dlsym (void *handle, const char *symbol)
+{
+#ifdef HAVE_DLFCN_H
+  return dlsym (handle, symbol);
+#elif __MINGW32__
+  return (void *) GetProcAddress (handle, symbol);
+#endif
+}
+
+int
+gdb_dlclose (void *handle)
+{
+#ifdef HAVE_DLFCN_H
+  return dlclose (handle);
+#elif __MINGW32__
+  return !((int) FreeLibrary (handle));
+#endif
+}
+
+static void
+do_dlclose_cleanup (void *handle)
+{
+  gdb_dlclose (handle);
+}
+
+struct cleanup *
+make_cleanup_dlclose (void *handle)
+{
+  return make_cleanup (do_dlclose_cleanup, handle);
+}
diff --git a/gdb/gdb-dlfcn.h b/gdb/gdb-dlfcn.h
new file mode 100644
index 0000000..e87672a
--- /dev/null
+++ b/gdb/gdb-dlfcn.h
@@ -0,0 +1,46 @@
+/* Platform independent shared object routines for GDB.
+
+   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_DLFCN_H
+#define GDB_DLFCN_H
+
+#include "defs.h"
+
+/* Load the dynamic library file named FILENAME, and return a handle
+   for that dynamic library.  Return NULL if the loading fails for any
+   reason.  */
+
+void *gdb_dlopen (const char *filename);
+
+/* Return the address of the symbol named SYMBOL inside the shared
+   library whose handle is HANDLE.  Return NULL when the symbol could
+   not be found.  */
+
+void *gdb_dlsym (void *handle, const char *symbol);
+
+/* Install a cleanup routine which closes the handle HANDLE.  */
+
+struct cleanup *make_cleanup_dlclose (void *handle);
+
+/* Cleanup the shared object pointed to by HANDLE. Return 0 on success
+   and nonzero on failure.  */
+
+int gdb_dlclose (void *handle);
+
+#endif /* GDB_DLFCN_H */
-- 
1.7.5.4


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

* Re: [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-30  6:01         ` Sanjoy Das
@ 2011-08-30 18:40           ` Tom Tromey
  0 siblings, 0 replies; 20+ messages in thread
From: Tom Tromey @ 2011-08-30 18:40 UTC (permalink / raw)
  To: Sanjoy Das; +Cc: Pedro Alves, gdb-patches

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

Sanjoy> 	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
Sanjoy> 	system.
Sanjoy> 	* gdb/config.in: Add new #define HAVE_DLFCN_H.
Sanjoy> 	* gdb/configure.ac: Add check for dlopen and for dlfcn.h
Sanjoy> 	* gdb/configure: Re-generated by autoconf.

Sanjoy> +AC_SEARCH_LIBS(dlopen, dl)
Sanjoy> +AC_CHECK_HEADERS([dlfcn.h])

There is one big call to AC_CHECK_HEADERS in gdb/configure.ac.
Search for "Checks for header files".

You should just add this header to that check; that is where all the
simple checks should go since having them in a single call makes the
resulting configure file smaller.

Sanjoy> +#include "gdb-dlfcn.h"
Sanjoy> +
Sanjoy> +#include "defs.h"

Put defs.h first.

This is ok with those changes.  Thanks.

Tom


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

* Re: [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-31  3:31 ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
@ 2011-08-31  4:01   ` Sanjoy Das
  0 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-31  4:01 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 122 bytes --]

Hi!

I forgot a few corrections on this one -- new patch attached.

Thanks!
-- 
Sanjoy Das
http://playingwithpointers.com

[-- Attachment #2: 0003-Platform-agnostic-dynamic-loading-code.patch --]
[-- Type: text/x-diff, Size: 10659 bytes --]

From 9c0dccc6c62d4d0ce6b19ee1e04fa760c5d5a030 Mon Sep 17 00:00:00 2001
From: Sanjoy Das <sanjoy@playingwithpointers.com>
Date: Wed, 24 Aug 2011 22:38:05 +0530
Subject: [PATCH 3/7] Platform agnostic dynamic loading code.

gdb-dlfcn.h and gdb-dlfcn.c are added, which implement the (cross
platform) functions gdb_dlopen, gdb_dlsym and gdb_dlclose. They should
work correctly on POSIX and windows systems.

gdb/ChangeLog:
	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
	system.
	* gdb/config.in: Add new #define HAVE_DLFCN_H.
	* gdb/configure.ac: Add check for dlopen and for dlfcn.h
	* gdb/configure: Re-generated by autoconf.
---
 gdb/ChangeLog    |    8 ++++
 gdb/Makefile.in  |    6 ++--
 gdb/config.in    |    3 ++
 gdb/configure    |   60 +++++++++++++++++++++++++++++++++-
 gdb/configure.ac |    5 ++-
 gdb/gdb-dlfcn.c  |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb-dlfcn.h  |   46 ++++++++++++++++++++++++++
 7 files changed, 218 insertions(+), 5 deletions(-)
 create mode 100644 gdb/gdb-dlfcn.c
 create mode 100644 gdb/gdb-dlfcn.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3196016..995599c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2011-08-27  Sanjoy Das  <sdas@igalia.com>
 
+    	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
+    	system.
+    	* gdb/config.in: Add new #define HAVE_DLFCN_H.
+    	* gdb/configure.ac: Add check for dlopen and for dlfcn.h
+    	* gdb/configure: Re-generated by autoconf.
+
+2011-08-27  Sanjoy Das  <sdas@igalia.com>
+
 	* gdb/config.in: Add new #defines: JIT_READER_DIR and
 	JIT_READER_DIR_RELOCATABLE.
 	* gdb/configure.ac: New GDB directory entry for jit-reader-dir.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 246a810..1a51666 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -739,7 +739,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \
 	regset.c sol-thread.c windows-termcap.c \
 	common/common-utils.c common/xml-utils.c \
-	common/ptid.c common/buffer.c
+	common/ptid.c common/buffer.c gdb-dlfcn.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -820,7 +820,7 @@ 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 \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h
+common/linux-osdata.h gdb-dlfcn.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o gcore.o \
 	jit.o progspace.o \
-	common-utils.o buffer.o ptid.o
+	common-utils.o buffer.o ptid.o gdb-dlfcn.o
 
 TSOBS = inflow.o
 
diff --git a/gdb/config.in b/gdb/config.in
index 27a4e2c..4af4e69 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -988,3 +988,6 @@
 
 /* Define if JIT_READER_DIR should be relocated when GDB is moved.  */
 #undef JIT_READER_DIR_RELOCATABLE
+
+/* Define if the platform has dlfcn.h.  */
+#undef HAVE_DLFCN_H
diff --git a/gdb/configure b/gdb/configure
index c6dfbf7..daaa12c 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9934,6 +9934,63 @@ fi
 ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if test "${ac_cv_search_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_dlopen+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_dlopen+set}" = set; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
 
 
 # Check whether --with-jit-reader-dir was given.
@@ -11530,7 +11587,8 @@ for ac_header in nlist.h machine/reg.h poll.h sys/poll.h proc_service.h \
 		  sys/resource.h sys/procfs.h sys/ptrace.h ptrace.h \
 		  sys/reg.h sys/debugreg.h sys/select.h sys/syscall.h \
 		  sys/types.h sys/wait.h wait.h termios.h termio.h \
-		  sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h
+		  sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h \
+                  dlfcn.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
diff --git a/gdb/configure.ac b/gdb/configure.ac
index ee73e9b..661e6df 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -595,6 +595,8 @@ fi
 AC_SUBST(TARGET_PTR)
 AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
 
+AC_SEARCH_LIBS(dlopen, dl)
+
 GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
                 [directory to load the JIT readers from],
                 [${libdir}/gdb])
@@ -949,7 +951,8 @@ AC_CHECK_HEADERS([nlist.h machine/reg.h poll.h sys/poll.h proc_service.h \
 		  sys/resource.h sys/procfs.h sys/ptrace.h ptrace.h \
 		  sys/reg.h sys/debugreg.h sys/select.h sys/syscall.h \
 		  sys/types.h sys/wait.h wait.h termios.h termio.h \
-		  sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h])
+		  sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h \
+		  dlfcn.h])
 AC_CHECK_HEADERS(link.h, [], [],
 [#if HAVE_SYS_TYPES_H
 # include <sys/types.h>
diff --git a/gdb/gdb-dlfcn.c b/gdb/gdb-dlfcn.c
new file mode 100644
index 0000000..b05c853
--- /dev/null
+++ b/gdb/gdb-dlfcn.c
@@ -0,0 +1,95 @@
+/* Platform independent shared object routines for GDB.
+
+   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/>.  */
+
+#include "defs.h"
+
+#include "gdb-dlfcn.h"
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#elif __MINGW32__
+#include <windows.h>
+#else
+/* Unsupported configuration.  See Eg. gdb_dlopen for details.  */
+#error API to load shared library missing (Eg. libdl)
+#endif
+
+void *
+gdb_dlopen (const char *filename)
+{
+  void *result;
+#ifdef HAVE_DLFCN_H
+  result = dlopen (filename, RTLD_NOW);
+#elif __MINGW32__
+  result = (void *) LoadLibrary (filename);
+#endif
+  if (result != NULL)
+    return result;
+
+#ifdef HAVE_DLFCN_H
+  error (_("Could not load %s: %s"), filename, dlerror());
+#else
+  {
+    LPVOID buffer;
+    DWORD dw;
+
+    dw = GetLastError();
+
+    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                   FORMAT_MESSAGE_IGNORE_INSERTS,
+                   NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   (LPTSTR) &buffer
+                   0, NULL);
+
+    error (_("Could not load %s: %s"), filename, (char *) buffer);
+  }
+#endif
+}
+
+void *
+gdb_dlsym (void *handle, const char *symbol)
+{
+#ifdef HAVE_DLFCN_H
+  return dlsym (handle, symbol);
+#elif __MINGW32__
+  return (void *) GetProcAddress (handle, symbol);
+#endif
+}
+
+int
+gdb_dlclose (void *handle)
+{
+#ifdef HAVE_DLFCN_H
+  return dlclose (handle);
+#elif __MINGW32__
+  return !((int) FreeLibrary (handle));
+#endif
+}
+
+static void
+do_dlclose_cleanup (void *handle)
+{
+  gdb_dlclose (handle);
+}
+
+struct cleanup *
+make_cleanup_dlclose (void *handle)
+{
+  return make_cleanup (do_dlclose_cleanup, handle);
+}
diff --git a/gdb/gdb-dlfcn.h b/gdb/gdb-dlfcn.h
new file mode 100644
index 0000000..e87672a
--- /dev/null
+++ b/gdb/gdb-dlfcn.h
@@ -0,0 +1,46 @@
+/* Platform independent shared object routines for GDB.
+
+   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_DLFCN_H
+#define GDB_DLFCN_H
+
+#include "defs.h"
+
+/* Load the dynamic library file named FILENAME, and return a handle
+   for that dynamic library.  Return NULL if the loading fails for any
+   reason.  */
+
+void *gdb_dlopen (const char *filename);
+
+/* Return the address of the symbol named SYMBOL inside the shared
+   library whose handle is HANDLE.  Return NULL when the symbol could
+   not be found.  */
+
+void *gdb_dlsym (void *handle, const char *symbol);
+
+/* Install a cleanup routine which closes the handle HANDLE.  */
+
+struct cleanup *make_cleanup_dlclose (void *handle);
+
+/* Cleanup the shared object pointed to by HANDLE. Return 0 on success
+   and nonzero on failure.  */
+
+int gdb_dlclose (void *handle);
+
+#endif /* GDB_DLFCN_H */
-- 
1.7.5.4


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

* [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-31  3:31 JIT Reader (re-roll) Sanjoy Das
@ 2011-08-31  3:31 ` Sanjoy Das
  2011-08-31  4:01   ` Sanjoy Das
  0 siblings, 1 reply; 20+ messages in thread
From: Sanjoy Das @ 2011-08-31  3:31 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

gdb-dlfcn.h and gdb-dlfcn.c are added, which implement the (cross
platform) functions gdb_dlopen, gdb_dlsym and gdb_dlclose. They should
work correctly on POSIX and windows systems.

gdb/ChangeLog:
	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
	system.
	* gdb/config.in: Add new #define HAVE_DLFCN_H.
	* gdb/configure.ac: Add check for dlopen and for dlfcn.h
	* gdb/configure: Re-generated by autoconf.
---
 gdb/ChangeLog    |    8 ++++
 gdb/Makefile.in  |    6 ++--
 gdb/config.in    |    3 ++
 gdb/configure    |   69 +++++++++++++++++++++++++++++++++++++++
 gdb/configure.ac |    3 ++
 gdb/gdb-dlfcn.c  |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb-dlfcn.h  |   46 ++++++++++++++++++++++++++
 7 files changed, 227 insertions(+), 3 deletions(-)
 create mode 100644 gdb/gdb-dlfcn.c
 create mode 100644 gdb/gdb-dlfcn.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3196016..995599c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2011-08-27  Sanjoy Das  <sdas@igalia.com>
 
+    	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
+    	system.
+    	* gdb/config.in: Add new #define HAVE_DLFCN_H.
+    	* gdb/configure.ac: Add check for dlopen and for dlfcn.h
+    	* gdb/configure: Re-generated by autoconf.
+
+2011-08-27  Sanjoy Das  <sdas@igalia.com>
+
 	* gdb/config.in: Add new #defines: JIT_READER_DIR and
 	JIT_READER_DIR_RELOCATABLE.
 	* gdb/configure.ac: New GDB directory entry for jit-reader-dir.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 246a810..1a51666 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -739,7 +739,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \
 	regset.c sol-thread.c windows-termcap.c \
 	common/common-utils.c common/xml-utils.c \
-	common/ptid.c common/buffer.c
+	common/ptid.c common/buffer.c gdb-dlfcn.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -820,7 +820,7 @@ 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 \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h
+common/linux-osdata.h gdb-dlfcn.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o gcore.o \
 	jit.o progspace.o \
-	common-utils.o buffer.o ptid.o
+	common-utils.o buffer.o ptid.o gdb-dlfcn.o
 
 TSOBS = inflow.o
 
diff --git a/gdb/config.in b/gdb/config.in
index 27a4e2c..4af4e69 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -988,3 +988,6 @@
 
 /* Define if JIT_READER_DIR should be relocated when GDB is moved.  */
 #undef JIT_READER_DIR_RELOCATABLE
+
+/* Define if the platform has dlfcn.h.  */
+#undef HAVE_DLFCN_H
diff --git a/gdb/configure b/gdb/configure
index c6dfbf7..3e68336 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9934,6 +9934,75 @@ fi
 ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if test "${ac_cv_search_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if test "${ac_cv_search_dlopen+set}" = set; then :
+  break
+fi
+done
+if test "${ac_cv_search_dlopen+set}" = set; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
 
 
 # Check whether --with-jit-reader-dir was given.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index ee73e9b..6b4e13c 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -595,6 +595,9 @@ fi
 AC_SUBST(TARGET_PTR)
 AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
 
+AC_SEARCH_LIBS(dlopen, dl)
+AC_CHECK_HEADERS([dlfcn.h])
+
 GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
                 [directory to load the JIT readers from],
                 [${libdir}/gdb])
diff --git a/gdb/gdb-dlfcn.c b/gdb/gdb-dlfcn.c
new file mode 100644
index 0000000..d5d244d
--- /dev/null
+++ b/gdb/gdb-dlfcn.c
@@ -0,0 +1,95 @@
+/* Platform independent shared object routines for GDB.
+
+   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/>.  */
+
+#include "gdb-dlfcn.h"
+
+#include "defs.h"
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#elif __MINGW32__
+#include <windows.h>
+#else
+/* Unsupported configuration.  See Eg. gdb_dlopen for details.  */
+#error API to load shared library missing (Eg. libdl)
+#endif
+
+void *
+gdb_dlopen (const char *filename)
+{
+  void *result;
+#ifdef HAVE_DLFCN_H
+  result = dlopen (filename, RTLD_NOW);
+#elif __MINGW32__
+  result = (void *) LoadLibrary (filename);
+#endif
+  if (result != NULL)
+    return result;
+
+#ifdef HAVE_DLFCN_H
+  error (_("Could not load %s: %s"), filename, dlerror());
+#else
+  {
+    LPVOID buffer;
+    DWORD dw;
+
+    dw = GetLastError();
+
+    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                   FORMAT_MESSAGE_IGNORE_INSERTS,
+                   NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   (LPTSTR) &buffer
+                   0, NULL);
+
+    error (_("Could not load %s: %s"), filename, (char *) buffer);
+  }
+#endif
+}
+
+void *
+gdb_dlsym (void *handle, const char *symbol)
+{
+#ifdef HAVE_DLFCN_H
+  return dlsym (handle, symbol);
+#elif __MINGW32__
+  return (void *) GetProcAddress (handle, symbol);
+#endif
+}
+
+int
+gdb_dlclose (void *handle)
+{
+#ifdef HAVE_DLFCN_H
+  return dlclose (handle);
+#elif __MINGW32__
+  return !((int) FreeLibrary (handle));
+#endif
+}
+
+static void
+do_dlclose_cleanup (void *handle)
+{
+  gdb_dlclose (handle);
+}
+
+struct cleanup *
+make_cleanup_dlclose (void *handle)
+{
+  return make_cleanup (do_dlclose_cleanup, handle);
+}
diff --git a/gdb/gdb-dlfcn.h b/gdb/gdb-dlfcn.h
new file mode 100644
index 0000000..e87672a
--- /dev/null
+++ b/gdb/gdb-dlfcn.h
@@ -0,0 +1,46 @@
+/* Platform independent shared object routines for GDB.
+
+   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_DLFCN_H
+#define GDB_DLFCN_H
+
+#include "defs.h"
+
+/* Load the dynamic library file named FILENAME, and return a handle
+   for that dynamic library.  Return NULL if the loading fails for any
+   reason.  */
+
+void *gdb_dlopen (const char *filename);
+
+/* Return the address of the symbol named SYMBOL inside the shared
+   library whose handle is HANDLE.  Return NULL when the symbol could
+   not be found.  */
+
+void *gdb_dlsym (void *handle, const char *symbol);
+
+/* Install a cleanup routine which closes the handle HANDLE.  */
+
+struct cleanup *make_cleanup_dlclose (void *handle);
+
+/* Cleanup the shared object pointed to by HANDLE. Return 0 on success
+   and nonzero on failure.  */
+
+int gdb_dlclose (void *handle);
+
+#endif /* GDB_DLFCN_H */
-- 
1.7.5.4


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

* [PATCH 3/7] Platform agnostic dynamic loading code.
       [not found] ` <1314518609-10204-1-git-send-email-sanjoy@playingwithpointers.com>
@ 2011-08-28  8:04   ` Sanjoy Das
  0 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-28  8:04 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

gdb-dlfcn.h and gdb-dlfcn.c are added, which implement the (cross
platform) functions gdb_dlopen, gdb_dlsym and gdb_dlclose. They should
work correctly on POSIX and windows systems.

gdb/ChangeLog:
	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
	system.
	* gdb/config.in: Add new #define HAVE_LIBDL.
	* gdb/configure.ac: Add check for -ldl.
	* gdb/configure: Re-generated by autoconf.
---
 gdb/ChangeLog    |    8 ++++
 gdb/Makefile.in  |    6 ++--
 gdb/config.in    |    3 ++
 gdb/configure    |   46 ++++++++++++++++++++++++++
 gdb/configure.ac |    2 +
 gdb/gdb-dlfcn.c  |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb-dlfcn.h  |   46 ++++++++++++++++++++++++++
 7 files changed, 203 insertions(+), 3 deletions(-)
 create mode 100644 gdb/gdb-dlfcn.c
 create mode 100644 gdb/gdb-dlfcn.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3196016..3536807 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2011-08-27  Sanjoy Das  <sdas@igalia.com>
 
+	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
+	system.
+	* gdb/config.in: Add new #define HAVE_LIBDL.
+	* gdb/configure.ac: Add check for -ldl.
+	* gdb/configure: Re-generated by autoconf.
+
+2011-08-27  Sanjoy Das  <sdas@igalia.com>
+
 	* gdb/config.in: Add new #defines: JIT_READER_DIR and
 	JIT_READER_DIR_RELOCATABLE.
 	* gdb/configure.ac: New GDB directory entry for jit-reader-dir.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index b277597..732b8f0 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -739,7 +739,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \
 	regset.c sol-thread.c windows-termcap.c \
 	common/common-utils.c common/xml-utils.c \
-	common/ptid.c common/buffer.c
+	common/ptid.c common/buffer.c gdb-dlfcn.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -820,7 +820,7 @@ 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 \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h
+common/linux-osdata.h gdb-dlfcn.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o gcore.o \
 	jit.o progspace.o \
-	common-utils.o buffer.o ptid.o
+	common-utils.o buffer.o ptid.o gdb-dlfcn.o
 
 TSOBS = inflow.o
 
diff --git a/gdb/config.in b/gdb/config.in
index 27a4e2c..65945cb 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -988,3 +988,6 @@
 
 /* Define if JIT_READER_DIR should be relocated when GDB is moved.  */
 #undef JIT_READER_DIR_RELOCATABLE
+
+/* Define if -ldl will work.  */
+#undef HAVE_LIBDL
diff --git a/gdb/configure b/gdb/configure
index c6dfbf7..b7753bf 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9934,6 +9934,52 @@ fi
 ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+
 
 
 # Check whether --with-jit-reader-dir was given.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index ee73e9b..0ce5ac0 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -595,6 +595,8 @@ fi
 AC_SUBST(TARGET_PTR)
 AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
 
+AC_CHECK_LIB([dl], [dlopen], [], [], [])
+
 GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
                 [directory to load the JIT readers from],
                 [${libdir}/gdb])
diff --git a/gdb/gdb-dlfcn.c b/gdb/gdb-dlfcn.c
new file mode 100644
index 0000000..34c58d7
--- /dev/null
+++ b/gdb/gdb-dlfcn.c
@@ -0,0 +1,95 @@
+/* Platform independent shared object routines for GDB.
+
+   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/>.  */
+
+#include "gdb-dlfcn.h"
+
+#include "defs.h"
+
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
+#elif __MINGW32__
+#include <windows.h>
+#else
+/* Unsupported configuration.  See Eg. gdb_dlopen for details.  */
+#error API to load shared library missing (Eg. libdl)
+#endif
+
+void *
+gdb_dlopen (const char *filename)
+{
+  void *result;
+#ifdef HAVE_LIBDL
+  result = dlopen (filename, RTLD_NOW);
+#elif __MINGW32__
+  result = (void *) LoadLibrary (filename);
+#endif
+  if (result != NULL)
+    return result;
+
+#ifdef HAVE_LIBDL
+  error (_("Could not load %s: %s"), filename, dlerror());
+#else
+  {
+    LPVOID buffer;
+    DWORD dw;
+
+    dw = GetLastError();
+
+    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                   FORMAT_MESSAGE_IGNORE_INSERTS,
+                   NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   (LPTSTR) &buffer
+                   0, NULL);
+
+    error (_("Could not load %s: %s"), filename, (char *) buffer);
+  }
+#endif
+}
+
+void *
+gdb_dlsym (void *handle, const char *symbol)
+{
+#ifdef HAVE_LIBDL
+  return dlsym (handle, symbol);
+#elif __MINGW32__
+  return (void *) GetProcAddress (handle, symbol);
+#endif
+}
+
+int
+gdb_dlclose (void *handle)
+{
+#ifdef HAVE_LIBDL
+  return dlclose (handle);
+#elif __MINGW32__
+  return !((int) FreeLibrary (handle));
+#endif
+}
+
+static void
+do_dlclose_cleanup (void *handle)
+{
+  gdb_dlclose (handle);
+}
+
+struct cleanup *
+make_cleanup_dlclose (void *handle)
+{
+  return make_cleanup (do_dlclose_cleanup, handle);
+}
diff --git a/gdb/gdb-dlfcn.h b/gdb/gdb-dlfcn.h
new file mode 100644
index 0000000..e87672a
--- /dev/null
+++ b/gdb/gdb-dlfcn.h
@@ -0,0 +1,46 @@
+/* Platform independent shared object routines for GDB.
+
+   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_DLFCN_H
+#define GDB_DLFCN_H
+
+#include "defs.h"
+
+/* Load the dynamic library file named FILENAME, and return a handle
+   for that dynamic library.  Return NULL if the loading fails for any
+   reason.  */
+
+void *gdb_dlopen (const char *filename);
+
+/* Return the address of the symbol named SYMBOL inside the shared
+   library whose handle is HANDLE.  Return NULL when the symbol could
+   not be found.  */
+
+void *gdb_dlsym (void *handle, const char *symbol);
+
+/* Install a cleanup routine which closes the handle HANDLE.  */
+
+struct cleanup *make_cleanup_dlclose (void *handle);
+
+/* Cleanup the shared object pointed to by HANDLE. Return 0 on success
+   and nonzero on failure.  */
+
+int gdb_dlclose (void *handle);
+
+#endif /* GDB_DLFCN_H */
-- 
1.7.5.4


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

* [PATCH 3/7] Platform agnostic dynamic loading code.
  2011-08-27 13:08 JIT Debug Info Reader Sanjoy Das
@ 2011-08-27 13:08 ` Sanjoy Das
  0 siblings, 0 replies; 20+ messages in thread
From: Sanjoy Das @ 2011-08-27 13:08 UTC (permalink / raw)
  To: gdb-patches; +Cc: Sanjoy Das

gdb-dlfcn.h and gdb-dlfcn.c are added, which implement the (cross
platform) functions gdb_dlopen, gdb_dlsym and gdb_dlclose. They should
work correctly on POSIX and windows systems.

gdb/ChangeLog:
	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
	system.
	* gdb/config.in: Add new #define HAVE_LIBDL.
	* gdb/configure.ac: Add check for -ldl.
	* gdb/configure: Re-generated by autoconf.
---
 gdb/ChangeLog    |    8 ++++
 gdb/Makefile.in  |    6 ++--
 gdb/config.in    |    3 ++
 gdb/configure    |   46 ++++++++++++++++++++++++++
 gdb/configure.ac |    2 +
 gdb/gdb-dlfcn.c  |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb-dlfcn.h  |   46 ++++++++++++++++++++++++++
 7 files changed, 203 insertions(+), 3 deletions(-)
 create mode 100644 gdb/gdb-dlfcn.c
 create mode 100644 gdb/gdb-dlfcn.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3196016..3536807 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2011-08-27  Sanjoy Das  <sdas@igalia.com>
 
+	* gdb/Makefile.in: Add gdb-dlfcn.c and gdb-dlfcn.h to build
+	system.
+	* gdb/config.in: Add new #define HAVE_LIBDL.
+	* gdb/configure.ac: Add check for -ldl.
+	* gdb/configure: Re-generated by autoconf.
+
+2011-08-27  Sanjoy Das  <sdas@igalia.com>
+
 	* gdb/config.in: Add new #defines: JIT_READER_DIR and
 	JIT_READER_DIR_RELOCATABLE.
 	* gdb/configure.ac: New GDB directory entry for jit-reader-dir.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index b277597..732b8f0 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -739,7 +739,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \
 	regset.c sol-thread.c windows-termcap.c \
 	common/common-utils.c common/xml-utils.c \
-	common/ptid.c common/buffer.c
+	common/ptid.c common/buffer.c gdb-dlfcn.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -820,7 +820,7 @@ 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 \
 common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
-common/linux-osdata.h
+common/linux-osdata.h gdb-dlfcn.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o gdb_usleep.o record.o gcore.o \
 	jit.o progspace.o \
-	common-utils.o buffer.o ptid.o
+	common-utils.o buffer.o ptid.o gdb-dlfcn.o
 
 TSOBS = inflow.o
 
diff --git a/gdb/config.in b/gdb/config.in
index b1aef82..89c0eb4 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -988,3 +988,6 @@
 
 /* Define if JIT_READER_DIR should be relocated when GDB is moved. */
 #undef JIT_READER_DIR_RELOCATABLE
+
+/* Define if -ldl will work. */
+#undef HAVE_LIBDL
diff --git a/gdb/configure b/gdb/configure
index c6dfbf7..b7753bf 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9934,6 +9934,52 @@ fi
 ac_config_files="$ac_config_files jit-reader.h:jit-reader.in"
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+
 
 
 # Check whether --with-jit-reader-dir was given.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index ee73e9b..0ce5ac0 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -595,6 +595,8 @@ fi
 AC_SUBST(TARGET_PTR)
 AC_CONFIG_FILES([jit-reader.h:jit-reader.in])
 
+AC_CHECK_LIB([dl], [dlopen], [], [], [])
+
 GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
                 [directory to load the JIT readers from],
                 [${libdir}/gdb])
diff --git a/gdb/gdb-dlfcn.c b/gdb/gdb-dlfcn.c
new file mode 100644
index 0000000..34c58d7
--- /dev/null
+++ b/gdb/gdb-dlfcn.c
@@ -0,0 +1,95 @@
+/* Platform independent shared object routines for GDB.
+
+   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/>.  */
+
+#include "gdb-dlfcn.h"
+
+#include "defs.h"
+
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
+#elif __MINGW32__
+#include <windows.h>
+#else
+/* Unsupported configuration.  See Eg. gdb_dlopen for details.  */
+#error API to load shared library missing (Eg. libdl)
+#endif
+
+void *
+gdb_dlopen (const char *filename)
+{
+  void *result;
+#ifdef HAVE_LIBDL
+  result = dlopen (filename, RTLD_NOW);
+#elif __MINGW32__
+  result = (void *) LoadLibrary (filename);
+#endif
+  if (result != NULL)
+    return result;
+
+#ifdef HAVE_LIBDL
+  error (_("Could not load %s: %s"), filename, dlerror());
+#else
+  {
+    LPVOID buffer;
+    DWORD dw;
+
+    dw = GetLastError();
+
+    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                   FORMAT_MESSAGE_IGNORE_INSERTS,
+                   NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   (LPTSTR) &buffer
+                   0, NULL);
+
+    error (_("Could not load %s: %s"), filename, (char *) buffer);
+  }
+#endif
+}
+
+void *
+gdb_dlsym (void *handle, const char *symbol)
+{
+#ifdef HAVE_LIBDL
+  return dlsym (handle, symbol);
+#elif __MINGW32__
+  return (void *) GetProcAddress (handle, symbol);
+#endif
+}
+
+int
+gdb_dlclose (void *handle)
+{
+#ifdef HAVE_LIBDL
+  return dlclose (handle);
+#elif __MINGW32__
+  return !((int) FreeLibrary (handle));
+#endif
+}
+
+static void
+do_dlclose_cleanup (void *handle)
+{
+  gdb_dlclose (handle);
+}
+
+struct cleanup *
+make_cleanup_dlclose (void *handle)
+{
+  return make_cleanup (do_dlclose_cleanup, handle);
+}
diff --git a/gdb/gdb-dlfcn.h b/gdb/gdb-dlfcn.h
new file mode 100644
index 0000000..df6c05c
--- /dev/null
+++ b/gdb/gdb-dlfcn.h
@@ -0,0 +1,46 @@
+/* Platform independent shared object routines for GDB.
+
+   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_DLFCN_H
+#define GDB_DLFCN_H
+
+#include "defs.h"
+
+/* Load the dynamic library file named FILENAME, and return a handle
+   for that dynamic library. Return NULL if the loading fails for any
+   reason.  */
+
+void *gdb_dlopen (const char *filename);
+
+/* Return the address of the symbol named SYMBOL inside the shared
+   library whose handle is HANDLE. Return NULL when the symbol could
+   not be found. */
+
+void *gdb_dlsym (void *handle, const char *symbol);
+
+/* Install a cleanup routine which closes the handle HANDLE. */
+
+struct cleanup *make_cleanup_dlclose (void *handle);
+
+/* Cleanup the shared object pointed to by HANDLE. Return 0 on success
+   and nonzero on failure. */
+
+int gdb_dlclose (void *handle);
+
+#endif /* GDB_DLFCN_H */
-- 
1.7.5.4


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

end of thread, other threads:[~2011-08-31  4:01 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-24 18:57 JIT Debug Info Reader (re-roll) Sanjoy Das
2011-08-24 18:57 ` [PATCH 2/7] Relocatable directory for loading JIT readers Sanjoy Das
2011-08-24 18:57 ` [PATCH 6/7] New JIT unwinder Sanjoy Das
2011-08-24 19:04   ` Jan Kratochvil
2011-08-24 19:08     ` Sanjoy Das
2011-08-24 18:57 ` [PATCH 7/7] Documentation Sanjoy Das
2011-08-24 20:14   ` Eli Zaretskii
2011-08-24 18:57 ` [PATCH 5/7] Use the loaded reader Sanjoy Das
2011-08-24 18:57 ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
2011-08-29 10:03   ` Pedro Alves
2011-08-29 12:54     ` Sanjoy Das
2011-08-29 14:22       ` Pedro Alves
2011-08-30  6:01         ` Sanjoy Das
2011-08-30 18:40           ` Tom Tromey
2011-08-24 18:57 ` [PATCH 1/7] Introduce jit-reader.in and modify build system Sanjoy Das
2011-08-24 18:57 ` [PATCH 4/7] New commands for loading and unloading a reader Sanjoy Das
2011-08-27 13:08 JIT Debug Info Reader Sanjoy Das
2011-08-27 13:08 ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
2011-08-27 13:08 [PATCH 6/7] New JIT unwinder Sanjoy Das
     [not found] ` <1314518609-10204-1-git-send-email-sanjoy@playingwithpointers.com>
2011-08-28  8:04   ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
2011-08-31  3:31 JIT Reader (re-roll) Sanjoy Das
2011-08-31  3:31 ` [PATCH 3/7] Platform agnostic dynamic loading code Sanjoy Das
2011-08-31  4:01   ` Sanjoy Das

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox