+ /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
+
+ return dwo_unit;
+}
+
+/* Subroutine of create_dwo_unit_in_dwp_v2 to simplify it.
+ Given a pointer to the containing section SECTION, and OFFSET,SIZE of the
+ piece within that section used by a TU/CU, return a virtual section
+ of just that piece. */
+
+static struct dwarf2_section_info
+create_dwp_v2_section (struct dwarf2_section_info *section,
+ bfd_size_type offset, bfd_size_type size)
+{
+ struct dwarf2_section_info result;
+ asection *sectp;
+
+ gdb_assert (section != NULL);
+ gdb_assert (!section->is_virtual);
+
+ memset (&result, 0, sizeof (result));
+ result.s.containing_section = section;
+ result.is_virtual = 1;
+
+ if (size == 0)
+ return result;
+
+ sectp = get_section_bfd_section (section);
+
+ /* Flag an error if the piece denoted by OFFSET,SIZE is outside the
+ bounds of the real section. This is a pretty-rare event, so just
+ flag an error (easier) instead of a warning and trying to cope. */
+ if (sectp == NULL
+ || offset + size > bfd_get_section_size (sectp))
+ {
+ bfd *abfd = sectp->owner;
+
+ error (_("Dwarf Error: Bad DWP V2 section info, doesn't fit"
+ " in section %s [in module %s]"),
+ sectp ? bfd_section_name (abfd, sectp) : "<unknown>",
+ objfile_name (dwarf2_per_objfile->objfile));
+ }
+
+ result.virtual_offset = offset;
+ result.size = size;
+ return result;
+}
+
+/* Create a dwo_unit object for the DWO unit with signature SIGNATURE.
+ UNIT_INDEX is the index of the DWO unit in the DWP hash table.
+ COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
+ This is for DWP version 2 files. */
+
+static struct dwo_unit *
+create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
+ uint32_t unit_index,
+ const char *comp_dir,
+ ULONGEST signature, int is_debug_types)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const struct dwp_hash_table *dwp_htab =
+ is_debug_types ? dwp_file->tus : dwp_file->cus;
+ bfd *dbfd = dwp_file->dbfd;
+ const char *kind = is_debug_types ? "TU" : "CU";
+ struct dwo_file *dwo_file;
+ struct dwo_unit *dwo_unit;
+ struct virtual_v2_dwo_sections sections;
+ void **dwo_file_slot;
+ char *virtual_dwo_name;
+ struct dwarf2_section_info *cutu;
+ struct cleanup *cleanups;
+ int i;
+
+ gdb_assert (dwp_file->version == 2);
+
+ if (dwarf_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V2 file: %s\n",
+ kind,
+ pulongest (unit_index), hex_string (signature),
+ dwp_file->name);
+ }
+
+ /* Fetch the section offsets of this DWO unit. */
+
+ memset (§ions, 0, sizeof (sections));
+ cleanups = make_cleanup (null_cleanup, 0);
+
+ for (i = 0; i < dwp_htab->nr_columns; ++i)
+ {
+ uint32_t offset = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v2.offsets
+ + (((unit_index - 1) * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+ uint32_t size = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v2.sizes
+ + (((unit_index - 1) * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+
+ switch (dwp_htab->section_pool.v2.section_ids[i])
+ {
+ case DW_SECT_INFO:
+ case DW_SECT_TYPES:
+ sections.info_or_types_offset = offset;
+ sections.info_or_types_size = size;
+ break;
+ case DW_SECT_ABBREV:
+ sections.abbrev_offset = offset;
+ sections.abbrev_size = size;
+ break;
+ case DW_SECT_LINE:
+ sections.line_offset = offset;
+ sections.line_size = size;
+ break;
+ case DW_SECT_LOC:
+ sections.loc_offset = offset;
+ sections.loc_size = size;
+ break;
+ case DW_SECT_STR_OFFSETS:
+ sections.str_offsets_offset = offset;
+ sections.str_offsets_size = size;
+ break;
+ case DW_SECT_MACINFO:
+ sections.macinfo_offset = offset;
+ sections.macinfo_size = size;
+ break;
+ case DW_SECT_MACRO:
+ sections.macro_offset = offset;
+ sections.macro_size = size;
+ break;
+ }
+ }
+
+ /* It's easier for the rest of the code if we fake a struct dwo_file and
+ have dwo_unit "live" in that. At least for now.
+
+ The DWP file can be made up of a random collection of CUs and TUs.
+ However, for each CU + set of TUs that came from the same original DWO
+ file, we can combine them back into a virtual DWO file to save space
+ (fewer struct dwo_file objects to allocate). Remember that for really
+ large apps there can be on the order of 8K CUs and 200K TUs, or more. */
+
+ virtual_dwo_name =
+ xstrprintf ("virtual-dwo/%ld-%ld-%ld-%ld",
+ (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
+ (long) (sections.line_size ? sections.line_offset : 0),
+ (long) (sections.loc_size ? sections.loc_offset : 0),
+ (long) (sections.str_offsets_size
+ ? sections.str_offsets_offset : 0));
+ make_cleanup (xfree, virtual_dwo_name);
+ /* Can we use an existing virtual DWO file? */
+ dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
+ /* Create one if necessary. */
+ if (*dwo_file_slot == NULL)
+ {
+ if (dwarf_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
+ virtual_dwo_name);
+ }
+ dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
+ dwo_file->dwo_name
+ = (const char *) obstack_copy0 (&objfile->objfile_obstack,
+ virtual_dwo_name,
+ strlen (virtual_dwo_name));
+ dwo_file->comp_dir = comp_dir;
+ dwo_file->sections.abbrev =
+ create_dwp_v2_section (&dwp_file->sections.abbrev,
+ sections.abbrev_offset, sections.abbrev_size);
+ dwo_file->sections.line =
+ create_dwp_v2_section (&dwp_file->sections.line,
+ sections.line_offset, sections.line_size);
+ dwo_file->sections.loc =
+ create_dwp_v2_section (&dwp_file->sections.loc,
+ sections.loc_offset, sections.loc_size);
+ dwo_file->sections.macinfo =
+ create_dwp_v2_section (&dwp_file->sections.macinfo,
+ sections.macinfo_offset, sections.macinfo_size);
+ dwo_file->sections.macro =
+ create_dwp_v2_section (&dwp_file->sections.macro,
+ sections.macro_offset, sections.macro_size);
+ dwo_file->sections.str_offsets =
+ create_dwp_v2_section (&dwp_file->sections.str_offsets,
+ sections.str_offsets_offset,
+ sections.str_offsets_size);
+ /* The "str" section is global to the entire DWP file. */
+ dwo_file->sections.str = dwp_file->sections.str;
+ /* The info or types section is assigned below to dwo_unit,
+ there's no need to record it in dwo_file.
+ Also, we can't simply record type sections in dwo_file because
+ we record a pointer into the vector in dwo_unit. As we collect more
+ types we'll grow the vector and eventually have to reallocate space
+ for it, invalidating all copies of pointers into the previous
+ contents. */
+ *dwo_file_slot = dwo_file;
+ }
+ else
+ {
+ if (dwarf_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
+ virtual_dwo_name);
+ }
+ dwo_file = (struct dwo_file *) *dwo_file_slot;
+ }
+ do_cleanups (cleanups);
+
+ dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
+ dwo_unit->dwo_file = dwo_file;
+ dwo_unit->signature = signature;
+ dwo_unit->section =
+ XOBNEW (&objfile->objfile_obstack, struct dwarf2_section_info);
+ *dwo_unit->section = create_dwp_v2_section (is_debug_types
+ ? &dwp_file->sections.types
+ : &dwp_file->sections.info,
+ sections.info_or_types_offset,
+ sections.info_or_types_size);
+ /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */