// script.cc -- handle linker scripts for gold.
+// Copyright 2006, 2007 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 <string>
#include <vector>
-#include <cassert>
#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"
Token(Classification classification, int lineno, int charpos)
: classification_(classification), value_(), opcode_(0),
lineno_(lineno), charpos_(charpos)
- { assert(classification == TOKEN_INVALID || classification == TOKEN_EOF); }
+ {
+ gold_assert(classification == TOKEN_INVALID
+ || classification == TOKEN_EOF);
+ }
// A general token with a value.
Token(Classification classification, const std::string& value,
int lineno, int charpos)
: classification_(classification), value_(value), opcode_(0),
lineno_(lineno), charpos_(charpos)
- { assert(classification != TOKEN_INVALID && classification != TOKEN_EOF); }
+ {
+ gold_assert(classification != TOKEN_INVALID
+ && classification != TOKEN_EOF);
+ }
// A token representing a string of characters.
Token(const std::string& s, int lineno, int charpos)
const std::string&
string_value() const
{
- assert(this->classification_ == TOKEN_STRING);
+ gold_assert(this->classification_ == TOKEN_STRING);
return this->value_;
}
int
operator_value() const
{
- assert(this->classification_ == TOKEN_OPERATOR);
+ gold_assert(this->classification_ == TOKEN_OPERATOR);
return this->opcode_;
}
int64_t
integer_value() const
{
- assert(this->classification_ == TOKEN_INTEGER);
+ gold_assert(this->classification_ == TOKEN_INTEGER);
return strtoll(this->value_.c_str(), NULL, 0);
}
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_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
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)
{ }
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
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_;
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)
default:
case Token::TOKEN_INVALID:
case Token::TOKEN_EOF:
- abort();
+ gold_unreachable();
case Token::TOKEN_STRING:
{
script_add_file(void* closurev, const char* name)
{
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
- Input_file_argument file(name, false, 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);
}