diff options
author | Ian Lance Taylor <iant@google.com> | 2008-02-04 06:45:50 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2008-02-04 06:45:50 +0000 |
commit | 3802b2dd6b937e2904b6e2de087e224437eab493 (patch) | |
tree | ac185197a2a44c92c3785020c2ce1e389f2b0287 /gold/expression.cc | |
parent | ae7d22a6f2f59251b85ef5655b800f2dfe2dfbee (diff) | |
download | binutils-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.cc | 170 |
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* |