/* Core file generic interface routines for BFD.
   Copyright (C) 1990-2016 Free Software Foundation, Inc.
   Written by Cygnus Support.

   This file is part of BFD, the Binary File Descriptor library.

   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, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */

/*
SECTION
	Core files

SUBSECTION
	Core file functions

DESCRIPTION
	These are functions pertaining to core files.
*/

#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"

/*
FUNCTION
	bfd_core_file_failing_command

SYNOPSIS
	const char *bfd_core_file_failing_command (bfd *abfd);

DESCRIPTION
	Return a read-only string explaining which program was running
	when it failed and produced the core file @var{abfd}.

*/

const char *
bfd_core_file_failing_command (bfd *abfd)
{
  if (abfd->format != bfd_core)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return NULL;
    }
  return BFD_SEND (abfd, _core_file_failing_command, (abfd));
}

/*
FUNCTION
	bfd_core_file_failing_signal

SYNOPSIS
	int bfd_core_file_failing_signal (bfd *abfd);

DESCRIPTION
	Returns the signal number which caused the core dump which
	generated the file the BFD @var{abfd} is attached to.
*/

int
bfd_core_file_failing_signal (bfd *abfd)
{
  if (abfd->format != bfd_core)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return 0;
    }
  return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
}

/*
FUNCTION
	bfd_core_file_pid

SYNOPSIS
	int bfd_core_file_pid (bfd *abfd);

DESCRIPTION

	Returns the PID of the process the core dump the BFD
	@var{abfd} is attached to was generated from.
*/

int
bfd_core_file_pid (bfd *abfd)
{
  if (abfd->format != bfd_core)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return 0;
    }
  return BFD_SEND (abfd, _core_file_pid, (abfd));
}


/*
FUNCTION
	core_file_matches_executable_p

SYNOPSIS
	bfd_boolean core_file_matches_executable_p
	  (bfd *core_bfd, bfd *exec_bfd);

DESCRIPTION
	Return <<TRUE>> if the core file attached to @var{core_bfd}
	was generated by a run of the executable file attached to
	@var{exec_bfd}, <<FALSE>> otherwise.
*/

bfd_boolean
core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
  if (core_bfd->format != bfd_core || exec_bfd->format != bfd_object)
    {
      bfd_set_error (bfd_error_wrong_format);
      return FALSE;
    }

  return BFD_SEND (core_bfd, _core_file_matches_executable_p,
		   (core_bfd, exec_bfd));
}

/*
FUNCTION
        generic_core_file_matches_executable_p

SYNOPSIS
        bfd_boolean generic_core_file_matches_executable_p
          (bfd *core_bfd, bfd *exec_bfd);

DESCRIPTION
        Return TRUE if the core file attached to @var{core_bfd}
        was generated by a run of the executable file attached
        to @var{exec_bfd}.  The match is based on executable
        basenames only.

        Note: When not able to determine the core file failing
        command or the executable name, we still return TRUE even
        though we're not sure that core file and executable match.
        This is to avoid generating a false warning in situations
        where we really don't know whether they match or not.
*/

bfd_boolean
generic_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
{
  char *exec;
  char *core;
  char *last_slash;

  if (exec_bfd == NULL || core_bfd == NULL)
    return TRUE;

  /* The cast below is to avoid a compiler warning due to the assignment
     of the const char * returned by bfd_core_file_failing_command to a
     non-const char *.  In this case, the assignement does not lead to
     breaking the const, as we're only reading the string.  */

  core = (char *) bfd_core_file_failing_command (core_bfd);
  if (core == NULL)
    return TRUE;

  exec = bfd_get_filename (exec_bfd);
  if (exec == NULL)
    return TRUE;

  last_slash = strrchr (core, '/');
  if (last_slash != NULL)
    core = last_slash + 1;

  last_slash = strrchr (exec, '/');
  if (last_slash != NULL)
    exec = last_slash + 1;

  return filename_cmp (exec, core) == 0;
}

