display_debug_names (struct dwarf_section *section, void *file)
{
  unsigned char *hdrptr = section->start;
  dwarf_vma unit_length;
  unsigned char *unit_start;
  const unsigned char *const section_end = section->start + section->size;
  unsigned char *unit_end;

  introduce (section, false);

  load_debug_section_with_follow (str, file);

  for (; hdrptr < section_end; hdrptr = unit_end)
    {
      unsigned int offset_size;
      uint16_t dwarf_version, padding;
      uint32_t comp_unit_count, local_type_unit_count, foreign_type_unit_count;
      uint64_t bucket_count, name_count, abbrev_table_size;
      uint32_t augmentation_string_size;
      unsigned int i;
      bool augmentation_printable;
      const char *augmentation_string;
      size_t total;

      unit_start = hdrptr;

      /* Get and check the length of the block.  */
      SAFE_BYTE_GET_AND_INC (unit_length, hdrptr, 4, section_end);

      if (unit_length == 0xffffffff)
	{
	  /* This section is 64-bit DWARF.  */
	  SAFE_BYTE_GET_AND_INC (unit_length, hdrptr, 8, section_end);
	  offset_size = 8;
	}
      else
	offset_size = 4;

      if (unit_length > (size_t) (section_end - hdrptr)
	  || unit_length < 2 + 2 + 4 * 7)
	{
	too_short:
	  warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
		section->name,
		(unsigned long) (unit_start - section->start),
		dwarf_vmatoa ("x", unit_length));
	  return 0;
	}
      unit_end = hdrptr + unit_length;

      /* Get and check the version number.  */
      SAFE_BYTE_GET_AND_INC (dwarf_version, hdrptr, 2, unit_end);
      printf (_("Version %ld\n"), (long) dwarf_version);

      /* Prior versions did not exist, and future versions may not be
	 backwards compatible.  */
      if (dwarf_version != 5)
	{
	  warn (_("Only DWARF version 5 .debug_names "
		  "is currently supported.\n"));
	  return 0;
	}

      SAFE_BYTE_GET_AND_INC (padding, hdrptr, 2, unit_end);
      if (padding != 0)
	warn (_("Padding field of .debug_names must be 0 (found 0x%x)\n"),
	      padding);

      SAFE_BYTE_GET_AND_INC (comp_unit_count, hdrptr, 4, unit_end);
      if (comp_unit_count == 0)
	warn (_("Compilation unit count must be >= 1 in .debug_names\n"));

      SAFE_BYTE_GET_AND_INC (local_type_unit_count, hdrptr, 4, unit_end);
      SAFE_BYTE_GET_AND_INC (foreign_type_unit_count, hdrptr, 4, unit_end);
      SAFE_BYTE_GET_AND_INC (bucket_count, hdrptr, 4, unit_end);
      SAFE_BYTE_GET_AND_INC (name_count, hdrptr, 4, unit_end);
      SAFE_BYTE_GET_AND_INC (abbrev_table_size, hdrptr, 4, unit_end);

      SAFE_BYTE_GET_AND_INC (augmentation_string_size, hdrptr, 4, unit_end);
      if (augmentation_string_size % 4 != 0)
	{
	  warn (_("Augmentation string length %u must be rounded up "
		  "to a multiple of 4 in .debug_names.\n"),
		augmentation_string_size);
	  augmentation_string_size += (-augmentation_string_size) & 3;
	}
      if (augmentation_string_size > (size_t) (unit_end - hdrptr))
	goto too_short;

      printf (_("Augmentation string:"));

      augmentation_printable = true;
      augmentation_string = (const char *) hdrptr;

      for (i = 0; i < augmentation_string_size; i++)
	{
	  unsigned char uc;

	  SAFE_BYTE_GET_AND_INC (uc, hdrptr, 1, unit_end);
	  printf (" %02x", uc);

	  if (uc != 0 && !ISPRINT (uc))
	    augmentation_printable = false;
	}

      if (augmentation_printable)
	{
	  printf ("  (\"");
	  for (i = 0;
	       i < augmentation_string_size && augmentation_string[i];
	       ++i)
	    putchar (augmentation_string[i]);
	  printf ("\")");
	}
      putchar ('\n');

      printf (_("CU table:\n"));
      if (_mul_overflow (comp_unit_count, offset_size, &total)
	  || total > (size_t) (unit_end - hdrptr))
	goto too_short;
      for (i = 0; i < comp_unit_count; i++)
	{
	  uint64_t cu_offset;

	  SAFE_BYTE_GET_AND_INC (cu_offset, hdrptr, offset_size, unit_end);
	  printf (_("[%3u] 0x%lx\n"), i, (unsigned long) cu_offset);
	}
      putchar ('\n');

      printf (_("TU table:\n"));
      if (_mul_overflow (local_type_unit_count, offset_size, &total)
	  || total > (size_t) (unit_end - hdrptr))
	goto too_short;
      for (i = 0; i < local_type_unit_count; i++)
	{
	  uint64_t tu_offset;

	  SAFE_BYTE_GET_AND_INC (tu_offset, hdrptr, offset_size, unit_end);
	  printf (_("[%3u] 0x%lx\n"), i, (unsigned long) tu_offset);
	}
      putchar ('\n');

      printf (_("Foreign TU table:\n"));
      if (_mul_overflow (foreign_type_unit_count, 8, &total)
	  || total > (size_t) (unit_end - hdrptr))
	goto too_short;
      for (i = 0; i < foreign_type_unit_count; i++)
	{
	  uint64_t signature;

	  SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, unit_end);
	  printf (_("[%3u] "), i);
	  print_dwarf_vma (signature, 8);
	  putchar ('\n');
	}
      putchar ('\n');

      uint64_t xtra = (bucket_count * sizeof (uint32_t)
		       + name_count * (sizeof (uint32_t) + 2 * offset_size)
		       + abbrev_table_size);
      if (xtra > (size_t) (unit_end - hdrptr))
	{
	  warn (_("Entry pool offset (0x%lx) exceeds unit size 0x%lx "
		  "for unit 0x%lx in the debug_names\n"),
		(long) xtra,
		(long) (unit_end - unit_start),
		(long) (unit_start - section->start));
	  return 0;
	}
      const uint32_t *const hash_table_buckets = (uint32_t *) hdrptr;
      hdrptr += bucket_count * sizeof (uint32_t);
      const uint32_t *const hash_table_hashes = (uint32_t *) hdrptr;
      hdrptr += name_count * sizeof (uint32_t);
      unsigned char *const name_table_string_offsets = hdrptr;
      hdrptr += name_count * offset_size;
      unsigned char *const name_table_entry_offsets = hdrptr;
      hdrptr += name_count * offset_size;
      unsigned char *const abbrev_table = hdrptr;
      hdrptr += abbrev_table_size;
      const unsigned char *const abbrev_table_end = hdrptr;
      unsigned char *const entry_pool = hdrptr;

      size_t buckets_filled = 0;
      size_t bucketi;
      for (bucketi = 0; bucketi < bucket_count; bucketi++)
	{
	  const uint32_t bucket = hash_table_buckets[bucketi];

	  if (bucket != 0)
	    ++buckets_filled;
	}
      printf (ngettext ("Used %zu of %lu bucket.\n",
			"Used %zu of %lu buckets.\n",
			bucket_count),
	      buckets_filled, (unsigned long) bucket_count);

      if (bucket_count != 0)
	{
	  uint32_t hash_prev = 0;
	  size_t hash_clash_count = 0;
	  size_t longest_clash = 0;
	  size_t this_length = 0;
	  size_t hashi;
	  for (hashi = 0; hashi < name_count; hashi++)
	    {
	      const uint32_t hash_this = hash_table_hashes[hashi];

	      if (hashi > 0)
		{
		  if (hash_prev % bucket_count == hash_this % bucket_count)
		    {
		      ++hash_clash_count;
		      ++this_length;
		      longest_clash = MAX (longest_clash, this_length);
		    }
		  else
		    this_length = 0;
		}
	      hash_prev = hash_this;
	    }
	  printf (_("Out of %lu items there are %zu bucket clashes"
		    " (longest of %zu entries).\n"),
		  (unsigned long) name_count, hash_clash_count, longest_clash);

	  if (name_count != buckets_filled + hash_clash_count)
	    warn (_("The name_count (%lu) is not the same as the used bucket_count (%lu) + the hash clash count (%lu)"),
		  (unsigned long) name_count,
		  (unsigned long) buckets_filled,
		  (unsigned long) hash_clash_count);
	}

      struct abbrev_lookup_entry
      {
	dwarf_vma abbrev_tag;
	unsigned char *abbrev_lookup_ptr;
      };
      struct abbrev_lookup_entry *abbrev_lookup = NULL;
      size_t abbrev_lookup_used = 0;
      size_t abbrev_lookup_allocated = 0;

      unsigned char *abbrevptr = abbrev_table;
      for (;;)
	{
	  dwarf_vma abbrev_tag;

	  READ_ULEB (abbrev_tag, abbrevptr, abbrev_table_end);
	  if (abbrev_tag == 0)
	    break;
	  if (abbrev_lookup_used == abbrev_lookup_allocated)
	    {
	      abbrev_lookup_allocated = MAX (0x100,
					     abbrev_lookup_allocated * 2);
	      abbrev_lookup = xrealloc (abbrev_lookup,
					(abbrev_lookup_allocated
					 * sizeof (*abbrev_lookup)));
	    }
	  assert (abbrev_lookup_used < abbrev_lookup_allocated);
	  struct abbrev_lookup_entry *entry;
	  for (entry = abbrev_lookup;
	       entry < abbrev_lookup + abbrev_lookup_used;
	       entry++)
	    if (entry->abbrev_tag == abbrev_tag)
	      {
		warn (_("Duplicate abbreviation tag %lu "
			"in unit 0x%lx in the debug_names\n"),
		      (long) abbrev_tag, (long) (unit_start - section->start));
		break;
	      }
	  entry = &abbrev_lookup[abbrev_lookup_used++];
	  entry->abbrev_tag = abbrev_tag;
	  entry->abbrev_lookup_ptr = abbrevptr;

	  /* Skip DWARF tag.  */
	  SKIP_ULEB (abbrevptr, abbrev_table_end);
	  for (;;)
	    {
	      dwarf_vma xindex, form;

	      READ_ULEB (xindex, abbrevptr, abbrev_table_end);
	      READ_ULEB (form, abbrevptr, abbrev_table_end);
	      if (xindex == 0 && form == 0)
		break;
	    }
	}

      printf (_("\nSymbol table:\n"));
      uint32_t namei;
      for (namei = 0; namei < name_count; ++namei)
	{
	  uint64_t string_offset, entry_offset;
	  unsigned char *p;

	  p = name_table_string_offsets + namei * offset_size;
	  SAFE_BYTE_GET (string_offset, p, offset_size, unit_end);
	  p = name_table_entry_offsets + namei * offset_size;
	  SAFE_BYTE_GET (entry_offset, p, offset_size, unit_end);

	  printf ("[%3u] #%08x %s:", namei, hash_table_hashes[namei],
		  fetch_indirect_string (string_offset));

	  unsigned char *entryptr = entry_pool + entry_offset;

	  /* We need to scan first whether there is a single or multiple
	     entries.  TAGNO is -2 for the first entry, it is -1 for the
	     initial tag read of the second entry, then it becomes 0 for the
	     first entry for real printing etc.  */
	  int tagno = -2;
	  /* Initialize it due to a false compiler warning.  */
	  dwarf_vma second_abbrev_tag = -1;
	  for (;;)
	    {
	      dwarf_vma abbrev_tag;
	      dwarf_vma dwarf_tag;
	      const struct abbrev_lookup_entry *entry;

	      READ_ULEB (abbrev_tag, entryptr, unit_end);
	      if (tagno == -1)
		{
		  second_abbrev_tag = abbrev_tag;
		  tagno = 0;
		  entryptr = entry_pool + entry_offset;
		  continue;
		}
	      if (abbrev_tag == 0)
		break;
	      if (tagno >= 0)
		printf ("%s<%lu>",
		        (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"),
			(unsigned long) abbrev_tag);

	      for (entry = abbrev_lookup;
		   entry < abbrev_lookup + abbrev_lookup_used;
		   entry++)
		if (entry->abbrev_tag == abbrev_tag)
		  break;
	      if (entry >= abbrev_lookup + abbrev_lookup_used)
		{
		  warn (_("Undefined abbreviation tag %lu "
			  "in unit 0x%lx in the debug_names\n"),
			(long) abbrev_tag,
			(long) (unit_start - section->start));
		  break;
		}
	      abbrevptr = entry->abbrev_lookup_ptr;
	      READ_ULEB (dwarf_tag, abbrevptr, abbrev_table_end);
	      if (tagno >= 0)
		printf (" %s", get_TAG_name (dwarf_tag));
	      for (;;)
		{
		  dwarf_vma xindex, form;

		  READ_ULEB (xindex, abbrevptr, abbrev_table_end);
		  READ_ULEB (form, abbrevptr, abbrev_table_end);
		  if (xindex == 0 && form == 0)
		    break;

		  if (tagno >= 0)
		    printf (" %s", get_IDX_name (xindex));
		  entryptr = read_and_display_attr_value (0, form, 0,
							  unit_start, entryptr, unit_end,
							  0, 0, offset_size,
							  dwarf_version, NULL,
							  (tagno < 0), section,
							  NULL, '=', -1);
		}
	      ++tagno;
	    }
	  if (tagno <= 0)
	    printf (_(" <no entries>"));
	  putchar ('\n');
	}

      free (abbrev_lookup);
    }

  return 1;
}


Replace a run-time assertion failure with a warning message when parsing corrupt DWARF data.

	PR 29289
	* dwarf.c (display_debug_names): Replace assert with a warning
	message.

read_cie (unsigned char *start, unsigned char *end,
	  Frame_Chunk **p_cie, int *p_version,
	  bfd_size_type *p_aug_len, unsigned char **p_aug)
{
  int version;
  Frame_Chunk *fc;
  unsigned char *augmentation_data = NULL;
  bfd_size_type augmentation_data_len = 0;

  * p_cie = NULL;
  /* PR 17512: file: 001-228113-0.004.  */
  if (start >= end)
    return end;

  fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
  memset (fc, 0, sizeof (Frame_Chunk));

  fc->col_type = (short int *) xmalloc (sizeof (short int));
  fc->col_offset = (int *) xmalloc (sizeof (int));

  version = *start++;

  fc->augmentation = (char *) start;
  /* PR 17512: file: 001-228113-0.004.
     Skip past augmentation name, but avoid running off the end of the data.  */
  while (start < end)
    if (* start ++ == '\0')
      break;
  if (start == end)
    {
      warn (_("No terminator for augmentation name\n"));
      goto fail;
    }

  if (strcmp (fc->augmentation, "eh") == 0)
    {
      if (eh_addr_size > (size_t) (end - start))
	goto fail;
      start += eh_addr_size;
    }

  if (version >= 4)
    {
      if (2 > (size_t) (end - start))
	goto fail;
      GET (fc->ptr_size, 1);
      if (fc->ptr_size < 1 || fc->ptr_size > 8)
	{
	  warn (_("Invalid pointer size (%d) in CIE data\n"), fc->ptr_size);
	  goto fail;
	}

      GET (fc->segment_size, 1);
      /* PR 17512: file: e99d2804.  */
      if (fc->segment_size > 8 || fc->segment_size + fc->ptr_size > 8)
	{
	  warn (_("Invalid segment size (%d) in CIE data\n"), fc->segment_size);
	  goto fail;
	}

      eh_addr_size = fc->ptr_size;
    }
  else
    {
      fc->ptr_size = eh_addr_size;
      fc->segment_size = 0;
    }

  READ_ULEB (fc->code_factor, start, end);
  READ_SLEB (fc->data_factor, start, end);

  if (start >= end)
    goto fail;

  if (version == 1)
    {
      GET (fc->ra, 1);
    }
  else
    {
      READ_ULEB (fc->ra, start, end);
    }

  if (fc->augmentation[0] == 'z')
    {
      if (start >= end)
	goto fail;
      READ_ULEB (augmentation_data_len, start, end);
      augmentation_data = start;
      /* PR 17512: file: 11042-2589-0.004.  */
      if (augmentation_data_len > (bfd_size_type) (end - start))
	{
	  warn (_("Augmentation data too long: 0x%s, expected at most %#lx\n"),
		dwarf_vmatoa ("x", augmentation_data_len),
		(unsigned long) (end - start));
	  goto fail;
	}
      start += augmentation_data_len;
    }

  if (augmentation_data_len)
    {
      unsigned char *p;
      unsigned char *q;
      unsigned char *qend;

      p = (unsigned char *) fc->augmentation + 1;
      q = augmentation_data;
      qend = q + augmentation_data_len;

      while (p < end && q < qend)
	{
	  if (*p == 'L')
	    q++;
	  else if (*p == 'P')
	    q += 1 + size_of_encoded_value (*q);
	  else if (*p == 'R')
	    fc->fde_encoding = *q++;
	  else if (*p == 'S')
	    ;
	  else if (*p == 'B')
	    ;
	  else
	    break;
	  p++;
	}
      /* Note - it is OK if this loop terminates with q < qend.
	 Padding may have been inserted to align the end of the CIE.  */
    }

  *p_cie = fc;
  if (p_version)
    *p_version = version;
  if (p_aug_len)
    {
      *p_aug_len = augmentation_data_len;
      *p_aug = augmentation_data;
    }
  return start;

 fail:
  free (fc->col_offset);
  free (fc->col_type);
  free (fc);
  return end;
}


read_and_display_attr_value (unsigned long           attribute,
			     unsigned long           form,
			     dwarf_signed_vma        implicit_const,
			     unsigned char *         start,
			     unsigned char *         data,
			     unsigned char *         end,
			     dwarf_vma               cu_offset,
			     dwarf_vma               pointer_size,
			     dwarf_vma               offset_size,
			     int                     dwarf_version,
			     debug_info *            debug_info_p,
			     int                     do_loc,
			     struct dwarf_section *  section,
			     struct cu_tu_set *      this_set,
			     char                    delimiter,
			     int                     level)
{
  dwarf_signed_vma svalue;
  dwarf_vma uvalue = 0;
  dwarf_vma uvalue_hi = 0;
  unsigned char *block_start = NULL;
  unsigned char *orig_data = data;

  if (data > end || (data == end && form != DW_FORM_flag_present))
    {
      warn (_("Corrupt attribute\n"));
      return data;
    }

  if (do_wide && ! do_loc)
    {
      /* PR 26847: Display the name of the form.  */
      const char * name = get_FORM_name (form);

      /* For convenience we skip the DW_FORM_ prefix to the name.  */
      if (name[0] == 'D')
	name += 8; /* strlen ("DW_FORM_")  */
      printf ("%c(%s)", delimiter, name);
    }

  switch (form)
    {
    case DW_FORM_ref_addr:
      if (dwarf_version == 2)
	SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
      else if (dwarf_version > 2)
	SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
      else
	error (_("Internal error: DW_FORM_ref_addr is not supported in DWARF version 1.\n"));
      break;

    case DW_FORM_addr:
      SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
      break;

    case DW_FORM_strp_sup:
    case DW_FORM_strp:
    case DW_FORM_line_strp:
    case DW_FORM_sec_offset:
    case DW_FORM_GNU_ref_alt:
    case DW_FORM_GNU_strp_alt:
      SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
      break;

    case DW_FORM_flag_present:
      uvalue = 1;
      break;

    case DW_FORM_ref1:
    case DW_FORM_flag:
    case DW_FORM_data1:
    case DW_FORM_strx1:
    case DW_FORM_addrx1:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
      break;

    case DW_FORM_ref2:
    case DW_FORM_data2:
    case DW_FORM_strx2:
    case DW_FORM_addrx2:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
      break;

    case DW_FORM_strx3:
    case DW_FORM_addrx3:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 3, end);
      break;

    case DW_FORM_ref_sup4:
    case DW_FORM_ref4:
    case DW_FORM_data4:
    case DW_FORM_strx4:
    case DW_FORM_addrx4:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
      break;

    case DW_FORM_ref_sup8:
    case DW_FORM_ref8:
    case DW_FORM_data8:
    case DW_FORM_ref_sig8:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 8, end);
      break;

    case DW_FORM_data16:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 8, end);
      SAFE_BYTE_GET_AND_INC (uvalue_hi, data, 8, end);
      if (byte_get != byte_get_little_endian)
	{
	  dwarf_vma utmp = uvalue;
	  uvalue = uvalue_hi;
	  uvalue_hi = utmp;
	}
      break;

    case DW_FORM_sdata:
      READ_SLEB (svalue, data, end);
      uvalue = svalue;
      break;

    case DW_FORM_GNU_str_index:
    case DW_FORM_strx:
    case DW_FORM_ref_udata:
    case DW_FORM_udata:
    case DW_FORM_GNU_addr_index:
    case DW_FORM_addrx:
    case DW_FORM_loclistx:
    case DW_FORM_rnglistx:
      READ_ULEB (uvalue, data, end);
      break;

    case DW_FORM_indirect:
      READ_ULEB (form, data, end);
      if (!do_loc)
	printf ("%c%s", delimiter, get_FORM_name (form));
      if (form == DW_FORM_implicit_const)
	READ_SLEB (implicit_const, data, end);
      return read_and_display_attr_value (attribute, form, implicit_const,
					  start, data, end,
					  cu_offset, pointer_size,
					  offset_size, dwarf_version,
					  debug_info_p, do_loc,
					  section, this_set, delimiter, level);

    case DW_FORM_implicit_const:
      uvalue = implicit_const;
      break;

    default:
      break;
    }

  switch (form)
    {
    case DW_FORM_ref_addr:
      if (!do_loc)
	printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
      break;

    case DW_FORM_GNU_ref_alt:
      if (!do_loc)
	{
	  if (do_wide)
	    /* We have already printed the form name.  */
	    printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
	  else
	    printf ("%c<alt 0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
	}
      /* FIXME: Follow the reference...  */
      break;

    case DW_FORM_ref1:
    case DW_FORM_ref2:
    case DW_FORM_ref4:
    case DW_FORM_ref_sup4:
    case DW_FORM_ref_udata:
      if (!do_loc)
	printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
      break;

    case DW_FORM_data4:
    case DW_FORM_addr:
    case DW_FORM_sec_offset:
      if (!do_loc)
	printf ("%c0x%s", delimiter, dwarf_vmatoa ("x", uvalue));
      break;

    case DW_FORM_flag_present:
    case DW_FORM_flag:
    case DW_FORM_data1:
    case DW_FORM_data2:
    case DW_FORM_sdata:
      if (!do_loc)
	printf ("%c%s", delimiter, dwarf_vmatoa ("d", uvalue));
      break;

    case DW_FORM_udata:
      if (!do_loc)
	printf ("%c%s", delimiter, dwarf_vmatoa ("u", uvalue));
      break;

    case DW_FORM_implicit_const:
      if (!do_loc)
	printf ("%c%s", delimiter, dwarf_vmatoa ("d", implicit_const));
      break;

    case DW_FORM_ref_sup8:
    case DW_FORM_ref8:
    case DW_FORM_data8:
      if (!do_loc)
	{
	  dwarf_vma utmp = uvalue;
	  if (form == DW_FORM_ref8)
	    utmp += cu_offset;
	  printf ("%c0x%s", delimiter, dwarf_vmatoa ("x", utmp));
	}
      break;

    case DW_FORM_data16:
      if (!do_loc)
	printf (" 0x%s%s",
		uvalue_hi == 0 ? "" : dwarf_vmatoa ("x", uvalue_hi),
		dwarf_vmatoa_1 ("x", uvalue, uvalue_hi == 0 ? 0 : 8));
      break;

    case DW_FORM_string:
      if (!do_loc)
	printf ("%c%.*s", delimiter, (int) (end - data), data);
      data += strnlen ((char *) data, end - data);
      if (data < end)
	data++;
      break;

    case DW_FORM_block:
    case DW_FORM_exprloc:
      READ_ULEB (uvalue, data, end);
    do_block:
      block_start = data;
      if (block_start >= end)
	{
	  warn (_("Block ends prematurely\n"));
	  uvalue = 0;
	  block_start = end;
	}

      uvalue = check_uvalue (block_start, uvalue, end);

      data = block_start + uvalue;
      if (!do_loc)
	{
	  unsigned char op;

	  SAFE_BYTE_GET (op, block_start, sizeof (op), end);
	  if (op != DW_OP_addrx)
	    data = display_block (block_start, uvalue, end, delimiter);
	}
      break;

    case DW_FORM_block1:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
      goto do_block;

    case DW_FORM_block2:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
      goto do_block;

    case DW_FORM_block4:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
      goto do_block;

    case DW_FORM_strp:
      if (!do_loc)
	{
	  if (do_wide)
	    /* We have already displayed the form name.  */
	    printf (_("%c(offset: 0x%s): %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue),
		    fetch_indirect_string (uvalue));
	  else
	    printf (_("%c(indirect string, offset: 0x%s): %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue),
		    fetch_indirect_string (uvalue));
	}
      break;

    case DW_FORM_line_strp:
      if (!do_loc)
	{
	  if (do_wide)
	    /* We have already displayed the form name.  */
	    printf (_("%c(offset: 0x%s): %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue),
		    fetch_indirect_line_string (uvalue));
	  else
	    printf (_("%c(indirect line string, offset: 0x%s): %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue),
		    fetch_indirect_line_string (uvalue));
	}
      break;

    case DW_FORM_GNU_str_index:
    case DW_FORM_strx:
    case DW_FORM_strx1:
    case DW_FORM_strx2:
    case DW_FORM_strx3:
    case DW_FORM_strx4:
      if (!do_loc)
	{
	  const char *suffix = section ? strrchr (section->name, '.') : NULL;
	  bool dwo = suffix && strcmp (suffix, ".dwo") == 0;
	  const char *strng;

	  strng = fetch_indexed_string (uvalue, this_set, offset_size, dwo,
					debug_info_p ? debug_info_p->str_offsets_base : 0);
	  if (do_wide)
	    /* We have already displayed the form name.  */
	    printf (_("%c(offset: 0x%s): %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue), strng);
	  else
	    printf (_("%c(indexed string: 0x%s): %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue), strng);
	}
      break;

    case DW_FORM_GNU_strp_alt:
      if (!do_loc)
	{
	  if (do_wide)
	    /* We have already displayed the form name.  */
	    printf (_("%c(offset: 0x%s) %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue),
		    fetch_alt_indirect_string (uvalue));
	  else
	    printf (_("%c(alt indirect string, offset: 0x%s) %s"), delimiter,
		    dwarf_vmatoa ("x", uvalue),
		    fetch_alt_indirect_string (uvalue));
	}
      break;

    case DW_FORM_indirect:
      /* Handled above.  */
      break;

    case DW_FORM_ref_sig8:
      if (!do_loc)
	printf ("%c%s: 0x%s", delimiter, do_wide ? "" : "signature",
		dwarf_vmatoa ("x", uvalue));
      break;

    case DW_FORM_GNU_addr_index:
    case DW_FORM_addrx:
    case DW_FORM_addrx1:
    case DW_FORM_addrx2:
    case DW_FORM_addrx3:
    case DW_FORM_addrx4:
    case DW_FORM_loclistx:
    case DW_FORM_rnglistx:
      if (!do_loc)
	{
	  dwarf_vma base;
	  dwarf_vma offset;

	  if (debug_info_p == NULL)
	    base = 0;
	  else if (debug_info_p->addr_base == DEBUG_INFO_UNAVAILABLE)
	    base = 0;
	  else
	    base = debug_info_p->addr_base;

	  offset = base + uvalue * pointer_size;

	  if (do_wide)
	    /* We have already displayed the form name.  */
	    if (form == DW_FORM_loclistx)
	      printf (_("%c(index: 0x%s): %s"), delimiter,
	              dwarf_vmatoa ("x", uvalue),
	              dwarf_vmatoa ("x", debug_info_p->loc_offsets [uvalue]));
	    else
	      printf (_("%c(index: 0x%s): %s"), delimiter,
	              dwarf_vmatoa ("x", uvalue),
	              dwarf_vmatoa ("x", fetch_indexed_addr (offset, pointer_size)));
	  else
	    if (form == DW_FORM_loclistx)
	      printf (_("%c(addr_index: 0x%s): %s"), delimiter,
	              dwarf_vmatoa ("x", uvalue),
	              dwarf_vmatoa ("x", debug_info_p->loc_offsets [uvalue]));
	    else
	      printf (_("%c(addr_index: 0x%s): %s"), delimiter,
	              dwarf_vmatoa ("x", uvalue),
	              dwarf_vmatoa ("x", fetch_indexed_addr (offset, pointer_size)));
	}
      break;

    case DW_FORM_strp_sup:
      if (!do_loc)
	printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
      break;

    default:
      warn (_("Unrecognized form: 0x%lx\n"), form);
      /* What to do?  Consume a byte maybe?  */
      ++data;
      break;
    }

  if ((do_loc || do_debug_loc || do_debug_ranges || do_debug_info)
      && num_debug_info_entries == 0
      && debug_info_p != NULL)
    {
      switch (attribute)
	{
	case DW_AT_loclists_base:
	  if (debug_info_p->loclists_base)
	    warn (_("CU @ 0x%s has multiple loclists_base values"),
		  dwarf_vmatoa ("x", debug_info_p->cu_offset));
	  debug_info_p->loclists_base = uvalue;
	  break;
	case DW_AT_rnglists_base:
	  if (debug_info_p->rnglists_base)
	    warn (_("CU @ 0x%s has multiple rnglists_base values"),
	          dwarf_vmatoa ("x", debug_info_p->cu_offset));
	  debug_info_p->rnglists_base = uvalue;
	  break;
	case DW_AT_str_offsets_base:
	  if (debug_info_p->str_offsets_base)
	    warn (_("CU @ 0x%s has multiple str_offsets_base values"),
		  dwarf_vmatoa ("x", debug_info_p->cu_offset));
	  debug_info_p->str_offsets_base = uvalue;
	  break;

	case DW_AT_frame_base:
	  have_frame_base = 1;
	  /* Fall through.  */
	case DW_AT_location:
	case DW_AT_GNU_locviews:
	case DW_AT_string_length:
	case DW_AT_return_addr:
	case DW_AT_data_member_location:
	case DW_AT_vtable_elem_location:
	case DW_AT_segment:
	case DW_AT_static_link:
	case DW_AT_use_location:
	case DW_AT_call_value:
	case DW_AT_GNU_call_site_value:
	case DW_AT_call_data_value:
	case DW_AT_GNU_call_site_data_value:
	case DW_AT_call_target:
	case DW_AT_GNU_call_site_target:
	case DW_AT_call_target_clobbered:
	case DW_AT_GNU_call_site_target_clobbered:
	  if ((dwarf_version < 4
	       && (form == DW_FORM_data4 || form == DW_FORM_data8))
	      || form == DW_FORM_sec_offset
	      || form == DW_FORM_loclistx)
	    {
	      /* Process location list.  */
	      unsigned int lmax = debug_info_p->max_loc_offsets;
	      unsigned int num = debug_info_p->num_loc_offsets;

	      if (lmax == 0 || num >= lmax)
		{
		  lmax += 1024;
		  debug_info_p->loc_offsets = (dwarf_vma *)
		    xcrealloc (debug_info_p->loc_offsets,
			       lmax, sizeof (*debug_info_p->loc_offsets));
		  debug_info_p->loc_views = (dwarf_vma *)
		    xcrealloc (debug_info_p->loc_views,
			       lmax, sizeof (*debug_info_p->loc_views));
		  debug_info_p->have_frame_base = (int *)
		    xcrealloc (debug_info_p->have_frame_base,
			       lmax, sizeof (*debug_info_p->have_frame_base));
		  debug_info_p->max_loc_offsets = lmax;
		}
	      if (form == DW_FORM_loclistx)
		uvalue = fetch_indexed_value (num, loclists, debug_info_p->loclists_base);
	      else if (this_set != NULL)
		uvalue += this_set->section_offsets [DW_SECT_LOC];

	      debug_info_p->have_frame_base [num] = have_frame_base;
	      if (attribute != DW_AT_GNU_locviews)
		{
		  uvalue += debug_info_p->loclists_base;

		  /* Corrupt DWARF info can produce more offsets than views.
		     See PR 23062 for an example.  */
		  if (debug_info_p->num_loc_offsets
		      > debug_info_p->num_loc_views)
		    warn (_("More location offset attributes than DW_AT_GNU_locview attributes\n"));
		  else
		    {
		      debug_info_p->loc_offsets [num] = uvalue;
		      debug_info_p->num_loc_offsets++;
		    }
		}
	      else
		{
		  assert (debug_info_p->num_loc_views <= num);
		  num = debug_info_p->num_loc_views;
		  if (num > debug_info_p->num_loc_offsets)
		    warn (_("More DW_AT_GNU_locview attributes than location offset attributes\n"));
		  else
		    {
		      debug_info_p->loc_views [num] = uvalue;
		      debug_info_p->num_loc_views++;
		    }
		}
	    }
	  break;

	case DW_AT_low_pc:
	  if (need_base_address)
	    debug_info_p->base_address = uvalue;
	  break;

	case DW_AT_GNU_addr_base:
	case DW_AT_addr_base:
	  debug_info_p->addr_base = uvalue;
	  break;

	case DW_AT_GNU_ranges_base:
	  debug_info_p->ranges_base = uvalue;
	  break;

	case DW_AT_ranges:
	  if ((dwarf_version < 4
	       && (form == DW_FORM_data4 || form == DW_FORM_data8))
	      || form == DW_FORM_sec_offset
	      || form == DW_FORM_rnglistx)
	    {
	      /* Process range list.  */
	      unsigned int lmax = debug_info_p->max_range_lists;
	      unsigned int num = debug_info_p->num_range_lists;

	      if (lmax == 0 || num >= lmax)
		{
		  lmax += 1024;
		  debug_info_p->range_lists = (dwarf_vma *)
		    xcrealloc (debug_info_p->range_lists,
			       lmax, sizeof (*debug_info_p->range_lists));
		  debug_info_p->max_range_lists = lmax;
		}

	      if (form == DW_FORM_rnglistx)
		uvalue = fetch_indexed_value (uvalue, rnglists, 0);

	      debug_info_p->range_lists [num] = uvalue;
	      debug_info_p->num_range_lists++;
	    }
	  break;

	case DW_AT_GNU_dwo_name:
	case DW_AT_dwo_name:
	  if (need_dwo_info)
	    switch (form)
	      {
	      case DW_FORM_strp:
		add_dwo_name ((const char *) fetch_indirect_string (uvalue), cu_offset);
		break;
	      case DW_FORM_GNU_strp_alt:
		add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue), cu_offset);
		break;
	      case DW_FORM_GNU_str_index:
	      case DW_FORM_strx:
	      case DW_FORM_strx1:
	      case DW_FORM_strx2:
	      case DW_FORM_strx3:
	      case DW_FORM_strx4:
		add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, false,
		                                    debug_info_p->str_offsets_base),
			      cu_offset);
		break;
	      case DW_FORM_string:
		add_dwo_name ((const char *) orig_data, cu_offset);
		break;
	      default:
		warn (_("Unsupported form (%s) for attribute %s\n"),
		      get_FORM_name (form), get_AT_name (attribute));
		break;
	      }
	  break;

	case DW_AT_comp_dir:
	  /* FIXME: Also extract a build-id in a CU/TU.  */
	  if (need_dwo_info)
	    switch (form)
	      {
	      case DW_FORM_strp:
		add_dwo_dir ((const char *) fetch_indirect_string (uvalue), cu_offset);
		break;
	      case DW_FORM_GNU_strp_alt:
		add_dwo_dir (fetch_alt_indirect_string (uvalue), cu_offset);
		break;
	      case DW_FORM_line_strp:
		add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue), cu_offset);
		break;
	      case DW_FORM_GNU_str_index:
	      case DW_FORM_strx:
	      case DW_FORM_strx1:
	      case DW_FORM_strx2:
	      case DW_FORM_strx3:
	      case DW_FORM_strx4:
		add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, false,
		                                   debug_info_p->str_offsets_base),
			     cu_offset);
		break;
	      case DW_FORM_string:
		add_dwo_dir ((const char *) orig_data, cu_offset);
		break;
	      default:
		warn (_("Unsupported form (%s) for attribute %s\n"),
		      get_FORM_name (form), get_AT_name (attribute));
		break;
	      }
	  break;

	case DW_AT_GNU_dwo_id:
	  if (need_dwo_info)
	    switch (form)
	      {
	      case DW_FORM_data8:
		/* FIXME: Record the length of the ID as well ?  */
		add_dwo_id ((const char *) (data - 8), cu_offset);
		break;
	      default:
		warn (_("Unsupported form (%s) for attribute %s\n"),
		      get_FORM_name (form), get_AT_name (attribute));
		break;
	      }
	  break;

	default:
	  break;
	}
    }

  if (do_loc || attribute == 0)
    return data;

  /* For some attributes we can display further information.  */
  switch (attribute)
    {
    case DW_AT_type:
      if (level >= 0 && level < MAX_CU_NESTING
	  && uvalue < (size_t) (end - start))
	{
	  bool is_signed = false;
	  abbrev_entry *type_abbrev;
	  unsigned char *type_data;
	  abbrev_map *map;

	  type_abbrev = get_type_abbrev_from_form (form, uvalue,
						   cu_offset, end,
						   section, NULL,
						   &type_data, &map);
	  if (type_abbrev != NULL)
	    {
	      get_type_signedness (type_abbrev, section, type_data,
				   map ? section->start + map->end : end,
				   map ? map->start : cu_offset,
				   pointer_size, offset_size, dwarf_version,
				   & is_signed, 0);
	    }
	  level_type_signed[level] = is_signed;
	}
      break;

    case DW_AT_inline:
      printf ("\t");
      switch (uvalue)
	{
	case DW_INL_not_inlined:
	  printf (_("(not inlined)"));
	  break;
	case DW_INL_inlined:
	  printf (_("(inlined)"));
	  break;
	case DW_INL_declared_not_inlined:
	  printf (_("(declared as inline but ignored)"));
	  break;
	case DW_INL_declared_inlined:
	  printf (_("(declared as inline and inlined)"));
	  break;
	default:
	  printf (_("  (Unknown inline attribute value: %s)"),
		  dwarf_vmatoa ("x", uvalue));
	  break;
	}
      break;

    case DW_AT_language:
      printf ("\t");
      switch (uvalue)
	{
	  /* Ordered by the numeric value of these constants.  */
	case DW_LANG_C89:		printf ("(ANSI C)"); break;
	case DW_LANG_C:			printf ("(non-ANSI C)"); break;
	case DW_LANG_Ada83:		printf ("(Ada)"); break;
	case DW_LANG_C_plus_plus:	printf ("(C++)"); break;
	case DW_LANG_Cobol74:		printf ("(Cobol 74)"); break;
	case DW_LANG_Cobol85:		printf ("(Cobol 85)"); break;
	case DW_LANG_Fortran77:		printf ("(FORTRAN 77)"); break;
	case DW_LANG_Fortran90:		printf ("(Fortran 90)"); break;
	case DW_LANG_Pascal83:		printf ("(ANSI Pascal)"); break;
	case DW_LANG_Modula2:		printf ("(Modula 2)"); break;
	  /* DWARF 2.1 values.	*/
	case DW_LANG_Java:		printf ("(Java)"); break;
	case DW_LANG_C99:		printf ("(ANSI C99)"); break;
	case DW_LANG_Ada95:		printf ("(ADA 95)"); break;
	case DW_LANG_Fortran95:		printf ("(Fortran 95)"); break;
	  /* DWARF 3 values.  */
	case DW_LANG_PLI:		printf ("(PLI)"); break;
	case DW_LANG_ObjC:		printf ("(Objective C)"); break;
	case DW_LANG_ObjC_plus_plus:	printf ("(Objective C++)"); break;
	case DW_LANG_UPC:		printf ("(Unified Parallel C)"); break;
	case DW_LANG_D:			printf ("(D)"); break;
	  /* DWARF 4 values.  */
	case DW_LANG_Python:		printf ("(Python)"); break;
	  /* DWARF 5 values.  */
	case DW_LANG_OpenCL:		printf ("(OpenCL)"); break;
	case DW_LANG_Go:		printf ("(Go)"); break;
	case DW_LANG_Modula3:		printf ("(Modula 3)"); break;
	case DW_LANG_Haskell:		printf ("(Haskell)"); break;
	case DW_LANG_C_plus_plus_03:	printf ("(C++03)"); break;
	case DW_LANG_C_plus_plus_11:	printf ("(C++11)"); break;
	case DW_LANG_OCaml:		printf ("(OCaml)"); break;
	case DW_LANG_Rust:		printf ("(Rust)"); break;
	case DW_LANG_C11:		printf ("(C11)"); break;
	case DW_LANG_Swift:		printf ("(Swift)"); break;
	case DW_LANG_Julia:		printf ("(Julia)"); break;
	case DW_LANG_Dylan:		printf ("(Dylan)"); break;
	case DW_LANG_C_plus_plus_14:	printf ("(C++14)"); break;
	case DW_LANG_Fortran03:		printf ("(Fortran 03)"); break;
	case DW_LANG_Fortran08:		printf ("(Fortran 08)"); break;
	case DW_LANG_RenderScript:	printf ("(RenderScript)"); break;
	  /* MIPS extension.  */
	case DW_LANG_Mips_Assembler:	printf ("(MIPS assembler)"); break;
	  /* UPC extension.  */
	case DW_LANG_Upc:		printf ("(Unified Parallel C)"); break;
	default:
	  if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user)
	    printf (_("(implementation defined: %s)"),
		    dwarf_vmatoa ("x", uvalue));
	  else
	    printf (_("(Unknown: %s)"), dwarf_vmatoa ("x", uvalue));
	  break;
	}
      break;

    case DW_AT_encoding:
      printf ("\t");
      switch (uvalue)
	{
	case DW_ATE_void:		printf ("(void)"); break;
	case DW_ATE_address:		printf ("(machine address)"); break;
	case DW_ATE_boolean:		printf ("(boolean)"); break;
	case DW_ATE_complex_float:	printf ("(complex float)"); break;
	case DW_ATE_float:		printf ("(float)"); break;
	case DW_ATE_signed:		printf ("(signed)"); break;
	case DW_ATE_signed_char:	printf ("(signed char)"); break;
	case DW_ATE_unsigned:		printf ("(unsigned)"); break;
	case DW_ATE_unsigned_char:	printf ("(unsigned char)"); break;
	  /* DWARF 2.1 values:  */
	case DW_ATE_imaginary_float:	printf ("(imaginary float)"); break;
	case DW_ATE_decimal_float:	printf ("(decimal float)"); break;
	  /* DWARF 3 values:  */
	case DW_ATE_packed_decimal:	printf ("(packed_decimal)"); break;
	case DW_ATE_numeric_string:	printf ("(numeric_string)"); break;
	case DW_ATE_edited:		printf ("(edited)"); break;
	case DW_ATE_signed_fixed:	printf ("(signed_fixed)"); break;
	case DW_ATE_unsigned_fixed:	printf ("(unsigned_fixed)"); break;
	  /* DWARF 4 values:  */
	case DW_ATE_UTF:		printf ("(unicode string)"); break;
	  /* DWARF 5 values:  */
	case DW_ATE_UCS:		printf ("(UCS)"); break;
	case DW_ATE_ASCII:		printf ("(ASCII)"); break;

	  /* HP extensions:  */
	case DW_ATE_HP_float80:		printf ("(HP_float80)"); break;
	case DW_ATE_HP_complex_float80:	printf ("(HP_complex_float80)"); break;
	case DW_ATE_HP_float128:	printf ("(HP_float128)"); break;
	case DW_ATE_HP_complex_float128:printf ("(HP_complex_float128)"); break;
	case DW_ATE_HP_floathpintel:	printf ("(HP_floathpintel)"); break;
	case DW_ATE_HP_imaginary_float80:	printf ("(HP_imaginary_float80)"); break;
	case DW_ATE_HP_imaginary_float128:	printf ("(HP_imaginary_float128)"); break;

	default:
	  if (uvalue >= DW_ATE_lo_user
	      && uvalue <= DW_ATE_hi_user)
	    printf (_("(user defined type)"));
	  else
	    printf (_("(unknown type)"));
	  break;
	}
      break;

    case DW_AT_accessibility:
      printf ("\t");
      switch (uvalue)
	{
	case DW_ACCESS_public:		printf ("(public)"); break;
	case DW_ACCESS_protected:	printf ("(protected)"); break;
	case DW_ACCESS_private:		printf ("(private)"); break;
	default:
	  printf (_("(unknown accessibility)"));
	  break;
	}
      break;

    case DW_AT_visibility:
      printf ("\t");
      switch (uvalue)
	{
	case DW_VIS_local:		printf ("(local)"); break;
	case DW_VIS_exported:		printf ("(exported)"); break;
	case DW_VIS_qualified:		printf ("(qualified)"); break;
	default:			printf (_("(unknown visibility)")); break;
	}
      break;

    case DW_AT_endianity:
      printf ("\t");
      switch (uvalue)
	{
	case DW_END_default:		printf ("(default)"); break;
	case DW_END_big:		printf ("(big)"); break;
	case DW_END_little:		printf ("(little)"); break;
	default:
	  if (uvalue >= DW_END_lo_user && uvalue <= DW_END_hi_user)
	    printf (_("(user specified)"));
	  else
	    printf (_("(unknown endianity)"));
	  break;
	}
      break;

    case DW_AT_virtuality:
      printf ("\t");
      switch (uvalue)
	{
	case DW_VIRTUALITY_none:	printf ("(none)"); break;
	case DW_VIRTUALITY_virtual:	printf ("(virtual)"); break;
	case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
	default:			printf (_("(unknown virtuality)")); break;
	}
      break;

    case DW_AT_identifier_case:
      printf ("\t");
      switch (uvalue)
	{
	case DW_ID_case_sensitive:	printf ("(case_sensitive)"); break;
	case DW_ID_up_case:		printf ("(up_case)"); break;
	case DW_ID_down_case:		printf ("(down_case)"); break;
	case DW_ID_case_insensitive:	printf ("(case_insensitive)"); break;
	default:			printf (_("(unknown case)")); break;
	}
      break;

    case DW_AT_calling_convention:
      printf ("\t");
      switch (uvalue)
	{
	case DW_CC_normal:	printf ("(normal)"); break;
	case DW_CC_program:	printf ("(program)"); break;
	case DW_CC_nocall:	printf ("(nocall)"); break;
	case DW_CC_pass_by_reference: printf ("(pass by ref)"); break;
	case DW_CC_pass_by_value: printf ("(pass by value)"); break;
	case DW_CC_GNU_renesas_sh: printf ("(Rensas SH)"); break;
	case DW_CC_GNU_borland_fastcall_i386: printf ("(Borland fastcall i386)"); break;
	default:
	  if (uvalue >= DW_CC_lo_user
	      && uvalue <= DW_CC_hi_user)
	    printf (_("(user defined)"));
	  else
	    printf (_("(unknown convention)"));
	}
      break;

    case DW_AT_ordering:
      printf ("\t");
      switch (uvalue)
	{
	case 255:
	case -1: printf (_("(undefined)")); break;
	case 0:  printf ("(row major)"); break;
	case 1:  printf ("(column major)"); break;
	}
      break;

    case DW_AT_decimal_sign:
      printf ("\t");
      switch (uvalue)
	{
	case DW_DS_unsigned:            printf (_("(unsigned)")); break;
	case DW_DS_leading_overpunch:   printf (_("(leading overpunch)")); break;
	case DW_DS_trailing_overpunch:  printf (_("(trailing overpunch)")); break;
	case DW_DS_leading_separate:    printf (_("(leading separate)")); break;
	case DW_DS_trailing_separate:   printf (_("(trailing separate)")); break;
	default:                        printf (_("(unrecognised)")); break;
	}
      break;

    case DW_AT_defaulted:
      printf ("\t");
      switch (uvalue)
	{
	case DW_DEFAULTED_no:           printf (_("(no)")); break;
	case DW_DEFAULTED_in_class:     printf (_("(in class)")); break;
	case DW_DEFAULTED_out_of_class: printf (_("(out of class)")); break;
	default:                        printf (_("(unrecognised)")); break;
	}
      break;

    case DW_AT_discr_list:
      printf ("\t");
      display_discr_list (form, uvalue, data, level);
      break;

    case DW_AT_frame_base:
      have_frame_base = 1;
      /* Fall through.  */
    case DW_AT_location:
    case DW_AT_loclists_base:
    case DW_AT_rnglists_base:
    case DW_AT_str_offsets_base:
    case DW_AT_string_length:
    case DW_AT_return_addr:
    case DW_AT_data_member_location:
    case DW_AT_vtable_elem_location:
    case DW_AT_segment:
    case DW_AT_static_link:
    case DW_AT_use_location:
    case DW_AT_call_value:
    case DW_AT_GNU_call_site_value:
    case DW_AT_call_data_value:
    case DW_AT_GNU_call_site_data_value:
    case DW_AT_call_target:
    case DW_AT_GNU_call_site_target:
    case DW_AT_call_target_clobbered:
    case DW_AT_GNU_call_site_target_clobbered:
      if ((dwarf_version < 4
	   && (form == DW_FORM_data4 || form == DW_FORM_data8))
	  || form == DW_FORM_sec_offset
	  || form == DW_FORM_loclistx)
	{
	  if (attribute != DW_AT_rnglists_base
	      && attribute != DW_AT_str_offsets_base)
	    printf (_(" (location list)"));
	}
      /* Fall through.  */
    case DW_AT_allocated:
    case DW_AT_associated:
    case DW_AT_data_location:
    case DW_AT_stride:
    case DW_AT_upper_bound:
    case DW_AT_lower_bound:
      if (block_start)
	{
	  int need_frame_base;

	  printf ("\t(");
	  need_frame_base = decode_location_expression (block_start,
							pointer_size,
							offset_size,
							dwarf_version,
							uvalue,
							cu_offset, section);
	  printf (")");
	  if (need_frame_base && !have_frame_base)
	    printf (_(" [without DW_AT_frame_base]"));
	}
      break;

    case DW_AT_data_bit_offset:
    case DW_AT_byte_size:
    case DW_AT_bit_size:
    case DW_AT_string_length_byte_size:
    case DW_AT_string_length_bit_size:
    case DW_AT_bit_stride:
      if (form == DW_FORM_exprloc)
	{
	  printf ("\t(");
	  (void) decode_location_expression (block_start, pointer_size,
					     offset_size, dwarf_version,
					     uvalue, cu_offset, section);
	  printf (")");
	}
      break;

    case DW_AT_import:
      {
	unsigned long abbrev_number;
	abbrev_entry *entry;

	entry = get_type_abbrev_from_form (form, uvalue, cu_offset, end,
					   section, & abbrev_number, NULL, NULL);
	if (entry == NULL)
	  {
	    if (form != DW_FORM_GNU_ref_alt)
	      warn (_("Offset %s used as value for DW_AT_import attribute of DIE at offset 0x%lx is too big.\n"),
		    dwarf_vmatoa ("x", uvalue),
		    (unsigned long) (orig_data - section->start));
	  }
	else
	  {
	    printf (_("\t[Abbrev Number: %ld"), abbrev_number);
	    printf (" (%s)", get_TAG_name (entry->tag));
	    printf ("]");
	  }
      }
      break;

    default:
      break;
    }

  return data;
}


