12a6b7db3Sskrll // descriptors.cc -- manage file descriptors for gold
22a6b7db3Sskrll
3*f22f0ef4Schristos // Copyright (C) 2008-2022 Free Software Foundation, Inc.
42a6b7db3Sskrll // Written by Ian Lance Taylor <iant@google.com>.
52a6b7db3Sskrll
62a6b7db3Sskrll // This file is part of gold.
72a6b7db3Sskrll
82a6b7db3Sskrll // This program is free software; you can redistribute it and/or modify
92a6b7db3Sskrll // it under the terms of the GNU General Public License as published by
102a6b7db3Sskrll // the Free Software Foundation; either version 3 of the License, or
112a6b7db3Sskrll // (at your option) any later version.
122a6b7db3Sskrll
132a6b7db3Sskrll // This program is distributed in the hope that it will be useful,
142a6b7db3Sskrll // but WITHOUT ANY WARRANTY; without even the implied warranty of
152a6b7db3Sskrll // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162a6b7db3Sskrll // GNU General Public License for more details.
172a6b7db3Sskrll
182a6b7db3Sskrll // You should have received a copy of the GNU General Public License
192a6b7db3Sskrll // along with this program; if not, write to the Free Software
202a6b7db3Sskrll // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
212a6b7db3Sskrll // MA 02110-1301, USA.
222a6b7db3Sskrll
232a6b7db3Sskrll #include "gold.h"
242a6b7db3Sskrll
252a6b7db3Sskrll #include <cerrno>
26b578a859Schristos #include <cstdio>
272a6b7db3Sskrll #include <cstring>
282a6b7db3Sskrll #include <fcntl.h>
29f7172901Schristos #include <string>
302a6b7db3Sskrll #include <unistd.h>
312a6b7db3Sskrll
325ba6b03cSchristos #include "debug.h"
332a6b7db3Sskrll #include "parameters.h"
34b578a859Schristos #include "options.h"
352a6b7db3Sskrll #include "gold-threads.h"
362a6b7db3Sskrll #include "descriptors.h"
37b578a859Schristos #include "binary-io.h"
38b578a859Schristos
3905caefcfSchristos // O_CLOEXEC is only available on newer systems.
4005caefcfSchristos #ifndef O_CLOEXEC
4105caefcfSchristos #define O_CLOEXEC 0
4205caefcfSchristos #endif
4305caefcfSchristos
44b578a859Schristos // Very old systems may not define FD_CLOEXEC.
45b578a859Schristos #ifndef FD_CLOEXEC
46b578a859Schristos #define FD_CLOEXEC 1
47b578a859Schristos #endif
48b578a859Schristos
4905caefcfSchristos static inline void
set_close_on_exec(int fd ATTRIBUTE_UNUSED)5005caefcfSchristos set_close_on_exec(int fd ATTRIBUTE_UNUSED)
5105caefcfSchristos {
5205caefcfSchristos // Mingw does not define F_SETFD.
5305caefcfSchristos #ifdef F_SETFD
5405caefcfSchristos fcntl(fd, F_SETFD, FD_CLOEXEC);
55b578a859Schristos #endif
5605caefcfSchristos }
572a6b7db3Sskrll
582a6b7db3Sskrll namespace gold
592a6b7db3Sskrll {
602a6b7db3Sskrll
612a6b7db3Sskrll // Class Descriptors.
622a6b7db3Sskrll
632a6b7db3Sskrll // The default for limit_ is meant to simply be large. It gets
642a6b7db3Sskrll // adjusted downward if we run out of file descriptors.
652a6b7db3Sskrll
Descriptors()662a6b7db3Sskrll Descriptors::Descriptors()
67b578a859Schristos : lock_(NULL), initialize_lock_(&this->lock_), open_descriptors_(),
68b578a859Schristos stack_top_(-1), current_(0), limit_(8192 - 16)
692a6b7db3Sskrll {
702a6b7db3Sskrll this->open_descriptors_.reserve(128);
712a6b7db3Sskrll }
722a6b7db3Sskrll
732a6b7db3Sskrll // Open a file.
742a6b7db3Sskrll
752a6b7db3Sskrll int
open(int descriptor,const char * name,int flags,int mode)762a6b7db3Sskrll Descriptors::open(int descriptor, const char* name, int flags, int mode)
772a6b7db3Sskrll {
782a6b7db3Sskrll // We don't initialize this until we are called, because we can't
792a6b7db3Sskrll // initialize a Lock until we have parsed the options to find out
802a6b7db3Sskrll // whether we are running with threads. We can be called before
812a6b7db3Sskrll // options are valid when reading a linker script.
82b578a859Schristos bool lock_initialized = this->initialize_lock_.initialize();
83b578a859Schristos
84b578a859Schristos gold_assert(lock_initialized || descriptor < 0);
852a6b7db3Sskrll
865ba6b03cSchristos if (is_debugging_enabled(DEBUG_FILES))
875ba6b03cSchristos this->limit_ = 8;
885ba6b03cSchristos
892a6b7db3Sskrll if (descriptor >= 0)
902a6b7db3Sskrll {
912a6b7db3Sskrll Hold_lock hl(*this->lock_);
922a6b7db3Sskrll
932a6b7db3Sskrll gold_assert(static_cast<size_t>(descriptor)
942a6b7db3Sskrll < this->open_descriptors_.size());
952a6b7db3Sskrll Open_descriptor* pod = &this->open_descriptors_[descriptor];
962a6b7db3Sskrll if (pod->name == name
972a6b7db3Sskrll || (pod->name != NULL && strcmp(pod->name, name) == 0))
982a6b7db3Sskrll {
992a6b7db3Sskrll gold_assert(!pod->inuse);
1002a6b7db3Sskrll pod->inuse = true;
101b578a859Schristos if (descriptor == this->stack_top_)
102b578a859Schristos {
103b578a859Schristos this->stack_top_ = pod->stack_next;
104b578a859Schristos pod->stack_next = -1;
105b578a859Schristos pod->is_on_stack = false;
106b578a859Schristos }
1075ba6b03cSchristos gold_debug(DEBUG_FILES, "Reused existing descriptor %d for \"%s\"",
1085ba6b03cSchristos descriptor, name);
1092a6b7db3Sskrll return descriptor;
1102a6b7db3Sskrll }
1112a6b7db3Sskrll }
1122a6b7db3Sskrll
1132a6b7db3Sskrll while (true)
1142a6b7db3Sskrll {
115b578a859Schristos // We always want to set the close-on-exec flag; we don't
116b578a859Schristos // require callers to pass it.
117b578a859Schristos flags |= O_CLOEXEC;
118b578a859Schristos
119b578a859Schristos // Always open the file as a binary file.
120b578a859Schristos flags |= O_BINARY;
121b578a859Schristos
1222a6b7db3Sskrll int new_descriptor = ::open(name, flags, mode);
1232a6b7db3Sskrll if (new_descriptor < 0
1242a6b7db3Sskrll && errno != ENFILE
1252a6b7db3Sskrll && errno != EMFILE)
1262a6b7db3Sskrll {
1272a6b7db3Sskrll if (descriptor >= 0 && errno == ENOENT)
1282a6b7db3Sskrll {
1292a6b7db3Sskrll {
1302a6b7db3Sskrll Hold_lock hl(*this->lock_);
1312a6b7db3Sskrll
132b578a859Schristos gold_error(_("file %s was removed during the link"), name);
1332a6b7db3Sskrll }
1342a6b7db3Sskrll
1352a6b7db3Sskrll errno = ENOENT;
1362a6b7db3Sskrll }
1372a6b7db3Sskrll
1385ba6b03cSchristos gold_debug(DEBUG_FILES, "Opened new descriptor %d for \"%s\"",
1395ba6b03cSchristos new_descriptor, name);
1402a6b7db3Sskrll return new_descriptor;
1412a6b7db3Sskrll }
1422a6b7db3Sskrll
1432a6b7db3Sskrll if (new_descriptor >= 0)
1442a6b7db3Sskrll {
145b578a859Schristos // If we have any plugins, we really do need to set the
146b578a859Schristos // close-on-exec flag, even if O_CLOEXEC is not defined.
147b578a859Schristos // FIXME: In some cases O_CLOEXEC may be defined in the
148b578a859Schristos // header file but not supported by the kernel.
149b578a859Schristos // Unfortunately there doesn't seem to be any obvious way to
150b578a859Schristos // detect that, as unknown flags passed to open are ignored.
151b578a859Schristos if (O_CLOEXEC == 0
152b578a859Schristos && parameters->options_valid()
153b578a859Schristos && parameters->options().has_plugins())
15405caefcfSchristos set_close_on_exec(new_descriptor);
155b578a859Schristos
156b578a859Schristos {
1572a6b7db3Sskrll Hold_optional_lock hl(this->lock_);
1582a6b7db3Sskrll
1592a6b7db3Sskrll if (static_cast<size_t>(new_descriptor)
1602a6b7db3Sskrll >= this->open_descriptors_.size())
1612a6b7db3Sskrll this->open_descriptors_.resize(new_descriptor + 64);
1622a6b7db3Sskrll
1632a6b7db3Sskrll Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
1642a6b7db3Sskrll pod->name = name;
1652a6b7db3Sskrll pod->stack_next = -1;
1662a6b7db3Sskrll pod->inuse = true;
1672a6b7db3Sskrll pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
168b578a859Schristos pod->is_on_stack = false;
1692a6b7db3Sskrll
1702a6b7db3Sskrll ++this->current_;
1712a6b7db3Sskrll if (this->current_ >= this->limit_)
1722a6b7db3Sskrll this->close_some_descriptor();
1732a6b7db3Sskrll
1745ba6b03cSchristos gold_debug(DEBUG_FILES, "Opened new descriptor %d for \"%s\"",
1755ba6b03cSchristos new_descriptor, name);
1762a6b7db3Sskrll return new_descriptor;
1772a6b7db3Sskrll }
178b578a859Schristos }
1792a6b7db3Sskrll
1802a6b7db3Sskrll // We ran out of file descriptors.
1812a6b7db3Sskrll {
1822a6b7db3Sskrll Hold_optional_lock hl(this->lock_);
1832a6b7db3Sskrll
1842a6b7db3Sskrll this->limit_ = this->current_ - 16;
1852a6b7db3Sskrll if (this->limit_ < 8)
1862a6b7db3Sskrll this->limit_ = 8;
1872a6b7db3Sskrll if (!this->close_some_descriptor())
1882a6b7db3Sskrll gold_fatal(_("out of file descriptors and couldn't close any"));
1892a6b7db3Sskrll }
1902a6b7db3Sskrll }
1912a6b7db3Sskrll }
1922a6b7db3Sskrll
1932a6b7db3Sskrll // Release a descriptor.
1942a6b7db3Sskrll
1952a6b7db3Sskrll void
release(int descriptor,bool permanent)1962a6b7db3Sskrll Descriptors::release(int descriptor, bool permanent)
1972a6b7db3Sskrll {
1982a6b7db3Sskrll Hold_optional_lock hl(this->lock_);
1992a6b7db3Sskrll
2002a6b7db3Sskrll gold_assert(descriptor >= 0
2012a6b7db3Sskrll && (static_cast<size_t>(descriptor)
2022a6b7db3Sskrll < this->open_descriptors_.size()));
2032a6b7db3Sskrll Open_descriptor* pod = &this->open_descriptors_[descriptor];
2042a6b7db3Sskrll
2052a6b7db3Sskrll if (permanent
2062a6b7db3Sskrll || (this->current_ > this->limit_ && !pod->is_write))
2072a6b7db3Sskrll {
2082a6b7db3Sskrll if (::close(descriptor) < 0)
2092a6b7db3Sskrll gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
2102a6b7db3Sskrll pod->name = NULL;
2112a6b7db3Sskrll --this->current_;
2122a6b7db3Sskrll }
2132a6b7db3Sskrll else
2142a6b7db3Sskrll {
2152a6b7db3Sskrll pod->inuse = false;
216b578a859Schristos if (!pod->is_write && !pod->is_on_stack)
2172a6b7db3Sskrll {
2182a6b7db3Sskrll pod->stack_next = this->stack_top_;
2192a6b7db3Sskrll this->stack_top_ = descriptor;
220b578a859Schristos pod->is_on_stack = true;
2212a6b7db3Sskrll }
2222a6b7db3Sskrll }
2235ba6b03cSchristos
2245ba6b03cSchristos gold_debug(DEBUG_FILES, "Released descriptor %d for \"%s\"",
2255ba6b03cSchristos descriptor, pod->name);
2262a6b7db3Sskrll }
2272a6b7db3Sskrll
2282a6b7db3Sskrll // Close some descriptor. The lock is held when this is called. We
2292a6b7db3Sskrll // close the descriptor on the top of the free stack. Note that this
2302a6b7db3Sskrll // is the opposite of an LRU algorithm--we close the most recently
2312a6b7db3Sskrll // used descriptor. That is because the linker tends to cycle through
2322a6b7db3Sskrll // all the files; after we release a file, we are unlikely to need it
2332a6b7db3Sskrll // again until we have looked at all the other files. Return true if
2342a6b7db3Sskrll // we closed a descriptor.
2352a6b7db3Sskrll
2362a6b7db3Sskrll bool
close_some_descriptor()2372a6b7db3Sskrll Descriptors::close_some_descriptor()
2382a6b7db3Sskrll {
2392a6b7db3Sskrll int last = -1;
2402a6b7db3Sskrll int i = this->stack_top_;
2412a6b7db3Sskrll while (i >= 0)
2422a6b7db3Sskrll {
2432a6b7db3Sskrll gold_assert(static_cast<size_t>(i) < this->open_descriptors_.size());
2442a6b7db3Sskrll Open_descriptor* pod = &this->open_descriptors_[i];
2452a6b7db3Sskrll if (!pod->inuse && !pod->is_write)
2462a6b7db3Sskrll {
2472a6b7db3Sskrll if (::close(i) < 0)
2482a6b7db3Sskrll gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
2492a6b7db3Sskrll --this->current_;
2505ba6b03cSchristos gold_debug(DEBUG_FILES, "Closed descriptor %d for \"%s\"",
2515ba6b03cSchristos i, pod->name);
2522a6b7db3Sskrll pod->name = NULL;
2532a6b7db3Sskrll if (last < 0)
2542a6b7db3Sskrll this->stack_top_ = pod->stack_next;
2552a6b7db3Sskrll else
2562a6b7db3Sskrll this->open_descriptors_[last].stack_next = pod->stack_next;
257b578a859Schristos pod->stack_next = -1;
258b578a859Schristos pod->is_on_stack = false;
2592a6b7db3Sskrll return true;
2602a6b7db3Sskrll }
2612a6b7db3Sskrll last = i;
2622a6b7db3Sskrll i = pod->stack_next;
2632a6b7db3Sskrll }
2642a6b7db3Sskrll
2652a6b7db3Sskrll // We couldn't find any descriptors to close. This is weird but not
2662a6b7db3Sskrll // necessarily an error.
2672a6b7db3Sskrll return false;
2682a6b7db3Sskrll }
2692a6b7db3Sskrll
2705ba6b03cSchristos // Close all the descriptors open for reading.
2715ba6b03cSchristos
2725ba6b03cSchristos void
close_all()2735ba6b03cSchristos Descriptors::close_all()
2745ba6b03cSchristos {
2755ba6b03cSchristos Hold_optional_lock hl(this->lock_);
2765ba6b03cSchristos
2775ba6b03cSchristos for (size_t i = 0; i < this->open_descriptors_.size(); i++)
2785ba6b03cSchristos {
2795ba6b03cSchristos Open_descriptor* pod = &this->open_descriptors_[i];
2805ba6b03cSchristos if (pod->name != NULL && !pod->inuse && !pod->is_write)
2815ba6b03cSchristos {
2825ba6b03cSchristos if (::close(i) < 0)
2835ba6b03cSchristos gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
2845ba6b03cSchristos gold_debug(DEBUG_FILES, "Closed descriptor %d for \"%s\" (close_all)",
2855ba6b03cSchristos static_cast<int>(i), pod->name);
2865ba6b03cSchristos pod->name = NULL;
2875ba6b03cSchristos pod->stack_next = -1;
2885ba6b03cSchristos pod->is_on_stack = false;
2895ba6b03cSchristos }
2905ba6b03cSchristos }
2915ba6b03cSchristos this->stack_top_ = -1;
2925ba6b03cSchristos }
2935ba6b03cSchristos
2942a6b7db3Sskrll // The single global variable which manages descriptors.
2952a6b7db3Sskrll
2962a6b7db3Sskrll Descriptors descriptors;
2972a6b7db3Sskrll
2982a6b7db3Sskrll } // End namespace gold.
299