* descriptors.cc: New file.
	* descriptors.h: New file.
	* gold-threads.h (class Hold_optional_lock): New class.
	* fileread.cc: Include "descriptors.h".
	(File_read::~File_read): Release descriptor rather than closing
	it.
	(File_read::open) [file]: Call open_descriptor rather than open.
	Set is_descriptor_opened_.
	(File_read::open) [memory]: Assert that descriptor is not open.
	(File_read::reopen_descriptor): New function.
	(File_read::release): Release descriptor.
	(File_read::do_read): Make non-const.  Reopen descriptor.
	(File_read::read): Make non-const.
	(File_read::make_view): Reopen descriptor.
	(File_read::do_readv): Likewise.
	* fileread.h (class File_read): Add is_descriptor_opened_ field.
	Update declarations.
	* layout.cc: Include "descriptors.h".
	(Layout::create_build_id): Use open_descriptor rather than open.
	* output.cc: Include "descriptors.h".
	(Output_file::open): Use open_descriptor rather than open.
	* archive.cc (Archive::const_iterator): Change Archive to be
	non-const.
	(Archive::begin, Archive::end): Make non-const.
	(Archive::count_members): Likewise.
	* archive.h (class Archive): Update declarations.
	* object.h (Object::read): Make non-const.
	* Makefile.am (CCFILES): Add descriptors.cc.
	(HFILES): Add descriptors.h.
	* Makefile.in: Rebuild.
This commit is contained in:
Ian Lance Taylor 2008-07-25 04:25:49 +00:00
parent e2df110677
commit 2a00e4fb8e
13 changed files with 459 additions and 45 deletions

View File

@ -1,5 +1,37 @@
2008-07-24 Ian Lance Taylor <iant@google.com>
PR 5990
* descriptors.cc: New file.
* descriptors.h: New file.
* gold-threads.h (class Hold_optional_lock): New class.
* fileread.cc: Include "descriptors.h".
(File_read::~File_read): Release descriptor rather than closing
it.
(File_read::open) [file]: Call open_descriptor rather than open.
Set is_descriptor_opened_.
(File_read::open) [memory]: Assert that descriptor is not open.
(File_read::reopen_descriptor): New function.
(File_read::release): Release descriptor.
(File_read::do_read): Make non-const. Reopen descriptor.
(File_read::read): Make non-const.
(File_read::make_view): Reopen descriptor.
(File_read::do_readv): Likewise.
* fileread.h (class File_read): Add is_descriptor_opened_ field.
Update declarations.
* layout.cc: Include "descriptors.h".
(Layout::create_build_id): Use open_descriptor rather than open.
* output.cc: Include "descriptors.h".
(Output_file::open): Use open_descriptor rather than open.
* archive.cc (Archive::const_iterator): Change Archive to be
non-const.
(Archive::begin, Archive::end): Make non-const.
(Archive::count_members): Likewise.
* archive.h (class Archive): Update declarations.
* object.h (Object::read): Make non-const.
* Makefile.am (CCFILES): Add descriptors.cc.
(HFILES): Add descriptors.h.
* Makefile.in: Rebuild.
PR 6716
* gold.h: Always include <clocale>. Add Solaris workarounds
following code in binutils/sysdep.h.

View File

@ -36,6 +36,7 @@ CCFILES = \
copy-relocs.cc \
cref.cc \
defstd.cc \
descriptors.cc \
dirsearch.cc \
dynobj.cc \
dwarf_reader.cc \
@ -74,6 +75,7 @@ HFILES = \
cref.h \
defstd.h \
dirsearch.h \
descriptors.h \
dynobj.h \
dwarf_reader.h \
ehframe.h \

View File

