+\f
+
+/* Read in the symbols for PER_CU. OBJFILE is the objfile from which
+ this CU came. */
+static void
+dw2_do_instantiate_symtab (struct objfile *objfile,
+ struct dwarf2_per_cu_data *per_cu)
+{
+ struct cleanup *back_to;
+
+ back_to = make_cleanup (dwarf2_release_queue, NULL);
+
+ queue_comp_unit (per_cu, objfile);
+
+ if (per_cu->from_debug_types)
+ read_signatured_type_at_offset (objfile, per_cu->offset);
+ else
+ load_full_comp_unit (per_cu, objfile);
+
+ process_queue (objfile);
+
+ /* Age the cache, releasing compilation units that have not
+ been used recently. */
+ age_cached_comp_units ();
+
+ do_cleanups (back_to);
+}
+
+/* Ensure that the symbols for PER_CU have been read in. OBJFILE is
+ the objfile from which this CU came. Returns the resulting symbol
+ table. */
+static struct symtab *
+dw2_instantiate_symtab (struct objfile *objfile,
+ struct dwarf2_per_cu_data *per_cu)
+{
+ if (!per_cu->v.quick->symtab)
+ {
+ struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL);
+ increment_reading_symtab ();
+ dw2_do_instantiate_symtab (objfile, per_cu);
+ do_cleanups (back_to);
+ }
+ return per_cu->v.quick->symtab;
+}
+
+/* A helper function that knows how to read a 64-bit value in a way
+ that doesn't make gdb die. Returns 1 if the conversion went ok, 0
+ otherwise. */
+static int
+extract_cu_value (const char *bytes, ULONGEST *result)
+{
+ if (sizeof (ULONGEST) < 8)
+ {
+ int i;
+
+ /* Ignore the upper 4 bytes if they are all zero. */
+ for (i = 0; i < 4; ++i)
+ if (bytes[i + 4] != 0)
+ return 0;
+
+ *result = extract_unsigned_integer (bytes, 4, BFD_ENDIAN_LITTLE);
+ }
+ else
+ *result = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
+ return 1;
+}
+
+/* Read the CU list from the mapped index, and use it to create all
+ the CU objects for this objfile. Return 0 if something went wrong,
+ 1 if everything went ok. */
+static int
+create_cus_from_index (struct objfile *objfile, struct mapped_index *index,
+ const gdb_byte *cu_list, offset_type cu_list_elements)
+{
+ offset_type i;
+ const char *entry;
+
+ dwarf2_per_objfile->n_comp_units = cu_list_elements / 2;
+ dwarf2_per_objfile->all_comp_units
+ = obstack_alloc (&objfile->objfile_obstack,
+ dwarf2_per_objfile->n_comp_units
+ * sizeof (struct dwarf2_per_cu_data *));
+
+ for (i = 0; i < cu_list_elements; i += 2)
+ {
+ struct dwarf2_per_cu_data *the_cu;
+ ULONGEST offset, length;
+
+ if (!extract_cu_value (cu_list, &offset)
+ || !extract_cu_value (cu_list + 8, &length))
+ return 0;
+ cu_list += 2 * 8;
+
+ the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_data);
+ the_cu->offset = offset;
+ the_cu->length = length;
+ the_cu->objfile = objfile;
+ the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_quick_data);
+ dwarf2_per_objfile->all_comp_units[i / 2] = the_cu;
+ }
+
+ return 1;
+}
+
+/* Read the address map data from the mapped index, and use it to
+ populate the objfile's psymtabs_addrmap. */
+static void
+create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
+{
+ const gdb_byte *iter, *end;
+ struct obstack temp_obstack;
+ struct addrmap *mutable_map;
+ struct cleanup *cleanup;
+ CORE_ADDR baseaddr;
+
+ obstack_init (&temp_obstack);
+ cleanup = make_cleanup_obstack_free (&temp_obstack);
+ mutable_map = addrmap_create_mutable (&temp_obstack);
+
+ iter = index->address_table;
+ end = iter + index->address_table_size;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ while (iter < end)
+ {
+ ULONGEST hi, lo, cu_index;
+ lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE);
+ iter += 8;
+ hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE);
+ iter += 8;
+ cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE);
+ iter += 4;
+
+ addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
+ dwarf2_per_objfile->all_comp_units[cu_index]);
+ }
+
+ objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
+ &objfile->objfile_obstack);
+ do_cleanups (cleanup);
+}
+
+/* The hash function for strings in the mapped index. This is the
+ same as the hashtab.c hash function, but we keep a separate copy to
+ maintain control over the implementation. This is necessary
+ because the hash function is tied to the format of the mapped index
+ file. */
+static hashval_t
+mapped_index_string_hash (const void *p)
+{
+ const unsigned char *str = (const unsigned char *) p;
+ hashval_t r = 0;
+ unsigned char c;
+
+ while ((c = *str++) != 0)
+ r = r * 67 + c - 113;
+
+ return r;
+}
+
+/* Find a slot in the mapped index INDEX for the object named NAME.
+ If NAME is found, set *VEC_OUT to point to the CU vector in the
+ constant pool and return 1. If NAME cannot be found, return 0. */
+static int
+find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
+ offset_type **vec_out)
+{
+ offset_type hash = mapped_index_string_hash (name);
+ offset_type slot, step;
+
+ slot = hash & (index->index_table_slots - 1);
+ step = ((hash * 17) & (index->index_table_slots - 1)) | 1;
+
+ for (;;)
+ {
+ /* Convert a slot number to an offset into the table. */
+ offset_type i = 2 * slot;
+ const char *str;
+ if (index->index_table[i] == 0 && index->index_table[i + 1] == 0)
+ return 0;
+
+ str = index->constant_pool + MAYBE_SWAP (index->index_table[i]);
+ if (!strcmp (name, str))
+ {
+ *vec_out = (offset_type *) (index->constant_pool
+ + MAYBE_SWAP (index->index_table[i + 1]));
+ return 1;
+ }
+
+ slot = (slot + step) & (index->index_table_slots - 1);
+ }
+}
+
+/* Read the index file. If everything went ok, initialize the "quick"
+ elements of all the CUs and return 1. Otherwise, return 0. */
+static int
+dwarf2_read_index (struct objfile *objfile)
+{
+ struct stat st, obstat;
+ int fd;
+ char *addr;
+ struct mapped_index *map;
+ offset_type val, *metadata;
+ char buf1[8], buf2[8];
+ const gdb_byte *cu_list;
+ offset_type cu_list_elements;
+
+ if (dwarf2_per_objfile->gdb_index.asection == NULL
+ || dwarf2_per_objfile->gdb_index.size == 0)
+ return 0;
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->gdb_index);
+
+ addr = dwarf2_per_objfile->gdb_index.buffer;
+ /* Version check. */
+ if (MAYBE_SWAP (*(offset_type *) addr) != 1)
+ return 0;
+
+ map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index);
+ map->total_size = st.st_size;
+
+ metadata = (offset_type *) (addr + sizeof (offset_type));
+ cu_list = addr + MAYBE_SWAP (metadata[0]);
+ cu_list_elements = ((MAYBE_SWAP (metadata[1]) - MAYBE_SWAP (metadata[0]))
+ / 8);
+ map->address_table = addr + MAYBE_SWAP (metadata[1]);
+ map->address_table_size = (MAYBE_SWAP (metadata[2])
+ - MAYBE_SWAP (metadata[1]));
+ map->index_table = (offset_type *) (addr + MAYBE_SWAP (metadata[2]));
+ map->index_table_slots = ((MAYBE_SWAP (metadata[3])
+ - MAYBE_SWAP (metadata[2]))
+ / (2 * sizeof (offset_type)));
+ map->constant_pool = addr + MAYBE_SWAP (metadata[3]);
+
+ if (!create_cus_from_index (objfile, map, cu_list, cu_list_elements))
+ return 0;
+
+ create_addrmap_from_index (objfile, map);
+
+ dwarf2_per_objfile->index_table = map;
+ dwarf2_per_objfile->using_index = 1;
+
+ return 1;
+}
+
+/* A helper for the "quick" functions which sets the global
+ dwarf2_per_objfile according to OBJFILE. */
+static void
+dw2_setup (struct objfile *objfile)
+{
+ dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
+ gdb_assert (dwarf2_per_objfile);
+}
+
+/* A helper for the "quick" functions which attempts to read the line
+ table for THIS_CU. */
+static void
+dw2_require_line_header (struct objfile *objfile,
+ struct dwarf2_per_cu_data *this_cu)
+{
+ bfd *abfd = objfile->obfd;
+ struct line_header *lh = NULL;
+ struct attribute *attr;
+ struct cleanup *cleanups;
+ struct die_info *comp_unit_die;
+ gdb_byte *beg_of_comp_unit, *info_ptr, *buffer;
+ int has_children, i;
+ struct dwarf2_cu cu;
+ unsigned int bytes_read, buffer_size;
+ struct die_reader_specs reader_specs;
+ char *name, *comp_dir;
+
+ if (this_cu->v.quick->read_lines)
+ return;
+ this_cu->v.quick->read_lines = 1;
+
+ memset (&cu, 0, sizeof (cu));
+ cu.objfile = objfile;
+ obstack_init (&cu.comp_unit_obstack);
+
+ cleanups = make_cleanup (free_stack_comp_unit, &cu);
+
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
+ buffer_size = dwarf2_per_objfile->info.size;
+ buffer = dwarf2_per_objfile->info.buffer;
+ info_ptr = buffer + this_cu->offset;
+ beg_of_comp_unit = info_ptr;
+
+ info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
+ buffer, buffer_size,
+ abfd);
+
+ /* Complete the cu_header. */
+ cu.header.offset = beg_of_comp_unit - buffer;
+ cu.header.first_die_offset = info_ptr - beg_of_comp_unit;
+
+ this_cu->cu = &cu;
+ cu.per_cu = this_cu;
+
+ dwarf2_read_abbrevs (abfd, &cu);
+ make_cleanup (dwarf2_free_abbrev_table, &cu);
+
+ if (this_cu->from_debug_types)
+ info_ptr += 8 /*signature*/ + cu.header.offset_size;
+ init_cu_die_reader (&reader_specs, &cu);
+ info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr,
+ &has_children);
+
+ attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, &cu);
+ if (attr)
+ {
+ unsigned int line_offset = DW_UNSND (attr);
+ lh = dwarf_decode_line_header (line_offset, abfd, &cu);
+ }
+ if (lh == NULL)
+ {
+ do_cleanups (cleanups);
+ return;
+ }
+
+ find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir);
+
+ this_cu->v.quick->lines = lh;
+
+ this_cu->v.quick->file_names
+ = obstack_alloc (&objfile->objfile_obstack,
+ lh->num_file_names * sizeof (char *));
+ for (i = 0; i < lh->num_file_names; ++i)
+ this_cu->v.quick->file_names[i] = file_full_name (i + 1, lh, comp_dir);
+
+ do_cleanups (cleanups);
+}
+
+/* A helper for the "quick" functions which computes and caches the
+ real path for a given file name from the line table.
+ dw2_require_line_header must have been called before this is
+ invoked. */
+static const char *
+dw2_require_full_path (struct objfile *objfile,
+ struct dwarf2_per_cu_data *cu,
+ int index)
+{
+ if (!cu->v.quick->full_names)
+ cu->v.quick->full_names
+ = OBSTACK_CALLOC (&objfile->objfile_obstack,
+ cu->v.quick->lines->num_file_names,
+ sizeof (char *));
+
+ if (!cu->v.quick->full_names[index])
+ cu->v.quick->full_names[index]
+ = gdb_realpath (cu->v.quick->file_names[index]);
+
+ return cu->v.quick->full_names[index];
+}
+
+static struct symtab *
+dw2_find_last_source_symtab (struct objfile *objfile)
+{
+ int index;
+ dw2_setup (objfile);
+ index = dwarf2_per_objfile->n_comp_units - 1;
+ return dw2_instantiate_symtab (objfile,
+ dwarf2_per_objfile->all_comp_units[index]);
+}
+
+static void
+dw2_forget_cached_source_info (struct objfile *objfile)
+{
+ int i;
+
+ dw2_setup (objfile);
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ if (cu->v.quick->full_names)
+ {
+ int j;
+
+ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j)
+ xfree ((void *) cu->v.quick->full_names[j]);
+ }
+ }
+}
+
+static int
+dw2_lookup_symtab (struct objfile *objfile, const char *name,
+ const char *full_path, const char *real_path,
+ struct symtab **result)
+{
+ int i;
+ int check_basename = lbasename (name) == name;
+ struct dwarf2_per_cu_data *base_cu = NULL;
+
+ dw2_setup (objfile);
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ int j;
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ if (cu->v.quick->symtab)
+ continue;
+
+ dw2_require_line_header (objfile, cu);
+ if (!cu->v.quick->lines)
+ continue;
+
+ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j)
+ {
+ const char *this_name = cu->v.quick->file_names[j];
+
+ if (FILENAME_CMP (name, this_name) == 0)
+ {
+ *result = dw2_instantiate_symtab (objfile, cu);
+ return 1;
+ }
+
+ if (check_basename && ! base_cu
+ && FILENAME_CMP (lbasename (this_name), name) == 0)
+ base_cu = cu;
+
+ if (full_path != NULL)
+ {
+ const char *this_full_name = dw2_require_full_path (objfile,
+ cu, j);
+
+ if (this_full_name
+ && FILENAME_CMP (full_path, this_full_name) == 0)
+ {
+ *result = dw2_instantiate_symtab (objfile, cu);
+ return 1;
+ }
+ }
+
+ if (real_path != NULL)
+ {
+ const char *this_full_name = dw2_require_full_path (objfile,
+ cu, j);
+
+ if (this_full_name != NULL)
+ {
+ char *rp = gdb_realpath (this_full_name);
+ if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
+ {
+ xfree (rp);
+ *result = dw2_instantiate_symtab (objfile, cu);
+ return 1;
+ }
+ xfree (rp);
+ }
+ }
+ }
+ }
+
+ if (base_cu)
+ {
+ *result = dw2_instantiate_symtab (objfile, base_cu);
+ return 1;
+ }
+
+ return 0;
+}
+
+static struct symtab *
+dw2_lookup_symbol (struct objfile *objfile, int block_index,
+ const char *name, domain_enum domain)
+{
+ /* We do all the work in the pre_expand_symtabs_matching hook
+ instead. */
+ return NULL;
+}
+
+/* A helper function that expands all symtabs that hold an object
+ named NAME. */
+static void
+dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name)
+{
+ dw2_setup (objfile);
+
+ if (dwarf2_per_objfile->index_table)
+ {
+ offset_type *vec;
+
+ if (find_slot_in_mapped_hash (dwarf2_per_objfile->index_table,
+ name, &vec))
+ {
+ offset_type i, len = MAYBE_SWAP (*vec);
+ for (i = 0; i < len; ++i)
+ {
+ offset_type cu_index = MAYBE_SWAP (vec[i + 1]);
+ struct dwarf2_per_cu_data *cu;
+ cu = dwarf2_per_objfile->all_comp_units[cu_index];
+ dw2_instantiate_symtab (objfile, cu);
+ }
+ }
+ }
+}
+
+static void
+dw2_pre_expand_symtabs_matching (struct objfile *objfile,
+ int kind, const char *name,
+ domain_enum domain)
+{
+ dw2_do_expand_symtabs_matching (objfile, name);
+}
+
+static void
+dw2_print_stats (struct objfile *objfile)
+{
+ int i, count;
+
+ dw2_setup (objfile);
+ count = 0;
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ if (!cu->v.quick->symtab)
+ ++count;
+ }
+ printf_filtered (_(" Number of unread CUs: %d\n"), count);
+}
+
+static void
+dw2_dump (struct objfile *objfile)
+{
+ /* Nothing worth printing. */
+}
+
+static void
+dw2_relocate (struct objfile *objfile, struct section_offsets *new_offsets,
+ struct section_offsets *delta)
+{
+ /* There's nothing to relocate here. */
+}
+
+static void
+dw2_expand_symtabs_for_function (struct objfile *objfile,
+ const char *func_name)
+{
+ dw2_do_expand_symtabs_matching (objfile, func_name);
+}
+
+static void
+dw2_expand_all_symtabs (struct objfile *objfile)
+{
+ int i;
+
+ dw2_setup (objfile);
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ dw2_instantiate_symtab (objfile, cu);
+ }
+}
+
+static void
+dw2_expand_symtabs_with_filename (struct objfile *objfile,
+ const char *filename)
+{
+ int i;
+
+ dw2_setup (objfile);
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ int j;
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ if (cu->v.quick->symtab)
+ continue;
+
+ dw2_require_line_header (objfile, cu);
+ if (!cu->v.quick->lines)
+ continue;
+
+ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j)
+ {
+ const char *this_name = cu->v.quick->file_names[j];
+ if (strcmp (this_name, filename) == 0)
+ {
+ dw2_instantiate_symtab (objfile, cu);
+ break;
+ }
+ }
+ }
+}
+
+static char *
+dw2_find_symbol_file (struct objfile *objfile, const char *name)
+{
+ struct dwarf2_per_cu_data *cu;
+ offset_type *vec;
+
+ dw2_setup (objfile);
+
+ if (!dwarf2_per_objfile->index_table)
+ return NULL;
+
+ if (!find_slot_in_mapped_hash (dwarf2_per_objfile->index_table,
+ name, &vec))
+ return NULL;
+
+ /* Note that this just looks at the very first one named NAME -- but
+ actually we are looking for a function. find_main_filename
+ should be rewritten so that it doesn't require a custom hook. It
+ could just use the ordinary symbol tables. */
+ /* vec[0] is the length, which must always be >0. */
+ cu = dwarf2_per_objfile->all_comp_units[MAYBE_SWAP (vec[1])];
+
+ dw2_require_line_header (objfile, cu);
+ if (!cu->v.quick->lines)
+ return NULL;
+
+ return (char *) cu->v.quick->file_names[cu->v.quick->lines->num_file_names
+ - 1];
+}
+
+static void
+dw2_map_ada_symtabs (struct objfile *objfile,
+ int (*wild_match) (const char *, int, const char *),
+ int (*is_name_suffix) (const char *),
+ void (*callback) (struct objfile *,
+ struct symtab *, void *),
+ const char *name, int global,
+ domain_enum namespace, int wild,
+ void *data)
+{
+ /* For now, we don't support Ada, so this function can't be
+ reached. */
+ internal_error (__FILE__, __LINE__,
+ _("map_ada_symtabs called via index method"));
+}
+
+static void
+dw2_expand_symtabs_matching (struct objfile *objfile,
+ int (*file_matcher) (const char *, void *),
+ int (*name_matcher) (const char *, void *),
+ domain_enum kind,
+ void *data)
+{
+ int i;
+ offset_type iter;
+
+ dw2_setup (objfile);
+ if (!dwarf2_per_objfile->index_table)
+ return;
+
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ int j;
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ cu->v.quick->mark = 0;
+ if (cu->v.quick->symtab)
+ continue;
+
+ dw2_require_line_header (objfile, cu);
+ if (!cu->v.quick->lines)
+ continue;
+
+ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j)
+ {
+ if (file_matcher (cu->v.quick->file_names[j], data))
+ {
+ cu->v.quick->mark = 1;
+ break;
+ }
+ }
+ }
+
+ for (iter = 0;
+ iter < dwarf2_per_objfile->index_table->index_table_slots;
+ ++iter)
+ {
+ offset_type idx = 2 * iter;
+ const char *name;
+ offset_type *vec, vec_len, vec_idx;
+
+ if (dwarf2_per_objfile->index_table->index_table[idx] == 0
+ && dwarf2_per_objfile->index_table->index_table[idx + 1] == 0)
+ continue;
+
+ name = (dwarf2_per_objfile->index_table->constant_pool
+ + dwarf2_per_objfile->index_table->index_table[idx]);
+
+ if (! (*name_matcher) (name, data))
+ continue;
+
+ /* The name was matched, now expand corresponding CUs that were
+ marked. */
+ vec = (offset_type *) (dwarf2_per_objfile->index_table->constant_pool
+ + dwarf2_per_objfile->index_table->index_table[idx + 1]);
+ vec_len = MAYBE_SWAP (vec[0]);
+ for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
+ {
+ struct dwarf2_per_cu_data *cu
+ = dwarf2_per_objfile->all_comp_units[MAYBE_SWAP (vec[vec_idx + 1])];
+ if (cu->v.quick->mark)
+ dw2_instantiate_symtab (objfile, cu);
+ }
+ }
+}
+
+static struct symtab *
+dw2_find_pc_sect_symtab (struct objfile *objfile,
+ struct minimal_symbol *msymbol,
+ CORE_ADDR pc,
+ struct obj_section *section,
+ int warn_if_readin)
+{
+ struct dwarf2_per_cu_data *data;
+
+ dw2_setup (objfile);
+
+ if (!objfile->psymtabs_addrmap)
+ return NULL;
+
+ data = addrmap_find (objfile->psymtabs_addrmap, pc);
+ if (!data)
+ return NULL;
+
+ if (warn_if_readin && data->v.quick->symtab)
+ warning (_("(Internal error: pc %s in read in CU, but not in symtab.)\n"),
+ paddress (get_objfile_arch (objfile), pc));
+
+ return dw2_instantiate_symtab (objfile, data);
+}
+
+static void
+dw2_map_symbol_names (struct objfile *objfile,
+ void (*fun) (const char *, void *),
+ void *data)
+{
+ offset_type iter;
+ dw2_setup (objfile);
+
+ if (!dwarf2_per_objfile->index_table)
+ return;
+
+ for (iter = 0;
+ iter < dwarf2_per_objfile->index_table->index_table_slots;
+ ++iter)
+ {
+ offset_type idx = 2 * iter;
+ const char *name;
+ offset_type *vec, vec_len, vec_idx;
+
+ if (dwarf2_per_objfile->index_table->index_table[idx] == 0
+ && dwarf2_per_objfile->index_table->index_table[idx + 1] == 0)
+ continue;
+
+ name = (dwarf2_per_objfile->index_table->constant_pool
+ + dwarf2_per_objfile->index_table->index_table[idx]);
+
+ (*fun) (name, data);
+ }
+}
+
+static void
+dw2_map_symbol_filenames (struct objfile *objfile,
+ void (*fun) (const char *, const char *, void *),
+ void *data)
+{
+ int i;
+
+ dw2_setup (objfile);
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ int j;
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ if (cu->v.quick->symtab)
+ continue;
+
+ dw2_require_line_header (objfile, cu);
+ if (!cu->v.quick->lines)
+ continue;
+
+ for (j = 0; j < cu->v.quick->lines->num_file_names; ++j)
+ {
+ const char *this_full_name = dw2_require_full_path (objfile, cu, j);
+ (*fun) (cu->v.quick->file_names[j], this_full_name, data);
+ }
+ }
+}
+
+static int
+dw2_has_symbols (struct objfile *objfile)
+{
+ return 1;
+}
+
+const struct quick_symbol_functions dwarf2_gdb_index_functions =
+{
+ dw2_has_symbols,
+ dw2_find_last_source_symtab,
+ dw2_forget_cached_source_info,
+ dw2_lookup_symtab,
+ dw2_lookup_symbol,
+ dw2_pre_expand_symtabs_matching,
+ dw2_print_stats,
+ dw2_dump,
+ dw2_relocate,
+ dw2_expand_symtabs_for_function,
+ dw2_expand_all_symtabs,
+ dw2_expand_symtabs_with_filename,
+ dw2_find_symbol_file,
+ dw2_map_ada_symtabs,
+ dw2_expand_symtabs_matching,
+ dw2_find_pc_sect_symtab,
+ dw2_map_symbol_names,
+ dw2_map_symbol_filenames
+};
+
+/* Initialize for reading DWARF for this objfile. Return 0 if this
+ file will use psymtabs, or 1 if using the GNU index. */
+
+int
+dwarf2_initialize_objfile (struct objfile *objfile)
+{
+ /* If we're about to read full symbols, don't bother with the
+ indices. In this case we also don't care if some other debug
+ format is making psymtabs, because they are all about to be
+ expanded anyway. */
+ if ((objfile->flags & OBJF_READNOW))
+ {
+ int i;
+
+ dwarf2_per_objfile->using_index = 1;
+ create_all_comp_units (objfile);
+
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ struct dwarf2_per_cu_data *cu = dwarf2_per_objfile->all_comp_units[i];
+
+ cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_quick_data);
+ }
+
+ /* Return 1 so that gdb sees the "quick" functions. However,
+ these functions will be no-ops because we will have expanded
+ all symtabs. */
+ return 1;
+ }
+
+ if (dwarf2_read_index (objfile))
+ return 1;
+
+ dwarf2_build_psymtabs (objfile);
+ return 0;
+}
+
+\f
+