/* Reading code for .debug_names

   Copyright (C) 2023-2024 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "read-debug-names.h"
#include "dwarf2/aranges.h"
#include "dwarf2/cooked-index.h"

#include "complaints.h"
#include "cp-support.h"
#include "dwz.h"
#include "mapped-index.h"
#include "read.h"
#include "stringify.h"

/* This is just like cooked_index_functions, but overrides a single
   method so the test suite can distinguish the .debug_names case from
   the ordinary case.  */
struct dwarf2_debug_names_index : public cooked_index_functions
{
  /* This dumps minimal information about .debug_names.  It is called
     via "mt print objfiles".  The gdb.dwarf2/gdb-index.exp testcase
     uses this to verify that .debug_names has been loaded.  */
  void dump (struct objfile *objfile) override
  {
    gdb_printf (".debug_names: exists\n");
    /* This could call the superclass method if that's useful.  */
  }
};

/* This is like a cooked index, but as it has been ingested from
   .debug_names, it can't be used to write out an index.  */
class debug_names_index : public cooked_index
{
public:

  using cooked_index::cooked_index;

  cooked_index *index_for_writing () override
  { return nullptr; }

  quick_symbol_functions_up make_quick_functions () const override
  { return quick_symbol_functions_up (new dwarf2_debug_names_index); }
};

/* A description of the mapped .debug_names.  */

struct mapped_debug_names_reader
{
  const gdb_byte *scan_one_entry (const char *name,
				  const gdb_byte *entry,
				  cooked_index_entry **result,
				  std::optional<ULONGEST> &parent);
  void scan_entries (uint32_t index, const char *name, const gdb_byte *entry);
  void scan_all_names ();

  dwarf2_per_objfile *per_objfile = nullptr;
  bfd *abfd = nullptr;
  bfd_endian dwarf5_byte_order {};
  bool dwarf5_is_dwarf64 = false;
  bool augmentation_is_gdb = false;
  uint8_t offset_size = 0;
  uint32_t cu_count = 0;
  uint32_t tu_count = 0, bucket_count = 0, name_count = 0;
  const gdb_byte *cu_table_reordered = nullptr;
  const gdb_byte *tu_table_reordered = nullptr;
  const uint32_t *bucket_table_reordered = nullptr;
  const uint32_t *hash_table_reordered = nullptr;
  const gdb_byte *name_table_string_offs_reordered = nullptr;
  const gdb_byte *name_table_entry_offs_reordered = nullptr;
  const gdb_byte *entry_pool = nullptr;

  struct index_val
  {
    ULONGEST dwarf_tag;
    struct attr
    {
      /* Attribute name DW_IDX_*.  */
      ULONGEST dw_idx;

      /* Attribute form DW_FORM_*.  */
      ULONGEST form;

      /* Value if FORM is DW_FORM_implicit_const.  */
      LONGEST implicit_const;
    };
    std::vector<attr> attr_vec;
  };

  std::unordered_map<ULONGEST, index_val> abbrev_map;

  std::unique_ptr<cooked_index_shard> shard;
  std::vector<std::pair<cooked_index_entry *, ULONGEST>> needs_parent;
  std::vector<std::vector<cooked_index_entry *>> all_entries;
};

/* Scan a single entry from the entries table.  Set *RESULT and PARENT
   (if needed) and return the updated pointer on success, or return
   nullptr on error, or at the end of the table.  */

