Full support for --sysroot.
[binutils-gdb.git] / gold / script.cc
index 582f6b76ff3b1ea90c82fa1434f77ba551e7ca04..365cedf9c2ef8d68cee4b4b9a90480c84d2bbe2f 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"
@@ -299,17 +301,21 @@ class Lex
 void
 Lex::read_file(std::string* contents)
 {
+  off_t filesize = this->input_file_->file().filesize();
   contents->clear();
+  contents->reserve(filesize);
+
   off_t off = 0;
-  off_t got;
   unsigned char buf[BUFSIZ];
-  do
+  while (off < filesize)
     {
-      this->input_file_->file().read(off, sizeof buf, buf, &got);
-      contents->append(reinterpret_cast<char*>(&buf[0]), got);
-      off += got;
+      off_t get = BUFSIZ;
+      if (get > filesize - off)
+       get = filesize - off;
+      this->input_file_->file().read(off, get, buf);
+      contents->append(reinterpret_cast<char*>(&buf[0]), get);
+      off += get;
     }
-  while (got == sizeof buf);
 }
 
 // Return whether C can be the start of a name, if the next character
@@ -823,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)
   { }
 
@@ -846,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
@@ -882,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_;
@@ -911,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)
@@ -1162,20 +1177,39 @@ extern "C" void
 script_add_file(void* closurev, const char* name)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
-  std::string absname;
-  if (name[0] == '/')
+
+  // 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))
     {
-      absname = 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
     {
-      // 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;
+      // 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(absname.c_str(), false, closure->position_dependent_options());
+
+  Input_file_argument file(name, false, extra_search_path,
+                          closure->position_dependent_options());
   closure->inputs()->add_file(file);
 }