/* Target-dependent code for SDE on MIPS processors.

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

   This file is part of GDB.

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

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

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

#include "osabi.h"
#include "elf-bfd.h"
#include "symtab.h"

#include "frame.h"
#include "frame-unwind.h"
#include "frame-base.h"
#include "trad-frame.h"

#include "mips-tdep.h"

/* Fill in the register cache *THIS_CACHE for THIS_FRAME for use
   in the SDE frame unwinder.  */

static struct trad_frame_cache *
mips_sde_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  const struct mips_regnum *regs = mips_regnum (gdbarch);
  const int sizeof_reg_t = mips_abi_regsize (gdbarch);
  enum mips_abi abi = mips_abi (gdbarch);
  struct trad_frame_cache *cache;
  CORE_ADDR xcpt_frame;
  CORE_ADDR start_addr;
  CORE_ADDR stack_addr;
  CORE_ADDR pc;
  int i;

  if (*this_cache != NULL)
    return (struct trad_frame_cache *) *this_cache;
  cache = trad_frame_cache_zalloc (this_frame);
  *this_cache = cache;

  /* The previous registers are held in struct xcptcontext
     which is at $sp+offs

     struct xcptcontext {
       reg_t	sr;		CP0 Status
       reg_t	cr;		CP0 Cause
       reg_t	epc;		CP0 EPC
       reg_t	vaddr;		CP0 BadVAddr
       reg_t	regs[32];	General registers
       reg_t	mdlo;		LO
       reg_t	mdhi;		HI
       reg_t	mdex;		ACX
       ...
     };
  */

  stack_addr = get_frame_register_signed (this_frame,
					  gdbarch_sp_regnum (gdbarch));
  switch (abi)
    {
    case MIPS_ABI_O32:
      /* 40: XCPTCONTEXT
	 24: xcpt_gen() argspace		(16 bytes)
	 16: _xcptcall() saved ra, rounded up	( 8 bytes)
	 00: _xcptcall() argspace 		(16 bytes)  */
      xcpt_frame = stack_addr + 40;
      break;
    case MIPS_ABI_N32:
    case MIPS_ABI_N64:
    default:			/* Wild guess.  */
      /* 16: XCPTCONTEXT
	 16: xcpt_gen() argspace 		( 0 bytes)
	 00: _xcptcall() saved ra, rounded up	(16 bytes)  */
      xcpt_frame = stack_addr + 16;
      break;
    }

  trad_frame_set_reg_addr (cache,
			   MIPS_PS_REGNUM + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 0 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->cause + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 1 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->pc + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 2 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->badvaddr + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 3 * sizeof_reg_t);
  for (i = 0; i < MIPS_NUMREGS; i++)
    trad_frame_set_reg_addr (cache,
			     i + MIPS_ZERO_REGNUM + gdbarch_num_regs (gdbarch),
			     xcpt_frame + (4 + i) * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->lo + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 36 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->hi + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 37 * sizeof_reg_t);

  pc = get_frame_pc (this_frame);
  find_pc_partial_function (pc, NULL, &start_addr, NULL);
  trad_frame_set_id (cache, frame_id_build (start_addr, stack_addr));

  return cache;
}

/* Implement the this_id function for the SDE frame unwinder.  */

static void
mips_sde_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
			struct frame_id *this_id)
{
  struct trad_frame_cache *this_trad_cache
    = mips_sde_frame_cache (this_frame, this_cache);

  trad_frame_get_id (this_trad_cache, this_id);
}

/* Implement the prev_register function for the SDE frame unwinder.  */

static struct value *
mips_sde_frame_prev_register (const frame_info_ptr &this_frame,
			      void **this_cache,
			      int prev_regnum)
{
  struct trad_frame_cache *trad_cache
    = mips_sde_frame_cache (this_frame, this_cache);

  return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
}

/* Implement the sniffer function for the SDE frame unwinder.  */

static int
mips_sde_frame_sniffer (const struct frame_unwind *self,
			const frame_info_ptr &this_frame,
			void **this_cache)
{
  CORE_ADDR pc = get_frame_pc (this_frame);
  const char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  return (name
	  && (strcmp (name, "_xcptcall") == 0
	      || strcmp (name, "_sigtramp") == 0));
}

/* Data structure for the SDE frame unwinder.  */

static const struct frame_unwind_legacy mips_sde_frame_unwind (
  "mips sde sigtramp",
  SIGTRAMP_FRAME,
  FRAME_UNWIND_ARCH,
  default_frame_unwind_stop_reason,
  mips_sde_frame_this_id,
  mips_sde_frame_prev_register,
  NULL,
  mips_sde_frame_sniffer
);

/* Implement the this_base, this_locals, and this_args hooks
   for the normal unwinder.  */

static CORE_ADDR
mips_sde_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
{
  struct trad_frame_cache *this_trad_cache
    = mips_sde_frame_cache (this_frame, this_cache);

  return trad_frame_get_this_base (this_trad_cache);
}

static const struct frame_base mips_sde_frame_base =
{
  &mips_sde_frame_unwind,
  mips_sde_frame_base_address,
  mips_sde_frame_base_address,
  mips_sde_frame_base_address
};

static const struct frame_base *
mips_sde_frame_base_sniffer (const frame_info_ptr &this_frame)
{
  if (mips_sde_frame_sniffer (&mips_sde_frame_unwind, this_frame, NULL))
    return &mips_sde_frame_base;
  else
    return NULL;
}

static void
mips_sde_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect,
					   void *obj)
{
  enum gdb_osabi *os_ident_ptr = (enum gdb_osabi *) obj;
  const char *name;

  name = bfd_section_name (sect);

  /* The presence of a section with a ".sde" prefix is indicative
     of an SDE binary.  */
  if (startswith (name, ".sde"))
    *os_ident_ptr = GDB_OSABI_SDE;
}

/* OSABI sniffer for MIPS SDE.  */

static enum gdb_osabi
mips_sde_elf_osabi_sniffer (bfd *abfd)
{
  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
  unsigned int elfosabi;

  /* If the generic sniffer gets a hit, return and let other sniffers
     get a crack at it.  */
  for (asection *sect : gdb_bfd_sections (abfd))
    generic_elf_osabi_sniff_abi_tag_sections (abfd, sect, &osabi);
  if (osabi != GDB_OSABI_UNKNOWN)
    return GDB_OSABI_UNKNOWN;

  elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];

  if (elfosabi == ELFOSABI_NONE)
    {
      /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the
	 file are conforming to the base specification for that machine
	 (there are no OS-specific extensions).  In order to determine the
	 real OS in use we must look for OS notes that have been added.

	 For SDE, we simply look for sections named with .sde as prefixes.  */
      bfd_map_over_sections (abfd,
			     mips_sde_elf_osabi_sniff_abi_tag_sections,
			     &osabi);
    }
  return osabi;
}

static void
mips_sde_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  frame_unwind_append_unwinder (gdbarch, &mips_sde_frame_unwind);
  frame_base_append_sniffer (gdbarch, mips_sde_frame_base_sniffer);
}

void _initialize_mips_sde_tdep ();
void
_initialize_mips_sde_tdep ()
{
  gdbarch_register_osabi_sniffer (bfd_arch_mips,
				  bfd_target_elf_flavour,
				  mips_sde_elf_osabi_sniffer);

  gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_SDE, mips_sde_init_abi);
}
