[PATCH 3/7] New commands for loading and unloading a reader.

Sanjoy Das
2011-08-09T15:21:32Z

Introduces two new GDB commands - `load-jit-reader' and
`unload-jit-reader'.
---
gdb/ChangeLog | 6 +++
gdb/jit.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 125 insertions(+), 11 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 639f1f7..884b51a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2011-08-09 Sanjoy Das <sdas@igalia.com>

+ * jit.c (_initialize_jit): Add commands load-jit-reader and
+ unload-jit-reader.
+ (jit_reader_load): New function.
+
+2011-08-09 Sanjoy Das <sdas@igalia.com>
+
* gdb-dlfcn.h, gdb-dlfcn.c: New.
* Makefile.in: Add gdb_dlcfn.c and gdb_dlcfn.h to the build
system.
diff --git a/gdb/jit.c b/gdb/jit.c
index e3bb81a..3f83065 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -31,8 +31,11 @@
#include "symfile.h"
#include "symtab.h"
#include "target.h"
+#include "gdb-dlfcn.h"
#include "gdb_stat.h"

+#define GDB_READER_DIR (LIBDIR "/gdb/")
+
static const struct objfile_data *jit_objfile_data;

static const char *const jit_break_name = "__jit_debug_register_code";
@@ -113,6 +116,102 @@ 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. */
+struct jit_reader
+{
+ struct gdb_reader_funcs *functions;
+} *loaded_jit_reader = NULL;
+
+typedef struct gdb_reader_funcs * (reader_init_fn_type) (void);
+const char *reader_init_fn_sym = "gdb_init_reader";
+
+/* Try to load FILE_NAME as a JIT debug info reader. Set ERROR_STRING
+ in case of an error (and return NULL), else return a correcly
+ formed struct jit_reader. */
+static struct jit_reader *
+jit_reader_load (const char *file_name, char **error_string)
+{
+ void *so;
+ reader_init_fn_type *init_fn;
+ struct jit_reader *new_reader = NULL;
+ struct gdb_reader_funcs *funcs = NULL;
+
+ if (jit_debug)
+ fprintf_unfiltered (gdb_stdlog, "Opening shared object %s.\n", file_name);
+ so = gdb_dlopen (file_name);
+
+ if (!so)
+ {
+ *error_string = _("could not open reader file");
+ return NULL;
+ }
+
+ init_fn = gdb_dlsym (so, reader_init_fn_sym);
+ if (!init_fn)
+ {
+ *error_string = _("could not locate initialization routine");
+ goto error;
+ }
+
+ if (gdb_dlsym (so, "plugin_is_GPL_compatible") == NULL)
+ {
+ *error_string = _("reader not GPL compatible");
+ goto error;
+ }
+
+ funcs = init_fn ();
+ if (funcs->reader_version != GDB_READER_INTERFACE_VERSION)
+ {
+ *error_string = _("incorrect module version");
+ goto error;
+ }
+
+ new_reader = XZALLOC (struct jit_reader);
+ new_reader->functions = funcs;
+ return new_reader;
+
+ error:
+ if (so)
+ gdb_dlclose(so);
+ return NULL;
+}
+
+/* Provides the load-jit-reader command. */
+static void
+load_jit_reader_command (char *args, int from_tty)
+{
+ char so_name[PATH_MAX] = GDB_READER_DIR;
+ char *error_string;
+
+ if (args == NULL)
+ {
+ error (_("No reader name provided."));
+ return;
+ }
+
+ strncat (so_name, args, PATH_MAX - sizeof(GDB_READER_DIR) - 4);
+ strcat (so_name, ".so");
+
+ loaded_jit_reader = jit_reader_load (so_name, &error_string);
+ if (loaded_jit_reader == NULL)
+ error(_("Unable to load reader: %s."), error_string);
+}
+
+/* Provides the unload-jit-reader command. */
+static void
+unload_jit_reader_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 *
@@ -137,6 +236,7 @@ struct jit_inferior_data
{
CORE_ADDR breakpoint_addr; /* &__jit_debug_register_code() */
CORE_ADDR descriptor_addr; /* &__jit_debug_descriptor */
+ struct objfile *jit_objfile; /* All the JIT symbols will be added to this. */
};

/* Return jit_inferior_data for current inferior. Allocate if not already
@@ -510,10 +610,10 @@ jit_event_handler (struct gdbarch *gdbarch)
struct jit_code_entry code_entry;
CORE_ADDR entry_addr;
struct objfile *objf;
+ struct jit_inferior_data *inf_data = get_jit_inferior_data ();

/* Read the descriptor from remote memory. */
- jit_read_descriptor (gdbarch, &descriptor,
- get_jit_inferior_data ()->descriptor_addr);
+ jit_read_descriptor (gdbarch, &descriptor, inf_data->descriptor_addr);
entry_addr = descriptor.relevant_entry;

/* Do the corresponding action. */
@@ -526,15 +626,16 @@ jit_event_handler (struct gdbarch *gdbarch)
jit_register_code (gdbarch, entry_addr, &code_entry);
break;
case JIT_UNREGISTER:
- objf = jit_find_objf_with_entry_addr (entry_addr);
- if (objf == NULL)
- printf_unfiltered (_("Unable to find JITed code "
- "entry at address: %s\n"),
- paddress (gdbarch, entry_addr));
- else
- jit_unregister_code (objf);
-
- break;
+ {
+ objf = jit_find_objf_with_entry_addr (entry_addr);
+ if (objf == NULL)
+ printf_unfiltered (_("Unable to find JITed code "
+ "entry at address: %s\n"),
+ paddress (gdbarch, entry_addr));
+ else
+ jit_unregister_code (objf);
+ break;
+ }
default:
error (_("Unknown action_flag value in JIT descriptor!"));
break;
@@ -562,4 +663,11 @@ _initialize_jit (void)
jit_objfile_data = register_objfile_data ();
jit_inferior_data =
register_inferior_data_with_cleanup (jit_inferior_data_cleanup);
+ add_com ("load-jit-reader", no_class, load_jit_reader_command, _("\
+Try to load file FILE as a debug info reader (and unwinder) for\n\
+JIT compiled code from " LIBDIR "/gdb\n\
+Usage is `load-jit-reader FILE`."));
+ add_com ("unload-jit-reader", no_class, unload_jit_reader_command, _("\
+Unload the currently loaded JIT reader (loaded using load-jit-reader)\n\
+Usage is simply `unload-jit-reader`."));
}
--
1.7.5.4