From a8b8576e54323add0cd7d239ea3e7f5cbb4f4bdc Mon Sep 17 00:00:00 2001
From: Tom Tromey <tom@tromey.com>
Date: Thu, 4 Sep 2025 14:12:52 -0600
Subject: [PATCH 08/25] Change return value of _bfd_mmap_temporary

_bfd_mmap_temporary will return MAP_FAILED in some cases, but only one
caller was prepared for this.  This caused a couple of issues in gdb.

This patch chnages _bfd_mmap_temporary to always return NULL on
failure.  It also changes the logic to fall back to bfd_malloc if mmap
fails.

I took the opportunity to change some "(void *) -1" to MAP_FAILED
where appropriate.

Tested by "make check" in binutils, and also by applying a hack from
bug 33354 to gdb and testing something approximating the original
report.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32542
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33354

(cherry picked from commit 8b50cc76f19d129b3887dbcb58f8286a7b36099f)
---
 bfd/bfdio.c  |  5 +++--
 bfd/libbfd.c | 33 +++++++++++++++------------------
 bfd/libbfd.h |  2 +-
 3 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/bfd/bfdio.c b/bfd/bfdio.c
index 2a7f77fa8d4..1602743c7e2 100644
--- a/bfd/bfdio.c
+++ b/bfd/bfdio.c
@@ -293,7 +293,7 @@ DESCRIPTION
 .  int (*bstat) (struct bfd *abfd, struct stat *sb);
 .  {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
 .     mmap parameter, except that LEN and OFFSET do not need to be page
-.     aligned.  Returns (void *)-1 on failure, mmapped address on success.
+.     aligned.  Returns MAP_FAILED on failure, mmapped address on success.
 .     Also write in MAP_ADDR the address of the page aligned buffer and in
 .     MAP_LEN the size mapped (a page multiple).  Use unmap with MAP_ADDR and
 .     MAP_LEN to unmap.  *}
@@ -725,6 +725,7 @@ DESCRIPTION
 	Return mmap()ed region of the file, if possible and implemented.
 	LEN and OFFSET do not need to be page aligned.  The page aligned
 	address and length are written to MAP_ADDR and MAP_LEN.
+	Returns MAP_FAILED on failure.
 
 */
 
@@ -898,7 +899,7 @@ memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
 	      void **map_addr ATTRIBUTE_UNUSED,
 	      size_t *map_len ATTRIBUTE_UNUSED)
 {
-  return (void *)-1;
+  return MAP_FAILED;
 }
 
 const struct bfd_iovec _bfd_memory_iovec =
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index 4ab5bf498fd..3488bd09abe 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -1098,24 +1098,26 @@ bfd_mmap_local (bfd *abfd, size_t rsize, void **map_addr, size_t *map_size)
 
 /* Mmap a memory region of RSIZE bytes at the current offset.
    Return mmap address and size in MAP_ADDR and MAP_SIZE.  Return NULL
-   on invalid input and MAP_FAILED for mmap failure.  */
+   on invalid input.  */
 
 void *
 _bfd_mmap_temporary (bfd *abfd, size_t rsize, void **map_addr,
 		     size_t *map_size)
 {
   /* Use mmap only if section size >= the minimum mmap section size.  */
-  if (rsize < _bfd_minimum_mmap_size)
+  if (rsize >= _bfd_minimum_mmap_size)
     {
-      void *mem = _bfd_malloc_and_read (abfd, rsize, rsize);
-      /* NB: Set *MAP_ADDR to MEM and *MAP_SIZE to 0 to indicate that
-	 _bfd_malloc_and_read is called.  */
-      *map_addr = mem;
-      *map_size = 0;
-      return mem;
+      void *result = bfd_mmap_local (abfd, rsize, map_addr, map_size);
+      if (result != MAP_FAILED)
+	return result;
     }
 
-  return bfd_mmap_local (abfd, rsize, map_addr, map_size);
+  void *mem = _bfd_malloc_and_read (abfd, rsize, rsize);
+  /* NB: Set *MAP_ADDR to MEM and *MAP_SIZE to 0 to indicate that
+     _bfd_malloc_and_read is called.  */
+  *map_addr = mem;
+  *map_size = 0;
+  return mem;
 }
 
 /* Munmap RSIZE bytes at PTR.  */
@@ -1213,15 +1215,10 @@ _bfd_mmap_read_temporary (void **data_p, size_t *size_p,
   if (use_mmmap)
     {
       void *mmaped = _bfd_mmap_temporary (abfd, size, mmap_base, size_p);
-      /* MAP_FAILED is returned when called from GDB on an object with
-	 opncls_iovec.  Use bfd_read in this case.  */
-      if (mmaped != MAP_FAILED)
-	{
-	  if (mmaped == NULL)
-	    abort ();
-	  *data_p = mmaped;
-	  return true;
-	}
+      if (mmaped == NULL)
+	return false;
+      *data_p = mmaped;
+      return true;
     }
 #endif
 
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index d4be334bf87..fa09e3c656e 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1022,7 +1022,7 @@ struct bfd_iovec
   int (*bstat) (struct bfd *abfd, struct stat *sb);
   /* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
      mmap parameter, except that LEN and OFFSET do not need to be page
-     aligned.  Returns (void *)-1 on failure, mmapped address on success.
+     aligned.  Returns MAP_FAILED on failure, mmapped address on success.
      Also write in MAP_ADDR the address of the page aligned buffer and in
      MAP_LEN the size mapped (a page multiple).  Use unmap with MAP_ADDR and
      MAP_LEN to unmap.  */
-- 
2.51.0

