This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gold][patch] Add a plugin callback for setting the extra search path


This patch complements the add_input_library callback by adding the
ability to set the extra search path used by it.

The use case for it is when we have two copies of libc. One being
bitcode and the other ELF. We want to use the bitcode one with the
plugin so that LTO can do as much simplification as possible. The
issues is that when looking for libc again because of a call to the
add_input_library callback, gold will find an archive with bitcode
files and not know what to do with it.

With this patch the users can hide the ELF libc from the -L options
and just have the plugin pass the correct directory in the extra
search path.


include/
2010-06-18  Rafael Espindola  <espindola@google.com>

	* plugin-api.h (ld_plugin_set_extra_library_path): New.
	(ld_plugin_tag): Add LDPT_SET_EXTRA_LIBRARY_PATH.
	(ld_plugin_tv): Add tv_set_extra_library_path.

gold/
2010-06-18  Rafael Espindola  <espindola@google.com>

	* fileread.cc (Input_file::find_fie): New
	(Input_file::open): Use Input_file::find_fie.
	* fileread.h (Input_file::find_fie): New
	* plugin.cc (set_extra_library_path): New.
	(Plugin::load): Add set_extra_library_path to the transfer vector.
	(Plugin_manager::set_extra_library_path): New.
	(Plugin_manager::add_input_file): Use the extra search path if set.
	(set_extra_library_path(): New.
	* plugin.h (Plugin_manager): Adde set_extra_library_path and
	extra_search_path_.

Cheers,
-- 
Rafael Ãvila de EspÃndola
diff --git a/gold/fileread.cc b/gold/fileread.cc
index 10e1dec..eb59278 100644
--- a/gold/fileread.cc
+++ b/gold/fileread.cc
@@ -841,18 +841,8 @@ File_read::get_mtime()
 #endif
 }
 
-// Open the file.
-
-// If the filename is not absolute, we assume it is in the current
-// directory *except* when:
-//    A) input_argument_->is_lib() is true;
-//    B) input_argument_->is_searched_file() is true; or
-//    C) input_argument_->extra_search_path() is not empty.
-// In each, we look in extra_search_path + library_path to find
-// the file location, rather than the current directory.
-
 bool
-Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
+Input_file::find_file(const Dirsearch& dirpath, int *pindex, std::string *namep)
 {
   std::string name;
 
@@ -866,13 +856,13 @@ Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
     {
       name = this->input_argument_->name();
       this->found_name_ = name;
+      *namep = name;
+      return true;
     }
   // Case 3: is_lib is true or is_searched_file is true
   else if (this->input_argument_->is_lib()
 	   || this->input_argument_->is_searched_file())
     {
-      // We don't yet support extra_search_path with -l.
-      gold_assert(this->input_argument_->extra_search_path() == NULL);
       std::string n1, n2;
       if (this->input_argument_->is_lib())
 	{
@@ -889,6 +879,34 @@ Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
 	}
       else
 	n1 = this->input_argument_->name();
+
+      if (this->input_argument_->extra_search_path())
+	{
+	  // First, check extra_search_path.
+	  std::string prefix = this->input_argument_->extra_search_path();
+	  if (!IS_DIR_SEPARATOR (prefix[prefix.length() - 1]))
+	    prefix += '/';
+
+	  name = prefix + n1;
+	  struct stat dummy_stat;
+	  if (*pindex <= 0 && ::stat(name.c_str(), &dummy_stat) >= 0)
+	    {
+	      this->found_name_ = this->input_argument_->name();
+	      *namep = name;
+	      return true;
+	    }
+
+	  name = prefix + n2;
+	  if (!n2.empty() && *pindex <= 0
+	      && ::stat(name.c_str(), &dummy_stat) >= 0)
+	    {
+	      this->found_name_ = this->input_argument_->name();
+	      *namep = name;
+	      return true;
+	    }
+	}
+
+      // It is not in the extra_search_path.
       name = dirpath.find(n1, n2, &this->is_in_sysroot_, pindex);
       if (name.empty())
 	{
@@ -901,6 +919,8 @@ Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
 	this->found_name_ = n1;
       else
 	this->found_name_ = n2;
+      *namep = name;
+      return true;
     }
   // Case 4: extra_search_path is not empty
   else
@@ -930,7 +950,27 @@ Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
 	  *pindex = index + 1;
         }
       this->found_name_ = this->input_argument_->name();
+      *namep = name;
+      return true;
     }
+}
+
+// Open the file.
+
+// If the filename is not absolute, we assume it is in the current
+// directory *except* when:
+//    A) input_argument_->is_lib() is true;
+//    B) input_argument_->is_searched_file() is true; or
+//    C) input_argument_->extra_search_path() is not empty.
+// In each, we look in extra_search_path + library_path to find
+// the file location, rather than the current directory.
+
+bool
+Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
+{
+  std::string name;
+  if (!this->find_file(dirpath, pindex, &name))
+    return false;
 
   // Now that we've figured out where the file lives, try to open it.
 
diff --git a/gold/fileread.h b/gold/fileread.h
index a81b5fe..cecd8a5 100644
--- a/gold/fileread.h
+++ b/gold/fileread.h
@@ -569,6 +569,10 @@ class Input_file
   Input_file(const Input_file&);
   Input_file& operator=(const Input_file&);
 
+  // Find a file.
+  bool
+  find_file(const Dirsearch& dirpath, int *pindex, std::string *namep);
+
   // Open a binary file.
   bool
   open_binary(const Task* task, const std::string& name);
diff --git a/gold/plugin.cc b/gold/plugin.cc
index 1c33b12..c9e55ef 100644
--- a/gold/plugin.cc
+++ b/gold/plugin.cc
@@ -81,6 +81,9 @@ static enum ld_plugin_status
 add_input_library(const char *pathname);
 
 static enum ld_plugin_status
+set_extra_library_path(const char *path);
+
+static enum ld_plugin_status
 message(int level, const char *format, ...);
 
 };