@ -76,16 +76,17 @@ libgold_a_AR = $(AR) $(ARFLAGS)
libgold_a_LIBADD =
am__objects_1 = archive.$(OBJEXT) binary.$(OBJEXT) common.$(OBJEXT) \
compressed_output.$(OBJEXT) copy-relocs.$(OBJEXT) \
cref.$(OBJEXT) defstd.$(OBJEXT) dirsearch.$(OBJEXT) \
dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) ehframe.$(OBJEXT) \
errors.$(OBJEXT) expression.$(OBJEXT) fileread.$(OBJEXT) \
gold.$(OBJEXT) gold-threads.$(OBJEXT) layout.$(OBJEXT) \
mapfile.$(OBJEXT) merge.$(OBJEXT) object.$(OBJEXT) \
options.$(OBJEXT) output.$(OBJEXT) parameters.$(OBJEXT) \
readsyms.$(OBJEXT) reduced_debug_output.$(OBJEXT) \
reloc.$(OBJEXT) resolve.$(OBJEXT) script-sections.$(OBJEXT) \
script.$(OBJEXT) stringpool.$(OBJEXT) symtab.$(OBJEXT) \
target-select.$(OBJEXT) version.$(OBJEXT) workqueue.$(OBJEXT) \
cref.$(OBJEXT) defstd.$(OBJEXT) descriptors.$(OBJEXT) \
dirsearch.$(OBJEXT) dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) \
ehframe.$(OBJEXT) errors.$(OBJEXT) expression.$(OBJEXT) \
fileread.$(OBJEXT) gold.$(OBJEXT) gold-threads.$(OBJEXT) \
layout.$(OBJEXT) mapfile.$(OBJEXT) merge.$(OBJEXT) \
object.$(OBJEXT) options.$(OBJEXT) output.$(OBJEXT) \
parameters.$(OBJEXT) readsyms.$(OBJEXT) \
reduced_debug_output.$(OBJEXT) reloc.$(OBJEXT) \
resolve.$(OBJEXT) script-sections.$(OBJEXT) script.$(OBJEXT) \
stringpool.$(OBJEXT) symtab.$(OBJEXT) target-select.$(OBJEXT) \
version.$(OBJEXT) workqueue.$(OBJEXT) \
workqueue-threads.$(OBJEXT)
am__objects_2 =
am__objects_3 = yyscript.$(OBJEXT)
@ -318,6 +319,7 @@ CCFILES = \
copy-relocs.cc \
cref.cc \
defstd.cc \
descriptors.cc \
dirsearch.cc \
dynobj.cc \
dwarf_reader.cc \
@ -356,6 +358,7 @@ HFILES = \
cref.h \
defstd.h \
dirsearch.h \
descriptors.h \
dynobj.h \
dwarf_reader.h \
ehframe.h \
@ -528,6 +531,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copy-relocs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cref.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defstd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/descriptors.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirsearch.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynobj.Po@am__quote@

View File

