/* Support for memory-mapped windows into a BFD.
   Copyright (C) 1995-2024 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.  */

#include "sysdep.h"

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

/* Currently, if USE_MMAP is undefined, none of the window stuff is
   used.  Enabled by --with-mmap.  */

#ifdef USE_MMAP

#undef HAVE_MPROTECT /* code's not tested yet */

static int debug_windows;

/* The idea behind the next and refcount fields is that one mapped
   region can suffice for multiple read-only windows or multiple
   non-overlapping read-write windows.  It's not implemented yet
   though.  */

/*
INTERNAL
.typedef struct _bfd_window_internal
.{
.  struct _bfd_window_internal *next;
.  void *data;
.  bfd_size_type size;
.  int refcount : 31;		{* should be enough...  *}
.  unsigned mapped : 1;		{* 1 = mmap, 0 = malloc *}
.}
.bfd_window_internal;
.

EXTERNAL
.struct _bfd_window_internal;
.
.typedef struct _bfd_window
.{
.  {* What the user asked for.  *}
.  void *data;
.  bfd_size_type size;
.  {* The actual window used by BFD.  Small user-requested read-only
.     regions sharing a page may share a single window into the object
.     file.  Read-write versions shouldn't until I've fixed things to
.     keep track of which portions have been claimed by the
.     application; don't want to give the same region back when the
.     application wants two writable copies!  *}
.  struct _bfd_window_internal *i;
.}
.bfd_window;
.
*/

/*
FUNCTION
	bfd_init_window

SYNOPSIS
	void bfd_init_window (bfd_window *);

DESCRIPTION
	Initialise mmap window.
*/

void
bfd_init_window (bfd_window *windowp)
{
  windowp->data = 0;
  windowp->i = 0;
  windowp->size = 0;
}

/*
FUNCTION
	bfd_free_window

SYNOPSIS
	void bfd_free_window (bfd_window *);

DESCRIPTION
	Finalise mmap window struct.
*/

void
bfd_free_window (bfd_window *windowp)
{
  bfd_window_internal *i = windowp->i;
  windowp->i = 0;
  windowp->data = 0;
  if (i == 0)
    return;
  i->refcount--;
  if (debug_windows)
    fprintf (stderr, "freeing window @%p<%p,%lx,%p>\n",
	     windowp, windowp->data, (unsigned long) windowp->size, windowp->i);
  if (i->refcount != 0)
    return;

  if (i->mapped)
    {
#ifdef HAVE_MMAP
      munmap (i->data, i->size);
      goto no_free;
#else
      abort ();
#endif
    }
#ifdef HAVE_MPROTECT
  mprotect (i->data, i->size, PROT_READ | PROT_WRITE);
#endif
  free (i->data);
#ifdef HAVE_MMAP
 no_free:
#endif
  i->data = 0;
  /* There should be no more references to i at this point.  */
  free (i);
}

/*
FUNCTION
	bfd_get_file_window

SYNOPSIS
	bool bfd_get_file_window
	  (bfd *, file_ptr, bfd_size_type, bfd_window *, bool {*writable*});

DESCRIPTION
	mmap from a bfd's iostream.
*/

