+ reader->comp_dir = NULL;
+}
+
+/* Subroutine of init_cutu_and_read_dies to simplify it.
+ Read in the rest of a CU/TU top level DIE from DWO_UNIT.
+ There's just a lot of work to do, and init_cutu_and_read_dies is big enough
+ already.
+
+ STUB_COMP_UNIT_DIE is for the stub DIE, we copy over certain attributes
+ from it to the DIE in the DWO. If NULL we are skipping the stub.
+ STUB_COMP_DIR is similar to STUB_COMP_UNIT_DIE: When reading a TU directly
+ from the DWO file, bypassing the stub, it contains the DW_AT_comp_dir
+ attribute of the referencing CU. Exactly one of STUB_COMP_UNIT_DIE and
+ COMP_DIR must be non-NULL.
+ *RESULT_READER,*RESULT_INFO_PTR,*RESULT_COMP_UNIT_DIE,*RESULT_HAS_CHILDREN
+ are filled in with the info of the DIE from the DWO file.
+ ABBREV_TABLE_PROVIDED is non-zero if the caller of init_cutu_and_read_dies
+ provided an abbrev table to use.
+ The result is non-zero if a valid (non-dummy) DIE was found. */
+
+static int
+read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
+ struct dwo_unit *dwo_unit,
+ int abbrev_table_provided,
+ struct die_info *stub_comp_unit_die,
+ const char *stub_comp_dir,
+ struct die_reader_specs *result_reader,
+ const gdb_byte **result_info_ptr,
+ struct die_info **result_comp_unit_die,
+ int *result_has_children)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwarf2_cu *cu = this_cu->cu;
+ struct dwarf2_section_info *section;
+ bfd *abfd;
+ const gdb_byte *begin_info_ptr, *info_ptr;
+ const char *comp_dir_string;
+ ULONGEST signature; /* Or dwo_id. */
+ struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
+ int i,num_extra_attrs;
+ struct dwarf2_section_info *dwo_abbrev_section;
+ struct attribute *attr;
+ struct attribute comp_dir_attr;
+ struct die_info *comp_unit_die;
+
+ /* Both can't be provided. */
+ gdb_assert (! (stub_comp_unit_die && stub_comp_dir));
+
+ /* These attributes aren't processed until later:
+ DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
+ However, the attribute is found in the stub which we won't have later.
+ In order to not impose this complication on the rest of the code,
+ we read them here and copy them to the DWO CU/TU die. */
+
+ stmt_list = NULL;
+ low_pc = NULL;
+ high_pc = NULL;
+ ranges = NULL;
+ comp_dir = NULL;
+
+ if (stub_comp_unit_die != NULL)
+ {
+ /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
+ DWO file. */
+ if (! this_cu->is_debug_types)
+ stmt_list = dwarf2_attr (stub_comp_unit_die, DW_AT_stmt_list, cu);
+ low_pc = dwarf2_attr (stub_comp_unit_die, DW_AT_low_pc, cu);
+ high_pc = dwarf2_attr (stub_comp_unit_die, DW_AT_high_pc, cu);
+ ranges = dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu);
+ comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);
+
+ /* There should be a DW_AT_addr_base attribute here (if needed).
+ We need the value before we can process DW_FORM_GNU_addr_index. */
+ cu->addr_base = 0;
+ attr = dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_addr_base, cu);
+ if (attr)
+ cu->addr_base = DW_UNSND (attr);
+
+ /* There should be a DW_AT_ranges_base attribute here (if needed).
+ We need the value before we can process DW_AT_ranges. */
+ cu->ranges_base = 0;
+ attr = dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_ranges_base, cu);
+ if (attr)
+ cu->ranges_base = DW_UNSND (attr);
+ }
+ else if (stub_comp_dir != NULL)
+ {
+ /* Reconstruct the comp_dir attribute to simplify the code below. */
+ comp_dir = (struct attribute *)
+ obstack_alloc (&cu->comp_unit_obstack, sizeof (*comp_dir));
+ comp_dir->name = DW_AT_comp_dir;
+ comp_dir->form = DW_FORM_string;
+ DW_STRING_IS_CANONICAL (comp_dir) = 0;
+ DW_STRING (comp_dir) = stub_comp_dir;
+ }
+
+ /* Set up for reading the DWO CU/TU. */
+ cu->dwo_unit = dwo_unit;
+ section = dwo_unit->section;
+ dwarf2_read_section (objfile, section);
+ abfd = section->asection->owner;
+ begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
+ dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
+ init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file);
+
+ if (this_cu->is_debug_types)
+ {
+ ULONGEST header_signature;
+ cu_offset type_offset_in_tu;
+ struct signatured_type *sig_type = (struct signatured_type *) this_cu;
+
+ info_ptr = read_and_check_type_unit_head (&cu->header, section,
+ dwo_abbrev_section,
+ info_ptr,
+ &header_signature,
+ &type_offset_in_tu);
+ /* This is not an assert because it can be caused by bad debug info. */
+ if (sig_type->signature != header_signature)
+ {
+ error (_("Dwarf Error: signature mismatch %s vs %s while reading"
+ " TU at offset 0x%x [in module %s]"),
+ hex_string (sig_type->signature),
+ hex_string (header_signature),
+ dwo_unit->offset.sect_off,
+ bfd_get_filename (abfd));
+ }
+ gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+ /* For DWOs coming from DWP files, we don't know the CU length
+ nor the type's offset in the TU until now. */
+ dwo_unit->length = get_cu_length (&cu->header);
+ dwo_unit->type_offset_in_tu = type_offset_in_tu;
+
+ /* Establish the type offset that can be used to lookup the type.
+ For DWO files, we don't know it until now. */
+ sig_type->type_offset_in_section.sect_off =
+ dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off;
+ }
+ else
+ {
+ info_ptr = read_and_check_comp_unit_head (&cu->header, section,
+ dwo_abbrev_section,
+ info_ptr, 0);
+ gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+ /* For DWOs coming from DWP files, we don't know the CU length
+ until now. */
+ dwo_unit->length = get_cu_length (&cu->header);
+ }
+
+ /* Replace the CU's original abbrev table with the DWO's.
+ Reminder: We can't read the abbrev table until we've read the header. */
+ if (abbrev_table_provided)
+ {
+ /* Don't free the provided abbrev table, the caller of
+ init_cutu_and_read_dies owns it. */
+ dwarf2_read_abbrevs (cu, dwo_abbrev_section);
+ /* Ensure the DWO abbrev table gets freed. */
+ make_cleanup (dwarf2_free_abbrev_table, cu);
+ }
+ else
+ {
+ dwarf2_free_abbrev_table (cu);
+ dwarf2_read_abbrevs (cu, dwo_abbrev_section);
+ /* Leave any existing abbrev table cleanup as is. */
+ }
+
+ /* Read in the die, but leave space to copy over the attributes
+ from the stub. This has the benefit of simplifying the rest of
+ the code - all the work to maintain the illusion of a single
+ DW_TAG_{compile,type}_unit DIE is done here. */
+ num_extra_attrs = ((stmt_list != NULL)
+ + (low_pc != NULL)
+ + (high_pc != NULL)
+ + (ranges != NULL)
+ + (comp_dir != NULL));
+ info_ptr = read_full_die_1 (result_reader, result_comp_unit_die, info_ptr,
+ result_has_children, num_extra_attrs);
+
+ /* Copy over the attributes from the stub to the DIE we just read in. */
+ comp_unit_die = *result_comp_unit_die;
+ i = comp_unit_die->num_attrs;
+ if (stmt_list != NULL)
+ comp_unit_die->attrs[i++] = *stmt_list;
+ if (low_pc != NULL)
+ comp_unit_die->attrs[i++] = *low_pc;
+ if (high_pc != NULL)
+ comp_unit_die->attrs[i++] = *high_pc;
+ if (ranges != NULL)
+ comp_unit_die->attrs[i++] = *ranges;
+ if (comp_dir != NULL)
+ comp_unit_die->attrs[i++] = *comp_dir;
+ comp_unit_die->num_attrs += num_extra_attrs;
+
+ if (dwarf2_die_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Read die from %s@0x%x of %s:\n",
+ bfd_section_name (abfd, section->asection),
+ (unsigned) (begin_info_ptr - section->buffer),
+ bfd_get_filename (abfd));
+ dump_die (comp_unit_die, dwarf2_die_debug);
+ }
+
+ /* Save the comp_dir attribute. If there is no DWP file then we'll read
+ TUs by skipping the stub and going directly to the entry in the DWO file.
+ However, skipping the stub means we won't get DW_AT_comp_dir, so we have
+ to get it via circuitous means. Blech. */
+ if (comp_dir != NULL)
+ result_reader->comp_dir = DW_STRING (comp_dir);
+
+ /* Skip dummy compilation units. */
+ if (info_ptr >= begin_info_ptr + dwo_unit->length
+ || peek_abbrev_code (abfd, info_ptr) == 0)
+ return 0;
+
+ *result_info_ptr = info_ptr;
+ return 1;
+}
+
+/* Subroutine of init_cutu_and_read_dies to simplify it.
+ Look up the DWO unit specified by COMP_UNIT_DIE of THIS_CU.
+ Returns NULL if the specified DWO unit cannot be found. */
+
+static struct dwo_unit *
+lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
+ struct die_info *comp_unit_die)
+{
+ struct dwarf2_cu *cu = this_cu->cu;
+ struct attribute *attr;
+ ULONGEST signature;
+ struct dwo_unit *dwo_unit;
+ const char *comp_dir, *dwo_name;
+
+ gdb_assert (cu != NULL);
+
+ /* Yeah, we look dwo_name up again, but it simplifies the code. */
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
+ gdb_assert (attr != NULL);
+ dwo_name = DW_STRING (attr);
+ comp_dir = NULL;
+ attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
+ if (attr)
+ comp_dir = DW_STRING (attr);
+
+ if (this_cu->is_debug_types)
+ {
+ struct signatured_type *sig_type;
+
+ /* Since this_cu is the first member of struct signatured_type,
+ we can go from a pointer to one to a pointer to the other. */
+ sig_type = (struct signatured_type *) this_cu;
+ signature = sig_type->signature;
+ dwo_unit = lookup_dwo_type_unit (sig_type, dwo_name, comp_dir);
+ }
+ else
+ {
+ struct attribute *attr;
+
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
+ if (! attr)
+ error (_("Dwarf Error: missing dwo_id for dwo_name %s"
+ " [in module %s]"),
+ dwo_name, this_cu->objfile->name);
+ signature = DW_UNSND (attr);
+ dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir,
+ signature);
+ }
+
+ return dwo_unit;
+}
+
+/* Subroutine of init_cutu_and_read_dies to simplify it.
+ Read a TU directly from a DWO file, bypassing the stub. */
+
+static void
+init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu, int keep,
+ die_reader_func_ftype *die_reader_func,
+ void *data)
+{
+ struct dwarf2_cu *cu;
+ struct signatured_type *sig_type;
+ struct cleanup *cleanups, *free_cu_cleanup;
+ struct die_reader_specs reader;
+ const gdb_byte *info_ptr;
+ struct die_info *comp_unit_die;
+ int has_children;
+
+ /* Verify we can do the following downcast, and that we have the
+ data we need. */
+ gdb_assert (this_cu->is_debug_types && this_cu->reading_dwo_directly);
+ sig_type = (struct signatured_type *) this_cu;
+ gdb_assert (sig_type->dwo_unit != NULL);
+
+ cleanups = make_cleanup (null_cleanup, NULL);
+
+ gdb_assert (this_cu->cu == NULL);
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, this_cu);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+
+ if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
+ 0 /* abbrev_table_provided */,
+ NULL /* stub_comp_unit_die */,
+ sig_type->dwo_unit->dwo_file->comp_dir,
+ &reader, &info_ptr,
+ &comp_unit_die, &has_children) == 0)
+ {
+ /* Dummy die. */
+ do_cleanups (cleanups);
+ return;
+ }
+
+ /* All the "real" work is done here. */
+ die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
+
+ /* This duplicates some code in init_cutu_and_read_dies,
+ but the alternative is making the latter more complex.
+ This function is only for the special case of using DWO files directly:
+ no point in overly complicating the general case just to handle this. */
+ if (keep)
+ {
+ /* We've successfully allocated this compilation unit. Let our
+ caller clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
+
+ /* We can only discard free_cu_cleanup and all subsequent cleanups.
+ So we have to manually free the abbrev table. */
+ dwarf2_free_abbrev_table (cu);
+
+ /* Link this CU into read_in_chain. */
+ this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = this_cu;
+ }
+ else
+ do_cleanups (free_cu_cleanup);
+
+ do_cleanups (cleanups);