Full support for --sysroot.
authorIan Lance Taylor <iant@google.com>
Thu, 4 Oct 2007 05:49:04 +0000 (05:49 +0000)
committerIan Lance Taylor <iant@google.com>
Thu, 4 Oct 2007 05:49:04 +0000 (05:49 +0000)
18 files changed:
gold/Makefile.am
gold/Makefile.in
gold/config.in
gold/configure
gold/configure.ac
gold/dirsearch.cc
gold/dirsearch.h
gold/fileread.cc
gold/fileread.h
gold/layout.cc
gold/main.cc
gold/options.cc
gold/options.h
gold/parameters.cc
gold/parameters.h
gold/script.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in

index bb5d3f6..f61dac3 100644 (file)
@@ -13,8 +13,11 @@ AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CXXFLAGS)
 INCLUDES = -D_GNU_SOURCE \
        -I$(srcdir) -I$(srcdir)/../include -I$(srcdir)/../elfcpp \
        -DLOCALEDIR="\"$(datadir)/locale\"" \
+       -DBINDIR="\"$(bindir)\"" -DTOOLBINDIR="\"$(tooldir)/bin\"" \
        @INCINTL@
 
+LIBIBERTY = ../libiberty/libiberty.a
+
 AM_YFLAGS = -d
 
 noinst_PROGRAMS = ld-new
@@ -87,8 +90,8 @@ ALL_TARGETOBJS = \
 libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
 
 sources_var = main.cc
-deps_var = $(TARGETOBJS) libgold.a $(LIBINTL_DEP)
-ldadd_var = $(TARGETOBJS) libgold.a $(LIBINTL)
+deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP)
+ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL)
 
 ld_new_SOURCES = $(sources_var)
 ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS)
index 168849e..a2e4100 100644 (file)
@@ -88,9 +88,10 @@ am__objects_4 = main.$(OBJEXT)
 am_ld_new_OBJECTS = $(am__objects_4)
 ld_new_OBJECTS = $(am_ld_new_OBJECTS)
 am__DEPENDENCIES_1 =
-am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) libgold.a \
-       $(am__DEPENDENCIES_1)
-am__DEPENDENCIES_3 = @LIBOBJS@
+am__DEPENDENCIES_2 = ../libiberty/libiberty.a
+am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) libgold.a \
+       $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_4 = @LIBOBJS@
 am__ld1_SOURCES_DIST = main.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_OBJECTS = $(am__objects_4)
 ld1_OBJECTS = $(am_ld1_OBJECTS)
@@ -265,8 +266,10 @@ AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CXXFLAGS)
 INCLUDES = -D_GNU_SOURCE \
        -I$(srcdir) -I$(srcdir)/../include -I$(srcdir)/../elfcpp \
        -DLOCALEDIR="\"$(datadir)/locale\"" \
+       -DBINDIR="\"$(bindir)\"" -DTOOLBINDIR="\"$(tooldir)/bin\"" \
        @INCINTL@
 
+LIBIBERTY = ../libiberty/libiberty.a
 AM_YFLAGS = -d
 noinst_LIBRARIES = libgold.a
 CCFILES = \
@@ -334,8 +337,8 @@ ALL_TARGETOBJS = \
 
 libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES)
 sources_var = main.cc
-deps_var = $(TARGETOBJS) libgold.a $(LIBINTL_DEP)
-ldadd_var = $(TARGETOBJS) libgold.a $(LIBINTL)
+deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP)
+ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL)
 ld_new_SOURCES = $(sources_var)
 ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS)
 ld_new_LDADD = $(ldadd_var) $(LIBOBJS)
index bbdf051..46d67e5 100644 (file)
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
+/* System root for target files */
+#undef TARGET_SYSTEM_ROOT
+
+/* Whether the system root can be relocated */
+#undef TARGET_SYSTEM_ROOT_RELOCATABLE
+
 /* Version number of package */
 #undef VERSION
 
