+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;
+ }
+}
+
+/* Called by readers to close a gdb_symtab. Does not need to do
+ anything as of now. */
+
+static void
+jit_symtab_close_impl (struct gdb_symbol_callbacks *cb,
+ struct gdb_symtab *stab)
+{
+ /* Right now nothing needs to be done here. We may need to do some
+ cleanup here in the future (again, without breaking the plugin
+ ABI). */
+}
+
+/* Transform STAB to a proper symtab, and add it it OBJFILE. */
+
+static void
+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;
+ CORE_ADDR begin, end;
+
+ actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
+
+ symtab = allocate_symtab (stab->file_name, objfile);
+ /* JIT compilers compile in memory. */
+ symtab->dirname = 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;
+ }
+
+ blockvector_size = (sizeof (struct blockvector)
+ + (actual_nblocks - 1) * sizeof (struct block *));
+ symtab->blockvector = obstack_alloc (&objfile->objfile_obstack,
+ blockvector_size);
+
+ /* (begin, end) will contain the PC range this entire blockvector
+ spans. */
+ set_symtab_primary (symtab, 1);
+ BLOCKVECTOR_MAP (symtab->blockvector) = NULL;
+ begin = stab->blocks->begin;
+ end = stab->blocks->end;
+ BLOCKVECTOR_NBLOCKS (symtab->blockvector) = actual_nblocks;
+
+ /* First run over all the gdb_block objects, creating a real block
+ object for each. Simultaneously, keep setting the real_block
+ fields. */
+ 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);
+ /* The address range. */
+ BLOCK_START (new_block) = (CORE_ADDR) gdb_block_iter->begin;
+ BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end;
+
+ /* The name. */
+ SYMBOL_DOMAIN (block_name) = VAR_DOMAIN;
+ 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 = 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;
+ 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;
+ }
+
+ /* Now add the special blocks. */
+ 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 (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
+ real_block fields populated earlier. */
+ for (gdb_block_iter = stab->blocks;
+ gdb_block_iter;
+ gdb_block_iter = gdb_block_iter->next)
+ {
+ if (gdb_block_iter->parent != NULL)
+ {
+ /* 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 (symtab->blockvector, STATIC_BLOCK);
+ }
+ }
+
+ /* Free memory. */
+ 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);
+}
+
+/* Called when closing a gdb_objfile. Converts OBJ to a proper
+ objfile. */
+
+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);
+}
+
+/* Try to read CODE_ENTRY using the loaded jit reader (if any).
+ ENTRY_ADDR is the address of the struct jit_code_entry in the
+ inferior address space. */
+
+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;
+}
+
+/* Try to read CODE_ENTRY using BFD. ENTRY_ADDR is the address of the
+ struct jit_code_entry in the inferior address space. */
+
+static void
+jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
+ CORE_ADDR entry_addr,
+ struct gdbarch *gdbarch)