/* Everything about exec catchpoints, for GDB.

   Copyright (C) 1986-2022 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 "defs.h"

#include "annotate.h"
#include "arch-utils.h"
#include "breakpoint.h"
#include "cli/cli-decode.h"
#include "inferior.h"
#include "mi/mi-common.h"
#include "target.h"
#include "valprint.h"

/* Exec catchpoints.  */

/* An instance of this type is used to represent an exec catchpoint.
   A breakpoint is really of this type iff its ops pointer points to
   CATCH_EXEC_BREAKPOINT_OPS.  */

struct exec_catchpoint : public breakpoint
{
  int insert_location (struct bp_location *) override;
  int remove_location (struct bp_location *,
		       enum remove_bp_reason reason) override;
  int breakpoint_hit (const struct bp_location *bl,
		      const address_space *aspace,
		      CORE_ADDR bp_addr,
		      const target_waitstatus &ws) override;
  enum print_stop_action print_it (struct bpstat *bs) override;
  bool print_one (struct bp_location **) override;
  void print_mention () override;
  void print_recreate (struct ui_file *fp) override;

  /* Filename of a program whose exec triggered this catchpoint.
     This field is only valid immediately after this catchpoint has
     triggered.  */
  gdb::unique_xmalloc_ptr<char> exec_pathname;
};

int
exec_catchpoint::insert_location (struct bp_location *bl)
{
  return target_insert_exec_catchpoint (inferior_ptid.pid ());
}

int
exec_catchpoint::remove_location (struct bp_location *bl,
				  enum remove_bp_reason reason)
{
  return target_remove_exec_catchpoint (inferior_ptid.pid ());
}

int
exec_catchpoint::breakpoint_hit (const struct bp_location *bl,
				 const address_space *aspace,
				 CORE_ADDR bp_addr,
				 const target_waitstatus &ws)
{
  if (ws.kind () != TARGET_WAITKIND_EXECD)
    return 0;

  exec_pathname = make_unique_xstrdup (ws.execd_pathname ());
  return 1;
}

enum print_stop_action
exec_catchpoint::print_it (bpstat *bs)
{
  struct ui_out *uiout = current_uiout;

  annotate_catchpoint (number);
  maybe_print_thread_hit_breakpoint (uiout);
  if (disposition == disp_del)
    uiout->text ("Temporary catchpoint ");
  else
    uiout->text ("Catchpoint ");
  if (uiout->is_mi_like_p ())
    {
      uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_EXEC));
      uiout->field_string ("disp", bpdisp_text (disposition));
    }
  uiout->field_signed ("bkptno", number);
  uiout->text (" (exec'd ");
  uiout->field_string ("new-exec", exec_pathname.get ());
  uiout->text ("), ");

  return PRINT_SRC_AND_LOC;
}

bool
exec_catchpoint::print_one (struct bp_location **last_loc)
{
  struct value_print_options opts;
  struct ui_out *uiout = current_uiout;

  get_user_print_options (&opts);

  /* Field 4, the address, is omitted (which makes the columns
     not line up too nicely with the headers, but the effect
     is relatively readable).  */
  if (opts.addressprint)
    uiout->field_skip ("addr");
  annotate_field (5);
  uiout->text ("exec");
  if (exec_pathname != NULL)
    {
      uiout->text (", program \"");
      uiout->field_string ("what", exec_pathname.get ());
      uiout->text ("\" ");
    }

  if (uiout->is_mi_like_p ())
    uiout->field_string ("catch-type", "exec");

  return true;
}

void
exec_catchpoint::print_mention ()
{
  gdb_printf (_("Catchpoint %d (exec)"), number);
}

/* Implement the "print_recreate" method for exec catchpoints.  */

void
exec_catchpoint::print_recreate (struct ui_file *fp)
{
  gdb_printf (fp, "catch exec");
  print_recreate_thread (this, fp);
}

/* This function attempts to parse an optional "if <cond>" clause
   from the arg string.  If one is not found, it returns NULL.

   Else, it returns a pointer to the condition string.  (It does not
   attempt to evaluate the string against a particular block.)  And,
   it updates arg to point to the first character following the parsed
   if clause in the arg string.  */

const char *
ep_parse_optional_if_clause (const char **arg)
{
  const char *cond_string;

  if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
    return NULL;

  /* Skip the "if" keyword.  */
  (*arg) += 2;

  /* Skip any extra leading whitespace, and record the start of the
     condition string.  */
  *arg = skip_spaces (*arg);
  cond_string = *arg;

  /* Assume that the condition occupies the remainder of the arg
     string.  */
  (*arg) += strlen (cond_string);

  return cond_string;
}

/* Commands to deal with catching events, such as signals, exceptions,
   process start/exit, etc.  */

static void
catch_exec_command_1 (const char *arg, int from_tty,
		      struct cmd_list_element *command)
{
  struct gdbarch *gdbarch = get_current_arch ();
  const char *cond_string = NULL;
  bool temp = command->context () == CATCH_TEMPORARY;

  if (!arg)
    arg = "";
  arg = skip_spaces (arg);

  /* The allowed syntax is:
     catch exec
     catch exec if <cond>

     First, check if there's an if clause.  */
  cond_string = ep_parse_optional_if_clause (&arg);

  if ((*arg != '\0') && !isspace (*arg))
    error (_("Junk at end of arguments."));

  std::unique_ptr<exec_catchpoint> c (new exec_catchpoint ());
  init_catchpoint (c.get (), gdbarch, temp, cond_string);
  c->exec_pathname.reset ();

  install_breakpoint (0, std::move (c), 1);
}

void _initialize_break_catch_exec ();
void
_initialize_break_catch_exec ()
{
  add_catch_command ("exec", _("Catch calls to exec."),
		     catch_exec_command_1,
		     NULL,
		     CATCH_PERMANENT,
		     CATCH_TEMPORARY);
}
