gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gold / dirsearch.cc
index 41a2660a88fdff4fd5e43669cb1e0f417f4620cc..e8c9b1203c8e80809d587ad99af85434c75379d7 100644 (file)
@@ -1,12 +1,37 @@
 // dirsearch.cc -- directory searching for gold
 
+// Copyright (C) 2006-2020 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 <sys/types.h>
+#include <sys/stat.h>
 #include <dirent.h>
 
+#include "debug.h"
 #include "gold-threads.h"
+#include "options.h"
+#include "workqueue.h"
 #include "dirsearch.h"
 
 namespace
@@ -42,14 +67,12 @@ Dir_cache::read_files()
   DIR* d = opendir(this->dirname_);
   if (d == NULL)
     {
-      // We ignore directories which do not exist.
-      if (errno == ENOENT)
-       return;
-
-      char *s = NULL;
-      if (asprintf(&s, _("can not read directory %s"), this->dirname_) < 0)
-       gold::gold_nomem();
-      gold::gold_fatal(s, true);
+      // We ignore directories which do not exist or are actually file
+      // names.
+      if (errno != ENOENT && errno != ENOTDIR)
+       gold::gold_error(_("%s: can not read directory: %s"),
+                        this->dirname_, strerror(errno));
+      return;
     }
 
   dirent* de;
@@ -57,7 +80,8 @@ Dir_cache::read_files()
     this->files_.insert(std::string(de->d_name));
 
   if (closedir(d) != 0)
-    gold::gold_fatal("closedir failed", true);
+    gold::gold_warning("%s: closedir failed: %s", this->dirname_,
+                      strerror(errno));
 }
 
 bool
@@ -78,7 +102,7 @@ class Dir_caches
     : lock_(), caches_()
   { }
 
-  ~Dir_caches();
+  ~Dir_caches() ATTRIBUTE_UNUSED;
 
   // Add a cache for a directory.
   void add(const char*);
@@ -124,7 +148,7 @@ Dir_caches::add(const char* dirname)
 
     std::pair<const char*, Dir_cache*> v(dirname, cache);
     std::pair<Cache_hash::iterator, bool> p = this->caches_.insert(v);
-    assert(p.second);
+    gold_assert(p.second);
   }
 }
 
@@ -139,7 +163,7 @@ Dir_caches::lookup(const char* dirname) const
 
 // The caches.
 
-Dir_caches caches;
+Dir_caches* caches;
 
 // A Task to read the directory.
 
@@ -150,11 +174,18 @@ class Dir_cache_task : public gold::Task
     : dir_(dir), token_(token)
   { }
 
-  Is_runnable_type is_runnable(gold::Workqueue*);
+  gold::Task_token*
+  is_runnable();
 
-  gold::Task_locker* locks(gold::Workqueue*);
+  void
+  locks(gold::Task_locker*);
 
-  void run(gold::Workqueue*);
+  void
+  run(gold::Workqueue*);
+
+  std::string
+  get_name() const
+  { return std::string("Dir_cache_task ") + this->dir_; }
 
  private:
   const char* dir_;
@@ -163,19 +194,19 @@ class Dir_cache_task : public gold::Task
 
 // We can always run the task to read the directory.
 
-gold::Task::Is_runnable_type
-Dir_cache_task::is_runnable(gold::Workqueue*)
+gold::Task_token*
+Dir_cache_task::is_runnable()
 {
-  return IS_RUNNABLE;
+  return NULL;
 }
 
 // Return the locks to hold.  We use a blocker lock to prevent file
 // lookups from starting until the directory contents have been read.
 
-gold::Task_locker*
-Dir_cache_task::locks(gold::Workqueue* workqueue)
+void
+Dir_cache_task::locks(gold::Task_locker* tl)
 {
-  return new gold::Task_locker_block(this->token_, workqueue);
+  tl->add(this, &this->token_);
 }
 
 // Run the task--read the directory contents.
