From 26736d8ec174d5de8d1699ed7b482282d587c270 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 24 Mar 2009 18:04:26 +0000 Subject: [PATCH] * 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. --- gold/ChangeLog | 7 +++++++ gold/output.cc | 29 +++++++++++++++++++++++------ gold/output.h | 6 +++++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index bb76e93706..d233ab560b 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,10 @@ +2009-03-24 Elliott Hughes + + * 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 * target-select.cc (instantiate_target): Don't acquire the lock if diff --git a/gold/output.cc b/gold/output.cc index cb9e038502..d70c37a830 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(this->file_size_), + strerror(errno)); this->base_ = static_cast(base); } diff --git a/gold/output.h b/gold/output.h index 6c37dfd019..5d2c62f3e3 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();