summaryrefslogtreecommitdiff
path: root/gold/expression.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-02-04 06:45:50 +0000
committerIan Lance Taylor <iant@google.com>2008-02-04 06:45:50 +0000
commit3802b2dd6b937e2904b6e2de087e224437eab493 (patch)
treeac185197a2a44c92c3785020c2ce1e389f2b0287 /gold/expression.cc
parentae7d22a6f2f59251b85ef5655b800f2dfe2dfbee (diff)
downloadbinutils-gdb-3802b2dd6b937e2904b6e2de087e224437eab493.tar.gz
Implement SIZEOF_HEADERS, section constraints, other minor linker
script items.
Diffstat (limited to 'gold/expression.cc')
-rw-r--r--gold/expression.cc170
1 files changed, 145 insertions, 25 deletions
diff --git a/gold/expression.cc b/gold/expression.cc
index e8fd9fd8954..d57b45cb396 100644
--- a/gold/expression.cc
+++ b/gold/expression.cc
@@ -24,6 +24,7 @@
#include <string>
+#include "elfcpp.h"
#include "parameters.h"
#include "symtab.h"
#include "layout.h"
@@ -632,78 +633,197 @@ script_exp_function_addr(const char* section_name, size_t section_name_len)
return new Addr_expression(section_name, section_name_len);
}
-// Functions.
+// CONSTANT. It would be nice if we could simply evaluate this
+// immediately and return an Integer_expression, but unfortunately we
+// don't know the target.
+
+class Constant_expression : public Expression
+{
+ public:
+ Constant_expression(const char* name, size_t length);
+
+ uint64_t
+ value(const Expression_eval_info*);
+
+ void
+ print(FILE* f) const;
+
+ private:
+ enum Constant_function
+ {
+ CONSTANT_MAXPAGESIZE,
+ CONSTANT_COMMONPAGESIZE
+ };
+ Constant_function function_;
+};
+
+Constant_expression::Constant_expression(const char* name, size_t length)
+{
+ if (length == 11 && strncmp(name, "MAXPAGESIZE", length) == 0)
+ this->function_ = CONSTANT_MAXPAGESIZE;
+ else if (length == 14 && strncmp(name, "COMMONPAGESIZE", length) == 0)
+ this->function_ = CONSTANT_COMMONPAGESIZE;
+ else
+ {
+ std::string s(name, length);
+ gold_error(_("unknown constant %s"), s.c_str());
+ this->function_ = CONSTANT_MAXPAGESIZE;
+ }
+}
+
+uint64_t
+Constant_expression::value(const Expression_eval_info*)
+{
+ switch (this->function_)
+ {
+ case CONSTANT_MAXPAGESIZE:
+ return parameters->target()->abi_pagesize();
+ case CONSTANT_COMMONPAGESIZE:
+ return parameters->target()->common_pagesize();
+ default:
+ gold_unreachable();
+ }
+}
+
+void
+Constant_expression::print(FILE* f) const
+{
+ const char* name;
+ switch (this->function_)
+ {
+ case CONSTANT_MAXPAGESIZE:
+ name = "MAXPAGESIZE";
+ break;
+ case CONSTANT_COMMONPAGESIZE:
+ name = "COMMONPAGESIZE";
+ break;
+ default:
+ gold_unreachable();
+ }
+ fprintf(f, "CONSTANT(%s)", name);
+}
+
extern "C" Expression*
-script_exp_function_defined(const char*, size_t)
+script_exp_function_constant(const char* name, size_t length)
{
- gold_fatal(_("DEFINED not implemented"));
+ return new Constant_expression(name, length);
}
+// DATA_SEGMENT_ALIGN. FIXME: we don't implement this; we always fall
+// back to the general case.
+
extern "C" Expression*
-script_exp_function_sizeof_headers()
+script_exp_function_data_segment_align(Expression* left, Expression*)
{
- gold_fatal(_("SIZEOF_HEADERS not implemented"));
+ Expression* e1 = script_exp_function_align(script_exp_string(".", 1), left);
+ Expression* e2 = script_exp_binary_sub(left, script_exp_integer(1));
+ Expression* e3 = script_exp_binary_bitwise_and(script_exp_string(".", 1),
+ e2);
+ return script_exp_binary_add(e1, e3);
}
+// DATA_SEGMENT_RELRO. FIXME: This is not implemented.
+
extern "C" Expression*
-script_exp_function_alignof(const char*, size_t)
+script_exp_function_data_segment_relro_end(Expression*, Expression* right)
{
- gold_fatal(_("ALIGNOF not implemented"));
+ return right;
}
+// DATA_SEGMENT_END. FIXME: This is not implemented.
+
extern "C" Expression*
-script_exp_function_sizeof(const char*, size_t)
+script_exp_function_data_segment_end(Expression* val)
{
- gold_fatal(_("SIZEOF not implemented"));
+ return val;
+}
+
+// SIZEOF_HEADERS.
+
+class Sizeof_headers_expression : public Expression
+{
+ public:
+ Sizeof_headers_expression()
+ { }
+
+ uint64_t
+ value(const Expression_eval_info*);
+
+ void
+ print(FILE* f) const
+ { fprintf(f, "SIZEOF_HEADERS"); }
+};
+
+uint64_t
+Sizeof_headers_expression::value(const Expression_eval_info* eei)
+{
+ unsigned int ehdr_size;
+ unsigned int phdr_size;
+ if (parameters->get_size() == 32)
+ {
+ ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size;
+ phdr_size = elfcpp::Elf_sizes<32>::phdr_size;
+ }
+ else if (parameters->get_size() == 64)
+ {
+ ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size;
+ phdr_size = elfcpp::Elf_sizes<64>::phdr_size;
+ }
+ else
+ gold_unreachable();
+
+ return ehdr_size + phdr_size * eei->layout->expected_segment_count();
}
extern "C" Expression*
-script_exp_function_loadaddr(const char*, size_t)
+script_exp_function_sizeof_headers()
{
- gold_fatal(_("LOADADDR not implemented"));
+ return new Sizeof_headers_expression();
}
+// Functions.
+
extern "C" Expression*
-script_exp_function_origin(const char*, size_t)
+script_exp_function_defined(const char*, size_t)
{
- gold_fatal(_("ORIGIN not implemented"));
+ gold_fatal(_("DEFINED not implemented"));
}
extern "C" Expression*
-script_exp_function_length(const char*, size_t)
+script_exp_function_alignof(const char*, size_t)
{
- gold_fatal(_("LENGTH not implemented"));
+ gold_fatal(_("ALIGNOF not implemented"));
}
extern "C" Expression*
-script_exp_function_constant(const char*, size_t)
+script_exp_function_sizeof(const char*, size_t)
{
- gold_fatal(_("CONSTANT not implemented"));
+ gold_fatal(_("SIZEOF not implemented"));
}
extern "C" Expression*
-script_exp_function_absolute(Expression*)
+script_exp_function_loadaddr(const char*, size_t)
{
- gold_fatal(_("ABSOLUTE not implemented"));
+ gold_fatal(_("LOADADDR not implemented"));
}
extern "C" Expression*
-script_exp_function_data_segment_align(Expression*, Expression*)
+script_exp_function_origin(const char*, size_t)
{
- gold_fatal(_("DATA_SEGMENT_ALIGN not implemented"));
+ gold_fatal(_("ORIGIN not implemented"));
}
extern "C" Expression*
-script_exp_function_data_segment_relro_end(Expression*, Expression*)
+script_exp_function_length(const char*, size_t)
{
- gold_fatal(_("DATA_SEGMENT_RELRO_END not implemented"));
+ gold_fatal(_("LENGTH not implemented"));
}
extern "C" Expression*
-script_exp_function_data_segment_end(Expression*)
+script_exp_function_absolute(Expression*)
{
- gold_fatal(_("DATA_SEGMENT_END not implemented"));
+ gold_fatal(_("ABSOLUTE not implemented"));
}
extern "C" Expression*