/* DWARF 2 low-level section code

   Copyright (C) 1994-2025 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 "dwarf2/section.h"
#include "gdb_bfd.h"
#include "objfiles.h"
#include "complaints.h"
#include "dwarf2/error.h"

void
dwarf2_section_info::overflow_complaint () const
{
  complaint (_("debug info runs off end of %s section"
	       " [in module %s]"),
	     get_name (), get_file_name ());
}

struct dwarf2_section_info *
dwarf2_section_info::get_containing_section () const
{
  gdb_assert (is_virtual);
  return s.containing_section;
}

struct bfd *
dwarf2_section_info::get_bfd_owner () const
{
  const dwarf2_section_info *section = this;
  if (is_virtual)
    {
      section = get_containing_section ();
      gdb_assert (!section->is_virtual);
    }
  gdb_assert (section->s.section != nullptr);
  return section->s.section->owner;
}

asection *
dwarf2_section_info::get_bfd_section () const
{
  const dwarf2_section_info *section = this;
  if (section->is_virtual)
    {
      section = get_containing_section ();
      gdb_assert (!section->is_virtual);
    }
  return section->s.section;
}

const char *
dwarf2_section_info::get_name () const
{
  asection *sectp = get_bfd_section ();

  gdb_assert (sectp != NULL);
  return bfd_section_name (sectp);
}

const char *
dwarf2_section_info::get_file_name () const
{
  bfd *abfd = get_bfd_owner ();

  gdb_assert (abfd != nullptr);
  return bfd_get_filename (abfd);
}

int
dwarf2_section_info::get_id () const
{
  asection *sectp = get_bfd_section ();

  if (sectp == NULL)
    return 0;
  return sectp->id;
}

int
dwarf2_section_info::get_flags () const
{
  asection *sectp = get_bfd_section ();

  gdb_assert (sectp != NULL);
  return bfd_section_flags (sectp);
}

bool
dwarf2_section_info::empty () const
{
  if (is_virtual)
    return size == 0;
  return s.section == NULL || size == 0;
}

void
dwarf2_section_info::read (struct objfile *objfile)
{
  asection *sectp;
  bfd *abfd;
  gdb_byte *buf, *retbuf;

  if (readin)
    return;
  buffer = NULL;
  readin = true;

  if (empty ())
    return;

  sectp = get_bfd_section ();

  /* If this is a virtual section we need to read in the real one first.  */
  if (is_virtual)
    {
      struct dwarf2_section_info *containing_section =
	get_containing_section ();

      gdb_assert (sectp != NULL);
      if ((sectp->flags & SEC_RELOC) != 0)
	{
	  error (_(DWARF_ERROR_PREFIX
		   "DWP format V2 with relocations is not supported"
		   " in section %s [in module %s]"),
		 get_name (), get_file_name ());
	}
      containing_section->read (objfile);
      /* Other code should have already caught virtual sections that don't
	 fit.  */
      gdb_assert (virtual_offset + size <= containing_section->size);
      /* If the real section is empty or there was a problem reading the
	 section we shouldn't get here.  */
      gdb_assert (containing_section->buffer != NULL);
      buffer = containing_section->buffer + virtual_offset;
      return;
    }

  /* If the section has relocations, we must read it ourselves.
     Otherwise we attach it to the BFD.  */
  if ((sectp->flags & SEC_RELOC) == 0)
    {
      buffer = gdb_bfd_map_section (sectp, &size);
      return;
    }

  buf = (gdb_byte *) obstack_alloc (&objfile->objfile_obstack, size);
  buffer = buf;

  /* When debugging .o files, we may need to apply relocations; see
     http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html .
     We never compress sections in .o files, so we only need to
     try this when the section is not compressed.  */
  retbuf = symfile_relocate_debug_section (objfile, sectp, buf);
  if (retbuf != NULL)
    {
      buffer = retbuf;
      return;
    }

  abfd = get_bfd_owner ();
  gdb_assert (abfd != NULL);

  if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
      || bfd_read (buf, size, abfd) != size)
    {
      error (_(DWARF_ERROR_PREFIX
	       "Can't read DWARF data in section %s [in module %s]"),
	     bfd_section_name (sectp), bfd_get_filename (abfd));
    }
}

const char *
dwarf2_section_info::read_string (struct objfile *objfile, LONGEST str_offset,
				  const char *form_name)
{
  read (objfile);
  if (buffer == NULL)
    {
      if (get_bfd_section () == nullptr)
	error (_(DWARF_ERROR_PREFIX
		 "%s used without required section"),
	       form_name);
      else
	error (_(DWARF_ERROR_PREFIX
		 "%s used without %s section [in module %s]"),
	       form_name, get_name (), get_file_name ());
    }
  if (str_offset >= size)
    error (_("%s pointing outside of %s section [in module %s]"),
	   form_name, get_name (), get_file_name ());
  gdb_assert (HOST_CHAR_BIT == 8);
  if (buffer[str_offset] == '\0')
    return NULL;
  return (const char *) (buffer + str_offset);
}
