/* Handle JIT code generation in the inferior for GDB, the GNU Debugger.
- Copyright (C) 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 2009-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdb-dlfcn.h"
#include <sys/stat.h>
#include "gdb_bfd.h"
+#include "readline/tilde.h"
+#include "completer.h"
static const char *jit_reader_dir = NULL;
static const struct program_space_data *jit_program_space_data = NULL;
static void jit_inferior_init (struct gdbarch *gdbarch);
+static void jit_inferior_exit_hook (struct inferior *inf);
/* An unwinder is registered for every gdbarch. This key is used to
remember if the unwinder has been registered for a particular
{
struct target_buffer *buffer = (struct target_buffer*) stream;
+ memset (sb, 0, sizeof (struct stat));
sb->st_size = buffer->size;
return 0;
}
/* Open a BFD from the target's memory. */
-static struct bfd *
+static gdb_bfd_ref_ptr
bfd_open_from_target_memory (CORE_ADDR addr, ULONGEST size, char *target)
{
- struct target_buffer *buffer = xmalloc (sizeof (struct target_buffer));
+ struct target_buffer *buffer = XNEW (struct target_buffer);
buffer->base = addr;
buffer->size = size;
so = gdb_dlopen (file_name);
old_cleanups = make_cleanup_dlclose (so);
- init_fn = gdb_dlsym (so, reader_init_fn_sym);
+ init_fn = (reader_init_fn_type *) gdb_dlsym (so, reader_init_fn_sym);
if (!init_fn)
error (_("Could not locate initialization function: %s."),
reader_init_fn_sym);
if (args == NULL)
error (_("No reader name provided."));
+ args = tilde_expand (args);
+ prev_cleanup = make_cleanup (xfree, args);
if (loaded_jit_reader != NULL)
error (_("JIT reader already loaded. Run jit-reader-unload first."));
if (IS_ABSOLUTE_PATH (args))
- so_name = xstrdup (args);
+ so_name = args;
else
- so_name = xstrprintf ("%s%s%s", jit_reader_dir, SLASH_STRING, args);
- prev_cleanup = make_cleanup (xfree, so_name);
+ {
+ so_name = xstrprintf ("%s%s%s", jit_reader_dir, SLASH_STRING, args);
+ make_cleanup (xfree, so_name);
+ }
loaded_jit_reader = jit_reader_load (so_name);
+ reinit_frame_cache ();
+ jit_inferior_created_hook ();
do_cleanups (prev_cleanup);
}
if (!loaded_jit_reader)
error (_("No JIT reader loaded."));
+ reinit_frame_cache ();
+ jit_inferior_exit_hook (current_inferior ());
loaded_jit_reader->functions->destroy (loaded_jit_reader->functions);
gdb_dlclose (loaded_jit_reader->handle);
{
struct jit_objfile_data *objf_data;
- objf_data = objfile_data (objf, jit_objfile_data);
+ objf_data = (struct jit_objfile_data *) objfile_data (objf, jit_objfile_data);
if (objf_data == NULL)
{
objf_data = XCNEW (struct jit_objfile_data);
{
struct jit_program_space_data *ps_data;
- ps_data = program_space_data (current_program_space, jit_program_space_data);
+ ps_data
+ = ((struct jit_program_space_data *)
+ program_space_data (current_program_space, jit_program_space_data));
if (ps_data == NULL)
{
ps_data = XCNEW (struct jit_program_space_data);
ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
ptr_size = TYPE_LENGTH (ptr_type);
desc_size = 8 + 2 * ptr_size; /* Two 32-bit ints and two pointers. */
- desc_buf = alloca (desc_size);
+ desc_buf = (gdb_byte *) alloca (desc_size);
/* Read the descriptor. */
err = target_read_memory (MSYMBOL_VALUE_ADDRESS (ps_data->objfile,
off = (off + (align_bytes - 1)) & ~(align_bytes - 1);
entry_size = off + 8; /* Three pointers and one 64-bit int. */
- entry_buf = alloca (entry_size);
+ entry_buf = (gdb_byte *) alloca (entry_size);
/* Read the entry. */
err = target_read_memory (code_addr, entry_buf, entry_size);
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);
+ int result = target_read_memory ((CORE_ADDR) target_mem,
+ (gdb_byte *) gdb_buf, len);
if (result == 0)
return GDB_SUCCESS;
else
static int
compare_block (const struct gdb_block *const old,
- const struct gdb_block *const new)
+ const struct gdb_block *const newobj)
{
if (old == NULL)
return 1;
- if (old->begin < new->begin)
+ if (old->begin < newobj->begin)
return 1;
- else if (old->begin == new->begin)
+ else if (old->begin == newobj->begin)
{
- if (old->end > new->end)
+ if (old->end > newobj->end)
return 1;
else
return 0;
struct gdb_line_mapping *map)
{
int i;
+ int alloc_len;
if (nlines < 1)
return;
- stab->linetable = xmalloc (sizeof (struct linetable)
- + (nlines - 1) * sizeof (struct linetable_entry));
+ alloc_len = sizeof (struct linetable)
+ + (nlines - 1) * sizeof (struct linetable_entry);
+ stab->linetable = (struct linetable *) xmalloc (alloc_len);
stab->linetable->nitems = nlines;
for (i = 0; i < nlines; i++)
{
* sizeof (struct linetable_entry)
+ sizeof (struct linetable));
SYMTAB_LINETABLE (COMPUNIT_FILETABS (cust))
- = obstack_alloc (&objfile->objfile_obstack, size);
+ = (struct linetable *) obstack_alloc (&objfile->objfile_obstack, size);
memcpy (SYMTAB_LINETABLE (COMPUNIT_FILETABS (cust)), stab->linetable,
size);
}
blockvector_size = (sizeof (struct blockvector)
+ (actual_nblocks - 1) * sizeof (struct block *));
- bv = obstack_alloc (&objfile->objfile_obstack, blockvector_size);
+ bv = (struct blockvector *) obstack_alloc (&objfile->objfile_obstack,
+ blockvector_size);
COMPUNIT_BLOCKVECTOR (cust) = bv;
/* (begin, end) will contain the PC range this entire blockvector
SYMBOL_TYPE (block_name) = lookup_function_type (block_type);
SYMBOL_BLOCK_VALUE (block_name) = new_block;
- block_name->ginfo.name = obstack_copy0 (&objfile->objfile_obstack,
- gdb_block_iter->name,
- strlen (gdb_block_iter->name));
+ block_name->ginfo.name
+ = (const char *) obstack_copy0 (&objfile->objfile_obstack,
+ gdb_block_iter->name,
+ strlen (gdb_block_iter->name));
BLOCK_FUNCTION (new_block) = block_name;
struct objfile *objfile;
jit_dbg_reader_data *priv_data;
- priv_data = cb->priv_data;
+ priv_data = (jit_dbg_reader_data *) cb->priv_data;
objfile = allocate_objfile (NULL, "<< JIT compiled code >>",
OBJF_NOT_FILENAME);
jit_reader_try_read_symtab (struct jit_code_entry *code_entry,
CORE_ADDR entry_addr)
{
- void *gdb_mem;
+ gdb_byte *gdb_mem;
int status;
jit_dbg_reader_data priv_data;
struct gdb_reader_funcs *funcs;
- volatile struct gdb_exception e;
struct gdb_symbol_callbacks callbacks =
{
jit_object_open_impl,
if (!loaded_jit_reader)
return 0;
- gdb_mem = xmalloc (code_entry->symfile_size);
+ gdb_mem = (gdb_byte *) xmalloc (code_entry->symfile_size);
status = 1;
- TRY_CATCH (e, RETURN_MASK_ALL)
- if (target_read_memory (code_entry->symfile_addr, gdb_mem,
- code_entry->symfile_size))
+ TRY
+ {
+ if (target_read_memory (code_entry->symfile_addr, gdb_mem,
+ code_entry->symfile_size))
+ status = 0;
+ }
+ CATCH (e, RETURN_MASK_ALL)
+ {
status = 0;
- if (e.reason < 0)
- status = 0;
+ }
+ END_CATCH
if (status)
{
CORE_ADDR entry_addr,
struct gdbarch *gdbarch)
{
- bfd *nbfd;
struct section_addr_info *sai;
struct bfd_section *sec;
struct objfile *objfile;
paddress (gdbarch, code_entry->symfile_addr),
pulongest (code_entry->symfile_size));
- nbfd = bfd_open_from_target_memory (code_entry->symfile_addr,
- code_entry->symfile_size, gnutarget);
+ gdb_bfd_ref_ptr nbfd (bfd_open_from_target_memory (code_entry->symfile_addr,
+ code_entry->symfile_size,
+ gnutarget));
if (nbfd == NULL)
{
puts_unfiltered (_("Error opening JITed symbol file, ignoring it.\n"));
/* Check the format. NOTE: This initializes important data that GDB uses!
We would segfault later without this line. */
- if (!bfd_check_format (nbfd, bfd_object))
+ if (!bfd_check_format (nbfd.get (), bfd_object))
{
printf_unfiltered (_("\
JITed symbol file is not an object file, ignoring it.\n"));
- gdb_bfd_unref (nbfd);
return;
}
/* Check bfd arch. */
b = gdbarch_bfd_arch_info (gdbarch);
- if (b->compatible (b, bfd_get_arch_info (nbfd)) != b)
+ if (b->compatible (b, bfd_get_arch_info (nbfd.get ())) != b)
warning (_("JITed object file architecture %s is not compatible "
- "with target architecture %s."), bfd_get_arch_info
- (nbfd)->printable_name, b->printable_name);
+ "with target architecture %s."),
+ bfd_get_arch_info (nbfd.get ())->printable_name,
+ b->printable_name);
/* Read the section address information out of the symbol file. Since the
file is generated by the JIT at runtime, it should all of the absolute
addresses that we care about. */
- sai = alloc_section_addr_info (bfd_count_sections (nbfd));
+ sai = alloc_section_addr_info (bfd_count_sections (nbfd.get ()));
old_cleanups = 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)
+ if ((bfd_get_section_flags (nbfd.get (), sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
{
/* We assume that these virtual addresses are absolute, and do not
treat them as offsets. */
- sai->other[i].addr = bfd_get_section_vma (nbfd, sec);
- sai->other[i].name = xstrdup (bfd_get_section_name (nbfd, sec));
+ sai->other[i].addr = bfd_get_section_vma (nbfd.get (), sec);
+ sai->other[i].name = xstrdup (bfd_get_section_name (nbfd.get (), sec));
sai->other[i].sectindex = sec->index;
++i;
}
sai->num_sections = i;
/* This call does not take ownership of SAI. */
- make_cleanup_bfd_unref (nbfd);
- objfile = symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd), 0, sai,
+ objfile = symbol_file_add_from_bfd (nbfd.get (),
+ bfd_get_filename (nbfd.get ()), 0, sai,
OBJF_SHARED | OBJF_NOT_FILENAME, NULL);
do_cleanups (old_cleanups);
{
struct jit_objfile_data *objf_data;
- objf_data = objfile_data (objf, jit_objfile_data);
+ objf_data
+ = (struct jit_objfile_data *) objfile_data (objf, jit_objfile_data);
if (objf_data != NULL && objf_data->addr == entry_addr)
return objf;
}
{
struct jit_program_space_data *ps_data;
- ps_data = program_space_data (iter->pspace, jit_program_space_data);
+ ps_data = ((struct jit_program_space_data *)
+ program_space_data (iter->pspace, jit_program_space_data));
if (ps_data != NULL && ps_data->jit_breakpoint == iter->owner)
{
ps_data->cached_code_address = 0;
}
/* (Re-)Initialize the jit breakpoint if necessary.
- Return 0 on success. */
+ Return 0 if the jit breakpoint has been successfully initialized. */
static int
jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
paddress (gdbarch, addr));
if (ps_data->cached_code_address == addr)
- return 1;
+ return 0;
/* Delete the old breakpoint. */
if (ps_data->jit_breakpoint != NULL)
{
/* Cached register values. See jit_frame_sniffer to see how this
works. */
- struct gdb_reg_value **registers;
+ struct regcache *regcache;
/* The frame being unwound. */
struct frame_info *this_frame;
struct jit_unwind_private *priv;
int gdb_reg;
- priv = cb->priv_data;
+ priv = (struct jit_unwind_private *) cb->priv_data;
gdb_reg = gdbarch_dwarf2_reg_to_regnum (get_frame_arch (priv->this_frame),
dwarf_regnum);
fprintf_unfiltered (gdb_stdlog,
_("Could not recognize DWARF regnum %d"),
dwarf_regnum);
+ value->free (value);
return;
}
- gdb_assert (priv->registers);
- priv->registers[gdb_reg] = value;
+ regcache_raw_set_cached_value (priv->regcache, gdb_reg, value->value);
+ value->free (value);
}
static void
int gdb_reg, size;
struct gdbarch *frame_arch;
- priv = cb->priv_data;
+ priv = (struct jit_unwind_private *) 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 = ((struct 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;
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]);
+ struct jit_unwind_private *priv_data = (struct jit_unwind_private *) cache;
- xfree (priv_data->registers);
+ gdb_assert (priv_data->regcache != NULL);
+ regcache_xfree (priv_data->regcache);
xfree (priv_data);
}
struct jit_unwind_private *priv_data;
struct gdb_unwind_callbacks callbacks;
struct gdb_reader_funcs *funcs;
+ struct address_space *aspace;
+ struct gdbarch *gdbarch;
callbacks.reg_get = jit_unwind_reg_get_impl;
callbacks.reg_set = jit_unwind_reg_set_impl;
gdb_assert (!*cache);
+ aspace = get_frame_address_space (this_frame);
+ gdbarch = get_frame_arch (this_frame);
+
*cache = XCNEW (struct jit_unwind_private);
- priv_data = *cache;
- priv_data->registers =
- XCNEWVEC (struct gdb_reg_value *,
- gdbarch_num_regs (get_frame_arch (this_frame)));
+ priv_data = (struct jit_unwind_private *) *cache;
+ priv_data->regcache = regcache_xmalloc (gdbarch, aspace);
priv_data->this_frame = this_frame;
callbacks.priv_data = priv_data;
jit_frame_this_id (struct frame_info *this_frame, void **cache,
struct frame_id *this_id)
{
- struct jit_unwind_private private;
+ struct jit_unwind_private priv;
struct gdb_frame_id frame_id;
struct gdb_reader_funcs *funcs;
struct gdb_unwind_callbacks callbacks;
- private.registers = NULL;
- private.this_frame = this_frame;
+ priv.regcache = NULL;
+ priv.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;
+ callbacks.priv_data = &priv;
gdb_assert (loaded_jit_reader);
funcs = loaded_jit_reader->functions;
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;
+ struct jit_unwind_private *priv = (struct jit_unwind_private *) *cache;
+ struct gdbarch *gdbarch;
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);
+ gdbarch = get_regcache_arch (priv->regcache);
+ if (reg < gdbarch_num_regs (gdbarch))
+ {
+ gdb_byte *buf = (gdb_byte *) alloca (register_size (gdbarch, reg));
+ enum register_status status;
+
+ status = regcache_raw_read (priv->regcache, reg, buf);
+ if (status == REG_VALID)
+ return frame_unwind_got_bytes (this_frame, reg, buf);
+ else
+ return frame_unwind_got_optimized (this_frame, reg);
+ }
else
- return frame_unwind_got_optimized (this_frame, reg);
+ return gdbarch_pseudo_register_read_value (gdbarch, priv->regcache, reg);
}
/* Relay everything back to the unwinder registered by the JIT debug
{
struct jit_gdbarch_data_type *data;
- data = gdbarch_data (gdbarch, jit_gdbarch_data);
+ data
+ = (struct jit_gdbarch_data_type *) gdbarch_data (gdbarch, jit_gdbarch_data);
if (!data->unwinder_registered)
{
frame_unwind_prepend_unwinder (gdbarch, &jit_frame_unwind);
}
}
+/* inferior_created observer. */
+
+static void
+jit_inferior_created (struct target_ops *ops, int from_tty)
+{
+ jit_inferior_created_hook ();
+}
+
/* Exported routine to call when an inferior has been created. */
void
ALL_OBJFILES_SAFE (objf, temp)
{
- struct jit_objfile_data *objf_data = objfile_data (objf,
- jit_objfile_data);
+ struct jit_objfile_data *objf_data
+ = (struct jit_objfile_data *) objfile_data (objf, jit_objfile_data);
if (objf_data != NULL && objf_data->addr != 0)
jit_unregister_code (objf);
static void
free_objfile_data (struct objfile *objfile, void *data)
{
- struct jit_objfile_data *objf_data = data;
+ struct jit_objfile_data *objf_data = (struct jit_objfile_data *) data;
if (objf_data->register_code != NULL)
{
struct jit_program_space_data *ps_data;
- ps_data = program_space_data (objfile->pspace, jit_program_space_data);
+ ps_data
+ = ((struct jit_program_space_data *)
+ program_space_data (objfile->pspace, jit_program_space_data));
if (ps_data != NULL && ps_data->objfile == objfile)
- ps_data->objfile = NULL;
+ {
+ ps_data->objfile = NULL;
+ delete_breakpoint (ps_data->jit_breakpoint);
+ ps_data->cached_code_address = 0;
+ }
}
xfree (data);
static void *
jit_gdbarch_data_init (struct obstack *obstack)
{
- struct jit_gdbarch_data_type *data;
+ struct jit_gdbarch_data_type *data =
+ XOBNEW (obstack, struct jit_gdbarch_data_type);
- data = obstack_alloc (obstack, sizeof (struct jit_gdbarch_data_type));
data->unwinder_registered = 0;
+
return data;
}
show_jit_debug,
&setdebuglist, &showdebuglist);
+ observer_attach_inferior_created (jit_inferior_created);
observer_attach_inferior_exit (jit_inferior_exit_hook);
observer_attach_breakpoint_deleted (jit_breakpoint_deleted);
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, _("\
+ struct cmd_list_element *c;
+
+ c = add_com ("jit-reader-load", no_class, jit_reader_load_command, _("\
Load FILE as debug info reader and unwinder for JIT compiled code.\n\
Usage: jit-reader-load FILE\n\
Try to load file FILE as a debug info reader (and unwinder) for\n\
JIT compiled code. The file is loaded from " JIT_READER_DIR ",\n\
relocated relative to the GDB executable if required."));
- add_com ("jit-reader-unload", no_class, jit_reader_unload_command, _("\
+ set_cmd_completer (c, filename_completer);
+
+ c = add_com ("jit-reader-unload", no_class,
+ jit_reader_unload_command, _("\
Unload the currently loaded JIT debug info reader.\n\
-Usage: jit-reader-unload FILE\n\n\
+Usage: jit-reader-unload\n\n\
Do \"help jit-reader-load\" for info on loading debug info readers."));
+ set_cmd_completer (c, noop_completer);
}
}