This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] change bfd_mmap API


Hi,

I wrote this patch to fix a bug in gdb for Darwin, and it implies a change in the bfd_mmap API which is used only by gdb.
So this is a patch for both bfd and gdb.

The bfd_mmap function was not correctly defined.  It had a profile very similar to mmap(2), and thus assuming the part of the bfd file mmapped was at the same offset in the page as the offset in the bfd.  But this is not correct if the bfd was a member of an archive because of the origin offset, which happened on Darwin.

So I changed the bfd_mmap function so that it now returns the beginning and the size of the mmapped region (as well as the address corresponding to the offset in the bfd).

This makes bfd_mmap easier to use, and the call to munmap/madvise less complex.

No regression in gdb on i386 gnu/linux.

ok for trunk for gdb ?
ok for trunk for binutils ?

(Maybe we could simplify again and support only a read-only mmapped so that it could be ported to Windows too, but that would be for a future patch).

Tristan.

bfd/
2011-06-24  Tristan Gingold  <gingold@adacore.com>

	* cache.c: Include bfd_stdint.h.
	(cache_bmmap): Change profile.  Return region start and size.
	* bfdio.c (struct bfd_iovec): Change bmmap profile.
	(bfd_mmap): Change profile and adjust.   Update comment.
	(memory_bmmap): Change profile.
	* opncls.c (opncls_bmmap): Change profile.
	* vms-lib.c (vms_lib_bmmap): Likewise.
	* libbfd.h: Regenerate.
	* bfd-in2.h: Regenerate.

gdb/
2011-06-24  Tristan Gingold  <gingold@adacore.com>

	* dwarf2read.c (struct dwarf2_section_info): Replace was_mmapped
	field by map_addr and map_len.
	(dwarf2_read_section): Adjust for the new bfd_mmap api.
	(munmap_section_buffer): Likewise.

diff --git a/bfd/bfdio.c b/bfd/bfdio.c
index dab8e88..841c781 100644
--- a/bfd/bfdio.c
+++ b/bfd/bfdio.c
@@ -158,9 +158,15 @@ DESCRIPTION
 .  int (*bclose) (struct bfd *abfd);
 .  int (*bflush) (struct bfd *abfd);
 .  int (*bstat) (struct bfd *abfd, struct stat *sb);
-.  {* Just like mmap: (void*)-1 on failure, mmapped address on success.  *}
+.  {* 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.
+.     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.  *}
 .  void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
-.                  int prot, int flags, file_ptr offset);
+.                  int prot, int flags, file_ptr offset,
+.                  void **map_addr, bfd_size_type *map_len);
 .};
 
 .extern const struct bfd_iovec _bfd_memory_iovec;
@@ -423,23 +429,28 @@ FUNCTION
 
 SYNOPSIS
 	void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
-	                int prot, int flags, file_ptr offset);
+	                int prot, int flags, file_ptr offset,
+	                void **map_addr, bfd_size_type *map_len);
 
 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.
 
 */
 
 void *
 bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
-	  int prot, int flags, file_ptr offset)
+	  int prot, int flags, file_ptr offset,
+          void **map_addr, bfd_size_type *map_len)
 {
   void *ret = (void *)-1;
 
   if (abfd->iovec == NULL)
     return ret;
 
-  return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset);
+  return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
+                             map_addr, map_len);
 }
 
 /* Memory file I/O operations.  */
@@ -586,7 +597,9 @@ memory_bstat (bfd *abfd, struct stat *statbuf)
 static void *
 memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
               bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
-              int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED)
+              int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED,
+              void **map_addr ATTRIBUTE_UNUSED,
+              bfd_size_type *map_len ATTRIBUTE_UNUSED)
 {
   return (void *)-1;
 }
diff --git a/bfd/cache.c b/bfd/cache.c
index 2239c28..5ddbbe4 100644
--- a/bfd/cache.c
+++ b/bfd/cache.c
@@ -45,6 +45,7 @@ SUBSECTION
 #include "bfd.h"
 #include "libbfd.h"
 #include "libiberty.h"
+#include "bfd_stdint.h"
 
 #ifdef HAVE_MMAP
 #include <sys/mman.h>
@@ -398,7 +399,9 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
 	     bfd_size_type len ATTRIBUTE_UNUSED,
 	     int prot ATTRIBUTE_UNUSED,
 	     int flags ATTRIBUTE_UNUSED,