const gdb_byte *
mapped_debug_names_reader::scan_one_entry (const char *name,
					   const gdb_byte *entry,
					   cooked_index_entry **result,
					   std::optional<ULONGEST> &parent)
{
  unsigned int bytes_read;
  const ULONGEST abbrev = read_unsigned_leb128 (abfd, entry, &bytes_read);
  entry += bytes_read;
  if (abbrev == 0)
    return nullptr;

  const auto indexval_it = abbrev_map.find (abbrev);
  if (indexval_it == abbrev_map.cend ())
    {
      complaint (_("Wrong .debug_names undefined abbrev code %s "
		   "[in module %s]"),
		 pulongest (abbrev), bfd_get_filename (abfd));
      return nullptr;
    }

  const auto &indexval = indexval_it->second;
  cooked_index_flag flags = 0;
  sect_offset die_offset {};
  enum language lang = language_unknown;
  dwarf2_per_cu_data *per_cu = nullptr;
  for (const auto &attr : indexval.attr_vec)
    {
      ULONGEST ull;
      switch (attr.form)
	{
	case DW_FORM_implicit_const:
	  ull = attr.implicit_const;
	  break;
	case DW_FORM_flag_present:
	  ull = 1;
	  break;
	case DW_FORM_udata:
	  ull = read_unsigned_leb128 (abfd, entry, &bytes_read);
	  entry += bytes_read;
	  break;
	case DW_FORM_ref_addr:
	  ull = read_offset (abfd, entry, offset_size);
	  entry += offset_size;
	  break;
	case DW_FORM_ref4:
	  ull = read_4_bytes (abfd, entry);
	  entry += 4;
	  break;
	case DW_FORM_ref8:
	  ull = read_8_bytes (abfd, entry);
	  entry += 8;
	  break;
	case DW_FORM_ref_sig8:
	  ull = read_8_bytes (abfd, entry);
	  entry += 8;
	  break;
	default:
	  complaint (_("Unsupported .debug_names form %s [in module %s]"),
		     dwarf_form_name (attr.form),
		     bfd_get_filename (abfd));
	  return nullptr;
	}
      switch (attr.dw_idx)
	{
	case DW_IDX_compile_unit:
	  {
	    /* Don't crash on bad data.  */
	    if (ull >= per_objfile->per_bfd->all_comp_units.size ())
	      {
		complaint (_(".debug_names entry has bad CU index %s"
			     " [in module %s]"),
			   pulongest (ull),
			   bfd_get_filename (abfd));
		continue;
	      }
	  }
	  per_cu = per_objfile->per_bfd->get_cu (ull);
	  break;
	case DW_IDX_type_unit:
	  /* Don't crash on bad data.  */
	  if (ull >= per_objfile->per_bfd->all_type_units.size ())
	    {
	      complaint (_(".debug_names entry has bad TU index %s"
			   " [in module %s]"),
			 pulongest (ull),
			 bfd_get_filename (abfd));
	      continue;
	    }
	  {
	    int nr_cus = per_objfile->per_bfd->all_comp_units.size ();
	    per_cu = per_objfile->per_bfd->get_cu (nr_cus + ull);
	  }
	  break;
	case DW_IDX_die_offset:
	  die_offset = sect_offset (ull);
	  /* In a per-CU index (as opposed to a per-module index), index
	     entries without CU attribute implicitly refer to the single CU.  */
	  if (per_cu == NULL)
	    per_cu = per_objfile->per_bfd->get_cu (0);
	  break;
	case DW_IDX_parent:
	  parent = ull;
	  break;
	case DW_IDX_GNU_internal:
	  if (augmentation_is_gdb && ull != 0)
	    flags |= IS_STATIC;
	  break;
	case DW_IDX_GNU_main:
	  if (augmentation_is_gdb && ull != 0)
	    flags |= IS_MAIN;
	  break;
	case DW_IDX_GNU_language:
	  if (augmentation_is_gdb)
	    lang = dwarf_lang_to_enum_language (ull);
	  break;
	case DW_IDX_GNU_linkage_name:
	  if (augmentation_is_gdb && ull != 0)
	    flags |= IS_LINKAGE;
	  break;
	}
    }

  /* Skip if we couldn't find a valid CU/TU index.  */
  if (per_cu != nullptr)
    *result = shard->add (die_offset, (dwarf_tag) indexval.dwarf_tag, flags,
			  lang, name, nullptr, per_cu);
  return entry;
}

/* Scan all the entries for NAME, at name slot INDEX.  */