display_block (unsigned char *data,
	       dwarf_vma length,
	       const unsigned char * const end, char delimiter)
{
  dwarf_vma maxlen;

  printf (_("%c%s byte block: "), delimiter, dwarf_vmatoa ("u", length));
  if (data > end)
    return (unsigned char *) end;

  maxlen = (dwarf_vma) (end - data);
  length = length > maxlen ? maxlen : length;

  while (length --)
    printf ("%lx ", (unsigned long) byte_get (data++, 1));

  return data;
}


display_debug_abbrev (struct dwarf_section *section,
		      void *file ATTRIBUTE_UNUSED)
{
  abbrev_entry *entry;
  unsigned char *start = section->start;

  introduce (section, false);

  do
    {
      abbrev_list *    list;
      dwarf_vma        offset;

      offset = start - section->start;
      list = find_abbrev_list_by_abbrev_offset (0, offset);
      if (list == NULL)
	{
	  list = new_abbrev_list (0, offset);
	  start = process_abbrev_set (section, 0, section->size, offset, list);
	  list->start_of_next_abbrevs = start;
	}
      else
	start = list->start_of_next_abbrevs;

      if (list->first_abbrev == NULL)
	continue;

      printf (_("  Number TAG (0x%lx)\n"), (long) offset);

      for (entry = list->first_abbrev; entry; entry = entry->next)
	{
	  abbrev_attr *attr;

	  printf ("   %ld      %s    [%s]\n",
		  entry->number,
		  get_TAG_name (entry->tag),
		  entry->children ? _("has children") : _("no children"));

	  for (attr = entry->first_attr; attr; attr = attr->next)
	    {
	      printf ("    %-18s %s",
		      get_AT_name (attr->attribute),
		      get_FORM_name (attr->form));
	      if (attr->form == DW_FORM_implicit_const)
		printf (": %s", dwarf_vmatoa ("d", attr->implicit_const));
	      putchar ('\n');
	    }
	}
    }
  while (start);

  printf ("\n");

  return 1;
}


get_type_signedness (abbrev_entry *entry,
		     const struct dwarf_section *section,
		     unsigned char *data,
		     unsigned char *end,
		     dwarf_vma cu_offset,
		     dwarf_vma pointer_size,
		     dwarf_vma offset_size,
		     int dwarf_version,
		     bool *is_signed,
		     unsigned int nesting)
{
  abbrev_attr *   attr;

  * is_signed = false;

#define MAX_NESTING 20
  if (nesting > MAX_NESTING)
    {
      /* FIXME: Warn - or is this expected ?
	 NB/ We need to avoid infinite recursion.  */
      return;
    }

  for (attr = entry->first_attr;
       attr != NULL && attr->attribute;
       attr = attr->next)
    {
      unsigned char * orig_data = data;
      dwarf_vma uvalue = 0;

      data = skip_attr_bytes (attr->form, data, end, pointer_size,
			      offset_size, dwarf_version, & uvalue);
      if (data == NULL)
	return;

      switch (attr->attribute)
	{
	case DW_AT_linkage_name:
	case DW_AT_name:
	  if (do_wide)
	    {
	      if (attr->form == DW_FORM_strp)
		printf (", %s", fetch_indirect_string (uvalue));
	      else if (attr->form == DW_FORM_string)
		printf (", %.*s", (int) (end - orig_data), orig_data);
	    }
	  break;

	case DW_AT_type:
	  /* Recurse.  */
	  {
	    abbrev_entry *type_abbrev;
	    unsigned char *type_data;
	    abbrev_map *map;

	    type_abbrev = get_type_abbrev_from_form (attr->form,
						     uvalue,
						     cu_offset,
						     end,
						     section,
						     NULL /* abbrev num return */,
						     &type_data,
						     &map);
	    if (type_abbrev == NULL)
	      break;

	    get_type_signedness (type_abbrev, section, type_data,
				 map ? section->start + map->end : end,
				 map ? map->start : cu_offset,
				 pointer_size, offset_size, dwarf_version,
				 is_signed, nesting + 1);
	  }
	  break;

	case DW_AT_encoding:
	  /* Determine signness.  */
	  switch (uvalue)
	    {
	    case DW_ATE_address:
	      /* FIXME - some architectures have signed addresses.  */
	    case DW_ATE_boolean:
	    case DW_ATE_unsigned:
	    case DW_ATE_unsigned_char:
	    case DW_ATE_unsigned_fixed:
	      * is_signed = false;
	      break;

	    default:
	    case DW_ATE_complex_float:
	    case DW_ATE_float:
	    case DW_ATE_signed:
	    case DW_ATE_signed_char:
	    case DW_ATE_imaginary_float:
	    case DW_ATE_decimal_float:
	    case DW_ATE_signed_fixed:
	      * is_signed = true;
	      break;
	    }
	  break;
	}
    }
}


