Index: gdb/jit.c |
diff --git a/gdb/jit.c b/gdb/jit.c |
index 24e2cf90a9292b5144e74b57c962436280cf63e6..568d17be0f9576d6feffa515621c1c58066101a4 100644 |
--- a/gdb/jit.c |
+++ b/gdb/jit.c |
@@ -127,6 +127,24 @@ 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) |
+{ |
+ const char *filename = xstrdup ("<in-memory>"); |
+ struct target_buffer *buffer = xmalloc (sizeof (struct target_buffer)); |
+ |
+ 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); |
+} |
+ |
/* One reader that has been loaded successfully, and can potentially be used to |
parse debug info. */ |
@@ -182,7 +200,6 @@ static void |
jit_reader_load_command (char *args, int from_tty) |
{ |
char *so_name; |
- int len; |
struct cleanup *prev_cleanup; |
if (args == NULL) |
@@ -213,43 +230,59 @@ jit_reader_unload_command (char *args, int from_tty) |
loaded_jit_reader = NULL; |
} |
-/* Open a BFD from the target's memory. */ |
+/* Per-inferior 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_inferior_data |
{ |
- const char *filename = xstrdup ("<in-memory>"); |
- 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; |
+}; |
-/* Per-inferior structure recording the addresses in the inferior. */ |
+/* Per-objfile structure recording the addresses in the inferior. */ |
-struct jit_inferior_data |
+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. */ |
+ 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 = XZALLOC (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 |
@@ -279,12 +312,12 @@ jit_inferior_data_cleanup (struct inferior *inf, void *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_inferior_data *inf_data) |
{ |
int err; |
struct type *ptr_type; |
@@ -292,6 +325,18 @@ 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 (inf_data->objfile == NULL) |
+ return 0; |
+ objf_data = get_jit_objfile_data (inf_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))); |
/* 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 +345,14 @@ 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 (SYMBOL_VALUE_ADDRESS (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 +361,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 +382,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 +403,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); |
} |
@@ -607,6 +660,10 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) |
struct block *new_block = allocate_block (&objfile->objfile_obstack); |
struct symbol *block_name = obstack_alloc (&objfile->objfile_obstack, |
sizeof (struct symbol)); |
+ 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); |
@@ -619,6 +676,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) |
SYMBOL_DOMAIN (block_name) = VAR_DOMAIN; |
SYMBOL_CLASS (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, |
@@ -640,7 +698,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; |
@@ -650,6 +712,9 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile) |
BLOCK_END (new_block) = (CORE_ADDR) end; |
BLOCKVECTOR_BLOCK (symtab->blockvector, i) = new_block; |
+ |
+ if (i == GLOBAL_BLOCK) |
+ set_block_symtab (new_block, symtab); |
} |
/* Fill up the superblock fields for the real blocks, using the |
@@ -694,9 +759,7 @@ jit_object_close_impl (struct gdb_symbol_callbacks *cb, |
objfile = allocate_objfile (NULL, 0); |
objfile->gdbarch = target_gdbarch; |
- objfile->msymbols = obstack_alloc (&objfile->objfile_obstack, |
- sizeof (struct minimal_symbol)); |
- memset (objfile->msymbols, 0, sizeof (struct minimal_symbol)); |
+ terminate_minimal_symbol_table (objfile); |
xfree (objfile->name); |
objfile->name = xstrdup ("<< JIT compiled code >>"); |
@@ -721,7 +784,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; |
@@ -882,12 +944,13 @@ 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; |
@@ -900,35 +963,39 @@ static int |
jit_breakpoint_re_set_internal (struct gdbarch *gdbarch, |
struct jit_inferior_data *inf_data) |
{ |
- if (inf_data->breakpoint_addr == 0) |
- { |
- 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 (jit_break_name, NULL, NULL); |
- if (reg_symbol == NULL) |
- 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); |
- } |
- else |
+ struct minimal_symbol *reg_symbol, *desc_symbol; |
+ struct objfile *objf; |
+ struct jit_objfile_data *objf_data; |
+ |
+ if (inf_data->objfile != NULL) |
return 0; |
+ /* Lookup the registration symbol. If it is missing, then we assume |
+ we are not attached to a JIT. */ |
+ reg_symbol = lookup_minimal_symbol_and_objfile (jit_break_name, &objf); |
+ if (reg_symbol == NULL || SYMBOL_VALUE_ADDRESS (reg_symbol) == 0) |
+ return 1; |
+ |
+ desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, objf); |
+ if (desc_symbol == NULL || SYMBOL_VALUE_ADDRESS (desc_symbol) == 0) |
+ return 1; |
+ |
+ objf_data = get_jit_objfile_data (objf); |
+ objf_data->register_code = reg_symbol; |
+ objf_data->descriptor = desc_symbol; |
+ |
+ inf_data->objfile = objf; |
+ |
+ jit_inferior_init (gdbarch); |
+ |
if (jit_debug) |
fprintf_unfiltered (gdb_stdlog, |
"jit_breakpoint_re_set_internal, " |
"breakpoint_addr = %s\n", |
- paddress (gdbarch, inf_data->breakpoint_addr)); |
+ paddress (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol))); |
/* Put a breakpoint in the registration symbol. */ |
- create_jit_event_breakpoint (gdbarch, inf_data->breakpoint_addr); |
+ create_jit_event_breakpoint (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol)); |
return 0; |
} |
@@ -1036,7 +1103,6 @@ jit_frame_sniffer (const struct frame_unwind *self, |
{ |
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; |
@@ -1188,33 +1254,19 @@ jit_inferior_init (struct gdbarch *gdbarch) |
if (jit_breakpoint_re_set_internal (gdbarch, inf_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, inf_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. */ |
@@ -1251,33 +1303,6 @@ jit_breakpoint_re_set (void) |
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 (); |
-} |
- |
/* This function cleans up any code entries left over when the |
inferior exits. We get left over code when the inferior exits |
without unregistering its code, for example when it crashes. */ |
@@ -1289,14 +1314,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 |
@@ -1308,8 +1332,8 @@ 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_inferior_data ())) |
+ return; |
entry_addr = descriptor.relevant_entry; |
/* Do the corresponding action. */ |
@@ -1342,6 +1366,16 @@ jit_event_handler (struct gdbarch *gdbarch) |
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_inferior_data *inf_data = get_jit_inferior_data (); |
+ |
+ if (inf_data->objfile == objfile) |
+ inf_data->objfile = NULL; |
+ } |
+ |
xfree (data); |
} |
@@ -1375,9 +1409,7 @@ _initialize_jit (void) |
show_jit_debug, |
&setdebuglist, &showdebuglist); |
- observer_attach_inferior_created (jit_inferior_created_observer); |
observer_attach_inferior_exit (jit_inferior_exit_hook); |
- observer_attach_executable_changed (jit_executable_changed_observer); |
jit_objfile_data = |
register_objfile_data_with_cleanup (NULL, free_objfile_data); |
jit_inferior_data = |