Support assignments and expressions in linker scripts.
This commit is contained in:
parent
cda30489fc
commit
e5756efb6d
21 changed files with 1876 additions and 444 deletions
|
@ -37,6 +37,7 @@ CCFILES = \
|
||||||
dwarf_reader.cc \
|
dwarf_reader.cc \
|
||||||
ehframe.cc \
|
ehframe.cc \
|
||||||
errors.cc \
|
errors.cc \
|
||||||
|
expression.cc \
|
||||||
fileread.cc \
|
fileread.cc \
|
||||||
gold.cc \
|
gold.cc \
|
||||||
gold-threads.cc \
|
gold-threads.cc \
|
||||||
|
|
|
@ -73,13 +73,13 @@ libgold_a_LIBADD =
|
||||||
am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) \
|
am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) \
|
||||||
compressed_output.$(OBJEXT) defstd.$(OBJEXT) \
|
compressed_output.$(OBJEXT) defstd.$(OBJEXT) \
|
||||||
dirsearch.$(OBJEXT) dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) \
|
dirsearch.$(OBJEXT) dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) \
|
||||||
ehframe.$(OBJEXT) errors.$(OBJEXT) fileread.$(OBJEXT) \
|
ehframe.$(OBJEXT) errors.$(OBJEXT) expression.$(OBJEXT) \
|
||||||
gold.$(OBJEXT) gold-threads.$(OBJEXT) layout.$(OBJEXT) \
|
fileread.$(OBJEXT) gold.$(OBJEXT) gold-threads.$(OBJEXT) \
|
||||||
merge.$(OBJEXT) object.$(OBJEXT) options.$(OBJEXT) \
|
layout.$(OBJEXT) merge.$(OBJEXT) object.$(OBJEXT) \
|
||||||
output.$(OBJEXT) parameters.$(OBJEXT) readsyms.$(OBJEXT) \
|
options.$(OBJEXT) output.$(OBJEXT) parameters.$(OBJEXT) \
|
||||||
reloc.$(OBJEXT) resolve.$(OBJEXT) script.$(OBJEXT) \
|
readsyms.$(OBJEXT) reloc.$(OBJEXT) resolve.$(OBJEXT) \
|
||||||
stringpool.$(OBJEXT) symtab.$(OBJEXT) target-select.$(OBJEXT) \
|
script.$(OBJEXT) stringpool.$(OBJEXT) symtab.$(OBJEXT) \
|
||||||
version.$(OBJEXT) workqueue.$(OBJEXT) \
|
target-select.$(OBJEXT) version.$(OBJEXT) workqueue.$(OBJEXT) \
|
||||||
workqueue-threads.$(OBJEXT)
|
workqueue-threads.$(OBJEXT)
|
||||||
am__objects_2 =
|
am__objects_2 =
|
||||||
am__objects_3 = yyscript.$(OBJEXT)
|
am__objects_3 = yyscript.$(OBJEXT)
|
||||||
|
@ -294,6 +294,7 @@ CCFILES = \
|
||||||
dwarf_reader.cc \
|
dwarf_reader.cc \
|
||||||
ehframe.cc \
|
ehframe.cc \
|
||||||
errors.cc \
|
errors.cc \
|
||||||
|
expression.cc \
|
||||||
fileread.cc \
|
fileread.cc \
|
||||||
gold.cc \
|
gold.cc \
|
||||||
gold-threads.cc \
|
gold-threads.cc \
|
||||||
|
@ -477,6 +478,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynobj.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynobj.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehframe.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehframe.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expression.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileread.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileread.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold-threads.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold-threads.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold.Po@am__quote@
|
||||||
|
|
508
gold/expression.cc
Normal file
508
gold/expression.cc
Normal file
|
@ -0,0 +1,508 @@
|
||||||
|
// expression.cc -- expressions in linker scripts for gold
|
||||||
|
|
||||||
|
// Copyright 2006, 2007, 2008 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 "parameters.h"
|
||||||
|
#include "symtab.h"
|
||||||
|
#include "layout.h"
|
||||||
|
#include "script.h"
|
||||||
|
#include "script-c.h"
|
||||||
|
|
||||||
|
namespace gold
|
||||||
|
{
|
||||||
|
|
||||||
|
// This file holds the code which handles linker expressions.
|
||||||
|
|
||||||
|
// When evaluating the value of an expression, we pass in a pointer to
|
||||||
|
// this struct, so that the expression evaluation can find the
|
||||||
|
// information it needs.
|
||||||
|
|
||||||
|
struct Expression::Expression_eval_info
|
||||||
|
{
|
||||||
|
const Symbol_table* symtab;
|
||||||
|
const Layout* layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Evaluate an expression.
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Expression::eval(const Symbol_table* symtab, const Layout* layout)
|
||||||
|
{
|
||||||
|
Expression_eval_info eei;
|
||||||
|
eei.symtab = symtab;
|
||||||
|
eei.layout = layout;
|
||||||
|
return this->value(&eei);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A number.
|
||||||
|
|
||||||
|
class Integer_expression : public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Integer_expression(uint64_t val)
|
||||||
|
: val_(val)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info*)
|
||||||
|
{ return this->val_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t val_;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_integer(uint64_t val)
|
||||||
|
{
|
||||||
|
return new Integer_expression(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// An expression whose value is the value of a symbol.
|
||||||
|
|
||||||
|
class Symbol_expression : public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Symbol_expression(const char* name, size_t length)
|
||||||
|
: name_(name, length)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Symbol_expression::value(const Expression_eval_info* eei)
|
||||||
|
{
|
||||||
|
Symbol* sym = eei->symtab->lookup(this->name_.c_str());
|
||||||
|
if (sym == NULL || !sym->is_defined())
|
||||||
|
{
|
||||||
|
gold_error(_("undefined symbol '%s' referenced in expression"),
|
||||||
|
this->name_.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameters->get_size() == 32)
|
||||||
|
return eei->symtab->get_sized_symbol<32>(sym)->value();
|
||||||
|
else if (parameters->get_size() == 64)
|
||||||
|
return eei->symtab->get_sized_symbol<64>(sym)->value();
|
||||||
|
else
|
||||||
|
gold_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// An expression whose value is the value of the special symbol ".".
|
||||||
|
// This is only valid within a SECTIONS clause.
|
||||||
|
|
||||||
|
class Dot_expression : public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Dot_expression()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info*);
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
Dot_expression::value(const Expression_eval_info*)
|
||||||
|
{
|
||||||
|
gold_error("dot symbol unimplemented");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A string. This is either the name of a symbol, or ".".
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_string(const char* name, size_t length)
|
||||||
|
{
|
||||||
|
if (length == 1 && name[0] == '.')
|
||||||
|
return new Dot_expression();
|
||||||
|
else
|
||||||
|
return new Symbol_expression(name, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A unary expression.
|
||||||
|
|
||||||
|
class Unary_expression : public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Unary_expression(Expression* arg)
|
||||||
|
: arg_(arg)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Unary_expression()
|
||||||
|
{ delete this->arg_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint64_t
|
||||||
|
arg_value(const Expression_eval_info* eei) const
|
||||||
|
{ return this->arg_->value(eei); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Expression* arg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle unary operators. We use a preprocessor macro as a hack to
|
||||||
|
// capture the C operator.
|
||||||
|
|
||||||
|
#define UNARY_EXPRESSION(NAME, OPERATOR) \
|
||||||
|
class Unary_ ## NAME : public Unary_expression \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
Unary_ ## NAME(Expression* arg) \
|
||||||
|
: Unary_expression(arg) \
|
||||||
|
{ } \
|
||||||
|
\
|
||||||
|
uint64_t \
|
||||||
|
value(const Expression_eval_info* eei) \
|
||||||
|
{ return OPERATOR this->arg_value(eei); } \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
extern "C" Expression* \
|
||||||
|
script_exp_unary_ ## NAME(Expression* arg) \
|
||||||
|
{ \
|
||||||
|
return new Unary_ ## NAME(arg); \
|
||||||
|
}
|
||||||
|
|
||||||
|
UNARY_EXPRESSION(minus, -)
|
||||||
|
UNARY_EXPRESSION(logical_not, !)
|
||||||
|
UNARY_EXPRESSION(bitwise_not, ~)
|
||||||
|
|
||||||
|
// A binary expression.
|
||||||
|
|
||||||
|
class Binary_expression : public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Binary_expression(Expression* left, Expression* right)
|
||||||
|
: left_(left), right_(right)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Binary_expression()
|
||||||
|
{
|
||||||
|
delete this->left_;
|
||||||
|
delete this->right_;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint64_t
|
||||||
|
left_value(const Expression_eval_info* eei) const
|
||||||
|
{ return this->left_->value(eei); }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
right_value(const Expression_eval_info* eei) const
|
||||||
|
{ return this->right_->value(eei); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Expression* left_;
|
||||||
|
Expression* right_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle binary operators. We use a preprocessor macro as a hack to
|
||||||
|
// capture the C operator.
|
||||||
|
|
||||||
|
#define BINARY_EXPRESSION(NAME, OPERATOR) \
|
||||||
|
class Binary_ ## NAME : public Binary_expression \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
Binary_ ## NAME(Expression* left, Expression* right) \
|
||||||
|
: Binary_expression(left, right) \
|
||||||
|
{ } \
|
||||||
|
\
|
||||||
|
uint64_t \
|
||||||
|
value(const Expression_eval_info* eei) \
|
||||||
|
{ \
|
||||||
|
return (this->left_value(eei) \
|
||||||
|
OPERATOR this->right_value(eei)); \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
extern "C" Expression* \
|
||||||
|
script_exp_binary_ ## NAME(Expression* left, Expression* right) \
|
||||||
|
{ \
|
||||||
|
return new Binary_ ## NAME(left, right); \
|
||||||
|
}
|
||||||
|
|
||||||
|
BINARY_EXPRESSION(mult, *)
|
||||||
|
BINARY_EXPRESSION(div, /)
|
||||||
|
BINARY_EXPRESSION(mod, %)
|
||||||
|
BINARY_EXPRESSION(add, +)
|
||||||
|
BINARY_EXPRESSION(sub, -)
|
||||||
|
BINARY_EXPRESSION(lshift, <<)
|
||||||
|
BINARY_EXPRESSION(rshift, >>)
|
||||||
|
BINARY_EXPRESSION(eq, ==)
|
||||||
|
BINARY_EXPRESSION(ne, !=)
|
||||||
|
BINARY_EXPRESSION(le, <=)
|
||||||
|
BINARY_EXPRESSION(ge, >=)
|
||||||
|
BINARY_EXPRESSION(lt, <)
|
||||||
|
BINARY_EXPRESSION(gt, >)
|
||||||
|
BINARY_EXPRESSION(bitwise_and, &)
|
||||||
|
BINARY_EXPRESSION(bitwise_xor, ^)
|
||||||
|
BINARY_EXPRESSION(bitwise_or, |)
|
||||||
|
BINARY_EXPRESSION(logical_and, &&)
|
||||||
|
BINARY_EXPRESSION(logical_or, ||)
|
||||||
|
|
||||||
|
// A trinary expression.
|
||||||
|
|
||||||
|
class Trinary_expression : public Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Trinary_expression(Expression* arg1, Expression* arg2, Expression* arg3)
|
||||||
|
: arg1_(arg1), arg2_(arg2), arg3_(arg3)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Trinary_expression()
|
||||||
|
{
|
||||||
|
delete this->arg1_;
|
||||||
|
delete this->arg2_;
|
||||||
|
delete this->arg3_;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint64_t
|
||||||
|
arg1_value(const Expression_eval_info* eei) const
|
||||||
|
{ return this->arg1_->value(eei); }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
arg2_value(const Expression_eval_info* eei) const
|
||||||
|
{ return this->arg2_->value(eei); }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
arg3_value(const Expression_eval_info* eei) const
|
||||||
|
{ return this->arg3_->value(eei); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Expression* arg1_;
|
||||||
|
Expression* arg2_;
|
||||||
|
Expression* arg3_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The conditional operator.
|
||||||
|
|
||||||
|
class Trinary_cond : public Trinary_expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
|
||||||
|
: Trinary_expression(arg1, arg2, arg3)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info* eei)
|
||||||
|
{
|
||||||
|
return (this->arg1_value(eei)
|
||||||
|
? this->arg2_value(eei)
|
||||||
|
: this->arg3_value(eei));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
|
||||||
|
{
|
||||||
|
return new Trinary_cond(arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max function.
|
||||||
|
|
||||||
|
class Max_expression : public Binary_expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Max_expression(Expression* left, Expression* right)
|
||||||
|
: Binary_expression(left, right)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info* eei)
|
||||||
|
{ return std::max(this->left_value(eei), this->right_value(eei)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_max(Expression* left, Expression* right)
|
||||||
|
{
|
||||||
|
return new Max_expression(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Min function.
|
||||||
|
|
||||||
|
class Min_expression : public Binary_expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Min_expression(Expression* left, Expression* right)
|
||||||
|
: Binary_expression(left, right)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info* eei)
|
||||||
|
{ return std::min(this->left_value(eei), this->right_value(eei)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_min(Expression* left, Expression* right)
|
||||||
|
{
|
||||||
|
return new Min_expression(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align function.
|
||||||
|
|
||||||
|
class Align_expression : public Binary_expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Align_expression(Expression* left, Expression* right)
|
||||||
|
: Binary_expression(left, right)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info* eei)
|
||||||
|
{
|
||||||
|
uint64_t align = this->right_value(eei);
|
||||||
|
uint64_t value = this->left_value(eei);
|
||||||
|
if (align <= 1)
|
||||||
|
return value;
|
||||||
|
return ((value + align - 1) / align) * align;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_align(Expression* left, Expression* right)
|
||||||
|
{
|
||||||
|
return new Align_expression(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert function.
|
||||||
|
|
||||||
|
class Assert_expression : public Unary_expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Assert_expression(Expression* arg, const char* message, size_t length)
|
||||||
|
: Unary_expression(arg), message_(message, length)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
value(const Expression_eval_info* eei)
|
||||||
|
{
|
||||||
|
uint64_t value = this->arg_value(eei);
|
||||||
|
if (!value)
|
||||||
|
gold_error("%s", this->message_.c_str());
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string message_;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_assert(Expression* expr, const char* message,
|
||||||
|
size_t length)
|
||||||
|
{
|
||||||
|
return new Assert_expression(expr, message, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions.
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_defined(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("DEFINED not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_sizeof_headers()
|
||||||
|
{
|
||||||
|
gold_fatal(_("SIZEOF_HEADERS not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_alignof(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("ALIGNOF not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_sizeof(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("SIZEOF not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_addr(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("ADDR not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_loadaddr(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("LOADADDR not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_origin(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("ORIGIN not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_length(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("LENGTH not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_constant(const char*, size_t)
|
||||||
|
{
|
||||||
|
gold_fatal(_("CONSTANT not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_absolute(Expression*)
|
||||||
|
{
|
||||||
|
gold_fatal(_("ABSOLUTE not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_data_segment_align(Expression*, Expression*)
|
||||||
|
{
|
||||||
|
gold_fatal(_("DATA_SEGMENT_ALIGN not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_data_segment_relro_end(Expression*, Expression*)
|
||||||
|
{
|
||||||
|
gold_fatal(_("DATA_SEGMENT_RELRO_END not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_data_segment_end(Expression*)
|
||||||
|
{
|
||||||
|
gold_fatal(_("DATA_SEGMENT_END not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Expression*
|
||||||
|
script_exp_function_segment_start(const char*, size_t, Expression*)
|
||||||
|
{
|
||||||
|
gold_fatal(_("SEGMENT_START not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace gold.
|
|
@ -1,6 +1,6 @@
|
||||||
// gold.cc -- main linker functions
|
// gold.cc -- main linker functions
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -202,6 +202,9 @@ queue_middle_tasks(const General_options& options,
|
||||||
// appropriate.
|
// appropriate.
|
||||||
layout->define_section_symbols(symtab, input_objects->target());
|
layout->define_section_symbols(symtab, input_objects->target());
|
||||||
|
|
||||||
|
// Define symbols from any linker scripts.
|
||||||
|
layout->define_script_symbols(symtab, input_objects->target());
|
||||||
|
|
||||||
// Read the relocations of the input files. We do this to find
|
// Read the relocations of the input files. We do this to find
|
||||||
// which symbols are used by relocations which require a GOT and/or
|
// which symbols are used by relocations which require a GOT and/or
|
||||||
// a PLT entry, or a COPY reloc. When we implement garbage
|
// a PLT entry, or a COPY reloc. When we implement garbage
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// layout.cc -- lay out output file sections for gold
|
// layout.cc -- lay out output file sections for gold
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -63,9 +63,9 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
|
||||||
|
|
||||||
// Layout methods.
|
// Layout methods.
|
||||||
|
|
||||||
Layout::Layout(const General_options& options)
|
Layout::Layout(const General_options& options, Script_options* script_options)
|
||||||
: options_(options), entry_(options.entry()), namepool_(), sympool_(),
|
: options_(options), script_options_(script_options), namepool_(),
|
||||||
dynpool_(), signatures_(),
|
sympool_(), dynpool_(), signatures_(),
|
||||||
section_name_map_(), segment_list_(), section_list_(),
|
section_name_map_(), segment_list_(), section_list_(),
|
||||||
unattached_section_list_(), special_output_list_(),
|
unattached_section_list_(), special_output_list_(),
|
||||||
section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL),
|
section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL),
|
||||||
|
@ -722,7 +722,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
|
||||||
// Lay out the file header.
|
// Lay out the file header.
|
||||||
Output_file_header* file_header;
|
Output_file_header* file_header;
|
||||||
file_header = new Output_file_header(target, symtab, segment_headers,
|
file_header = new Output_file_header(target, symtab, segment_headers,
|
||||||
this->entry_);
|
this->script_options_->entry());
|
||||||
load_seg->add_initial_output_data(file_header);
|
load_seg->add_initial_output_data(file_header);
|
||||||
this->special_output_list_.push_back(file_header);
|
this->special_output_list_.push_back(file_header);
|
||||||
|
|
||||||
|
@ -745,6 +745,10 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
|
||||||
if (!parameters->doing_static_link())
|
if (!parameters->doing_static_link())
|
||||||
this->assign_local_dynsym_offsets(input_objects);
|
this->assign_local_dynsym_offsets(input_objects);
|
||||||
|
|
||||||
|
// Process any symbol assignments from a linker script. This must
|
||||||
|
// be called after the symbol table has been finalized.
|
||||||
|
this->script_options_->finalize_symbols(symtab, this);
|
||||||
|
|
||||||
// Create the .shstrtab section.
|
// Create the .shstrtab section.
|
||||||
Output_section* shstrtab_section = this->create_shstrtab();
|
Output_section* shstrtab_section = this->create_shstrtab();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// layout.h -- lay out output file sections for gold -*- C++ -*-
|
// layout.h -- lay out output file sections for gold -*- C++ -*-
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "script.h"
|
||||||
#include "workqueue.h"
|
#include "workqueue.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "dynobj.h"
|
#include "dynobj.h"
|
||||||
|
@ -84,7 +85,7 @@ class Layout_task_runner : public Task_function_runner
|
||||||
class Layout
|
class Layout
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Layout(const General_options& options);
|
Layout(const General_options& options, Script_options*);
|
||||||
|
|
||||||
// Given an input section SHNDX, named NAME, with data in SHDR, from
|
// Given an input section SHNDX, named NAME, with data in SHDR, from
|
||||||
// the object file OBJECT, return the output section where this
|
// the object file OBJECT, return the output section where this
|
||||||
|
@ -142,6 +143,11 @@ class Layout
|
||||||
void
|
void
|
||||||
define_section_symbols(Symbol_table*, const Target*);
|
define_section_symbols(Symbol_table*, const Target*);
|
||||||
|
|
||||||
|
// Define symbols from any linker script.
|
||||||
|
void
|
||||||
|
define_script_symbols(Symbol_table* symtab, const Target* target)
|
||||||
|
{ this->script_options_->add_symbols_to_table(symtab, target); }
|
||||||
|
|
||||||
// Return the Stringpool used for symbol names.
|
// Return the Stringpool used for symbol names.
|
||||||
const Stringpool*
|
const Stringpool*
|
||||||
sympool() const
|
sympool() const
|
||||||
|
@ -241,11 +247,14 @@ class Layout
|
||||||
has_static_tls() const
|
has_static_tls() const
|
||||||
{ return this->has_static_tls_; }
|
{ return this->has_static_tls_; }
|
||||||
|
|
||||||
// Set the name of the entry symbol. This is used by linker scripts
|
// Return the options which may be set by a linker script.
|
||||||
// which look like regular objects.
|
Script_options*
|
||||||
void
|
script_options()
|
||||||
set_entry(const char* entry)
|
{ return this->script_options_; }
|
||||||
{ this->entry_ = entry; }
|
|
||||||
|
const Script_options*
|
||||||
|
script_options() const
|
||||||
|
{ return this->script_options_; }
|
||||||
|
|
||||||
// Dump statistical information to stderr.
|
// Dump statistical information to stderr.
|
||||||
void
|
void
|
||||||
|
@ -432,9 +441,8 @@ class Layout
|
||||||
|
|
||||||
// A reference to the options on the command line.
|
// A reference to the options on the command line.
|
||||||
const General_options& options_;
|
const General_options& options_;
|
||||||
// The name of the entry symbol. This is from the command line, or
|
// Information set by scripts or by command line options.
|
||||||
// from a linker script, or is NULL.
|
Script_options* script_options_;
|
||||||
const char* entry_;
|
|
||||||
// The output section names.
|
// The output section names.
|
||||||
Stringpool namepool_;
|
Stringpool namepool_;
|
||||||
// The output symbol names.
|
// The output symbol names.
|
||||||
|
|
11
gold/main.cc
11
gold/main.cc
|
@ -1,6 +1,6 @@
|
||||||
// main.cc -- gold main function.
|
// main.cc -- gold main function.
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
|
|
||||||
|
#include "script.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
@ -58,8 +59,12 @@ main(int argc, char** argv)
|
||||||
// errors object.
|
// errors object.
|
||||||
initialize_parameters(&errors);
|
initialize_parameters(&errors);
|
||||||
|
|
||||||
|
// Options which may be set by the command line or by linker
|
||||||
|
// scripts.
|
||||||
|
Script_options script_options;
|
||||||
|
|
||||||
// Handle the command line options.
|
// Handle the command line options.
|
||||||
Command_line command_line;
|
Command_line command_line(&script_options);
|
||||||
command_line.process(argc - 1, argv + 1);
|
command_line.process(argc - 1, argv + 1);
|
||||||
|
|
||||||
long start_time = 0;
|
long start_time = 0;
|
||||||
|
@ -82,7 +87,7 @@ main(int argc, char** argv)
|
||||||
Symbol_table symtab(command_line.number_of_input_files() * 1024);
|
Symbol_table symtab(command_line.number_of_input_files() * 1024);
|
||||||
|
|
||||||
// The layout object.
|
// The layout object.
|
||||||
Layout layout(command_line.options());
|
Layout layout(command_line.options(), &script_options);
|
||||||
|
|
||||||
// Get the search path from the -L options.
|
// Get the search path from the -L options.
|
||||||
Dirsearch search_path;
|
Dirsearch search_path;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// options.c -- handle command line options for gold
|
// options.c -- handle command line options for gold
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -29,6 +29,7 @@
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "script.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
namespace gold
|
namespace gold
|
||||||
|
@ -154,7 +155,7 @@ invoke_script(int argc, char** argv, char* arg, bool long_option,
|
||||||
arg, long_option,
|
arg, long_option,
|
||||||
&ret);
|
&ret);
|
||||||
if (!read_commandline_script(script_name, cmdline))
|
if (!read_commandline_script(script_name, cmdline))
|
||||||
gold::gold_error(_("unable to parse script file %s\n"), script_name);
|
gold::gold_error(_("unable to parse script file %s"), script_name);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +387,9 @@ options::Command_line_options::options[] =
|
||||||
N_("--compress-debug-sections=[none" ZLIB_STR "]"),
|
N_("--compress-debug-sections=[none" ZLIB_STR "]"),
|
||||||
TWO_DASHES,
|
TWO_DASHES,
|
||||||
&General_options::set_compress_debug_sections),
|
&General_options::set_compress_debug_sections),
|
||||||
|
GENERAL_ARG('\0', "defsym", N_("Define a symbol"),
|
||||||
|
N_("--defsym SYMBOL=EXPRESSION"), TWO_DASHES,
|
||||||
|
&General_options::define_symbol),
|
||||||
GENERAL_NOARG('\0', "demangle", N_("Demangle C++ symbols in log messages"),
|
GENERAL_NOARG('\0', "demangle", N_("Demangle C++ symbols in log messages"),
|
||||||
NULL, TWO_DASHES, &General_options::set_demangle),
|
NULL, TWO_DASHES, &General_options::set_demangle),
|
||||||
GENERAL_NOARG('\0', "no-demangle",
|
GENERAL_NOARG('\0', "no-demangle",
|
||||||
|
@ -531,9 +535,8 @@ const int options::Command_line_options::debug_options_size =
|
||||||
|
|
||||||
// The default values for the general options.
|
// The default values for the general options.
|
||||||
|
|
||||||
General_options::General_options()
|
General_options::General_options(Script_options* script_options)
|
||||||
: entry_(NULL),
|
: export_dynamic_(false),
|
||||||
export_dynamic_(false),
|
|
||||||
soname_(NULL),
|
soname_(NULL),
|
||||||
dynamic_linker_(NULL),
|
dynamic_linker_(NULL),
|
||||||
search_path_(),
|
search_path_(),
|
||||||
|
@ -558,7 +561,8 @@ General_options::General_options()
|
||||||
thread_count_middle_(0),
|
thread_count_middle_(0),
|
||||||
thread_count_final_(0),
|
thread_count_final_(0),
|
||||||
execstack_(EXECSTACK_FROM_INPUT),
|
execstack_(EXECSTACK_FROM_INPUT),
|
||||||
debug_(0)
|
debug_(0),
|
||||||
|
script_options_(script_options)
|
||||||
{
|
{
|
||||||
// We initialize demangle_ based on the environment variable
|
// We initialize demangle_ based on the environment variable
|
||||||
// COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the
|
// COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the
|
||||||
|
@ -568,13 +572,12 @@ General_options::General_options()
|
||||||
this->demangle_ = getenv("COLLECT_NO_DEMANGLE") == NULL;
|
this->demangle_ = getenv("COLLECT_NO_DEMANGLE") == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The default values for the position dependent options.
|
// Handle the --defsym option.
|
||||||
|
|
||||||
Position_dependent_options::Position_dependent_options()
|
void
|
||||||
: do_static_search_(false),
|
General_options::define_symbol(const char* arg)
|
||||||
as_needed_(false),
|
|
||||||
include_whole_archive_(false)
|
|
||||||
{
|
{
|
||||||
|
this->script_options_->define_symbol(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the -z option.
|
// Handle the -z option.
|
||||||
|
@ -645,6 +648,15 @@ General_options::add_sysroot()
|
||||||
free(canonical_sysroot);
|
free(canonical_sysroot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The default values for the position dependent options.
|
||||||
|
|
||||||
|
Position_dependent_options::Position_dependent_options()
|
||||||
|
: do_static_search_(false),
|
||||||
|
as_needed_(false),
|
||||||
|
include_whole_archive_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Search_directory methods.
|
// Search_directory methods.
|
||||||
|
|
||||||
// This is called if we have a sysroot. Apply the sysroot if
|
// This is called if we have a sysroot. Apply the sysroot if
|
||||||
|
@ -721,8 +733,8 @@ Input_arguments::end_group()
|
||||||
|
|
||||||
// Command_line options.
|
// Command_line options.
|
||||||
|
|
||||||
Command_line::Command_line()
|
Command_line::Command_line(Script_options* script_options)
|
||||||
: options_(), position_options_(), inputs_()
|
: options_(script_options), position_options_(), inputs_()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// options.h -- handle command line options for gold -*- C++ -*-
|
// options.h -- handle command line options for gold -*- C++ -*-
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -106,12 +106,12 @@ class Search_directory
|
||||||
class General_options
|
class General_options
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
General_options();
|
General_options(Script_options*);
|
||||||
|
|
||||||
// -e: set entry address.
|
// -e: set entry address.
|
||||||
const char*
|
const char*
|
||||||
entry() const
|
entry() const
|
||||||
{ return this->entry_; }
|
{ return this->script_options_->entry(); }
|
||||||
|
|
||||||
// -E: export dynamic symbols.
|
// -E: export dynamic symbols.
|
||||||
bool
|
bool
|
||||||
|
@ -277,6 +277,15 @@ class General_options
|
||||||
debug() const
|
debug() const
|
||||||
{ return this->debug_; }
|
{ return this->debug_; }
|
||||||
|
|
||||||
|
// Return the options which may be set from a linker script.
|
||||||
|
Script_options*
|
||||||
|
script_options()
|
||||||
|
{ return this->script_options_; }
|
||||||
|
|
||||||
|
const Script_options*
|
||||||
|
script_options() const
|
||||||
|
{ return this->script_options_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Don't copy this structure.
|
// Don't copy this structure.
|
||||||
General_options(const General_options&);
|
General_options(const General_options&);
|
||||||
|
@ -318,7 +327,7 @@ class General_options
|
||||||
|
|
||||||
void
|
void
|
||||||
set_entry(const char* arg)
|
set_entry(const char* arg)
|
||||||
{ this->entry_ = arg; }
|
{ this->script_options_->set_entry(arg, strlen(arg)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
set_export_dynamic()
|
set_export_dynamic()
|
||||||
|
@ -396,6 +405,9 @@ class General_options
|
||||||
arg);
|
arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
define_symbol(const char* arg);
|
||||||
|
|
||||||
void
|
void
|
||||||
set_demangle()
|
set_demangle()
|
||||||
{ this->demangle_ = true; }
|
{ this->demangle_ = true; }
|
||||||
|
@ -518,7 +530,6 @@ class General_options
|
||||||
void
|
void
|
||||||
add_sysroot();
|
add_sysroot();
|
||||||
|
|
||||||
const char* entry_;
|
|
||||||
bool export_dynamic_;
|
bool export_dynamic_;
|
||||||
const char* soname_;
|
const char* soname_;
|
||||||
const char* dynamic_linker_;
|
const char* dynamic_linker_;
|
||||||
|
@ -546,6 +557,9 @@ class General_options
|
||||||
int thread_count_final_;
|
int thread_count_final_;
|
||||||
Execstack execstack_;
|
Execstack execstack_;
|
||||||
unsigned int debug_;
|
unsigned int debug_;
|
||||||
|
// Some options can also be set from linker scripts. Those are
|
||||||
|
// stored here.
|
||||||
|
Script_options* script_options_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The current state of the position dependent options.
|
// The current state of the position dependent options.
|
||||||
|
@ -810,7 +824,7 @@ class Command_line
|
||||||
public:
|
public:
|
||||||
typedef Input_arguments::const_iterator const_iterator;
|
typedef Input_arguments::const_iterator const_iterator;
|
||||||
|
|
||||||
Command_line();
|
Command_line(Script_options*);
|
||||||
|
|
||||||
// Process the command line options. This will exit with an
|
// Process the command line options. This will exit with an
|
||||||
// appropriate error message if an unrecognized option is seen.
|
// appropriate error message if an unrecognized option is seen.
|
||||||
|
@ -834,11 +848,6 @@ class Command_line
|
||||||
void
|
void
|
||||||
end_group(const char* arg);
|
end_group(const char* arg);
|
||||||
|
|
||||||
// Set the entry symbol from a linker script.
|
|
||||||
void
|
|
||||||
set_entry(const char* entry)
|
|
||||||
{ this->options_.set_entry(entry); }
|
|
||||||
|
|
||||||
// Get an option argument--a helper function for special processing.
|
// Get an option argument--a helper function for special processing.
|
||||||
const char*
|
const char*
|
||||||
get_special_argument(const char* longname, int argc, char** argv,
|
get_special_argument(const char* longname, int argc, char** argv,
|
||||||
|
@ -855,6 +864,15 @@ class Command_line
|
||||||
position_dependent_options() const
|
position_dependent_options() const
|
||||||
{ return this->position_options_; }
|
{ return this->position_options_; }
|
||||||
|
|
||||||
|
// Get the options which may be set from a linker script.
|
||||||
|
Script_options*
|
||||||
|
script_options()
|
||||||
|
{ return this->options_.script_options(); }
|
||||||
|
|
||||||
|
const Script_options*
|
||||||
|
script_options() const
|
||||||
|
{ return this->options_.script_options(); }
|
||||||
|
|
||||||
// The number of input files.
|
// The number of input files.
|
||||||
int
|
int
|
||||||
number_of_input_files() const
|
number_of_input_files() const
|
||||||
|
|
|
@ -16,6 +16,7 @@ ehframe.cc
|
||||||
ehframe.h
|
ehframe.h
|
||||||
errors.cc
|
errors.cc
|
||||||
errors.h
|
errors.h
|
||||||
|
expression.cc
|
||||||
fileread.cc
|
fileread.cc
|
||||||
fileread.h
|
fileread.h
|
||||||
gold.cc
|
gold.cc
|
||||||
|
|
429
gold/po/gold.pot
429
gold/po/gold.pot
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2007-12-21 15:26-0800\n"
|
"POT-Creation-Date: 2008-01-09 11:37-0800\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -16,47 +16,47 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=CHARSET\n"
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: archive.cc:96
|
#: archive.cc:97
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: no archive symbol table (run ranlib)"
|
msgid "%s: no archive symbol table (run ranlib)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:147
|
#: archive.cc:151
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: bad archive symbol table names"
|
msgid "%s: bad archive symbol table names"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:177
|
#: archive.cc:181
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: malformed archive header at %zu"
|
msgid "%s: malformed archive header at %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:197
|
#: archive.cc:201
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: malformed archive header size at %zu"
|
msgid "%s: malformed archive header size at %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:208
|
#: archive.cc:212
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: malformed archive header name at %zu"
|
msgid "%s: malformed archive header name at %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:233
|
#: archive.cc:237
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: bad extended name index at %zu"
|
msgid "%s: bad extended name index at %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:243
|
#: archive.cc:247
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: bad extended name entry at header %zu"
|
msgid "%s: bad extended name entry at header %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:336
|
#: archive.cc:340
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: short archive header at %zu"
|
msgid "%s: short archive header at %zu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: archive.cc:387 archive.cc:401
|
#: archive.cc:391 archive.cc:405
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: member at %zu is not an ELF object"
|
msgid "%s: member at %zu is not an ELF object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -114,7 +114,7 @@ msgstr ""
|
||||||
msgid "dynamic symbol table name section has wrong type: %u"
|
msgid "dynamic symbol table name section has wrong type: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:404 object.cc:241 object.cc:579
|
#: dynobj.cc:404 object.cc:251 object.cc:589
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "bad section name offset for section %u: %lu"
|
msgid "bad section name offset for section %u: %lu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -178,82 +178,158 @@ msgstr ""
|
||||||
msgid "size of dynamic symbols is not multiple of symbol size"
|
msgid "size of dynamic symbols is not multiple of symbol size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: dynobj.cc:1312
|
#: dynobj.cc:1316
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "symbol %s has undefined version %s"
|
msgid "symbol %s has undefined version %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: errors.cc:88
|
#: errors.cc:106
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: warning: "
|
msgid "%s: warning: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: errors.cc:127
|
#: errors.cc:137
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: warning: "
|
msgid "%s: %s: warning: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: errors.cc:154
|
#: errors.cc:161
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: undefined reference to '%s'\n"
|
msgid "%s: %s: undefined reference to '%s'\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: errors.cc:164
|
#: errors.cc:171
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: "
|
msgid "%s: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:49
|
#: expression.cc:104
|
||||||
|
#, c-format
|
||||||
|
msgid "undefined symbol '%s' referenced in expression"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:427
|
||||||
|
msgid "DEFINED not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:433
|
||||||
|
msgid "SIZEOF_HEADERS not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:439
|
||||||
|
msgid "ALIGNOF not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:445
|
||||||
|
msgid "SIZEOF not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:451
|
||||||
|
msgid "ADDR not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:457
|
||||||
|
msgid "LOADADDR not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:463
|
||||||
|
msgid "ORIGIN not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:469
|
||||||
|
msgid "LENGTH not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:475
|
||||||
|
msgid "CONSTANT not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:481
|
||||||
|
msgid "ABSOLUTE not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:487
|
||||||
|
msgid "DATA_SEGMENT_ALIGN not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:493
|
||||||
|
msgid "DATA_SEGMENT_RELRO_END not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:499
|
||||||
|
msgid "DATA_SEGMENT_END not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: expression.cc:505
|
||||||
|
msgid "SEGMENT_START not implemented"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: fileread.cc:50
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "munmap failed: %s"
|
msgid "munmap failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:90
|
#: fileread.cc:91
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "close of %s failed: %s"
|
msgid "close of %s failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:114
|
#: fileread.cc:115
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: fstat failed: %s"
|
msgid "%s: fstat failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:229
|
#: fileread.cc:240
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: pread failed: %s"
|
msgid "%s: pread failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:235
|
#: fileread.cc:246
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: file too short: read only %lld of %lld bytes at %lld"
|
msgid "%s: file too short: read only %lld of %lld bytes at %lld"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:310
|
#: fileread.cc:325
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: mmap offset %lld size %lld failed: %s"
|
msgid "%s: mmap offset %lld size %lld failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:391
|
#: fileread.cc:400
|
||||||
|
#, c-format
|
||||||
|
msgid "%s: lseek failed: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: fileread.cc:406
|
||||||
|
#, c-format
|
||||||
|
msgid "%s: readv failed: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: fileread.cc:409
|
||||||
|
#, c-format
|
||||||
|
msgid "%s: file too short: read only %zd of %zd bytes at %lld"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: fileread.cc:556
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: total bytes mapped for read: %llu\n"
|
msgid "%s: total bytes mapped for read: %llu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:393
|
#: fileread.cc:558
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: maximum bytes mapped for read at one time: %llu\n"
|
msgid "%s: maximum bytes mapped for read at one time: %llu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:463
|
#: fileread.cc:628
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot find -l%s"
|
msgid "cannot find -l%s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:490
|
#: fileread.cc:655
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot find %s"
|
msgid "cannot find %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: fileread.cc:501
|
#: fileread.cc:666
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot open %s: %s"
|
msgid "cannot open %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -398,7 +474,7 @@ msgstr ""
|
||||||
msgid "%s: unsupported ELF machine number %d"
|
msgid "%s: unsupported ELF machine number %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:71 script.cc:1229
|
#: object.cc:71
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s"
|
msgid "%s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -408,124 +484,124 @@ msgstr ""
|
||||||
msgid "section name section has wrong type: %u"
|
msgid "section name section has wrong type: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:315
|
#: object.cc:325
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid symbol table name index: %u"
|
msgid "invalid symbol table name index: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:321
|
#: object.cc:331
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "symbol table name section has wrong type: %u"
|
msgid "symbol table name section has wrong type: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:402
|
#: object.cc:412
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "section group %u info %u out of range"
|
msgid "section group %u info %u out of range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:420
|
#: object.cc:430
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "symbol %u name offset %u out of range"
|
msgid "symbol %u name offset %u out of range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:452
|
#: object.cc:462
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "section %u in section group %u out of range"
|
msgid "section %u in section group %u out of range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:542 reloc.cc:206 reloc.cc:530
|
#: object.cc:552 reloc.cc:213 reloc.cc:570
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "relocation section %u has bad info %u"
|
msgid "relocation section %u has bad info %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:713
|
#: object.cc:723
|
||||||
msgid "size of symbols is not multiple of symbol size"
|
msgid "size of symbols is not multiple of symbol size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:812
|
#: object.cc:823
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "local symbol %u section name out of range: %u >= %u"
|
msgid "local symbol %u section name out of range: %u >= %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. FIXME: Handle SHN_XINDEX.
|
#. FIXME: Handle SHN_XINDEX.
|
||||||
#: object.cc:869
|
#: object.cc:880
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unknown section index %u for local symbol %u"
|
msgid "unknown section index %u for local symbol %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:878
|
#: object.cc:889
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "local symbol %u section index %u out of range"
|
msgid "local symbol %u section index %u out of range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1181
|
#: object.cc:1192
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: incompatible target"
|
msgid "%s: incompatible target"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1336
|
#: object.cc:1347
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported ELF file type %d"
|
msgid "%s: unsupported ELF file type %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1355 object.cc:1401 object.cc:1435
|
#: object.cc:1366 object.cc:1412 object.cc:1446
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: ELF file too short"
|
msgid "%s: ELF file too short"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1363
|
#: object.cc:1374
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: invalid ELF version 0"
|
msgid "%s: invalid ELF version 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1365
|
#: object.cc:1376
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported ELF version %d"
|
msgid "%s: unsupported ELF version %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1372
|
#: object.cc:1383
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: invalid ELF class 0"
|
msgid "%s: invalid ELF class 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1378
|
#: object.cc:1389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported ELF class %d"
|
msgid "%s: unsupported ELF class %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1385
|
#: object.cc:1396
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: invalid ELF data encoding"
|
msgid "%s: invalid ELF data encoding"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1391
|
#: object.cc:1402
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported ELF data encoding %d"
|
msgid "%s: unsupported ELF data encoding %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1411
|
#: object.cc:1422
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: not configured to support 32-bit big-endian object"
|
msgid "%s: not configured to support 32-bit big-endian object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1424
|
#: object.cc:1435
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: not configured to support 32-bit little-endian object"
|
msgid "%s: not configured to support 32-bit little-endian object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1445
|
#: object.cc:1456
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: not configured to support 64-bit big-endian object"
|
msgid "%s: not configured to support 64-bit big-endian object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: object.cc:1458
|
#: object.cc:1469
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: not configured to support 64-bit little-endian object"
|
msgid "%s: not configured to support 64-bit little-endian object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:157
|
#: options.cc:158
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unable to parse script file %s\n"
|
msgid "unable to parse script file %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:185
|
#: options.cc:185
|
||||||
|
@ -576,337 +652,361 @@ msgid "]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:390
|
#: options.cc:390
|
||||||
msgid "Demangle C++ symbols in log messages"
|
msgid "Define a symbol"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:391
|
||||||
|
msgid "--defsym SYMBOL=EXPRESSION"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:393
|
#: options.cc:393
|
||||||
msgid "Do not demangle C++ symbols in log messages"
|
msgid "Demangle C++ symbols in log messages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:396
|
#: options.cc:396
|
||||||
|
msgid "Do not demangle C++ symbols in log messages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:399
|
||||||
msgid "Try to detect violations of the One Definition Rule"
|
msgid "Try to detect violations of the One Definition Rule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:398
|
#: options.cc:401
|
||||||
msgid "Export all dynamic symbols"
|
msgid "Set program start address"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:400
|
|
||||||
msgid "Create exception frame header"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:402
|
#: options.cc:402
|
||||||
msgid "Set dynamic linker path"
|
msgid "-e ADDRESS, --entry ADDRESS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:403
|
#: options.cc:404
|
||||||
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
|
msgid "Export all dynamic symbols"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: options.cc:405
|
|
||||||
msgid "Search for library LIBNAME"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:406
|
#: options.cc:406
|
||||||
msgid "-lLIBNAME, --library LIBNAME"
|
msgid "Create exception frame header"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:408
|
#: options.cc:408
|
||||||
msgid "Add directory to search path"
|
msgid "Set shared library name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:409
|
#: options.cc:409
|
||||||
msgid "-L DIR, --library-path DIR"
|
msgid "-h FILENAME, -soname FILENAME"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:411
|
#: options.cc:411
|
||||||
msgid "Ignored for compatibility"
|
msgid "Set dynamic linker path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:413
|
#: options.cc:412
|
||||||
msgid "Set output file name"
|
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:414
|
#: options.cc:414
|
||||||
msgid "-o FILE, --output FILE"
|
msgid "Search for library LIBNAME"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:416
|
#: options.cc:415
|
||||||
msgid "Optimize output file size"
|
msgid "-lLIBNAME, --library LIBNAME"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:417
|
#: options.cc:417
|
||||||
msgid "-O level"
|
msgid "Add directory to search path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:419
|
#: options.cc:418
|
||||||
msgid "Generate relocatable output"
|
msgid "-L DIR, --library-path DIR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:421
|
#: options.cc:420
|
||||||
msgid "Add DIR to runtime search path"
|
msgid "Ignored for compatibility"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:422
|
#: options.cc:422
|
||||||
msgid "-R DIR, -rpath DIR"
|
msgid "Set output file name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:423
|
||||||
|
msgid "-o FILE, --output FILE"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:425
|
#: options.cc:425
|
||||||
msgid "Add DIR to link time shared library search path"
|
msgid "Optimize output file size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:426
|
#: options.cc:426
|
||||||
msgid "--rpath-link DIR"
|
msgid "-O level"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:428
|
#: options.cc:428
|
||||||
msgid "Strip all symbols"
|
msgid "Generate relocatable output"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:430
|
||||||
|
msgid "Add DIR to runtime search path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:431
|
#: options.cc:431
|
||||||
|
msgid "-R DIR, -rpath DIR"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:434
|
||||||
|
msgid "Add DIR to link time shared library search path"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:435
|
||||||
|
msgid "--rpath-link DIR"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:437
|
||||||
|
msgid "Strip all symbols"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: options.cc:440
|
||||||
msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)"
|
msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. This must come after -Sdebug since it's a prefix of it.
|
#. This must come after -Sdebug since it's a prefix of it.
|
||||||
#: options.cc:435
|
#: options.cc:444
|
||||||
msgid "Strip debugging information"
|
msgid "Strip debugging information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:437
|
#: options.cc:446
|
||||||
msgid "Generate shared library"
|
msgid "Generate shared library"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:439
|
#: options.cc:448
|
||||||
msgid "Do not link against shared libraries"
|
msgid "Do not link against shared libraries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:441
|
#: options.cc:450
|
||||||
msgid "Print resource usage statistics"
|
msgid "Print resource usage statistics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:443
|
#: options.cc:452
|
||||||
msgid "Set target system root directory"
|
msgid "Set target system root directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:444
|
#: options.cc:453
|
||||||
msgid "--sysroot DIR"
|
msgid "--sysroot DIR"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:445
|
#: options.cc:454
|
||||||
msgid "Set the address of the .text section"
|
msgid "Set the address of the .text section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:446
|
#: options.cc:455
|
||||||
msgid "-Ttext ADDRESS"
|
msgid "-Ttext ADDRESS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. This must come after -Ttext since it's a prefix of it.
|
#. This must come after -Ttext since it's a prefix of it.
|
||||||
#: options.cc:449
|
#: options.cc:458
|
||||||
msgid "Read linker script"
|
msgid "Read linker script"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:450
|
#: options.cc:459
|
||||||
msgid "-T FILE, --script FILE"
|
msgid "-T FILE, --script FILE"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:452
|
#: options.cc:461
|
||||||
msgid "Run the linker multi-threaded"
|
msgid "Run the linker multi-threaded"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:454
|
#: options.cc:463
|
||||||
msgid "Do not run the linker multi-threaded"
|
msgid "Do not run the linker multi-threaded"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:456
|
#: options.cc:465
|
||||||
msgid "Number of threads to use"
|
msgid "Number of threads to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:457
|
#: options.cc:466
|
||||||
msgid "--thread-count COUNT"
|
msgid "--thread-count COUNT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:460
|
#: options.cc:469
|
||||||
msgid "Number of threads to use in initial pass"
|
msgid "Number of threads to use in initial pass"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:461
|
#: options.cc:470
|
||||||
msgid "--thread-count-initial COUNT"
|
msgid "--thread-count-initial COUNT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:464
|
#: options.cc:473
|
||||||
msgid "Number of threads to use in middle pass"
|
msgid "Number of threads to use in middle pass"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:465
|
#: options.cc:474
|
||||||
msgid "--thread-count-middle COUNT"
|
msgid "--thread-count-middle COUNT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:468
|
#: options.cc:477
|
||||||
msgid "Number of threads to use in final pass"
|
msgid "Number of threads to use in final pass"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:469
|
#: options.cc:478
|
||||||
msgid "--thread-count-final COUNT"
|
msgid "--thread-count-final COUNT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:472
|
#: options.cc:481
|
||||||
msgid "Include all archive contents"
|
msgid "Include all archive contents"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:476
|
#: options.cc:485
|
||||||
msgid "Include only needed archive contents"
|
msgid "Include only needed archive contents"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:481
|
#: options.cc:490
|
||||||
msgid ""
|
msgid ""
|
||||||
"Subcommands as follows:\n"
|
"Subcommands as follows:\n"
|
||||||
" -z execstack Mark output as requiring executable stack\n"
|
" -z execstack Mark output as requiring executable stack\n"
|
||||||
" -z noexecstack Mark output as not requiring executable stack"
|
" -z noexecstack Mark output as not requiring executable stack"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:484
|
#: options.cc:493
|
||||||
msgid "-z SUBCOMMAND"
|
msgid "-z SUBCOMMAND"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:487
|
#: options.cc:496
|
||||||
msgid "Start a library search group"
|
msgid "Start a library search group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:489
|
#: options.cc:498
|
||||||
msgid "End a library search group"
|
msgid "End a library search group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:491
|
#: options.cc:500
|
||||||
msgid "Report usage information"
|
msgid "Report usage information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:493
|
#: options.cc:502
|
||||||
msgid "Report version information"
|
msgid "Report version information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:495
|
#: options.cc:504
|
||||||
msgid "Turn on debugging (all,task)"
|
msgid "Turn on debugging (all,task)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:496
|
#: options.cc:505
|
||||||
msgid "--debug=TYPE"
|
msgid "--debug=TYPE"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:590
|
#: options.cc:600
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unrecognized -z subcommand: %s\n"
|
msgid "%s: unrecognized -z subcommand: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:613
|
#: options.cc:623
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unrecognized --debug subcommand: %s\n"
|
msgid "%s: unrecognized --debug subcommand: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:793
|
#: options.cc:812
|
||||||
msgid "unexpected argument"
|
msgid "unexpected argument"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:800 options.cc:852 options.cc:933
|
#: options.cc:819 options.cc:871 options.cc:952
|
||||||
msgid "missing argument"
|
msgid "missing argument"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:813 options.cc:861
|
#: options.cc:832 options.cc:880
|
||||||
msgid "unknown option"
|
msgid "unknown option"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:879
|
#: options.cc:898
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: missing group end\n"
|
msgid "%s: missing group end\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1007
|
#: options.cc:1026
|
||||||
msgid "may not nest groups"
|
msgid "may not nest groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1017
|
#: options.cc:1036
|
||||||
msgid "group end without group start"
|
msgid "group end without group start"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1027
|
#: options.cc:1046
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: use the --help option for usage information\n"
|
msgid "%s: use the --help option for usage information\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1036
|
#: options.cc:1055
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s: %s\n"
|
msgid "%s: %s: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.cc:1045
|
#: options.cc:1064
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: -%c: %s\n"
|
msgid "%s: -%c: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:331
|
#: options.h:358
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid optimization level: %s"
|
msgid "invalid optimization level: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:377
|
#: options.h:404
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unsupported argument to --compress-debug-sections: %s"
|
msgid "unsupported argument to --compress-debug-sections: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:428
|
#: options.h:458
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid argument to -Ttext: %s"
|
msgid "invalid argument to -Ttext: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:437
|
#: options.h:467
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid thread count: %s"
|
msgid "invalid thread count: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: options.h:445
|
#: options.h:475
|
||||||
msgid "--threads not supported"
|
msgid "--threads not supported"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:1478
|
#: output.cc:1511
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "invalid alignment %lu for section \"%s\""
|
msgid "invalid alignment %lu for section \"%s\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2383
|
#: output.cc:2418
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: open: %s"
|
msgid "%s: open: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2403
|
#: output.cc:2438
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: mremap: %s"
|
msgid "%s: mremap: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2439
|
#: output.cc:2474
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: lseek: %s"
|
msgid "%s: lseek: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2442 output.cc:2479
|
#: output.cc:2477 output.cc:2514
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: write: %s"
|
msgid "%s: write: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2450
|
#: output.cc:2485
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: mmap: %s"
|
msgid "%s: mmap: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2460
|
#: output.cc:2495
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: munmap: %s"
|
msgid "%s: munmap: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2477
|
#: output.cc:2512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: write: unexpected 0 return-value"
|
msgid "%s: write: unexpected 0 return-value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: output.cc:2489
|
#: output.cc:2524
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: close: %s"
|
msgid "%s: close: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -927,22 +1027,22 @@ msgstr ""
|
||||||
msgid "%s: not an object or archive"
|
msgid "%s: not an object or archive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: reloc.cc:225 reloc.cc:548
|
#: reloc.cc:232 reloc.cc:588
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "relocation section %u uses unexpected symbol table %u"
|
msgid "relocation section %u uses unexpected symbol table %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: reloc.cc:240 reloc.cc:566
|
#: reloc.cc:247 reloc.cc:606
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unexpected entsize for reloc section %u: %lu != %u"
|
msgid "unexpected entsize for reloc section %u: %lu != %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: reloc.cc:249 reloc.cc:575
|
#: reloc.cc:256 reloc.cc:615
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "reloc section %u size %lu uneven"
|
msgid "reloc section %u size %lu uneven"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: reloc.cc:839
|
#: reloc.cc:879
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "reloc section size %zu is not a multiple of reloc size %d\n"
|
msgid "reloc section size %zu is not a multiple of reloc size %d\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -961,40 +1061,45 @@ msgstr ""
|
||||||
|
|
||||||
#. Two definitions of the same symbol.
|
#. Two definitions of the same symbol.
|
||||||
#. FIXME: Do a better job of reporting locations.
|
#. FIXME: Do a better job of reporting locations.
|
||||||
#: resolve.cc:318
|
#: resolve.cc:322
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: multiple definition of %s"
|
msgid "%s: multiple definition of %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: resolve.cc:319 resolve.cc:324
|
#: resolve.cc:323 resolve.cc:328
|
||||||
msgid "command line"
|
msgid "command line"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: resolve.cc:321
|
#: resolve.cc:325
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: previous definition here"
|
msgid "%s: previous definition here"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. There are some options that we could handle here--e.g.,
|
#: script.cc:1413
|
||||||
#. -lLIBRARY. Should we bother?
|
|
||||||
#: script.cc:1333
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid "%s:%d:%d: %s"
|
||||||
"%s: Ignoring command OPTION; OPTION is only valid for scripts specified via -"
|
|
||||||
"T"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stringpool.cc:537
|
#. There are some options that we could handle here--e.g.,
|
||||||
|
#. -lLIBRARY. Should we bother?
|
||||||
|
#: script.cc:1539
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s:%d:%d: ignoring command OPTION; OPTION is only valid for scripts "
|
||||||
|
"specified via -T/--script"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: stringpool.cc:525
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s entries: %zu; buckets: %zu\n"
|
msgid "%s: %s entries: %zu; buckets: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stringpool.cc:541
|
#: stringpool.cc:529
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s entries: %zu\n"
|
msgid "%s: %s entries: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: stringpool.cc:544
|
#: stringpool.cc:532
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: %s Stringdata structures: %zu\n"
|
msgid "%s: %s Stringdata structures: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1023,27 +1128,27 @@ msgstr ""
|
||||||
msgid "versym for symbol %zu has no name: %u"
|
msgid "versym for symbol %zu has no name: %u"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1493 symtab.cc:1709
|
#: symtab.cc:1499 symtab.cc:1715
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: unsupported symbol section 0x%x"
|
msgid "%s: unsupported symbol section 0x%x"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1833
|
#: symtab.cc:1839
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: undefined reference to '%s'"
|
msgid "%s: undefined reference to '%s'"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1918
|
#: symtab.cc:1924
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: symbol table entries: %zu; buckets: %zu\n"
|
msgid "%s: symbol table entries: %zu; buckets: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1921
|
#: symtab.cc:1927
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s: symbol table entries: %zu\n"
|
msgid "%s: symbol table entries: %zu\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: symtab.cc:1990
|
#: symtab.cc:1996
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"while linking %s: symbol '%s' defined in multiple places (possible ODR "
|
"while linking %s: symbol '%s' defined in multiple places (possible ODR "
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// resolve.cc -- symbol resolution for gold
|
// resolve.cc -- symbol resolution for gold
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -277,11 +277,15 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
|
||||||
{
|
{
|
||||||
*adjust_common_sizes = false;
|
*adjust_common_sizes = false;
|
||||||
|
|
||||||
unsigned int tobits = symbol_to_bits(to->binding(),
|
unsigned int tobits;
|
||||||
(to->source() == Symbol::FROM_OBJECT
|
if (to->source() == Symbol::FROM_OBJECT)
|
||||||
&& to->object()->is_dynamic()),
|
tobits = symbol_to_bits(to->binding(),
|
||||||
to->shndx(),
|
to->object()->is_dynamic(),
|
||||||
to->type());
|
to->shndx(),
|
||||||
|
to->type());
|
||||||
|
else
|
||||||
|
tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS,
|
||||||
|
to->type());
|
||||||
|
|
||||||
// FIXME: Warn if either but not both of TO and SYM are STT_TLS.
|
// FIXME: Warn if either but not both of TO and SYM are STT_TLS.
|
||||||
|
|
||||||
|
|
141
gold/script-c.h
141
gold/script-c.h
|
@ -1,6 +1,6 @@
|
||||||
/* script-c.h -- C interface for linker scripts in gold. */
|
/* script-c.h -- C interface for linker scripts in gold. */
|
||||||
|
|
||||||
/* Copyright 2006, 2007 Free Software Foundation, Inc.
|
/* Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
Written by Ian Lance Taylor <iant@google.com>.
|
Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
This file is part of gold.
|
This file is part of gold.
|
||||||
|
@ -30,6 +30,31 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* A string value for the bison parser. */
|
||||||
|
|
||||||
|
struct Parser_string
|
||||||
|
{
|
||||||
|
const char* value;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The expression functions deal with pointers to Expression objects.
|
||||||
|
Since the bison parser generates C code, this is a hack to keep the
|
||||||
|
C++ code type safe. This hacks assumes that all pointers look
|
||||||
|
alike. */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
namespace gold
|
||||||
|
{
|
||||||
|
class Expression;
|
||||||
|
}
|
||||||
|
typedef gold::Expression* Expression_ptr;
|
||||||
|
#else
|
||||||
|
typedef void* Expression_ptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The bison parser definitions. */
|
||||||
|
|
||||||
#include "yyscript.h"
|
#include "yyscript.h"
|
||||||
|
|
||||||
/* The bison parser function. */
|
/* The bison parser function. */
|
||||||
|
@ -50,7 +75,7 @@ yyerror(void* closure, const char*);
|
||||||
/* Called by the bison parser to add a file to the link. */
|
/* Called by the bison parser to add a file to the link. */
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
script_add_file(void* closure, const char*);
|
script_add_file(void* closure, const char*, size_t);
|
||||||
|
|
||||||
/* Called by the bison parser to start and stop a group. */
|
/* Called by the bison parser to start and stop a group. */
|
||||||
|
|
||||||
|
@ -69,11 +94,119 @@ script_end_as_needed(void* closure);
|
||||||
/* Called by the bison parser to set the entry symbol. */
|
/* Called by the bison parser to set the entry symbol. */
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
script_set_entry(void* closure, const char*);
|
script_set_entry(void* closure, const char*, size_t);
|
||||||
|
|
||||||
/* Called by the bison parser to parse an OPTION. */
|
/* Called by the bison parser to parse an OPTION. */
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
script_parse_option(void* closure, const char*);
|
script_parse_option(void* closure, const char*, size_t);
|
||||||
|
|
||||||
|
/* Called by the bison parser to push the lexer into expression
|
||||||
|
mode. */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
script_push_lex_into_expression_mode(void* closure);
|
||||||
|
|
||||||
|
/* Called by the bison parser to pop the lexer mode. */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
script_pop_lex_mode(void* closure);
|
||||||
|
|
||||||
|
/* Called by the bison parser to set a symbol to a value. PROVIDE is
|
||||||
|
non-zero if the symbol should be provided--only defined if there is
|
||||||
|
an undefined reference. HIDDEN is non-zero if the symbol should be
|
||||||
|
hidden. */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
script_set_symbol(void* closure, const char*, size_t, Expression_ptr,
|
||||||
|
int provide, int hidden);
|
||||||
|
|
||||||
|
/* Called by the bison parser for expressions. */
|
||||||
|
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_unary_minus(Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_unary_logical_not(Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_unary_bitwise_not(Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_mult(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_div(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_mod(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_add(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_sub(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_lshift(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_rshift(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_eq(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_ne(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_le(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_ge(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_lt(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_gt(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_bitwise_and(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_bitwise_xor(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_bitwise_or(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_logical_and(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_binary_logical_or(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_trinary_cond(Expression_ptr, Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_integer(uint64_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_string(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_max(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_min(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_defined(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_sizeof_headers();
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_alignof(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_sizeof(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_addr(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_loadaddr(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_origin(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_length(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_constant(const char*, size_t);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_absolute(Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_align(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_data_segment_align(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_data_segment_relro_end(Expression_ptr, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_data_segment_end(Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_segment_start(const char*, size_t, Expression_ptr);
|
||||||
|
extern Expression_ptr
|
||||||
|
script_exp_function_assert(Expression_ptr, const char*, size_t);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
580
gold/script.cc
580
gold/script.cc
|
@ -1,6 +1,6 @@
|
||||||
// script.cc -- handle linker scripts for gold.
|
// script.cc -- handle linker scripts for gold.
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "filenames.h"
|
#include "filenames.h"
|
||||||
|
|
||||||
|
#include "elfcpp.h"
|
||||||
#include "dirsearch.h"
|
#include "dirsearch.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "fileread.h"
|
#include "fileread.h"
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
#include "readsyms.h"
|
#include "readsyms.h"
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
#include "yyscript.h"
|
#include "symtab.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "script-c.h"
|
#include "script-c.h"
|
||||||
|
|
||||||
|
@ -57,6 +58,8 @@ class Token
|
||||||
TOKEN_EOF,
|
TOKEN_EOF,
|
||||||
// Token is a string of characters.
|
// Token is a string of characters.
|
||||||
TOKEN_STRING,
|
TOKEN_STRING,
|
||||||
|
// Token is a quoted string of characters.
|
||||||
|
TOKEN_QUOTED_STRING,
|
||||||
// Token is an operator.
|
// Token is an operator.
|
||||||
TOKEN_OPERATOR,
|
TOKEN_OPERATOR,
|
||||||
// Token is a number (an integer).
|
// Token is a number (an integer).
|
||||||
|
@ -65,39 +68,33 @@ class Token
|
||||||
|
|
||||||
// We need an empty constructor so that we can put this STL objects.
|
// We need an empty constructor so that we can put this STL objects.
|
||||||
Token()
|
Token()
|
||||||
: classification_(TOKEN_INVALID), value_(), opcode_(0),
|
: classification_(TOKEN_INVALID), value_(NULL), value_length_(0),
|
||||||
lineno_(0), charpos_(0)
|
opcode_(0), lineno_(0), charpos_(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// A general token with no value.
|
// A general token with no value.
|
||||||
Token(Classification classification, int lineno, int charpos)
|
Token(Classification classification, int lineno, int charpos)
|
||||||
: classification_(classification), value_(), opcode_(0),
|
: classification_(classification), value_(NULL), value_length_(0),
|
||||||
lineno_(lineno), charpos_(charpos)
|
opcode_(0), lineno_(lineno), charpos_(charpos)
|
||||||
{
|
{
|
||||||
gold_assert(classification == TOKEN_INVALID
|
gold_assert(classification == TOKEN_INVALID
|
||||||
|| classification == TOKEN_EOF);
|
|| classification == TOKEN_EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A general token with a value.
|
// A general token with a value.
|
||||||
Token(Classification classification, const std::string& value,
|
Token(Classification classification, const char* value, size_t length,
|
||||||
int lineno, int charpos)
|
int lineno, int charpos)
|
||||||
: classification_(classification), value_(value), opcode_(0),
|
: classification_(classification), value_(value), value_length_(length),
|
||||||
lineno_(lineno), charpos_(charpos)
|
opcode_(0), lineno_(lineno), charpos_(charpos)
|
||||||
{
|
{
|
||||||
gold_assert(classification != TOKEN_INVALID
|
gold_assert(classification != TOKEN_INVALID
|
||||||
&& classification != TOKEN_EOF);
|
&& classification != TOKEN_EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A token representing a string of characters.
|
|
||||||
Token(const std::string& s, int lineno, int charpos)
|
|
||||||
: classification_(TOKEN_STRING), value_(s), opcode_(0),
|
|
||||||
lineno_(lineno), charpos_(charpos)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
// A token representing an operator.
|
// A token representing an operator.
|
||||||
Token(int opcode, int lineno, int charpos)
|
Token(int opcode, int lineno, int charpos)
|
||||||
: classification_(TOKEN_OPERATOR), value_(), opcode_(opcode),
|
: classification_(TOKEN_OPERATOR), value_(NULL), value_length_(0),
|
||||||
lineno_(lineno), charpos_(charpos)
|
opcode_(opcode), lineno_(lineno), charpos_(charpos)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Return whether the token is invalid.
|
// Return whether the token is invalid.
|
||||||
|
@ -127,10 +124,12 @@ class Token
|
||||||
|
|
||||||
// Get the value of a token.
|
// Get the value of a token.
|
||||||
|
|
||||||
const std::string&
|
const char*
|
||||||
string_value() const
|
string_value(size_t* length) const
|
||||||
{
|
{
|
||||||
gold_assert(this->classification_ == TOKEN_STRING);
|
gold_assert(this->classification_ == TOKEN_STRING
|
||||||
|
|| this->classification_ == TOKEN_QUOTED_STRING);
|
||||||
|
*length = this->value_length_;
|
||||||
return this->value_;
|
return this->value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,18 +140,23 @@ class Token
|
||||||
return this->opcode_;
|
return this->opcode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
uint64_t
|
||||||
integer_value() const
|
integer_value() const
|
||||||
{
|
{
|
||||||
gold_assert(this->classification_ == TOKEN_INTEGER);
|
gold_assert(this->classification_ == TOKEN_INTEGER);
|
||||||
return strtoll(this->value_.c_str(), NULL, 0);
|
// Null terminate.
|
||||||
|
std::string s(this->value_, this->value_length_);
|
||||||
|
return strtoull(s.c_str(), NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The token classification.
|
// The token classification.
|
||||||
Classification classification_;
|
Classification classification_;
|
||||||
// The token value, for TOKEN_STRING or TOKEN_INTEGER.
|
// The token value, for TOKEN_STRING or TOKEN_QUOTED_STRING or
|
||||||
std::string value_;
|
// TOKEN_INTEGER.
|
||||||
|
const char* value_;
|
||||||
|
// The length of the token value.
|
||||||
|
size_t value_length_;
|
||||||
// The token value, for TOKEN_OPERATOR.
|
// The token value, for TOKEN_OPERATOR.
|
||||||
int opcode_;
|
int opcode_;
|
||||||
// The line number where this token started (one based).
|
// The line number where this token started (one based).
|
||||||
|
@ -162,80 +166,95 @@ class Token
|
||||||
int charpos_;
|
int charpos_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class handles lexing a file into a sequence of tokens. We
|
// This class handles lexing a file into a sequence of tokens.
|
||||||
// don't expect linker scripts to be large, so we just read them and
|
|
||||||
// tokenize them all at once.
|
|
||||||
|
|
||||||
class Lex
|
class Lex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Lex(Input_file* input_file)
|
// We unfortunately have to support different lexing modes, because
|
||||||
: input_file_(input_file), tokens_()
|
// when reading different parts of a linker script we need to parse
|
||||||
|
// things differently.
|
||||||
|
enum Mode
|
||||||
|
{
|
||||||
|
// Reading an ordinary linker script.
|
||||||
|
LINKER_SCRIPT,
|
||||||
|
// Reading an expression in a linker script.
|
||||||
|
EXPRESSION,
|
||||||
|
// Reading a version script.
|
||||||
|
VERSION_SCRIPT
|
||||||
|
};
|
||||||
|
|
||||||
|
Lex(const char* input_string, size_t input_length, int parsing_token)
|
||||||
|
: input_string_(input_string), input_length_(input_length),
|
||||||
|
current_(input_string), mode_(LINKER_SCRIPT),
|
||||||
|
first_token_(parsing_token), token_(),
|
||||||
|
lineno_(1), linestart_(input_string)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Tokenize the file. Return the final token, which will be either
|
// Read a file into a string.
|
||||||
// an invalid token or an EOF token. An invalid token indicates
|
static void
|
||||||
// that tokenization failed.
|
read_file(Input_file*, std::string*);
|
||||||
Token
|
|
||||||
tokenize();
|
|
||||||
|
|
||||||
// A token sequence.
|
// Return the next token.
|
||||||
typedef std::vector<Token> Token_sequence;
|
const Token*
|
||||||
|
next_token();
|
||||||
|
|
||||||
// Return the tokens.
|
// Return the current lexing mode.
|
||||||
const Token_sequence&
|
Lex::Mode
|
||||||
tokens() const
|
mode() const
|
||||||
{ return this->tokens_; }
|
{ return this->mode_; }
|
||||||
|
|
||||||
|
// Set the lexing mode.
|
||||||
|
void
|
||||||
|
set_mode(Mode mode)
|
||||||
|
{ this->mode_ = mode; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Lex(const Lex&);
|
Lex(const Lex&);
|
||||||
Lex& operator=(const Lex&);
|
Lex& operator=(const Lex&);
|
||||||
|
|
||||||
// Read the file into a string buffer.
|
|
||||||
void
|
|
||||||
read_file(std::string*);
|
|
||||||
|
|
||||||
// Make a general token with no value at the current location.
|
// Make a general token with no value at the current location.
|
||||||
Token
|
Token
|
||||||
make_token(Token::Classification c, const char* p) const
|
make_token(Token::Classification c, const char* start) const
|
||||||
{ return Token(c, this->lineno_, p - this->linestart_ + 1); }
|
{ return Token(c, this->lineno_, start - this->linestart_ + 1); }
|
||||||
|
|
||||||
// Make a general token with a value at the current location.
|
// Make a general token with a value at the current location.
|
||||||
Token
|
Token
|
||||||
make_token(Token::Classification c, const std::string& v, const char* p)
|
make_token(Token::Classification c, const char* v, size_t len,
|
||||||
|
const char* start)
|
||||||
const
|
const
|
||||||
{ return Token(c, v, this->lineno_, p - this->linestart_ + 1); }
|
{ return Token(c, v, len, this->lineno_, start - this->linestart_ + 1); }
|
||||||
|
|
||||||
// Make an operator token at the current location.
|
// Make an operator token at the current location.
|
||||||
Token
|
Token
|
||||||
make_token(int opcode, const char* p) const
|
make_token(int opcode, const char* start) const
|
||||||
{ return Token(opcode, this->lineno_, p - this->linestart_ + 1); }
|
{ return Token(opcode, this->lineno_, start - this->linestart_ + 1); }
|
||||||
|
|
||||||
// Make an invalid token at the current location.
|
// Make an invalid token at the current location.
|
||||||
Token
|
Token
|
||||||
make_invalid_token(const char* p)
|
make_invalid_token(const char* start)
|
||||||
{ return this->make_token(Token::TOKEN_INVALID, p); }
|
{ return this->make_token(Token::TOKEN_INVALID, start); }
|
||||||
|
|
||||||
// Make an EOF token at the current location.
|
// Make an EOF token at the current location.
|
||||||
Token
|
Token
|
||||||
make_eof_token(const char* p)
|
make_eof_token(const char* start)
|
||||||
{ return this->make_token(Token::TOKEN_EOF, p); }
|
{ return this->make_token(Token::TOKEN_EOF, start); }
|
||||||
|
|
||||||
// Return whether C can be the first character in a name. C2 is the
|
// Return whether C can be the first character in a name. C2 is the
|
||||||
// next character, since we sometimes need that.
|
// next character, since we sometimes need that.
|
||||||
static inline bool
|
inline bool
|
||||||
can_start_name(char c, char c2);
|
can_start_name(char c, char c2);
|
||||||
|
|
||||||
// Return whether C can appear in a name which has already started.
|
// Return whether C can appear in a name which has already started.
|
||||||
static inline bool
|
inline bool
|
||||||
can_continue_name(char c);
|
can_continue_name(char c);
|
||||||
|
|
||||||
// Return whether C, C2, C3 can start a hex number.
|
// Return whether C, C2, C3 can start a hex number.
|
||||||
static inline bool
|
inline bool
|
||||||
can_start_hex(char c, char c2, char c3);
|
can_start_hex(char c, char c2, char c3);
|
||||||
|
|
||||||
// Return whether C can appear in a hex number.
|
// Return whether C can appear in a hex number.
|
||||||
static inline bool
|
inline bool
|
||||||
can_continue_hex(char c);
|
can_continue_hex(char c);
|
||||||
|
|
||||||
// Return whether C can start a non-hex number.
|
// Return whether C can start a non-hex number.
|
||||||
|
@ -243,7 +262,7 @@ class Lex
|
||||||
can_start_number(char c);
|
can_start_number(char c);
|
||||||
|
|
||||||
// Return whether C can appear in a non-hex number.
|
// Return whether C can appear in a non-hex number.
|
||||||
static inline bool
|
inline bool
|
||||||
can_continue_number(char c)
|
can_continue_number(char c)
|
||||||
{ return Lex::can_start_number(c); }
|
{ return Lex::can_start_number(c); }
|
||||||
|
|
||||||
|
@ -279,20 +298,30 @@ class Lex
|
||||||
// CAN_CONTINUE_FN. The token starts at START. Start matching from
|
// CAN_CONTINUE_FN. The token starts at START. Start matching from
|
||||||
// MATCH. Set *PP to the character following the token.
|
// MATCH. Set *PP to the character following the token.
|
||||||
inline Token
|
inline Token
|
||||||
gather_token(Token::Classification, bool (*can_continue_fn)(char),
|
gather_token(Token::Classification,
|
||||||
|
bool (Lex::*can_continue_fn)(char),
|
||||||
const char* start, const char* match, const char** pp);
|
const char* start, const char* match, const char** pp);
|
||||||
|
|
||||||
// Build a token from a quoted string.
|
// Build a token from a quoted string.
|
||||||
Token
|
Token
|
||||||
gather_quoted_string(const char** pp);
|
gather_quoted_string(const char** pp);
|
||||||
|
|
||||||
// The file we are reading.
|
// The string we are tokenizing.
|
||||||
Input_file* input_file_;
|
const char* input_string_;
|
||||||
// The token sequence we create.
|
// The length of the string.
|
||||||
Token_sequence tokens_;
|
size_t input_length_;
|
||||||
|
// The current offset into the string.
|
||||||
|
const char* current_;
|
||||||
|
// The current lexing mode.
|
||||||
|
Mode mode_;
|
||||||
|
// The code to use for the first token. This is set to 0 after it
|
||||||
|
// is used.
|
||||||
|
int first_token_;
|
||||||
|
// The current token.
|
||||||
|
Token token_;
|
||||||
// The current line number.
|
// The current line number.
|
||||||
int lineno_;
|
int lineno_;
|
||||||
// The start of the current line in the buffer.
|
// The start of the current line in the string.
|
||||||
const char* linestart_;
|
const char* linestart_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -301,9 +330,9 @@ class Lex
|
||||||
// data we've already read, so that we read aligned buffers.
|
// data we've already read, so that we read aligned buffers.
|
||||||
|
|
||||||
void
|
void
|
||||||
Lex::read_file(std::string* contents)
|
Lex::read_file(Input_file* input_file, std::string* contents)
|
||||||
{
|
{
|
||||||
off_t filesize = this->input_file_->file().filesize();
|
off_t filesize = input_file->file().filesize();
|
||||||
contents->clear();
|
contents->clear();
|
||||||
contents->reserve(filesize);
|
contents->reserve(filesize);
|
||||||
|
|
||||||
|
@ -314,7 +343,7 @@ Lex::read_file(std::string* contents)
|
||||||
off_t get = BUFSIZ;
|
off_t get = BUFSIZ;
|
||||||
if (get > filesize - off)
|
if (get > filesize - off)
|
||||||
get = filesize - off;
|
get = filesize - off;
|
||||||
this->input_file_->file().read(off, get, buf);
|
input_file->file().read(off, get, buf);
|
||||||
contents->append(reinterpret_cast<char*>(&buf[0]), get);
|
contents->append(reinterpret_cast<char*>(&buf[0]), get);
|
||||||
off += get;
|
off += get;
|
||||||
}
|
}
|
||||||
|
@ -326,8 +355,9 @@ Lex::read_file(std::string* contents)
|
||||||
// forward slash, backslash, and tilde. Tilde is the tricky case
|
// forward slash, backslash, and tilde. Tilde is the tricky case
|
||||||
// here; GNU ld also uses it as a bitwise not operator. It is only
|
// here; GNU ld also uses it as a bitwise not operator. It is only
|
||||||
// recognized as the operator if it is not immediately followed by
|
// recognized as the operator if it is not immediately followed by
|
||||||
// some character which can appear in a symbol. That is, "~0" is a
|
// some character which can appear in a symbol. That is, when we
|
||||||
// symbol name, and "~ 0" is an expression using bitwise not. We are
|
// don't know that we are looking at an expression, "~0" is a file
|
||||||
|
// name, and "~ 0" is an expression using bitwise not. We are
|
||||||
// compatible.
|
// compatible.
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
@ -345,11 +375,14 @@ Lex::can_start_name(char c, char c2)
|
||||||
case 'm': case 'n': case 'o': case 'q': case 'p': case 'r':
|
case 'm': case 'n': case 'o': case 'q': case 'p': case 'r':
|
||||||
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||||
case 'y': case 'z':
|
case 'y': case 'z':
|
||||||
case '_': case '.': case '$': case '/': case '\\':
|
case '_': case '.': case '$':
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case '/': case '\\':
|
||||||
|
return this->mode_ == LINKER_SCRIPT;
|
||||||
|
|
||||||
case '~':
|
case '~':
|
||||||
return can_continue_name(c2);
|
return this->mode_ == LINKER_SCRIPT && can_continue_name(c2);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -359,7 +392,8 @@ Lex::can_start_name(char c, char c2)
|
||||||
// Return whether C can continue a name which has already started.
|
// Return whether C can continue a name which has already started.
|
||||||
// Subsequent characters in a name are the same as the leading
|
// Subsequent characters in a name are the same as the leading
|
||||||
// characters, plus digits and "=+-:[],?*". So in general the linker
|
// characters, plus digits and "=+-:[],?*". So in general the linker
|
||||||
// script language requires spaces around operators.
|
// script language requires spaces around operators, unless we know
|
||||||
|
// that we are parsing an expression.
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
Lex::can_continue_name(char c)
|
Lex::can_continue_name(char c)
|
||||||
|
@ -376,14 +410,17 @@ Lex::can_continue_name(char c)
|
||||||
case 'm': case 'n': case 'o': case 'q': case 'p': case 'r':
|
case 'm': case 'n': case 'o': case 'q': case 'p': case 'r':
|
||||||
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||||
case 'y': case 'z':
|
case 'y': case 'z':
|
||||||
case '_': case '.': case '$': case '/': case '\\':
|
case '_': case '.': case '$':
|
||||||
case '~':
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
case '=': case '+': case '-': case ':': case '[': case ']':
|
|
||||||
case ',': case '?': case '*':
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case '/': case '\\': case '~':
|
||||||
|
case '=': case '+': case '-':
|
||||||
|
case ':': case '[': case ']':
|
||||||
|
case ',': case '?': case '*':
|
||||||
|
return this->mode_ == LINKER_SCRIPT;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -393,8 +430,8 @@ Lex::can_continue_name(char c)
|
||||||
// of digits. The old linker accepts leading '$' for hex, and
|
// of digits. The old linker accepts leading '$' for hex, and
|
||||||
// trailing HXBOD. Those are for MRI compatibility and we don't
|
// trailing HXBOD. Those are for MRI compatibility and we don't
|
||||||
// accept them. The old linker also accepts trailing MK for mega or
|
// accept them. The old linker also accepts trailing MK for mega or
|
||||||
// kilo. Those are mentioned in the documentation, and we accept
|
// kilo. FIXME: Those are mentioned in the documentation, and we
|
||||||
// them.
|
// should accept them.
|
||||||
|
|
||||||
// Return whether C1 C2 C3 can start a hex number.
|
// Return whether C1 C2 C3 can start a hex number.
|
||||||
|
|
||||||
|
@ -402,7 +439,7 @@ inline bool
|
||||||
Lex::can_start_hex(char c1, char c2, char c3)
|
Lex::can_start_hex(char c1, char c2, char c3)
|
||||||
{
|
{
|
||||||
if (c1 == '0' && (c2 == 'x' || c2 == 'X'))
|
if (c1 == '0' && (c2 == 'x' || c2 == 'X'))
|
||||||
return Lex::can_continue_hex(c3);
|
return this->can_continue_hex(c3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,17 +652,15 @@ Lex::skip_line_comment(const char** pp)
|
||||||
|
|
||||||
inline Token
|
inline Token
|
||||||
Lex::gather_token(Token::Classification classification,
|
Lex::gather_token(Token::Classification classification,
|
||||||
bool (*can_continue_fn)(char),
|
bool (Lex::*can_continue_fn)(char),
|
||||||
const char* start,
|
const char* start,
|
||||||
const char* match,
|
const char* match,
|
||||||
const char **pp)
|
const char **pp)
|
||||||
{
|
{
|
||||||
while ((*can_continue_fn)(*match))
|
while ((this->*can_continue_fn)(*match))
|
||||||
++match;
|
++match;
|
||||||
*pp = match;
|
*pp = match;
|
||||||
return this->make_token(classification,
|
return this->make_token(classification, start, match - start, start);
|
||||||
std::string(start, match - start),
|
|
||||||
start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a token from a quoted string.
|
// Build a token from a quoted string.
|
||||||
|
@ -640,9 +675,7 @@ Lex::gather_quoted_string(const char** pp)
|
||||||
if (p[skip] != '"')
|
if (p[skip] != '"')
|
||||||
return this->make_invalid_token(start);
|
return this->make_invalid_token(start);
|
||||||
*pp = p + skip + 1;
|
*pp = p + skip + 1;
|
||||||
return this->make_token(Token::TOKEN_STRING,
|
return this->make_token(Token::TOKEN_QUOTED_STRING, p, skip, start);
|
||||||
std::string(p, skip),
|
|
||||||
start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the next token at *PP. Update *PP. General guideline: we
|
// Return the next token at *PP. Update *PP. General guideline: we
|
||||||
|
@ -700,10 +733,10 @@ Lex::get_token(const char** pp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a name.
|
// Check for a name.
|
||||||
if (Lex::can_start_name(p[0], p[1]))
|
if (this->can_start_name(p[0], p[1]))
|
||||||
return this->gather_token(Token::TOKEN_STRING,
|
return this->gather_token(Token::TOKEN_STRING,
|
||||||
Lex::can_continue_name,
|
&Lex::can_continue_name,
|
||||||
p, p + 2, pp);
|
p, p + 1, pp);
|
||||||
|
|
||||||
// We accept any arbitrary name in double quotes, as long as it
|
// We accept any arbitrary name in double quotes, as long as it
|
||||||
// does not cross a line boundary.
|
// does not cross a line boundary.
|
||||||
|
@ -715,14 +748,14 @@ Lex::get_token(const char** pp)
|
||||||
|
|
||||||
// Check for a number.
|
// Check for a number.
|
||||||
|
|
||||||
if (Lex::can_start_hex(p[0], p[1], p[2]))
|
if (this->can_start_hex(p[0], p[1], p[2]))
|
||||||
return this->gather_token(Token::TOKEN_INTEGER,
|
return this->gather_token(Token::TOKEN_INTEGER,
|
||||||
Lex::can_continue_hex,
|
&Lex::can_continue_hex,
|
||||||
p, p + 3, pp);
|
p, p + 3, pp);
|
||||||
|
|
||||||
if (Lex::can_start_number(p[0]))
|
if (Lex::can_start_number(p[0]))
|
||||||
return this->gather_token(Token::TOKEN_INTEGER,
|
return this->gather_token(Token::TOKEN_INTEGER,
|
||||||
Lex::can_continue_number,
|
&Lex::can_continue_number,
|
||||||
p, p + 1, pp);
|
p, p + 1, pp);
|
||||||
|
|
||||||
// Check for operators.
|
// Check for operators.
|
||||||
|
@ -752,34 +785,29 @@ Lex::get_token(const char** pp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tokenize the file. Return the final token.
|
// Return the next token.
|
||||||
|
|
||||||
Token
|
const Token*
|
||||||
Lex::tokenize()
|
Lex::next_token()
|
||||||
{
|
{
|
||||||
std::string contents;
|
// The first token is special.
|
||||||
this->read_file(&contents);
|
if (this->first_token_ != 0)
|
||||||
|
|
||||||
const char* p = contents.c_str();
|
|
||||||
|
|
||||||
this->lineno_ = 1;
|
|
||||||
this->linestart_ = p;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
Token t(this->get_token(&p));
|
this->token_ = Token(this->first_token_, 0, 0);
|
||||||
|
this->first_token_ = 0;
|
||||||
// Don't let an early null byte fool us into thinking that we've
|
return &this->token_;
|
||||||
// reached the end of the file.
|
|
||||||
if (t.is_eof()
|
|
||||||
&& static_cast<size_t>(p - contents.c_str()) < contents.length())
|
|
||||||
t = this->make_invalid_token(p);
|
|
||||||
|
|
||||||
if (t.is_invalid() || t.is_eof())
|
|
||||||
return t;
|
|
||||||
|
|
||||||
this->tokens_.push_back(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->token_ = this->get_token(&this->current_);
|
||||||
|
|
||||||
|
// Don't let an early null byte fool us into thinking that we've
|
||||||
|
// reached the end of the file.
|
||||||
|
if (this->token_.is_eof()
|
||||||
|
&& (static_cast<size_t>(this->current_ - this->input_string_)
|
||||||
|
< this->input_length_))
|
||||||
|
this->token_ = this->make_invalid_token(this->current_);
|
||||||
|
|
||||||
|
return &this->token_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A trivial task which waits for THIS_BLOCKER to be clear and then
|
// A trivial task which waits for THIS_BLOCKER to be clear and then
|
||||||
|
@ -823,6 +851,79 @@ class Script_unblock : public Task
|
||||||
Task_token* next_blocker_;
|
Task_token* next_blocker_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Class Script_options.
|
||||||
|
|
||||||
|
Script_options::Script_options()
|
||||||
|
: entry_(), symbol_assignments_()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add any symbols we are defining to the symbol table.
|
||||||
|
|
||||||
|
void
|
||||||
|
Script_options::add_symbols_to_table(Symbol_table* symtab,
|
||||||
|
const Target* target)
|
||||||
|
{
|
||||||
|
for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
|
||||||
|
p != this->symbol_assignments_.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
elfcpp::STV vis = p->hidden ? elfcpp::STV_HIDDEN : elfcpp::STV_DEFAULT;
|
||||||
|
p->sym = symtab->define_as_constant(target,
|
||||||
|
p->name.c_str(),
|
||||||
|
NULL, // version
|
||||||
|
0, // value
|
||||||
|
0, // size
|
||||||
|
elfcpp::STT_NOTYPE,
|
||||||
|
elfcpp::STB_GLOBAL,
|
||||||
|
vis,
|
||||||
|
0, // nonvis
|
||||||
|
p->provide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize symbol values.
|
||||||
|
|
||||||
|
void
|
||||||
|
Script_options::finalize_symbols(Symbol_table* symtab, const Layout* layout)
|
||||||
|
{
|
||||||
|
if (parameters->get_size() == 32)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
|
||||||
|
this->sized_finalize_symbols<32>(symtab, layout);
|
||||||
|
#else
|
||||||
|
gold_unreachable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (parameters->get_size() == 64)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
|
||||||
|
this->sized_finalize_symbols<64>(symtab, layout);
|
||||||
|
#else
|
||||||
|
gold_unreachable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gold_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int size>
|
||||||
|
void
|
||||||
|
Script_options::sized_finalize_symbols(Symbol_table* symtab,
|
||||||
|
const Layout* layout)
|
||||||
|
{
|
||||||
|
for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
|
||||||
|
p != this->symbol_assignments_.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
if (p->sym != NULL)
|
||||||
|
{
|
||||||
|
Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(p->sym);
|
||||||
|
ssym->set_value(p->value->eval(symtab, layout));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This class holds data passed through the parser to the lexer and to
|
// This class holds data passed through the parser to the lexer and to
|
||||||
// the parser support functions. This avoids global variables. We
|
// the parser support functions. This avoids global variables. We
|
||||||
// can't use global variables because we need not be called by a
|
// can't use global variables because we need not be called by a
|
||||||
|
@ -835,12 +936,12 @@ class Parser_closure
|
||||||
const Position_dependent_options& posdep_options,
|
const Position_dependent_options& posdep_options,
|
||||||
bool in_group, bool is_in_sysroot,
|
bool in_group, bool is_in_sysroot,
|
||||||
Command_line* command_line,
|
Command_line* command_line,
|
||||||
Layout* layout,
|
Script_options* script_options,
|
||||||
const Lex::Token_sequence* tokens)
|
Lex* lex)
|
||||||
: filename_(filename), posdep_options_(posdep_options),
|
: filename_(filename), posdep_options_(posdep_options),
|
||||||
in_group_(in_group), is_in_sysroot_(is_in_sysroot),
|
in_group_(in_group), is_in_sysroot_(is_in_sysroot),
|
||||||
command_line_(command_line), layout_(layout), tokens_(tokens),
|
command_line_(command_line), script_options_(script_options),
|
||||||
next_token_index_(0), inputs_(NULL)
|
lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Return the file name.
|
// Return the file name.
|
||||||
|
@ -868,36 +969,52 @@ class Parser_closure
|
||||||
// Returns the Command_line structure passed in at constructor time.
|
// Returns the Command_line structure passed in at constructor time.
|
||||||
// This value may be NULL. The caller may modify this, which modifies
|
// This value may be NULL. The caller may modify this, which modifies
|
||||||
// the passed-in Command_line object (not a copy).
|
// the passed-in Command_line object (not a copy).
|
||||||
Command_line* command_line()
|
Command_line*
|
||||||
|
command_line()
|
||||||
{ return this->command_line_; }
|
{ return this->command_line_; }
|
||||||
|
|
||||||
// Return the Layout structure passed in at constructor time. This
|
// Return the options which may be set by a script.
|
||||||
// value may be NULL.
|
Script_options*
|
||||||
Layout* layout()
|
script_options()
|
||||||
{ return this->layout_; }
|
{ return this->script_options_; }
|
||||||
|
|
||||||
// Whether we are at the end of the token list.
|
|
||||||
bool
|
|
||||||
at_eof() const
|
|
||||||
{ return this->next_token_index_ >= this->tokens_->size(); }
|
|
||||||
|
|
||||||
// Return the next token, and advance.
|
// Return the next token, and advance.
|
||||||
const Token*
|
const Token*
|
||||||
next_token()
|
next_token()
|
||||||
{
|
{
|
||||||
const Token* ret = &(*this->tokens_)[this->next_token_index_];
|
const Token* token = this->lex_->next_token();
|
||||||
++this->next_token_index_;
|
this->lineno_ = token->lineno();
|
||||||
return ret;
|
this->charpos_ = token->charpos();
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the previous token.
|
// Set a new lexer mode, pushing the current one.
|
||||||
const Token*
|
void
|
||||||
last_token() const
|
push_lex_mode(Lex::Mode mode)
|
||||||
{
|
{
|
||||||
gold_assert(this->next_token_index_ > 0);
|
this->lex_mode_stack_.push_back(this->lex_->mode());
|
||||||
return &(*this->tokens_)[this->next_token_index_ - 1];
|
this->lex_->set_mode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pop the lexer mode.
|
||||||
|
void
|
||||||
|
pop_lex_mode()
|
||||||
|
{
|
||||||
|
gold_assert(!this->lex_mode_stack_.empty());
|
||||||
|
this->lex_->set_mode(this->lex_mode_stack_.back());
|
||||||
|
this->lex_mode_stack_.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the line number of the last token.
|
||||||
|
int
|
||||||
|
lineno() const
|
||||||
|
{ return this->lineno_; }
|
||||||
|
|
||||||
|
// Return the character position in the line of the last token.
|
||||||
|
int
|
||||||
|
charpos() const
|
||||||
|
{ return this->charpos_; }
|
||||||
|
|
||||||
// Return the list of input files, creating it if necessary. This
|
// Return the list of input files, creating it if necessary. This
|
||||||
// is a space leak--we never free the INPUTS_ pointer.
|
// is a space leak--we never free the INPUTS_ pointer.
|
||||||
Input_arguments*
|
Input_arguments*
|
||||||
|
@ -924,13 +1041,16 @@ class Parser_closure
|
||||||
bool is_in_sysroot_;
|
bool is_in_sysroot_;
|
||||||
// May be NULL if the user chooses not to pass one in.
|
// May be NULL if the user chooses not to pass one in.
|
||||||
Command_line* command_line_;
|
Command_line* command_line_;
|
||||||
// May be NULL if the user chooses not to pass one in.
|
// Options which may be set from any linker script.
|
||||||
Layout* layout_;
|
Script_options* script_options_;
|
||||||
|
// The lexer.
|
||||||
// The tokens to be returned by the lexer.
|
Lex* lex_;
|
||||||
const Lex::Token_sequence* tokens_;
|
// The line number of the last token returned by next_token.
|
||||||
// The index of the next token to return.
|
int lineno_;
|
||||||
unsigned int next_token_index_;
|
// The column number of the last token returned by next_token.
|
||||||
|
int charpos_;
|
||||||
|
// A stack of lexer modes.
|
||||||
|
std::vector<Lex::Mode> lex_mode_stack_;
|
||||||
// New input files found to add to the link.
|
// New input files found to add to the link.
|
||||||
Input_arguments* inputs_;
|
Input_arguments* inputs_;
|
||||||
};
|
};
|
||||||
|
@ -948,17 +1068,18 @@ read_input_script(Workqueue* workqueue, const General_options& options,
|
||||||
Input_file* input_file, const unsigned char*, off_t,
|
Input_file* input_file, const unsigned char*, off_t,
|
||||||
Task_token* this_blocker, Task_token* next_blocker)
|
Task_token* this_blocker, Task_token* next_blocker)
|
||||||
{
|
{
|
||||||
Lex lex(input_file);
|
std::string input_string;
|
||||||
if (lex.tokenize().is_invalid())
|
Lex::read_file(input_file, &input_string);
|
||||||
return false;
|
|
||||||
|
Lex lex(input_string.c_str(), input_string.length(), PARSING_LINKER_SCRIPT);
|
||||||
|
|
||||||
Parser_closure closure(input_file->filename().c_str(),
|
Parser_closure closure(input_file->filename().c_str(),
|
||||||
input_argument->file().options(),
|
input_argument->file().options(),
|
||||||
input_group != NULL,
|
input_group != NULL,
|
||||||
input_file->is_in_sysroot(),
|
input_file->is_in_sysroot(),
|
||||||
NULL,
|
NULL,
|
||||||
layout,
|
layout->script_options(),
|
||||||
&lex.tokens());
|
&lex);
|
||||||
|
|
||||||
if (yyparse(&closure) != 0)
|
if (yyparse(&closure) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1019,21 +1140,18 @@ read_commandline_script(const char* filename, Command_line* cmdline)
|
||||||
if (!input_file.open(cmdline->options(), dirsearch, task))
|
if (!input_file.open(cmdline->options(), dirsearch, task))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Lex lex(&input_file);
|
std::string input_string;
|
||||||
if (lex.tokenize().is_invalid())
|
Lex::read_file(&input_file, &input_string);
|
||||||
{
|
|
||||||
// Opening the file locked it, so now we need to unlock it.
|
Lex lex(input_string.c_str(), input_string.length(), PARSING_LINKER_SCRIPT);
|
||||||
input_file.file().unlock(task);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser_closure closure(filename,
|
Parser_closure closure(filename,
|
||||||
cmdline->position_dependent_options(),
|
cmdline->position_dependent_options(),
|
||||||
false,
|
false,
|
||||||
input_file.is_in_sysroot(),
|
input_file.is_in_sysroot(),
|
||||||
cmdline,
|
cmdline,
|
||||||
NULL,
|
cmdline->script_options(),
|
||||||
&lex.tokens());
|
&lex);
|
||||||
if (yyparse(&closure) != 0)
|
if (yyparse(&closure) != 0)
|
||||||
{
|
{
|
||||||
input_file.file().unlock(task);
|
input_file.file().unlock(task);
|
||||||
|
@ -1047,6 +1165,29 @@ read_commandline_script(const char* filename, Command_line* cmdline)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implement the --defsym option on the command line. Return true if
|
||||||
|
// all is well.
|
||||||
|
|
||||||
|
bool
|
||||||
|
Script_options::define_symbol(const char* definition)
|
||||||
|
{
|
||||||
|
Lex lex(definition, strlen(definition), PARSING_DEFSYM);
|
||||||
|
lex.set_mode(Lex::EXPRESSION);
|
||||||
|
|
||||||
|
// Dummy value.
|
||||||
|
Position_dependent_options posdep_options;
|
||||||
|
|
||||||
|
Parser_closure closure("command line", posdep_options, false, false, NULL,
|
||||||
|
this, &lex);
|
||||||
|
|
||||||
|
if (yyparse(&closure) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
gold_assert(!closure.saw_inputs());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Manage mapping from keywords to the codes expected by the bison
|
// Manage mapping from keywords to the codes expected by the bison
|
||||||
// parser.
|
// parser.
|
||||||
|
|
||||||
|
@ -1065,7 +1206,7 @@ class Keyword_to_parsecode
|
||||||
// Return the parsecode corresponding KEYWORD, or 0 if it is not a
|
// Return the parsecode corresponding KEYWORD, or 0 if it is not a
|
||||||
// keyword.
|
// keyword.
|
||||||
static int
|
static int
|
||||||
keyword_to_parsecode(const char* keyword);
|
keyword_to_parsecode(const char* keyword, size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The array of all keywords.
|
// The array of all keywords.
|
||||||
|
@ -1085,6 +1226,7 @@ Keyword_to_parsecode::keyword_parsecodes_[] =
|
||||||
{ "ABSOLUTE", ABSOLUTE },
|
{ "ABSOLUTE", ABSOLUTE },
|
||||||
{ "ADDR", ADDR },
|
{ "ADDR", ADDR },
|
||||||
{ "ALIGN", ALIGN_K },
|
{ "ALIGN", ALIGN_K },
|
||||||
|
{ "ALIGNOF", ALIGNOF },
|
||||||
{ "ASSERT", ASSERT_K },
|
{ "ASSERT", ASSERT_K },
|
||||||
{ "AS_NEEDED", AS_NEEDED },
|
{ "AS_NEEDED", AS_NEEDED },
|
||||||
{ "AT", AT },
|
{ "AT", AT },
|
||||||
|
@ -1170,21 +1312,35 @@ const int Keyword_to_parsecode::keyword_count =
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct Ktt_key
|
||||||
|
{
|
||||||
|
const char* str;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ktt_compare(const void* keyv, const void* kttv)
|
ktt_compare(const void* keyv, const void* kttv)
|
||||||
{
|
{
|
||||||
const char* key = static_cast<const char*>(keyv);
|
const Ktt_key* key = static_cast<const Ktt_key*>(keyv);
|
||||||
const Keyword_to_parsecode::Keyword_parsecode* ktt =
|
const Keyword_to_parsecode::Keyword_parsecode* ktt =
|
||||||
static_cast<const Keyword_to_parsecode::Keyword_parsecode*>(kttv);
|
static_cast<const Keyword_to_parsecode::Keyword_parsecode*>(kttv);
|
||||||
return strcmp(key, ktt->keyword);
|
int i = strncmp(key->str, ktt->keyword, key->len);
|
||||||
|
if (i != 0)
|
||||||
|
return i;
|
||||||
|
if (ktt->keyword[key->len] != '\0')
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End extern "C".
|
} // End extern "C".
|
||||||
|
|
||||||
int
|
int
|
||||||
Keyword_to_parsecode::keyword_to_parsecode(const char* keyword)
|
Keyword_to_parsecode::keyword_to_parsecode(const char* keyword, size_t len)
|
||||||
{
|
{
|
||||||
void* kttv = bsearch(keyword,
|
Ktt_key key;
|
||||||
|
key.str = keyword;
|
||||||
|
key.len = len;
|
||||||
|
void* kttv = bsearch(&key,
|
||||||
Keyword_to_parsecode::keyword_parsecodes_,
|
Keyword_to_parsecode::keyword_parsecodes_,
|
||||||
Keyword_to_parsecode::keyword_count,
|
Keyword_to_parsecode::keyword_count,
|
||||||
sizeof(Keyword_to_parsecode::keyword_parsecodes_[0]),
|
sizeof(Keyword_to_parsecode::keyword_parsecodes_[0]),
|
||||||
|
@ -1209,29 +1365,36 @@ extern "C" int
|
||||||
yylex(YYSTYPE* lvalp, void* closurev)
|
yylex(YYSTYPE* lvalp, void* closurev)
|
||||||
{
|
{
|
||||||
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
|
|
||||||
if (closure->at_eof())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const Token* token = closure->next_token();
|
const Token* token = closure->next_token();
|
||||||
|
|
||||||
switch (token->classification())
|
switch (token->classification())
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case Token::TOKEN_INVALID:
|
|
||||||
case Token::TOKEN_EOF:
|
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
|
|
||||||
|
case Token::TOKEN_INVALID:
|
||||||
|
yyerror(closurev, "invalid character");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case Token::TOKEN_EOF:
|
||||||
|
return 0;
|
||||||
|
|
||||||
case Token::TOKEN_STRING:
|
case Token::TOKEN_STRING:
|
||||||
{
|
{
|
||||||
const char* str = token->string_value().c_str();
|
// This is either a keyword or a STRING.
|
||||||
int parsecode = Keyword_to_parsecode::keyword_to_parsecode(str);
|
size_t len;
|
||||||
|
const char* str = token->string_value(&len);
|
||||||
|
int parsecode = Keyword_to_parsecode::keyword_to_parsecode(str, len);
|
||||||
if (parsecode != 0)
|
if (parsecode != 0)
|
||||||
return parsecode;
|
return parsecode;
|
||||||
lvalp->string = str;
|
lvalp->string.value = str;
|
||||||
|
lvalp->string.length = len;
|
||||||
return STRING;
|
return STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Token::TOKEN_QUOTED_STRING:
|
||||||
|
lvalp->string.value = token->string_value(&lvalp->string.length);
|
||||||
|
return STRING;
|
||||||
|
|
||||||
case Token::TOKEN_OPERATOR:
|
case Token::TOKEN_OPERATOR:
|
||||||
return token->operator_value();
|
return token->operator_value();
|
||||||
|
|
||||||
|
@ -1247,16 +1410,14 @@ extern "C" void
|
||||||
yyerror(void* closurev, const char* message)
|
yyerror(void* closurev, const char* message)
|
||||||
{
|
{
|
||||||
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
|
gold_error(_("%s:%d:%d: %s"), closure->filename(), closure->lineno(),
|
||||||
const Token* token = closure->last_token();
|
closure->charpos(), message);
|
||||||
gold_error(_("%s:%d:%d: %s"), closure->filename(), token->lineno(),
|
|
||||||
token->charpos(), message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the bison parser to add a file to the link.
|
// Called by the bison parser to add a file to the link.
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
script_add_file(void* closurev, const char* name)
|
script_add_file(void* closurev, const char* name, size_t length)
|
||||||
{
|
{
|
||||||
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
|
|
||||||
|
@ -1264,17 +1425,16 @@ script_add_file(void* closurev, const char* name)
|
||||||
// sysroot, then we want to prepend the sysroot to the file name.
|
// 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
|
// For example, this is how we handle a cross link to the x86_64
|
||||||
// libc.so, which refers to /lib/libc.so.6.
|
// libc.so, which refers to /lib/libc.so.6.
|
||||||
std::string name_string;
|
std::string name_string(name, length);
|
||||||
const char* extra_search_path = ".";
|
const char* extra_search_path = ".";
|
||||||
std::string script_directory;
|
std::string script_directory;
|
||||||
if (IS_ABSOLUTE_PATH (name))
|
if (IS_ABSOLUTE_PATH(name_string.c_str()))
|
||||||
{
|
{
|
||||||
if (closure->is_in_sysroot())
|
if (closure->is_in_sysroot())
|
||||||
{
|
{
|
||||||
const std::string& sysroot(parameters->sysroot());
|
const std::string& sysroot(parameters->sysroot());
|
||||||
gold_assert(!sysroot.empty());
|
gold_assert(!sysroot.empty());
|
||||||
name_string = sysroot + name;
|
name_string = sysroot + name_string;
|
||||||
name = name_string.c_str();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1290,7 +1450,7 @@ script_add_file(void* closurev, const char* name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Input_file_argument file(name, false, extra_search_path,
|
Input_file_argument file(name_string.c_str(), false, extra_search_path,
|
||||||
closure->position_dependent_options());
|
closure->position_dependent_options());
|
||||||
closure->inputs()->add_file(file);
|
closure->inputs()->add_file(file);
|
||||||
}
|
}
|
||||||
|
@ -1345,19 +1505,29 @@ script_end_as_needed(void* closurev)
|
||||||
// Called by the bison parser to set the entry symbol.
|
// Called by the bison parser to set the entry symbol.
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
script_set_entry(void* closurev, const char* entry)
|
script_set_entry(void* closurev, const char* entry, size_t length)
|
||||||
{
|
{
|
||||||
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
if (closure->command_line() != NULL)
|
closure->script_options()->set_entry(entry, length);
|
||||||
closure->command_line()->set_entry(entry);
|
}
|
||||||
else
|
|
||||||
closure->layout()->set_entry(entry);
|
// Called by the bison parser to define a symbol.
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
script_set_symbol(void* closurev, const char* name, size_t length,
|
||||||
|
Expression* value, int providei, int hiddeni)
|
||||||
|
{
|
||||||
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
|
const bool provide = providei != 0;
|
||||||
|
const bool hidden = hiddeni != 0;
|
||||||
|
closure->script_options()->add_symbol_assignment(name, length, value,
|
||||||
|
provide, hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the bison parser to parse an OPTION.
|
// Called by the bison parser to parse an OPTION.
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
script_parse_option(void* closurev, const char* option)
|
script_parse_option(void* closurev, const char* option, size_t length)
|
||||||
{
|
{
|
||||||
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
// We treat the option as a single command-line option, even if
|
// We treat the option as a single command-line option, even if
|
||||||
|
@ -1366,16 +1536,36 @@ script_parse_option(void* closurev, const char* option)
|
||||||
{
|
{
|
||||||
// There are some options that we could handle here--e.g.,
|
// There are some options that we could handle here--e.g.,
|
||||||
// -lLIBRARY. Should we bother?
|
// -lLIBRARY. Should we bother?
|
||||||
gold_warning(_("%s: ignoring command OPTION; OPTION is only valid"
|
gold_warning(_("%s:%d:%d: ignoring command OPTION; OPTION is only valid"
|
||||||
" for scripts specified via -T/--script"),
|
" for scripts specified via -T/--script"),
|
||||||
closure->filename());
|
closure->filename(), closure->lineno(), closure->charpos());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool past_a_double_dash_option = false;
|
bool past_a_double_dash_option = false;
|
||||||
char* mutable_option = strdup(option);
|
char* mutable_option = strndup(option, length);
|
||||||
|
gold_assert(mutable_option != NULL);
|
||||||
closure->command_line()->process_one_option(1, &mutable_option, 0,
|
closure->command_line()->process_one_option(1, &mutable_option, 0,
|
||||||
&past_a_double_dash_option);
|
&past_a_double_dash_option);
|
||||||
free(mutable_option);
|
free(mutable_option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called by the bison parser to push the lexer into expression
|
||||||
|
mode. */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
script_push_lex_into_expression_mode(void* closurev)
|
||||||
|
{
|
||||||
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
|
closure->push_lex_mode(Lex::EXPRESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called by the bison parser to pop the lexer mode. */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
script_pop_lex_mode(void* closurev)
|
||||||
|
{
|
||||||
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
|
closure->pop_lex_mode();
|
||||||
|
}
|
||||||
|
|
120
gold/script.h
120
gold/script.h
|
@ -1,6 +1,6 @@
|
||||||
// script.h -- handle linker scripts for gold -*- C++ -*-
|
// script.h -- handle linker scripts for gold -*- C++ -*-
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -30,6 +30,8 @@
|
||||||
#ifndef GOLD_SCRIPT_H
|
#ifndef GOLD_SCRIPT_H
|
||||||
#define GOLD_SCRIPT_H
|
#define GOLD_SCRIPT_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace gold
|
namespace gold
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -41,9 +43,125 @@ class Input_argument;
|
||||||
class Input_objects;
|
class Input_objects;
|
||||||
class Input_group;
|
class Input_group;
|
||||||
class Input_file;
|
class Input_file;
|
||||||
|
class Target;
|
||||||
class Task_token;
|
class Task_token;
|
||||||
class Workqueue;
|
class Workqueue;
|
||||||
|
|
||||||
|
// This class represents an expression in a linker script.
|
||||||
|
|
||||||
|
class Expression
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// These should only be created by child classes.
|
||||||
|
Expression()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~Expression()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
// Return the value of the expression.
|
||||||
|
uint64_t
|
||||||
|
eval(const Symbol_table*, const Layout*);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Expression_eval_info;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Compute the value of the expression (implemented by child class).
|
||||||
|
// This is public rather than protected because it is called
|
||||||
|
// directly by children of Expression on other Expression objects.
|
||||||
|
virtual uint64_t
|
||||||
|
value(const Expression_eval_info*) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// May not be copied.
|
||||||
|
Expression(const Expression&);
|
||||||
|
Expression& operator=(const Expression&);
|
||||||
|
};
|
||||||
|
|
||||||
|
// We can read a linker script in two different contexts: when
|
||||||
|
// initially parsing the command line, and when we find an input file
|
||||||
|
// which is actually a linker script. Also some of the data which can
|
||||||
|
// be set by a linker script can also be set via command line options
|
||||||
|
// like -e and --defsym. This means that we have a type of data which
|
||||||
|
// can be set both during command line option parsing and while
|
||||||
|
// reading input files. We store that data in an instance of this
|
||||||
|
// object. We will keep pointers to that instance in both the
|
||||||
|
// Command_line and Layout objects.
|
||||||
|
|
||||||
|
class Script_options
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Script_options();
|
||||||
|
|
||||||
|
// The entry address.
|
||||||
|
const char*
|
||||||
|
entry() const
|
||||||
|
{ return this->entry_.empty() ? NULL : this->entry_.c_str(); }
|
||||||
|
|
||||||
|
// Set the entry address.
|
||||||
|
void
|
||||||
|
set_entry(const char* entry, size_t length)
|
||||||
|
{ this->entry_.assign(entry, length); }
|
||||||
|
|
||||||
|
// Add a symbol to be defined. These are for symbol definitions
|
||||||
|
// which appear outside of a SECTIONS clause.
|
||||||
|
void
|
||||||
|
add_symbol_assignment(const char* name, size_t length, Expression* value,
|
||||||
|
bool provided, bool hidden)
|
||||||
|
{
|
||||||
|
this->symbol_assignments_.push_back(Symbol_assignment(name, length, value,
|
||||||
|
provided, hidden));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a symbol from the command line.
|
||||||
|
bool
|
||||||
|
define_symbol(const char* definition);
|
||||||
|
|
||||||
|
// Add all symbol definitions to the symbol table.
|
||||||
|
void
|
||||||
|
add_symbols_to_table(Symbol_table*, const Target*);
|
||||||
|
|
||||||
|
// Finalize the symbol values.
|
||||||
|
void
|
||||||
|
finalize_symbols(Symbol_table*, const Layout*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// We keep a list of symbol assignments.
|
||||||
|
struct Symbol_assignment
|
||||||
|
{
|
||||||
|
// Symbol name.
|
||||||
|
std::string name;
|
||||||
|
// Expression to assign to symbol.
|
||||||
|
Expression* value;
|
||||||
|
// Whether the assignment should be provided (only set if there is
|
||||||
|
// an undefined reference to the symbol.
|
||||||
|
bool provide;
|
||||||
|
// Whether the assignment should be hidden.
|
||||||
|
bool hidden;
|
||||||
|
// The entry in the symbol table.
|
||||||
|
Symbol* sym;
|
||||||
|
|
||||||
|
Symbol_assignment(const char* namea, size_t lengtha, Expression* valuea,
|
||||||
|
bool providea, bool hiddena)
|
||||||
|
: name(namea, lengtha), value(valuea), provide(providea),
|
||||||
|
hidden(hiddena), sym(NULL)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Symbol_assignment> Symbol_assignments;
|
||||||
|
|
||||||
|
template<int size>
|
||||||
|
void
|
||||||
|
sized_finalize_symbols(Symbol_table*, const Layout*);
|
||||||
|
|
||||||
|
// The entry address. This will be empty if not set.
|
||||||
|
std::string entry_;
|
||||||
|
// Symbols to set.
|
||||||
|
Symbol_assignments symbol_assignments_;
|
||||||
|
};
|
||||||
|
|
||||||
// FILE was found as an argument on the command line, but was not
|
// FILE was found as an argument on the command line, but was not
|
||||||
// recognized as an ELF file. Try to read it as a script. We've
|
// recognized as an ELF file. Try to read it as a script. We've
|
||||||
// already read BYTES of data into P. Return true if the file was
|
// already read BYTES of data into P. Return true if the file was
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// symtab.cc -- the gold symbol table
|
// symtab.cc -- the gold symbol table
|
||||||
|
|
||||||
// Copyright 2006, 2007 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
|
@ -1056,11 +1056,13 @@ Symbol_table::do_define_in_output_data(
|
||||||
sym->init(name, od, value, symsize, type, binding, visibility, nonvis,
|
sym->init(name, od, value, symsize, type, binding, visibility, nonvis,
|
||||||
offset_is_from_end);
|
offset_is_from_end);
|
||||||
|
|
||||||
if (oldsym != NULL
|
if (oldsym == NULL)
|
||||||
&& Symbol_table::should_override_with_special(oldsym))
|
return sym;
|
||||||
this->override_with_special(oldsym, sym);
|
|
||||||
|
|
||||||
return sym;
|
if (Symbol_table::should_override_with_special(oldsym))
|
||||||
|
this->override_with_special(oldsym, sym);
|
||||||
|
delete sym;
|
||||||
|
return oldsym;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a symbol based on an Output_segment.
|
// Define a symbol based on an Output_segment.
|
||||||
|
@ -1150,11 +1152,13 @@ Symbol_table::do_define_in_output_segment(
|
||||||
sym->init(name, os, value, symsize, type, binding, visibility, nonvis,
|
sym->init(name, os, value, symsize, type, binding, visibility, nonvis,
|
||||||
offset_base);
|
offset_base);
|
||||||
|
|
||||||
if (oldsym != NULL
|
if (oldsym == NULL)
|
||||||
&& Symbol_table::should_override_with_special(oldsym))
|
return sym;
|
||||||
this->override_with_special(oldsym, sym);
|
|
||||||
|
|
||||||
return sym;
|
if (Symbol_table::should_override_with_special(oldsym))
|
||||||
|
this->override_with_special(oldsym, sym);
|
||||||
|
delete sym;
|
||||||
|
return oldsym;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a special symbol with a constant value. It is a multiple
|
// Define a special symbol with a constant value. It is a multiple
|
||||||
|
@ -1237,11 +1241,13 @@ Symbol_table::do_define_as_constant(
|
||||||
gold_assert(version == NULL || oldsym != NULL);
|
gold_assert(version == NULL || oldsym != NULL);
|
||||||
sym->init(name, value, symsize, type, binding, visibility, nonvis);
|
sym->init(name, value, symsize, type, binding, visibility, nonvis);
|
||||||
|
|
||||||
if (oldsym != NULL
|
if (oldsym == NULL)
|
||||||
&& Symbol_table::should_override_with_special(oldsym))
|
return sym;
|
||||||
this->override_with_special(oldsym, sym);
|
|
||||||
|
|
||||||
return sym;
|
if (Symbol_table::should_override_with_special(oldsym))
|
||||||
|
this->override_with_special(oldsym, sym);
|
||||||
|
delete sym;
|
||||||
|
return oldsym;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a set of symbols in output sections.
|
// Define a set of symbols in output sections.
|
||||||
|
|
|
@ -503,5 +503,10 @@ ver_test_3.o: ver_test_3.cc
|
||||||
ver_test_4.o: ver_test_4.cc
|
ver_test_4.o: ver_test_4.cc
|
||||||
$(CXXCOMPILE) -c -fpic -o $@ $<
|
$(CXXCOMPILE) -c -fpic -o $@ $<
|
||||||
|
|
||||||
|
check_PROGRAMS += script_test_1
|
||||||
|
script_test_1_SOURCES = script_test_1.cc
|
||||||
|
script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t
|
||||||
|
script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t
|
||||||
|
|
||||||
endif GCC
|
endif GCC
|
||||||
endif NATIVE_LINKER
|
endif NATIVE_LINKER
|
||||||
|
|
|
@ -171,7 +171,14 @@ check_PROGRAMS = object_unittest$(EXEEXT) $(am__EXEEXT_1) \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_10 = flagstest_compress_debug_sections \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_10 = flagstest_compress_debug_sections \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test script_test_1
|
||||||
|
@GCC_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \
|
||||||
|
@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
|
||||||
|
@GCC_FALSE@ $(am__DEPENDENCIES_1)
|
||||||
|
@NATIVE_LINKER_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a \
|
||||||
|
@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \
|
||||||
|
@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \
|
||||||
|
@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1)
|
||||||
subdir = testsuite
|
subdir = testsuite
|
||||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
@ -233,7 +240,8 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_7 = flagstest_compress_debug_sections$(EXEEXT) \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_7 = flagstest_compress_debug_sections$(EXEEXT) \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile$(EXEEXT) \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile$(EXEEXT) \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test$(EXEEXT)
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test$(EXEEXT) \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1$(EXEEXT)
|
||||||
basic_pic_test_SOURCES = basic_pic_test.c
|
basic_pic_test_SOURCES = basic_pic_test.c
|
||||||
basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT)
|
basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT)
|
||||||
basic_pic_test_LDADD = $(LDADD)
|
basic_pic_test_LDADD = $(LDADD)
|
||||||
|
@ -349,6 +357,11 @@ object_unittest_LDADD = $(LDADD)
|
||||||
object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \
|
object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \
|
||||||
../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
|
../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
|
||||||
$(am__DEPENDENCIES_1)
|
$(am__DEPENDENCIES_1)
|
||||||
|
am__script_test_1_SOURCES_DIST = script_test_1.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@am_script_test_1_OBJECTS = \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1.$(OBJEXT)
|
||||||
|
script_test_1_OBJECTS = $(am_script_test_1_OBJECTS)
|
||||||
|
script_test_1_LDADD = $(LDADD)
|
||||||
am__tls_pic_test_SOURCES_DIST = tls_test_main.cc
|
am__tls_pic_test_SOURCES_DIST = tls_test_main.cc
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_pic_test_OBJECTS = tls_test_main.$(OBJEXT)
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_pic_test_OBJECTS = tls_test_main.$(OBJEXT)
|
||||||
tls_pic_test_OBJECTS = $(am_tls_pic_test_OBJECTS)
|
tls_pic_test_OBJECTS = $(am_tls_pic_test_OBJECTS)
|
||||||
|
@ -503,8 +516,8 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \
|
||||||
$(exception_static_test_SOURCES) $(exception_test_SOURCES) \
|
$(exception_static_test_SOURCES) $(exception_test_SOURCES) \
|
||||||
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
|
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
|
||||||
flagstest_o_specialfile_and_compress_debug_sections.c \
|
flagstest_o_specialfile_and_compress_debug_sections.c \
|
||||||
$(object_unittest_SOURCES) $(tls_pic_test_SOURCES) \
|
$(object_unittest_SOURCES) $(script_test_1_SOURCES) \
|
||||||
$(tls_shared_ie_test_SOURCES) \
|
$(tls_pic_test_SOURCES) $(tls_shared_ie_test_SOURCES) \
|
||||||
$(tls_shared_nonpic_test_SOURCES) $(tls_shared_test_SOURCES) \
|
$(tls_shared_nonpic_test_SOURCES) $(tls_shared_test_SOURCES) \
|
||||||
$(tls_static_pic_test_SOURCES) $(tls_static_test_SOURCES) \
|
$(tls_static_pic_test_SOURCES) $(tls_static_test_SOURCES) \
|
||||||
$(tls_test_SOURCES) $(two_file_pic_test_SOURCES) \
|
$(tls_test_SOURCES) $(two_file_pic_test_SOURCES) \
|
||||||
|
@ -535,7 +548,8 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \
|
||||||
$(am__exception_test_SOURCES_DIST) \
|
$(am__exception_test_SOURCES_DIST) \
|
||||||
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
|
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
|
||||||
flagstest_o_specialfile_and_compress_debug_sections.c \
|
flagstest_o_specialfile_and_compress_debug_sections.c \
|
||||||
$(object_unittest_SOURCES) $(am__tls_pic_test_SOURCES_DIST) \
|
$(object_unittest_SOURCES) $(am__script_test_1_SOURCES_DIST) \
|
||||||
|
$(am__tls_pic_test_SOURCES_DIST) \
|
||||||
$(am__tls_shared_ie_test_SOURCES_DIST) \
|
$(am__tls_shared_ie_test_SOURCES_DIST) \
|
||||||
$(am__tls_shared_nonpic_test_SOURCES_DIST) \
|
$(am__tls_shared_nonpic_test_SOURCES_DIST) \
|
||||||
$(am__tls_shared_test_SOURCES_DIST) \
|
$(am__tls_shared_test_SOURCES_DIST) \
|
||||||
|
@ -905,6 +919,9 @@ object_unittest_SOURCES = object_unittest.cc
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_DEPENDENCIES = gcctestdir/ld ver_test_1.so ver_test_2.so ver_test_4.so
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_DEPENDENCIES = gcctestdir/ld ver_test_1.so ver_test_2.so ver_test_4.so
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDADD = ver_test_1.so ver_test_2.so ver_test_4.so
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDADD = ver_test_1.so ver_test_2.so ver_test_4.so
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_SOURCES = script_test_1.cc
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
@ -1020,6 +1037,9 @@ exception_test$(EXEEXT): $(exception_test_OBJECTS) $(exception_test_DEPENDENCIES
|
||||||
object_unittest$(EXEEXT): $(object_unittest_OBJECTS) $(object_unittest_DEPENDENCIES)
|
object_unittest$(EXEEXT): $(object_unittest_OBJECTS) $(object_unittest_DEPENDENCIES)
|
||||||
@rm -f object_unittest$(EXEEXT)
|
@rm -f object_unittest$(EXEEXT)
|
||||||
$(CXXLINK) $(object_unittest_LDFLAGS) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS)
|
$(CXXLINK) $(object_unittest_LDFLAGS) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS)
|
||||||
|
script_test_1$(EXEEXT): $(script_test_1_OBJECTS) $(script_test_1_DEPENDENCIES)
|
||||||
|
@rm -f script_test_1$(EXEEXT)
|
||||||
|
$(CXXLINK) $(script_test_1_LDFLAGS) $(script_test_1_OBJECTS) $(script_test_1_LDADD) $(LIBS)
|
||||||
tls_pic_test$(EXEEXT): $(tls_pic_test_OBJECTS) $(tls_pic_test_DEPENDENCIES)
|
tls_pic_test$(EXEEXT): $(tls_pic_test_OBJECTS) $(tls_pic_test_DEPENDENCIES)
|
||||||
@rm -f tls_pic_test$(EXEEXT)
|
@rm -f tls_pic_test$(EXEEXT)
|
||||||
$(CXXLINK) $(tls_pic_test_LDFLAGS) $(tls_pic_test_OBJECTS) $(tls_pic_test_LDADD) $(LIBS)
|
$(CXXLINK) $(tls_pic_test_LDFLAGS) $(tls_pic_test_OBJECTS) $(tls_pic_test_LDADD) $(LIBS)
|
||||||
|
@ -1111,6 +1131,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_unittest.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_unittest.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_1.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testfile.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testfile.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmain.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmain.Po@am__quote@
|
||||||
|
|
47
gold/testsuite/script_test_1.cc
Normal file
47
gold/testsuite/script_test_1.cc
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// script_test_1.cc -- linker script test 1 for gold -*- C++ -*-
|
||||||
|
|
||||||
|
// Copyright 2008 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.
|
||||||
|
|
||||||
|
// A test for a linker script which sets symbols to values.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern char a, b, c, d, e, f, g;
|
||||||
|
int sym = 3;
|
||||||
|
int common_sym;
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int, char**)
|
||||||
|
{
|
||||||
|
assert(reinterpret_cast<intptr_t>(&a) == 123);
|
||||||
|
assert(reinterpret_cast<intptr_t>(&b) == reinterpret_cast<intptr_t>(&a) * 2);
|
||||||
|
assert(reinterpret_cast<intptr_t>(&c)
|
||||||
|
== reinterpret_cast<intptr_t>(&b) + 3 * 6);
|
||||||
|
assert(reinterpret_cast<intptr_t>(&d)
|
||||||
|
== (reinterpret_cast<intptr_t>(&b) + 3) * 6);
|
||||||
|
assert(reinterpret_cast<int*>(&e) == &sym);
|
||||||
|
assert(reinterpret_cast<intptr_t>(&f)
|
||||||
|
== reinterpret_cast<intptr_t>(&sym) + 10);
|
||||||
|
assert(reinterpret_cast<int*>(&g) == &common_sym);
|
||||||
|
return 0;
|
||||||
|
}
|
29
gold/testsuite/script_test_1.t
Normal file
29
gold/testsuite/script_test_1.t
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* script_test_1.t -- linker script test 1 for gold
|
||||||
|
|
||||||
|
Copyright 2008 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. */
|
||||||
|
|
||||||
|
a = 123;
|
||||||
|
b = a * 2;
|
||||||
|
c = b + 3 * 6;
|
||||||
|
d = (b + 3) * 6;
|
||||||
|
e = sym;
|
||||||
|
f = sym + 10;
|
||||||
|
g = common_sym;
|
228
gold/yyscript.y
228
gold/yyscript.y
|
@ -1,6 +1,6 @@
|
||||||
/* yyscript.y -- linker script grammer for gold. */
|
/* yyscript.y -- linker script grammer for gold. */
|
||||||
|
|
||||||
/* Copyright 2006, 2007 Free Software Foundation, Inc.
|
/* Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
Written by Ian Lance Taylor <iant@google.com>.
|
Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
This file is part of gold.
|
This file is part of gold.
|
||||||
|
@ -49,8 +49,12 @@
|
||||||
/* The values associated with tokens. */
|
/* The values associated with tokens. */
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
const char* string;
|
/* A string. */
|
||||||
int64_t integer;
|
struct Parser_string string;
|
||||||
|
/* A number. */
|
||||||
|
uint64_t integer;
|
||||||
|
/* An expression. */
|
||||||
|
Expression_ptr expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Operators, including a precedence table for expressions. */
|
/* Operators, including a precedence table for expressions. */
|
||||||
|
@ -68,6 +72,9 @@
|
||||||
%left '+' '-'
|
%left '+' '-'
|
||||||
%left '*' '/' '%'
|
%left '*' '/' '%'
|
||||||
|
|
||||||
|
/* A fake operator used to indicate unary operator precedence. */
|
||||||
|
%right UNARY
|
||||||
|
|
||||||
/* Constants. */
|
/* Constants. */
|
||||||
|
|
||||||
%token <string> STRING
|
%token <string> STRING
|
||||||
|
@ -82,6 +89,7 @@
|
||||||
%token ABSOLUTE
|
%token ABSOLUTE
|
||||||
%token ADDR
|
%token ADDR
|
||||||
%token ALIGN_K /* ALIGN */
|
%token ALIGN_K /* ALIGN */
|
||||||
|
%token ALIGNOF
|
||||||
%token ASSERT_K /* ASSERT */
|
%token ASSERT_K /* ASSERT */
|
||||||
%token AS_NEEDED
|
%token AS_NEEDED
|
||||||
%token AT
|
%token AT
|
||||||
|
@ -158,11 +166,31 @@
|
||||||
|
|
||||||
%token OPTION
|
%token OPTION
|
||||||
|
|
||||||
|
/* Special tokens used to tell the grammar what type of tokens we are
|
||||||
|
parsing. The token stream always begins with one of these tokens.
|
||||||
|
We do this because version scripts can appear embedded within
|
||||||
|
linker scripts, and because --defsym uses the expression
|
||||||
|
parser. */
|
||||||
|
%token PARSING_LINKER_SCRIPT
|
||||||
|
%token PARSING_VERSION_SCRIPT
|
||||||
|
%token PARSING_DEFSYM
|
||||||
|
|
||||||
|
/* Non-terminal types, where needed. */
|
||||||
|
|
||||||
|
%type <expr> parse_exp exp
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
/* Read the special token to see what to read next. */
|
||||||
|
top:
|
||||||
|
PARSING_LINKER_SCRIPT linker_script
|
||||||
|
| PARSING_VERSION_SCRIPT version_script
|
||||||
|
| PARSING_DEFSYM defsym_expr
|
||||||
|
;
|
||||||
|
|
||||||
/* A file contains a list of commands. */
|
/* A file contains a list of commands. */
|
||||||
file_list:
|
linker_script:
|
||||||
file_list file_cmd
|
linker_script file_cmd
|
||||||
| /* empty */
|
| /* empty */
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -173,7 +201,7 @@ file_cmd:
|
||||||
'(' input_list ')'
|
'(' input_list ')'
|
||||||
{ script_end_group(closure); }
|
{ script_end_group(closure); }
|
||||||
| OPTION '(' STRING ')'
|
| OPTION '(' STRING ')'
|
||||||
{ script_parse_option(closure, $3); }
|
{ script_parse_option(closure, $3.value, $3.length); }
|
||||||
| file_or_sections_cmd
|
| file_or_sections_cmd
|
||||||
| ignore_cmd
|
| ignore_cmd
|
||||||
;
|
;
|
||||||
|
@ -197,7 +225,7 @@ input_list:
|
||||||
/* An input file name. */
|
/* An input file name. */
|
||||||
input_list_element:
|
input_list_element:
|
||||||
STRING
|
STRING
|
||||||
{ script_add_file(closure, $1); }
|
{ script_add_file(closure, $1.value, $1.length); }
|
||||||
| AS_NEEDED
|
| AS_NEEDED
|
||||||
{ script_start_as_needed(closure); }
|
{ script_start_as_needed(closure); }
|
||||||
'(' input_list ')'
|
'(' input_list ')'
|
||||||
|
@ -208,7 +236,191 @@ input_list_element:
|
||||||
within a SECTIONS block. */
|
within a SECTIONS block. */
|
||||||
file_or_sections_cmd:
|
file_or_sections_cmd:
|
||||||
ENTRY '(' STRING ')'
|
ENTRY '(' STRING ')'
|
||||||
{ script_set_entry(closure, $3); }
|
{ script_set_entry(closure, $3.value, $3.length); }
|
||||||
|
| assignment end
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Set a symbol to a value. */
|
||||||
|
assignment:
|
||||||
|
STRING '=' parse_exp
|
||||||
|
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
||||||
|
| STRING PLUSEQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_add(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| STRING MINUSEQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_sub(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| STRING MULTEQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_mult(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| STRING DIVEQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_div(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| STRING LSHIFTEQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_lshift(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| STRING RSHIFTEQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_rshift(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| STRING ANDEQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_bitwise_and(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| STRING OREQ parse_exp
|
||||||
|
{
|
||||||
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
|
Expression_ptr e = script_exp_binary_bitwise_or(s, $3);
|
||||||
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
|
}
|
||||||
|
| PROVIDE '(' STRING '=' parse_exp ')'
|
||||||
|
{ script_set_symbol(closure, $3.value, $3.length, $5, 1, 0); }
|
||||||
|
| PROVIDE_HIDDEN '(' STRING '=' parse_exp ')'
|
||||||
|
{ script_set_symbol(closure, $3.value, $3.length, $5, 1, 1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Parse an expression, putting the lexer into the right mode. */
|
||||||
|
parse_exp:
|
||||||
|
{ script_push_lex_into_expression_mode(closure); }
|
||||||
|
exp
|
||||||
|
{
|
||||||
|
script_pop_lex_mode(closure);
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/* An expression. */
|
||||||
|
exp:
|
||||||
|
'(' exp ')'
|
||||||
|
{ $$ = $2; }
|
||||||
|
| '-' exp %prec UNARY
|
||||||
|
{ $$ = script_exp_unary_minus($2); }
|
||||||
|
| '!' exp %prec UNARY
|
||||||
|
{ $$ = script_exp_unary_logical_not($2); }
|
||||||
|
| '~' exp %prec UNARY
|
||||||
|
{ $$ = script_exp_unary_bitwise_not($2); }
|
||||||
|
| '+' exp %prec UNARY
|
||||||
|
{ $$ = $2; }
|
||||||
|
| exp '*' exp
|
||||||
|
{ $$ = script_exp_binary_mult($1, $3); }
|
||||||
|
| exp '/' exp
|
||||||
|
{ $$ = script_exp_binary_div($1, $3); }
|
||||||
|
| exp '%' exp
|
||||||
|
{ $$ = script_exp_binary_mod($1, $3); }
|
||||||
|
| exp '+' exp
|
||||||
|
{ $$ = script_exp_binary_add($1, $3); }
|
||||||
|
| exp '-' exp
|
||||||
|
{ $$ = script_exp_binary_sub($1, $3); }
|
||||||
|
| exp LSHIFT exp
|
||||||
|
{ $$ = script_exp_binary_lshift($1, $3); }
|
||||||
|
| exp RSHIFT exp
|
||||||
|
{ $$ = script_exp_binary_rshift($1, $3); }
|
||||||
|
| exp EQ exp
|
||||||
|
{ $$ = script_exp_binary_eq($1, $3); }
|
||||||
|
| exp NE exp
|
||||||
|
{ $$ = script_exp_binary_ne($1, $3); }
|
||||||
|
| exp LE exp
|
||||||
|
{ $$ = script_exp_binary_le($1, $3); }
|
||||||
|
| exp GE exp
|
||||||
|
{ $$ = script_exp_binary_ge($1, $3); }
|
||||||
|
| exp '<' exp
|
||||||
|
{ $$ = script_exp_binary_lt($1, $3); }
|
||||||
|
| exp '>' exp
|
||||||
|
{ $$ = script_exp_binary_gt($1, $3); }
|
||||||
|
| exp '&' exp
|
||||||
|
{ $$ = script_exp_binary_bitwise_and($1, $3); }
|
||||||
|
| exp '^' exp
|
||||||
|
{ $$ = script_exp_binary_bitwise_xor($1, $3); }
|
||||||
|
| exp '|' exp
|
||||||
|
{ $$ = script_exp_binary_bitwise_or($1, $3); }
|
||||||
|
| exp ANDAND exp
|
||||||
|
{ $$ = script_exp_binary_logical_and($1, $3); }
|
||||||
|
| exp OROR exp
|
||||||
|
{ $$ = script_exp_binary_logical_or($1, $3); }
|
||||||
|
| exp '?' exp ':' exp
|
||||||
|
{ $$ = script_exp_trinary_cond($1, $3, $5); }
|
||||||
|
| INTEGER
|
||||||
|
{ $$ = script_exp_integer($1); }
|
||||||
|
| STRING
|
||||||
|
{ $$ = script_exp_string($1.value, $1.length); }
|
||||||
|
| MAX_K '(' exp ',' exp ')'
|
||||||
|
{ $$ = script_exp_function_max($3, $5); }
|
||||||
|
| MIN_K '(' exp ',' exp ')'
|
||||||
|
{ $$ = script_exp_function_min($3, $5); }
|
||||||
|
| DEFINED '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_defined($3.value, $3.length); }
|
||||||
|
| SIZEOF_HEADERS
|
||||||
|
{ $$ = script_exp_function_sizeof_headers(); }
|
||||||
|
| ALIGNOF '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_alignof($3.value, $3.length); }
|
||||||
|
| SIZEOF '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_sizeof($3.value, $3.length); }
|
||||||
|
| ADDR '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_addr($3.value, $3.length); }
|
||||||
|
| LOADADDR '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_loadaddr($3.value, $3.length); }
|
||||||
|
| ORIGIN '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_origin($3.value, $3.length); }
|
||||||
|
| LENGTH '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_length($3.value, $3.length); }
|
||||||
|
| CONSTANT '(' STRING ')'
|
||||||
|
{ $$ = script_exp_function_constant($3.value, $3.length); }
|
||||||
|
| ABSOLUTE '(' exp ')'
|
||||||
|
{ $$ = script_exp_function_absolute($3); }
|
||||||
|
| ALIGN_K '(' exp ')'
|
||||||
|
{ $$ = script_exp_function_align(script_exp_string(".", 1), $3); }
|
||||||
|
| ALIGN_K '(' exp ',' exp ')'
|
||||||
|
{ $$ = script_exp_function_align($3, $5); }
|
||||||
|
| BLOCK '(' exp ')'
|
||||||
|
{ $$ = script_exp_function_align(script_exp_string(".", 1), $3); }
|
||||||
|
| DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
|
||||||
|
{ $$ = script_exp_function_data_segment_align($3, $5); }
|
||||||
|
| DATA_SEGMENT_RELRO_END '(' exp ',' exp ')'
|
||||||
|
{ $$ = script_exp_function_data_segment_relro_end($3, $5); }
|
||||||
|
| DATA_SEGMENT_END '(' exp ')'
|
||||||
|
{ $$ = script_exp_function_data_segment_end($3); }
|
||||||
|
| SEGMENT_START '(' STRING ',' exp ')'
|
||||||
|
{
|
||||||
|
$$ = script_exp_function_segment_start($3.value, $3.length, $5);
|
||||||
|
}
|
||||||
|
| ASSERT_K '(' exp ',' STRING ')'
|
||||||
|
{ $$ = script_exp_function_assert($3, $5.value, $5.length); }
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Handle the --defsym option. */
|
||||||
|
defsym_expr:
|
||||||
|
STRING '=' parse_exp
|
||||||
|
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
||||||
|
;
|
||||||
|
|
||||||
|
/* A version script. Not yet implemented. */
|
||||||
|
version_script:
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Some statements require a terminator, which may be a semicolon or a
|
||||||
|
comma. */
|
||||||
|
end:
|
||||||
|
';'
|
||||||
|
| ','
|
||||||
;
|
;
|
||||||
|
|
||||||
/* An optional comma. */
|
/* An optional comma. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue