X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Fjit.c;h=c12a72f3da518233de709e5afbcac4b3fde7d640;hb=720a66cfb68d5d7d8f2e18e9b44c346ac630c68b;hp=c1274237259e8aff9220339fc58db760898c3eab;hpb=a5bd37c3cab43e33d3c2daf0586d6401e0dca8fd;p=platform%2Fupstream%2Fbinutils.git diff --git a/gdb/jit.c b/gdb/jit.c index c127423..c12a72f 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, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2014 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,8 +37,8 @@ #include "symtab.h" #include "target.h" #include "gdb-dlfcn.h" -#include "gdb_stat.h" -#include "exceptions.h" +#include +#include "gdb_bfd.h" static const char *jit_reader_dir = NULL; @@ -47,7 +48,7 @@ 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); @@ -59,7 +60,7 @@ 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, @@ -88,7 +89,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 @@ -127,6 +130,23 @@ mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb) 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 ("", 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. */ @@ -168,7 +188,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; @@ -182,7 +202,6 @@ static void jit_reader_load_command (char *args, int from_tty) { char *so_name; - int len; struct cleanup *prev_cleanup; if (args == NULL) @@ -191,7 +210,10 @@ jit_reader_load_command (char *args, int from_tty) if (loaded_jit_reader != NULL) error (_("JIT reader already loaded. Run jit-reader-unload first.")); - so_name = xstrprintf ("%s/%s", jit_reader_dir, args); + if (IS_ABSOLUTE_PATH (args)) + so_name = xstrdup (args); + else + so_name = xstrprintf ("%s%s%s", jit_reader_dir, SLASH_STRING, args); prev_cleanup = make_cleanup (xfree, so_name); loaded_jit_reader = jit_reader_load (so_name); @@ -213,78 +235,109 @@ jit_reader_unload_command (char *args, int from_tty) loaded_jit_reader = NULL; } -/* Open a BFD from the target's memory. */ +/* Per-program space 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_program_space_data { - const char *filename = xstrdup (""); - 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; + + /* 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. */ -/* Per-inferior structure recording the addresses in the inferior. */ + CORE_ADDR cached_code_address; -struct jit_inferior_data + /* 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 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 { - 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. This is only + non-zero for objfiles that represent code created by the JIT. */ + CORE_ADDR addr; }; +/* 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 = XCNEW (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 - 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 = 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); } /* 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_program_space_data *ps_data) { int err; struct type *ptr_type; @@ -292,6 +345,19 @@ jit_read_descriptor (struct gdbarch *gdbarch, int desc_size; gdb_byte *desc_buf; enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct jit_objfile_data *objf_data; + + if (ps_data->objfile == NULL) + return 0; + 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, 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; @@ -300,9 +366,15 @@ jit_read_descriptor (struct gdbarch *gdbarch, desc_buf = alloca (desc_size); /* Read the descriptor. */ - err = target_read_memory (descriptor_addr, desc_buf, desc_size); + err = target_read_memory (MSYMBOL_VALUE_ADDRESS (ps_data->objfile, + 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); @@ -311,6 +383,8 @@ jit_read_descriptor (struct gdbarch *gdbarch, 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. */ @@ -330,7 +404,13 @@ jit_read_code_entry (struct gdbarch *gdbarch, /* 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. */ @@ -345,11 +425,6 @@ jit_read_code_entry (struct gdbarch *gdbarch, 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); } @@ -430,7 +505,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, @@ -445,7 +520,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; @@ -483,7 +558,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; @@ -561,8 +636,10 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) struct symtab *symtab; 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; @@ -573,9 +650,9 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) /* 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)); + size_t 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); } @@ -586,16 +663,16 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) blockvector_size = (sizeof (struct blockvector) + (actual_nblocks - 1) * sizeof (struct block *)); - symtab->blockvector = obstack_alloc (&objfile->objfile_obstack, - blockvector_size); + bv = obstack_alloc (&objfile->objfile_obstack, blockvector_size); + symtab->blockvector = bv; /* (begin, end) will contain the PC range this entire blockvector spans. */ - symtab->primary = 1; - BLOCKVECTOR_MAP (symtab->blockvector) = NULL; + set_symtab_primary (symtab, 1); + 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 @@ -605,8 +682,11 @@ 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, + "void"); BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack, NULL); @@ -615,19 +695,19 @@ 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_ACLASS_INDEX (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, - strlen (gdb_block_iter->name), - &objfile->objfile_obstack); + block_name->ginfo.name = 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)) @@ -640,7 +720,11 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) 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; @@ -649,7 +733,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); } /* Fill up the superblock fields for the real blocks, using the @@ -659,8 +746,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. */ @@ -691,14 +788,12 @@ jit_object_close_impl (struct gdb_symbol_callbacks *cb, priv_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); - xfree (objfile->name); - objfile->name = xstrdup ("<< JIT compiled code >>"); - j = NULL; for (i = obj->symtabs; i; i = j) { @@ -719,7 +814,6 @@ jit_reader_try_read_symtab (struct jit_code_entry *code_entry, { 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; @@ -804,7 +898,7 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry, { printf_unfiltered (_("\ JITed symbol file is not an object file, ignoring it.\n")); - bfd_close (nbfd); + gdb_bfd_unref (nbfd); return; } @@ -831,9 +925,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 takes ownership of NBFD. It does not take ownership of SAI. */ - objfile = symbol_file_add_from_bfd (nbfd, 0, sai, OBJF_SHARED, NULL); + /* 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, + OBJF_SHARED | OBJF_NOT_FILENAME, NULL); do_cleanups (old_cleanups); add_objfile_entry (objfile, entry_addr); @@ -848,9 +945,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, @@ -880,53 +975,96 @@ static struct objfile * 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; } +/* This is called when a breakpoint is deleted. It updates the + inferior's cache, if needed. */ + +static void +jit_breakpoint_deleted (struct breakpoint *b) +{ + struct bp_location *iter; + + if (b->type != bp_jit_event) + return; + + for (iter = b->loc; iter != NULL; iter = iter->next) + { + struct jit_program_space_data *ps_data; + + ps_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; + } + } +} + /* (Re-)Initialize the jit breakpoint if necessary. Return 0 on success. */ static int jit_breakpoint_re_set_internal (struct gdbarch *gdbarch, - struct jit_inferior_data *inf_data) + struct jit_program_space_data *ps_data) { - if (inf_data->breakpoint_addr == 0) + struct bound_minimal_symbol reg_symbol; + struct bound_minimal_symbol desc_symbol; + struct jit_objfile_data *objf_data; + CORE_ADDR addr; + + if (ps_data->objfile == NULL) { - 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_and_objfile (jit_break_name); + if (reg_symbol.minsym == NULL + || BMSYMBOL_VALUE_ADDRESS (reg_symbol) == 0) + return 1; - /* 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) + 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; - 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); + + 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 - return 0; + objf_data = get_jit_objfile_data (ps_data->objfile); + + 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, inf_data->breakpoint_addr)); + paddress (gdbarch, addr)); + + if (ps_data->cached_code_address == addr) + return 1; + + /* 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, inf_data->breakpoint_addr); + ps_data->cached_code_address = addr; + ps_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr); return 0; } @@ -992,8 +1130,8 @@ jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum) 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->defined = deprecated_frame_register_read (priv->this_frame, gdb_reg, + value->value); value->size = size; value->free = reg_value_free_impl; return value; @@ -1032,14 +1170,10 @@ 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 jit_dbg_reader *iter; 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; @@ -1051,11 +1185,11 @@ jit_frame_sniffer (const struct frame_unwind *self, gdb_assert (!*cache); - *cache = XZALLOC (struct jit_unwind_private); + *cache = XCNEW (struct jit_unwind_private); priv_data = *cache; priv_data->registers = - XCALLOC (gdbarch_num_regs (get_frame_arch (this_frame)), - struct gdb_reg_value *); + XCNEWVEC (struct gdb_reg_value *, + gdbarch_num_regs (get_frame_arch (this_frame))); priv_data->this_frame = this_frame; callbacks.priv_data = priv_data; @@ -1174,7 +1308,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) @@ -1182,37 +1316,23 @@ 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; - 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, ps_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. */ @@ -1236,7 +1356,7 @@ jit_inferior_init (struct gdbarch *gdbarch) 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, @@ -1245,35 +1365,8 @@ jit_inferior_created_hook (void) void jit_breakpoint_re_set (void) { - 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 (); + jit_breakpoint_re_set_internal (target_gdbarch (), + get_jit_program_space_data ()); } /* This function cleans up any code entries left over when the @@ -1287,14 +1380,13 @@ jit_inferior_exit_hook (struct inferior *inf) 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 @@ -1306,8 +1398,9 @@ jit_event_handler (struct gdbarch *gdbarch) 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_program_space_data ())) + return; entry_addr = descriptor.relevant_entry; /* Do the corresponding action. */ @@ -1335,11 +1428,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; + + if (objf_data->register_code != NULL) + { + struct jit_program_space_data *ps_data; + + ps_data = program_space_data (objfile->pspace, jit_program_space_data); + if (ps_data != NULL && ps_data->objfile == objfile) + ps_data->objfile = NULL; + } + xfree (data); } @@ -1365,21 +1469,22 @@ _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); + 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 (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 ()) {