diff options
-rw-r--r-- | gold/ChangeLog | 7 | ||||
-rw-r--r-- | gold/output.cc | 29 | ||||
-rw-r--r-- | gold/output.h | 6 |
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(); |