index 7bf0364..f7192cd 100755 (executable)
@@ -867,6 +867,11 @@ Optional Features:
   --enable-maintainer-mode  enable make rules and dependencies not useful
                          (and sometimes confusing) to the casual installer
 
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-sysroot=DIR    search for usr/lib et al within DIR
+
 Some influential environment variables:
   CC          C compiler command
   CFLAGS      C compiler flags
@@ -1842,6 +1847,44 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
           ac_config_headers="$ac_config_headers config.h:config.in"
 
 
+
+# Check whether --with-sysroot or --without-sysroot was given.
+if test "${with_sysroot+set}" = set; then
+  withval="$with_sysroot"
+  sysroot=$withval
+else
+  sysroot=no
+fi;
+
+if test "$sysroot" = "yes"; then
+  sysroot='${exec_prefix}/${target_alias}/sys-root'
+elif test "$sysroot" = "no"; then
+  sysroot=
+fi
+
+sysroot_relocatable=0
+if test -n "$sysroot"; then
+  case "sysroot" in
+    "${prefix}" | "${prefix}/"* | \
+    "${exec_prefix}" | "${exec_prefix}/"* | \
+    '${prefix}' | '${prefix}/'*| \
+    '${exec_prefix}' | '${exec_prefix}/'*)
+      sysroot_relocatable=1
+      ;;
+  esac
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define TARGET_SYSTEM_ROOT "$sysroot"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define TARGET_SYSTEM_ROOT_RELOCATABLE $sysroot_relocatable
+_ACEOF
+
+
 # Check whether --enable-targets or --disable-targets was given.
 if test "${enable_targets+set}" = set; then
   enableval="$enable_targets"
index 4efe83d..d01ab91 100644 (file)
@@ -10,6 +10,33 @@ AM_INIT_AUTOMAKE(gold, 0.1)
 
 AM_CONFIG_HEADER(config.h:config.in)
 
+AC_ARG_WITH(sysroot,
+[  --with-sysroot[=DIR]    search for usr/lib et al within DIR],
+[sysroot=$withval], [sysroot=no])
+
+if test "$sysroot" = "yes"; then
+  sysroot='${exec_prefix}/${target_alias}/sys-root'
+elif test "$sysroot" = "no"; then
+  sysroot=
+fi
+
+sysroot_relocatable=0
+if test -n "$sysroot"; then
+  case "sysroot" in
+    "${prefix}" | "${prefix}/"* | \
+    "${exec_prefix}" | "${exec_prefix}/"* | \
+    '${prefix}' | '${prefix}/'*| \
+    '${exec_prefix}' | '${exec_prefix}/'*)
+      sysroot_relocatable=1
+      ;;
+  esac
+fi
+
+AC_DEFINE_UNQUOTED(TARGET_SYSTEM_ROOT, "$sysroot",
+  [System root for target files])
+AC_DEFINE_UNQUOTED(TARGET_SYSTEM_ROOT_RELOCATABLE, $sysroot_relocatable,
+  [Whether the system root can be relocated])
+
 AC_ARG_ENABLE([targets],
 [  --enable-targets        alternative target configurations],
 [case "${enableval}" in
index 8965903..6dea53d 100644 (file)
@@ -211,43 +211,43 @@ Dir_cache_task::run(gold::Workqueue*)
 namespace gold
 {
 
-Dirsearch::Dirsearch()
-  : directories_(), token_()
-{
-}
-
 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();
+  this->directories_ = directories;
+  for (General_options::Dir_list::const_iterator p = directories->begin();
+       p != directories->end();
        ++p)
-    this->add(workqueue, *p);
+    {
+      this->token_.add_blocker();
+      workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_));
+    }
 }
 
 std::string
-Dirsearch::find(const std::string& n1, const std::string& n2) const
+Dirsearch::find(const std::string& n1, const std::string& n2,
+               bool *is_in_sysroot) const
 {
   gold_assert(!this->token_.is_blocked());
 
-  for (std::list<const char*>::const_iterator p = this->directories_.begin();
-       p != this->directories_.end();
+  for (General_options::Dir_list::const_iterator p =
+        this->directories_->begin();
+       p != this->directories_->end();
        ++p)
     {
-      Dir_cache* pdc = caches.lookup(*p);
+      Dir_cache* pdc = caches.lookup(p->name().c_str());
       gold_assert(pdc != NULL);
       if (pdc->find(n1))
-       return std::string(*p) + '/' + n1;
+       {
+         *is_in_sysroot = p->is_in_sysroot();
+         return p->name() + '/' + n1;
+       }
       if (!n2.empty() && pdc->find(n2))
-       return std::string(*p) + '/' + n2;
+       {
+         *is_in_sysroot = p->is_in_sysroot();
+         return p->name() + '/' + n2;
+       }
     }
 
   return std::string();
index 8b5a91e..c1af843 100644 (file)
@@ -39,22 +39,21 @@ class General_options;
 class Dirsearch
 {
  public:
-  Dirsearch();
+  Dirsearch()
+    : directories_(NULL), token_()
+  { }
 
-  // Add a directory to the search path.
+  // Set the list of directories to search.
   void
-  add(Workqueue*, const char*);
-
-  // Add a list of directories to the search path.
-  void
-  add(Workqueue*, const General_options::Dir_list&);
+  initialize(Workqueue*, const General_options::Dir_list*);
 
   // Search for a file, giving one or two names to search for (the
   // second one may be empty).  Return a full path name for the file,
   // or the empty string if it could not be found.  This may only be
-  // called if the token is not blocked.
+  // called if the token is not blocked.  Set *IS_IN_SYSROOT if the
+  // file was found in a directory which is in the sysroot.
   std::string
-  find(const std::string&, const std::string& n2 = std::string()) const;
+  find(const std::string&, const std::string& n2, bool *is_in_sysroot) const;
 
   // Return a reference to the blocker token which controls access.
   const Task_token&
@@ -67,7 +66,7 @@ class Dirsearch
   Dirsearch& operator=(const Dirsearch&);
 
   // Directories to search.
-  std::list<const char*> directories_;
+  const General_options::Dir_list* directories_;
   // Blocker token to control access from tasks.
   Task_token token_;
 };
index 9e6cd90..1bbd841 100644 (file)
@@ -414,10 +414,10 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath)
          n2 = n1 + ".a";
          n1 += ".so";
        }
-      name = dirpath.find(n1, n2);
+      name = dirpath.find(n1, n2, &this->is_in_sysroot_);
       if (name.empty())
        {
-         fprintf(stderr, _("%s: cannot find %s\n"), program_name,
+         fprintf(stderr, _("%s: cannot find -l%s\n"), program_name,
                  this->input_argument_->name());
          gold_exit(false);
        }
@@ -437,7 +437,8 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath)
       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(), "");
+          name = dirpath.find(this->input_argument_->name(), "",
+                             &this->is_in_sysroot_);
           if (name.empty())
             {
               fprintf(stderr, _("%s: cannot find %s\n"), program_name,
index cda5d9c..abeb28e 100644 (file)
@@ -260,7 +260,7 @@ class Input_file
 {
  public:
   Input_file(const Input_file_argument* input_argument)
-    : input_argument_(input_argument), file_()
+    : input_argument_(input_argument), file_(), is_in_sysroot_(false)
   { }
 
   // Create an input file with the contents already provided.  This is
@@ -292,12 +292,21 @@ class Input_file
   file()
   { return this->file_; }
 
+  // Whether we found the file in a directory in the system root.
+  bool
+  is_in_sysroot() const
+  { return this->is_in_sysroot_; }
+
  private:
   Input_file(const Input_file&);
   Input_file& operator=(const Input_file&);
 
+  // The argument from the command line.
   const Input_file_argument* input_argument_;
+  // The file after we open it.
   File_read file_;
+  // Whether we found the file in a directory in the system root.
+  bool is_in_sysroot_;
 };
 
 } // end namespace gold
index 9dad4b0..e878456 100644 (file)
@@ -1309,18 +1309,18 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
            ++p)
         {
           if (rpath_val.empty())
-            rpath_val = *p;
+            rpath_val = p->name();
           else
             {
               // Eliminate duplicates.
               General_options::Dir_list::const_iterator q;
               for (q = rpath.begin(); q != p; ++q)
-                if (strcmp(*q, *p) == 0)
+               if (q->name() == p->name())
                   break;
               if (q == p)
                 {
                   rpath_val += ':';
-                  rpath_val += *p;
+                  rpath_val += p->name();
                 }
             }
         }
index e1135e9..ccd958d 100644 (file)
@@ -65,7 +65,7 @@ main(int argc, char** argv)
 
   // Get the search path from the -L options.
   Dirsearch search_path;
-  search_path.add(&workqueue, command_line.options().search_path());
+  search_path.initialize(&workqueue, &command_line.options().search_path());
 
   // Queue up the first set of tasks.
   queue_initial_tasks(command_line.options(), search_path,
index 4df21b0..f49b9f5 100644 (file)
 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
 // MA 02110-1301, USA.
 
+#include "gold.h"
+
 #include <iostream>
+#include <sys/stat.h>
+#include "filenames.h"
+#include "libiberty.h"
 
-#include "gold.h"
 #include "options.h"
 
 namespace gold
@@ -216,6 +220,51 @@ help(int, char**, char*, gold::Command_line*)
   return 0;
 }
 
+// If the default sysroot is relocatable, try relocating it based on
+// the prefix FROM.
+
+char*
+get_relative_sysroot(const char* from)
+{
+  char* path = make_relative_prefix(gold::program_name, from,
+                                   TARGET_SYSTEM_ROOT);
+  if (path != NULL)
+    {
+      struct stat s;
+      if (::stat(path, &s) == 0 && S_ISDIR(s.st_mode))
+       return path;
+      free(path);
+    }
+
+  return NULL;
+}
+
+// Return the default sysroot.  This is set by the --with-sysroot
+// option to configure.
+
+std::string
+get_default_sysroot()
+{
+  const char* sysroot = TARGET_SYSTEM_ROOT;
+  if (*sysroot == '\0')
+    return "";
+
+  if (TARGET_SYSTEM_ROOT_RELOCATABLE)
+    {
+      char* path = get_relative_sysroot (BINDIR);
+      if (path == NULL)
+       path = get_relative_sysroot (TOOLBINDIR);
+      if (path != NULL)
+       {
+         std::string ret = path;
+         free(path);
+         return ret;
+       }
+    }
+
+  return sysroot;
+}
+
 } // End anonymous namespace.
 
 namespace gold
@@ -285,8 +334,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),
+  GENERAL_ARG('\0', "sysroot", N_("Set target system root directory"),
+             N_("--sysroot DIR"), TWO_DASHES, &General_options::set_sysroot),
   POSDEP_NOARG('\0', "as-needed",
               N_("Only set DT_NEEDED for dynamic libs if used"),
               NULL, TWO_DASHES, &Position_dependent_options::set_as_needed),
@@ -321,7 +370,8 @@ General_options::General_options()
     rpath_(),
     rpath_link_(),
     is_shared_(false),
-    is_static_(false)
+    is_static_(false),
+    sysroot_()
 {
 }
 
@@ -334,6 +384,66 @@ Position_dependent_options::Position_dependent_options()
 {
 }
 