@@ -183,7 +214,7 @@ Dir_cache_task::locks(gold::Workqueue* workqueue)
 void
 Dir_cache_task::run(gold::Workqueue*)
 {
-  caches.add(this->dir_);
+  caches->add(this->dir_);
 }
 
 }
@@ -191,46 +222,84 @@ Dir_cache_task::run(gold::Workqueue*)
 namespace gold
 {
 
-Dirsearch::Dirsearch()
-  : directories_(), token_()
-{
-}
+// Initialize.
 
 void
-Dirsearch::add(Workqueue* workqueue, const char* d)
+Dirsearch::initialize(Workqueue* workqueue,
+                     const General_options::Dir_list* directories)
 {
-  this->directories_.push_back(d);
-  this->token_.add_blocker();
-  workqueue->queue(new Dir_cache_task(d, this->token_));
-}
-
-void
-Dirsearch::add(Workqueue* workqueue, const General_options::Dir_list& list)
-{
-  for (General_options::Dir_list::const_iterator p = list.begin();
-       p != list.end();
+  gold_assert(caches == NULL);
+  caches = new Dir_caches;
+  this->directories_ = directories;
+  this->token_.add_blockers(directories->size());
+  for (General_options::Dir_list::const_iterator p = directories->begin();
+       p != directories->end();
        ++p)
-    this->add(workqueue, *p);
+    workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_));
 }
 
+// Search for a file.  NOTE: we only log failed file-lookup attempts
+// here.  Successfully lookups will eventually get logged in
+// File_read::open.
+
 std::string
-Dirsearch::find(const std::string& n1, const std::string& n2) const
+Dirsearch::find(const std::vector<std::string>& names,
+               bool* is_in_sysroot, int* pindex,
+               std::string *found_name) const
 {
-  assert(!this->token_.is_blocked());
+  gold_assert(!this->token_.is_blocked());
+  gold_assert(*pindex >= 0);
 
-  for (std::list<const char*>::const_iterator p = this->directories_.begin();
-       p != this->directories_.end();
-       ++p)
+  for (unsigned int i = static_cast<unsigned int>(*pindex);
+       i < this->directories_->size();
+       ++i)
     {
-      Dir_cache* pdc = caches.lookup(*p);
-      assert(pdc != NULL);
-      if (pdc->find(n1))
-       return std::string(*p) + '/' + n1;
-      if (!n2.empty() && pdc->find(n2))
-       return std::string(*p) + '/' + n2;
+      const Search_directory* p = &this->directories_->at(i);
+      Dir_cache* pdc = caches->lookup(p->name().c_str());
+      gold_assert(pdc != NULL);
+      for (std::vector<std::string>::const_iterator n = names.begin();
+          n != names.end();
+          ++n)
+       {
+         if (pdc->find(*n))
+           {
+             *is_in_sysroot = p->is_in_sysroot();
+             *pindex = i;
+             *found_name = *n;
+             return p->name() + '/' + *n;
+           }
+         else
+           gold_debug(DEBUG_FILES, "Attempt to open %s/%s failed",
+                      p->name().c_str(), (*n).c_str());
+       }
     }
 
+  *pindex = -2;
   return std::string();
 }
 
+// Search for a file in a directory list.  This is a low-level function and
+// therefore can be used before options and parameters are set.
+
+std::string
+Dirsearch::find_file_in_dir_list(const std::string& name,
+                                 const General_options::Dir_list& directories,
+                                 const std::string& extra_search_dir)
+{
+  struct stat buf;
+  std::string extra_name = extra_search_dir + '/' + name;
+
+  if (stat(extra_name.c_str(), &buf) == 0)
+    return extra_name;
+  for (General_options::Dir_list::const_iterator dir = directories.begin();
+       dir != directories.end();
+       ++dir)
+    {
+      std::string full_name = dir->name() + '/' + name;
+      if (stat(full_name.c_str(), &buf) == 0)
+        return full_name;
+    }
+  return name;
+}
+
 } // End namespace gold.
This page took 0.026144 seconds and 4 git commands to generate.