X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fjit.c;h=81a2c26ccf6c59a8cffd862013faa60dfe74bd9b;hb=f99bd5f2c1e6b545a0a6cfb3b13f79deea84098e;hp=9e8f295c8137738b408969e7356f5b5b0276d5a7;hpb=e1507e953ec06f50f83f0bbc2b50a7f3b11f4022;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/jit.c b/gdb/jit.c index 9e8f295c81..81a2c26ccf 100644 --- a/gdb/jit.c +++ b/gdb/jit.c @@ -1,6 +1,6 @@ /* Handle JIT code generation in the inferior for GDB, the GNU Debugger. - Copyright (C) 2009-2012 Free Software Foundation, Inc. + Copyright (C) 2009-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -25,6 +25,7 @@ #include "breakpoint.h" #include "command.h" #include "dictionary.h" +#include "filenames.h" #include "frame-unwind.h" #include "gdbcmd.h" #include "gdbcore.h" @@ -36,9 +37,10 @@ #include "symtab.h" #include "target.h" #include "gdb-dlfcn.h" -#include "gdb_stat.h" -#include "exceptions.h" +#include #include "gdb_bfd.h" +#include "readline/tilde.h" +#include "completer.h" static const char *jit_reader_dir = NULL; @@ -48,9 +50,10 @@ static const char *const jit_break_name = "__jit_debug_register_code"; static const char *const jit_descriptor_name = "__jit_debug_descriptor"; -static const struct inferior_data *jit_inferior_data = 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 @@ -89,7 +92,9 @@ static int mem_bfd_iovec_close (struct bfd *abfd, void *stream) { xfree (stream); - return 1; + + /* Zero means success. */ + return 0; } /* For reading the file, we just need to pass through to target_read_memory and @@ -124,6 +129,7 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb) { struct target_buffer *buffer = (struct target_buffer*) stream; + memset (sb, 0, sizeof (struct stat)); sb->st_size = buffer->size; return 0; } @@ -133,7 +139,7 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb) static struct bfd * 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; @@ -174,7 +180,7 @@ jit_reader_load (const char *file_name) 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); @@ -186,7 +192,7 @@ jit_reader_load (const char *file_name) if (funcs->reader_version != GDB_READER_INTERFACE_VERSION) error (_("Reader version does not match GDB version.")); - new_reader = XZALLOC (struct jit_reader); + new_reader = XCNEW (struct jit_reader); new_reader->functions = funcs; new_reader->handle = so; @@ -204,14 +210,23 @@ jit_reader_load_command (char *args, int from_tty) 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.")); - so_name = xstrprintf ("%s/%s", jit_reader_dir, args); - prev_cleanup = make_cleanup (xfree, so_name); + if (IS_ABSOLUTE_PATH (args)) + so_name = args; + else + { + 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); } @@ -223,6 +238,8 @@ jit_reader_unload_command (char *args, int from_tty) 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); @@ -230,18 +247,33 @@ jit_reader_unload_command (char *args, int from_tty) loaded_jit_reader = NULL; } -/* Per-inferior structure recording which objfile has the JIT +/* Per-program space structure recording which objfile has the JIT symbols. */ -struct jit_inferior_data +struct jit_program_space_data { /* The objfile. This is NULL if no objfile holds the JIT symbols. */ struct objfile *objfile; + + /* 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; + + /* This is the JIT event breakpoint, or NULL if it has not been + set. */ + + struct breakpoint *jit_breakpoint; }; -/* Per-objfile structure recording the addresses in the inferior. */ +/* 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 + JIT-created objfiles, it holds some information about the + jit_code_entry. */ struct jit_objfile_data { @@ -251,7 +283,8 @@ struct jit_objfile_data /* Symbol for __jit_debug_descriptor. */ struct minimal_symbol *descriptor; - /* Address of struct jit_code_entry in this objfile. */ + /* Address of struct jit_code_entry in this objfile. This is only + non-zero for objfiles that represent code created by the JIT. */ CORE_ADDR addr; }; @@ -263,10 +296,10 @@ get_jit_objfile_data (struct objfile *objf) { 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 = XZALLOC (struct jit_objfile_data); + objf_data = XCNEW (struct jit_objfile_data); set_objfile_data (objf, jit_objfile_data, objf_data); } @@ -285,28 +318,29 @@ add_objfile_entry (struct objfile *objfile, CORE_ADDR entry) objf_data->addr = entry; } -/* Return jit_inferior_data for current inferior. Allocate if not already - present. */ +/* Return jit_program_space_data for current program space. Allocate + if not already present. */ -static struct jit_inferior_data * -get_jit_inferior_data (void) +static struct jit_program_space_data * +get_jit_program_space_data (void) { - struct inferior *inf; - struct jit_inferior_data *inf_data; + struct jit_program_space_data *ps_data; - inf = current_inferior (); - inf_data = inferior_data (inf, jit_inferior_data); - if (inf_data == NULL) + ps_data + = ((struct jit_program_space_data *) + program_space_data (current_program_space, jit_program_space_data)); + if (ps_data == NULL) { - inf_data = XZALLOC (struct jit_inferior_data); - set_inferior_data (inf, jit_inferior_data, inf_data); + ps_data = XCNEW (struct jit_program_space_data); + set_program_space_data (current_program_space, jit_program_space_data, + ps_data); } - return inf_data; + return ps_data; } static void -jit_inferior_data_cleanup (struct inferior *inf, void *arg) +jit_program_space_data_cleanup (struct program_space *ps, void *arg) { xfree (arg); } @@ -317,7 +351,7 @@ jit_inferior_data_cleanup (struct inferior *inf, void *arg) static int jit_read_descriptor (struct gdbarch *gdbarch, struct jit_descriptor *descriptor, - struct jit_inferior_data *inf_data) + struct jit_program_space_data *ps_data) { int err; struct type *ptr_type; @@ -327,25 +361,27 @@ jit_read_descriptor (struct gdbarch *gdbarch, enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct jit_objfile_data *objf_data; - if (inf_data->objfile == NULL) + if (ps_data->objfile == NULL) return 0; - objf_data = get_jit_objfile_data (inf_data->objfile); + objf_data = get_jit_objfile_data (ps_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))); + paddress (gdbarch, MSYMBOL_VALUE_ADDRESS (ps_data->objfile, + 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; 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 (SYMBOL_VALUE_ADDRESS (objf_data->descriptor), + err = target_read_memory (MSYMBOL_VALUE_ADDRESS (ps_data->objfile, + objf_data->descriptor), desc_buf, desc_size); if (err) { @@ -389,7 +425,7 @@ jit_read_code_entry (struct gdbarch *gdbarch, 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); @@ -466,7 +502,8 @@ typedef CORE_ADDR jit_dbg_reader_data; 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 @@ -483,7 +520,7 @@ jit_object_open_impl (struct gdb_symbol_callbacks *cb) /* CB is not required right now, but sometime in the future we might need a handle to it, and we'd like to do that without breaking the ABI. */ - return XZALLOC (struct gdb_object); + return XCNEW (struct gdb_object); } /* Readers call into this function to open a new gdb_symtab, which, @@ -498,7 +535,7 @@ jit_symtab_open_impl (struct gdb_symbol_callbacks *cb, /* CB stays unused. See comment in jit_object_open_impl. */ - ret = XZALLOC (struct gdb_symtab); + ret = XCNEW (struct gdb_symtab); ret->file_name = file_name ? xstrdup (file_name) : xstrdup (""); ret->next = object->symtabs; object->symtabs = ret; @@ -510,15 +547,15 @@ jit_symtab_open_impl (struct gdb_symbol_callbacks *cb, 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; @@ -536,7 +573,7 @@ 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); + struct gdb_block *block = XCNEW (struct gdb_block); block->next = symtab->blocks; block->begin = (CORE_ADDR) begin; @@ -580,12 +617,14 @@ jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb, 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++) { @@ -611,44 +650,47 @@ jit_symtab_close_impl (struct gdb_symbol_callbacks *cb, static void finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) { - struct symtab *symtab; + struct compunit_symtab *cust; struct gdb_block *gdb_block_iter, *gdb_block_iter_tmp; struct block *block_iter; - int actual_nblocks, i, blockvector_size; + int actual_nblocks, i; + size_t blockvector_size; CORE_ADDR begin, end; + struct blockvector *bv; actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks; - symtab = allocate_symtab (stab->file_name, objfile); + cust = allocate_compunit_symtab (objfile, stab->file_name); + allocate_symtab (cust, stab->file_name); + add_compunit_symtab_to_objfile (cust); + /* JIT compilers compile in memory. */ - symtab->dirname = NULL; + COMPUNIT_DIRNAME (cust) = NULL; /* 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; + size_t size = ((stab->linetable->nitems - 1) + * sizeof (struct linetable_entry) + + sizeof (struct linetable)); + SYMTAB_LINETABLE (COMPUNIT_FILETABS (cust)) + = (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 *)); - symtab->blockvector = 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 spans. */ - symtab->primary = 1; - BLOCKVECTOR_MAP (symtab->blockvector) = NULL; + BLOCKVECTOR_MAP (bv) = NULL; begin = stab->blocks->begin; end = stab->blocks->end; - BLOCKVECTOR_NBLOCKS (symtab->blockvector) = actual_nblocks; + BLOCKVECTOR_NBLOCKS (bv) = actual_nblocks; /* First run over all the gdb_block objects, creating a real block object for each. Simultaneously, keep setting the real_block @@ -658,8 +700,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) 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)); + struct symbol *block_name = allocate_symbol (objfile); struct type *block_type = arch_type (get_objfile_arch (objfile), TYPE_CODE_VOID, 1, @@ -672,20 +713,20 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) 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_ACLASS_INDEX (block_name) = LOC_BLOCK; + symbol_set_symtab (block_name, COMPUNIT_FILETABS (cust)); 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, - strlen (gdb_block_iter->name), - &objfile->objfile_obstack); + 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; - BLOCKVECTOR_BLOCK (symtab->blockvector, i) = new_block; + BLOCKVECTOR_BLOCK (bv, i) = new_block; if (begin > BLOCK_START (new_block)) begin = BLOCK_START (new_block); if (end < BLOCK_END (new_block)) @@ -711,10 +752,10 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) BLOCK_START (new_block) = (CORE_ADDR) begin; BLOCK_END (new_block) = (CORE_ADDR) end; - BLOCKVECTOR_BLOCK (symtab->blockvector, i) = new_block; + BLOCKVECTOR_BLOCK (bv, i) = new_block; if (i == GLOBAL_BLOCK) - set_block_symtab (new_block, symtab); + set_block_compunit_symtab (new_block, cust); } /* Fill up the superblock fields for the real blocks, using the @@ -724,8 +765,18 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) 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; + { + /* If the plugin specifically mentioned a parent block, we + use that. */ + BLOCK_SUPERBLOCK (gdb_block_iter->real_block) = + gdb_block_iter->parent->real_block; + } + else + { + /* And if not, we set a default parent block. */ + BLOCK_SUPERBLOCK (gdb_block_iter->real_block) = + BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + } } /* Free memory. */ @@ -754,15 +805,14 @@ jit_object_close_impl (struct gdb_symbol_callbacks *cb, 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, 0); - objfile->gdbarch = target_gdbarch; + objfile = allocate_objfile (NULL, "<< JIT compiled code >>", + OBJF_NOT_FILENAME); + objfile->per_bfd->gdbarch = target_gdbarch (); terminate_minimal_symbol_table (objfile); - objfile->name = "<< JIT compiled code >>"; - j = NULL; for (i = obj->symtabs; i; i = j) { @@ -781,11 +831,10 @@ static int 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, @@ -805,15 +854,20 @@ jit_reader_try_read_symtab (struct jit_code_entry *code_entry, 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) { @@ -894,10 +948,12 @@ JITed symbol file is not an object file, ignoring it.\n")); 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, 0, sai, OBJF_SHARED, NULL); + objfile = symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd), 0, sai, + OBJF_SHARED | OBJF_NOT_FILENAME, NULL); do_cleanups (old_cleanups); add_objfile_entry (objfile, entry_addr); @@ -912,9 +968,7 @@ 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 (); + int success; if (jit_debug) fprintf_unfiltered (gdb_stdlog, @@ -949,53 +1003,93 @@ jit_find_objf_with_entry_addr (CORE_ADDR entry_addr) { 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; } return NULL; } -/* (Re-)Initialize the jit breakpoint if necessary. - Return 0 on success. */ +/* This is called when a breakpoint is deleted. It updates the + inferior's cache, if needed. */ -static int -jit_breakpoint_re_set_internal (struct gdbarch *gdbarch, - struct jit_inferior_data *inf_data) +static void +jit_breakpoint_deleted (struct breakpoint *b) { - struct minimal_symbol *reg_symbol, *desc_symbol; - struct objfile *objf; - struct jit_objfile_data *objf_data; + struct bp_location *iter; - if (inf_data->objfile != NULL) - return 0; + if (b->type != bp_jit_event) + return; - /* 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; + for (iter = b->loc; iter != NULL; iter = iter->next) + { + struct jit_program_space_data *ps_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; + ps_data->jit_breakpoint = NULL; + } + } +} - desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, objf); - if (desc_symbol == NULL || SYMBOL_VALUE_ADDRESS (desc_symbol) == 0) - return 1; +/* (Re-)Initialize the jit breakpoint if necessary. + Return 0 if the jit breakpoint has been successfully initialized. */ - objf_data = get_jit_objfile_data (objf); - objf_data->register_code = reg_symbol; - objf_data->descriptor = desc_symbol; +static int +jit_breakpoint_re_set_internal (struct gdbarch *gdbarch, + struct jit_program_space_data *ps_data) +{ + struct bound_minimal_symbol reg_symbol; + struct bound_minimal_symbol desc_symbol; + struct jit_objfile_data *objf_data; + CORE_ADDR addr; - inf_data->objfile = objf; + if (ps_data->objfile == NULL) + { + /* 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); + if (reg_symbol.minsym == NULL + || BMSYMBOL_VALUE_ADDRESS (reg_symbol) == 0) + return 1; + + desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, + reg_symbol.objfile); + if (desc_symbol.minsym == NULL + || BMSYMBOL_VALUE_ADDRESS (desc_symbol) == 0) + return 1; + + objf_data = get_jit_objfile_data (reg_symbol.objfile); + objf_data->register_code = reg_symbol.minsym; + objf_data->descriptor = desc_symbol.minsym; + + ps_data->objfile = reg_symbol.objfile; + } + else + objf_data = get_jit_objfile_data (ps_data->objfile); - jit_inferior_init (gdbarch); + addr = MSYMBOL_VALUE_ADDRESS (ps_data->objfile, objf_data->register_code); if (jit_debug) fprintf_unfiltered (gdb_stdlog, "jit_breakpoint_re_set_internal, " "breakpoint_addr = %s\n", - paddress (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol))); + paddress (gdbarch, addr)); + + if (ps_data->cached_code_address == addr) + return 0; + + /* Delete the old breakpoint. */ + if (ps_data->jit_breakpoint != NULL) + delete_breakpoint (ps_data->jit_breakpoint); /* Put a breakpoint in the registration symbol. */ - create_jit_event_breakpoint (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol)); + ps_data->cached_code_address = addr; + ps_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr); return 0; } @@ -1007,7 +1101,7 @@ struct jit_unwind_private { /* 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; @@ -1022,7 +1116,7 @@ jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int dwarf_regnum, 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); @@ -1032,11 +1126,12 @@ jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int 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 @@ -1055,14 +1150,15 @@ jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum) 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->defined = frame_register_read (priv->this_frame, gdb_reg, - value->value); + 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; value->free = reg_value_free_impl; return value; @@ -1074,18 +1170,10 @@ jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum) 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); + struct jit_unwind_private *priv_data = (struct jit_unwind_private *) cache; - 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); + gdb_assert (priv_data->regcache != NULL); + regcache_xfree (priv_data->regcache); xfree (priv_data); } @@ -1101,12 +1189,11 @@ 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 (); + struct address_space *aspace; + struct gdbarch *gdbarch; callbacks.reg_get = jit_unwind_reg_get_impl; callbacks.reg_set = jit_unwind_reg_set_impl; @@ -1119,11 +1206,12 @@ jit_frame_sniffer (const struct frame_unwind *self, 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 *); + aspace = get_frame_address_space (this_frame); + gdbarch = get_frame_arch (this_frame); + + *cache = XCNEW (struct jit_unwind_private); + 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; @@ -1154,20 +1242,20 @@ static void 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; @@ -1182,18 +1270,26 @@ jit_frame_this_id (struct frame_info *this_frame, void **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; + 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 @@ -1227,7 +1323,8 @@ jit_prepend_unwinder (struct gdbarch *gdbarch) { 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); @@ -1242,7 +1339,7 @@ jit_inferior_init (struct gdbarch *gdbarch) { struct jit_descriptor descriptor; struct jit_code_entry cur_entry; - struct jit_inferior_data *inf_data; + struct jit_program_space_data *ps_data; CORE_ADDR cur_entry_addr; if (jit_debug) @@ -1250,13 +1347,13 @@ jit_inferior_init (struct gdbarch *gdbarch) jit_prepend_unwinder (gdbarch); - inf_data = get_jit_inferior_data (); - if (jit_breakpoint_re_set_internal (gdbarch, inf_data) != 0) + ps_data = get_jit_program_space_data (); + if (jit_breakpoint_re_set_internal (gdbarch, ps_data) != 0) return; /* Read the descriptor so we can check the version number and load any already JITed functions. */ - if (!jit_read_descriptor (gdbarch, &descriptor, inf_data)) + if (!jit_read_descriptor (gdbarch, &descriptor, ps_data)) return; /* Check that the version number agrees with that we support. */ @@ -1285,12 +1382,20 @@ jit_inferior_init (struct gdbarch *gdbarch) } } +/* 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 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, @@ -1299,8 +1404,8 @@ jit_inferior_created_hook (void) void jit_breakpoint_re_set (void) { - jit_breakpoint_re_set_internal (target_gdbarch, - get_jit_inferior_data ()); + jit_breakpoint_re_set_internal (target_gdbarch (), + get_jit_program_space_data ()); } /* This function cleans up any code entries left over when the @@ -1315,8 +1420,8 @@ jit_inferior_exit_hook (struct inferior *inf) 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); @@ -1332,7 +1437,8 @@ jit_event_handler (struct gdbarch *gdbarch) struct objfile *objf; /* Read the descriptor from remote memory. */ - if (!jit_read_descriptor (gdbarch, &descriptor, get_jit_inferior_data ())) + if (!jit_read_descriptor (gdbarch, &descriptor, + get_jit_program_space_data ())) return; entry_addr = descriptor.relevant_entry; @@ -1361,19 +1467,22 @@ jit_event_handler (struct gdbarch *gdbarch) } } -/* Called to free the data allocated to the jit_inferior_data slot. */ +/* Called to free the data allocated to the jit_program_space_data slot. */ 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_inferior_data *inf_data = get_jit_inferior_data (); + struct jit_program_space_data *ps_data; - if (inf_data->objfile == objfile) - inf_data->objfile = NULL; + 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; } xfree (data); @@ -1385,10 +1494,11 @@ free_objfile_data (struct objfile *objfile, void *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; } @@ -1409,23 +1519,33 @@ _initialize_jit (void) 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_objfile_data = register_objfile_data_with_cleanup (NULL, free_objfile_data); - jit_inferior_data = - register_inferior_data_with_cleanup (NULL, jit_inferior_data_cleanup); + 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 ()) { - 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); } }