void
mapped_debug_names_reader::scan_entries (uint32_t index,
					 const char *name,
					 const gdb_byte *entry)
{
  std::vector<cooked_index_entry *> these_entries;
  
  while (true)
    {
      std::optional<ULONGEST> parent;
      cooked_index_entry *this_entry;
      entry = scan_one_entry (name, entry, &this_entry, parent);

      if (entry == nullptr)
	break;

      these_entries.push_back (this_entry);
      if (parent.has_value ())
	needs_parent.emplace_back (this_entry, *parent);
    }

  all_entries[index] = std::move (these_entries);
}

/* Scan the name table and create all the entries.  */

void
mapped_debug_names_reader::scan_all_names ()
{
  all_entries.resize (name_count);

  /* In the first pass, create all the entries.  */
  for (uint32_t i = 0; i < name_count; ++i)
    {
      const ULONGEST namei_string_offs
	= extract_unsigned_integer ((name_table_string_offs_reordered
				     + i * offset_size),
				    offset_size, dwarf5_byte_order);
      const char *name = read_indirect_string_at_offset (per_objfile,
							 namei_string_offs);

      const ULONGEST namei_entry_offs
	= extract_unsigned_integer ((name_table_entry_offs_reordered
				     + i * offset_size),
				    offset_size, dwarf5_byte_order);
      const gdb_byte *entry = entry_pool + namei_entry_offs;

      scan_entries (i, name, entry);
    }

  /* Now update the parent pointers for all entries.  This has to be
     done in a funny way because DWARF specifies the parent entry to
     point to a name -- but we don't know which specific one.  */
  for (auto [entry, parent_idx] : needs_parent)
    {
      /* Name entries are indexed from 1 in DWARF.  */
      std::vector<cooked_index_entry *> &entries = all_entries[parent_idx - 1];
      for (const auto &parent : entries)
	if (parent->lang == entry->lang)
	  {
	    entry->set_parent (parent);
	    break;
	  }
    }
}

/* A reader for .debug_names.  */

struct cooked_index_debug_names : public cooked_index_worker
{
  cooked_index_debug_names (dwarf2_per_objfile *per_objfile,
			    mapped_debug_names_reader &&map)
    : cooked_index_worker (per_objfile),
      m_map (std::move (map))
  { }

  void do_reading () override;

  mapped_debug_names_reader m_map;
};

void
cooked_index_debug_names::do_reading ()
{
  complaint_interceptor complaint_handler;
  std::vector<gdb_exception> exceptions;
  try
    {
      m_map.scan_all_names ();
    }
  catch (const gdb_exception &exc)
    {
      exceptions.push_back (std::move (exc));
    }

  dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
  per_bfd->quick_file_names_table
    = create_quick_file_names_table (per_bfd->all_units.size ());
  m_results.emplace_back (nullptr,
			  complaint_handler.release (),
			  std::move (exceptions));
  std::vector<std::unique_ptr<cooked_index_shard>> indexes;
  indexes.push_back (std::move (m_map.shard));
  cooked_index *table
    = (gdb::checked_static_cast<cooked_index *>
       (per_bfd->index_table.get ()));
  table->set_contents (std::move (indexes));

  bfd_thread_cleanup ();
}

/* Check the signatured type hash table from .debug_names.  */

static bool
check_signatured_type_table_from_debug_names
  (dwarf2_per_objfile *per_objfile,
   const mapped_debug_names_reader &map,
   struct dwarf2_section_info *section)
{
  struct objfile *objfile = per_objfile->objfile;
  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
  int nr_cus = per_bfd->all_comp_units.size ();
  int nr_cus_tus = per_bfd->all_units.size ();

  section->read (objfile);

  uint32_t j = nr_cus;
  for (uint32_t i = 0; i < map.tu_count; ++i)
    {
      sect_offset sect_off
	= (sect_offset) (extract_unsigned_integer
			 (map.tu_table_reordered + i * map.offset_size,
			  map.offset_size,
			  map.dwarf5_byte_order));

      bool found = false;
      for (; j < nr_cus_tus; j++)
	if (per_bfd->get_cu (j)->sect_off == sect_off)
	  {
	    found = true;
	    break;
	  }
      if (!found)
	{
	  warning (_("Section .debug_names has incorrect entry in TU table,"
		     " ignoring .debug_names."));
	  return false;
	}
      per_bfd->all_comp_units_index_tus.push_back (per_bfd->get_cu (j));
    }
  return true;
}

