1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363 |
- // expression.cc -- expressions in linker scripts for gold
- // Copyright (C) 2006-2022 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
- set_expr_sym_in_real_elf(Symbol_table* symtab) const
- {
- Symbol* sym = symtab->lookup(this->name_.c_str());
- if (sym != NULL)
- sym->set_in_real_elf();
- }
- 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); }
- void
- set_expr_sym_in_real_elf(Symbol_table* symtab) const
- { return this->arg_->set_expr_sym_in_real_elf(symtab); }
- 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, ")");
- }
- void
- set_expr_sym_in_real_elf(Symbol_table* symtab) const
- {
- this->left_->set_expr_sym_in_real_elf(symtab);
- this->right_->set_expr_sym_in_real_elf(symtab);
- }
- 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->arg2_->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->arg3_->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); }
- void
- set_expr_sym_in_real_elf(Symbol_table* symtab) const
- {
- this->arg1_->set_expr_sym_in_real_elf(symtab);
- this->arg2_->set_expr_sym_in_real_elf(symtab);
- this->arg3_->set_expr_sym_in_real_elf(symtab);
- }
- 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.
|