+// Add the sysroot, if any, to the search paths.
+
+void
+General_options::add_sysroot()
+{
+  if (this->sysroot_.empty())
+    {
+      this->sysroot_ = get_default_sysroot();
+      if (this->sysroot_.empty())
+       return;
+    }
+
+  const char* sysroot = this->sysroot_.c_str();
+  char* canonical_sysroot = lrealpath(sysroot);
+
+  for (Dir_list::iterator p = this->search_path_.begin();
+       p != this->search_path_.end();
+       ++p)
+    p->add_sysroot(sysroot, canonical_sysroot);
+
+  free(canonical_sysroot);
+}
+
+// Search_directory methods.
+
+// This is called if we have a sysroot.  Apply the sysroot if
+// appropriate.  Record whether the directory is in the sysroot.
+
+void
+Search_directory::add_sysroot(const char* sysroot,
+                             const char* canonical_sysroot)
+{
+  gold_assert(*sysroot != '\0');
+  if (this->put_in_sysroot_)
+    {
+      if (!IS_DIR_SEPARATOR(this->name_[0])
+         && !IS_DIR_SEPARATOR(sysroot[strlen(sysroot) - 1]))
+       this->name_ = '/' + this->name_;
+      this->name_ = sysroot + this->name_;
+      this->is_in_sysroot_ = true;
+    }
+  else
+    {
+      // Check whether this entry is in the sysroot.  To do this
+      // correctly, we need to use canonical names.  Otherwise we will
+      // get confused by the ../../.. paths that gcc tends to use.
+      char* canonical_name = lrealpath(this->name_.c_str());
+      int canonical_name_len = strlen(canonical_name);
+      int canonical_sysroot_len = strlen(canonical_sysroot);
+      if (canonical_name_len > canonical_sysroot_len
+         && IS_DIR_SEPARATOR(canonical_name[canonical_sysroot_len]))
+       {
+         canonical_name[canonical_sysroot_len] = '\0';
+         if (FILENAME_CMP(canonical_name, canonical_sysroot) == 0)
+           this->is_in_sysroot_ = true;
+       }
+      free(canonical_name);
+    }
+}
+
 // Input_arguments methods.
 
 // Add a file to the list.
@@ -414,8 +524,12 @@ Command_line::process(int argc, char** argv)
       char first = opt[0];
       int skiparg = 0;
       char* arg = strchr(opt, '=');
+      bool argument_with_equals = arg != NULL;
       if (arg != NULL)
-       *arg = '\0';
+       {
+         *arg = '\0';
+         ++arg;
+       }
       else if (i + 1 < argc)
        {
          arg = argv[i + 1];
@@ -438,6 +552,8 @@ Command_line::process(int argc, char** argv)
                {
                  if (!options[j].takes_argument())
                    {
+                     if (argument_with_equals)
+                       this->usage(_("unexpected argument"), argv[i]);
                      arg = NULL;
                      skiparg = 0;
                    }
@@ -517,8 +633,10 @@ Command_line::process(int argc, char** argv)
     }
 
   // FIXME: We should only do this when configured in native mode.
-  this->options_.add_to_search_path("/lib");
-  this->options_.add_to_search_path("/usr/lib");
+  this->options_.add_to_search_path_with_sysroot("/lib");
+  this->options_.add_to_search_path_with_sysroot("/usr/lib");
+
+  this->options_.add_sysroot();
 }
 
 // Apply a command line option.
index 3b7c051..159e7b2 100644 (file)
@@ -50,6 +50,50 @@ struct One_option;
 
 } // End namespace gold::options.
 
+// A directory to search.  For each directory we record whether it is
+// in the sysroot.  We need to know this so that, if a linker script
+// is found within the sysroot, we will apply the sysroot to any files
+// named by that script.
+
+class Search_directory
+{
+ public:
+  // We need a default constructor because we put this in a
+  // std::vector.
+  Search_directory()
+    : name_(NULL), put_in_sysroot_(false), is_in_sysroot_(false)
+  { }
+
+  // This is the usual constructor.
+  Search_directory(const char* name, bool put_in_sysroot)
+    : name_(name), put_in_sysroot_(put_in_sysroot), is_in_sysroot_(false)
+  { gold_assert(!this->name_.empty()); }
+
+  // This is called if we have a sysroot.  The sysroot is prefixed to
+  // any entries for which put_in_sysroot_ is true.  is_in_sysroot_ is
+  // set to true for any enries which are in the sysroot (this will
+  // naturally include any entries for which put_in_sysroot_ is true).
+  // SYSROOT is the sysroot, CANONICAL_SYSROOT is the result of
+  // passing SYSROOT to lrealpath.
+  void
+  add_sysroot(const char* sysroot, const char* canonical_sysroot);
+
+  // Get the directory name.
+  const std::string&
+  name() const
+  { return this->name_; }
+
+  // Return whether this directory is in the sysroot.
+  bool
+  is_in_sysroot() const
+  { return this->is_in_sysroot_; }
+
+ private:
+  std::string name_;
+  bool put_in_sysroot_;
+  bool is_in_sysroot_;
+};
+
 // The position independent options which apply to the whole link.
 // There are a lot of them.
 
