diff options
-rw-r--r-- | gold/ChangeLog | 25 | ||||
-rw-r--r-- | gold/config.in | 8 | ||||
-rwxr-xr-x | gold/configure | 67 | ||||
-rw-r--r-- | gold/configure.ac | 18 | ||||
-rw-r--r-- | gold/fileread.cc | 88 | ||||
-rw-r--r-- | gold/gold.h | 7 | ||||
-rw-r--r-- | gold/mremap.c | 38 | ||||
-rw-r--r-- | gold/output.cc | 116 | ||||
-rw-r--r-- | gold/output.h | 4 |
9 files changed, 317 insertions, 54 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index cb4cdfa..bb29127 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,28 @@ +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. + 2011-04-11 Ian Lance Taylor <iant@google.com> * incremental.cc (Sized_incr_relobj::do_add_symbols): Always diff --git a/gold/config.in b/gold/config.in index 7a824b0..8611376 100644 --- a/gold/config.in +++ b/gold/config.in @@ -87,7 +87,10 @@ /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H -/* Define to 1 if you have the `mremap' function. */ +/* Define to 1 if you have the `mmap' function. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the mremap function with MREMAP_MAYMOVE support */ #undef HAVE_MREMAP /* Define if compiler supports #pragma omp threadprivate */ @@ -120,6 +123,9 @@ /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF +/* Define to 1 if you have the <sys/mman.h> header file. */ +#undef HAVE_SYS_MMAN_H + /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H diff --git a/gold/configure b/gold/configure index 1a0d47d..5a7268d 100755 --- a/gold/configure +++ b/gold/configure @@ -6486,18 +6486,32 @@ WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmi LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" -for ac_func in chsize +for ac_header in sys/mman.h do : - ac_fn_c_check_func "$LINENO" "chsize" "ac_cv_func_chsize" -if test "x$ac_cv_func_chsize" = x""yes; then : + ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mman_h" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_CHSIZE 1 +#define HAVE_SYS_MMAN_H 1 +_ACEOF + +fi + +done + +for ac_func in chsize mmap +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done -for ac_func in pread ftruncate mremap ffsll +for ac_func in pread ftruncate ffsll do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -6519,6 +6533,49 @@ done +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking mremap with MREMAP_MAYMOVE" >&5 +$as_echo_n "checking mremap with MREMAP_MAYMOVE... " >&6; } +if test "${gold_cv_lib_mremap_maymove+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +#include <sys/mman.h> +void f() { mremap (0, 0, 0, MREMAP_MAYMOVE); } + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gold_cv_lib_mremap_maymove=yes +else + gold_cv_lib_mremap_maymove=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_lib_mremap_maymove" >&5 +$as_echo "$gold_cv_lib_mremap_maymove" >&6; } +if test "$gold_cv_lib_mremap_maymove" = "yes"; then + +$as_echo "#define HAVE_MREMAP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" mremap.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS mremap.$ac_objext" + ;; +esac + +fi + # Link in zlib if we can. This allows us to write compressed sections. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing zlibVersion" >&5 $as_echo_n "checking for library containing zlibVersion... " >&6; } diff --git a/gold/configure.ac b/gold/configure.ac index 60243d0..7757d8c 100644 --- a/gold/configure.ac +++ b/gold/configure.ac @@ -393,8 +393,22 @@ dnl host dependent. If build == host, we can check getconf LFS_CFLAGS. 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)]) diff --git a/gold/fileread.cc b/gold/fileread.cc index 2ae0a43..2324734 100644 --- a/gold/fileread.cc +++ b/gold/fileread.cc @@ -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, section_size_type size, 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 offset, off_t start, { 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()); diff --git a/gold/gold.h b/gold/gold.h index 158f63b..133a64e 100644 --- a/gold/gold.h +++ b/gold/gold.h @@ -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*, size_t, off_t); 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 diff --git a/gold/mremap.c b/gold/mremap.c index 332fded..e165634 100644 --- a/gold/mremap.c +++ b/gold/mremap.c @@ -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_size, size_t new_size, (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) */ diff --git a/gold/output.cc b/gold/output.cc index 5c1fae9..26f843c 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -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* name) 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; } diff --git a/gold/output.h b/gold/output.h index d62ae73..f47c724 100644 --- a/gold/output.h +++ b/gold/output.h @@ -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_; }; |