/* DWARF-5 debug_names reader.  */

/* The old, no-longer-supported GDB augmentation.  */
static const gdb_byte old_gdb_augmentation[]
     = { 'G', 'D', 'B', 0 };
static_assert (sizeof (old_gdb_augmentation) % 4 == 0);

/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  This
   must have a size that is a multiple of 4.  */
const gdb_byte dwarf5_augmentation[8] = { 'G', 'D', 'B', '2', 0, 0, 0, 0 };
static_assert (sizeof (dwarf5_augmentation) % 4 == 0);

/* A helper function that reads the .debug_names section in SECTION
   and fills in MAP.  FILENAME is the name of the file containing the
   section; it is used for error reporting.

   Returns true if all went well, false otherwise.  */

static bool
read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
			       const char *filename,
			       struct dwarf2_section_info *section,
			       mapped_debug_names_reader &map)
{
  struct objfile *objfile = per_objfile->objfile;

  if (section->empty ())
    return false;

  /* Older elfutils strip versions could keep the section in the main
     executable while splitting it for the separate debug info file.  */
  if ((section->get_flags () & SEC_HAS_CONTENTS) == 0)
    return false;

  section->read (objfile);

  map.per_objfile = per_objfile;
  map.dwarf5_byte_order = gdbarch_byte_order (objfile->arch ());

  const gdb_byte *addr = section->buffer;

  bfd *abfd = section->get_bfd_owner ();
  map.abfd = abfd;

  unsigned int bytes_read;
  LONGEST length = read_initial_length (abfd, addr, &bytes_read);
  addr += bytes_read;

  map.dwarf5_is_dwarf64 = bytes_read != 4;
  map.offset_size = map.dwarf5_is_dwarf64 ? 8 : 4;
  if (bytes_read + length != section->size)
    {
      /* There may be multiple per-CU indices.  */
      warning (_("Section .debug_names in %s length %s does not match "
		 "section length %s, ignoring .debug_names."),
	       filename, plongest (bytes_read + length),
	       pulongest (section->size));
      return false;
    }

  /* The version number.  */
  uint16_t version = read_2_bytes (abfd, addr);
  addr += 2;
  if (version != 5)
    {
      warning (_("Section .debug_names in %s has unsupported version %d, "
		 "ignoring .debug_names."),
	       filename, version);
      return false;
    }

  /* Padding.  */
  uint16_t padding = read_2_bytes (abfd, addr);
  addr += 2;
  if (padding != 0)
    {
      warning (_("Section .debug_names in %s has unsupported padding %d, "
		 "ignoring .debug_names."),
	       filename, padding);
      return false;
    }

  /* comp_unit_count - The number of CUs in the CU list.  */
  map.cu_count = read_4_bytes (abfd, addr);
  addr += 4;

  /* local_type_unit_count - The number of TUs in the local TU
     list.  */
  map.tu_count = read_4_bytes (abfd, addr);
  addr += 4;

  /* foreign_type_unit_count - The number of TUs in the foreign TU
     list.  */
  uint32_t foreign_tu_count = read_4_bytes (abfd, addr);
  addr += 4;
  if (foreign_tu_count != 0)
    {
      warning (_("Section .debug_names in %s has unsupported %lu foreign TUs, "
		 "ignoring .debug_names."),
	       filename, static_cast<unsigned long> (foreign_tu_count));
      return false;
    }

  /* bucket_count - The number of hash buckets in the hash lookup
     table.  */
  map.bucket_count = read_4_bytes (abfd, addr);
  addr += 4;

  /* name_count - The number of unique names in the index.  */
  map.name_count = read_4_bytes (abfd, addr);
  addr += 4;

  /* abbrev_table_size - The size in bytes of the abbreviations
     table.  */
  uint32_t abbrev_table_size = read_4_bytes (abfd, addr);
  addr += 4;

  /* augmentation_string_size - The size in bytes of the augmentation
     string.  This value is rounded up to a multiple of 4.  */
  uint32_t augmentation_string_size = read_4_bytes (abfd, addr);
  addr += 4;
  augmentation_string_size += (-augmentation_string_size) & 3;

  if (augmentation_string_size == sizeof (old_gdb_augmentation)
      && memcmp (addr, old_gdb_augmentation,
		 sizeof (old_gdb_augmentation)) == 0)
    {
      warning (_(".debug_names created by an old version of gdb; ignoring"));
      return false;
    }

  map.augmentation_is_gdb = ((augmentation_string_size
			      == sizeof (dwarf5_augmentation))
			     && memcmp (addr, dwarf5_augmentation,
					sizeof (dwarf5_augmentation)) == 0);

  if (!map.augmentation_is_gdb)
    {
      warning (_(".debug_names not created by gdb; ignoring"));
      return false;
    }

  addr += augmentation_string_size;

  /* List of CUs */
  map.cu_table_reordered = addr;
  addr += map.cu_count * map.offset_size;

  /* List of Local TUs */
  map.tu_table_reordered = addr;
  addr += map.tu_count * map.offset_size;

  /* Hash Lookup Table */
  map.bucket_table_reordered = reinterpret_cast<const uint32_t *> (addr);
  addr += map.bucket_count * 4;
  map.hash_table_reordered = reinterpret_cast<const uint32_t *> (addr);
  if (map.bucket_count != 0)
    addr += map.name_count * 4;

  /* Name Table */
  map.name_table_string_offs_reordered = addr;
  addr += map.name_count * map.offset_size;
  map.name_table_entry_offs_reordered = addr;
  addr += map.name_count * map.offset_size;

  const gdb_byte *abbrev_table_start = addr;
  for (;;)
    {
      const ULONGEST index_num = read_unsigned_leb128 (abfd, addr, &bytes_read);
      addr += bytes_read;
      if (index_num == 0)
	break;

      const auto insertpair
	= map.abbrev_map.emplace (index_num, mapped_debug_names_reader::index_val ());
      if (!insertpair.second)
	{
	  warning (_("Section .debug_names in %s has duplicate index %s, "
		     "ignoring .debug_names."),
		   filename, pulongest (index_num));
	  return false;
	}
      mapped_debug_names_reader::index_val &indexval = insertpair.first->second;
      indexval.dwarf_tag = read_unsigned_leb128 (abfd, addr, &bytes_read);
      addr += bytes_read;

      for (;;)
	{
	  mapped_debug_names_reader::index_val::attr attr;
	  attr.dw_idx = read_unsigned_leb128 (abfd, addr, &bytes_read);
	  addr += bytes_read;
	  attr.form = read_unsigned_leb128 (abfd, addr, &bytes_read);
	  addr += bytes_read;
	  if (attr.form == DW_FORM_implicit_const)
	    {
	      attr.implicit_const = read_signed_leb128 (abfd, addr,
							&bytes_read);
	      addr += bytes_read;
	    }
	  if (attr.dw_idx == 0 && attr.form == 0)
	    break;
	  indexval.attr_vec.push_back (std::move (attr));
	}
    }
  if (addr != abbrev_table_start + abbrev_table_size)
    {
      warning (_("Section .debug_names in %s has abbreviation_table "
		 "of size %s vs. written as %u, ignoring .debug_names."),
	       filename, plongest (addr - abbrev_table_start),
	       abbrev_table_size);
      return false;
    }
  map.entry_pool = addr;

  return true;
}