@@ -69,7 +113,7 @@ class General_options
   { return this->dynamic_linker_; }
 
   // -L: Library search path.
-  typedef std::vector<const char*> Dir_list;
+  typedef std::vector<Search_directory> Dir_list;
 
   const Dir_list&
   search_path() const
@@ -115,6 +159,11 @@ class General_options
   is_static() const
   { return this->is_static_; }
 
+  // --sysroot: The system root of a cross-linker.
+  const std::string&
+  sysroot() const
+  { return this->sysroot_; }
+
  private:
   // Don't copy this structure.
   General_options(const General_options&);
@@ -133,7 +182,11 @@ class General_options
 
   void
   add_to_search_path(const char* arg)
-  { this->search_path_.push_back(arg); }
+  { this->search_path_.push_back(Search_directory(arg, false)); }
+
+  void
+  add_to_search_path_with_sysroot(const char* arg)
+  { this->search_path_.push_back(Search_directory(arg, true)); }
 
   void
   set_optimization_level(const char* arg)
@@ -153,11 +206,11 @@ class General_options
 
   void
   add_to_rpath(const char* arg)
-  { this->rpath_.push_back(arg); }
+  { this->rpath_.push_back(Search_directory(arg, false)); }
 
   void
   add_to_rpath_link(const char* arg)
-  { this->rpath_link_.push_back(arg); }
+  { this->rpath_link_.push_back(Search_directory(arg, false)); }
 
   void
   set_shared()
@@ -168,9 +221,17 @@ class General_options
   { this->is_static_ = true; }
 
   void
+  set_sysroot(const char* arg)
+  { this->sysroot_ = arg; }
+
+  void
   ignore(const char*)
   { }
 
+  // Apply any sysroot to the directory lists.
+  void
+  add_sysroot();
+
   bool export_dynamic_;
   const char* dynamic_linker_;
   Dir_list search_path_;
@@ -182,6 +243,7 @@ class General_options
   Dir_list rpath_link_;
   bool is_shared_;
   bool is_static_;
+  std::string sysroot_;
 };
 
 // The current state of the position dependent options.
@@ -251,7 +313,7 @@ class Input_file_argument
   //         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.
+  //         command line, such as --whole-archive.
   Input_file_argument()
     : name_(), is_lib_(false), extra_search_path_(""), options_()
   { }
index 0c38ef7..3c7cf28 100644 (file)
@@ -31,7 +31,8 @@ namespace gold
 // Initialize the parameters from the options.
 
 Parameters::Parameters(const General_options* options)