dwarf_vmatoa (const char * fmtch, dwarf_vma value)
{
  return dwarf_vmatoa_1 (fmtch, value, 0);
}


print_addr_index (unsigned int idx, unsigned int len)
{
  static char buf[15];
  snprintf (buf, sizeof (buf), "[%d]", idx);
  printf ("%*s ", len, buf);
}


parse_gnu_debugaltlink (struct dwarf_section * section, void * data)
{
  const char *     name;
  bfd_size_type    namelen;
  bfd_size_type    id_len;
  Build_id_data *  build_id_data;

  /* The name is first.
     The build-id follows immediately, with no padding, up to the section's end.  */

  name = (const char *) section->start;
  namelen = strnlen (name, section->size) + 1;
  if (namelen == 1)
    return NULL;
  if (namelen >= section->size)
    return NULL;

  id_len = section->size - namelen;
  if (id_len < 0x14)
    return NULL;

  build_id_data = (Build_id_data *) data;
  build_id_data->len = id_len;
  build_id_data->data = section->start + namelen;

  return name;
}


find_cu_tu_set (void *file, unsigned int shndx)
{
  unsigned int i;

  if (! load_cu_tu_indexes (file))
    return NULL;

  /* Find SHNDX in the shndx pool.  */
  for (i = 0; i < shndx_pool_used; i++)
    if (shndx_pool [i] == shndx)
      break;

  if (i >= shndx_pool_used)
    return NULL;

  /* Now backup to find the first entry in the set.  */
  while (i > 0 && shndx_pool [i - 1] != 0)
    i--;

  return shndx_pool + i;
}


read_debug_line_header (struct dwarf_section * section,
			unsigned char * data,
			unsigned char * end,
			DWARF2_Internal_LineInfo * linfo,
			unsigned char ** end_of_sequence)
{
  unsigned char *hdrptr;

  /* Extract information from the Line Number Program Header.
     (section 6.2.4 in the Dwarf3 doc).  */
  hdrptr = data;

  /* Get and check the length of the block.  */
  SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 4, end);

  if (linfo->li_length == 0xffffffff)
    {
      /* This section is 64-bit DWARF 3.  */
      SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 8, end);
      linfo->li_offset_size = 8;
    }
  else
    linfo->li_offset_size = 4;

  if (linfo->li_length > (size_t) (end - hdrptr))
    {
      /* If the length field has a relocation against it, then we should
	 not complain if it is inaccurate (and probably negative).  This
	 happens in object files when the .debug_line section is actually
	 comprised of several different .debug_line.* sections, (some of
	 which may be removed by linker garbage collection), and a relocation
	 is used to compute the correct length once that is done.  */
      if (reloc_at (section, (hdrptr - section->start) - linfo->li_offset_size))
	{
	  linfo->li_length = end - hdrptr;
	}
      else
	{
	  warn (_("The length field (0x%lx) in the debug_line header is wrong - the section is too small\n"),
		(long) linfo->li_length);
	  return NULL;
	}
    }
  end = hdrptr + linfo->li_length;

  /* Get and check the version number.  */
  SAFE_BYTE_GET_AND_INC (linfo->li_version, hdrptr, 2, end);

  if (linfo->li_version != 2
      && linfo->li_version != 3
      && linfo->li_version != 4
      && linfo->li_version != 5)
    {
      warn (_("Only DWARF version 2, 3, 4 and 5 line info "
	      "is currently supported.\n"));
      return NULL;
    }

  if (linfo->li_version >= 5)
    {
      SAFE_BYTE_GET_AND_INC (linfo->li_address_size, hdrptr, 1, end);

      SAFE_BYTE_GET_AND_INC (linfo->li_segment_size, hdrptr, 1, end);
      if (linfo->li_segment_size != 0)
	{
	  warn (_("The %s section contains "
		  "unsupported segment selector size: %d.\n"),
		section->name, linfo->li_segment_size);
	  return NULL;
	}
    }

  SAFE_BYTE_GET_AND_INC (linfo->li_prologue_length, hdrptr,
			 linfo->li_offset_size, end);
  SAFE_BYTE_GET_AND_INC (linfo->li_min_insn_length, hdrptr, 1, end);

  if (linfo->li_version >= 4)
    {
      SAFE_BYTE_GET_AND_INC (linfo->li_max_ops_per_insn, hdrptr, 1, end);

      if (linfo->li_max_ops_per_insn == 0)
	{
	  warn (_("Invalid maximum operations per insn.\n"));
	  return NULL;
	}
    }
  else
    linfo->li_max_ops_per_insn = 1;

  SAFE_BYTE_GET_AND_INC (linfo->li_default_is_stmt, hdrptr, 1, end);
  SAFE_SIGNED_BYTE_GET_AND_INC (linfo->li_line_base, hdrptr, 1, end);
  SAFE_BYTE_GET_AND_INC (linfo->li_line_range, hdrptr, 1, end);
  SAFE_BYTE_GET_AND_INC (linfo->li_opcode_base, hdrptr, 1, end);

  *end_of_sequence = end;
  return hdrptr;
}


fetch_indirect_line_string (dwarf_vma offset)
{
  struct dwarf_section *section = &debug_displays [line_str].section;
  const unsigned char * ret;

  if (section->start == NULL)
    return (const unsigned char *) _("<no .debug_line_str section>");

  if (offset >= section->size)
    {
      warn (_("DW_FORM_line_strp offset too big: 0x%s\n"),
	    dwarf_vmatoa ("x", offset));
      return (const unsigned char *) _("<offset is too big>");
    }

  ret = section->start + offset;
  /* Unfortunately we cannot rely upon the .debug_line_str section ending
     with a NUL byte.  Since our caller is expecting to receive a well formed
     C string we test for the lack of a terminating byte here.  */
  if (strnlen ((const char *) ret, section->size - offset)
      == section->size - offset)
    ret = (const unsigned char *)
      _("<no NUL byte at end of .debug_line_str section>");

  return ret;
}


display_data (bfd_size_type          printed,
	      const unsigned char *  data,
	      const bfd_size_type    len)
{
  if (do_wide || len < ((80 - printed) / 3))
    for (printed = 0; printed < len; ++printed)
      printf (" %02x", data[printed]);
  else
    {
      for (printed = 0; printed < len; ++printed)
	{
	  if (printed % (80 / 3) == 0)
	    putchar ('\n');
	  printf (" %02x", data[printed]);
	}
    }
}


skip_attr_bytes (unsigned long form,
		 unsigned char *data,
		 unsigned char *end,
		 dwarf_vma pointer_size,
		 dwarf_vma offset_size,
		 int dwarf_version,
		 dwarf_vma *value_return)
{
  dwarf_signed_vma svalue;
  dwarf_vma uvalue = 0;
  dwarf_vma inc = 0;

  * value_return = 0;

  switch (form)
    {
    case DW_FORM_ref_addr:
      if (dwarf_version == 2)
	SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
      else if (dwarf_version > 2)
	SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
      else
	return NULL;
      break;

    case DW_FORM_addr:
      SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
      break;

    case DW_FORM_strp:
    case DW_FORM_line_strp:
    case DW_FORM_sec_offset:
    case DW_FORM_GNU_ref_alt:
    case DW_FORM_GNU_strp_alt:
      SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
      break;

    case DW_FORM_flag_present:
      uvalue = 1;
      break;

    case DW_FORM_ref1:
    case DW_FORM_flag:
    case DW_FORM_data1:
    case DW_FORM_strx1:
    case DW_FORM_addrx1:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
      break;

    case DW_FORM_strx3:
    case DW_FORM_addrx3:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 3, end);
      break;

    case DW_FORM_ref2:
    case DW_FORM_data2:
    case DW_FORM_strx2:
    case DW_FORM_addrx2:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
      break;

    case DW_FORM_ref4:
    case DW_FORM_data4:
    case DW_FORM_strx4:
    case DW_FORM_addrx4:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
      break;

    case DW_FORM_sdata:
      READ_SLEB (svalue, data, end);
      uvalue = svalue;
      break;

    case DW_FORM_ref_udata:
    case DW_FORM_udata:
    case DW_FORM_GNU_str_index:
    case DW_FORM_strx:
    case DW_FORM_GNU_addr_index:
    case DW_FORM_addrx:
    case DW_FORM_loclistx:
    case DW_FORM_rnglistx:
      READ_ULEB (uvalue, data, end);
      break;

    case DW_FORM_ref8:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 8, end);
      break;

    case DW_FORM_data8:
    case DW_FORM_ref_sig8:
      inc = 8;
      break;

    case DW_FORM_data16:
      inc = 16;
      break;

    case DW_FORM_string:
      inc = strnlen ((char *) data, end - data) + 1;
      break;

    case DW_FORM_block:
    case DW_FORM_exprloc:
      READ_ULEB (uvalue, data, end);
      inc = uvalue;
      break;

    case DW_FORM_block1:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
      inc = uvalue;
      break;

    case DW_FORM_block2:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
      inc = uvalue;
      break;

    case DW_FORM_block4:
      SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
      inc = uvalue;
      break;

    case DW_FORM_indirect:
      READ_ULEB (form, data, end);
      if (form == DW_FORM_implicit_const)
	SKIP_ULEB (data, end);
      return skip_attr_bytes (form, data, end, pointer_size, offset_size,
			      dwarf_version, value_return);

    default:
      return NULL;
    }

  * value_return = uvalue;
  if (inc <= (dwarf_vma) (end - data))
    data += inc;
  else
    data = end;
  return data;
}


read_and_display_attr (unsigned long           attribute,
		       unsigned long           form,
		       dwarf_signed_vma        implicit_const,
		       unsigned char *         start,
		       unsigned char *         data,
		       unsigned char *         end,
		       dwarf_vma               cu_offset,
		       dwarf_vma               pointer_size,
		       dwarf_vma               offset_size,
		       int                     dwarf_version,
		       debug_info *            debug_info_p,
		       int                     do_loc,
		       struct dwarf_section *  section,
		       struct cu_tu_set *      this_set,
		       int                     level)
{
  if (!do_loc)
    printf ("   %-18s:", get_AT_name (attribute));
  data = read_and_display_attr_value (attribute, form, implicit_const,
				      start, data, end,
				      cu_offset, pointer_size, offset_size,
				      dwarf_version, debug_info_p,
				      do_loc, section, this_set, ' ', level);
  if (!do_loc)
    printf ("\n");
  return data;
}