/* A helper for check_cus_from_debug_names that handles the MAP's CU
   list.  */

static bool
check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
				  const mapped_debug_names_reader &map,
				  dwarf2_section_info &section,
				  bool is_dwz)
{
  int nr_cus = per_bfd->all_comp_units.size ();

  if (!map.augmentation_is_gdb)
    {
      uint32_t j = 0;
      for (uint32_t i = 0; i < map.cu_count; ++i)
	{
	  sect_offset sect_off
	    = (sect_offset) (extract_unsigned_integer
			     (map.cu_table_reordered + i * map.offset_size,
			      map.offset_size,
			      map.dwarf5_byte_order));
	  bool found = false;
	  for (; j < nr_cus; j++)
	    if (per_bfd->get_cu (j)->sect_off == sect_off)
	      {
		found = true;
		break;
	      }
	  if (!found)
	    {
	      warning (_("Section .debug_names has incorrect entry in CU table,"
			 " ignoring .debug_names."));
	      return false;
	    }
	  per_bfd->all_comp_units_index_cus.push_back (per_bfd->get_cu (j));
	}
      return true;
    }

  if (map.cu_count != nr_cus)
    {
      warning (_("Section .debug_names has incorrect number of CUs in CU table,"
		 " ignoring .debug_names."));
      return false;
    }

  for (uint32_t i = 0; i < map.cu_count; ++i)
    {
      sect_offset sect_off
	= (sect_offset) (extract_unsigned_integer
			 (map.cu_table_reordered + i * map.offset_size,
			  map.offset_size,
			  map.dwarf5_byte_order));
      if (sect_off != per_bfd->get_cu (i)->sect_off)
	{
	  warning (_("Section .debug_names has incorrect entry in CU table,"
		     " ignoring .debug_names."));
	  return false;
	}
    }

  return true;
}