-  : is_doing_static_link_valid_(false), doing_static_link_(false),
+  : sysroot_(options->sysroot()),
+    is_doing_static_link_valid_(false), doing_static_link_(false),
     is_size_and_endian_valid_(false), size_(0), is_big_endian_(false),
     optimization_level_(options->optimization_level())
 {
index 2a21607..a150981 100644 (file)
@@ -56,6 +56,12 @@ class Parameters
   output_is_object() const
   { return this->output_file_type_ == OUTPUT_OBJECT; }
 
+  // The target system root directory.  This is NULL if there isn't
+  // one.
+  const std::string&
+  sysroot() const
+  { return this->sysroot_; }
+
   // Whether we are doing a static link--a link in which none of the
   // input files are shared libraries.  This is only known after we
   // have seen all the input files.
@@ -110,6 +116,9 @@ class Parameters
 
   // The type of the output file.
   Output_file_type output_file_type_;
+  // The target system root directory.
+  std::string sysroot_;
+  
   // Whether the doing_static_link_ field is valid.
   bool is_doing_static_link_valid_;
   // Whether we are doing a static link.
index b003add..365cedf 100644 (file)
 #include <vector>
 #include <cstdio>
 #include <cstdlib>
+#include "filenames.h"
 
 #include "options.h"
 #include "fileread.h"
 #include "workqueue.h"
 #include "readsyms.h"
+#include "parameters.h"
 #include "yyscript.h"
 #include "script.h"
 #include "script-c.h"
@@ -827,10 +829,10 @@ class Parser_closure
  public:
   Parser_closure(const char* filename,
                 const Position_dependent_options& posdep_options,
-                bool in_group,
+                bool in_group, bool is_in_sysroot,
                 const Lex::Token_sequence* tokens)
     : filename_(filename), posdep_options_(posdep_options),
-      in_group_(in_group), tokens_(tokens),
+      in_group_(in_group), is_in_sysroot_(is_in_sysroot), tokens_(tokens),
       next_token_index_(0), inputs_(NULL)
   { }
 
@@ -850,6 +852,12 @@ class Parser_closure
   in_group() const
   { return this->in_group_; }
 
+  // Return whether this script was found using a directory in the
+  // sysroot.
+  bool
+  is_in_sysroot() const
+  { return this->is_in_sysroot_; }
+
   // Whether we are at the end of the token list.
   bool
   at_eof() const
@@ -886,6 +894,8 @@ class Parser_closure
   Position_dependent_options posdep_options_;
   // Whether we are currently in a --start-group/--end-group.
   bool in_group_;
+  // Whether the script was found in a sysrooted directory.
+  bool is_in_sysroot_;
 
   // The tokens to be returned by the lexer.
   const Lex::Token_sequence* tokens_;
@@ -915,6 +925,7 @@ read_input_script(Workqueue* workqueue, const General_options& options,
   Parser_closure closure(input_file->filename().c_str(),
                         input_argument->file().options(),
                         input_group != NULL,
+                        input_file->is_in_sysroot(),
                         &lex.tokens());
 
   if (yyparse(&closure) != 0)
@@ -1166,14 +1177,39 @@ extern "C" void
 script_add_file(void* closurev, const char* name)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
-  // 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());
+
+  // If this is an absolute path, and we found the script in the
+  // sysroot, then we want to prepend the sysroot to the file name.
+  // For example, this is how we handle a cross link to the x86_64
+  // libc.so, which refers to /lib/libc.so.6.
+  std::string name_string;
+  const char* extra_search_path = ".";
+  std::string script_directory;
+  if (IS_ABSOLUTE_PATH (name))
+    {
+      if (closure->is_in_sysroot())
+       {
+         const std::string& sysroot(parameters->sysroot());
+         gold_assert(!sysroot.empty());
+         name_string = sysroot + name;
+         name = name_string.c_str();
+       }
+    }
+  else
+    {
+      // In addition to checking the normal library search path, we
+      // also want to check in the script-directory.
+      const char *slash = strrchr(closure->filename(), '/');
+      if (slash != NULL)
+       {
+         script_directory.assign(closure->filename(),
+                                 slash - closure->filename() + 1);
+         extra_search_path = script_directory.c_str();
+       }
+    }
+
+  Input_file_argument file(name, false, extra_search_path,
+                          closure->position_dependent_options());
   closure->inputs()->add_file(file);
 }
 
index 6054d66..b2f56dc 100644 (file)
@@ -60,7 +60,9 @@ TESTS = object_unittest $(NATIVE_TESTING)
 check_LIBRARIES = libgoldtest.a
 libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc
 
-LDADD = libgoldtest.a ../libgold.a
+DEPENDENCIES = \
+       libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP)
+LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL)
 
 check_PROGRAMS = object_unittest $(NATIVE_PROGS)
 
index 5de0c50..6cf79cc 100644 (file)
@@ -50,23 +50,35 @@ target_triplet = @target@
 @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_nonpic_test
 
 check_PROGRAMS = object_unittest$(EXEEXT) $(am__EXEEXT_2)
-@GCC_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a ../libgold.a
+@GCC_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a ../libgold.a \
+@GCC_FALSE@    ../../libiberty/libiberty.a $(am__DEPENDENCIES_1)
 @NATIVE_LINKER_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a \
