From 51dee2fec3afad5e6fc9f78b8c1d8486ebf3a334 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 2 Oct 2007 21:24:41 +0000 Subject: From Craig Silverstein: add support for searching for input files named in linker scripts. --- gold/fileread.cc | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- gold/options.cc | 4 +++- gold/options.h | 29 +++++++++++++++++++++++++++-- gold/readsyms.cc | 2 +- gold/script.cc | 22 ++++++++-------------- 5 files changed, 85 insertions(+), 21 deletions(-) diff --git a/gold/fileread.cc b/gold/fileread.cc index d87f773..9e6cd90 100644 --- a/gold/fileread.cc +++ b/gold/fileread.cc @@ -27,6 +27,7 @@ #include #include #include +#include "filenames.h" #include "options.h" #include "dirsearch.h" @@ -371,21 +372,38 @@ Input_file::Input_file(const char* name, const unsigned char* contents, : file_() { this->input_argument_ = - new Input_file_argument(name, false, Position_dependent_options()); + new Input_file_argument(name, false, "", Position_dependent_options()); bool ok = file_.open(name, contents, size); gold_assert(ok); } // 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; or +// B) input_argument_->extra_search_path() is not empty. +// In both cases, we look in extra_search_path + library_path to find +// the file location, rather than the current directory. + void Input_file::open(const General_options& options, const Dirsearch& dirpath) { std::string name; - if (!this->input_argument_->is_lib()) + + // Case 1: name is an absolute file, just try to open it + // Case 2: name is relative but is_lib is false and extra_search_path + // is empty + if (IS_ABSOLUTE_PATH (this->input_argument_->name()) + || (!this->input_argument_->is_lib() + && this->input_argument_->extra_search_path() == NULL)) name = this->input_argument_->name(); - else + + // Case 3: is_lib is true + else if (this->input_argument_->is_lib()) { + // We don't yet support extra_search_path with -l. + gold_assert(this->input_argument_->extra_search_path() == NULL); std::string n1("lib"); n1 += this->input_argument_->name(); std::string n2; @@ -405,6 +423,31 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath) } } + // Case 4: extra_search_path is not empty + else + { + gold_assert(this->input_argument_->extra_search_path() != NULL); + + // First, check extra_search_path. + name = this->input_argument_->extra_search_path(); + if (!IS_DIR_SEPARATOR (name[name.length() - 1])) + name += '/'; + name += this->input_argument_->name(); + struct stat dummy_stat; + if (::stat(name.c_str(), &dummy_stat) < 0) + { + // extra_search_path failed, so check the normal search-path. + name = dirpath.find(this->input_argument_->name(), ""); + if (name.empty()) + { + fprintf(stderr, _("%s: cannot find %s\n"), program_name, + this->input_argument_->name()); + gold_exit(false); + } + } + } + + // Now that we've figured out where the file lives, try to open it. if (!this->file_.open(name)) { fprintf(stderr, _("%s: cannot open %s: %s\n"), program_name, diff --git a/gold/options.cc b/gold/options.cc index 577c604..4df21b0 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -285,6 +285,8 @@ options::Command_line_options::options[] = NULL, ONE_DASH, &General_options::set_shared), GENERAL_NOARG('\0', "static", N_("Do not link against shared libraries"), NULL, ONE_DASH, &General_options::set_static), + GENERAL_ARG('\0', "sysroot", N_("Currently ignored"), NULL, TWO_DASHES, + &General_options::ignore), POSDEP_NOARG('\0', "as-needed", N_("Only set DT_NEEDED for dynamic libs if used"), NULL, TWO_DASHES, &Position_dependent_options::set_as_needed), @@ -550,7 +552,7 @@ Command_line::apply_option(const options::One_option& opt, void Command_line::add_file(const char* name, bool is_lib) { - Input_file_argument file(name, is_lib, this->position_options_); + Input_file_argument file(name, is_lib, "", this->position_options_); this->inputs_.add_file(file); } diff --git a/gold/options.h b/gold/options.h index 85a7aee..3b7c051 100644 --- a/gold/options.h +++ b/gold/options.h @@ -244,13 +244,23 @@ class Position_dependent_options class Input_file_argument { public: + // name: file name or library name + // is_lib: true if name is a library name: that is, emits the leading + // "lib" and trailing ".so"/".a" from the name + // extra_search_path: an extra directory to look for the file, prior + // to checking the normal library search path. If this is "", + // then no extra directory is added. + // options: The position dependent options at this point in the + // command line, such as --group. Input_file_argument() - : name_(), is_lib_(false), options_() + : name_(), is_lib_(false), extra_search_path_(""), options_() { } Input_file_argument(const char* name, bool is_lib, + const char* extra_search_path, const Position_dependent_options& options) - : name_(name), is_lib_(is_lib), options_(options) + : name_(name), is_lib_(is_lib), extra_search_path_(extra_search_path), + options_(options) { } const char* @@ -265,12 +275,27 @@ class Input_file_argument is_lib() const { return this->is_lib_; } + const char* + extra_search_path() const + { + return (this->extra_search_path_.empty() + ? NULL + : this->extra_search_path_.c_str()); + } + + // Return whether this file may require a search using the -L + // options. + bool + may_need_search() const + { return this->is_lib_ || !this->extra_search_path_.empty(); } + private: // We use std::string, not const char*, here for convenience when // using script files, so that we do not have to preserve the string // in that case. std::string name_; bool is_lib_; + std::string extra_search_path_; Position_dependent_options options_; }; diff --git a/gold/readsyms.cc b/gold/readsyms.cc index bbeb425..87e4fa4 100644 --- a/gold/readsyms.cc +++ b/gold/readsyms.cc @@ -52,7 +52,7 @@ Task::Is_runnable_type Read_symbols::is_runnable(Workqueue*) { if (this->input_argument_->is_file() - && this->input_argument_->file().is_lib() + && this->input_argument_->file().may_need_search() && this->dirpath_.token().is_blocked()) return IS_BLOCKED; diff --git a/gold/script.cc b/gold/script.cc index 950fa15..b003add 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -1166,20 +1166,14 @@ extern "C" void script_add_file(void* closurev, const char* name) { Parser_closure* closure = static_cast(closurev); - std::string absname; - if (name[0] == '/') - { - absname = name; - } - else - { - // Prepend `dirname closure->filename()` to make the path absolute. - char *slash = strrchr(closure->filename(), '/'); - absname.assign(closure->filename(), - slash ? slash - closure->filename() + 1 : 0); - absname += name; - } - Input_file_argument file(absname.c_str(), false, closure->position_dependent_options()); + // In addition to checking the normal library search path, we also + // want to check in the script-directory. + const char *slash = strrchr(closure->filename(), '/'); + std::string script_directory(closure->filename(), + slash ? slash - closure->filename() + 1 : 0); + Input_file_argument file(name, false, + slash ? script_directory.c_str() : ".", + closure->position_dependent_options()); closure->inputs()->add_file(file); } -- cgit v1.1