This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: gold work on mingw/mingw64 support
- From: Ian Lance Taylor <iant at google dot com>
- To: Vladimir Simonov <sv at sw dot ru>
- Cc: binutils at sourceware dot org
- Date: Tue, 12 Apr 2011 11:06:28 -0700
- Subject: Re: gold work on mingw/mingw64 support
- References: <4D1CC5CB.5030700@sw.ru> <mcrd3oj12so.fsf@google.com> <4D234F4B.2010600@sw.ru> <mcr7hekr2q8.fsf@google.com> <4D24613E.1050807@sw.ru>
Vladimir Simonov <sv@sw.ru> writes:
> On 01/04/2011 08:35 PM, Ian Lance Taylor wrote:
>> Vladimir Simonov<sv@sw.ru> writes:
>>
>>> IMO mremap.c, pread.c, etc. are a kind of such library.
>>> Analysis of target OS capabilities is overkill here, we
>>> know in advance - mingw doesn't have mmap and most probably
>>> won't have it.
>>
>> Sure, but there are other systems that also don't have mmap. We don't
>> want to test for all of them.
>>
>>> If __MINGW32__ looks too OS specific it may be
>>> replaced with HAVE_NO_MMAP, HAVE_NO_CLOEXEC defined
>>> in config/mh-mingw. Really __MINGW32__ looks quite strange
>>> in the middle of descriptors.cc but I don't know how to do it
>>> better - fake function in mremap.h would be also strange,
>>> new fcntl.c - the same...
>>
>> I'm complaining in part about the __MINGW32__ and in part about the
>> #ifdef. Apart from ENABLE_THREADS, the only #ifdefs in gold are very
>> small ones at the top of a few .cc files. Let's keep it that way.
>>
>> Ian
>>
>
> OK. Here is a version without __MINGW32__, with sys/mman.h and mmap
> function presence detection and new mmap.h/mmap.c.
> It is larger but should satisfy you requirements.
> Could you comment?
Thanks.
I decided to go a different route. It seems that mmap could in general
fail for a file which can nevertheless be read. So I decided to go
ahead and change gold to handle the case of mmap failing. This then
turns the mingw32 code into a matter of supporting systems which don't
provide mmap by providing a stub mmap which always fails.
I committed the appended patch. Let me know if you find problems with
it. This patch also cleans up mremap a bit even on systems which
provide mmap.
Ian
2011-04-12 Ian Lance Taylor <iant@google.com>
* configure.ac: Check for sys/mman.h and mmap. Check for mremap
with MREMAP_MAYMOVE.
* output.h (class Output_file): Add map_is_allocated_ field.
* output.cc: Only #include <sys/mman.h> if it exists. If mmap is
not available, provide stubs. If mremap is not available, #define
it to gold_mremap.
(MREMAP_MAYMOVE): Define if not defined.
(Output_file::Output_file): Initialize map_is_allocated_.
(Output_file::resize): Check map_is_allocated_.
(Output_file::map_anonymous): If mmap fails, use malloc.
(Output_file::unmap): Don't do anything for an anonymous map.
* fileread.cc: Only #include <sys/mman.h> if it exists. If mmap
is not available, provide stubs.
(File_read::View::~View): Use free rather than delete[].
(File_read::make_view): Use malloc rather than new[]. If mmap
fails, use malloc.
(File_read::find_or_make_view): Use malloc rather than new[].
* gold.h: Remove HAVE_REMAP code.
* mremap.c: #include <errno.h>. Only #include <sys/mman.h> if it
exists. Rename mremap to gold_mremap. If mmap is not available
don't do anything.
* configure, config.in: Rebuild.
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.119
diff -p -u -r1.119 output.h
--- output.h 12 Apr 2011 00:44:48 -0000 1.119
+++ output.h 12 Apr 2011 18:01:49 -0000
@@ -1,6 +1,6 @@
// output.h -- manage the output file for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -4221,6 +4221,8 @@ class Output_file
unsigned char* base_;
// True iff base_ points to a memory buffer rather than an output file.
bool map_is_anonymous_;
+ // True if base_ was allocated using new rather than mmap.
+ bool map_is_allocated_;
// True if this is a temporary file which should not be output.
bool is_temporary_;
};
Index: configure.ac
===================================================================
RCS file: /cvs/src/src/gold/configure.ac,v
retrieving revision 1.61
diff -p -u -r1.61 configure.ac
--- configure.ac 2 Mar 2011 14:51:42 -0000 1.61
+++ configure.ac 12 Apr 2011 18:01:49 -0000
@@ -393,8 +393,22 @@ dnl host dependent. If build == host, w
LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
AC_SUBST(LFS_CFLAGS)
-AC_CHECK_FUNCS(chsize)
-AC_REPLACE_FUNCS(pread ftruncate mremap ffsll)
+AC_CHECK_HEADERS(sys/mman.h)
+AC_CHECK_FUNCS(chsize mmap)
+AC_REPLACE_FUNCS(pread ftruncate ffsll)
+
+AC_CACHE_CHECK([mremap with MREMAP_MAYMOVE], [gold_cv_lib_mremap_maymove],
+[AC_LINK_IFELSE([
+AC_LANG_PROGRAM([[
+#include <sys/mman.h>
+void f() { mremap (0, 0, 0, MREMAP_MAYMOVE); }
+]])], [gold_cv_lib_mremap_maymove=yes], [gold_cv_lib_mremap_maymove=no])])
+if test "$gold_cv_lib_mremap_maymove" = "yes"; then
+ AC_DEFINE(HAVE_MREMAP, 1,
+ [Define to 1 if you have the mremap function with MREMAP_MAYMOVE support])
+else
+ AC_LIBOBJ(mremap)
+fi
# Link in zlib if we can. This allows us to write compressed sections.
AC_SEARCH_LIBS(zlibVersion, z, [AC_CHECK_HEADERS(zlib.h)])
Index: gold.h
===================================================================
RCS file: /cvs/src/src/gold/gold.h,v
retrieving revision 1.45
diff -p -u -r1.45 gold.h
--- gold.h 14 Dec 2010 19:03:29 -0000 1.45
+++ gold.h 12 Apr 2011 18:01:49 -0000
@@ -1,6 +1,6 @@
// gold.h -- general definitions for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -135,11 +135,6 @@ extern "C" ssize_t pread(int, void*, siz
extern "C" int ftruncate(int, off_t);
#endif
-#ifndef HAVE_MREMAP
-#define MREMAP_MAYMOVE 1
-extern "C" void *mremap(void *, size_t, size_t, int, ...);
-#endif
-
#ifndef HAVE_FFSLL
extern "C" int ffsll(long long);
#endif
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.141
diff -p -u -r1.141 output.cc
--- output.cc 12 Apr 2011 00:44:48 -0000 1.141
+++ output.cc 12 Apr 2011 18:01:49 -0000
@@ -1,6 +1,6 @@
// output.cc -- manage the output file for gold
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -27,9 +27,13 @@
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
-#include <sys/mman.h>
#include <sys/stat.h>
#include <algorithm>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
#include "libiberty.h"
#include "parameters.h"
@@ -40,11 +44,71 @@
#include "descriptors.h"
#include "output.h"
+// For systems without mmap support.
+#ifndef HAVE_MMAP
+# define mmap gold_mmap
+# define munmap gold_munmap
+# define mremap gold_mremap
+# ifndef MAP_FAILED
+# define MAP_FAILED (reinterpret_cast<void*>(-1))
+# endif
+# ifndef PROT_READ
+# define PROT_READ 0
+# endif
+# ifndef PROT_WRITE
+# define PROT_WRITE 0
+# endif
+# ifndef MAP_PRIVATE
+# define MAP_PRIVATE 0
+# endif
+# ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS 0
+# endif
+# ifndef MAP_SHARED
+# define MAP_SHARED 0
+# endif
+
+# ifndef ENOSYS
+# define ENOSYS EINVAL
+# endif
+
+static void *
+gold_mmap(void *, size_t, int, int, int, off_t)
+{
+ errno = ENOSYS;
+ return MAP_FAILED;
+}
+
+static int
+gold_munmap(void *, size_t)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static void *
+gold_mremap(void *, size_t, size_t, int)
+{
+ errno = ENOSYS;
+ return MAP_FAILED;
+}
+
+#endif
+
+#if defined(HAVE_MMAP) && !defined(HAVE_MREMAP)
+# define mremap gold_mremap
+extern "C" void *gold_mremap(void *, size_t, size_t, int);
+#endif
+
// Some BSD systems still use MAP_ANON instead of MAP_ANONYMOUS
#ifndef MAP_ANONYMOUS
# define MAP_ANONYMOUS MAP_ANON
#endif
+#ifndef MREMAP_MAYMOVE
+# define MREMAP_MAYMOVE 1
+#endif
+
#ifndef HAVE_POSIX_FALLOCATE
// A dummy, non general, version of posix_fallocate. Here we just set
// the file size and hope that there is enough disk space. FIXME: We
@@ -4415,6 +4479,7 @@ Output_file::Output_file(const char* nam
file_size_(0),
base_(NULL),
map_is_anonymous_(false),
+ map_is_allocated_(false),
is_temporary_(false)
{
}
@@ -4522,10 +4587,23 @@ Output_file::resize(off_t file_size)
// to unmap to flush to the file, then remap after growing the file.
if (this->map_is_anonymous_)
{
- void* base = ::mremap(this->base_, this->file_size_, file_size,
- MREMAP_MAYMOVE);
- if (base == MAP_FAILED)
- gold_fatal(_("%s: mremap: %s"), this->name_, strerror(errno));
+ void* base;
+ if (!this->map_is_allocated_)
+ {
+ base = ::mremap(this->base_, this->file_size_, file_size,
+ MREMAP_MAYMOVE);
+ if (base == MAP_FAILED)
+ gold_fatal(_("%s: mremap: %s"), this->name_, strerror(errno));
+ }
+ else
+ {
+ base = realloc(this->base_, file_size);
+ if (base == NULL)
+ gold_nomem();
+ if (file_size > this->file_size_)
+ memset(static_cast<char*>(base) + this->file_size_, 0,
+ file_size - this->file_size_);
+ }
this->base_ = static_cast<unsigned char*>(base);
this->file_size_ = file_size;
}
@@ -4546,13 +4624,17 @@ Output_file::map_anonymous()
{
void* base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (base != MAP_FAILED)
+ if (base == MAP_FAILED)
{
- this->map_is_anonymous_ = true;
- this->base_ = static_cast<unsigned char*>(base);
- return true;
+ base = malloc(this->file_size_);
+ if (base == NULL)
+ return false;
+ memset(base, 0, this->file_size_);
+ this->map_is_allocated_ = true;
}
- return false;
+ this->base_ = static_cast<unsigned char*>(base);
+ this->map_is_anonymous_ = true;
+ return true;
}
// Map the file into memory. Return whether the mapping succeeded.
@@ -4624,8 +4706,16 @@ Output_file::map()
void
Output_file::unmap()
{
- if (::munmap(this->base_, this->file_size_) < 0)
- gold_error(_("%s: munmap: %s"), this->name_, strerror(errno));
+ if (this->map_is_anonymous_)
+ {
+ // We've already written out the data, so there is no reason to
+ // waste time unmapping or freeing the memory.
+ }
+ else
+ {
+ if (::munmap(this->base_, this->file_size_) < 0)
+ gold_error(_("%s: munmap: %s"), this->name_, strerror(errno));
+ }
this->base_ = NULL;
}
Index: fileread.cc
===================================================================
RCS file: /cvs/src/src/gold/fileread.cc,v
retrieving revision 1.72
diff -p -u -r1.72 fileread.cc
--- fileread.cc 12 Apr 2011 00:44:47 -0000 1.72
+++ fileread.cc 12 Apr 2011 18:01:49 -0000
@@ -27,7 +27,10 @@
#include <climits>
#include <fcntl.h>
#include <unistd.h>
+
+#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
+#endif
#ifdef HAVE_READV
#include <sys/uio.h>
@@ -46,6 +49,40 @@
#include "gold-threads.h"
#include "fileread.h"
+// For systems without mmap support.
+#ifndef HAVE_MMAP
+# define mmap gold_mmap
+# define munmap gold_munmap
+# ifndef MAP_FAILED
+# define MAP_FAILED (reinterpret_cast<void*>(-1))
+# endif
+# ifndef PROT_READ
+# define PROT_READ 0
+# endif
+# ifndef MAP_PRIVATE
+# define MAP_PRIVATE 0
+# endif
+
+# ifndef ENOSYS
+# define ENOSYS EINVAL
+# endif
+
+static void *
+gold_mmap(void *, size_t, int, int, int, off_t)
+{
+ errno = ENOSYS;
+ return MAP_FAILED;
+}
+
+static int
+gold_munmap(void *, size_t)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
+
#ifndef HAVE_READV
struct iovec { void* iov_base; size_t iov_len; };
ssize_t
@@ -96,7 +133,7 @@ File_read::View::~View()
switch (this->data_ownership_)
{
case DATA_ALLOCATED_ARRAY:
- delete[] this->data_;
+ free(const_cast<unsigned char*>(this->data_));
break;
case DATA_MMAPPED:
if (::munmap(const_cast<unsigned char*>(this->data_), this->size_) != 0)
@@ -440,34 +477,40 @@ File_read::make_view(off_t start, sectio
gold_assert(psize >= size);
}
- File_read::View* v;
+ void* p;
+ View::Data_ownership ownership;
if (byteshift != 0)
{
- unsigned char* p = new unsigned char[psize + byteshift];
+ p = malloc(psize + byteshift);
+ if (p == NULL)
+ gold_nomem();
memset(p, 0, byteshift);
- this->do_read(poff, psize, p + byteshift);
- v = new File_read::View(poff, psize, p, byteshift, cache,
- View::DATA_ALLOCATED_ARRAY);
+ this->do_read(poff, psize, static_cast<unsigned char*>(p) + byteshift);
+ ownership = View::DATA_ALLOCATED_ARRAY;
}
else
{
this->reopen_descriptor();
- void* p = ::mmap(NULL, psize, PROT_READ, MAP_PRIVATE,
- this->descriptor_, poff);
- if (p == MAP_FAILED)
- gold_fatal(_("%s: mmap offset %lld size %lld failed: %s"),
- this->filename().c_str(),
- static_cast<long long>(poff),
- static_cast<long long>(psize),
- strerror(errno));
-
- this->mapped_bytes_ += psize;
-
- const unsigned char* pbytes = static_cast<const unsigned char*>(p);
- v = new File_read::View(poff, psize, pbytes, 0, cache,
- View::DATA_MMAPPED);
+ p = ::mmap(NULL, psize, PROT_READ, MAP_PRIVATE, this->descriptor_, poff);
+ if (p != MAP_FAILED)
+ {
+ ownership = View::DATA_MMAPPED;
+ this->mapped_bytes_ += psize;
+ }
+ else
+ {
+ p = malloc(psize);
+ if (p == NULL)
+ gold_nomem();
+ this->do_read(poff, psize, p);
+ ownership = View::DATA_ALLOCATED_ARRAY;
+ }
}
+ const unsigned char* pbytes = static_cast<const unsigned char*>(p);
+ File_read::View* v = new File_read::View(poff, psize, pbytes, byteshift,
+ cache, ownership);
+
this->add_view(v);
return v;
@@ -525,7 +568,10 @@ File_read::find_or_make_view(off_t offse
{
gold_assert(aligned);
- unsigned char* pbytes = new unsigned char[v->size() + byteshift];
+ unsigned char* pbytes;
+ pbytes = static_cast<unsigned char*>(malloc(v->size() + byteshift));
+ if (pbytes == NULL)
+ gold_nomem();
memset(pbytes, 0, byteshift);
memcpy(pbytes + byteshift, v->data() + v->byteshift(), v->size());
Index: mremap.c
===================================================================
RCS file: /cvs/src/src/gold/mremap.c,v
retrieving revision 1.2
diff -p -u -r1.2 mremap.c
--- mremap.c 28 Mar 2009 05:22:30 -0000 1.2
+++ mremap.c 12 Apr 2011 18:01:49 -0000
@@ -1,6 +1,6 @@
/* mremap.c -- version of mremap for gold. */
-/* Copyright 2009 Free Software Foundation, Inc.
+/* Copyright 2009, 2011 Free Software Foundation, Inc.
Written by Ian Lance Taylor <iant@google.com>.
This file is part of gold.
@@ -23,9 +23,17 @@
#include "config.h"
#include "ansidecl.h"
+#include <errno.h>
#include <string.h>
#include <sys/types.h>
+
+#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
+#endif
+
+extern void *gold_mremap (void *, size_t, size_t, int);
+
+#ifdef HAVE_MMAP
/* This file implements mremap for systems which don't have it. The
gold code requires support for mmap. However, there are systems
@@ -40,11 +48,9 @@
# define MAP_ANONYMOUS MAP_ANON
#endif
-extern void *mremap (void *, size_t, size_t, int, ...);
-
void *
-mremap (void *old_address, size_t old_size, size_t new_size,
- int flags ATTRIBUTE_UNUSED, ...)
+gold_mremap (void *old_address, size_t old_size, size_t new_size,
+ int flags ATTRIBUTE_UNUSED)
{
void *ret;
@@ -57,3 +63,25 @@ mremap (void *old_address, size_t old_si
(void) munmap (old_address, old_size);
return ret;
}
+
+#else /* !defined(HAVE_MMAP) */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+void *
+gold_mremap (void *old_address ATTRIBUTE_UNUSED,
+ size_t old_size ATTRIBUTE_UNUSED,
+ size_t new_size ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED)
+{
+ errno = ENOSYS;
+ return MAP_FAILED;
+}
+
+#endif /* !defined(HAVE_MMAP) */