-@NATIVE_LINKER_FALSE@  ../libgold.a
+@NATIVE_LINKER_FALSE@  ../libgold.a ../../libiberty/libiberty.a \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1)
 @GCC_FALSE@constructor_static_test_DEPENDENCIES = libgoldtest.a \
-@GCC_FALSE@    ../libgold.a
+@GCC_FALSE@    ../libgold.a ../../libiberty/libiberty.a \
+@GCC_FALSE@    $(am__DEPENDENCIES_1)
 @NATIVE_LINKER_FALSE@constructor_static_test_DEPENDENCIES =  \
-@NATIVE_LINKER_FALSE@  libgoldtest.a ../libgold.a
-@GCC_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a ../libgold.a
+@NATIVE_LINKER_FALSE@  libgoldtest.a ../libgold.a \
+@NATIVE_LINKER_FALSE@  ../../libiberty/libiberty.a \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1)
+@GCC_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a ../libgold.a \
+@GCC_FALSE@    ../../libiberty/libiberty.a $(am__DEPENDENCIES_1)
 @NATIVE_LINKER_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a \
-@NATIVE_LINKER_FALSE@  ../libgold.a
-@GCC_FALSE@exception_test_DEPENDENCIES = libgoldtest.a ../libgold.a
+@NATIVE_LINKER_FALSE@  ../libgold.a ../../libiberty/libiberty.a \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1)
+@GCC_FALSE@exception_test_DEPENDENCIES = libgoldtest.a ../libgold.a \
+@GCC_FALSE@    ../../libiberty/libiberty.a $(am__DEPENDENCIES_1)
 @NATIVE_LINKER_FALSE@exception_test_DEPENDENCIES = libgoldtest.a \
-@NATIVE_LINKER_FALSE@  ../libgold.a
+@NATIVE_LINKER_FALSE@  ../libgold.a ../../libiberty/libiberty.a \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1)
 @GCC_FALSE@exception_static_test_DEPENDENCIES = libgoldtest.a \
-@GCC_FALSE@    ../libgold.a
+@GCC_FALSE@    ../libgold.a ../../libiberty/libiberty.a \
+@GCC_FALSE@    $(am__DEPENDENCIES_1)
 @NATIVE_LINKER_FALSE@exception_static_test_DEPENDENCIES =  \
-@NATIVE_LINKER_FALSE@  libgoldtest.a ../libgold.a
+@NATIVE_LINKER_FALSE@  libgoldtest.a ../libgold.a \
+@NATIVE_LINKER_FALSE@  ../../libiberty/libiberty.a \
+@NATIVE_LINKER_FALSE@  $(am__DEPENDENCIES_1)
 subdir = testsuite
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -116,6 +128,7 @@ am__constructor_static_test_SOURCES_DIST = constructor_test.cc
 constructor_static_test_OBJECTS =  \
        $(am_constructor_static_test_OBJECTS)
 constructor_static_test_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
 am__constructor_test_SOURCES_DIST = constructor_test.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am_constructor_test_OBJECTS =  \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test.$(OBJEXT)
@@ -171,7 +184,8 @@ exception_test_LDADD = $(LDADD)
 am_object_unittest_OBJECTS = object_unittest.$(OBJEXT)
 object_unittest_OBJECTS = $(am_object_unittest_OBJECTS)
 object_unittest_LDADD = $(LDADD)
-object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a
+object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \
+       ../../libiberty/libiberty.a $(am__DEPENDENCIES_1)
 am__two_file_same_shared_nonpic_test_SOURCES_DIST =  \
        two_file_test_main.cc
 @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_same_shared_nonpic_test_OBJECTS = two_file_test_main.$(OBJEXT)
@@ -447,7 +461,10 @@ INCLUDES = -D_GNU_SOURCE \
 TESTS = object_unittest $(NATIVE_TESTING)
 check_LIBRARIES = libgoldtest.a
 libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc
-LDADD = libgoldtest.a ../libgold.a
+DEPENDENCIES = \
+       libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP)
+
+LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL)
 object_unittest_SOURCES = object_unittest.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_SOURCES = constructor_test.cc
 @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_DEPENDENCIES = gcctestdir/ld