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