/* Handle JIT code generation in the inferior for GDB, the GNU Debugger.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2009-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "symfile.h"
#include "symtab.h"
#include "target.h"
-#include "gdb-dlfcn.h"
+#include "gdbsupport/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 std::string jit_reader_dir;
static const struct objfile_data *jit_objfile_data;
static const char *const jit_descriptor_name = "__jit_debug_descriptor";
-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);
ULONGEST size;
};
-/* Openning the file is a no-op. */
+/* Opening the file is a no-op. */
static void *
mem_bfd_iovec_open (struct bfd *abfd, void *open_closure)
static file_ptr
mem_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf,
- file_ptr nbytes, file_ptr offset)
+ file_ptr nbytes, file_ptr offset)
{
int err;
struct target_buffer *buffer = (struct target_buffer *) stream;
if (jit_debug)
fprintf_unfiltered (gdb_stdlog, _("Opening shared object %s.\n"),
- file_name);
+ file_name);
gdb_dlhandle_up so = gdb_dlopen (file_name);
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);
+ reader_init_fn_sym);
if (gdb_dlsym (so, "plugin_is_GPL_compatible") == NULL)
error (_("Reader not GPL compatible."));
error (_("JIT reader already loaded. Run jit-reader-unload first."));
if (!IS_ABSOLUTE_PATH (file.get ()))
- file.reset (xstrprintf ("%s%s%s", jit_reader_dir, SLASH_STRING,
+ file.reset (xstrprintf ("%s%s%s", jit_reader_dir.c_str (), SLASH_STRING,
file.get ()));
loaded_jit_reader = jit_reader_load (file.get ());
/* The objfile. This is NULL if no objfile holds the JIT
symbols. */
- struct objfile *objfile;
+ struct objfile *objfile = nullptr;
/* If this program space has __jit_debug_register_code, this is the
cached address from the minimal symbol. This is used to detect
relocations requiring the breakpoint to be re-created. */
- CORE_ADDR cached_code_address;
+ CORE_ADDR cached_code_address = 0;
/* This is the JIT event breakpoint, or NULL if it has not been
set. */
- struct breakpoint *jit_breakpoint;
+ struct breakpoint *jit_breakpoint = nullptr;
};
+static program_space_key<jit_program_space_data> jit_program_space_key;
+
/* Per-objfile structure recording the addresses in the program space.
This object serves two purposes: for ordinary objfiles, it may
cache some symbols related to the JIT interface; and for
if not already present. */
static struct jit_program_space_data *
-get_jit_program_space_data (void)
+get_jit_program_space_data ()
{
struct jit_program_space_data *ps_data;
- ps_data
- = ((struct jit_program_space_data *)
- program_space_data (current_program_space, jit_program_space_data));
+ ps_data = jit_program_space_key.get (current_program_space);
if (ps_data == NULL)
- {
- ps_data = XCNEW (struct jit_program_space_data);
- set_program_space_data (current_program_space, jit_program_space_data,
- ps_data);
- }
-
+ ps_data = jit_program_space_key.emplace (current_program_space);
return ps_data;
}
-static void
-jit_program_space_data_cleanup (struct program_space *ps, void *arg)
-{
- xfree (arg);
-}
-
/* Helper function for reading the global JIT descriptor from remote
memory. Returns 1 if all went well, 0 otherwise. */
ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
ptr_size = TYPE_LENGTH (ptr_type);
- /* Figure out where the longlong value will be. */
- align_bytes = gdbarch_long_long_align_bit (gdbarch) / 8;
+ /* Figure out where the uint64_t value will be. */
+ align_bytes = type_align (builtin_type (gdbarch)->builtin_uint64);
off = 3 * ptr_size;
off = (off + (align_bytes - 1)) & ~(align_bytes - 1);
static struct gdb_symtab *
jit_symtab_open_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_object *object,
- const char *file_name)
+ struct gdb_object *object,
+ const char *file_name)
{
struct gdb_symtab *ret;
static int
compare_block (const struct gdb_block *const old,
- const struct gdb_block *const newobj)
+ const struct gdb_block *const newobj)
{
if (old == NULL)
return 1;
else if (old->begin == newobj->begin)
{
if (old->end > newobj->end)
- return 1;
+ return 1;
else
- return 0;
+ return 0;
}
else
return 0;
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_symtab *symtab, struct gdb_block *parent,
+ GDB_CORE_ADDR begin, GDB_CORE_ADDR end, const char *name)
{
struct gdb_block *block = XCNEW (struct gdb_block);
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;
- }
- }
+ {
+ /* 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++;
static void
jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_symtab *stab, int nlines,
- struct gdb_line_mapping *map)
+ struct gdb_symtab *stab, int nlines,
+ struct gdb_line_mapping *map)
{
int i;
int alloc_len;
static void
jit_symtab_close_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_symtab *stab)
+ struct gdb_symtab *stab)
{
/* Right now nothing needs to be done here. We may need to do some
cleanup here in the future (again, without breaking the plugin
size_t blockvector_size;
CORE_ADDR begin, end;
struct blockvector *bv;
- enum language language;
actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
cust = allocate_compunit_symtab (objfile, stab->file_name);
allocate_symtab (cust, stab->file_name);
add_compunit_symtab_to_objfile (cust);
- language = compunit_language (cust);
/* JIT compilers compile in memory. */
COMPUNIT_DIRNAME (cust) = NULL;
}
blockvector_size = (sizeof (struct blockvector)
- + (actual_nblocks - 1) * sizeof (struct block *));
+ + (actual_nblocks - 1) * sizeof (struct block *));
bv = (struct blockvector *) obstack_alloc (&objfile->objfile_obstack,
blockvector_size);
COMPUNIT_BLOCKVECTOR (cust) = bv;
TARGET_CHAR_BIT,
"void");
- BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
- language, NULL);
+ BLOCK_MULTIDICT (new_block)
+ = mdict_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;
SYMBOL_TYPE (block_name) = lookup_function_type (block_type);
SYMBOL_BLOCK_VALUE (block_name) = new_block;
- block_name->ginfo.name
- = (const char *) obstack_copy0 (&objfile->objfile_obstack,
- gdb_block_iter->name,
- strlen (gdb_block_iter->name));
+ block_name->name = obstack_strdup (&objfile->objfile_obstack,
+ gdb_block_iter->name);
BLOCK_FUNCTION (new_block) = block_name;
BLOCKVECTOR_BLOCK (bv, i) = new_block;
if (begin > BLOCK_START (new_block))
- begin = BLOCK_START (new_block);
+ begin = BLOCK_START (new_block);
if (end < BLOCK_END (new_block))
- end = BLOCK_END (new_block);
+ end = BLOCK_END (new_block);
gdb_block_iter->real_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,
- language, NULL);
+ BLOCK_MULTIDICT (new_block)
+ = mdict_create_linear (&objfile->objfile_obstack, NULL);
BLOCK_SUPERBLOCK (new_block) = block_iter;
block_iter = new_block;
static void
jit_object_close_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_object *obj)
+ struct gdb_object *obj)
{
struct gdb_symtab *i, *j;
struct objfile *objfile;
priv_data = (jit_dbg_reader_data *) cb->priv_data;
- objfile = new struct objfile (NULL, "<< JIT compiled code >>",
- OBJF_NOT_FILENAME);
+ objfile = objfile::make (nullptr, "<< JIT compiled code >>",
+ OBJF_NOT_FILENAME);
objfile->per_bfd->gdbarch = target_gdbarch ();
- terminate_minimal_symbol_table (objfile);
-
j = NULL;
for (i = obj->symtabs; i; i = j)
{
static int
jit_reader_try_read_symtab (struct jit_code_entry *code_entry,
- CORE_ADDR entry_addr)
+ CORE_ADDR entry_addr)
{
- gdb_byte *gdb_mem;
int status;
jit_dbg_reader_data priv_data;
struct gdb_reader_funcs *funcs;
if (!loaded_jit_reader)
return 0;
- gdb_mem = (gdb_byte *) xmalloc (code_entry->symfile_size);
+ gdb::byte_vector gdb_mem (code_entry->symfile_size);
status = 1;
- TRY
+ try
{
- if (target_read_memory (code_entry->symfile_addr, gdb_mem,
+ if (target_read_memory (code_entry->symfile_addr, gdb_mem.data (),
code_entry->symfile_size))
status = 0;
}
- CATCH (e, RETURN_MASK_ALL)
+ catch (const gdb_exception &e)
{
status = 0;
}
- END_CATCH
if (status)
{
funcs = loaded_jit_reader->functions;
- if (funcs->read (funcs, &callbacks, gdb_mem, code_entry->symfile_size)
- != GDB_SUCCESS)
- status = 0;
+ if (funcs->read (funcs, &callbacks, gdb_mem.data (),
+ code_entry->symfile_size)
+ != GDB_SUCCESS)
+ status = 0;
}
- xfree (gdb_mem);
if (jit_debug && status == 0)
fprintf_unfiltered (gdb_stdlog,
- "Could not read symtab using the loaded JIT reader.\n");
+ "Could not read symtab using the loaded JIT reader.\n");
return status;
}
static void
jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
- CORE_ADDR entry_addr,
- struct gdbarch *gdbarch)
+ CORE_ADDR entry_addr,
+ struct gdbarch *gdbarch)
{
struct bfd_section *sec;
struct objfile *objfile;
if (jit_debug)
fprintf_unfiltered (gdb_stdlog,
- "jit_register_code, symfile_addr = %s, "
+ "jit_bfd_try_read_symtab, symfile_addr = %s, "
"symfile_size = %s\n",
paddress (gdbarch, code_entry->symfile_addr),
pulongest (code_entry->symfile_size));
b = gdbarch_bfd_arch_info (gdbarch);
if (b->compatible (b, bfd_get_arch_info (nbfd.get ())) != b)
warning (_("JITed object file architecture %s is not compatible "
- "with target architecture %s."),
+ "with target architecture %s."),
bfd_get_arch_info (nbfd.get ())->printable_name,
b->printable_name);
addresses that we care about. */
section_addr_info sai;
for (sec = nbfd->sections; sec != NULL; sec = sec->next)
- if ((bfd_get_section_flags (nbfd.get (), sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
+ if ((bfd_section_flags (sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
{
- /* We assume that these virtual addresses are absolute, and do not
- treat them as offsets. */
- sai.emplace_back (bfd_get_section_vma (nbfd.get (), sec),
- bfd_get_section_name (nbfd.get (), sec),
+ /* We assume that these virtual addresses are absolute, and do not
+ treat them as offsets. */
+ sai.emplace_back (bfd_section_vma (sec),
+ bfd_section_name (sec),
sec->index);
}
static void
jit_register_code (struct gdbarch *gdbarch,
- CORE_ADDR entry_addr, struct jit_code_entry *code_entry)
+ CORE_ADDR entry_addr, struct jit_code_entry *code_entry)
{
int success;
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));
+ "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, entry_addr);
jit_bfd_try_read_symtab (code_entry, entry_addr, gdbarch);
}
-/* This function unregisters JITed code and frees the corresponding
- objfile. */
-
-static void
-jit_unregister_code (struct objfile *objfile)
-{
- delete objfile;
-}
-
/* Look up the objfile with this code entry address. */
static struct objfile *
jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
{
- struct objfile *objf;
-
- ALL_OBJFILES (objf)
+ for (objfile *objf : current_program_space->objfiles ())
{
struct jit_objfile_data *objf_data;
objf_data
= (struct jit_objfile_data *) objfile_data (objf, jit_objfile_data);
if (objf_data != NULL && objf_data->addr == entry_addr)
- return objf;
+ return objf;
}
return NULL;
}
{
struct jit_program_space_data *ps_data;
- ps_data = ((struct jit_program_space_data *)
- program_space_data (iter->pspace, jit_program_space_data));
+ ps_data = jit_program_space_key.get (iter->pspace);
if (ps_data != NULL && ps_data->jit_breakpoint == iter->owner)
{
ps_data->cached_code_address = 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);
+ reg_symbol = lookup_bound_minimal_symbol (jit_break_name);
if (reg_symbol.minsym == NULL
|| BMSYMBOL_VALUE_ADDRESS (reg_symbol) == 0)
return 1;
static void
jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int dwarf_regnum,
- struct gdb_reg_value *value)
+ struct gdb_reg_value *value)
{
struct jit_unwind_private *priv;
int gdb_reg;
priv = (struct jit_unwind_private *) cb->priv_data;
gdb_reg = gdbarch_dwarf2_reg_to_regnum (get_frame_arch (priv->this_frame),
- dwarf_regnum);
+ dwarf_regnum);
if (gdb_reg == -1)
{
if (jit_debug)
- fprintf_unfiltered (gdb_stdlog,
- _("Could not recognize DWARF regnum %d"),
- dwarf_regnum);
+ fprintf_unfiltered (gdb_stdlog,
+ _("Could not recognize DWARF regnum %d"),
+ dwarf_regnum);
value->free (value);
return;
}
static int
jit_frame_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame, void **cache)
+ struct frame_info *this_frame, void **cache)
{
struct jit_unwind_private *priv_data;
struct gdb_unwind_callbacks callbacks;
if (funcs->unwind (funcs, &callbacks) == GDB_SUCCESS)
{
if (jit_debug)
- fprintf_unfiltered (gdb_stdlog, _("Successfully unwound frame using "
- "JIT reader.\n"));
+ 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 reader.\n"));
jit_dealloc_cache (this_frame, *cache);
*cache = NULL;
static void
jit_frame_this_id (struct frame_info *this_frame, void **cache,
- struct frame_id *this_id)
+ struct frame_id *this_id)
{
struct jit_unwind_private priv;
struct gdb_frame_id frame_id;
jit_read_code_entry (gdbarch, cur_entry_addr, &cur_entry);
/* This hook may be called many times during setup, so make sure we don't
- add the same symbol file twice. */
+ add the same symbol file twice. */
if (jit_find_objf_with_entry_addr (cur_entry_addr) != NULL)
- continue;
+ continue;
jit_register_code (gdbarch, cur_entry_addr, &cur_entry);
}
static void
jit_inferior_exit_hook (struct inferior *inf)
{
- struct objfile *objf;
- struct objfile *temp;
-
- ALL_OBJFILES_SAFE (objf, temp)
+ for (objfile *objf : current_program_space->objfiles_safe ())
{
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);
+ objf->unlink ();
}
}
"entry at address: %s\n"),
paddress (gdbarch, entry_addr));
else
- jit_unregister_code (objf);
+ objf->unlink ();
break;
default:
{
struct jit_program_space_data *ps_data;
- ps_data
- = ((struct jit_program_space_data *)
- program_space_data (objfile->pspace, jit_program_space_data));
+ ps_data = jit_program_space_key.get (objfile->pspace);
if (ps_data != NULL && ps_data->objfile == objfile)
{
ps_data->objfile = NULL;
- delete_breakpoint (ps_data->jit_breakpoint);
+ if (ps_data->jit_breakpoint != NULL)
+ delete_breakpoint (ps_data->jit_breakpoint);
ps_data->cached_code_address = 0;
}
}
_initialize_jit (void)
{
jit_reader_dir = relocate_gdb_directory (JIT_READER_DIR,
- JIT_READER_DIR_RELOCATABLE);
+ JIT_READER_DIR_RELOCATABLE);
add_setshow_zuinteger_cmd ("jit", class_maintenance, &jit_debug,
_("Set JIT debugging."),
_("Show JIT debugging."),
jit_objfile_data =
register_objfile_data_with_cleanup (NULL, free_objfile_data);
- jit_program_space_data =
- register_program_space_data_with_cleanup (NULL,
- jit_program_space_data_cleanup);
jit_gdbarch_data = gdbarch_data_register_pre_init (jit_gdbarch_data_init);
if (is_dl_available ())
{