@ -384,7 +384,7 @@ class Archive::const_iterator
off_t size;
};
const_iterator(const Archive* archive, off_t off)
const_iterator(Archive* archive, off_t off)
: archive_(archive), off_(off)
{ this->read_next_header(); }
@ -431,7 +431,7 @@ class Archive::const_iterator
read_next_header();
// The underlying archive.
const Archive* archive_;
Archive* archive_;
// The current offset in the file.
off_t off_;
// The current archive header.
@ -481,7 +481,7 @@ Archive::const_iterator::read_next_header()
// Initial iterator.
Archive::const_iterator
Archive::begin() const
Archive::begin()
{
return Archive::const_iterator(this, sarmag);
}
@ -489,7 +489,7 @@ Archive::begin() const
// Final iterator.
Archive::const_iterator
Archive::end() const
Archive::end()
{
return Archive::const_iterator(this, this->input_file_->file().filesize());
}
@ -515,7 +515,7 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
// reports.
size_t
Archive::count_members() const
Archive::count_members()
{
size_t ret = 0;
for (Archive::const_iterator p = this->begin();

View File

@ -133,7 +133,7 @@ class Archive
// Return the number of members in the archive.
size_t
count_members() const;
count_members();
private:
Archive(const Archive&);
@ -175,10 +175,10 @@ class Archive
class const_iterator;
const_iterator
begin() const;
begin();
const_iterator
end() const;
end();
friend class const_iterator;

211
gold/descriptors.cc Normal file
View File

@ -0,0 +1,211 @@
// descriptors.cc -- manage file descriptors for gold
// Copyright 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
#include "gold.h"
#include <cerrno>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
#include "parameters.h"
#include "gold-threads.h"
#include "descriptors.h"
namespace gold
{
// Class Descriptors.
// The default for limit_ is meant to simply be large. It gets
// adjusted downward if we run out of file descriptors.
Descriptors::Descriptors()
: lock_(NULL), open_descriptors_(), stack_top_(-1), current_(0),
limit_(8192 - 16)
{
this->open_descriptors_.reserve(128);
}
// Open a file.
int
Descriptors::open(int descriptor, const char* name, int flags, int mode)
{
// We don't initialize this until we are called, because we can't
// initialize a Lock until we have parsed the options to find out
// whether we are running with threads. We can be called before
// options are valid when reading a linker script.
if (this->lock_ == NULL)
{
if (parameters->options_valid())
this->lock_ = new Lock();
else
gold_assert(descriptor < 0);
}
if (descriptor >= 0)
{
Hold_lock hl(*this->lock_);
gold_assert(static_cast<size_t>(descriptor)
< this->open_descriptors_.size());
Open_descriptor* pod = &this->open_descriptors_[descriptor];
if (pod->name == name
|| (pod->name != NULL && strcmp(pod->name, name) == 0))
{
gold_assert(!pod->inuse);
pod->inuse = true;
return descriptor;
}
}
while (true)
{
int new_descriptor = ::open(name, flags, mode);
if (new_descriptor < 0
&& errno != ENFILE
&& errno != EMFILE)
{
if (descriptor >= 0 && errno == ENOENT)
{
{
Hold_lock hl(*this->lock_);
gold_error(_("file %s was removed during the link"),
this->open_descriptors_[descriptor].name);
}
errno = ENOENT;
}
return new_descriptor;
}
if (new_descriptor >= 0)
{
Hold_optional_lock hl(this->lock_);
if (static_cast<size_t>(new_descriptor)
>= this->open_descriptors_.size())
this->open_descriptors_.resize(new_descriptor + 64);
Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
pod->name = name;
pod->stack_next = -1;
pod->inuse = true;
pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
++this->current_;
if (this->current_ >= this->limit_)
this->close_some_descriptor();
return new_descriptor;
}
// We ran out of file descriptors.
{
Hold_optional_lock hl(this->lock_);
this->limit_ = this->current_ - 16;
if (this->limit_ < 8)
this->limit_ = 8;
if (!this->close_some_descriptor())
gold_fatal(_("out of file descriptors and couldn't close any"));
}
}
}
// Release a descriptor.
void
Descriptors::release(int descriptor, bool permanent)
{
Hold_optional_lock hl(this->lock_);
gold_assert(descriptor >= 0
&& (static_cast<size_t>(descriptor)
< this->open_descriptors_.size()));
Open_descriptor* pod = &this->open_descriptors_[descriptor];
if (permanent
|| (this->current_ > this->limit_ && !pod->is_write))
{
if (::close(descriptor) < 0)
gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
pod->name = NULL;
--this->current_;
}
else
{
pod->inuse = false;
if (!pod->is_write)
{
pod->stack_next = this->stack_top_;
this->stack_top_ = descriptor;
}
}
}
// Close some descriptor. The lock is held when this is called. We
// close the descriptor on the top of the free stack. Note that this
// is the opposite of an LRU algorithm--we close the most recently
// used descriptor. That is because the linker tends to cycle through
// all the files; after we release a file, we are unlikely to need it
// again until we have looked at all the other files. Return true if
// we closed a descriptor.
bool
Descriptors::close_some_descriptor()
{
int last = -1;
int i = this->stack_top_;
while (i >= 0)
{
gold_assert(static_cast<size_t>(i) < this->open_descriptors_.size());
Open_descriptor* pod = &this->open_descriptors_[i];
if (!pod->inuse && !pod->is_write)
{
if (::close(i) < 0)
gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
--this->current_;
pod->name = NULL;
if (last < 0)
this->stack_top_ = pod->stack_next;
else
this->open_descriptors_[last].stack_next = pod->stack_next;
return true;
}
last = i;
i = pod->stack_next;
}
// We couldn't find any descriptors to close. This is weird but not
// necessarily an error.
return false;
}
// The single global variable which manages descriptors.
Descriptors descriptors;
} // End namespace gold.

105
gold/descriptors.h Normal file
View File

@ -0,0 +1,105 @@
// descriptors.h -- manage file descriptors for gold -*- C++ -*-
// Copyright 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
#ifndef GOLD_DESCRIPTORS_H
#define GOLD_DESCRIPTORS_H
#include <vector>
namespace gold
{
class Lock;
// This class manages file descriptors for gold.
class Descriptors
{
public:
Descriptors();
// Get a file descriptor for a file. The DESCRIPTOR parameter is
// the descriptor the last time the file was used; this will be -1
// if this is the first time the file is being opened. The NAME,
// FLAGS, and MODE parameters are as for ::open. NAME must be in
// permanent storage. This returns the descriptor to use, which may
// or may not be the same as DESCRIPTOR. If there is an error
// opening the file, this will return -1 with errno set
// appropriately.
int
open(int descriptor, const char* name, int flags, int mode = 0);
// Release the file descriptor DESCRIPTOR. If PERMANENT is true, it
// will be closed, and the caller may not reopen it. If PERMANENT
// is false this doesn't necessarily close the descriptor, but it
// makes it available to be closed; the descriptor must not be used
// again except as an argument to Descriptor::open.
void
release(int descriptor, bool permanent);
private:
// Information kept for a descriptor.
struct Open_descriptor
{
// File name currently associated with descriptor. This is empty
// if none.
const char* name;
// Index of next descriptor on stack of released descriptors.
int stack_next;
// Whether the descriptor is currently in use.
bool inuse;
// Whether this is a write descriptor.
bool is_write;
};
bool
close_some_descriptor();
// We need to lock before accessing any fields.
Lock* lock_;
// Information for descriptors.
std::vector<Open_descriptor> open_descriptors_;
// Top of stack.
int stack_top_;
// The current number of file descriptors open.
int current_;
// The maximum number of file descriptors we open.
int limit_;
};
// File descriptors are a centralized data structure, and we use a
// global variable rather than passing the data structure into every
// routine that does file I/O.
extern Descriptors descriptors;
inline int
open_descriptor(int descriptor, const char* name, int flags, int mode = 0)
{ return descriptors.open(descriptor, name, flags, mode); }
inline void
release_descriptor(int descriptor, bool permanent)
{ descriptors.release(descriptor, permanent); }
} // End namespace gold.
#endif // !defined(GOLD_DESCRIPTORS_H)

View File

@ -36,6 +36,7 @@
#include "dirsearch.h"
#include "target.h"
#include "binary.h"
#include "descriptors.h"
#include "fileread.h"
namespace gold
@ -83,18 +84,14 @@ unsigned long long File_read::total_mapped_bytes;
unsigned long long File_read::current_mapped_bytes;
unsigned long long File_read::maximum_mapped_bytes;
// The File_read class is designed to support file descriptor caching,
// but this is not currently implemented.
File_read::~File_read()
{
gold_assert(this->token_.is_writable());
if (this->descriptor_ >= 0)
if (this->is_descriptor_opened_)
{
if (close(this->descriptor_) < 0)
gold_warning(_("close of %s failed: %s"),
this->name_.c_str(), strerror(errno));
release_descriptor(this->descriptor_, true);
this->descriptor_ = -1;
this->is_descriptor_opened_ = false;
}
this->name_.clear();
this->clear_views(true);
@ -107,13 +104,16 @@ File_read::open(const Task* task, const std::string& name)
{
gold_assert(this->token_.is_writable()
&& this->descriptor_ < 0
&& !this->is_descriptor_opened_
&& this->name_.empty());
this->name_ = name;
this->descriptor_ = ::open(this->name_.c_str(), O_RDONLY);
this->descriptor_ = open_descriptor(-1, this->name_.c_str(),
O_RDONLY);
if (this->descriptor_ >= 0)
{
this->is_descriptor_opened_ = true;
struct stat s;
if (::fstat(this->descriptor_, &s) < 0)
gold_error(_("%s: fstat failed: %s"),
@ -136,6 +136,7 @@ File_read::open(const Task* task, const std::string& name,
{
gold_assert(this->token_.is_writable()
&& this->descriptor_ < 0
&& !this->is_descriptor_opened_
&& this->name_.empty());
this->name_ = name;
this->contents_ = contents;
@ -144,6 +145,22 @@ File_read::open(const Task* task, const std::string& name,
return true;
}
// Reopen a descriptor if necessary.
void
File_read::reopen_descriptor()
{
if (!this->is_descriptor_opened_)
{
this->descriptor_ = open_descriptor(this->descriptor_,
this->name_.c_str(),
O_RDONLY);
if (this->descriptor_ < 0)
gold_fatal(_("could not reopen file %s"), this->name_.c_str());
this->is_descriptor_opened_ = true;
}
}
// Release the file. This is called when we are done with the file in
// a Task.
@ -159,9 +176,17 @@ File_read::release()
File_read::maximum_mapped_bytes = File_read::current_mapped_bytes;
// Only clear views if there is only one attached object. Otherwise
// we waste time trying to clear cached archive views.
// we waste time trying to clear cached archive views. Similarly
// for releasing the descriptor.
if (this->object_count_ <= 1)
this->clear_views(false);
{
this->clear_views(false);
if (this->is_descriptor_opened_)
{
release_descriptor(this->descriptor_, false);
this->is_descriptor_opened_ = false;
}
}
this->released_ = true;
}
@ -243,7 +268,7 @@ File_read::find_view(off_t start, section_size_type size,
// the buffer at P.
void
File_read::do_read(off_t start, section_size_type size, void* p) const
File_read::do_read(off_t start, section_size_type size, void* p)
{
ssize_t bytes;
if (this->contents_ != NULL)
@ -257,6 +282,7 @@ File_read::do_read(off_t start, section_size_type size, void* p) const
}
else
{
this->reopen_descriptor();
bytes = ::pread(this->descriptor_, p, size, start);
if (static_cast<section_size_type>(bytes) == size)
return;
@ -279,7 +305,7 @@ File_read::do_read(off_t start, section_size_type size, void* p) const
// Read data from the file.
void
File_read::read(off_t start, section_size_type size, void* p) const
File_read::read(off_t start, section_size_type size, void* p)
{
const File_read::View* pv = this->find_view(start, size, -1U, NULL);
if (pv != NULL)
@ -349,6 +375,7 @@ File_read::make_view(off_t start, section_size_type size,
}
else
{
this->reopen_descriptor();
void* p = ::mmap(NULL, psize, PROT_READ, MAP_PRIVATE,
this->descriptor_, poff);
if (p == MAP_FAILED)
@ -493,6 +520,8 @@ File_read::do_readv(off_t base, const Read_multiple& rm, size_t start,
last_offset = i_entry.file_offset + i_entry.size;
}
this->reopen_descriptor();
gold_assert(iov_index < sizeof iov / sizeof iov[0]);
if (::lseek(this->descriptor_, base + first_offset, SEEK_SET) < 0)

View File

@ -40,17 +40,16 @@ class Input_file_argument;
class Dirsearch;
class File_view;
// File_read manages a file descriptor for a file we are reading. We
// close file descriptors if we run out of them, so this class reopens
// the file as needed.
// File_read manages a file descriptor and mappings for a file we are
// reading.
class File_read
{
public:
File_read()
: name_(), descriptor_(-1), object_count_(0), size_(0), token_(false),
views_(), saved_views_(), contents_(NULL), mapped_bytes_(0),
released_(true)
: name_(), descriptor_(-1), is_descriptor_opened_(false), object_count_(0),
size_(0), token_(false), views_(), saved_views_(), contents_(NULL),
mapped_bytes_(0), released_(true)
{ }
~File_read();
@ -82,12 +81,12 @@ class File_read
{ --this->object_count_; }
// Lock the file for exclusive access within a particular Task::run
// execution. This means that the descriptor can not be closed.
// This routine may only be called when the workqueue lock is held.
// execution. This routine may only be called when the workqueue
// lock is held.
void
lock(const Task* t);
// Unlock the descriptor, permitting it to be closed if necessary.
// Unlock the file.
void
unlock(const Task* t);
@ -133,7 +132,7 @@ class File_read
// Read data from the file into the buffer P starting at file offset
// START for SIZE bytes.
void
read(off_t start, section_size_type size, void* p) const;
read(off_t start, section_size_type size, void* p);
// Return a lasting view into the file starting at file offset START
// for SIZE bytes. This is allocated with new, and the caller is
@ -296,6 +295,10 @@ class File_read
// A simple list of Views.
typedef std::list<View*> Saved_views;
// Open the descriptor if necessary.
void
reopen_descriptor();
// Find a view into the file.
View*
find_view(off_t start, section_size_type size, unsigned int byteshift,
@ -303,7 +306,7 @@ class File_read
// Read data from the file into a buffer.
void
do_read(off_t start, section_size_type size, void* p) const;
do_read(off_t start, section_size_type size, void* p);
// Add a view.
void
@ -347,6 +350,8 @@ class File_read
std::string name_;
// File descriptor.
int descriptor_;
// Whether we have regained the descriptor after releasing the file.
bool is_descriptor_opened_;
// The number of objects associated with this file. This will be
// more than 1 in the case of an archive.
int object_count_;

View File

@ -107,6 +107,29 @@ class Hold_lock
Lock& lock_;
};
class Hold_optional_lock
{
public:
Hold_optional_lock(Lock* lock)
: lock_(lock)
{
if (this->lock_ != NULL)
this->lock_->acquire();
}
~Hold_optional_lock()
{
if (this->lock_ != NULL)
this->lock_->release();
}
private:
Hold_optional_lock(const Hold_optional_lock&);
Hold_optional_lock& operator=(const Hold_optional_lock&);
Lock* lock_;
};
// The interface for the implementation of a condition variable.
class Condvar_impl

View File

@ -45,6 +45,7 @@
#include "compressed_output.h"
#include "reduced_debug_output.h"
#include "reloc.h"
#include "descriptors.h"
#include "layout.h"
namespace gold
@ -1507,14 +1508,14 @@ Layout::create_build_id()
char buffer[uuidsz];
memset(buffer, 0, uuidsz);
int descriptor = ::open("/dev/urandom", O_RDONLY);
int descriptor = open_descriptor(-1, "/dev/urandom", O_RDONLY);
if (descriptor < 0)
gold_error(_("--build-id=uuid failed: could not open /dev/urandom: %s"),
strerror(errno));
else
{
ssize_t got = ::read(descriptor, buffer, uuidsz);
::close(descriptor);
release_descriptor(descriptor, true);
if (got < 0)
gold_error(_("/dev/urandom: read failed: %s"), strerror(errno));
else if (static_cast<size_t>(got) != uuidsz)

View File

@ -410,7 +410,7 @@ class Object
// Read data from the underlying file.
void
read(off_t start, section_size_type size, void* p) const
read(off_t start, section_size_type size, void* p)
{ this->input_file()->file().read(start + this->offset_, size, p); }
// Read multiple data from the underlying file.

View File

@ -37,6 +37,7 @@
#include "symtab.h"
#include "reloc.h"
#include "merge.h"
#include "descriptors.h"
#include "output.h"
// Some BSD systems still use MAP_ANON instead of MAP_ANONYMOUS
@ -3321,7 +3322,8 @@ Output_file::open(off_t file_size)
unlink_if_ordinary(this->name_);
int mode = parameters->options().relocatable() ? 0666 : 0777;
int o = ::open(this->name_, O_RDWR | O_CREAT | O_TRUNC, mode);
int o = open_descriptor(-1, this->name_, O_RDWR | O_CREAT | O_TRUNC,
mode);
if (o < 0)
gold_fatal(_("%s: open: %s"), this->name_, strerror(errno));
this->o_ = o;