-	     file_ptr offset ATTRIBUTE_UNUSED)
+	     file_ptr offset ATTRIBUTE_UNUSED,
+             void **map_addr ATTRIBUTE_UNUSED,
+             bfd_size_type *map_len ATTRIBUTE_UNUSED)
 {
   void *ret = (void *) -1;
 
@@ -407,13 +410,35 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
 #ifdef HAVE_MMAP
   else
     {
-      FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
+      static uintptr_t pagesize_m1;
+      FILE *f;
+      file_ptr pg_offset;
+      bfd_size_type pg_len;
+
+      f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR);
       if (f == NULL)
 	return ret;
 
-      ret = mmap (addr, len, prot, flags, fileno (f), offset);
+      if (pagesize_m1 == 0)
+        pagesize_m1 = getpagesize () - 1;
+
+      /* Handle archive members.  */
+      if (abfd->my_archive != NULL)
+        offset += abfd->origin;
+
+      /* Align.  */
+      pg_offset = offset & ~pagesize_m1;
+      pg_len = (len + (offset - pg_offset) + pagesize_m1) & ~pagesize_m1;
+
+      ret = mmap (addr, pg_len, prot, flags, fileno (f), pg_offset);
       if (ret == (void *) -1)
 	bfd_set_error (bfd_error_system_call);
+      else
+        {
+          *map_addr = ret;
+          *map_len = pg_len;
+          ret += offset & pagesize_m1;
+        }
     }
 #endif
 
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 4043200..9d33f39 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -525,7 +525,9 @@ opncls_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
 	      bfd_size_type len ATTRIBUTE_UNUSED,
 	      int prot ATTRIBUTE_UNUSED,
 	      int flags ATTRIBUTE_UNUSED,
-	      file_ptr offset ATTRIBUTE_UNUSED)
+	      file_ptr offset ATTRIBUTE_UNUSED,
+              void **map_addr ATTRIBUTE_UNUSED,
+              bfd_size_type *map_len ATTRIBUTE_UNUSED)
 {
   return (void *) -1;
 }
diff --git a/bfd/vms-lib.c b/bfd/vms-lib.c
index 888982d..0584186 100644
--- a/bfd/vms-lib.c
+++ b/bfd/vms-lib.c
@@ -1196,11 +1196,13 @@ vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED,
 
 static void *
 vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED,
-	      void *addr ATTRIBUTE_UNUSED,
-	      bfd_size_type len ATTRIBUTE_UNUSED,
-	      int prot ATTRIBUTE_UNUSED,
-	      int flags ATTRIBUTE_UNUSED,
-	      file_ptr offset ATTRIBUTE_UNUSED)
+               void *addr ATTRIBUTE_UNUSED,
+               bfd_size_type len ATTRIBUTE_UNUSED,
+               int prot ATTRIBUTE_UNUSED,
+               int flags ATTRIBUTE_UNUSED,
+               file_ptr offset ATTRIBUTE_UNUSED,
+               void **map_addr ATTRIBUTE_UNUSED,
+               bfd_size_type *map_len ATTRIBUTE_UNUSED)
 {
   return (void *) -1;
 }




diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 399d593..cfe0514 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -134,7 +134,10 @@ struct dwarf2_section_info
   asection *asection;
   gdb_byte *buffer;
   bfd_size_type size;
-  int was_mmapped;
+  /* Not NULL if the section was actually mmapped.  */
+  void *map_addr;
+  /* Page aligned size of mmapped area.  */
+  bfd_size_type map_len;
   /* True if we have tried to read this section.  */
   int readin;
 };
@@ -1562,7 +1565,7 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
   if (info->readin)
     return;
   info->buffer = NULL;
-  info->was_mmapped = 0;
+  info->map_addr = NULL;
   info->readin = 1;
 
   if (dwarf2_section_empty_p (info))
@@ -1592,17 +1595,14 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
 
   if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0)
     {
-      off_t pg_offset = sectp->filepos & ~(pagesize - 1);
-      size_t map_length = info->size + sectp->filepos - pg_offset;
-      caddr_t retbuf = bfd_mmap (abfd, 0, map_length, PROT_READ,
-				 MAP_PRIVATE, pg_offset);
+      info->buffer = bfd_mmap (abfd, 0, info->size, PROT_READ,
+                         MAP_PRIVATE, sectp->filepos,
+                         &info->map_addr, &info->map_len);
 
-      if (retbuf != MAP_FAILED)
+      if ((caddr_t)info->buffer != MAP_FAILED)
 	{
-	  info->was_mmapped = 1;
-	  info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ;
 #if HAVE_POSIX_MADVISE
-	  posix_madvise (retbuf, map_length, POSIX_MADV_WILLNEED);
+	  posix_madvise (info->map_addr, info->map_len, POSIX_MADV_WILLNEED);
 #endif
 	  return;
 	}
@@ -15357,14 +15357,13 @@ show_dwarf2_cmd (char *args, int from_tty)
 static void
 munmap_section_buffer (struct dwarf2_section_info *info)
 {
-  if (info->was_mmapped)
+  if (info->map_addr != NULL)
     {
 #ifdef HAVE_MMAP
-      intptr_t begin = (intptr_t) info->buffer;
-      intptr_t map_begin = begin & ~(pagesize - 1);
-      size_t map_length = info->size + begin - map_begin;
+      int res;
 
-      gdb_assert (munmap ((void *) map_begin, map_length) == 0);
+      res = munmap (info->map_addr, info->map_len);
+      gdb_assert (res == 0);
 #else
       /* Without HAVE_MMAP, we should never be here to begin with.  */
       gdb_assert_not_reached ("no mmap support");


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]