* output.cc (Output_file::map_anonymous): Define.
authorIan Lance Taylor <ian@airs.com>
Tue, 24 Mar 2009 18:04:26 +0000 (18:04 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 24 Mar 2009 18:04:26 +0000 (18:04 +0000)
(Output_file::map): Use map_anonymous.  If the regular mmap fails,
try an anonymous one.  Report the size if the mmap fails.
* output.h (class Output_file): Declare map_anonymous.

gold/ChangeLog
gold/output.cc
gold/output.h

index bb76e937068d6cfeab013e14f3132c715fc0e14b..d233ab560b0e399f101e588b4adfaf0abe027836 100644 (file)
@@ -1,3 +1,10 @@
+2009-03-24  Elliott Hughes  <enh@google.com>
+
+       * output.cc (Output_file::map_anonymous): Define.
+       (Output_file::map): Use map_anonymous.  If the regular mmap fails,
+       try an anonymous one.  Report the size if the mmap fails.
+       * output.h (class Output_file): Declare map_anonymous.
+
 2009-03-24  Ian Lance Taylor  <iant@google.com>
 
        * target-select.cc (instantiate_target): Don't acquire the lock if
index cb9e0385020ce00c6a727f68335646531613813e..d70c37a8300b5533cd658cf643060da9097d7eac 100644 (file)
@@ -3380,6 +3380,17 @@ Output_file::resize(off_t file_size)
     }
 }
 
+// Map a block of memory which will later be written to the file.
+// Return a pointer to the memory.
+
+void*
+Output_file::map_anonymous()
+{
+  this->map_is_anonymous_ = true;
+  return ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
+               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
 // Map the file into memory.
 
 void
@@ -3396,11 +3407,7 @@ Output_file::map()
       || ::fstat(o, &statbuf) != 0
       || !S_ISREG(statbuf.st_mode)
       || this->is_temporary_)
-    {
-      this->map_is_anonymous_ = true;
-      base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
-                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    }
+    base = this->map_anonymous();
   else
     {
       // Ensure that we have disk space available for the file.  If we
@@ -3418,9 +3425,19 @@ Output_file::map()
       this->map_is_anonymous_ = false;
       base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
                     MAP_SHARED, o, 0);
+
+      // The mmap call might fail because of file system issues: the
+      // file system might not support mmap at all, or it might not
+      // support mmap with PROT_WRITE.  I'm not sure which errno
+      // values we will see in all cases, so if the mmap fails for any
+      // reason try for an anonymous map.
+      if (base == MAP_FAILED)
+       base = this->map_anonymous();
     }
   if (base == MAP_FAILED)
-    gold_fatal(_("%s: mmap: %s"), this->name_, strerror(errno));
+    gold_fatal(_("%s: mmap: failed to allocate %lu bytes for output file: %s"),
+              this->name_, static_cast<unsigned long>(this->file_size_),
+              strerror(errno));
   this->base_ = static_cast<unsigned char*>(base);
 }
 
index 6c37dfd0191c3d9e9b560901c424ac204368646f..5d2c62f3e3c28a0aba9095c14bc670ee5166c519 100644 (file)
@@ -3115,10 +3115,14 @@ class Output_file
   { }
 
  private:
-  // Map the file into memory and return a pointer to the map.
+  // Map the file into memory.
   void
   map();
 
+  // Allocate anonymous memory for the file.
+  void*
+  map_anonymous();
+
   // Unmap the file from memory (and flush to disk buffers).
   void
   unmap();