gdb/jit.c - gdb
Global variables defined
Data types defined
Functions defined
Source code
- #include "defs.h"
- #include "jit.h"
- #include "jit-reader.h"
- #include "block.h"
- #include "breakpoint.h"
- #include "command.h"
- #include "dictionary.h"
- #include "filenames.h"
- #include "frame-unwind.h"
- #include "gdbcmd.h"
- #include "gdbcore.h"
- #include "inferior.h"
- #include "observer.h"
- #include "objfiles.h"
- #include "regcache.h"
- #include "symfile.h"
- #include "symtab.h"
- #include "target.h"
- #include "gdb-dlfcn.h"
- #include <sys/stat.h>
- #include "gdb_bfd.h"
- static const char *jit_reader_dir = NULL;
- static const struct objfile_data *jit_objfile_data;
- static const char *const jit_break_name = "__jit_debug_register_code";
- 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 struct gdbarch_data *jit_gdbarch_data;
- static unsigned int jit_debug = 0;
- static void
- show_jit_debug (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- fprintf_filtered (file, _("JIT debugging is %s.\n"), value);
- }
- struct target_buffer
- {
- CORE_ADDR base;
- ULONGEST size;
- };
- static void *
- mem_bfd_iovec_open (struct bfd *abfd, void *open_closure)
- {
- return open_closure;
- }
- static int
- mem_bfd_iovec_close (struct bfd *abfd, void *stream)
- {
- xfree (stream);
-
- return 0;
- }
- static file_ptr
- mem_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf,
- file_ptr nbytes, file_ptr offset)
- {
- int err;
- struct target_buffer *buffer = (struct target_buffer *) stream;
-
- if (offset + nbytes > buffer->size)
- nbytes = buffer->size - offset;
-
- if (nbytes == 0)
- return 0;
- err = target_read_memory (buffer->base + offset, (gdb_byte *) buf, nbytes);
- if (err)
- return -1;
- return nbytes;
- }
- static int
- mem_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
- {
- struct target_buffer *buffer = (struct target_buffer*) stream;
- sb->st_size = buffer->size;
- return 0;
- }
- static struct bfd *
- bfd_open_from_target_memory (CORE_ADDR addr, ULONGEST size, char *target)
- {
- struct target_buffer *buffer = xmalloc (sizeof (struct target_buffer));
- buffer->base = addr;
- buffer->size = size;
- return gdb_bfd_openr_iovec ("<in-memory>", target,
- mem_bfd_iovec_open,
- buffer,
- mem_bfd_iovec_pread,
- mem_bfd_iovec_close,
- mem_bfd_iovec_stat);
- }
- static struct jit_reader
- {
- struct gdb_reader_funcs *functions;
- void *handle;
- } *loaded_jit_reader = NULL;
- typedef struct gdb_reader_funcs * (reader_init_fn_type) (void);
- static const char *reader_init_fn_sym = "gdb_init_reader";
- static struct jit_reader *
- jit_reader_load (const char *file_name)
- {
- void *so;
- reader_init_fn_type *init_fn;
- struct jit_reader *new_reader = NULL;
- struct gdb_reader_funcs *funcs = NULL;
- struct cleanup *old_cleanups;
- if (jit_debug)
- fprintf_unfiltered (gdb_stdlog, _("Opening shared object %s.\n"),
- file_name);
- so = gdb_dlopen (file_name);
- old_cleanups = make_cleanup_dlclose (so);
- init_fn = gdb_dlsym (so, reader_init_fn_sym);
- if (!init_fn)
- error (_("Could not locate initialization function: %s."),
- reader_init_fn_sym);
- if (gdb_dlsym (so, "plugin_is_GPL_compatible") == NULL)
- error (_("Reader not GPL compatible."));
- funcs = init_fn ();
- if (funcs->reader_version != GDB_READER_INTERFACE_VERSION)
- error (_("Reader version does not match GDB version."));
- new_reader = XCNEW (struct jit_reader);
- new_reader->functions = funcs;
- new_reader->handle = so;
- discard_cleanups (old_cleanups);
- return new_reader;
- }
- static void
- jit_reader_load_command (char *args, int from_tty)
- {
- char *so_name;
- struct cleanup *prev_cleanup;
- if (args == NULL)
- error (_("No reader name provided."));
- if (loaded_jit_reader != NULL)
- error (_("JIT reader already loaded. Run jit-reader-unload first."));
- 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);
- do_cleanups (prev_cleanup);
- }
- static void
- jit_reader_unload_command (char *args, int from_tty)
- {
- if (!loaded_jit_reader)
- error (_("No JIT reader loaded."));
- loaded_jit_reader->functions->destroy (loaded_jit_reader->functions);
- gdb_dlclose (loaded_jit_reader->handle);
- xfree (loaded_jit_reader);
- loaded_jit_reader = NULL;
- }
- struct jit_program_space_data
- {
-
- struct objfile *objfile;
-
- CORE_ADDR cached_code_address;
-
- struct breakpoint *jit_breakpoint;
- };
- struct jit_objfile_data
- {
-
- struct minimal_symbol *register_code;
-
- struct minimal_symbol *descriptor;
-
- CORE_ADDR addr;
- };
- 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;
- }
- static void
- add_objfile_entry (struct objfile *objfile, CORE_ADDR entry)
- {
- struct jit_objfile_data *objf_data;
- objf_data = get_jit_objfile_data (objfile);
- objf_data->addr = entry;
- }
- static struct jit_program_space_data *
- get_jit_program_space_data (void)
- {
- struct jit_program_space_data *ps_data;
- ps_data = program_space_data (current_program_space, jit_program_space_data);
- 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);
- }
- return ps_data;
- }
- static void
- jit_program_space_data_cleanup (struct program_space *ps, void *arg)
- {
- xfree (arg);
- }
- static int
- jit_read_descriptor (struct gdbarch *gdbarch,
- struct jit_descriptor *descriptor,
- struct jit_program_space_data *ps_data)
- {
- int err;
- struct type *ptr_type;
- int ptr_size;
- 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)));
-
- ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
- ptr_size = TYPE_LENGTH (ptr_type);
- desc_size = 8 + 2 * ptr_size;
- desc_buf = alloca (desc_size);
-
- err = target_read_memory (MSYMBOL_VALUE_ADDRESS (ps_data->objfile,
- objf_data->descriptor),
- desc_buf, desc_size);
- if (err)
- {
- printf_unfiltered (_("Unable to read JIT descriptor from "
- "remote memory\n"));
- return 0;
- }
-
- descriptor->version = extract_unsigned_integer (&desc_buf[0], 4, byte_order);
- descriptor->action_flag =
- extract_unsigned_integer (&desc_buf[4], 4, byte_order);
- descriptor->relevant_entry = extract_typed_address (&desc_buf[8], ptr_type);
- descriptor->first_entry =
- extract_typed_address (&desc_buf[8 + ptr_size], ptr_type);
- return 1;
- }
- static void
- jit_read_code_entry (struct gdbarch *gdbarch,
- CORE_ADDR code_addr, struct jit_code_entry *code_entry)
- {
- int err, off;
- struct type *ptr_type;
- int ptr_size;
- int entry_size;
- int align_bytes;
- gdb_byte *entry_buf;
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
- ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
- ptr_size = TYPE_LENGTH (ptr_type);
-
- 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;
- entry_buf = alloca (entry_size);
-
- err = target_read_memory (code_addr, entry_buf, entry_size);
- if (err)
- error (_("Unable to read JIT code entry from remote memory!"));
-
- ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
- code_entry->next_entry = extract_typed_address (&entry_buf[0], ptr_type);
- code_entry->prev_entry =
- extract_typed_address (&entry_buf[ptr_size], ptr_type);
- code_entry->symfile_addr =
- extract_typed_address (&entry_buf[2 * ptr_size], ptr_type);
- code_entry->symfile_size =
- extract_unsigned_integer (&entry_buf[off], 8, byte_order);
- }
- struct gdb_block
- {
-
- struct gdb_block *next, *parent;
-
- struct block *real_block;
-
- CORE_ADDR begin, end;
-
- const char *name;
- };
- struct gdb_symtab
- {
-
- struct gdb_block *blocks;
-
- int nblocks;
-
- struct linetable *linetable;
-
- const char *file_name;
- struct gdb_symtab *next;
- };
- struct gdb_object
- {
- struct gdb_symtab *symtabs;
- };
- 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);
- if (result == 0)
- return GDB_SUCCESS;
- else
- return GDB_FAIL;
- }
- static struct gdb_object *
- jit_object_open_impl (struct gdb_symbol_callbacks *cb)
- {
-
- return XCNEW (struct gdb_object);
- }
- static struct gdb_symtab *
- jit_symtab_open_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_object *object,
- const char *file_name)
- {
- struct gdb_symtab *ret;
-
- ret = XCNEW (struct gdb_symtab);
- ret->file_name = file_name ? xstrdup (file_name) : xstrdup ("");
- ret->next = object->symtabs;
- object->symtabs = ret;
- return ret;
- }
- static int
- compare_block (const struct gdb_block *const old,
- const struct gdb_block *const new)
- {
- if (old == NULL)
- return 1;
- if (old->begin < new->begin)
- return 1;
- else if (old->begin == new->begin)
- {
- if (old->end > new->end)
- return 1;
- else
- 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_block *block = XCNEW (struct gdb_block);
- block->next = symtab->blocks;
- block->begin = (CORE_ADDR) begin;
- block->end = (CORE_ADDR) end;
- block->name = name ? xstrdup (name) : NULL;
- block->parent = parent;
-
- if (compare_block (symtab->blocks, block))
- {
- symtab->blocks = block;
- }
- else
- {
- struct gdb_block *i = symtab->blocks;
- for (;; i = i->next)
- {
-
- if (compare_block (i->next, block))
- {
- block->next = i->next;
- i->next = block;
- break;
- }
- }
- }
- symtab->nblocks++;
- return block;
- }
- static void
- jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_symtab *stab, int nlines,
- struct gdb_line_mapping *map)
- {
- int i;
- if (nlines < 1)
- return;
- stab->linetable = xmalloc (sizeof (struct linetable)
- + (nlines - 1) * sizeof (struct linetable_entry));
- stab->linetable->nitems = nlines;
- for (i = 0; i < nlines; i++)
- {
- stab->linetable->item[i].pc = (CORE_ADDR) map[i].pc;
- stab->linetable->item[i].line = map[i].line;
- }
- }
- static void
- jit_symtab_close_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_symtab *stab)
- {
-
- }
- static void
- finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
- {
- struct compunit_symtab *cust;
- struct gdb_block *gdb_block_iter, *gdb_block_iter_tmp;
- struct block *block_iter;
- int actual_nblocks, i;
- size_t blockvector_size;
- CORE_ADDR begin, end;
- struct blockvector *bv;
- 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);
-
- COMPUNIT_DIRNAME (cust) = NULL;
-
- if (stab->linetable)
- {
- size_t size = ((stab->linetable->nitems - 1)
- * sizeof (struct linetable_entry)
- + sizeof (struct linetable));
- SYMTAB_LINETABLE (COMPUNIT_FILETABS (cust))
- = 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);
- COMPUNIT_BLOCKVECTOR (cust) = bv;
-
- BLOCKVECTOR_MAP (bv) = NULL;
- begin = stab->blocks->begin;
- end = stab->blocks->end;
- BLOCKVECTOR_NBLOCKS (bv) = actual_nblocks;
-
- for (i = (actual_nblocks - 1), gdb_block_iter = stab->blocks;
- i >= FIRST_LOCAL_BLOCK;
- i--, gdb_block_iter = gdb_block_iter->next)
- {
- struct block *new_block = allocate_block (&objfile->objfile_obstack);
- 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);
-
- BLOCK_START (new_block) = (CORE_ADDR) gdb_block_iter->begin;
- BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end;
-
- SYMBOL_DOMAIN (block_name) = VAR_DOMAIN;
- 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 = obstack_copy0 (&objfile->objfile_obstack,
- gdb_block_iter->name,
- strlen (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);
- if (end < BLOCK_END (new_block))
- end = BLOCK_END (new_block);
- gdb_block_iter->real_block = new_block;
- }
-
- block_iter = NULL;
- for (i = 0; i < FIRST_LOCAL_BLOCK; i++)
- {
- struct block *new_block;
- new_block = (i == GLOBAL_BLOCK
- ? allocate_global_block (&objfile->objfile_obstack)
- : allocate_block (&objfile->objfile_obstack));
- BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
- NULL);
- BLOCK_SUPERBLOCK (new_block) = block_iter;
- block_iter = new_block;
- BLOCK_START (new_block) = (CORE_ADDR) begin;
- BLOCK_END (new_block) = (CORE_ADDR) end;
- BLOCKVECTOR_BLOCK (bv, i) = new_block;
- if (i == GLOBAL_BLOCK)
- set_block_compunit_symtab (new_block, cust);
- }
-
- for (gdb_block_iter = stab->blocks;
- gdb_block_iter;
- 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;
- }
- else
- {
-
- BLOCK_SUPERBLOCK (gdb_block_iter->real_block) =
- BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- }
- }
-
- gdb_block_iter = stab->blocks;
- for (gdb_block_iter = stab->blocks, gdb_block_iter_tmp = gdb_block_iter->next;
- gdb_block_iter;
- gdb_block_iter = gdb_block_iter_tmp)
- {
- xfree ((void *) gdb_block_iter->name);
- xfree (gdb_block_iter);
- }
- xfree (stab->linetable);
- xfree ((char *) stab->file_name);
- xfree (stab);
- }
- static void
- jit_object_close_impl (struct gdb_symbol_callbacks *cb,
- struct gdb_object *obj)
- {
- struct gdb_symtab *i, *j;
- struct objfile *objfile;
- jit_dbg_reader_data *priv_data;
- priv_data = cb->priv_data;
- objfile = allocate_objfile (NULL, "<< 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)
- {
- j = i->next;
- finalize_symtab (i, objfile);
- }
- add_objfile_entry (objfile, *priv_data);
- xfree (obj);
- }
- static int
- jit_reader_try_read_symtab (struct jit_code_entry *code_entry,
- CORE_ADDR entry_addr)
- {
- void *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,
- jit_symtab_open_impl,
- jit_block_open_impl,
- jit_symtab_close_impl,
- jit_object_close_impl,
- jit_symtab_line_mapping_add_impl,
- jit_target_read_impl,
- &priv_data
- };
- priv_data = entry_addr;
- if (!loaded_jit_reader)
- return 0;
- gdb_mem = 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))
- status = 0;
- if (e.reason < 0)
- status = 0;
- if (status)
- {
- funcs = loaded_jit_reader->functions;
- if (funcs->read (funcs, &callbacks, gdb_mem, 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");
- return status;
- }
- static void
- jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
- CORE_ADDR entry_addr,
- struct gdbarch *gdbarch)
- {
- bfd *nbfd;
- struct section_addr_info *sai;
- struct bfd_section *sec;
- struct objfile *objfile;
- struct cleanup *old_cleanups;
- int i;
- const struct bfd_arch_info *b;
- 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));
- 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"));
- return;
- }
-
- if (!bfd_check_format (nbfd, bfd_object))
- {
- printf_unfiltered (_("\
- JITed symbol file is not an object file, ignoring it.\n"));
- gdb_bfd_unref (nbfd);
- return;
- }
-
- b = gdbarch_bfd_arch_info (gdbarch);
- if (b->compatible (b, bfd_get_arch_info (nbfd)) != b)
- warning (_("JITed object file architecture %s is not compatible "
- "with target architecture %s."), bfd_get_arch_info
- (nbfd)->printable_name, b->printable_name);
-
- sai = alloc_section_addr_info (bfd_count_sections (nbfd));
- 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)
- {
-
- sai->other[i].addr = bfd_get_section_vma (nbfd, sec);
- sai->other[i].name = xstrdup (bfd_get_section_name (nbfd, sec));
- sai->other[i].sectindex = sec->index;
- ++i;
- }
- sai->num_sections = i;
-
- 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);
- }
- static void
- jit_register_code (struct gdbarch *gdbarch,
- 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));
- success = jit_reader_try_read_symtab (code_entry, entry_addr);
- if (!success)
- jit_bfd_try_read_symtab (code_entry, entry_addr, gdbarch);
- }
- static void
- jit_unregister_code (struct objfile *objfile)
- {
- free_objfile (objfile);
- }
- static struct objfile *
- jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
- {
- struct objfile *objf;
- ALL_OBJFILES (objf)
- {
- 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;
- }
- 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;
- }
- }
- }
- 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;
- if (ps_data->objfile == NULL)
- {
-
- 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);
- 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, addr));
- if (ps_data->cached_code_address == addr)
- return 1;
-
- if (ps_data->jit_breakpoint != NULL)
- delete_breakpoint (ps_data->jit_breakpoint);
-
- ps_data->cached_code_address = addr;
- ps_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr);
- return 0;
- }
- struct jit_unwind_private
- {
-
- struct gdb_reg_value **registers;
-
- struct frame_info *this_frame;
- };
- static void
- jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int dwarf_regnum,
- struct gdb_reg_value *value)
- {
- struct jit_unwind_private *priv;
- int gdb_reg;
- priv = cb->priv_data;
- gdb_reg = gdbarch_dwarf2_reg_to_regnum (get_frame_arch (priv->this_frame),
- dwarf_regnum);
- if (gdb_reg == -1)
- {
- if (jit_debug)
- fprintf_unfiltered (gdb_stdlog,
- _("Could not recognize DWARF regnum %d"),
- dwarf_regnum);
- return;
- }
- gdb_assert (priv->registers);
- priv->registers[gdb_reg] = value;
- }
- static void
- reg_value_free_impl (struct gdb_reg_value *value)
- {
- xfree (value);
- }
- static struct gdb_reg_value *
- jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum)
- {
- struct jit_unwind_private *priv;
- struct gdb_reg_value *value;
- int gdb_reg, size;
- struct gdbarch *frame_arch;
- priv = cb->priv_data;
- frame_arch = get_frame_arch (priv->this_frame);
- gdb_reg = gdbarch_dwarf2_reg_to_regnum (frame_arch, regnum);
- size = register_size (frame_arch, gdb_reg);
- value = xmalloc (sizeof (struct gdb_reg_value) + size - 1);
- value->defined = deprecated_frame_register_read (priv->this_frame, gdb_reg,
- value->value);
- value->size = size;
- value->free = reg_value_free_impl;
- return value;
- }
- static void
- jit_dealloc_cache (struct frame_info *this_frame, void *cache)
- {
- struct jit_unwind_private *priv_data = cache;
- struct gdbarch *frame_arch;
- int i;
- gdb_assert (priv_data->registers);
- frame_arch = get_frame_arch (priv_data->this_frame);
- for (i = 0; i < gdbarch_num_regs (frame_arch); i++)
- if (priv_data->registers[i] && priv_data->registers[i]->free)
- priv_data->registers[i]->free (priv_data->registers[i]);
- xfree (priv_data->registers);
- xfree (priv_data);
- }
- static int
- jit_frame_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame, void **cache)
- {
- struct jit_unwind_private *priv_data;
- struct gdb_unwind_callbacks callbacks;
- struct gdb_reader_funcs *funcs;
- callbacks.reg_get = jit_unwind_reg_get_impl;
- callbacks.reg_set = jit_unwind_reg_set_impl;
- callbacks.target_read = jit_target_read_impl;
- if (loaded_jit_reader == NULL)
- return 0;
- funcs = loaded_jit_reader->functions;
- gdb_assert (!*cache);
- *cache = 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->this_frame = this_frame;
- callbacks.priv_data = priv_data;
-
- if (funcs->unwind (funcs, &callbacks) == GDB_SUCCESS)
- {
- if (jit_debug)
- fprintf_unfiltered (gdb_stdlog, _("Successfully unwound frame using "
- "JIT reader.\n"));
- return 1;
- }
- if (jit_debug)
- fprintf_unfiltered (gdb_stdlog, _("Could not unwind frame using "
- "JIT reader.\n"));
- jit_dealloc_cache (this_frame, *cache);
- *cache = NULL;
- return 0;
- }
- static void
- jit_frame_this_id (struct frame_info *this_frame, void **cache,
- struct frame_id *this_id)
- {
- struct jit_unwind_private private;
- struct gdb_frame_id frame_id;
- struct gdb_reader_funcs *funcs;
- struct gdb_unwind_callbacks callbacks;
- private.registers = NULL;
- private.this_frame = this_frame;
-
- callbacks.reg_get = jit_unwind_reg_get_impl;
- callbacks.reg_set = NULL;
- callbacks.target_read = jit_target_read_impl;
- callbacks.priv_data = &private;
- gdb_assert (loaded_jit_reader);
- funcs = loaded_jit_reader->functions;
- frame_id = funcs->get_frame_id (funcs, &callbacks);
- *this_id = frame_id_build (frame_id.stack_address, frame_id.code_address);
- }
- static struct value *
- jit_frame_prev_register (struct frame_info *this_frame, void **cache, int reg)
- {
- struct jit_unwind_private *priv = *cache;
- struct gdb_reg_value *value;
- if (priv == NULL)
- return frame_unwind_got_optimized (this_frame, reg);
- gdb_assert (priv->registers);
- value = priv->registers[reg];
- if (value && value->defined)
- return frame_unwind_got_bytes (this_frame, reg, value->value);
- else
- return frame_unwind_got_optimized (this_frame, reg);
- }
- static const struct frame_unwind jit_frame_unwind =
- {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- jit_frame_this_id,
- jit_frame_prev_register,
- NULL,
- jit_frame_sniffer,
- jit_dealloc_cache
- };
- struct jit_gdbarch_data_type
- {
-
- int unwinder_registered;
- };
- static void
- jit_prepend_unwinder (struct gdbarch *gdbarch)
- {
- struct jit_gdbarch_data_type *data;
- data = gdbarch_data (gdbarch, jit_gdbarch_data);
- if (!data->unwinder_registered)
- {
- frame_unwind_prepend_unwinder (gdbarch, &jit_frame_unwind);
- data->unwinder_registered = 1;
- }
- }
- static void
- jit_inferior_init (struct gdbarch *gdbarch)
- {
- struct jit_descriptor descriptor;
- struct jit_code_entry cur_entry;
- struct jit_program_space_data *ps_data;
- CORE_ADDR cur_entry_addr;
- if (jit_debug)
- fprintf_unfiltered (gdb_stdlog, "jit_inferior_init\n");
- jit_prepend_unwinder (gdbarch);
- ps_data = get_jit_program_space_data ();
- if (jit_breakpoint_re_set_internal (gdbarch, ps_data) != 0)
- return;
-
- if (!jit_read_descriptor (gdbarch, &descriptor, ps_data))
- return;
-
- if (descriptor.version != 1)
- {
- printf_unfiltered (_("Unsupported JIT protocol version %ld "
- "in descriptor (expected 1)\n"),
- (long) descriptor.version);
- return;
- }
-
- for (cur_entry_addr = descriptor.first_entry;
- cur_entry_addr != 0;
- cur_entry_addr = cur_entry.next_entry)
- {
- jit_read_code_entry (gdbarch, cur_entry_addr, &cur_entry);
-
- if (jit_find_objf_with_entry_addr (cur_entry_addr) != NULL)
- continue;
- jit_register_code (gdbarch, cur_entry_addr, &cur_entry);
- }
- }
- void
- jit_inferior_created_hook (void)
- {
- jit_inferior_init (target_gdbarch ());
- }
- void
- jit_breakpoint_re_set (void)
- {
- jit_breakpoint_re_set_internal (target_gdbarch (),
- get_jit_program_space_data ());
- }
- static void
- jit_inferior_exit_hook (struct inferior *inf)
- {
- struct objfile *objf;
- struct objfile *temp;
- ALL_OBJFILES_SAFE (objf, temp)
- {
- struct jit_objfile_data *objf_data = objfile_data (objf,
- jit_objfile_data);
- if (objf_data != NULL && objf_data->addr != 0)
- jit_unregister_code (objf);
- }
- }
- void
- jit_event_handler (struct gdbarch *gdbarch)
- {
- struct jit_descriptor descriptor;
- struct jit_code_entry code_entry;
- CORE_ADDR entry_addr;
- struct objfile *objf;
-
- if (!jit_read_descriptor (gdbarch, &descriptor,
- get_jit_program_space_data ()))
- return;
- entry_addr = descriptor.relevant_entry;
-
- switch (descriptor.action_flag)
- {
- case JIT_NOACTION:
- break;
- case JIT_REGISTER:
- jit_read_code_entry (gdbarch, entry_addr, &code_entry);
- jit_register_code (gdbarch, entry_addr, &code_entry);
- break;
- case JIT_UNREGISTER:
- objf = jit_find_objf_with_entry_addr (entry_addr);
- if (objf == NULL)
- printf_unfiltered (_("Unable to find JITed code "
- "entry at address: %s\n"),
- paddress (gdbarch, entry_addr));
- else
- jit_unregister_code (objf);
- break;
- default:
- error (_("Unknown action_flag value in JIT descriptor!"));
- break;
- }
- }
- 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);
- }
- static void *
- jit_gdbarch_data_init (struct obstack *obstack)
- {
- struct jit_gdbarch_data_type *data;
- data = obstack_alloc (obstack, sizeof (struct jit_gdbarch_data_type));
- data->unwinder_registered = 0;
- return data;
- }
- extern void _initialize_jit (void);
- void
- _initialize_jit (void)
- {
- jit_reader_dir = relocate_gdb_directory (JIT_READER_DIR,
- JIT_READER_DIR_RELOCATABLE);
- 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_breakpoint_deleted (jit_breakpoint_deleted);
- 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 ())
- {
- 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, _("\
- Unload the currently loaded JIT debug info reader.\n\
- Usage: jit-reader-unload FILE\n\n\
- Do \"help jit-reader-load\" for info on loading debug info readers."));
- }
- }