/* Handle JIT code generation in the inferior for GDB, the GNU Debugger.
- Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2009-2012 Free Software Foundation, Inc.
This file is part of GDB.
#include "inferior.h"
#include "observer.h"
#include "objfiles.h"
+#include "regcache.h"
#include "symfile.h"
#include "symtab.h"
#include "target.h"
#include "gdb-dlfcn.h"
#include "gdb_stat.h"
#include "exceptions.h"
+#include "gdb_bfd.h"
static const char *jit_reader_dir = 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;
+static unsigned int jit_debug = 0;
static void
show_jit_debug (struct ui_file *file, int from_tty,
return 0;
}
+/* Open a BFD from the target's memory. */
+
+static struct bfd *
+bfd_open_from_target_memory (CORE_ADDR addr, ULONGEST size, char *target)
+{
+ struct target_buffer *buffer = xmalloc (sizeof (struct target_buffer));
+
+ buffer->base = addr;
+ buffer->size = size;
+ return gdb_bfd_openr_iovec ("<in-memory>", target,
+ mem_bfd_iovec_open,
+ buffer,
+ mem_bfd_iovec_pread,
+ mem_bfd_iovec_close,
+ mem_bfd_iovec_stat);
+}
+
/* One reader that has been loaded successfully, and can potentially be used to
parse debug info. */
jit_reader_load_command (char *args, int from_tty)
{
char *so_name;
- int len;
struct cleanup *prev_cleanup;
if (args == NULL)
loaded_jit_reader = NULL;
}
-/* Open a BFD from the target's memory. */
+/* Per-inferior structure recording which objfile has the JIT
+ symbols. */
-static struct bfd *
-bfd_open_from_target_memory (CORE_ADDR addr, ULONGEST size, char *target)
+struct jit_inferior_data
{
- const char *filename = xstrdup ("<in-memory>");
- struct target_buffer *buffer = xmalloc (sizeof (struct target_buffer));
+ /* The objfile. This is NULL if no objfile holds the JIT
+ symbols. */
- buffer->base = addr;
- buffer->size = size;
- return bfd_openr_iovec (filename, target,
- mem_bfd_iovec_open,
- buffer,
- mem_bfd_iovec_pread,
- mem_bfd_iovec_close,
- mem_bfd_iovec_stat);
-}
+ struct objfile *objfile;
+};
-/* Per-inferior structure recording the addresses in the inferior. */
+/* Per-objfile structure recording the addresses in the inferior. */
-struct jit_inferior_data
+struct jit_objfile_data
{
- CORE_ADDR breakpoint_addr; /* &__jit_debug_register_code() */
- CORE_ADDR descriptor_addr; /* &__jit_debug_descriptor */
+ /* Symbol for __jit_debug_register_code. */
+ struct minimal_symbol *register_code;
+
+ /* Symbol for __jit_debug_descriptor. */
+ struct minimal_symbol *descriptor;
+
+ /* Address of struct jit_code_entry in this objfile. */
+ CORE_ADDR addr;
};
-/* Remember a mapping from entry_addr to objfile. */
+/* Fetch the jit_objfile_data associated with OBJF. If no data exists
+ yet, make a new structure and attach it. */
+
+static struct jit_objfile_data *
+get_jit_objfile_data (struct objfile *objf)
+{
+ struct jit_objfile_data *objf_data;
+
+ objf_data = objfile_data (objf, jit_objfile_data);
+ if (objf_data == NULL)
+ {
+ objf_data = XZALLOC (struct jit_objfile_data);
+ set_objfile_data (objf, jit_objfile_data, objf_data);
+ }
+
+ return objf_data;
+}
+
+/* Remember OBJFILE has been created for struct jit_code_entry located
+ at inferior address ENTRY. */
static void
add_objfile_entry (struct objfile *objfile, CORE_ADDR entry)
{
- CORE_ADDR *entry_addr_ptr;
+ struct jit_objfile_data *objf_data;
- entry_addr_ptr = xmalloc (sizeof (CORE_ADDR));
- *entry_addr_ptr = entry;
- set_objfile_data (objfile, jit_objfile_data, entry_addr_ptr);
+ objf_data = get_jit_objfile_data (objfile);
+ objf_data->addr = entry;
}
/* Return jit_inferior_data for current inferior. Allocate if not already
}
/* Helper function for reading the global JIT descriptor from remote
- memory. */
+ memory. Returns 1 if all went well, 0 otherwise. */
-static void
+static int
jit_read_descriptor (struct gdbarch *gdbarch,
struct jit_descriptor *descriptor,
- CORE_ADDR descriptor_addr)
+ struct jit_inferior_data *inf_data)
{
int err;
struct type *ptr_type;
int desc_size;
gdb_byte *desc_buf;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ struct jit_objfile_data *objf_data;
+
+ if (inf_data->objfile == NULL)
+ return 0;
+ objf_data = get_jit_objfile_data (inf_data->objfile);
+ if (objf_data->descriptor == NULL)
+ return 0;
+
+ if (jit_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "jit_read_descriptor, descriptor_addr = %s\n",
+ paddress (gdbarch, SYMBOL_VALUE_ADDRESS (objf_data->descriptor)));
/* Figure out how big the descriptor is on the remote and how to read it. */
ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
desc_buf = alloca (desc_size);
/* Read the descriptor. */
- err = target_read_memory (descriptor_addr, desc_buf, desc_size);
+ err = target_read_memory (SYMBOL_VALUE_ADDRESS (objf_data->descriptor),
+ desc_buf, desc_size);
if (err)
- error (_("Unable to read JIT descriptor from remote memory!"));
+ {
+ printf_unfiltered (_("Unable to read JIT descriptor from "
+ "remote memory\n"));
+ return 0;
+ }
/* Fix the endianness to match the host. */
descriptor->version = extract_unsigned_integer (&desc_buf[0], 4, byte_order);
descriptor->relevant_entry = extract_typed_address (&desc_buf[8], ptr_type);
descriptor->first_entry =
extract_typed_address (&desc_buf[8 + ptr_size], ptr_type);
+
+ return 1;
}
/* Helper function for reading a JITed code entry from remote memory. */
/* Figure out how big the entry is on the remote and how to read it. */
ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
ptr_size = TYPE_LENGTH (ptr_type);
- entry_size = 3 * ptr_size + 8; /* Three pointers and one 64-bit int. */
+
+ /* Figure out where the longlong value will be. */
+ align_bytes = gdbarch_long_long_align_bit (gdbarch) / 8;
+ off = 3 * ptr_size;
+ off = (off + (align_bytes - 1)) & ~(align_bytes - 1);
+
+ entry_size = off + 8; /* Three pointers and one 64-bit int. */
entry_buf = alloca (entry_size);
/* Read the entry. */
extract_typed_address (&entry_buf[ptr_size], ptr_type);
code_entry->symfile_addr =
extract_typed_address (&entry_buf[2 * ptr_size], ptr_type);
-
- align_bytes = gdbarch_long_long_align_bit (gdbarch) / 8;
- off = 3 * ptr_size;
- off = (off + (align_bytes - 1)) & ~(align_bytes - 1);
-
code_entry->symfile_size =
extract_unsigned_integer (&entry_buf[off], 8, byte_order);
}
struct block *new_block = allocate_block (&objfile->objfile_obstack);
struct symbol *block_name = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
+ struct type *block_type = arch_type (get_objfile_arch (objfile),
+ TYPE_CODE_VOID,
+ 1,
+ "void");
BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
NULL);
SYMBOL_DOMAIN (block_name) = VAR_DOMAIN;
SYMBOL_CLASS (block_name) = LOC_BLOCK;
SYMBOL_SYMTAB (block_name) = symtab;
+ SYMBOL_TYPE (block_name) = lookup_function_type (block_type);
SYMBOL_BLOCK_VALUE (block_name) = new_block;
block_name->ginfo.name = obsavestring (gdb_block_iter->name,
block_iter = NULL;
for (i = 0; i < FIRST_LOCAL_BLOCK; i++)
{
- struct block *new_block = allocate_block (&objfile->objfile_obstack);
+ struct block *new_block;
+
+ new_block = (i == GLOBAL_BLOCK
+ ? allocate_global_block (&objfile->objfile_obstack)
+ : allocate_block (&objfile->objfile_obstack));
BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
NULL);
BLOCK_SUPERBLOCK (new_block) = block_iter;
BLOCK_END (new_block) = (CORE_ADDR) end;
BLOCKVECTOR_BLOCK (symtab->blockvector, i) = new_block;
+
+ if (i == GLOBAL_BLOCK)
+ set_block_symtab (new_block, symtab);
}
/* Fill up the superblock fields for the real blocks, using the
priv_data = cb->priv_data;
objfile = allocate_objfile (NULL, 0);
- objfile->gdbarch = target_gdbarch;
+ objfile->gdbarch = target_gdbarch ();
- objfile->msymbols = obstack_alloc (&objfile->objfile_obstack,
- sizeof (struct minimal_symbol));
- memset (objfile->msymbols, 0, sizeof (struct minimal_symbol));
+ terminate_minimal_symbol_table (objfile);
- xfree (objfile->name);
- objfile->name = xstrdup ("<< JIT compiled code >>");
+ objfile->name = "<< JIT compiled code >>";
j = NULL;
for (i = obj->symtabs; i; i = j)
xfree (obj);
}
-/* Try to read CODE_ENTRY using the loaded jit reader (if any). */
+/* Try to read CODE_ENTRY using the loaded jit reader (if any).
+ ENTRY_ADDR is the address of the struct jit_code_entry in the
+ inferior address space. */
static int
-jit_reader_try_read_symtab (struct jit_code_entry *code_entry)
+jit_reader_try_read_symtab (struct jit_code_entry *code_entry,
+ CORE_ADDR entry_addr)
{
void *gdb_mem;
int status;
- struct jit_dbg_reader *i;
jit_dbg_reader_data priv_data;
struct gdb_reader_funcs *funcs;
volatile struct gdb_exception e;
&priv_data
};
- priv_data = code_entry->symfile_addr;
+ priv_data = entry_addr;
if (!loaded_jit_reader)
return 0;
return status;
}
-/* Try to read CODE_ENTRY using BFD. */
+/* Try to read CODE_ENTRY using BFD. ENTRY_ADDR is the address of the
+ struct jit_code_entry in the inferior address space. */
static void
jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
+ CORE_ADDR entry_addr,
struct gdbarch *gdbarch)
{
bfd *nbfd;
{
printf_unfiltered (_("\
JITed symbol file is not an object file, ignoring it.\n"));
- bfd_close (nbfd);
+ gdb_bfd_unref (nbfd);
return;
}
++i;
}
- /* This call takes ownership of NBFD. It does not take ownership of SAI. */
+ /* This call does not take ownership of SAI. */
+ make_cleanup_bfd_unref (nbfd);
objfile = symbol_file_add_from_bfd (nbfd, 0, sai, OBJF_SHARED, NULL);
do_cleanups (old_cleanups);
- add_objfile_entry (objfile, code_entry->symfile_addr);
+ add_objfile_entry (objfile, entry_addr);
}
/* This function registers code associated with a JIT code entry. It uses the
paddress (gdbarch, code_entry->symfile_addr),
pulongest (code_entry->symfile_size));
- success = jit_reader_try_read_symtab (code_entry);
+ success = jit_reader_try_read_symtab (code_entry, entry_addr);
if (!success)
- jit_bfd_try_read_symtab (code_entry, gdbarch);
+ jit_bfd_try_read_symtab (code_entry, entry_addr, gdbarch);
}
/* This function unregisters JITed code and frees the corresponding
jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
{
struct objfile *objf;
- CORE_ADDR *objf_entry_addr;
ALL_OBJFILES (objf)
{
- objf_entry_addr = (CORE_ADDR *) objfile_data (objf, jit_objfile_data);
- if (objf_entry_addr != NULL && *objf_entry_addr == entry_addr)
+ struct jit_objfile_data *objf_data;
+
+ objf_data = objfile_data (objf, jit_objfile_data);
+ if (objf_data != NULL && objf_data->addr == entry_addr)
return objf;
}
return NULL;
jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
struct jit_inferior_data *inf_data)
{
- if (inf_data->breakpoint_addr == 0)
- {
- struct minimal_symbol *reg_symbol;
-
- /* Lookup the registration symbol. If it is missing, then we assume
- we are not attached to a JIT. */
- reg_symbol = lookup_minimal_symbol (jit_break_name, NULL, NULL);
- if (reg_symbol == NULL)
- return 1;
- inf_data->breakpoint_addr = SYMBOL_VALUE_ADDRESS (reg_symbol);
- if (inf_data->breakpoint_addr == 0)
- return 2;
-
- /* If we have not read the jit descriptor yet (e.g. because the JITer
- itself is in a shared library which just got loaded), do so now. */
- if (inf_data->descriptor_addr == 0)
- jit_inferior_init (gdbarch);
- }
- else
+ struct minimal_symbol *reg_symbol, *desc_symbol;
+ struct objfile *objf;
+ struct jit_objfile_data *objf_data;
+
+ if (inf_data->objfile != NULL)
return 0;
+ /* Lookup the registration symbol. If it is missing, then we assume
+ we are not attached to a JIT. */
+ reg_symbol = lookup_minimal_symbol_and_objfile (jit_break_name, &objf);
+ if (reg_symbol == NULL || SYMBOL_VALUE_ADDRESS (reg_symbol) == 0)
+ return 1;
+
+ desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, objf);
+ if (desc_symbol == NULL || SYMBOL_VALUE_ADDRESS (desc_symbol) == 0)
+ return 1;
+
+ objf_data = get_jit_objfile_data (objf);
+ objf_data->register_code = reg_symbol;
+ objf_data->descriptor = desc_symbol;
+
+ inf_data->objfile = objf;
+
+ jit_inferior_init (gdbarch);
+
if (jit_debug)
fprintf_unfiltered (gdb_stdlog,
"jit_breakpoint_re_set_internal, "
"breakpoint_addr = %s\n",
- paddress (gdbarch, inf_data->breakpoint_addr));
+ paddress (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol)));
/* Put a breakpoint in the registration symbol. */
- create_jit_event_breakpoint (gdbarch, inf_data->breakpoint_addr);
+ create_jit_event_breakpoint (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol));
return 0;
}
+/* The private data passed around in the frame unwind callback
+ functions. */
+
+struct jit_unwind_private
+{
+ /* Cached register values. See jit_frame_sniffer to see how this
+ works. */
+ struct gdb_reg_value **registers;
+
+ /* The frame being unwound. */
+ struct frame_info *this_frame;
+};
+
+/* Sets the value of a particular register in this frame. */
+
+static void
+jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int dwarf_regnum,
+ struct gdb_reg_value *value)
+{
+ struct jit_unwind_private *priv;
+ int gdb_reg;
+
+ priv = cb->priv_data;
+
+ gdb_reg = gdbarch_dwarf2_reg_to_regnum (get_frame_arch (priv->this_frame),
+ dwarf_regnum);
+ if (gdb_reg == -1)
+ {
+ if (jit_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ _("Could not recognize DWARF regnum %d"),
+ dwarf_regnum);
+ return;
+ }
+
+ gdb_assert (priv->registers);
+ priv->registers[gdb_reg] = value;
+}
+
+static void
+reg_value_free_impl (struct gdb_reg_value *value)
+{
+ xfree (value);
+}
+
+/* Get the value of register REGNUM in the previous frame. */
+
+static struct gdb_reg_value *
+jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum)
+{
+ struct jit_unwind_private *priv;
+ struct gdb_reg_value *value;
+ int gdb_reg, size;
+ struct gdbarch *frame_arch;
+
+ priv = cb->priv_data;
+ frame_arch = get_frame_arch (priv->this_frame);
+
+ gdb_reg = gdbarch_dwarf2_reg_to_regnum (frame_arch, regnum);
+ size = register_size (frame_arch, gdb_reg);
+ value = xmalloc (sizeof (struct gdb_reg_value) + size - 1);
+ value->defined = deprecated_frame_register_read (priv->this_frame, gdb_reg,
+ value->value);
+ value->size = size;
+ value->free = reg_value_free_impl;
+ return value;
+}
+
+/* gdb_reg_value has a free function, which must be called on each
+ saved register value. */
+
+static void
+jit_dealloc_cache (struct frame_info *this_frame, void *cache)
+{
+ struct jit_unwind_private *priv_data = cache;
+ struct gdbarch *frame_arch;
+ int i;
+
+ gdb_assert (priv_data->registers);
+ frame_arch = get_frame_arch (priv_data->this_frame);
+
+ for (i = 0; i < gdbarch_num_regs (frame_arch); i++)
+ if (priv_data->registers[i] && priv_data->registers[i]->free)
+ priv_data->registers[i]->free (priv_data->registers[i]);
+
+ xfree (priv_data->registers);
+ xfree (priv_data);
+}
+
+/* The frame sniffer for the pseudo unwinder.
+
+ While this is nominally a frame sniffer, in the case where the JIT
+ reader actually recognizes the frame, it does a lot more work -- it
+ unwinds the frame and saves the corresponding register values in
+ the cache. jit_frame_prev_register simply returns the saved
+ register values. */
+
+static int
+jit_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame, void **cache)
+{
+ struct jit_inferior_data *inf_data;
+ struct jit_unwind_private *priv_data;
+ struct gdb_unwind_callbacks callbacks;
+ struct gdb_reader_funcs *funcs;
+
+ inf_data = get_jit_inferior_data ();
+
+ callbacks.reg_get = jit_unwind_reg_get_impl;
+ callbacks.reg_set = jit_unwind_reg_set_impl;
+ callbacks.target_read = jit_target_read_impl;
+
+ if (loaded_jit_reader == NULL)
+ return 0;
+
+ funcs = loaded_jit_reader->functions;
+
+ gdb_assert (!*cache);
+
+ *cache = XZALLOC (struct jit_unwind_private);
+ priv_data = *cache;
+ priv_data->registers =
+ XCALLOC (gdbarch_num_regs (get_frame_arch (this_frame)),
+ struct gdb_reg_value *);
+ priv_data->this_frame = this_frame;
+
+ callbacks.priv_data = priv_data;
+
+ /* Try to coax the provided unwinder to unwind the stack */
+ if (funcs->unwind (funcs, &callbacks) == GDB_SUCCESS)
+ {
+ if (jit_debug)
+ fprintf_unfiltered (gdb_stdlog, _("Successfully unwound frame using "
+ "JIT reader.\n"));
+ return 1;
+ }
+ if (jit_debug)
+ fprintf_unfiltered (gdb_stdlog, _("Could not unwind frame using "
+ "JIT reader.\n"));
+
+ jit_dealloc_cache (this_frame, *cache);
+ *cache = NULL;
+
+ return 0;
+}
+
+
+/* The frame_id function for the pseudo unwinder. Relays the call to
+ the loaded plugin. */
+
+static void
+jit_frame_this_id (struct frame_info *this_frame, void **cache,
+ struct frame_id *this_id)
+{
+ struct jit_unwind_private private;
+ struct gdb_frame_id frame_id;
+ struct gdb_reader_funcs *funcs;
+ struct gdb_unwind_callbacks callbacks;
+
+ private.registers = NULL;
+ private.this_frame = this_frame;
+
+ /* We don't expect the frame_id function to set any registers, so we
+ set reg_set to NULL. */
+ callbacks.reg_get = jit_unwind_reg_get_impl;
+ callbacks.reg_set = NULL;
+ callbacks.target_read = jit_target_read_impl;
+ callbacks.priv_data = &private;
+
+ gdb_assert (loaded_jit_reader);
+ funcs = loaded_jit_reader->functions;
+
+ frame_id = funcs->get_frame_id (funcs, &callbacks);
+ *this_id = frame_id_build (frame_id.stack_address, frame_id.code_address);
+}
+
+/* Pseudo unwinder function. Reads the previously fetched value for
+ the register from the cache. */
+
+static struct value *
+jit_frame_prev_register (struct frame_info *this_frame, void **cache, int reg)
+{
+ struct jit_unwind_private *priv = *cache;
+ struct gdb_reg_value *value;
+
+ if (priv == NULL)
+ return frame_unwind_got_optimized (this_frame, reg);
+
+ gdb_assert (priv->registers);
+ value = priv->registers[reg];
+ if (value && value->defined)
+ return frame_unwind_got_bytes (this_frame, reg, value->value);
+ else
+ return frame_unwind_got_optimized (this_frame, reg);
+}
+
+/* Relay everything back to the unwinder registered by the JIT debug
+ info reader.*/
+
+static const struct frame_unwind jit_frame_unwind =
+{
+ NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
+ jit_frame_this_id,
+ jit_frame_prev_register,
+ NULL,
+ jit_frame_sniffer,
+ jit_dealloc_cache
+};
+
+
+/* This is the information that is stored at jit_gdbarch_data for each
+ architecture. */
+
+struct jit_gdbarch_data_type
+{
+ /* Has the (pseudo) unwinder been prepended? */
+ int unwinder_registered;
+};
+
+/* Check GDBARCH and prepend the pseudo JIT unwinder if needed. */
+
+static void
+jit_prepend_unwinder (struct gdbarch *gdbarch)
+{
+ struct jit_gdbarch_data_type *data;
+
+ data = gdbarch_data (gdbarch, jit_gdbarch_data);
+ if (!data->unwinder_registered)
+ {
+ frame_unwind_prepend_unwinder (gdbarch, &jit_frame_unwind);
+ data->unwinder_registered = 1;
+ }
+}
+
/* Register any already created translations. */
static void
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;
- if (inf_data->descriptor_addr == 0)
- {
- struct minimal_symbol *desc_symbol;
-
- /* Lookup the descriptor symbol and cache the addr. If it is
- missing, we assume we are not attached to a JIT and return early. */
- desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, NULL);
- if (desc_symbol == NULL)
- return;
-
- inf_data->descriptor_addr = SYMBOL_VALUE_ADDRESS (desc_symbol);
- if (inf_data->descriptor_addr == 0)
- return;
- }
-
- if (jit_debug)
- fprintf_unfiltered (gdb_stdlog,
- "jit_inferior_init, descriptor_addr = %s\n",
- paddress (gdbarch, inf_data->descriptor_addr));
-
/* Read the descriptor so we can check the version number and load
any already JITed functions. */
- jit_read_descriptor (gdbarch, &descriptor, inf_data->descriptor_addr);
+ if (!jit_read_descriptor (gdbarch, &descriptor, inf_data))
+ return;
/* Check that the version number agrees with that we support. */
if (descriptor.version != 1)
- error (_("Unsupported JIT protocol version in descriptor!"));
+ {
+ printf_unfiltered (_("Unsupported JIT protocol version %ld "
+ "in descriptor (expected 1)\n"),
+ (long) descriptor.version);
+ return;
+ }
/* If we've attached to a running program, we need to check the descriptor
to register any functions that were already generated. */
void
jit_inferior_created_hook (void)
{
- jit_inferior_init (target_gdbarch);
+ jit_inferior_init (target_gdbarch ());
}
/* Exported routine to call to re-set the jit breakpoints,
void
jit_breakpoint_re_set (void)
{
- jit_breakpoint_re_set_internal (target_gdbarch,
+ jit_breakpoint_re_set_internal (target_gdbarch (),
get_jit_inferior_data ());
}
-/* Reset inferior_data, so sybols will be looked up again, and jit_breakpoint
- will be reset. */
-
-static void
-jit_reset_inferior_data_and_breakpoints (void)
-{
- struct jit_inferior_data *inf_data;
-
- /* Force jit_inferior_init to re-lookup of jit symbol addresses. */
- inf_data = get_jit_inferior_data ();
- inf_data->breakpoint_addr = 0;
- inf_data->descriptor_addr = 0;
-
- /* Remove any existing JIT breakpoint(s). */
- remove_jit_event_breakpoints ();
-
- jit_inferior_init (target_gdbarch);
-}
-
-/* Wrapper to match the observer function pointer prototype. */
-
-static void
-jit_inferior_created_observer (struct target_ops *objfile, int from_tty)
-{
- jit_reset_inferior_data_and_breakpoints ();
-}
-
/* This function cleans up any code entries left over when the
inferior exits. We get left over code when the inferior exits
without unregistering its code, for example when it crashes. */
struct objfile *temp;
ALL_OBJFILES_SAFE (objf, temp)
- if (objfile_data (objf, jit_objfile_data) != NULL)
- jit_unregister_code (objf);
-}
+ {
+ struct jit_objfile_data *objf_data = objfile_data (objf,
+ jit_objfile_data);
-static void
-jit_executable_changed_observer (void)
-{
- jit_reset_inferior_data_and_breakpoints ();
+ if (objf_data != NULL && objf_data->addr != 0)
+ jit_unregister_code (objf);
+ }
}
void
struct objfile *objf;
/* Read the descriptor from remote memory. */
- jit_read_descriptor (gdbarch, &descriptor,
- get_jit_inferior_data ()->descriptor_addr);
+ if (!jit_read_descriptor (gdbarch, &descriptor, get_jit_inferior_data ()))
+ return;
entry_addr = descriptor.relevant_entry;
/* Do the corresponding action. */
static void
free_objfile_data (struct objfile *objfile, void *data)
{
+ struct jit_objfile_data *objf_data = data;
+
+ if (objf_data->register_code != NULL)
+ {
+ struct jit_inferior_data *inf_data = get_jit_inferior_data ();
+
+ if (inf_data->objfile == objfile)
+ inf_data->objfile = NULL;
+ }
+
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);
{
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."),
- _("When non-zero, JIT debugging is enabled."),
- NULL,
- show_jit_debug,
- &setdebuglist, &showdebuglist);
-
- observer_attach_inferior_created (jit_inferior_created_observer);
+ add_setshow_zuinteger_cmd ("jit", class_maintenance, &jit_debug,
+ _("Set JIT debugging."),
+ _("Show JIT debugging."),
+ _("When non-zero, JIT debugging is enabled."),
+ NULL,
+ show_jit_debug,
+ &setdebuglist, &showdebuglist);
+
observer_attach_inferior_exit (jit_inferior_exit_hook);
- observer_attach_executable_changed (jit_executable_changed_observer);
jit_objfile_data =
register_objfile_data_with_cleanup (NULL, free_objfile_data);
jit_inferior_data =
- register_inferior_data_with_cleanup (jit_inferior_data_cleanup);
+ register_inferior_data_with_cleanup (NULL, jit_inferior_data_cleanup);
+ jit_gdbarch_data = gdbarch_data_register_pre_init (jit_gdbarch_data_init);
if (is_dl_available ())
{
add_com ("jit-reader-load", no_class, jit_reader_load_command, _("\