/* DWARF 2 abbreviations

   Copyright (C) 1994-2021 Free Software Foundation, Inc.

   Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
   Inc.  with support from Florida State University (under contract
   with the Ada Joint Program Office), and Silicon Graphics, Inc.
   Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
   based on Fred Fish's (Cygnus Support) implementation of DWARF 1
   support.

   This file is part of GDB.

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

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

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

#include "defs.h"
#include "dwarf2/read.h"
#include "dwarf2/abbrev.h"
#include "dwarf2/leb.h"
#include "bfd.h"

/* Hash function for an abbrev.  */

static hashval_t
hash_abbrev (const void *item)
{
  const struct abbrev_info *info = (const struct abbrev_info *) item;
  /* Warning: if you change this next line, you must also update the
     other code in this class using the _with_hash functions.  */
  return info->number;
}

/* Comparison function for abbrevs.  */

static int
eq_abbrev (const void *lhs, const void *rhs)
{
  const struct abbrev_info *l_info = (const struct abbrev_info *) lhs;
  const struct abbrev_info *r_info = (const struct abbrev_info *) rhs;
  return l_info->number == r_info->number;
}

/* Abbreviation tables.

   In DWARF version 2, the description of the debugging information is
   stored in a separate .debug_abbrev section.  Before we read any
   dies from a section we read in all abbreviations and install them
   in a hash table.  */

abbrev_table::abbrev_table (sect_offset off)
  : sect_off (off),
    m_abbrevs (htab_create_alloc (20, hash_abbrev, eq_abbrev,
				  nullptr, xcalloc, xfree))
{
}

/* Add an abbreviation to the table.  */

void
abbrev_table::add_abbrev (struct abbrev_info *abbrev)
{
  void **slot = htab_find_slot_with_hash (m_abbrevs.get (), abbrev,
					  abbrev->number, INSERT);
  *slot = abbrev;
}

/* Read in an abbrev table.  */

abbrev_table_up
abbrev_table::read (struct dwarf2_section_info *section,
		    sect_offset sect_off)
{
  bfd *abfd = section->get_bfd_owner ();
  const gdb_byte *abbrev_ptr;
  struct abbrev_info *cur_abbrev;

  abbrev_table_up abbrev_table (new struct abbrev_table (sect_off));
  struct obstack *obstack = &abbrev_table->m_abbrev_obstack;

  /* Caller must ensure this.  */
  gdb_assert (section->readin);
  abbrev_ptr = section->buffer + to_underlying (sect_off);

  while (true)
    {
      unsigned int bytes_read;
      /* Loop until we reach an abbrev number of 0.  */
      unsigned int abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr,
							 &bytes_read);
      if (abbrev_number == 0)
	break;
      abbrev_ptr += bytes_read;

      /* Start without any attrs.  */
      obstack_blank (obstack, offsetof (abbrev_info, attrs));
      cur_abbrev = (struct abbrev_info *) obstack_base (obstack);

      /* Read in abbrev header.  */
      cur_abbrev->number = abbrev_number;
      cur_abbrev->tag
	= (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr,
						 &bytes_read);
      abbrev_ptr += bytes_read;
      cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
      abbrev_ptr += 1;

      /* Now read in declarations.  */
      int num_attrs = 0;
      for (;;)
	{
	  struct attr_abbrev cur_attr;

	  cur_attr.name
	    = (enum dwarf_attribute) read_unsigned_leb128 (abfd, abbrev_ptr,
							   &bytes_read);
	  abbrev_ptr += bytes_read;
	  cur_attr.form
	    = (enum dwarf_form) read_unsigned_leb128 (abfd, abbrev_ptr,
						      &bytes_read);
	  abbrev_ptr += bytes_read;
	  if (cur_attr.form == DW_FORM_implicit_const)
	    {
	      cur_attr.implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
							    &bytes_read);
	      abbrev_ptr += bytes_read;
	    }
	  else
	    cur_attr.implicit_const = -1;

	  if (cur_attr.name == 0)
	    break;

	  ++num_attrs;
	  obstack_grow (obstack, &cur_attr, sizeof (cur_attr));
	}

      cur_abbrev = (struct abbrev_info *) obstack_finish (obstack);
      cur_abbrev->num_attrs = num_attrs;
      abbrev_table->add_abbrev (cur_abbrev);
    }

  return abbrev_table;
}