/* Read the CU list from the mapped index, and use it to create all
   the CU objects for this dwarf2_per_objfile.  */

static bool
check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
			     const mapped_debug_names_reader &map,
			     const mapped_debug_names_reader &dwz_map)
{
  if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->info,
					false /* is_dwz */))
    return false;

  if (dwz_map.cu_count == 0)
    return true;

  dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
  return check_cus_from_debug_names_list (per_bfd, dwz_map, dwz->info,
					  true /* is_dwz */);
}

/* This does all the work for dwarf2_read_debug_names, but putting it
   into a separate function makes some cleanup a bit simpler.  */

static bool
do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
{
  mapped_debug_names_reader map;
  mapped_debug_names_reader dwz_map;
  struct objfile *objfile = per_objfile->objfile;
  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;

  if (!read_debug_names_from_section (per_objfile, objfile_name (objfile),
				      &per_bfd->debug_names, map))
    return false;

  /* Don't use the index if it's empty.  */
  if (map.name_count == 0)
    return false;

  /* If there is a .dwz file, read it so we can get its CU list as
     well.  */
  dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
  if (dwz != NULL)
    {
      if (!read_debug_names_from_section (per_objfile,
					  bfd_get_filename (dwz->dwz_bfd.get ()),
					  &dwz->debug_names, dwz_map))
	{
	  warning (_("could not read '.debug_names' section from %s; skipping"),
		   bfd_get_filename (dwz->dwz_bfd.get ()));
	  return false;
	}
    }

  create_all_units (per_objfile);
  if (!check_cus_from_debug_names (per_bfd, map, dwz_map))
    return false;

  if (map.tu_count != 0)
    {
      /* We can only handle a single .debug_types when we have an
	 index.  */
      if (per_bfd->types.size () > 1)
	return false;

      dwarf2_section_info *section
	= (per_bfd->types.size () == 1
	   ? &per_bfd->types[0]
	   : &per_bfd->info);

      if (!check_signatured_type_table_from_debug_names (per_objfile,
							 map, section))
	return false;
    }

  per_bfd->debug_aranges.read (per_objfile->objfile);
  addrmap_mutable addrmap;
  deferred_warnings warnings;
  read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
			     &addrmap, &warnings);
  warnings.emit ();

  map.shard = std::make_unique<cooked_index_shard> ();
  map.shard->install_addrmap (&addrmap);

  cooked_index *idx
    = new debug_names_index (per_objfile,
			     (std::make_unique<cooked_index_debug_names>
			      (per_objfile, std::move (map))));
  per_bfd->index_table.reset (idx);

  idx->start_reading ();

  return true;
}

/* See read-debug-names.h.  */

bool
dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
{
  bool result = do_dwarf2_read_debug_names (per_objfile);
  if (!result)
    per_objfile->per_bfd->all_units.clear ();
  return result;
}
