+jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb,
+ struct gdb_symtab *stab, int nlines,
+ struct gdb_line_mapping *map)
+{
+ int i;
+ int alloc_len;
+
+ if (nlines < 1)
+ return;
+
+ alloc_len = sizeof (struct linetable)
+ + (nlines - 1) * sizeof (struct linetable_entry);
+ stab->linetable.reset (XNEWVAR (struct linetable, alloc_len));
+ 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;
+ stab->linetable->item[i].is_stmt = 1;
+ }
+}
+
+/* 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 compunit_symtab *cust;
+ size_t blockvector_size;
+ CORE_ADDR begin, end;
+ struct blockvector *bv;
+
+ int actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
+
+ /* Sort the blocks in the order they should appear in the blockvector. */
+ stab->blocks.sort([] (const gdb_block &a, const gdb_block &b)
+ {
+ if (a.begin != b.begin)
+ return a.begin < b.begin;
+
+ return a.end > b.end;
+ });
+
+ cust = allocate_compunit_symtab (objfile, stab->file_name.c_str ());
+ allocate_symtab (cust, stab->file_name.c_str ());
+ add_compunit_symtab_to_objfile (cust);
+
+ /* JIT compilers compile in memory. */
+ COMPUNIT_DIRNAME (cust) = NULL;
+
+ /* Copy over the linetable entry if one was provided. */
+ if (stab->linetable)
+ {
+ 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.get (), size);
+ }
+
+ blockvector_size = (sizeof (struct blockvector)
+ + (actual_nblocks - 1) * sizeof (struct block *));
+ bv = (struct blockvector *) obstack_alloc (&objfile->objfile_obstack,
+ blockvector_size);
+ COMPUNIT_BLOCKVECTOR (cust) = bv;
+
+ /* At the end of this function, (begin, end) will contain the PC range this
+ entire blockvector spans. */
+ BLOCKVECTOR_MAP (bv) = NULL;
+ begin = stab->blocks.front ().begin;
+ end = stab->blocks.front ().end;
+ 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
+ fields. */
+ int block_idx = FIRST_LOCAL_BLOCK;
+ for (gdb_block &gdb_block_iter : stab->blocks)
+ {
+ struct block *new_block = allocate_block (&objfile->objfile_obstack);
+ struct symbol *block_name = new (&objfile->objfile_obstack) symbol;
+ struct type *block_type = arch_type (objfile->arch (),
+ TYPE_CODE_VOID,
+ TARGET_CHAR_BIT,
+ "void");
+
+ BLOCK_MULTIDICT (new_block)
+ = mdict_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_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->m_name = obstack_strdup (&objfile->objfile_obstack,
+ gdb_block_iter.name.get ());
+
+ BLOCK_FUNCTION (new_block) = block_name;
+
+ BLOCKVECTOR_BLOCK (bv, block_idx) = 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_idx++;
+ }
+
+ /* Now add the special blocks. */
+ struct block *block_iter = NULL;
+ for (enum block_enum i : { GLOBAL_BLOCK, STATIC_BLOCK })
+ {
+ struct block *new_block;
+
+ new_block = (i == GLOBAL_BLOCK
+ ? allocate_global_block (&objfile->objfile_obstack)
+ : allocate_block (&objfile->objfile_obstack));
+ BLOCK_MULTIDICT (new_block)
+ = mdict_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);
+ }
+
+ /* Fill up the superblock fields for the real blocks, using the
+ real_block fields populated earlier. */
+ for (gdb_block &gdb_block_iter : stab->blocks)
+ {
+ 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 (bv, STATIC_BLOCK);
+ }
+ }
+}
+
+/* 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 objfile *objfile;
+ jit_dbg_reader_data *priv_data;
+
+ priv_data = (jit_dbg_reader_data *) cb->priv_data;
+
+ objfile = objfile::make (nullptr, "<< JIT compiled code >>",
+ OBJF_NOT_FILENAME);
+ objfile->per_bfd->gdbarch = target_gdbarch ();
+
+ for (gdb_symtab &symtab : obj->symtabs)
+ finalize_symtab (&symtab, objfile);
+
+ add_objfile_entry (objfile, *priv_data);
+
+ delete 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)
+{
+ int status;
+ jit_dbg_reader_data priv_data;
+ struct gdb_reader_funcs *funcs;
+ 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::byte_vector gdb_mem (code_entry->symfile_size);
+
+ status = 1;
+ try
+ {
+ if (target_read_memory (code_entry->symfile_addr, gdb_mem.data (),
+ code_entry->symfile_size))
+ status = 0;
+ }
+ catch (const gdb_exception &e)
+ {
+ status = 0;
+ }
+
+ if (status)
+ {
+ funcs = loaded_jit_reader->functions;
+ if (funcs->read (funcs, &callbacks, gdb_mem.data (),
+ code_entry->symfile_size)
+ != GDB_SUCCESS)
+ status = 0;
+ }
+
+ 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)