/* Main simulator entry points specific to the eBPF.
   Copyright (C) 2020-2022 Free Software Foundation, Inc.

   This file is part of GDB, the GNU debugger.

   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/>.  */

/* This must come before any other includes.  */
#include "defs.h"

#include <stdlib.h>

#include "sim/callback.h"
#include "sim-main.h"
#include "sim-options.h"
#include "libiberty.h"
#include "bfd.h"

/* Globals.  */

/* String with the name of the section containing the BPF program to
   run.  */
static char *bpf_program_section = NULL;

extern uint64_t skb_data_offset;


/* Handle BPF-specific options.  */

static SIM_RC bpf_option_handler (SIM_DESC, sim_cpu *, int, char *, int);

typedef enum
{
 OPTION_BPF_SET_PROGRAM = OPTION_START,
 OPTION_BPF_LIST_PROGRAMS,
 OPTION_BPF_VERIFY_PROGRAM,
 OPTION_BPF_SKB_DATA_OFFSET,
} BPF_OPTION;

static const OPTION bpf_options[] =
{
 { {"bpf-set-program", required_argument, NULL, OPTION_BPF_SET_PROGRAM},
   '\0', "SECTION_NAME", "Set the entry point",
   bpf_option_handler },
 { {"bpf-list-programs", no_argument, NULL, OPTION_BPF_LIST_PROGRAMS},
   '\0', "", "List loaded bpf programs",
   bpf_option_handler },
 { {"bpf-verify-program", required_argument, NULL, OPTION_BPF_VERIFY_PROGRAM},
   '\0', "PROGRAM", "Run the verifier on the given BPF program",
   bpf_option_handler },
 { {"skb-data-offset", required_argument, NULL, OPTION_BPF_SKB_DATA_OFFSET},
   '\0', "OFFSET", "Configure offsetof(struct sk_buff, data)",
   bpf_option_handler },

 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
};

static SIM_RC
bpf_option_handler (SIM_DESC sd, sim_cpu *cpu ATTRIBUTE_UNUSED, int opt,
                    char *arg, int is_command ATTRIBUTE_UNUSED)
{
  switch ((BPF_OPTION) opt)
    {
    case OPTION_BPF_VERIFY_PROGRAM:
      /* XXX call the verifier. */
      sim_io_printf (sd, "Verifying BPF program %s...\n", arg);
      break;

    case OPTION_BPF_LIST_PROGRAMS:
      /* XXX list programs.  */
      sim_io_printf (sd, "BPF programs available:\n");
      break;

    case OPTION_BPF_SET_PROGRAM:
      /* XXX: check that the section exists and tell the user about a
         new start_address.  */
      bpf_program_section = xstrdup (arg);
      break;

    case OPTION_BPF_SKB_DATA_OFFSET:
      skb_data_offset = strtoul (arg, NULL, 0);
      break;

    default:
      sim_io_eprintf (sd, "Unknown option `%s'\n", arg);
      return SIM_RC_FAIL;
    }

  return SIM_RC_OK;
}

/* Like sim_state_free, but free the cpu buffers as well.  */

static void
bpf_free_state (SIM_DESC sd)
{
  if (STATE_MODULES (sd) != NULL)
    sim_module_uninstall (sd);

  sim_cpu_free_all (sd);
  sim_state_free (sd);
}

extern const SIM_MACH * const bpf_sim_machs[];

/* Create an instance of the simulator.  */

SIM_DESC
sim_open (SIM_OPEN_KIND kind,
          host_callback *callback,
          struct bfd *abfd,
	  char * const *argv)
{
  /* XXX Analyze the program, and collect per-function information
     like the kernel verifier does.  The implementation of the CALL
     instruction will need that information, to update %fp.  */

  SIM_DESC sd = sim_state_alloc (kind, callback);

  /* Set default options before parsing user options.  */
  STATE_MACHS (sd) = bpf_sim_machs;
  STATE_MODEL_NAME (sd) = "bpf-def";

  if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
    goto error;

  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
    goto error;

  /* Add the BPF-specific option list to the simulator.  */
  if (sim_add_option_table (sd, NULL, bpf_options) != SIM_RC_OK)
    {
      bpf_free_state (sd);
      return 0;
    }

  if (sim_parse_args (sd, argv) != SIM_RC_OK)
    goto error;

  if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
    goto error;

  if (sim_config (sd) != SIM_RC_OK)
    goto error;

  if (sim_post_argv_init (sd) != SIM_RC_OK)
    goto error;

  /* ... */

  /* Initialize the CPU descriptors and the disassemble in the cpu
     descriptor table entries.  */
  {
    int i;
    CGEN_CPU_DESC cd = bpf_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name,
                                            CGEN_ENDIAN_LITTLE);

    /* We have one cpu per installed program! MAX_NR_PROCESSORS is an
       arbitrary upper limit.  XXX where is it defined?  */
    for (i = 0; i < MAX_NR_PROCESSORS; ++i)
      {
        SIM_CPU *cpu = STATE_CPU (sd, i);

        CPU_CPU_DESC (cpu) = cd;
        CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn;
      }

    bpf_cgen_init_dis (cd);
  }

  /* XXX do eBPF sim specific initializations.  */

  return sd;

 error:
      bpf_free_state (sd);
      return NULL;
}


SIM_RC
sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
		     char *const *argv, char *const *env)
{
  SIM_CPU *current_cpu = STATE_CPU (sd, 0);
  host_callback *cb = STATE_CALLBACK (sd);
  SIM_ADDR addr;

  /* Determine the start address.

     XXX acknowledge bpf_program_section.  If it is NULL, emit a
     warning explaining that we are using the ELF file start address,
     which often is not what is actually wanted.  */
  if (abfd != NULL)
    addr = bfd_get_start_address (abfd);
  else
    addr = 0;

  sim_pc_set (current_cpu, addr);

  if (STATE_PROG_ARGV (sd) != argv)
    {
      freeargv (STATE_PROG_ARGV (sd));
      STATE_PROG_ARGV (sd) = dupargv (argv);
    }

  if (STATE_PROG_ENVP (sd) != env)
    {
      freeargv (STATE_PROG_ENVP (sd));
      STATE_PROG_ENVP (sd) = dupargv (env);
    }

  cb->argv = STATE_PROG_ARGV (sd);
  cb->envp = STATE_PROG_ENVP (sd);

  return SIM_RC_OK;
}
