aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog7
-rw-r--r--gold/output.cc29
-rw-r--r--gold/output.h6
3 files changed, 35 insertions, 7 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index bb76e93..d233ab5 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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
diff --git a/gold/output.cc b/gold/output.cc
index cb9e038..d70c37a 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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);
}
diff --git a/gold/output.h b/gold/output.h
index 6c37dfd..5d2c62f 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -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();