display_gdb_index (struct dwarf_section *section,
		   void *file ATTRIBUTE_UNUSED)
{
  unsigned char *start = section->start;
  uint32_t version;
  uint32_t cu_list_offset, tu_list_offset;
  uint32_t address_table_offset, symbol_table_offset, constant_pool_offset;
  unsigned int cu_list_elements, tu_list_elements;
  unsigned int address_table_elements, symbol_table_slots;
  unsigned char *cu_list, *tu_list;
  unsigned char *address_table, *symbol_table, *constant_pool;
  unsigned int i;

  /* The documentation for the format of this file is in gdb/dwarf2read.c.  */

  introduce (section, false);

  if (section->size < 6 * sizeof (uint32_t))
    {
      warn (_("Truncated header in the %s section.\n"), section->name);
      return 0;
    }

  version = byte_get_little_endian (start, 4);
  printf (_("Version %ld\n"), (long) version);

  /* Prior versions are obsolete, and future versions may not be
     backwards compatible.  */
  if (version < 3 || version > 8)
    {
      warn (_("Unsupported version %lu.\n"), (unsigned long) version);
      return 0;
    }
  if (version < 4)
    warn (_("The address table data in version 3 may be wrong.\n"));
  if (version < 5)
    warn (_("Version 4 does not support case insensitive lookups.\n"));
  if (version < 6)
    warn (_("Version 5 does not include inlined functions.\n"));
  if (version < 7)
      warn (_("Version 6 does not include symbol attributes.\n"));
  /* Version 7 indices generated by Gold have bad type unit references,
     PR binutils/15021.  But we don't know if the index was generated by
     Gold or not, so to avoid worrying users with gdb-generated indices
     we say nothing for version 7 here.  */

  cu_list_offset = byte_get_little_endian (start + 4, 4);
  tu_list_offset = byte_get_little_endian (start + 8, 4);
  address_table_offset = byte_get_little_endian (start + 12, 4);
  symbol_table_offset = byte_get_little_endian (start + 16, 4);
  constant_pool_offset = byte_get_little_endian (start + 20, 4);

  if (cu_list_offset > section->size
      || tu_list_offset > section->size
      || address_table_offset > section->size
      || symbol_table_offset > section->size
      || constant_pool_offset > section->size
      || tu_list_offset < cu_list_offset
      || address_table_offset < tu_list_offset
      || symbol_table_offset < address_table_offset
      || constant_pool_offset < symbol_table_offset)
    {
      warn (_("Corrupt header in the %s section.\n"), section->name);
      return 0;
    }

  cu_list_elements = (tu_list_offset - cu_list_offset) / 16;
  tu_list_elements = (address_table_offset - tu_list_offset) / 24;
  address_table_elements = (symbol_table_offset - address_table_offset) / 20;
  symbol_table_slots = (constant_pool_offset - symbol_table_offset) / 8;

  cu_list = start + cu_list_offset;
  tu_list = start + tu_list_offset;
  address_table = start + address_table_offset;
  symbol_table = start + symbol_table_offset;
  constant_pool = start + constant_pool_offset;

  printf (_("\nCU table:\n"));
  for (i = 0; i < cu_list_elements; i++)
    {
      uint64_t cu_offset = byte_get_little_endian (cu_list + i * 16, 8);
      uint64_t cu_length = byte_get_little_endian (cu_list + i * 16 + 8, 8);

      printf (_("[%3u] 0x%lx - 0x%lx\n"), i,
	      (unsigned long) cu_offset,
	      (unsigned long) (cu_offset + cu_length - 1));
    }

  printf (_("\nTU table:\n"));
  for (i = 0; i < tu_list_elements; i++)
    {
      uint64_t tu_offset = byte_get_little_endian (tu_list + i * 24, 8);
      uint64_t type_offset = byte_get_little_endian (tu_list + i * 24 + 8, 8);
      uint64_t signature = byte_get_little_endian (tu_list + i * 24 + 16, 8);

      printf (_("[%3u] 0x%lx 0x%lx "), i,
	      (unsigned long) tu_offset,
	      (unsigned long) type_offset);
      print_dwarf_vma (signature, 8);
      printf ("\n");
    }

  printf (_("\nAddress table:\n"));
  for (i = 0; i < address_table_elements; i++)
    {
      uint64_t low = byte_get_little_endian (address_table + i * 20, 8);
      uint64_t high = byte_get_little_endian (address_table + i * 20 + 8, 8);
      uint32_t cu_index = byte_get_little_endian (address_table + i + 20 + 16, 4);

      print_dwarf_vma (low, 8);
      print_dwarf_vma (high, 8);
      printf (_("%lu\n"), (unsigned long) cu_index);
    }

  printf (_("\nSymbol table:\n"));
  for (i = 0; i < symbol_table_slots; ++i)
    {
      uint32_t name_offset = byte_get_little_endian (symbol_table + i * 8, 4);
      uint32_t cu_vector_offset = byte_get_little_endian (symbol_table + i * 8 + 4, 4);
      uint32_t num_cus, cu;

      if (name_offset != 0
	  || cu_vector_offset != 0)
	{
	  unsigned int j;

	  /* PR 17531: file: 5b7b07ad.  */
	  if (name_offset >= section->size - constant_pool_offset)
	    {
	      printf (_("[%3u] <corrupt offset: %x>"), i, name_offset);
	      warn (_("Corrupt name offset of 0x%x found for symbol table slot %d\n"),
		    name_offset, i);
	    }
	  else
	    printf ("[%3u] %.*s:", i,
		    (int) (section->size - (constant_pool_offset + name_offset)),
		    constant_pool + name_offset);

	  if (section->size - constant_pool_offset < 4
	      || cu_vector_offset > section->size - constant_pool_offset - 4)
	    {
	      printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset);
	      warn (_("Corrupt CU vector offset of 0x%x found for symbol table slot %d\n"),
		    cu_vector_offset, i);
	      continue;
	    }

	  num_cus = byte_get_little_endian (constant_pool + cu_vector_offset, 4);

	  if ((uint64_t) num_cus * 4 > section->size - (constant_pool_offset
							+ cu_vector_offset + 4))
	    {
	      printf ("<invalid number of CUs: %d>\n", num_cus);
	      warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"),
		    num_cus, i);
	      continue;
	    }

	  if (num_cus > 1)
	    printf ("\n");

	  for (j = 0; j < num_cus; ++j)
	    {
	      int is_static;
	      gdb_index_symbol_kind kind;

	      cu = byte_get_little_endian (constant_pool + cu_vector_offset + 4 + j * 4, 4);
	      is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu);
	      kind = GDB_INDEX_SYMBOL_KIND_VALUE (cu);
	      cu = GDB_INDEX_CU_VALUE (cu);
	      /* Convert to TU number if it's for a type unit.  */
	      if (cu >= cu_list_elements / 2)
		printf ("%cT%lu", num_cus > 1 ? '\t' : ' ',
			(unsigned long) (cu - cu_list_elements / 2));
	      else
		printf ("%c%lu", num_cus > 1 ? '\t' : ' ', (unsigned long) cu);

	      printf (" [%s, %s]",
		      is_static ? _("static") : _("global"),
		      get_gdb_index_symbol_kind_name (kind));
	      if (num_cus > 1)
		printf ("\n");
	    }
	  if (num_cus <= 1)
	    printf ("\n");
	}
    }

  return 1;
}


xcalloc2 (size_t nmemb, size_t size)
{
  /* Check for overflow.  */
  if (nmemb >= ~(size_t) 0 / size)
    {
      error (_("Attempt to allocate a zero'ed array with an excessive number of elements: 0x%lx\n"),
	     (long) nmemb);
      xexit (1);
    }

  return xcalloc (nmemb, size);
}


get_FORM_name (unsigned long form)
{
  const char *name;

  if (form == 0)
    return "DW_FORM value: 0";

  name = get_DW_FORM_name (form);
  if (name == NULL)
    {
      static char buffer[100];

      snprintf (buffer, sizeof (buffer), _("Unknown FORM value: %lx"), form);
      return buffer;
    }

  return name;
}


display_debug_str (struct dwarf_section *section,
		   void *file ATTRIBUTE_UNUSED)
{
  unsigned char *start = section->start;
  dwarf_vma bytes = section->size;
  dwarf_vma addr = section->address;

  if (bytes == 0)
    {
      printf (_("\nThe %s section is empty.\n"), section->name);
      return 0;
    }

  introduce (section, false);

  while (bytes)
    {
      int j;
      int k;
      int lbytes;

      lbytes = (bytes > 16 ? 16 : bytes);

      printf ("  0x%8.8lx ", (unsigned long) addr);

      for (j = 0; j < 16; j++)
	{
	  if (j < lbytes)
	    printf ("%2.2x", start[j]);
	  else
	    printf ("  ");

	  if ((j & 3) == 3)
	    printf (" ");
	}

      for (j = 0; j < lbytes; j++)
	{
	  k = start[j];
	  if (k >= ' ' && k < 0x80)
	    printf ("%c", k);
	  else
	    printf (".");
	}

      putchar ('\n');

      start += lbytes;
      addr  += lbytes;
      bytes -= lbytes;
    }

  putchar ('\n');

  return 1;
}


display_loclists_list (struct dwarf_section *  section,
		       unsigned char **        start_ptr,
		       unsigned int            debug_info_entry,
		       dwarf_vma               offset,
		       dwarf_vma               base_address,
		       unsigned char **        vstart_ptr,
		       int                     has_frame_base)
{
  unsigned char *  start = *start_ptr;
  unsigned char *  vstart = *vstart_ptr;
  unsigned char *  section_end = section->start + section->size;
  dwarf_vma        cu_offset;
  unsigned int     pointer_size;
  unsigned int     offset_size;
  unsigned int     dwarf_version;

  /* Initialize it due to a false compiler warning.  */
  dwarf_vma begin = -1, vbegin = -1;
  dwarf_vma end = -1, vend = -1;
  dwarf_vma length;
  int need_frame_base;

  if (debug_info_entry >= num_debug_info_entries)
    {
      warn (_("No debug information available for "
	      "loclists lists of entry: %u\n"),
	    debug_info_entry);
      return;
    }

  cu_offset = debug_information [debug_info_entry].cu_offset;
  pointer_size = debug_information [debug_info_entry].pointer_size;
  offset_size = debug_information [debug_info_entry].offset_size;
  dwarf_version = debug_information [debug_info_entry].dwarf_version;

  if (pointer_size < 2 || pointer_size > 8)
    {
      warn (_("Invalid pointer size (%d) in debug info for entry %d\n"),
	    pointer_size, debug_info_entry);
      return;
    }

  while (1)
    {
      dwarf_vma off = offset + (start - *start_ptr);
      enum dwarf_location_list_entry_type llet;

      if (start + 1 > section_end)
	{
	  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
		(unsigned long) offset);
	  break;
	}

      printf ("    ");
      print_dwarf_vma (off, 4);

      SAFE_BYTE_GET_AND_INC (llet, start, 1, section_end);

      if (vstart && (llet == DW_LLE_offset_pair
		     || llet == DW_LLE_start_end
		     || llet == DW_LLE_start_length))
	{
	  off = offset + (vstart - *start_ptr);

	  READ_ULEB (vbegin, vstart, section_end);
	  print_dwarf_view (vbegin, pointer_size, 1);

	  READ_ULEB (vend, vstart, section_end);
	  print_dwarf_view (vend, pointer_size, 1);

	  printf (_("views at %8.8lx for:\n    %*s "),
		  (unsigned long) off, 8, "");
	}

      switch (llet)
	{
	case DW_LLE_end_of_list:
	  printf (_("<End of list>\n"));
	  break;

	case DW_LLE_base_addressx:
	  READ_ULEB (base_address, start, section_end);
	  print_dwarf_vma (base_address, pointer_size);
	  printf (_("(index into .debug_addr) "));
	  base_address = fetch_indexed_addr (base_address, pointer_size);
	  print_dwarf_vma (base_address, pointer_size);
	  printf (_("(base address)\n"));
	  break;

	case DW_LLE_startx_endx:
	  READ_ULEB (begin, start, section_end);
	  begin = fetch_indexed_addr (begin, pointer_size);
	  READ_ULEB (end, start, section_end);
	  end = fetch_indexed_addr (end, pointer_size);
	  break;

	case DW_LLE_startx_length:
	  READ_ULEB (begin, start, section_end);
	  begin = fetch_indexed_addr (begin, pointer_size);
	  READ_ULEB (end, start, section_end);
	  end += begin;
	  break;

	case DW_LLE_default_location:
	  begin = end = 0;
	  break;

	case DW_LLE_offset_pair:
	  READ_ULEB (begin, start, section_end);
	  begin += base_address;
	  READ_ULEB (end, start, section_end);
	  end += base_address;
	  break;

	case DW_LLE_base_address:
	  SAFE_BYTE_GET_AND_INC (base_address, start, pointer_size,
				 section_end);
	  print_dwarf_vma (base_address, pointer_size);
	  printf (_("(base address)\n"));
	  break;

	case DW_LLE_start_end:
	  SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, section_end);
	  SAFE_BYTE_GET_AND_INC (end, start, pointer_size, section_end);
	  break;

	case DW_LLE_start_length:
	  SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, section_end);
	  READ_ULEB (end, start, section_end);
	  end += begin;
	  break;

#ifdef DW_LLE_view_pair
	case DW_LLE_view_pair:
	  if (vstart)
	    printf (_("View pair entry in loclist with locviews attribute\n"));
	  READ_ULEB (vbegin, start, section_end);
	  print_dwarf_view (vbegin, pointer_size, 1);

	  READ_ULEB (vend, start, section_end);
	  print_dwarf_view (vend, pointer_size, 1);

	  printf (_("views for:\n"));
	  continue;
#endif

	default:
	  error (_("Invalid location list entry type %d\n"), llet);
	  return;
	}

      if (llet == DW_LLE_end_of_list)
	break;

      if (llet == DW_LLE_base_address
	  || llet == DW_LLE_base_addressx)
	continue;

      if (start == section_end)
	{
	  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
		(unsigned long) offset);
	  break;
	}
      READ_ULEB (length, start, section_end);

      if (length > (size_t) (section_end - start))
	{
	  warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
		(unsigned long) offset);
	  break;
	}

      print_dwarf_vma (begin, pointer_size);
      print_dwarf_vma (end, pointer_size);

      putchar ('(');
      need_frame_base = decode_location_expression (start,
						    pointer_size,
						    offset_size,
						    dwarf_version,
						    length,
						    cu_offset, section);
      putchar (')');

      if (need_frame_base && !has_frame_base)
	printf (_(" [without DW_AT_frame_base]"));

      if (begin == end && vbegin == vend)
	fputs (_(" (start == end)"), stdout);
      else if (begin > end || (begin == end && vbegin > vend))
	fputs (_(" (start > end)"), stdout);

      putchar ('\n');

      start += length;
      vbegin = vend = -1;
    }

  if (vbegin != vm1 || vend != vm1)
    printf (_("Trailing view pair not used in a range"));

  *start_ptr = start;
  *vstart_ptr = vstart;
}


