12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337 |
- // expression.cc -- expressions in linker scripts for gold
- // Copyright (C) 2006-2015 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 "elfcpp.h"
- #include "parameters.h"
- #include "symtab.h"
- #include "layout.h"
- #include "output.h"
- #include "script.h"
- #include "script-c.h"
- namespace gold
- {
- // This file holds the code which handles linker expressions.
- // The dot symbol, which linker scripts refer to simply as ".",
- // requires special treatment. The dot symbol is set several times,
- // section addresses will refer to it, output sections will change it,
- // and it can be set based on the value of other symbols. We simplify
- // the handling by prohibiting setting the dot symbol to the value of
- // a non-absolute symbol.
- // 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
- {
- // The symbol table.
- const Symbol_table* symtab;
- // The layout--we use this to get section information.
- const Layout* layout;
- // Whether to check assertions.
- bool check_assertions;
- // Whether expressions can refer to the dot symbol. The dot symbol
- // is only available within a SECTIONS clause.
- bool is_dot_available;
- // The current value of the dot symbol.
- uint64_t dot_value;
- // The section in which the dot symbol is defined; this is NULL if
- // it is absolute.
- Output_section* dot_section;
- // Points to where the section of the result should be stored.
- Output_section** result_section_pointer;
- // Pointer to where the alignment of the result should be stored.
- uint64_t* result_alignment_pointer;
- // Pointer to where the type of the symbol on the RHS should be stored.
- elfcpp::STT* type_pointer;
- // Pointer to where the visibility of the symbol on the RHS should be stored.
- elfcpp::STV* vis_pointer;
- // Pointer to where the rest of the symbol's st_other field should be stored.
- unsigned char* nonvis_pointer;
- // Whether the value is valid. In Symbol_assignment::set_if_absolute, we
- // may be trying to evaluate the address of a section whose address is not
- // yet finalized, and we need to fail the evaluation gracefully.
- bool *is_valid_pointer;
- };
- // Evaluate an expression.
- uint64_t
- Expression::eval(const Symbol_table* symtab, const Layout* layout,
- bool check_assertions)
- {
- return this->eval_maybe_dot(symtab, layout, check_assertions, false, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, false, NULL);
- }
- // Evaluate an expression which may refer to the dot symbol.
- uint64_t
- Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout,
- bool check_assertions, uint64_t dot_value,
- Output_section* dot_section,
- Output_section** result_section_pointer,
- uint64_t* result_alignment_pointer,
- bool is_section_dot_assignment)
- {
- return this->eval_maybe_dot(symtab, layout, check_assertions, true,
- dot_value, dot_section, result_section_pointer,
- result_alignment_pointer, NULL, NULL, NULL,
- is_section_dot_assignment, NULL);
- }
- // Evaluate an expression which may or may not refer to the dot
- // symbol.
- uint64_t
- Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
- bool check_assertions, bool is_dot_available,
- uint64_t dot_value, Output_section* dot_section,
- Output_section** result_section_pointer,
- uint64_t* result_alignment_pointer,
- elfcpp::STT* type_pointer,
- elfcpp::STV* vis_pointer,
- unsigned char* nonvis_pointer,
- bool is_section_dot_assignment,
- bool* is_valid_pointer)
- {
- Expression_eval_info eei;
- eei.symtab = symtab;
- eei.layout = layout;
- eei.check_assertions = check_assertions;
- eei.is_dot_available = is_dot_available;
- eei.dot_value = dot_value;
- eei.dot_section = dot_section;
- // We assume the value is absolute, and only set this to a section
- // if we find a section-relative reference.
- if (result_section_pointer != NULL)
- *result_section_pointer = NULL;
- eei.result_section_pointer = result_section_pointer;
- // For symbol=symbol assignments, we need to track the type, visibility,
- // and remaining st_other bits.
- eei.type_pointer = type_pointer;
- eei.vis_pointer = vis_pointer;
- eei.nonvis_pointer = nonvis_pointer;
- eei.result_alignment_pointer = result_alignment_pointer;
- // Assume the value is valid until we try to evaluate an expression
- // that can't be evaluated yet.
- bool is_valid = true;
- eei.is_valid_pointer = &is_valid;
- uint64_t val = this->value(&eei);
- if (is_valid_pointer != NULL)
- *is_valid_pointer = is_valid;
- else
- gold_assert(is_valid);
- // If this is an assignment to dot within a section, and the value
- // is absolute, treat it as a section-relative offset.
- if (is_section_dot_assignment && *result_section_pointer == NULL)
- {
- gold_assert(dot_section != NULL);
- val += dot_section->address();
- *result_section_pointer = dot_section;
- }
- return val;
- }
- // 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_; }
- void
- print(FILE* f) const
- { fprintf(f, "0x%llx", static_cast<unsigned long long>(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*);
- void
- print(FILE* f) const
- { fprintf(f, "%s", this->name_.c_str()); }
- 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 (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = sym->output_section();
- if (eei->type_pointer != NULL)
- *eei->type_pointer = sym->type();
- if (eei->vis_pointer != NULL)
- *eei->vis_pointer = sym->visibility();
- if (eei->nonvis_pointer != NULL)
- *eei->nonvis_pointer = sym->nonvis();
- if (parameters->target().get_size() == 32)
- return eei->symtab->get_sized_symbol<32>(sym)->value();
- else if (parameters->target().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*);
- void
- print(FILE* f) const
- { fprintf(f, "."); }
- };
- uint64_t
- Dot_expression::value(const Expression_eval_info* eei)
- {
- if (!eei->is_dot_available)
- {
- gold_error(_("invalid reference to dot symbol outside of "
- "SECTIONS clause"));
- return 0;
- }
- if (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = eei->dot_section;
- return eei->dot_value;
- }
- // 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,
- Output_section** arg_section_pointer) const
- {
- return this->arg_->eval_maybe_dot(eei->symtab, eei->layout,
- eei->check_assertions,
- eei->is_dot_available,
- eei->dot_value,
- eei->dot_section,
- arg_section_pointer,
- eei->result_alignment_pointer,
- NULL,
- NULL,
- NULL,
- false,
- eei->is_valid_pointer);
- }
- void
- arg_print(FILE* f) const
- { this->arg_->print(f); }
- 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) \
- { \
- Output_section* arg_section; \
- uint64_t ret = OPERATOR this->arg_value(eei, &arg_section); \
- if (arg_section != NULL && parameters->options().relocatable()) \
- gold_warning(_("unary " #NAME " applied to section " \
- "relative value")); \
- return ret; \
- } \
- \
- void \
- print(FILE* f) const \
- { \
- fprintf(f, "(%s ", #OPERATOR); \
- this->arg_print(f); \
- fprintf(f, ")"); \
- } \
- }; \
- \
- 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,
- Output_section** section_pointer,
- uint64_t* alignment_pointer) const
- {
- return this->left_->eval_maybe_dot(eei->symtab, eei->layout,
- eei->check_assertions,
- eei->is_dot_available,
- eei->dot_value,
- eei->dot_section,
- section_pointer,
- alignment_pointer,
- NULL,
- NULL,
- NULL,
- false,
- eei->is_valid_pointer);
- }
- uint64_t
- right_value(const Expression_eval_info* eei,
- Output_section** section_pointer,
- uint64_t* alignment_pointer) const
- {
- return this->right_->eval_maybe_dot(eei->symtab, eei->layout,
- eei->check_assertions,
- eei->is_dot_available,
- eei->dot_value,
- eei->dot_section,
- section_pointer,
- alignment_pointer,
- NULL,
- NULL,
- NULL,
- false,
- eei->is_valid_pointer);
- }
- void
- left_print(FILE* f) const
- { this->left_->print(f); }
- void
- right_print(FILE* f) const
- { this->right_->print(f); }
- // This is a call to function FUNCTION_NAME. Print it. This is for
- // debugging.
- void
- print_function(FILE* f, const char* function_name) const
- {
- fprintf(f, "%s(", function_name);
- this->left_print(f);
- fprintf(f, ", ");
- this->right_print(f);
- fprintf(f, ")");
- }
- private:
- Expression* left_;
- Expression* right_;
- };
- // Handle binary operators. We use a preprocessor macro as a hack to
- // capture the C operator. KEEP_LEFT means that if the left operand
- // is section relative and the right operand is not, the result uses
- // the same section as the left operand. KEEP_RIGHT is the same with
- // left and right swapped. IS_DIV means that we need to give an error
- // if the right operand is zero. WARN means that we should warn if
- // used on section relative values in a relocatable link. We always
- // warn if used on values in different sections in a relocatable link.
- #define BINARY_EXPRESSION(NAME, OPERATOR, KEEP_LEFT, KEEP_RIGHT, IS_DIV, WARN) \
- 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) \
- { \
- Output_section* left_section; \
- uint64_t left_alignment = 0; \
- uint64_t left = this->left_value(eei, &left_section, \
- &left_alignment); \
- Output_section* right_section; \
- uint64_t right_alignment = 0; \
- uint64_t right = this->right_value(eei, &right_section, \
- &right_alignment); \
- if (KEEP_RIGHT && left_section == NULL && right_section != NULL) \
- { \
- if (eei->result_section_pointer != NULL) \
- *eei->result_section_pointer = right_section; \
- if (eei->result_alignment_pointer != NULL \
- && right_alignment > *eei->result_alignment_pointer) \
- *eei->result_alignment_pointer = right_alignment; \
- } \
- else if (KEEP_LEFT \
- && left_section != NULL \
- && right_section == NULL) \
- { \
- if (eei->result_section_pointer != NULL) \
- *eei->result_section_pointer = left_section; \
- if (eei->result_alignment_pointer != NULL \
- && left_alignment > *eei->result_alignment_pointer) \
- *eei->result_alignment_pointer = left_alignment; \
- } \
- else if ((WARN || left_section != right_section) \
- && (left_section != NULL || right_section != NULL) \
- && parameters->options().relocatable()) \
- gold_warning(_("binary " #NAME " applied to section " \
- "relative value")); \
- if (IS_DIV && right == 0) \
- { \
- gold_error(_(#NAME " by zero")); \
- return 0; \
- } \
- return left OPERATOR right; \
- } \
- \
- void \
- print(FILE* f) const \
- { \
- fprintf(f, "("); \
- this->left_print(f); \
- fprintf(f, " %s ", #OPERATOR); \
- this->right_print(f); \
- fprintf(f, ")"); \
- } \
- }; \
- \
- extern "C" Expression* \
- script_exp_binary_ ## NAME(Expression* left, Expression* right) \
- { \
- return new Binary_ ## NAME(left, right); \
- }
- BINARY_EXPRESSION(mult, *, false, false, false, true)
- BINARY_EXPRESSION(div, /, false, false, true, true)
- BINARY_EXPRESSION(mod, %, false, false, true, true)
- BINARY_EXPRESSION(add, +, true, true, false, true)
- BINARY_EXPRESSION(sub, -, true, false, false, false)
- BINARY_EXPRESSION(lshift, <<, false, false, false, true)
- BINARY_EXPRESSION(rshift, >>, false, false, false, true)
- BINARY_EXPRESSION(eq, ==, false, false, false, false)
- BINARY_EXPRESSION(ne, !=, false, false, false, false)
- BINARY_EXPRESSION(le, <=, false, false, false, false)
- BINARY_EXPRESSION(ge, >=, false, false, false, false)
- BINARY_EXPRESSION(lt, <, false, false, false, false)
- BINARY_EXPRESSION(gt, >, false, false, false, false)
- BINARY_EXPRESSION(bitwise_and, &, true, true, false, true)
- BINARY_EXPRESSION(bitwise_xor, ^, true, true, false, true)
- BINARY_EXPRESSION(bitwise_or, |, true, true, false, true)
- BINARY_EXPRESSION(logical_and, &&, false, false, false, true)
- BINARY_EXPRESSION(logical_or, ||, false, false, false, true)
- // 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,
- Output_section** section_pointer) const
- {
- return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
- eei->check_assertions,
- eei->is_dot_available,
- eei->dot_value,
- eei->dot_section,
- section_pointer,
- NULL,
- NULL,
- NULL,
- NULL,
- false,
- eei->is_valid_pointer);
- }
- uint64_t
- arg2_value(const Expression_eval_info* eei,
- Output_section** section_pointer,
- uint64_t* alignment_pointer) const
- {
- return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
- eei->check_assertions,
- eei->is_dot_available,
- eei->dot_value,
- eei->dot_section,
- section_pointer,
- alignment_pointer,
- NULL,
- NULL,
- NULL,
- false,
- eei->is_valid_pointer);
- }
- uint64_t
- arg3_value(const Expression_eval_info* eei,
- Output_section** section_pointer,
- uint64_t* alignment_pointer) const
- {
- return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
- eei->check_assertions,
- eei->is_dot_available,
- eei->dot_value,
- eei->dot_section,
- section_pointer,
- alignment_pointer,
- NULL,
- NULL,
- NULL,
- false,
- eei->is_valid_pointer);
- }
- void
- arg1_print(FILE* f) const
- { this->arg1_->print(f); }
- void
- arg2_print(FILE* f) const
- { this->arg2_->print(f); }
- void
- arg3_print(FILE* f) const
- { this->arg3_->print(f); }
- 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)
- {
- Output_section* arg1_section;
- uint64_t arg1 = this->arg1_value(eei, &arg1_section);
- return (arg1
- ? this->arg2_value(eei, eei->result_section_pointer,
- eei->result_alignment_pointer)
- : this->arg3_value(eei, eei->result_section_pointer,
- eei->result_alignment_pointer));
- }
- void
- print(FILE* f) const
- {
- fprintf(f, "(");
- this->arg1_print(f);
- fprintf(f, " ? ");
- this->arg2_print(f);
- fprintf(f, " : ");
- this->arg3_print(f);
- fprintf(f, ")");
- }
- };
- 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)
- {
- Output_section* left_section;
- uint64_t left_alignment;
- uint64_t left = this->left_value(eei, &left_section, &left_alignment);
- Output_section* right_section;
- uint64_t right_alignment;
- uint64_t right = this->right_value(eei, &right_section, &right_alignment);
- if (left_section == right_section)
- {
- if (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = left_section;
- }
- else if ((left_section != NULL || right_section != NULL)
- && parameters->options().relocatable())
- gold_warning(_("max applied to section relative value"));
- if (eei->result_alignment_pointer != NULL)
- {
- uint64_t ra = *eei->result_alignment_pointer;
- if (left > right)
- ra = std::max(ra, left_alignment);
- else if (right > left)
- ra = std::max(ra, right_alignment);
- else
- ra = std::max(ra, std::max(left_alignment, right_alignment));
- *eei->result_alignment_pointer = ra;
- }
- return std::max(left, right);
- }
- void
- print(FILE* f) const
- { this->print_function(f, "MAX"); }
- };
- 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)
- {
- Output_section* left_section;
- uint64_t left_alignment;
- uint64_t left = this->left_value(eei, &left_section, &left_alignment);
- Output_section* right_section;
- uint64_t right_alignment;
- uint64_t right = this->right_value(eei, &right_section, &right_alignment);
- if (left_section == right_section)
- {
- if (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = left_section;
- }
- else if ((left_section != NULL || right_section != NULL)
- && parameters->options().relocatable())
- gold_warning(_("min applied to section relative value"));
- if (eei->result_alignment_pointer != NULL)
- {
- uint64_t ra = *eei->result_alignment_pointer;
- if (left < right)
- ra = std::max(ra, left_alignment);
- else if (right < left)
- ra = std::max(ra, right_alignment);
- else
- ra = std::max(ra, std::max(left_alignment, right_alignment));
- *eei->result_alignment_pointer = ra;
- }
- return std::min(left, right);
- }
- void
- print(FILE* f) const
- { this->print_function(f, "MIN"); }
- };
- extern "C" Expression*
- script_exp_function_min(Expression* left, Expression* right)
- {
- return new Min_expression(left, right);
- }
- // Class Section_expression. This is a parent class used for
- // functions which take the name of an output section.
- class Section_expression : public Expression
- {
- public:
- Section_expression(const char* section_name, size_t section_name_len)
- : section_name_(section_name, section_name_len)
- { }
- uint64_t
- value(const Expression_eval_info*);
- void
- print(FILE* f) const
- { fprintf(f, "%s(%s)", this->function_name(), this->section_name_.c_str()); }
- protected:
- // The child class must implement this.
- virtual uint64_t
- value_from_output_section(const Expression_eval_info*,
- Output_section*) = 0;
- // The child class must implement this.
- virtual uint64_t
- value_from_script_output_section(uint64_t address, uint64_t load_address,
- uint64_t addralign, uint64_t size) = 0;
- // The child class must implement this.
- virtual const char*
- function_name() const = 0;
- private:
- std::string section_name_;
- };
- uint64_t
- Section_expression::value(const Expression_eval_info* eei)
- {
- const char* section_name = this->section_name_.c_str();
- Output_section* os = eei->layout->find_output_section(section_name);
- if (os != NULL)
- return this->value_from_output_section(eei, os);
- uint64_t address;
- uint64_t load_address;
- uint64_t addralign;
- uint64_t size;
- const Script_options* ss = eei->layout->script_options();
- if (ss->saw_sections_clause())
- {
- if (ss->script_sections()->get_output_section_info(section_name,
- &address,
- &load_address,
- &addralign,
- &size))
- return this->value_from_script_output_section(address, load_address,
- addralign, size);
- }
- gold_error("%s called on nonexistent output section '%s'",
- this->function_name(), section_name);
- return 0;
- }
- // ABSOLUTE function.
- class Absolute_expression : public Unary_expression
- {
- public:
- Absolute_expression(Expression* arg)
- : Unary_expression(arg)
- { }
- uint64_t
- value(const Expression_eval_info* eei)
- {
- uint64_t ret = this->arg_value(eei, NULL);
- // Force the value to be absolute.
- if (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = NULL;
- return ret;
- }
- void
- print(FILE* f) const
- {
- fprintf(f, "ABSOLUTE(");
- this->arg_print(f);
- fprintf(f, ")");
- }
- };
- extern "C" Expression*
- script_exp_function_absolute(Expression* arg)
- {
- return new Absolute_expression(arg);
- }
- // 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)
- {
- Output_section* align_section;
- uint64_t align = this->right_value(eei, &align_section, NULL);
- if (align_section != NULL
- && parameters->options().relocatable())
- gold_warning(_("aligning to section relative value"));
- if (eei->result_alignment_pointer != NULL
- && align > *eei->result_alignment_pointer)
- {
- uint64_t a = align;
- while ((a & (a - 1)) != 0)
- a &= a - 1;
- *eei->result_alignment_pointer = a;
- }
- uint64_t value = this->left_value(eei, eei->result_section_pointer, NULL);
- if (align <= 1)
- return value;
- return ((value + align - 1) / align) * align;
- }
- void
- print(FILE* f) const
- { this->print_function(f, "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, eei->result_section_pointer);
- if (!value && eei->check_assertions)
- gold_error("%s", this->message_.c_str());
- return value;
- }
- void
- print(FILE* f) const
- {
- fprintf(f, "ASSERT(");
- this->arg_print(f);
- fprintf(f, ", %s)", this->message_.c_str());
- }
- 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);
- }
- // ADDR function.
- class Addr_expression : public Section_expression
- {
- public:
- Addr_expression(const char* section_name, size_t section_name_len)
- : Section_expression(section_name, section_name_len)
- { }
- protected:
- uint64_t
- value_from_output_section(const Expression_eval_info* eei,
- Output_section* os)
- {
- if (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = os;
- if (os->is_address_valid())
- return os->address();
- *eei->is_valid_pointer = false;
- return 0;
- }
- uint64_t
- value_from_script_output_section(uint64_t address, uint64_t, uint64_t,
- uint64_t)
- { return address; }
- const char*
- function_name() const
- { return "ADDR"; }
- };
- extern "C" Expression*
- script_exp_function_addr(const char* section_name, size_t section_name_len)
- {
- return new Addr_expression(section_name, section_name_len);
- }
- // ALIGNOF.
- class Alignof_expression : public Section_expression
- {
- public:
- Alignof_expression(const char* section_name, size_t section_name_len)
- : Section_expression(section_name, section_name_len)
- { }
- protected:
- uint64_t
- value_from_output_section(const Expression_eval_info*,
- Output_section* os)
- { return os->addralign(); }
- uint64_t
- value_from_script_output_section(uint64_t, uint64_t, uint64_t addralign,
- uint64_t)
- { return addralign; }
- const char*
- function_name() const
- { return "ALIGNOF"; }
- };
- extern "C" Expression*
- script_exp_function_alignof(const char* section_name, size_t section_name_len)
- {
- return new Alignof_expression(section_name, section_name_len);
- }
- // 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_constant(const char* name, size_t length)
- {
- 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_data_segment_align(Expression* left, Expression*)
- {
- 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_data_segment_relro_end(Expression*, Expression* right)
- {
- return right;
- }
- // DATA_SEGMENT_END. FIXME: This is not implemented.
- extern "C" Expression*
- script_exp_function_data_segment_end(Expression* val)
- {
- return val;
- }
- // DEFINED function.
- class Defined_expression : public Expression
- {
- public:
- Defined_expression(const char* symbol_name, size_t symbol_name_len)
- : symbol_name_(symbol_name, symbol_name_len)
- { }
- uint64_t
- value(const Expression_eval_info* eei)
- {
- Symbol* sym = eei->symtab->lookup(this->symbol_name_.c_str());
- return sym != NULL && sym->is_defined();
- }
- void
- print(FILE* f) const
- { fprintf(f, "DEFINED(%s)", this->symbol_name_.c_str()); }
- private:
- std::string symbol_name_;
- };
- extern "C" Expression*
- script_exp_function_defined(const char* symbol_name, size_t symbol_name_len)
- {
- return new Defined_expression(symbol_name, symbol_name_len);
- }
- // LOADADDR function
- class Loadaddr_expression : public Section_expression
- {
- public:
- Loadaddr_expression(const char* section_name, size_t section_name_len)
- : Section_expression(section_name, section_name_len)
- { }
- protected:
- uint64_t
- value_from_output_section(const Expression_eval_info* eei,
- Output_section* os)
- {
- if (os->has_load_address())
- return os->load_address();
- else
- {
- if (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = os;
- return os->address();
- }
- }
- uint64_t
- value_from_script_output_section(uint64_t, uint64_t load_address, uint64_t,
- uint64_t)
- { return load_address; }
- const char*
- function_name() const
- { return "LOADADDR"; }
- };
- extern "C" Expression*
- script_exp_function_loadaddr(const char* section_name, size_t section_name_len)
- {
- return new Loadaddr_expression(section_name, section_name_len);
- }
- // SIZEOF function
- class Sizeof_expression : public Section_expression
- {
- public:
- Sizeof_expression(const char* section_name, size_t section_name_len)
- : Section_expression(section_name, section_name_len)
- { }
- protected:
- uint64_t
- value_from_output_section(const Expression_eval_info*,
- Output_section* os)
- {
- // We can not use data_size here, as the size of the section may
- // not have been finalized. Instead we get whatever the current
- // size is. This will work correctly for backward references in
- // linker scripts.
- return os->current_data_size();
- }
- uint64_t
- value_from_script_output_section(uint64_t, uint64_t, uint64_t,
- uint64_t size)
- { return size; }
- const char*
- function_name() const
- { return "SIZEOF"; }
- };
- extern "C" Expression*
- script_exp_function_sizeof(const char* section_name, size_t section_name_len)
- {
- return new Sizeof_expression(section_name, section_name_len);
- }
- // 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->target().get_size() == 32)
- {
- ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size;
- phdr_size = elfcpp::Elf_sizes<32>::phdr_size;
- }
- else if (parameters->target().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_sizeof_headers()
- {
- return new Sizeof_headers_expression();
- }
- // SEGMENT_START.
- class Segment_start_expression : public Unary_expression
- {
- public:
- Segment_start_expression(const char* segment_name, size_t segment_name_len,
- Expression* default_value)
- : Unary_expression(default_value),
- segment_name_(segment_name, segment_name_len)
- { }
- uint64_t
- value(const Expression_eval_info*);
- void
- print(FILE* f) const
- {
- fprintf(f, "SEGMENT_START(\"%s\", ", this->segment_name_.c_str());
- this->arg_print(f);
- fprintf(f, ")");
- }
- private:
- std::string segment_name_;
- };
- uint64_t
- Segment_start_expression::value(const Expression_eval_info* eei)
- {
- // Check for command line overrides.
- if (parameters->options().user_set_Ttext()
- && this->segment_name_ == ".text")
- return parameters->options().Ttext();
- else if (parameters->options().user_set_Tdata()
- && this->segment_name_ == ".data")
- return parameters->options().Tdata();
- else if (parameters->options().user_set_Tbss()
- && this->segment_name_ == ".bss")
- return parameters->options().Tbss();
- else
- {
- uint64_t ret = this->arg_value(eei, NULL);
- // Force the value to be absolute.
- if (eei->result_section_pointer != NULL)
- *eei->result_section_pointer = NULL;
- return ret;
- }
- }
- extern "C" Expression*
- script_exp_function_segment_start(const char* segment_name,
- size_t segment_name_len,
- Expression* default_value)
- {
- return new Segment_start_expression(segment_name, segment_name_len,
- default_value);
- }
- } // End namespace gold.
|