@@ -127,7 +130,7 @@ Plugin::load()
   sscanf(ver, "%d.%d", &major, &minor);
 
   // Allocate and populate a transfer vector.
-  const int tv_fixed_size = 15;
+  const int tv_fixed_size = 16;
   int tv_size = this->args_.size() + tv_fixed_size;
   ld_plugin_tv *tv = new ld_plugin_tv[tv_size];
 
@@ -202,6 +205,10 @@ Plugin::load()
   tv[i].tv_u.tv_add_input_library = add_input_library;
 
   ++i;
+  tv[i].tv_tag = LDPT_SET_EXTRA_LIBRARY_PATH;
+  tv[i].tv_u.tv_set_extra_library_path = set_extra_library_path;
+
+  ++i;
   tv[i].tv_tag = LDPT_NULL;
   tv[i].tv_u.tv_val = 0;
 
@@ -418,6 +425,15 @@ Plugin_manager::release_input_file(unsigned int handle)
   return LDPS_OK;
 }
 
+// Add a new library path.
+
+ld_plugin_status
+Plugin_manager::set_extra_library_path(const char *path)
+{
+  this->extra_search_path_ = std::string(path);
+  return LDPS_OK;
+}
+
 // Add a new input file.
 
 ld_plugin_status
@@ -427,7 +443,11 @@ Plugin_manager::add_input_file(const char *pathname, bool is_lib)
                            (is_lib
                             ? Input_file_argument::INPUT_FILE_TYPE_LIBRARY
                             : Input_file_argument::INPUT_FILE_TYPE_FILE),
-                           "", false, this->options_);
+                           (is_lib
+                            ? this->extra_search_path_.c_str()
+                            : ""),
+                           false,
+                           this->options_);
   Input_argument* input_argument = new Input_argument(file);
   Task_token* next_blocker = new Task_token(true);
   next_blocker->add_blocker();
@@ -1038,6 +1058,16 @@ add_input_library(const char *pathname)
   return parameters->options().plugins()->add_input_file(pathname, true);
 }
 
+// Set the extra library path to be used by libraries added via
+// add_input_library
+
+static enum ld_plugin_status
+set_extra_library_path(const char *path)
+{
+  gold_assert(parameters->options().has_plugins());
+  return parameters->options().plugins()->set_extra_library_path(path);
+}
+
 // Issue a diagnostic message from a plugin.
 
 static enum ld_plugin_status
diff --git a/gold/plugin.h b/gold/plugin.h
index 99e6d95..87e1f88 100644
--- a/gold/plugin.h
+++ b/gold/plugin.h
@@ -127,7 +127,7 @@ class Plugin_manager
       plugin_input_file_(), in_replacement_phase_(false),
       options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
       symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
-      this_blocker_(NULL)
+      this_blocker_(NULL), extra_search_path_()
   { this->current_ = plugins_.end(); }
 
   ~Plugin_manager();
@@ -232,6 +232,10 @@ class Plugin_manager
   ld_plugin_status
   add_input_file(const char *pathname, bool is_lib);
 
+  // Set the extra library path.
+  ld_plugin_status
+  set_extra_library_path(const char *path);
+
   // Return TRUE if we are in the replacement phase.
   bool
   in_replacement_phase() const
@@ -275,6 +279,10 @@ class Plugin_manager
   Dirsearch* dirpath_;
   Mapfile* mapfile_;
   Task_token* this_blocker_;
+
+  // an extra directory to look for the libraries passed by
+  // add_input_library.
+  std::string extra_search_path_;
 };
 
 
diff --git a/include/plugin-api.h b/include/plugin-api.h
index 55cfe25..a0cf5f4 100644
--- a/include/plugin-api.h
+++ b/include/plugin-api.h
@@ -228,6 +228,12 @@ typedef
 enum ld_plugin_status
 (*ld_plugin_add_input_library) (const char *libname);
 
+/* The linker's interface for adding a library path that should be searched.  */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_set_extra_library_path) (const char *path);
+
 /* The linker's interface for issuing a warning or error message.  */
 
 typedef
@@ -261,7 +267,8 @@ enum ld_plugin_tag
   LDPT_GET_INPUT_FILE,
   LDPT_RELEASE_INPUT_FILE,
   LDPT_ADD_INPUT_LIBRARY,
-  LDPT_OUTPUT_NAME
+  LDPT_OUTPUT_NAME,
+  LDPT_SET_EXTRA_LIBRARY_PATH
 };
 
 /* The plugin transfer vector.  */
@@ -283,6 +290,7 @@ struct ld_plugin_tv
     ld_plugin_get_input_file tv_get_input_file;
     ld_plugin_release_input_file tv_release_input_file;
     ld_plugin_add_input_library tv_add_input_library;
+    ld_plugin_set_extra_library_path tv_set_extra_library_path;
   } tv_u;
 };
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]