display_debug_lines_decoded (struct dwarf_section *  section,
			     unsigned char *         start,
			     unsigned char *         data,
			     unsigned char *         end,
			     void *                  fileptr)
{
  static DWARF2_Internal_LineInfo saved_linfo;

  introduce (section, false);

  while (data < end)
    {
      /* This loop amounts to one iteration per compilation unit.  */
      DWARF2_Internal_LineInfo linfo;
      unsigned char *standard_opcodes;
      unsigned char *end_of_sequence;
      int i;
      File_Entry *file_table = NULL;
      unsigned int n_files = 0;
      unsigned char **directory_table = NULL;
      dwarf_vma n_directories = 0;

      if (startswith (section->name, ".debug_line.")
	  /* Note: the following does not apply to .debug_line.dwo sections.
	     These are full debug_line sections.  */
	  && strcmp (section->name, ".debug_line.dwo") != 0)
	{
	  /* See comment in display_debug_lines_raw().  */
	  end_of_sequence = end;
	  standard_opcodes = NULL;
	  linfo = saved_linfo;
	  /* PR 17531: file: 0522b371.  */
	  if (linfo.li_line_range == 0)
	    {
	      warn (_("Partial .debug_line. section encountered without a prior full .debug_line section\n"));
	      return 0;
	    }
	  reset_state_machine (linfo.li_default_is_stmt);
	}
      else
	{
	  unsigned char *hdrptr;

	  if ((hdrptr = read_debug_line_header (section, data, end, & linfo,
						& end_of_sequence)) == NULL)
	      return 0;

	  /* PR 17531: file: 0522b371.  */
	  if (linfo.li_line_range == 0)
	    {
	      warn (_("Line range of 0 is invalid, using 1 instead\n"));
	      linfo.li_line_range = 1;
	    }
	  reset_state_machine (linfo.li_default_is_stmt);

	  /* Save a pointer to the contents of the Opcodes table.  */
	  standard_opcodes = hdrptr;

	  /* Traverse the Directory table just to count entries.  */
	  data = standard_opcodes + linfo.li_opcode_base - 1;
	  /* PR 20440 */
	  if (data >= end)
	    {
	      warn (_("opcode base of %d extends beyond end of section\n"),
		    linfo.li_opcode_base);
	      return 0;
	    }

	  if (linfo.li_version >= 5)
	    {
	      unsigned char *format_start, format_count, *format;
	      dwarf_vma formati, entryi;

	      load_debug_section_with_follow (line_str, fileptr);

	      /* Skip directories format.  */
	      SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
	      if (do_checks && format_count > 1)
		warn (_("Unexpectedly large number of columns in the directory name table (%u)\n"),
		      format_count);
	      format_start = data;
	      for (formati = 0; formati < format_count; formati++)
		{
		  SKIP_ULEB (data, end);
		  SKIP_ULEB (data, end);
		}

	      READ_ULEB (n_directories, data, end);
	      if (data >= end)
		{
		  warn (_("Corrupt directories list\n"));
		  break;
		}

	      if (n_directories == 0)
		directory_table = NULL;
	      else
		directory_table = (unsigned char **)
		  xmalloc (n_directories * sizeof (unsigned char *));

	      for (entryi = 0; entryi < n_directories; entryi++)
		{
		  unsigned char **pathp = &directory_table[entryi];

		  format = format_start;
		  for (formati = 0; formati < format_count; formati++)
		    {
		      dwarf_vma content_type, form;
		      dwarf_vma uvalue;

		      READ_ULEB (content_type, format, end);
		      READ_ULEB (form, format, end);
		      if (data >= end)
			{
			  warn (_("Corrupt directories list\n"));
			  break;
			}
		      switch (content_type)
			{
			case DW_LNCT_path:
			  switch (form)
			    {
			    case DW_FORM_string:
			      *pathp = data;
			      break;
			    case DW_FORM_line_strp:
			      SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
					     end);
			      /* Remove const by the cast.  */
			      *pathp = (unsigned char *)
				       fetch_indirect_line_string (uvalue);
			      break;
			    }
			  break;
			}
		      data = read_and_display_attr_value (0, form, 0, start,
							  data, end, 0, 0,
							  linfo.li_offset_size,
							  linfo.li_version,
							  NULL, 1, section,
							  NULL, '\t', -1);
		    }
		  if (data >= end)
		    {
		      warn (_("Corrupt directories list\n"));
		      break;
		    }
		}

	      /* Skip files format.  */
	      SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
	      if (do_checks && format_count > 5)
		warn (_("Unexpectedly large number of columns in the file name table (%u)\n"),
		      format_count);
	      format_start = data;
	      for (formati = 0; formati < format_count; formati++)
		{
		  SKIP_ULEB (data, end);
		  SKIP_ULEB (data, end);
		}

	      READ_ULEB (n_files, data, end);
	      if (data >= end && n_files > 0)
		{
		  warn (_("Corrupt file name list\n"));
		  break;
		}

	      if (n_files == 0)
		file_table = NULL;
	      else
		file_table = (File_Entry *) xcalloc (1, n_files
						     * sizeof (File_Entry));

	      for (entryi = 0; entryi < n_files; entryi++)
		{
		  File_Entry *file = &file_table[entryi];

		  format = format_start;
		  for (formati = 0; formati < format_count; formati++)
		    {
		      dwarf_vma content_type, form;
		      dwarf_vma uvalue;
		      unsigned char *tmp;

		      READ_ULEB (content_type, format, end);
		      READ_ULEB (form, format, end);
		      if (data >= end)
			{
			  warn (_("Corrupt file name list\n"));
			  break;
			}
		      switch (content_type)
			{
			case DW_LNCT_path:
			  switch (form)
			    {
			    case DW_FORM_string:
			      file->name = data;
			      break;
			    case DW_FORM_line_strp:
			      SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
					     end);
			      /* Remove const by the cast.  */
			      file->name = (unsigned char *)
					   fetch_indirect_line_string (uvalue);
			      break;
			    }
			  break;
			case DW_LNCT_directory_index:
			  switch (form)
			    {
			    case DW_FORM_data1:
			      SAFE_BYTE_GET (file->directory_index, data, 1,
					     end);
			      break;
			    case DW_FORM_data2:
			      SAFE_BYTE_GET (file->directory_index, data, 2,
					     end);
			      break;
			    case DW_FORM_udata:
			      tmp = data;
			      READ_ULEB (file->directory_index, tmp, end);
			      break;
			    }
			  break;
			}
		      data = read_and_display_attr_value (0, form, 0, start,
							  data, end, 0, 0,
							  linfo.li_offset_size,
							  linfo.li_version,
							  NULL, 1, section,
							  NULL, '\t', -1);
		    }
		  if (data >= end)
		    {
		      warn (_("Corrupt file name list\n"));
		      break;
		    }
		}
	    }
	  else
	    {
	      if (*data != 0)
		{
		  unsigned char *ptr_directory_table = data;

		  while (data < end && *data != 0)
		    {
		      data += strnlen ((char *) data, end - data);
		      if (data < end)
			data++;
		      n_directories++;
		    }

		  /* PR 20440 */
		  if (data >= end)
		    {
		      warn (_("directory table ends unexpectedly\n"));
		      n_directories = 0;
		      break;
		    }

		  /* Go through the directory table again to save the directories.  */
		  directory_table = (unsigned char **)
		    xmalloc (n_directories * sizeof (unsigned char *));

		  i = 0;
		  while (*ptr_directory_table != 0)
		    {
		      directory_table[i] = ptr_directory_table;
		      ptr_directory_table
			+= strlen ((char *) ptr_directory_table) + 1;
		      i++;
		    }
		}
	      /* Skip the NUL at the end of the table.  */
	      data++;

	      /* Traverse the File Name table just to count the entries.  */
	      if (data < end && *data != 0)
		{
		  unsigned char *ptr_file_name_table = data;

		  while (data < end && *data != 0)
		    {
		      /* Skip Name, directory index, last modification
			 time and length of file.  */
		      data += strnlen ((char *) data, end - data);
		      if (data < end)
			data++;
		      SKIP_ULEB (data, end);
		      SKIP_ULEB (data, end);
		      SKIP_ULEB (data, end);
		      n_files++;
		    }

		  if (data >= end)
		    {
		      warn (_("file table ends unexpectedly\n"));
		      n_files = 0;
		      break;
		    }

		  /* Go through the file table again to save the strings.  */
		  file_table = (File_Entry *) xmalloc (n_files * sizeof (File_Entry));

		  i = 0;
		  while (*ptr_file_name_table != 0)
		    {
		      file_table[i].name = ptr_file_name_table;
		      ptr_file_name_table
			+= strlen ((char *) ptr_file_name_table) + 1;

		      /* We are not interested in directory, time or size.  */
		      READ_ULEB (file_table[i].directory_index,
				 ptr_file_name_table, end);
		      READ_ULEB (file_table[i].modification_date,
				 ptr_file_name_table, end);
		      READ_ULEB (file_table[i].length,
				 ptr_file_name_table, end);
		      i++;
		    }
		  i = 0;
		}

	      /* Skip the NUL at the end of the table.  */
	      data++;
	    }

	  /* Print the Compilation Unit's name and a header.  */
	  if (file_table == NULL)
	    printf (_("CU: No directory table\n"));
	  else if (directory_table == NULL)
	    printf (_("CU: %s:\n"), file_table[0].name);
	  else
	    {
	      unsigned int ix = file_table[0].directory_index;
	      const char *directory;

	      if (ix == 0)
		directory = ".";
	      /* PR 20439 */
	      else if (n_directories == 0)
		directory = _("<unknown>");
	      else if (ix > n_directories)
		{
		  warn (_("directory index %u > number of directories %s\n"),
			ix, dwarf_vmatoa ("u", n_directories));
		  directory = _("<corrupt>");
		}
	      else
		directory = (char *) directory_table[ix - 1];

	      if (do_wide)
		printf (_("CU: %s/%s:\n"), directory, file_table[0].name);
	      else
		printf ("%s:\n", file_table[0].name);
	    }

	  if (n_files > 0)
	    printf (_("File name                            Line number    Starting address    View    Stmt\n"));
	  else
	    printf (_("CU: Empty file name table\n"));
	  saved_linfo = linfo;
	}

      /* This loop iterates through the Dwarf Line Number Program.  */
      while (data < end_of_sequence)
	{
	  unsigned char op_code;
	  int xop;
	  int adv;
	  unsigned long int uladv;
	  int is_special_opcode = 0;

	  op_code = *data++;
	  xop = op_code;

	  if (op_code >= linfo.li_opcode_base)
	    {
	      op_code -= linfo.li_opcode_base;
	      uladv = (op_code / linfo.li_line_range);
	      if (linfo.li_max_ops_per_insn == 1)
		{
		  uladv *= linfo.li_min_insn_length;
		  state_machine_regs.address += uladv;
		  if (uladv)
		    state_machine_regs.view = 0;
		}
	      else
		{
		  unsigned addrdelta
		    = ((state_machine_regs.op_index + uladv)
		       / linfo.li_max_ops_per_insn)
		    * linfo.li_min_insn_length;
		  state_machine_regs.address
		    += addrdelta;
		  state_machine_regs.op_index
		    = (state_machine_regs.op_index + uladv)
		    % linfo.li_max_ops_per_insn;
		  if (addrdelta)
		    state_machine_regs.view = 0;
		}

	      adv = (op_code % linfo.li_line_range) + linfo.li_line_base;
	      state_machine_regs.line += adv;
	      is_special_opcode = 1;
	      /* Increment view after printing this row.  */
	    }
	  else
	    switch (op_code)
	      {
	      case DW_LNS_extended_op:
		{
		  unsigned int ext_op_code_len;
		  unsigned char ext_op_code;
		  unsigned char *op_code_end;
		  unsigned char *op_code_data = data;

		  READ_ULEB (ext_op_code_len, op_code_data, end_of_sequence);
		  op_code_end = op_code_data + ext_op_code_len;
		  if (ext_op_code_len == 0 || op_code_end > end_of_sequence)
		    {
		      warn (_("Badly formed extended line op encountered!\n"));
		      break;
		    }
		  ext_op_code = *op_code_data++;
		  xop = ext_op_code;
		  xop = -xop;

		  switch (ext_op_code)
		    {
		    case DW_LNE_end_sequence:
		      /* Reset stuff after printing this row.  */
		      break;
		    case DW_LNE_set_address:
		      SAFE_BYTE_GET_AND_INC (state_machine_regs.address,
					     op_code_data,
					     op_code_end - op_code_data,
					     op_code_end);
		      state_machine_regs.op_index = 0;
		      state_machine_regs.view = 0;
		      break;
		    case DW_LNE_define_file:
		      file_table = (File_Entry *) xrealloc
			(file_table, (n_files + 1) * sizeof (File_Entry));

		      ++state_machine_regs.last_file_entry;
		      /* Source file name.  */
		      file_table[n_files].name = op_code_data;
		      op_code_data += strlen ((char *) op_code_data) + 1;
		      /* Directory index.  */
		      READ_ULEB (file_table[n_files].directory_index,
				 op_code_data, op_code_end);
		      /* Last modification time.  */
		      READ_ULEB (file_table[n_files].modification_date,
				 op_code_data, op_code_end);
		      /* File length.  */
		      READ_ULEB (file_table[n_files].length,
				 op_code_data, op_code_end);
		      n_files++;
		      break;

		    case DW_LNE_set_discriminator:
		    case DW_LNE_HP_set_sequence:
		      /* Simply ignored.  */
		      break;

		    default:
		      printf (_("UNKNOWN (%u): length %ld\n"),
			      ext_op_code, (long int) (op_code_data - data));
		      break;
		    }
		  data = op_code_end;
		  break;
		}
	      case DW_LNS_copy:
		/* Increment view after printing this row.  */
		break;

	      case DW_LNS_advance_pc:
		READ_ULEB (uladv, data, end);
		if (linfo.li_max_ops_per_insn == 1)
		  {
		    uladv *= linfo.li_min_insn_length;
		    state_machine_regs.address += uladv;
		    if (uladv)
		      state_machine_regs.view = 0;
		  }
		else
		  {
		    unsigned addrdelta
		      = ((state_machine_regs.op_index + uladv)
			 / linfo.li_max_ops_per_insn)
		      * linfo.li_min_insn_length;
		    state_machine_regs.address
		      += addrdelta;
		    state_machine_regs.op_index
		      = (state_machine_regs.op_index + uladv)
		      % linfo.li_max_ops_per_insn;
		    if (addrdelta)
		      state_machine_regs.view = 0;
		  }
		break;

	      case DW_LNS_advance_line:
		READ_SLEB (adv, data, end);
		state_machine_regs.line += adv;
		break;

	      case DW_LNS_set_file:
		READ_ULEB (uladv, data, end);
		state_machine_regs.file = uladv;

		{
		  unsigned file = state_machine_regs.file;
		  unsigned dir;

		  if (linfo.li_version < 5)
		    --file;
		  if (file_table == NULL || n_files == 0)
		    printf (_("\n [Use file table entry %d]\n"), file);
		  /* PR 20439 */
		  else if (file >= n_files)
		    {
		      warn (_("file index %u > number of files %u\n"), file, n_files);
		      printf (_("\n <over large file table index %u>"), file);
		    }
		  else if ((dir = file_table[file].directory_index) == 0)
		    /* If directory index is 0, that means current directory.  */
		    printf ("\n./%s:[++]\n", file_table[file].name);
		  else if (directory_table == NULL || n_directories == 0)
		    printf (_("\n [Use file %s in directory table entry %d]\n"),
			    file_table[file].name, dir);
		  /* PR 20439 */
		  else if (dir > n_directories)
		    {
		      warn (_("directory index %u > number of directories %s\n"),
			    dir, dwarf_vmatoa ("u", n_directories));
		      printf (_("\n <over large directory table entry %u>\n"), dir);
		    }
		  else
		    printf ("\n%s/%s:\n",
			    /* The directory index starts counting at 1.  */
			    directory_table[dir - 1], file_table[file].name);
		}
		break;

	      case DW_LNS_set_column:
		READ_ULEB (uladv, data, end);
		state_machine_regs.column = uladv;
		break;

	      case DW_LNS_negate_stmt:
		adv = state_machine_regs.is_stmt;
		adv = ! adv;
		state_machine_regs.is_stmt = adv;
		break;

	      case DW_LNS_set_basic_block:
		state_machine_regs.basic_block = 1;
		break;

	      case DW_LNS_const_add_pc:
		uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
		if (linfo.li_max_ops_per_insn == 1)
		  {
		    uladv *= linfo.li_min_insn_length;
		    state_machine_regs.address += uladv;
		    if (uladv)
		      state_machine_regs.view = 0;
		  }
		else
		  {
		    unsigned addrdelta
		      = ((state_machine_regs.op_index + uladv)
			 / linfo.li_max_ops_per_insn)
		      * linfo.li_min_insn_length;
		    state_machine_regs.address
		      += addrdelta;
		    state_machine_regs.op_index
		      = (state_machine_regs.op_index + uladv)
		      % linfo.li_max_ops_per_insn;
		    if (addrdelta)
		      state_machine_regs.view = 0;
		  }
		break;

	      case DW_LNS_fixed_advance_pc:
		SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
		state_machine_regs.address += uladv;
		state_machine_regs.op_index = 0;
		/* Do NOT reset view.  */
		break;

	      case DW_LNS_set_prologue_end:
		break;

	      case DW_LNS_set_epilogue_begin:
		break;

	      case DW_LNS_set_isa:
		READ_ULEB (uladv, data, end);
		printf (_("  Set ISA to %lu\n"), uladv);
		break;

	      default:
		printf (_("  Unknown opcode %d with operands: "), op_code);

		if (standard_opcodes != NULL)
		  for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
		    {
		      dwarf_vma val;

		      READ_ULEB (val, data, end);
		      printf ("0x%s%s", dwarf_vmatoa ("x", val),
			      i == 1 ? "" : ", ");
		    }
		putchar ('\n');
		break;
	      }

	  /* Only Special opcodes, DW_LNS_copy and DW_LNE_end_sequence adds a row
	     to the DWARF address/line matrix.  */
	  if ((is_special_opcode) || (xop == -DW_LNE_end_sequence)
	      || (xop == DW_LNS_copy))
	    {
	      const unsigned int MAX_FILENAME_LENGTH = 35;
	      char *fileName;
	      char *newFileName = NULL;
	      size_t fileNameLength;

	      if (file_table)
		{
		  unsigned indx = state_machine_regs.file;

		  if (linfo.li_version < 5)
		    --indx;
		  /* PR 20439  */
		  if (indx >= n_files)
		    {
		      warn (_("corrupt file index %u encountered\n"), indx);
		      fileName = _("<corrupt>");
		    }
		  else
		    fileName = (char *) file_table[indx].name;
		}
	      else
		fileName = _("<unknown>");

	      fileNameLength = strlen (fileName);
	      newFileName = fileName;
	      if (fileNameLength > MAX_FILENAME_LENGTH && !do_wide)
		{
		  newFileName = (char *) xmalloc (MAX_FILENAME_LENGTH + 1);
		  /* Truncate file name */
		  memcpy (newFileName,
			  fileName + fileNameLength - MAX_FILENAME_LENGTH,
			  MAX_FILENAME_LENGTH);
		  newFileName[MAX_FILENAME_LENGTH] = 0;
		}

	      /* A row with end_seq set to true has a meaningful address, but
		 the other information in the same row is not significant.
		 In such a row, print line as "-", and don't print
		 view/is_stmt.  */
	      if (!do_wide || fileNameLength <= MAX_FILENAME_LENGTH)
		{
		  if (linfo.li_max_ops_per_insn == 1)
		    {
		      if (xop == -DW_LNE_end_sequence)
			printf ("%-35s  %11s  %#18" DWARF_VMA_FMT "x",
				newFileName, "-",
				state_machine_regs.address);
		      else
			printf ("%-35s  %11d  %#18" DWARF_VMA_FMT "x",
				newFileName, state_machine_regs.line,
				state_machine_regs.address);
		    }
		  else
		    {
		      if (xop == -DW_LNE_end_sequence)
			printf ("%-35s  %11s  %#18" DWARF_VMA_FMT "x[%d]",
				newFileName, "-",
				state_machine_regs.address,
				state_machine_regs.op_index);
		      else
			printf ("%-35s  %11d  %#18" DWARF_VMA_FMT "x[%d]",
				newFileName, state_machine_regs.line,
				state_machine_regs.address,
				state_machine_regs.op_index);
		    }
		}
	      else
		{
		  if (linfo.li_max_ops_per_insn == 1)
		    {
		      if (xop == -DW_LNE_end_sequence)
			printf ("%s  %11s  %#18" DWARF_VMA_FMT "x",
				newFileName, "-",
				state_machine_regs.address);
		      else
			printf ("%s  %11d  %#18" DWARF_VMA_FMT "x",
				newFileName, state_machine_regs.line,
				state_machine_regs.address);
		    }
		  else
		    {
		      if (xop == -DW_LNE_end_sequence)
			printf ("%s  %11s  %#18" DWARF_VMA_FMT "x[%d]",
				newFileName, "-",
				state_machine_regs.address,
				state_machine_regs.op_index);
		      else
			printf ("%s  %11d  %#18" DWARF_VMA_FMT "x[%d]",
				newFileName, state_machine_regs.line,
				state_machine_regs.address,
				state_machine_regs.op_index);
		    }
		}

	      if (xop != -DW_LNE_end_sequence)
		{
		  if (state_machine_regs.view)
		    printf ("  %6u", state_machine_regs.view);
		  else
		    printf ("        ");

		  if (state_machine_regs.is_stmt)
		    printf ("       x");
		}

	      putchar ('\n');
	      state_machine_regs.view++;

	      if (xop == -DW_LNE_end_sequence)
		{
		  reset_state_machine (linfo.li_default_is_stmt);
		  putchar ('\n');
		}

	      if (newFileName != fileName)
		free (newFileName);
	    }
	}

      if (file_table)
	{
	  free (file_table);
	  file_table = NULL;
	  n_files = 0;
	}

      if (directory_table)
	{
	  free (directory_table);
	  directory_table = NULL;
	  n_directories = 0;
	}

      putchar ('\n');
    }

  return 1;
}