bool
bfd_get_file_window (bfd *abfd,
		     file_ptr offset,
		     bfd_size_type size,
		     bfd_window *windowp,
		     bool writable)
{
  static int ok_to_map = 1;
  static size_t pagesize;
  bfd_window_internal *i = windowp->i;
  bfd_size_type size_to_alloc = size;

  if (debug_windows)
    fprintf (stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
	     abfd, (long) offset, (long) size,
	     windowp, windowp->data, (unsigned long) windowp->size,
	     windowp->i, writable);

  /* Make sure we know the page size, so we can be friendly to mmap.  */
  if (pagesize == 0)
    pagesize = getpagesize ();
  if (pagesize == 0)
    abort ();

  if (i == NULL)
    {
      i = bfd_zmalloc (sizeof (bfd_window_internal));
      if (i == NULL)
	return false;
      i->data = NULL;
    }
#ifdef HAVE_MMAP
  if (ok_to_map
      && (i->data == NULL || i->mapped == 1)
      && (abfd->flags & BFD_IN_MEMORY) == 0)
    {
      file_ptr file_offset, offset2;
      size_t real_size;
      int fd;

      /* Find the real file and the real offset into it.  */
      while (abfd->my_archive != NULL
	     && !bfd_is_thin_archive (abfd->my_archive))
	{
	  offset += abfd->origin;
	  abfd = abfd->my_archive;
	}
      offset += abfd->origin;

      /* Seek into the file, to ensure it is open if cacheable.  */
      if (abfd->iostream == NULL
	  && (abfd->iovec == NULL
	      || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
	goto free_and_fail;

      fd = fileno ((FILE *) abfd->iostream);
      /* Compute offsets and size for mmap and for the user's data.  */
      offset2 = offset % pagesize;
      if (offset2 < 0)
	abort ();
      file_offset = offset - offset2;
      real_size = offset + size - file_offset;
      real_size = real_size + pagesize - 1;
      real_size -= real_size % pagesize;

      /* If we're re-using a memory region, make sure it's big enough.  */
      if (i->data != NULL && i->size < size)
	{
	  munmap (i->data, i->size);
	  i->data = NULL;
	}
      i->data = mmap (i->data, real_size,
		      writable ? PROT_WRITE | PROT_READ : PROT_READ,
		      (writable
		       ? MAP_FILE | MAP_PRIVATE
		       : MAP_FILE | MAP_SHARED),
		      fd, file_offset);
      if (i->data == MAP_FAILED)
	{
	  /* An error happened.  Report it, or try using malloc, or
	     something.  */
	  bfd_set_error (bfd_error_system_call);
	  windowp->data = 0;
	  if (debug_windows)
	    fprintf (stderr, "\t\tmmap failed!\n");
	  goto free_and_fail;
	}
      if (debug_windows)
	fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
		 (long) real_size, i->data, (long) offset2);
      i->size = real_size;
      windowp->data = (bfd_byte *) i->data + offset2;
      windowp->size = size;
      i->mapped = 1;
      i->refcount = 1;
      windowp->i = i;
      return true;
    }
  else if (debug_windows)
    {
      if (ok_to_map)
	fprintf (stderr, _("not mapping: data=%lx mapped=%d\n"),
		 (unsigned long) i->data, (int) i->mapped);
      else
	fprintf (stderr, _("not mapping: env var not set\n"));
    }
#else
  ok_to_map = 0;
#endif

#ifdef HAVE_MPROTECT
  if (!writable)
    {
      size_to_alloc += pagesize - 1;
      size_to_alloc -= size_to_alloc % pagesize;
    }
#endif
  if (debug_windows)
    fprintf (stderr, "\n\t%s(%6ld)",
	     i->data ? "realloc" : " malloc", (long) size_to_alloc);
  i->data = bfd_realloc_or_free (i->data, size_to_alloc);
  if (debug_windows)
    fprintf (stderr, "\t-> %p\n", i->data);
  if (i->data == NULL)
    {
      if (size_to_alloc == 0)
	{
	  windowp->i = i;
	  return true;
	}
      goto free_and_fail;
    }
  i->refcount = 1;
  if (bfd_seek (abfd, offset, SEEK_SET) != 0)
    goto free_and_fail;
  i->size = bfd_read (i->data, size, abfd);
  if (i->size != size)
    goto free_and_fail;
  i->mapped = 0;
#ifdef HAVE_MPROTECT
  if (!writable)
    {
      if (debug_windows)
	fprintf (stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data,
		 (long) i->size);
      mprotect (i->data, i->size, PROT_READ);
    }
#endif
  windowp->data = i->data;
  windowp->size = i->size;
  windowp->i = i;
  return true;

 free_and_fail:
  /* We have a bfd_window_internal, but an error occurred.  Free it. */
  free (i);
  return false;
}

#endif /* USE_MMAP */