display_debug_sup (struct dwarf_section *  section,
		   void *                  file ATTRIBUTE_UNUSED)
{
  unsigned char * start = section->start;
  unsigned char * end = section->start + section->size;
  unsigned int version;
  char is_supplementary;
  const unsigned char * sup_filename;
  size_t sup_filename_len;
  unsigned int num_read;
  int status;
  dwarf_vma checksum_len;

  introduce (section, true);
  if (section->size < 4)
    {
      error (_("corrupt .debug_sup section: size is too small\n"));
      return 0;
    }

  /* Read the data.  */
  SAFE_BYTE_GET_AND_INC (version, start, 2, end);
  if (version < 5)
    warn (_("corrupt .debug_sup section: version < 5"));

  SAFE_BYTE_GET_AND_INC (is_supplementary, start, 1, end);
  if (is_supplementary != 0 && is_supplementary != 1)
    warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n"));

  sup_filename = start;
  if (is_supplementary && sup_filename[0] != 0)
    warn (_("corrupt .debug_sup section: filename not empty in supplementary section\n"));

  sup_filename_len = strnlen ((const char *) start, end - start);
  if (sup_filename_len == (size_t) (end - start))
    {
      error (_("corrupt .debug_sup section: filename is not NUL terminated\n"));
      return 0;
    }
  start += sup_filename_len + 1;

  checksum_len = read_leb128 (start, end, false /* unsigned */, & num_read, & status);
  if (status)
    {
      error (_("corrupt .debug_sup section: bad LEB128 field for checksum length\n"));
      checksum_len = 0;
    }
  start += num_read;
  if (checksum_len > (dwarf_vma) (end - start))
    {
      error (_("corrupt .debug_sup section: checksum length is longer than the remaining section length\n"));
      checksum_len = end - start;
    }
  else if (checksum_len < (dwarf_vma) (end - start))
    {
      warn (_("corrupt .debug_sup section: there are 0x%lx extra, unused bytes at the end of the section\n"),
	    (long) ((end - start) - checksum_len));
    }

  printf (_("  Version:      %u\n"), version);
  printf (_("  Is Supp:      %u\n"), is_supplementary);
  printf (_("  Filename:     %s\n"), sup_filename);
  printf (_("  Checksum Len: %lu\n"), (long) checksum_len);
  if (checksum_len > 0)
    {
      printf (_("  Checksum:     "));
      while (checksum_len--)
	printf ("0x%x ", * start++ );
      printf ("\n");
    }
  return 1;
}


display_debug_str_offsets (struct dwarf_section *section,
			   void *file ATTRIBUTE_UNUSED)
{
  unsigned long idx;

  if (section->size == 0)
    {
      printf (_("\nThe %s section is empty.\n"), section->name);
      return 0;
    }

  unsigned char *start = section->start;
  unsigned char *end = start + section->size;
  unsigned char *curr = start;

  const char *suffix = strrchr (section->name, '.');
  bool dwo = suffix && strcmp (suffix, ".dwo") == 0;

  if (dwo)
    load_debug_section_with_follow (str_dwo, file);
  else
    load_debug_section_with_follow (str, file);

  introduce (section, false);

  while (curr < end)
    {
      dwarf_vma length;
      dwarf_vma entry_length;

      SAFE_BYTE_GET_AND_INC (length, curr, 4, end);
      /* FIXME: We assume that this means 64-bit DWARF is being used.  */
      if (length == 0xffffffff)
	{
	  SAFE_BYTE_GET_AND_INC (length, curr, 8, end);
	  entry_length = 8;
	}
      else
	entry_length = 4;

      unsigned char *entries_end;
      if (length == 0)
	{
	  /* This is probably an old style .debug_str_offset section which
	     just contains offsets and no header (and the first offset is 0).  */
	  length = section->size;
	  curr   = section->start;
	  entries_end = end;

	  printf (_("    Length: %#lx\n"), (unsigned long) length);
	  printf (_("       Index   Offset [String]\n"));
	}
      else
	{
	  if (length <= (dwarf_vma) (end - curr))
	    entries_end = curr + length;
	  else
	    {
	      warn (_("Section %s is too small %#lx\n"),
		    section->name, (unsigned long) section->size);
	      entries_end = end;
	    }

	  int version;
	  SAFE_BYTE_GET_AND_INC (version, curr, 2, entries_end);
	  if (version != 5)
	    warn (_("Unexpected version number in str_offset header: %#x\n"), version);

	  int padding;
	  SAFE_BYTE_GET_AND_INC (padding, curr, 2, entries_end);
	  if (padding != 0)
	    warn (_("Unexpected value in str_offset header's padding field: %#x\n"), padding);

	  printf (_("    Length: %#lx\n"), (unsigned long) length);
	  printf (_("    Version: %#lx\n"), (unsigned long) version);
	  printf (_("       Index   Offset [String]\n"));
	}

      for (idx = 0; curr < entries_end; idx++)
	{
	  dwarf_vma offset;
	  const unsigned char * string;

	  if ((dwarf_vma) (entries_end - curr) < entry_length)
	    /* Not enough space to read one entry_length, give up.  */
	    return 0;

	  SAFE_BYTE_GET_AND_INC (offset, curr, entry_length, entries_end);
	  if (dwo)
	    string = (const unsigned char *)
	      fetch_indexed_string (idx, NULL, entry_length, dwo, 0);
	  else
	    string = fetch_indirect_string (offset);

	  printf ("    %8lu %8s %s\n", idx, dwarf_vmatoa ("x", offset),
		  string);
	}
    }

  return 1;
}


parse_gnu_debuglink (struct dwarf_section * section, void * data)
{
  const char *     name;
  unsigned int     crc_offset;
  unsigned long *  crc32 = (unsigned long *) data;

  /* The name is first.
     The CRC value is stored after the filename, aligned up to 4 bytes.  */
  name = (const char *) section->start;

  crc_offset = strnlen (name, section->size) + 1;
  if (crc_offset == 1)
    return NULL;
  crc_offset = (crc_offset + 3) & ~3;
  if (crc_offset + 4 > section->size)
    return NULL;

  * crc32 = byte_get (section->start + crc_offset, 4);
  return name;
}


display_debug_info (struct dwarf_section *section, void *file)
{
  return process_debug_info (section, file, section->abbrev_sec, false, false);
}


free_debug_memory (void)
{
  unsigned int i;

  free_all_abbrevs ();

  free (cu_abbrev_map);
  cu_abbrev_map = NULL;
  next_free_abbrev_map_entry = 0;

  free (shndx_pool);
  shndx_pool = NULL;
  shndx_pool_size = 0;
  shndx_pool_used = 0;
  free (cu_sets);
  cu_sets = NULL;
  cu_count = 0;
  free (tu_sets);
  tu_sets = NULL;
  tu_count = 0;

  memset (level_type_signed, 0, sizeof level_type_signed);
  cu_tu_indexes_read = -1;

  for (i = 0; i < max; i++)
    free_debug_section ((enum dwarf_section_display_enum) i);

  if (debug_information != NULL)
    {
      for (i = 0; i < alloc_num_debug_info_entries; i++)
	{
	  if (debug_information [i].max_loc_offsets)
	    {
	      free (debug_information [i].loc_offsets);
	      free (debug_information [i].have_frame_base);
	    }
	  if (debug_information [i].max_range_lists)
	    free (debug_information [i].range_lists);
	}
      free (debug_information);
      debug_information = NULL;
      alloc_num_debug_info_entries = num_debug_info_entries = 0;
    }

  separate_info * d;
  separate_info * next;

  for (d = first_separate_info; d != NULL; d = next)
    {
      close_debug_file (d->handle);
      free ((void *) d->filename);
      next = d->next;
      free ((void *) d);
    }
  first_separate_info = NULL;

  free_dwo_info ();
}