1*a9fa9459Szrj // expression.cc -- expressions in linker scripts for gold 2*a9fa9459Szrj 3*a9fa9459Szrj // Copyright (C) 2006-2016 Free Software Foundation, Inc. 4*a9fa9459Szrj // Written by Ian Lance Taylor <iant@google.com>. 5*a9fa9459Szrj 6*a9fa9459Szrj // This file is part of gold. 7*a9fa9459Szrj 8*a9fa9459Szrj // This program is free software; you can redistribute it and/or modify 9*a9fa9459Szrj // it under the terms of the GNU General Public License as published by 10*a9fa9459Szrj // the Free Software Foundation; either version 3 of the License, or 11*a9fa9459Szrj // (at your option) any later version. 12*a9fa9459Szrj 13*a9fa9459Szrj // This program is distributed in the hope that it will be useful, 14*a9fa9459Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of 15*a9fa9459Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*a9fa9459Szrj // GNU General Public License for more details. 17*a9fa9459Szrj 18*a9fa9459Szrj // You should have received a copy of the GNU General Public License 19*a9fa9459Szrj // along with this program; if not, write to the Free Software 20*a9fa9459Szrj // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21*a9fa9459Szrj // MA 02110-1301, USA. 22*a9fa9459Szrj 23*a9fa9459Szrj #include "gold.h" 24*a9fa9459Szrj 25*a9fa9459Szrj #include <string> 26*a9fa9459Szrj 27*a9fa9459Szrj #include "elfcpp.h" 28*a9fa9459Szrj #include "parameters.h" 29*a9fa9459Szrj #include "symtab.h" 30*a9fa9459Szrj #include "layout.h" 31*a9fa9459Szrj #include "output.h" 32*a9fa9459Szrj #include "script.h" 33*a9fa9459Szrj #include "script-c.h" 34*a9fa9459Szrj 35*a9fa9459Szrj namespace gold 36*a9fa9459Szrj { 37*a9fa9459Szrj 38*a9fa9459Szrj // This file holds the code which handles linker expressions. 39*a9fa9459Szrj 40*a9fa9459Szrj // The dot symbol, which linker scripts refer to simply as ".", 41*a9fa9459Szrj // requires special treatment. The dot symbol is set several times, 42*a9fa9459Szrj // section addresses will refer to it, output sections will change it, 43*a9fa9459Szrj // and it can be set based on the value of other symbols. We simplify 44*a9fa9459Szrj // the handling by prohibiting setting the dot symbol to the value of 45*a9fa9459Szrj // a non-absolute symbol. 46*a9fa9459Szrj 47*a9fa9459Szrj // When evaluating the value of an expression, we pass in a pointer to 48*a9fa9459Szrj // this struct, so that the expression evaluation can find the 49*a9fa9459Szrj // information it needs. 50*a9fa9459Szrj 51*a9fa9459Szrj struct Expression::Expression_eval_info 52*a9fa9459Szrj { 53*a9fa9459Szrj // The symbol table. 54*a9fa9459Szrj const Symbol_table* symtab; 55*a9fa9459Szrj // The layout--we use this to get section information. 56*a9fa9459Szrj const Layout* layout; 57*a9fa9459Szrj // Whether to check assertions. 58*a9fa9459Szrj bool check_assertions; 59*a9fa9459Szrj // Whether expressions can refer to the dot symbol. The dot symbol 60*a9fa9459Szrj // is only available within a SECTIONS clause. 61*a9fa9459Szrj bool is_dot_available; 62*a9fa9459Szrj // The current value of the dot symbol. 63*a9fa9459Szrj uint64_t dot_value; 64*a9fa9459Szrj // The section in which the dot symbol is defined; this is NULL if 65*a9fa9459Szrj // it is absolute. 66*a9fa9459Szrj Output_section* dot_section; 67*a9fa9459Szrj // Points to where the section of the result should be stored. 68*a9fa9459Szrj Output_section** result_section_pointer; 69*a9fa9459Szrj // Pointer to where the alignment of the result should be stored. 70*a9fa9459Szrj uint64_t* result_alignment_pointer; 71*a9fa9459Szrj // Pointer to where the type of the symbol on the RHS should be stored. 72*a9fa9459Szrj elfcpp::STT* type_pointer; 73*a9fa9459Szrj // Pointer to where the visibility of the symbol on the RHS should be stored. 74*a9fa9459Szrj elfcpp::STV* vis_pointer; 75*a9fa9459Szrj // Pointer to where the rest of the symbol's st_other field should be stored. 76*a9fa9459Szrj unsigned char* nonvis_pointer; 77*a9fa9459Szrj // Whether the value is valid. In Symbol_assignment::set_if_absolute, we 78*a9fa9459Szrj // may be trying to evaluate the address of a section whose address is not 79*a9fa9459Szrj // yet finalized, and we need to fail the evaluation gracefully. 80*a9fa9459Szrj bool *is_valid_pointer; 81*a9fa9459Szrj }; 82*a9fa9459Szrj 83*a9fa9459Szrj // Evaluate an expression. 84*a9fa9459Szrj 85*a9fa9459Szrj uint64_t 86*a9fa9459Szrj Expression::eval(const Symbol_table* symtab, const Layout* layout, 87*a9fa9459Szrj bool check_assertions) 88*a9fa9459Szrj { 89*a9fa9459Szrj return this->eval_maybe_dot(symtab, layout, check_assertions, false, 0, 90*a9fa9459Szrj NULL, NULL, NULL, NULL, NULL, NULL, false, NULL); 91*a9fa9459Szrj } 92*a9fa9459Szrj 93*a9fa9459Szrj // Evaluate an expression which may refer to the dot symbol. 94*a9fa9459Szrj 95*a9fa9459Szrj uint64_t 96*a9fa9459Szrj Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout, 97*a9fa9459Szrj bool check_assertions, uint64_t dot_value, 98*a9fa9459Szrj Output_section* dot_section, 99*a9fa9459Szrj Output_section** result_section_pointer, 100*a9fa9459Szrj uint64_t* result_alignment_pointer, 101*a9fa9459Szrj bool is_section_dot_assignment) 102*a9fa9459Szrj { 103*a9fa9459Szrj return this->eval_maybe_dot(symtab, layout, check_assertions, true, 104*a9fa9459Szrj dot_value, dot_section, result_section_pointer, 105*a9fa9459Szrj result_alignment_pointer, NULL, NULL, NULL, 106*a9fa9459Szrj is_section_dot_assignment, NULL); 107*a9fa9459Szrj } 108*a9fa9459Szrj 109*a9fa9459Szrj // Evaluate an expression which may or may not refer to the dot 110*a9fa9459Szrj // symbol. 111*a9fa9459Szrj 112*a9fa9459Szrj uint64_t 113*a9fa9459Szrj Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, 114*a9fa9459Szrj bool check_assertions, bool is_dot_available, 115*a9fa9459Szrj uint64_t dot_value, Output_section* dot_section, 116*a9fa9459Szrj Output_section** result_section_pointer, 117*a9fa9459Szrj uint64_t* result_alignment_pointer, 118*a9fa9459Szrj elfcpp::STT* type_pointer, 119*a9fa9459Szrj elfcpp::STV* vis_pointer, 120*a9fa9459Szrj unsigned char* nonvis_pointer, 121*a9fa9459Szrj bool is_section_dot_assignment, 122*a9fa9459Szrj bool* is_valid_pointer) 123*a9fa9459Szrj { 124*a9fa9459Szrj Expression_eval_info eei; 125*a9fa9459Szrj eei.symtab = symtab; 126*a9fa9459Szrj eei.layout = layout; 127*a9fa9459Szrj eei.check_assertions = check_assertions; 128*a9fa9459Szrj eei.is_dot_available = is_dot_available; 129*a9fa9459Szrj eei.dot_value = dot_value; 130*a9fa9459Szrj eei.dot_section = dot_section; 131*a9fa9459Szrj 132*a9fa9459Szrj // We assume the value is absolute, and only set this to a section 133*a9fa9459Szrj // if we find a section-relative reference. 134*a9fa9459Szrj if (result_section_pointer != NULL) 135*a9fa9459Szrj *result_section_pointer = NULL; 136*a9fa9459Szrj eei.result_section_pointer = result_section_pointer; 137*a9fa9459Szrj 138*a9fa9459Szrj // For symbol=symbol assignments, we need to track the type, visibility, 139*a9fa9459Szrj // and remaining st_other bits. 140*a9fa9459Szrj eei.type_pointer = type_pointer; 141*a9fa9459Szrj eei.vis_pointer = vis_pointer; 142*a9fa9459Szrj eei.nonvis_pointer = nonvis_pointer; 143*a9fa9459Szrj 144*a9fa9459Szrj eei.result_alignment_pointer = result_alignment_pointer; 145*a9fa9459Szrj 146*a9fa9459Szrj // Assume the value is valid until we try to evaluate an expression 147*a9fa9459Szrj // that can't be evaluated yet. 148*a9fa9459Szrj bool is_valid = true; 149*a9fa9459Szrj eei.is_valid_pointer = &is_valid; 150*a9fa9459Szrj 151*a9fa9459Szrj uint64_t val = this->value(&eei); 152*a9fa9459Szrj 153*a9fa9459Szrj if (is_valid_pointer != NULL) 154*a9fa9459Szrj *is_valid_pointer = is_valid; 155*a9fa9459Szrj else 156*a9fa9459Szrj gold_assert(is_valid); 157*a9fa9459Szrj 158*a9fa9459Szrj // If this is an assignment to dot within a section, and the value 159*a9fa9459Szrj // is absolute, treat it as a section-relative offset. 160*a9fa9459Szrj if (is_section_dot_assignment && *result_section_pointer == NULL) 161*a9fa9459Szrj { 162*a9fa9459Szrj gold_assert(dot_section != NULL); 163*a9fa9459Szrj val += dot_section->address(); 164*a9fa9459Szrj *result_section_pointer = dot_section; 165*a9fa9459Szrj } 166*a9fa9459Szrj return val; 167*a9fa9459Szrj } 168*a9fa9459Szrj 169*a9fa9459Szrj // A number. 170*a9fa9459Szrj 171*a9fa9459Szrj class Integer_expression : public Expression 172*a9fa9459Szrj { 173*a9fa9459Szrj public: 174*a9fa9459Szrj Integer_expression(uint64_t val) 175*a9fa9459Szrj : val_(val) 176*a9fa9459Szrj { } 177*a9fa9459Szrj 178*a9fa9459Szrj uint64_t 179*a9fa9459Szrj value(const Expression_eval_info*) 180*a9fa9459Szrj { return this->val_; } 181*a9fa9459Szrj 182*a9fa9459Szrj void 183*a9fa9459Szrj print(FILE* f) const 184*a9fa9459Szrj { fprintf(f, "0x%llx", static_cast<unsigned long long>(this->val_)); } 185*a9fa9459Szrj 186*a9fa9459Szrj private: 187*a9fa9459Szrj uint64_t val_; 188*a9fa9459Szrj }; 189*a9fa9459Szrj 190*a9fa9459Szrj extern "C" Expression* 191*a9fa9459Szrj script_exp_integer(uint64_t val) 192*a9fa9459Szrj { 193*a9fa9459Szrj return new Integer_expression(val); 194*a9fa9459Szrj } 195*a9fa9459Szrj 196*a9fa9459Szrj // An expression whose value is the value of a symbol. 197*a9fa9459Szrj 198*a9fa9459Szrj class Symbol_expression : public Expression 199*a9fa9459Szrj { 200*a9fa9459Szrj public: 201*a9fa9459Szrj Symbol_expression(const char* name, size_t length) 202*a9fa9459Szrj : name_(name, length) 203*a9fa9459Szrj { } 204*a9fa9459Szrj 205*a9fa9459Szrj uint64_t 206*a9fa9459Szrj value(const Expression_eval_info*); 207*a9fa9459Szrj 208*a9fa9459Szrj void 209*a9fa9459Szrj print(FILE* f) const 210*a9fa9459Szrj { fprintf(f, "%s", this->name_.c_str()); } 211*a9fa9459Szrj 212*a9fa9459Szrj private: 213*a9fa9459Szrj std::string name_; 214*a9fa9459Szrj }; 215*a9fa9459Szrj 216*a9fa9459Szrj uint64_t 217*a9fa9459Szrj Symbol_expression::value(const Expression_eval_info* eei) 218*a9fa9459Szrj { 219*a9fa9459Szrj Symbol* sym = eei->symtab->lookup(this->name_.c_str()); 220*a9fa9459Szrj if (sym == NULL || !sym->is_defined()) 221*a9fa9459Szrj { 222*a9fa9459Szrj gold_error(_("undefined symbol '%s' referenced in expression"), 223*a9fa9459Szrj this->name_.c_str()); 224*a9fa9459Szrj return 0; 225*a9fa9459Szrj } 226*a9fa9459Szrj 227*a9fa9459Szrj if (eei->result_section_pointer != NULL) 228*a9fa9459Szrj *eei->result_section_pointer = sym->output_section(); 229*a9fa9459Szrj if (eei->type_pointer != NULL) 230*a9fa9459Szrj *eei->type_pointer = sym->type(); 231*a9fa9459Szrj if (eei->vis_pointer != NULL) 232*a9fa9459Szrj *eei->vis_pointer = sym->visibility(); 233*a9fa9459Szrj if (eei->nonvis_pointer != NULL) 234*a9fa9459Szrj *eei->nonvis_pointer = sym->nonvis(); 235*a9fa9459Szrj 236*a9fa9459Szrj if (parameters->target().get_size() == 32) 237*a9fa9459Szrj return eei->symtab->get_sized_symbol<32>(sym)->value(); 238*a9fa9459Szrj else if (parameters->target().get_size() == 64) 239*a9fa9459Szrj return eei->symtab->get_sized_symbol<64>(sym)->value(); 240*a9fa9459Szrj else 241*a9fa9459Szrj gold_unreachable(); 242*a9fa9459Szrj } 243*a9fa9459Szrj 244*a9fa9459Szrj // An expression whose value is the value of the special symbol ".". 245*a9fa9459Szrj // This is only valid within a SECTIONS clause. 246*a9fa9459Szrj 247*a9fa9459Szrj class Dot_expression : public Expression 248*a9fa9459Szrj { 249*a9fa9459Szrj public: 250*a9fa9459Szrj Dot_expression() 251*a9fa9459Szrj { } 252*a9fa9459Szrj 253*a9fa9459Szrj uint64_t 254*a9fa9459Szrj value(const Expression_eval_info*); 255*a9fa9459Szrj 256*a9fa9459Szrj void 257*a9fa9459Szrj print(FILE* f) const 258*a9fa9459Szrj { fprintf(f, "."); } 259*a9fa9459Szrj }; 260*a9fa9459Szrj 261*a9fa9459Szrj uint64_t 262*a9fa9459Szrj Dot_expression::value(const Expression_eval_info* eei) 263*a9fa9459Szrj { 264*a9fa9459Szrj if (!eei->is_dot_available) 265*a9fa9459Szrj { 266*a9fa9459Szrj gold_error(_("invalid reference to dot symbol outside of " 267*a9fa9459Szrj "SECTIONS clause")); 268*a9fa9459Szrj return 0; 269*a9fa9459Szrj } 270*a9fa9459Szrj if (eei->result_section_pointer != NULL) 271*a9fa9459Szrj *eei->result_section_pointer = eei->dot_section; 272*a9fa9459Szrj return eei->dot_value; 273*a9fa9459Szrj } 274*a9fa9459Szrj 275*a9fa9459Szrj // A string. This is either the name of a symbol, or ".". 276*a9fa9459Szrj 277*a9fa9459Szrj extern "C" Expression* 278*a9fa9459Szrj script_exp_string(const char* name, size_t length) 279*a9fa9459Szrj { 280*a9fa9459Szrj if (length == 1 && name[0] == '.') 281*a9fa9459Szrj return new Dot_expression(); 282*a9fa9459Szrj else 283*a9fa9459Szrj return new Symbol_expression(name, length); 284*a9fa9459Szrj } 285*a9fa9459Szrj 286*a9fa9459Szrj // A unary expression. 287*a9fa9459Szrj 288*a9fa9459Szrj class Unary_expression : public Expression 289*a9fa9459Szrj { 290*a9fa9459Szrj public: 291*a9fa9459Szrj Unary_expression(Expression* arg) 292*a9fa9459Szrj : arg_(arg) 293*a9fa9459Szrj { } 294*a9fa9459Szrj 295*a9fa9459Szrj ~Unary_expression() 296*a9fa9459Szrj { delete this->arg_; } 297*a9fa9459Szrj 298*a9fa9459Szrj protected: 299*a9fa9459Szrj uint64_t 300*a9fa9459Szrj arg_value(const Expression_eval_info* eei, 301*a9fa9459Szrj Output_section** arg_section_pointer) const 302*a9fa9459Szrj { 303*a9fa9459Szrj return this->arg_->eval_maybe_dot(eei->symtab, eei->layout, 304*a9fa9459Szrj eei->check_assertions, 305*a9fa9459Szrj eei->is_dot_available, 306*a9fa9459Szrj eei->dot_value, 307*a9fa9459Szrj eei->dot_section, 308*a9fa9459Szrj arg_section_pointer, 309*a9fa9459Szrj eei->result_alignment_pointer, 310*a9fa9459Szrj NULL, 311*a9fa9459Szrj NULL, 312*a9fa9459Szrj NULL, 313*a9fa9459Szrj false, 314*a9fa9459Szrj eei->is_valid_pointer); 315*a9fa9459Szrj } 316*a9fa9459Szrj 317*a9fa9459Szrj void 318*a9fa9459Szrj arg_print(FILE* f) const 319*a9fa9459Szrj { this->arg_->print(f); } 320*a9fa9459Szrj 321*a9fa9459Szrj private: 322*a9fa9459Szrj Expression* arg_; 323*a9fa9459Szrj }; 324*a9fa9459Szrj 325*a9fa9459Szrj // Handle unary operators. We use a preprocessor macro as a hack to 326*a9fa9459Szrj // capture the C operator. 327*a9fa9459Szrj 328*a9fa9459Szrj #define UNARY_EXPRESSION(NAME, OPERATOR) \ 329*a9fa9459Szrj class Unary_ ## NAME : public Unary_expression \ 330*a9fa9459Szrj { \ 331*a9fa9459Szrj public: \ 332*a9fa9459Szrj Unary_ ## NAME(Expression* arg) \ 333*a9fa9459Szrj : Unary_expression(arg) \ 334*a9fa9459Szrj { } \ 335*a9fa9459Szrj \ 336*a9fa9459Szrj uint64_t \ 337*a9fa9459Szrj value(const Expression_eval_info* eei) \ 338*a9fa9459Szrj { \ 339*a9fa9459Szrj Output_section* arg_section; \ 340*a9fa9459Szrj uint64_t ret = OPERATOR this->arg_value(eei, &arg_section); \ 341*a9fa9459Szrj if (arg_section != NULL && parameters->options().relocatable()) \ 342*a9fa9459Szrj gold_warning(_("unary " #NAME " applied to section " \ 343*a9fa9459Szrj "relative value")); \ 344*a9fa9459Szrj return ret; \ 345*a9fa9459Szrj } \ 346*a9fa9459Szrj \ 347*a9fa9459Szrj void \ 348*a9fa9459Szrj print(FILE* f) const \ 349*a9fa9459Szrj { \ 350*a9fa9459Szrj fprintf(f, "(%s ", #OPERATOR); \ 351*a9fa9459Szrj this->arg_print(f); \ 352*a9fa9459Szrj fprintf(f, ")"); \ 353*a9fa9459Szrj } \ 354*a9fa9459Szrj }; \ 355*a9fa9459Szrj \ 356*a9fa9459Szrj extern "C" Expression* \ 357*a9fa9459Szrj script_exp_unary_ ## NAME(Expression* arg) \ 358*a9fa9459Szrj { \ 359*a9fa9459Szrj return new Unary_ ## NAME(arg); \ 360*a9fa9459Szrj } 361*a9fa9459Szrj 362*a9fa9459Szrj UNARY_EXPRESSION(minus, -) 363*a9fa9459Szrj UNARY_EXPRESSION(logical_not, !) 364*a9fa9459Szrj UNARY_EXPRESSION(bitwise_not, ~) 365*a9fa9459Szrj 366*a9fa9459Szrj // A binary expression. 367*a9fa9459Szrj 368*a9fa9459Szrj class Binary_expression : public Expression 369*a9fa9459Szrj { 370*a9fa9459Szrj public: 371*a9fa9459Szrj Binary_expression(Expression* left, Expression* right) 372*a9fa9459Szrj : left_(left), right_(right) 373*a9fa9459Szrj { } 374*a9fa9459Szrj 375*a9fa9459Szrj ~Binary_expression() 376*a9fa9459Szrj { 377*a9fa9459Szrj delete this->left_; 378*a9fa9459Szrj delete this->right_; 379*a9fa9459Szrj } 380*a9fa9459Szrj 381*a9fa9459Szrj protected: 382*a9fa9459Szrj uint64_t 383*a9fa9459Szrj left_value(const Expression_eval_info* eei, 384*a9fa9459Szrj Output_section** section_pointer, 385*a9fa9459Szrj uint64_t* alignment_pointer) const 386*a9fa9459Szrj { 387*a9fa9459Szrj return this->left_->eval_maybe_dot(eei->symtab, eei->layout, 388*a9fa9459Szrj eei->check_assertions, 389*a9fa9459Szrj eei->is_dot_available, 390*a9fa9459Szrj eei->dot_value, 391*a9fa9459Szrj eei->dot_section, 392*a9fa9459Szrj section_pointer, 393*a9fa9459Szrj alignment_pointer, 394*a9fa9459Szrj NULL, 395*a9fa9459Szrj NULL, 396*a9fa9459Szrj NULL, 397*a9fa9459Szrj false, 398*a9fa9459Szrj eei->is_valid_pointer); 399*a9fa9459Szrj } 400*a9fa9459Szrj 401*a9fa9459Szrj uint64_t 402*a9fa9459Szrj right_value(const Expression_eval_info* eei, 403*a9fa9459Szrj Output_section** section_pointer, 404*a9fa9459Szrj uint64_t* alignment_pointer) const 405*a9fa9459Szrj { 406*a9fa9459Szrj return this->right_->eval_maybe_dot(eei->symtab, eei->layout, 407*a9fa9459Szrj eei->check_assertions, 408*a9fa9459Szrj eei->is_dot_available, 409*a9fa9459Szrj eei->dot_value, 410*a9fa9459Szrj eei->dot_section, 411*a9fa9459Szrj section_pointer, 412*a9fa9459Szrj alignment_pointer, 413*a9fa9459Szrj NULL, 414*a9fa9459Szrj NULL, 415*a9fa9459Szrj NULL, 416*a9fa9459Szrj false, 417*a9fa9459Szrj eei->is_valid_pointer); 418*a9fa9459Szrj } 419*a9fa9459Szrj 420*a9fa9459Szrj void 421*a9fa9459Szrj left_print(FILE* f) const 422*a9fa9459Szrj { this->left_->print(f); } 423*a9fa9459Szrj 424*a9fa9459Szrj void 425*a9fa9459Szrj right_print(FILE* f) const 426*a9fa9459Szrj { this->right_->print(f); } 427*a9fa9459Szrj 428*a9fa9459Szrj // This is a call to function FUNCTION_NAME. Print it. This is for 429*a9fa9459Szrj // debugging. 430*a9fa9459Szrj void 431*a9fa9459Szrj print_function(FILE* f, const char* function_name) const 432*a9fa9459Szrj { 433*a9fa9459Szrj fprintf(f, "%s(", function_name); 434*a9fa9459Szrj this->left_print(f); 435*a9fa9459Szrj fprintf(f, ", "); 436*a9fa9459Szrj this->right_print(f); 437*a9fa9459Szrj fprintf(f, ")"); 438*a9fa9459Szrj } 439*a9fa9459Szrj 440*a9fa9459Szrj private: 441*a9fa9459Szrj Expression* left_; 442*a9fa9459Szrj Expression* right_; 443*a9fa9459Szrj }; 444*a9fa9459Szrj 445*a9fa9459Szrj // Handle binary operators. We use a preprocessor macro as a hack to 446*a9fa9459Szrj // capture the C operator. KEEP_LEFT means that if the left operand 447*a9fa9459Szrj // is section relative and the right operand is not, the result uses 448*a9fa9459Szrj // the same section as the left operand. KEEP_RIGHT is the same with 449*a9fa9459Szrj // left and right swapped. IS_DIV means that we need to give an error 450*a9fa9459Szrj // if the right operand is zero. WARN means that we should warn if 451*a9fa9459Szrj // used on section relative values in a relocatable link. We always 452*a9fa9459Szrj // warn if used on values in different sections in a relocatable link. 453*a9fa9459Szrj 454*a9fa9459Szrj #define BINARY_EXPRESSION(NAME, OPERATOR, KEEP_LEFT, KEEP_RIGHT, IS_DIV, WARN) \ 455*a9fa9459Szrj class Binary_ ## NAME : public Binary_expression \ 456*a9fa9459Szrj { \ 457*a9fa9459Szrj public: \ 458*a9fa9459Szrj Binary_ ## NAME(Expression* left, Expression* right) \ 459*a9fa9459Szrj : Binary_expression(left, right) \ 460*a9fa9459Szrj { } \ 461*a9fa9459Szrj \ 462*a9fa9459Szrj uint64_t \ 463*a9fa9459Szrj value(const Expression_eval_info* eei) \ 464*a9fa9459Szrj { \ 465*a9fa9459Szrj Output_section* left_section; \ 466*a9fa9459Szrj uint64_t left_alignment = 0; \ 467*a9fa9459Szrj uint64_t left = this->left_value(eei, &left_section, \ 468*a9fa9459Szrj &left_alignment); \ 469*a9fa9459Szrj Output_section* right_section; \ 470*a9fa9459Szrj uint64_t right_alignment = 0; \ 471*a9fa9459Szrj uint64_t right = this->right_value(eei, &right_section, \ 472*a9fa9459Szrj &right_alignment); \ 473*a9fa9459Szrj if (KEEP_RIGHT && left_section == NULL && right_section != NULL) \ 474*a9fa9459Szrj { \ 475*a9fa9459Szrj if (eei->result_section_pointer != NULL) \ 476*a9fa9459Szrj *eei->result_section_pointer = right_section; \ 477*a9fa9459Szrj if (eei->result_alignment_pointer != NULL \ 478*a9fa9459Szrj && right_alignment > *eei->result_alignment_pointer) \ 479*a9fa9459Szrj *eei->result_alignment_pointer = right_alignment; \ 480*a9fa9459Szrj } \ 481*a9fa9459Szrj else if (KEEP_LEFT \ 482*a9fa9459Szrj && left_section != NULL \ 483*a9fa9459Szrj && right_section == NULL) \ 484*a9fa9459Szrj { \ 485*a9fa9459Szrj if (eei->result_section_pointer != NULL) \ 486*a9fa9459Szrj *eei->result_section_pointer = left_section; \ 487*a9fa9459Szrj if (eei->result_alignment_pointer != NULL \ 488*a9fa9459Szrj && left_alignment > *eei->result_alignment_pointer) \ 489*a9fa9459Szrj *eei->result_alignment_pointer = left_alignment; \ 490*a9fa9459Szrj } \ 491*a9fa9459Szrj else if ((WARN || left_section != right_section) \ 492*a9fa9459Szrj && (left_section != NULL || right_section != NULL) \ 493*a9fa9459Szrj && parameters->options().relocatable()) \ 494*a9fa9459Szrj gold_warning(_("binary " #NAME " applied to section " \ 495*a9fa9459Szrj "relative value")); \ 496*a9fa9459Szrj if (IS_DIV && right == 0) \ 497*a9fa9459Szrj { \ 498*a9fa9459Szrj gold_error(_(#NAME " by zero")); \ 499*a9fa9459Szrj return 0; \ 500*a9fa9459Szrj } \ 501*a9fa9459Szrj return left OPERATOR right; \ 502*a9fa9459Szrj } \ 503*a9fa9459Szrj \ 504*a9fa9459Szrj void \ 505*a9fa9459Szrj print(FILE* f) const \ 506*a9fa9459Szrj { \ 507*a9fa9459Szrj fprintf(f, "("); \ 508*a9fa9459Szrj this->left_print(f); \ 509*a9fa9459Szrj fprintf(f, " %s ", #OPERATOR); \ 510*a9fa9459Szrj this->right_print(f); \ 511*a9fa9459Szrj fprintf(f, ")"); \ 512*a9fa9459Szrj } \ 513*a9fa9459Szrj }; \ 514*a9fa9459Szrj \ 515*a9fa9459Szrj extern "C" Expression* \ 516*a9fa9459Szrj script_exp_binary_ ## NAME(Expression* left, Expression* right) \ 517*a9fa9459Szrj { \ 518*a9fa9459Szrj return new Binary_ ## NAME(left, right); \ 519*a9fa9459Szrj } 520*a9fa9459Szrj 521*a9fa9459Szrj BINARY_EXPRESSION(mult, *, false, false, false, true) 522*a9fa9459Szrj BINARY_EXPRESSION(div, /, false, false, true, true) 523*a9fa9459Szrj BINARY_EXPRESSION(mod, %, false, false, true, true) 524*a9fa9459Szrj BINARY_EXPRESSION(add, +, true, true, false, true) 525*a9fa9459Szrj BINARY_EXPRESSION(sub, -, true, false, false, false) 526*a9fa9459Szrj BINARY_EXPRESSION(lshift, <<, false, false, false, true) 527*a9fa9459Szrj BINARY_EXPRESSION(rshift, >>, false, false, false, true) 528*a9fa9459Szrj BINARY_EXPRESSION(eq, ==, false, false, false, false) 529*a9fa9459Szrj BINARY_EXPRESSION(ne, !=, false, false, false, false) 530*a9fa9459Szrj BINARY_EXPRESSION(le, <=, false, false, false, false) 531*a9fa9459Szrj BINARY_EXPRESSION(ge, >=, false, false, false, false) 532*a9fa9459Szrj BINARY_EXPRESSION(lt, <, false, false, false, false) 533*a9fa9459Szrj BINARY_EXPRESSION(gt, >, false, false, false, false) 534*a9fa9459Szrj BINARY_EXPRESSION(bitwise_and, &, true, true, false, true) 535*a9fa9459Szrj BINARY_EXPRESSION(bitwise_xor, ^, true, true, false, true) 536*a9fa9459Szrj BINARY_EXPRESSION(bitwise_or, |, true, true, false, true) 537*a9fa9459Szrj BINARY_EXPRESSION(logical_and, &&, false, false, false, true) 538*a9fa9459Szrj BINARY_EXPRESSION(logical_or, ||, false, false, false, true) 539*a9fa9459Szrj 540*a9fa9459Szrj // A trinary expression. 541*a9fa9459Szrj 542*a9fa9459Szrj class Trinary_expression : public Expression 543*a9fa9459Szrj { 544*a9fa9459Szrj public: 545*a9fa9459Szrj Trinary_expression(Expression* arg1, Expression* arg2, Expression* arg3) 546*a9fa9459Szrj : arg1_(arg1), arg2_(arg2), arg3_(arg3) 547*a9fa9459Szrj { } 548*a9fa9459Szrj 549*a9fa9459Szrj ~Trinary_expression() 550*a9fa9459Szrj { 551*a9fa9459Szrj delete this->arg1_; 552*a9fa9459Szrj delete this->arg2_; 553*a9fa9459Szrj delete this->arg3_; 554*a9fa9459Szrj } 555*a9fa9459Szrj 556*a9fa9459Szrj protected: 557*a9fa9459Szrj uint64_t 558*a9fa9459Szrj arg1_value(const Expression_eval_info* eei, 559*a9fa9459Szrj Output_section** section_pointer) const 560*a9fa9459Szrj { 561*a9fa9459Szrj return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout, 562*a9fa9459Szrj eei->check_assertions, 563*a9fa9459Szrj eei->is_dot_available, 564*a9fa9459Szrj eei->dot_value, 565*a9fa9459Szrj eei->dot_section, 566*a9fa9459Szrj section_pointer, 567*a9fa9459Szrj NULL, 568*a9fa9459Szrj NULL, 569*a9fa9459Szrj NULL, 570*a9fa9459Szrj NULL, 571*a9fa9459Szrj false, 572*a9fa9459Szrj eei->is_valid_pointer); 573*a9fa9459Szrj } 574*a9fa9459Szrj 575*a9fa9459Szrj uint64_t 576*a9fa9459Szrj arg2_value(const Expression_eval_info* eei, 577*a9fa9459Szrj Output_section** section_pointer, 578*a9fa9459Szrj uint64_t* alignment_pointer) const 579*a9fa9459Szrj { 580*a9fa9459Szrj return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout, 581*a9fa9459Szrj eei->check_assertions, 582*a9fa9459Szrj eei->is_dot_available, 583*a9fa9459Szrj eei->dot_value, 584*a9fa9459Szrj eei->dot_section, 585*a9fa9459Szrj section_pointer, 586*a9fa9459Szrj alignment_pointer, 587*a9fa9459Szrj NULL, 588*a9fa9459Szrj NULL, 589*a9fa9459Szrj NULL, 590*a9fa9459Szrj false, 591*a9fa9459Szrj eei->is_valid_pointer); 592*a9fa9459Szrj } 593*a9fa9459Szrj 594*a9fa9459Szrj uint64_t 595*a9fa9459Szrj arg3_value(const Expression_eval_info* eei, 596*a9fa9459Szrj Output_section** section_pointer, 597*a9fa9459Szrj uint64_t* alignment_pointer) const 598*a9fa9459Szrj { 599*a9fa9459Szrj return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout, 600*a9fa9459Szrj eei->check_assertions, 601*a9fa9459Szrj eei->is_dot_available, 602*a9fa9459Szrj eei->dot_value, 603*a9fa9459Szrj eei->dot_section, 604*a9fa9459Szrj section_pointer, 605*a9fa9459Szrj alignment_pointer, 606*a9fa9459Szrj NULL, 607*a9fa9459Szrj NULL, 608*a9fa9459Szrj NULL, 609*a9fa9459Szrj false, 610*a9fa9459Szrj eei->is_valid_pointer); 611*a9fa9459Szrj } 612*a9fa9459Szrj 613*a9fa9459Szrj void 614*a9fa9459Szrj arg1_print(FILE* f) const 615*a9fa9459Szrj { this->arg1_->print(f); } 616*a9fa9459Szrj 617*a9fa9459Szrj void 618*a9fa9459Szrj arg2_print(FILE* f) const 619*a9fa9459Szrj { this->arg2_->print(f); } 620*a9fa9459Szrj 621*a9fa9459Szrj void 622*a9fa9459Szrj arg3_print(FILE* f) const 623*a9fa9459Szrj { this->arg3_->print(f); } 624*a9fa9459Szrj 625*a9fa9459Szrj private: 626*a9fa9459Szrj Expression* arg1_; 627*a9fa9459Szrj Expression* arg2_; 628*a9fa9459Szrj Expression* arg3_; 629*a9fa9459Szrj }; 630*a9fa9459Szrj 631*a9fa9459Szrj // The conditional operator. 632*a9fa9459Szrj 633*a9fa9459Szrj class Trinary_cond : public Trinary_expression 634*a9fa9459Szrj { 635*a9fa9459Szrj public: 636*a9fa9459Szrj Trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3) 637*a9fa9459Szrj : Trinary_expression(arg1, arg2, arg3) 638*a9fa9459Szrj { } 639*a9fa9459Szrj 640*a9fa9459Szrj uint64_t 641*a9fa9459Szrj value(const Expression_eval_info* eei) 642*a9fa9459Szrj { 643*a9fa9459Szrj Output_section* arg1_section; 644*a9fa9459Szrj uint64_t arg1 = this->arg1_value(eei, &arg1_section); 645*a9fa9459Szrj return (arg1 646*a9fa9459Szrj ? this->arg2_value(eei, eei->result_section_pointer, 647*a9fa9459Szrj eei->result_alignment_pointer) 648*a9fa9459Szrj : this->arg3_value(eei, eei->result_section_pointer, 649*a9fa9459Szrj eei->result_alignment_pointer)); 650*a9fa9459Szrj } 651*a9fa9459Szrj 652*a9fa9459Szrj void 653*a9fa9459Szrj print(FILE* f) const 654*a9fa9459Szrj { 655*a9fa9459Szrj fprintf(f, "("); 656*a9fa9459Szrj this->arg1_print(f); 657*a9fa9459Szrj fprintf(f, " ? "); 658*a9fa9459Szrj this->arg2_print(f); 659*a9fa9459Szrj fprintf(f, " : "); 660*a9fa9459Szrj this->arg3_print(f); 661*a9fa9459Szrj fprintf(f, ")"); 662*a9fa9459Szrj } 663*a9fa9459Szrj }; 664*a9fa9459Szrj 665*a9fa9459Szrj extern "C" Expression* 666*a9fa9459Szrj script_exp_trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3) 667*a9fa9459Szrj { 668*a9fa9459Szrj return new Trinary_cond(arg1, arg2, arg3); 669*a9fa9459Szrj } 670*a9fa9459Szrj 671*a9fa9459Szrj // Max function. 672*a9fa9459Szrj 673*a9fa9459Szrj class Max_expression : public Binary_expression 674*a9fa9459Szrj { 675*a9fa9459Szrj public: 676*a9fa9459Szrj Max_expression(Expression* left, Expression* right) 677*a9fa9459Szrj : Binary_expression(left, right) 678*a9fa9459Szrj { } 679*a9fa9459Szrj 680*a9fa9459Szrj uint64_t 681*a9fa9459Szrj value(const Expression_eval_info* eei) 682*a9fa9459Szrj { 683*a9fa9459Szrj Output_section* left_section; 684*a9fa9459Szrj uint64_t left_alignment; 685*a9fa9459Szrj uint64_t left = this->left_value(eei, &left_section, &left_alignment); 686*a9fa9459Szrj Output_section* right_section; 687*a9fa9459Szrj uint64_t right_alignment; 688*a9fa9459Szrj uint64_t right = this->right_value(eei, &right_section, &right_alignment); 689*a9fa9459Szrj if (left_section == right_section) 690*a9fa9459Szrj { 691*a9fa9459Szrj if (eei->result_section_pointer != NULL) 692*a9fa9459Szrj *eei->result_section_pointer = left_section; 693*a9fa9459Szrj } 694*a9fa9459Szrj else if ((left_section != NULL || right_section != NULL) 695*a9fa9459Szrj && parameters->options().relocatable()) 696*a9fa9459Szrj gold_warning(_("max applied to section relative value")); 697*a9fa9459Szrj if (eei->result_alignment_pointer != NULL) 698*a9fa9459Szrj { 699*a9fa9459Szrj uint64_t ra = *eei->result_alignment_pointer; 700*a9fa9459Szrj if (left > right) 701*a9fa9459Szrj ra = std::max(ra, left_alignment); 702*a9fa9459Szrj else if (right > left) 703*a9fa9459Szrj ra = std::max(ra, right_alignment); 704*a9fa9459Szrj else 705*a9fa9459Szrj ra = std::max(ra, std::max(left_alignment, right_alignment)); 706*a9fa9459Szrj *eei->result_alignment_pointer = ra; 707*a9fa9459Szrj } 708*a9fa9459Szrj return std::max(left, right); 709*a9fa9459Szrj } 710*a9fa9459Szrj 711*a9fa9459Szrj void 712*a9fa9459Szrj print(FILE* f) const 713*a9fa9459Szrj { this->print_function(f, "MAX"); } 714*a9fa9459Szrj }; 715*a9fa9459Szrj 716*a9fa9459Szrj extern "C" Expression* 717*a9fa9459Szrj script_exp_function_max(Expression* left, Expression* right) 718*a9fa9459Szrj { 719*a9fa9459Szrj return new Max_expression(left, right); 720*a9fa9459Szrj } 721*a9fa9459Szrj 722*a9fa9459Szrj // Min function. 723*a9fa9459Szrj 724*a9fa9459Szrj class Min_expression : public Binary_expression 725*a9fa9459Szrj { 726*a9fa9459Szrj public: 727*a9fa9459Szrj Min_expression(Expression* left, Expression* right) 728*a9fa9459Szrj : Binary_expression(left, right) 729*a9fa9459Szrj { } 730*a9fa9459Szrj 731*a9fa9459Szrj uint64_t 732*a9fa9459Szrj value(const Expression_eval_info* eei) 733*a9fa9459Szrj { 734*a9fa9459Szrj Output_section* left_section; 735*a9fa9459Szrj uint64_t left_alignment; 736*a9fa9459Szrj uint64_t left = this->left_value(eei, &left_section, &left_alignment); 737*a9fa9459Szrj Output_section* right_section; 738*a9fa9459Szrj uint64_t right_alignment; 739*a9fa9459Szrj uint64_t right = this->right_value(eei, &right_section, &right_alignment); 740*a9fa9459Szrj if (left_section == right_section) 741*a9fa9459Szrj { 742*a9fa9459Szrj if (eei->result_section_pointer != NULL) 743*a9fa9459Szrj *eei->result_section_pointer = left_section; 744*a9fa9459Szrj } 745*a9fa9459Szrj else if ((left_section != NULL || right_section != NULL) 746*a9fa9459Szrj && parameters->options().relocatable()) 747*a9fa9459Szrj gold_warning(_("min applied to section relative value")); 748*a9fa9459Szrj if (eei->result_alignment_pointer != NULL) 749*a9fa9459Szrj { 750*a9fa9459Szrj uint64_t ra = *eei->result_alignment_pointer; 751*a9fa9459Szrj if (left < right) 752*a9fa9459Szrj ra = std::max(ra, left_alignment); 753*a9fa9459Szrj else if (right < left) 754*a9fa9459Szrj ra = std::max(ra, right_alignment); 755*a9fa9459Szrj else 756*a9fa9459Szrj ra = std::max(ra, std::max(left_alignment, right_alignment)); 757*a9fa9459Szrj *eei->result_alignment_pointer = ra; 758*a9fa9459Szrj } 759*a9fa9459Szrj return std::min(left, right); 760*a9fa9459Szrj } 761*a9fa9459Szrj 762*a9fa9459Szrj void 763*a9fa9459Szrj print(FILE* f) const 764*a9fa9459Szrj { this->print_function(f, "MIN"); } 765*a9fa9459Szrj }; 766*a9fa9459Szrj 767*a9fa9459Szrj extern "C" Expression* 768*a9fa9459Szrj script_exp_function_min(Expression* left, Expression* right) 769*a9fa9459Szrj { 770*a9fa9459Szrj return new Min_expression(left, right); 771*a9fa9459Szrj } 772*a9fa9459Szrj 773*a9fa9459Szrj // Class Section_expression. This is a parent class used for 774*a9fa9459Szrj // functions which take the name of an output section. 775*a9fa9459Szrj 776*a9fa9459Szrj class Section_expression : public Expression 777*a9fa9459Szrj { 778*a9fa9459Szrj public: 779*a9fa9459Szrj Section_expression(const char* section_name, size_t section_name_len) 780*a9fa9459Szrj : section_name_(section_name, section_name_len) 781*a9fa9459Szrj { } 782*a9fa9459Szrj 783*a9fa9459Szrj uint64_t 784*a9fa9459Szrj value(const Expression_eval_info*); 785*a9fa9459Szrj 786*a9fa9459Szrj void 787*a9fa9459Szrj print(FILE* f) const 788*a9fa9459Szrj { fprintf(f, "%s(%s)", this->function_name(), this->section_name_.c_str()); } 789*a9fa9459Szrj 790*a9fa9459Szrj protected: 791*a9fa9459Szrj // The child class must implement this. 792*a9fa9459Szrj virtual uint64_t 793*a9fa9459Szrj value_from_output_section(const Expression_eval_info*, 794*a9fa9459Szrj Output_section*) = 0; 795*a9fa9459Szrj 796*a9fa9459Szrj // The child class must implement this. 797*a9fa9459Szrj virtual uint64_t 798*a9fa9459Szrj value_from_script_output_section(uint64_t address, uint64_t load_address, 799*a9fa9459Szrj uint64_t addralign, uint64_t size) = 0; 800*a9fa9459Szrj 801*a9fa9459Szrj // The child class must implement this. 802*a9fa9459Szrj virtual const char* 803*a9fa9459Szrj function_name() const = 0; 804*a9fa9459Szrj 805*a9fa9459Szrj private: 806*a9fa9459Szrj std::string section_name_; 807*a9fa9459Szrj }; 808*a9fa9459Szrj 809*a9fa9459Szrj uint64_t 810*a9fa9459Szrj Section_expression::value(const Expression_eval_info* eei) 811*a9fa9459Szrj { 812*a9fa9459Szrj const char* section_name = this->section_name_.c_str(); 813*a9fa9459Szrj Output_section* os = eei->layout->find_output_section(section_name); 814*a9fa9459Szrj if (os != NULL) 815*a9fa9459Szrj return this->value_from_output_section(eei, os); 816*a9fa9459Szrj 817*a9fa9459Szrj uint64_t address; 818*a9fa9459Szrj uint64_t load_address; 819*a9fa9459Szrj uint64_t addralign; 820*a9fa9459Szrj uint64_t size; 821*a9fa9459Szrj const Script_options* ss = eei->layout->script_options(); 822*a9fa9459Szrj if (ss->saw_sections_clause()) 823*a9fa9459Szrj { 824*a9fa9459Szrj if (ss->script_sections()->get_output_section_info(section_name, 825*a9fa9459Szrj &address, 826*a9fa9459Szrj &load_address, 827*a9fa9459Szrj &addralign, 828*a9fa9459Szrj &size)) 829*a9fa9459Szrj return this->value_from_script_output_section(address, load_address, 830*a9fa9459Szrj addralign, size); 831*a9fa9459Szrj } 832*a9fa9459Szrj 833*a9fa9459Szrj gold_error("%s called on nonexistent output section '%s'", 834*a9fa9459Szrj this->function_name(), section_name); 835*a9fa9459Szrj return 0; 836*a9fa9459Szrj } 837*a9fa9459Szrj 838*a9fa9459Szrj // ABSOLUTE function. 839*a9fa9459Szrj 840*a9fa9459Szrj class Absolute_expression : public Unary_expression 841*a9fa9459Szrj { 842*a9fa9459Szrj public: 843*a9fa9459Szrj Absolute_expression(Expression* arg) 844*a9fa9459Szrj : Unary_expression(arg) 845*a9fa9459Szrj { } 846*a9fa9459Szrj 847*a9fa9459Szrj uint64_t 848*a9fa9459Szrj value(const Expression_eval_info* eei) 849*a9fa9459Szrj { 850*a9fa9459Szrj uint64_t ret = this->arg_value(eei, NULL); 851*a9fa9459Szrj // Force the value to be absolute. 852*a9fa9459Szrj if (eei->result_section_pointer != NULL) 853*a9fa9459Szrj *eei->result_section_pointer = NULL; 854*a9fa9459Szrj return ret; 855*a9fa9459Szrj } 856*a9fa9459Szrj 857*a9fa9459Szrj void 858*a9fa9459Szrj print(FILE* f) const 859*a9fa9459Szrj { 860*a9fa9459Szrj fprintf(f, "ABSOLUTE("); 861*a9fa9459Szrj this->arg_print(f); 862*a9fa9459Szrj fprintf(f, ")"); 863*a9fa9459Szrj } 864*a9fa9459Szrj }; 865*a9fa9459Szrj 866*a9fa9459Szrj extern "C" Expression* 867*a9fa9459Szrj script_exp_function_absolute(Expression* arg) 868*a9fa9459Szrj { 869*a9fa9459Szrj return new Absolute_expression(arg); 870*a9fa9459Szrj } 871*a9fa9459Szrj 872*a9fa9459Szrj // ALIGN function. 873*a9fa9459Szrj 874*a9fa9459Szrj class Align_expression : public Binary_expression 875*a9fa9459Szrj { 876*a9fa9459Szrj public: 877*a9fa9459Szrj Align_expression(Expression* left, Expression* right) 878*a9fa9459Szrj : Binary_expression(left, right) 879*a9fa9459Szrj { } 880*a9fa9459Szrj 881*a9fa9459Szrj uint64_t 882*a9fa9459Szrj value(const Expression_eval_info* eei) 883*a9fa9459Szrj { 884*a9fa9459Szrj Output_section* align_section; 885*a9fa9459Szrj uint64_t align = this->right_value(eei, &align_section, NULL); 886*a9fa9459Szrj if (align_section != NULL 887*a9fa9459Szrj && parameters->options().relocatable()) 888*a9fa9459Szrj gold_warning(_("aligning to section relative value")); 889*a9fa9459Szrj 890*a9fa9459Szrj if (eei->result_alignment_pointer != NULL 891*a9fa9459Szrj && align > *eei->result_alignment_pointer) 892*a9fa9459Szrj { 893*a9fa9459Szrj uint64_t a = align; 894*a9fa9459Szrj while ((a & (a - 1)) != 0) 895*a9fa9459Szrj a &= a - 1; 896*a9fa9459Szrj *eei->result_alignment_pointer = a; 897*a9fa9459Szrj } 898*a9fa9459Szrj 899*a9fa9459Szrj uint64_t value = this->left_value(eei, eei->result_section_pointer, NULL); 900*a9fa9459Szrj if (align <= 1) 901*a9fa9459Szrj return value; 902*a9fa9459Szrj return ((value + align - 1) / align) * align; 903*a9fa9459Szrj } 904*a9fa9459Szrj 905*a9fa9459Szrj void 906*a9fa9459Szrj print(FILE* f) const 907*a9fa9459Szrj { this->print_function(f, "ALIGN"); } 908*a9fa9459Szrj }; 909*a9fa9459Szrj 910*a9fa9459Szrj extern "C" Expression* 911*a9fa9459Szrj script_exp_function_align(Expression* left, Expression* right) 912*a9fa9459Szrj { 913*a9fa9459Szrj return new Align_expression(left, right); 914*a9fa9459Szrj } 915*a9fa9459Szrj 916*a9fa9459Szrj // ASSERT function. 917*a9fa9459Szrj 918*a9fa9459Szrj class Assert_expression : public Unary_expression 919*a9fa9459Szrj { 920*a9fa9459Szrj public: 921*a9fa9459Szrj Assert_expression(Expression* arg, const char* message, size_t length) 922*a9fa9459Szrj : Unary_expression(arg), message_(message, length) 923*a9fa9459Szrj { } 924*a9fa9459Szrj 925*a9fa9459Szrj uint64_t 926*a9fa9459Szrj value(const Expression_eval_info* eei) 927*a9fa9459Szrj { 928*a9fa9459Szrj uint64_t value = this->arg_value(eei, eei->result_section_pointer); 929*a9fa9459Szrj if (!value && eei->check_assertions) 930*a9fa9459Szrj gold_error("%s", this->message_.c_str()); 931*a9fa9459Szrj return value; 932*a9fa9459Szrj } 933*a9fa9459Szrj 934*a9fa9459Szrj void 935*a9fa9459Szrj print(FILE* f) const 936*a9fa9459Szrj { 937*a9fa9459Szrj fprintf(f, "ASSERT("); 938*a9fa9459Szrj this->arg_print(f); 939*a9fa9459Szrj fprintf(f, ", %s)", this->message_.c_str()); 940*a9fa9459Szrj } 941*a9fa9459Szrj 942*a9fa9459Szrj private: 943*a9fa9459Szrj std::string message_; 944*a9fa9459Szrj }; 945*a9fa9459Szrj 946*a9fa9459Szrj extern "C" Expression* 947*a9fa9459Szrj script_exp_function_assert(Expression* expr, const char* message, 948*a9fa9459Szrj size_t length) 949*a9fa9459Szrj { 950*a9fa9459Szrj return new Assert_expression(expr, message, length); 951*a9fa9459Szrj } 952*a9fa9459Szrj 953*a9fa9459Szrj // ADDR function. 954*a9fa9459Szrj 955*a9fa9459Szrj class Addr_expression : public Section_expression 956*a9fa9459Szrj { 957*a9fa9459Szrj public: 958*a9fa9459Szrj Addr_expression(const char* section_name, size_t section_name_len) 959*a9fa9459Szrj : Section_expression(section_name, section_name_len) 960*a9fa9459Szrj { } 961*a9fa9459Szrj 962*a9fa9459Szrj protected: 963*a9fa9459Szrj uint64_t 964*a9fa9459Szrj value_from_output_section(const Expression_eval_info* eei, 965*a9fa9459Szrj Output_section* os) 966*a9fa9459Szrj { 967*a9fa9459Szrj if (eei->result_section_pointer != NULL) 968*a9fa9459Szrj *eei->result_section_pointer = os; 969*a9fa9459Szrj if (os->is_address_valid()) 970*a9fa9459Szrj return os->address(); 971*a9fa9459Szrj *eei->is_valid_pointer = false; 972*a9fa9459Szrj return 0; 973*a9fa9459Szrj } 974*a9fa9459Szrj 975*a9fa9459Szrj uint64_t 976*a9fa9459Szrj value_from_script_output_section(uint64_t address, uint64_t, uint64_t, 977*a9fa9459Szrj uint64_t) 978*a9fa9459Szrj { return address; } 979*a9fa9459Szrj 980*a9fa9459Szrj const char* 981*a9fa9459Szrj function_name() const 982*a9fa9459Szrj { return "ADDR"; } 983*a9fa9459Szrj }; 984*a9fa9459Szrj 985*a9fa9459Szrj extern "C" Expression* 986*a9fa9459Szrj script_exp_function_addr(const char* section_name, size_t section_name_len) 987*a9fa9459Szrj { 988*a9fa9459Szrj return new Addr_expression(section_name, section_name_len); 989*a9fa9459Szrj } 990*a9fa9459Szrj 991*a9fa9459Szrj // ALIGNOF. 992*a9fa9459Szrj 993*a9fa9459Szrj class Alignof_expression : public Section_expression 994*a9fa9459Szrj { 995*a9fa9459Szrj public: 996*a9fa9459Szrj Alignof_expression(const char* section_name, size_t section_name_len) 997*a9fa9459Szrj : Section_expression(section_name, section_name_len) 998*a9fa9459Szrj { } 999*a9fa9459Szrj 1000*a9fa9459Szrj protected: 1001*a9fa9459Szrj uint64_t 1002*a9fa9459Szrj value_from_output_section(const Expression_eval_info*, 1003*a9fa9459Szrj Output_section* os) 1004*a9fa9459Szrj { return os->addralign(); } 1005*a9fa9459Szrj 1006*a9fa9459Szrj uint64_t 1007*a9fa9459Szrj value_from_script_output_section(uint64_t, uint64_t, uint64_t addralign, 1008*a9fa9459Szrj uint64_t) 1009*a9fa9459Szrj { return addralign; } 1010*a9fa9459Szrj 1011*a9fa9459Szrj const char* 1012*a9fa9459Szrj function_name() const 1013*a9fa9459Szrj { return "ALIGNOF"; } 1014*a9fa9459Szrj }; 1015*a9fa9459Szrj 1016*a9fa9459Szrj extern "C" Expression* 1017*a9fa9459Szrj script_exp_function_alignof(const char* section_name, size_t section_name_len) 1018*a9fa9459Szrj { 1019*a9fa9459Szrj return new Alignof_expression(section_name, section_name_len); 1020*a9fa9459Szrj } 1021*a9fa9459Szrj 1022*a9fa9459Szrj // CONSTANT. It would be nice if we could simply evaluate this 1023*a9fa9459Szrj // immediately and return an Integer_expression, but unfortunately we 1024*a9fa9459Szrj // don't know the target. 1025*a9fa9459Szrj 1026*a9fa9459Szrj class Constant_expression : public Expression 1027*a9fa9459Szrj { 1028*a9fa9459Szrj public: 1029*a9fa9459Szrj Constant_expression(const char* name, size_t length); 1030*a9fa9459Szrj 1031*a9fa9459Szrj uint64_t 1032*a9fa9459Szrj value(const Expression_eval_info*); 1033*a9fa9459Szrj 1034*a9fa9459Szrj void 1035*a9fa9459Szrj print(FILE* f) const; 1036*a9fa9459Szrj 1037*a9fa9459Szrj private: 1038*a9fa9459Szrj enum Constant_function 1039*a9fa9459Szrj { 1040*a9fa9459Szrj CONSTANT_MAXPAGESIZE, 1041*a9fa9459Szrj CONSTANT_COMMONPAGESIZE 1042*a9fa9459Szrj }; 1043*a9fa9459Szrj 1044*a9fa9459Szrj Constant_function function_; 1045*a9fa9459Szrj }; 1046*a9fa9459Szrj 1047*a9fa9459Szrj Constant_expression::Constant_expression(const char* name, size_t length) 1048*a9fa9459Szrj { 1049*a9fa9459Szrj if (length == 11 && strncmp(name, "MAXPAGESIZE", length) == 0) 1050*a9fa9459Szrj this->function_ = CONSTANT_MAXPAGESIZE; 1051*a9fa9459Szrj else if (length == 14 && strncmp(name, "COMMONPAGESIZE", length) == 0) 1052*a9fa9459Szrj this->function_ = CONSTANT_COMMONPAGESIZE; 1053*a9fa9459Szrj else 1054*a9fa9459Szrj { 1055*a9fa9459Szrj std::string s(name, length); 1056*a9fa9459Szrj gold_error(_("unknown constant %s"), s.c_str()); 1057*a9fa9459Szrj this->function_ = CONSTANT_MAXPAGESIZE; 1058*a9fa9459Szrj } 1059*a9fa9459Szrj } 1060*a9fa9459Szrj 1061*a9fa9459Szrj uint64_t 1062*a9fa9459Szrj Constant_expression::value(const Expression_eval_info*) 1063*a9fa9459Szrj { 1064*a9fa9459Szrj switch (this->function_) 1065*a9fa9459Szrj { 1066*a9fa9459Szrj case CONSTANT_MAXPAGESIZE: 1067*a9fa9459Szrj return parameters->target().abi_pagesize(); 1068*a9fa9459Szrj case CONSTANT_COMMONPAGESIZE: 1069*a9fa9459Szrj return parameters->target().common_pagesize(); 1070*a9fa9459Szrj default: 1071*a9fa9459Szrj gold_unreachable(); 1072*a9fa9459Szrj } 1073*a9fa9459Szrj } 1074*a9fa9459Szrj 1075*a9fa9459Szrj void 1076*a9fa9459Szrj Constant_expression::print(FILE* f) const 1077*a9fa9459Szrj { 1078*a9fa9459Szrj const char* name; 1079*a9fa9459Szrj switch (this->function_) 1080*a9fa9459Szrj { 1081*a9fa9459Szrj case CONSTANT_MAXPAGESIZE: 1082*a9fa9459Szrj name = "MAXPAGESIZE"; 1083*a9fa9459Szrj break; 1084*a9fa9459Szrj case CONSTANT_COMMONPAGESIZE: 1085*a9fa9459Szrj name = "COMMONPAGESIZE"; 1086*a9fa9459Szrj break; 1087*a9fa9459Szrj default: 1088*a9fa9459Szrj gold_unreachable(); 1089*a9fa9459Szrj } 1090*a9fa9459Szrj fprintf(f, "CONSTANT(%s)", name); 1091*a9fa9459Szrj } 1092*a9fa9459Szrj 1093*a9fa9459Szrj extern "C" Expression* 1094*a9fa9459Szrj script_exp_function_constant(const char* name, size_t length) 1095*a9fa9459Szrj { 1096*a9fa9459Szrj return new Constant_expression(name, length); 1097*a9fa9459Szrj } 1098*a9fa9459Szrj 1099*a9fa9459Szrj // DATA_SEGMENT_ALIGN. FIXME: we don't implement this; we always fall 1100*a9fa9459Szrj // back to the general case. 1101*a9fa9459Szrj 1102*a9fa9459Szrj extern "C" Expression* 1103*a9fa9459Szrj script_exp_function_data_segment_align(Expression* left, Expression*) 1104*a9fa9459Szrj { 1105*a9fa9459Szrj Expression* e1 = script_exp_function_align(script_exp_string(".", 1), left); 1106*a9fa9459Szrj Expression* e2 = script_exp_binary_sub(left, script_exp_integer(1)); 1107*a9fa9459Szrj Expression* e3 = script_exp_binary_bitwise_and(script_exp_string(".", 1), 1108*a9fa9459Szrj e2); 1109*a9fa9459Szrj return script_exp_binary_add(e1, e3); 1110*a9fa9459Szrj } 1111*a9fa9459Szrj 1112*a9fa9459Szrj // DATA_SEGMENT_RELRO. FIXME: This is not implemented. 1113*a9fa9459Szrj 1114*a9fa9459Szrj extern "C" Expression* 1115*a9fa9459Szrj script_exp_function_data_segment_relro_end(Expression*, Expression* right) 1116*a9fa9459Szrj { 1117*a9fa9459Szrj return right; 1118*a9fa9459Szrj } 1119*a9fa9459Szrj 1120*a9fa9459Szrj // DATA_SEGMENT_END. FIXME: This is not implemented. 1121*a9fa9459Szrj 1122*a9fa9459Szrj extern "C" Expression* 1123*a9fa9459Szrj script_exp_function_data_segment_end(Expression* val) 1124*a9fa9459Szrj { 1125*a9fa9459Szrj return val; 1126*a9fa9459Szrj } 1127*a9fa9459Szrj 1128*a9fa9459Szrj // DEFINED function. 1129*a9fa9459Szrj 1130*a9fa9459Szrj class Defined_expression : public Expression 1131*a9fa9459Szrj { 1132*a9fa9459Szrj public: 1133*a9fa9459Szrj Defined_expression(const char* symbol_name, size_t symbol_name_len) 1134*a9fa9459Szrj : symbol_name_(symbol_name, symbol_name_len) 1135*a9fa9459Szrj { } 1136*a9fa9459Szrj 1137*a9fa9459Szrj uint64_t 1138*a9fa9459Szrj value(const Expression_eval_info* eei) 1139*a9fa9459Szrj { 1140*a9fa9459Szrj Symbol* sym = eei->symtab->lookup(this->symbol_name_.c_str()); 1141*a9fa9459Szrj return sym != NULL && sym->is_defined(); 1142*a9fa9459Szrj } 1143*a9fa9459Szrj 1144*a9fa9459Szrj void 1145*a9fa9459Szrj print(FILE* f) const 1146*a9fa9459Szrj { fprintf(f, "DEFINED(%s)", this->symbol_name_.c_str()); } 1147*a9fa9459Szrj 1148*a9fa9459Szrj private: 1149*a9fa9459Szrj std::string symbol_name_; 1150*a9fa9459Szrj }; 1151*a9fa9459Szrj 1152*a9fa9459Szrj extern "C" Expression* 1153*a9fa9459Szrj script_exp_function_defined(const char* symbol_name, size_t symbol_name_len) 1154*a9fa9459Szrj { 1155*a9fa9459Szrj return new Defined_expression(symbol_name, symbol_name_len); 1156*a9fa9459Szrj } 1157*a9fa9459Szrj 1158*a9fa9459Szrj // LOADADDR function 1159*a9fa9459Szrj 1160*a9fa9459Szrj class Loadaddr_expression : public Section_expression 1161*a9fa9459Szrj { 1162*a9fa9459Szrj public: 1163*a9fa9459Szrj Loadaddr_expression(const char* section_name, size_t section_name_len) 1164*a9fa9459Szrj : Section_expression(section_name, section_name_len) 1165*a9fa9459Szrj { } 1166*a9fa9459Szrj 1167*a9fa9459Szrj protected: 1168*a9fa9459Szrj uint64_t 1169*a9fa9459Szrj value_from_output_section(const Expression_eval_info* eei, 1170*a9fa9459Szrj Output_section* os) 1171*a9fa9459Szrj { 1172*a9fa9459Szrj if (os->has_load_address()) 1173*a9fa9459Szrj return os->load_address(); 1174*a9fa9459Szrj else 1175*a9fa9459Szrj { 1176*a9fa9459Szrj if (eei->result_section_pointer != NULL) 1177*a9fa9459Szrj *eei->result_section_pointer = os; 1178*a9fa9459Szrj return os->address(); 1179*a9fa9459Szrj } 1180*a9fa9459Szrj } 1181*a9fa9459Szrj 1182*a9fa9459Szrj uint64_t 1183*a9fa9459Szrj value_from_script_output_section(uint64_t, uint64_t load_address, uint64_t, 1184*a9fa9459Szrj uint64_t) 1185*a9fa9459Szrj { return load_address; } 1186*a9fa9459Szrj 1187*a9fa9459Szrj const char* 1188*a9fa9459Szrj function_name() const 1189*a9fa9459Szrj { return "LOADADDR"; } 1190*a9fa9459Szrj }; 1191*a9fa9459Szrj 1192*a9fa9459Szrj extern "C" Expression* 1193*a9fa9459Szrj script_exp_function_loadaddr(const char* section_name, size_t section_name_len) 1194*a9fa9459Szrj { 1195*a9fa9459Szrj return new Loadaddr_expression(section_name, section_name_len); 1196*a9fa9459Szrj } 1197*a9fa9459Szrj 1198*a9fa9459Szrj // SIZEOF function 1199*a9fa9459Szrj 1200*a9fa9459Szrj class Sizeof_expression : public Section_expression 1201*a9fa9459Szrj { 1202*a9fa9459Szrj public: 1203*a9fa9459Szrj Sizeof_expression(const char* section_name, size_t section_name_len) 1204*a9fa9459Szrj : Section_expression(section_name, section_name_len) 1205*a9fa9459Szrj { } 1206*a9fa9459Szrj 1207*a9fa9459Szrj protected: 1208*a9fa9459Szrj uint64_t 1209*a9fa9459Szrj value_from_output_section(const Expression_eval_info*, 1210*a9fa9459Szrj Output_section* os) 1211*a9fa9459Szrj { 1212*a9fa9459Szrj // We can not use data_size here, as the size of the section may 1213*a9fa9459Szrj // not have been finalized. Instead we get whatever the current 1214*a9fa9459Szrj // size is. This will work correctly for backward references in 1215*a9fa9459Szrj // linker scripts. 1216*a9fa9459Szrj return os->current_data_size(); 1217*a9fa9459Szrj } 1218*a9fa9459Szrj 1219*a9fa9459Szrj uint64_t 1220*a9fa9459Szrj value_from_script_output_section(uint64_t, uint64_t, uint64_t, 1221*a9fa9459Szrj uint64_t size) 1222*a9fa9459Szrj { return size; } 1223*a9fa9459Szrj 1224*a9fa9459Szrj const char* 1225*a9fa9459Szrj function_name() const 1226*a9fa9459Szrj { return "SIZEOF"; } 1227*a9fa9459Szrj }; 1228*a9fa9459Szrj 1229*a9fa9459Szrj extern "C" Expression* 1230*a9fa9459Szrj script_exp_function_sizeof(const char* section_name, size_t section_name_len) 1231*a9fa9459Szrj { 1232*a9fa9459Szrj return new Sizeof_expression(section_name, section_name_len); 1233*a9fa9459Szrj } 1234*a9fa9459Szrj 1235*a9fa9459Szrj // SIZEOF_HEADERS. 1236*a9fa9459Szrj 1237*a9fa9459Szrj class Sizeof_headers_expression : public Expression 1238*a9fa9459Szrj { 1239*a9fa9459Szrj public: 1240*a9fa9459Szrj Sizeof_headers_expression() 1241*a9fa9459Szrj { } 1242*a9fa9459Szrj 1243*a9fa9459Szrj uint64_t 1244*a9fa9459Szrj value(const Expression_eval_info*); 1245*a9fa9459Szrj 1246*a9fa9459Szrj void 1247*a9fa9459Szrj print(FILE* f) const 1248*a9fa9459Szrj { fprintf(f, "SIZEOF_HEADERS"); } 1249*a9fa9459Szrj }; 1250*a9fa9459Szrj 1251*a9fa9459Szrj uint64_t 1252*a9fa9459Szrj Sizeof_headers_expression::value(const Expression_eval_info* eei) 1253*a9fa9459Szrj { 1254*a9fa9459Szrj unsigned int ehdr_size; 1255*a9fa9459Szrj unsigned int phdr_size; 1256*a9fa9459Szrj if (parameters->target().get_size() == 32) 1257*a9fa9459Szrj { 1258*a9fa9459Szrj ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size; 1259*a9fa9459Szrj phdr_size = elfcpp::Elf_sizes<32>::phdr_size; 1260*a9fa9459Szrj } 1261*a9fa9459Szrj else if (parameters->target().get_size() == 64) 1262*a9fa9459Szrj { 1263*a9fa9459Szrj ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size; 1264*a9fa9459Szrj phdr_size = elfcpp::Elf_sizes<64>::phdr_size; 1265*a9fa9459Szrj } 1266*a9fa9459Szrj else 1267*a9fa9459Szrj gold_unreachable(); 1268*a9fa9459Szrj 1269*a9fa9459Szrj return ehdr_size + phdr_size * eei->layout->expected_segment_count(); 1270*a9fa9459Szrj } 1271*a9fa9459Szrj 1272*a9fa9459Szrj extern "C" Expression* 1273*a9fa9459Szrj script_exp_function_sizeof_headers() 1274*a9fa9459Szrj { 1275*a9fa9459Szrj return new Sizeof_headers_expression(); 1276*a9fa9459Szrj } 1277*a9fa9459Szrj 1278*a9fa9459Szrj // SEGMENT_START. 1279*a9fa9459Szrj 1280*a9fa9459Szrj class Segment_start_expression : public Unary_expression 1281*a9fa9459Szrj { 1282*a9fa9459Szrj public: 1283*a9fa9459Szrj Segment_start_expression(const char* segment_name, size_t segment_name_len, 1284*a9fa9459Szrj Expression* default_value) 1285*a9fa9459Szrj : Unary_expression(default_value), 1286*a9fa9459Szrj segment_name_(segment_name, segment_name_len) 1287*a9fa9459Szrj { } 1288*a9fa9459Szrj 1289*a9fa9459Szrj uint64_t 1290*a9fa9459Szrj value(const Expression_eval_info*); 1291*a9fa9459Szrj 1292*a9fa9459Szrj void 1293*a9fa9459Szrj print(FILE* f) const 1294*a9fa9459Szrj { 1295*a9fa9459Szrj fprintf(f, "SEGMENT_START(\"%s\", ", this->segment_name_.c_str()); 1296*a9fa9459Szrj this->arg_print(f); 1297*a9fa9459Szrj fprintf(f, ")"); 1298*a9fa9459Szrj } 1299*a9fa9459Szrj 1300*a9fa9459Szrj private: 1301*a9fa9459Szrj std::string segment_name_; 1302*a9fa9459Szrj }; 1303*a9fa9459Szrj 1304*a9fa9459Szrj uint64_t 1305*a9fa9459Szrj Segment_start_expression::value(const Expression_eval_info* eei) 1306*a9fa9459Szrj { 1307*a9fa9459Szrj // Check for command line overrides. 1308*a9fa9459Szrj if (parameters->options().user_set_Ttext() 1309*a9fa9459Szrj && this->segment_name_ == ".text") 1310*a9fa9459Szrj return parameters->options().Ttext(); 1311*a9fa9459Szrj else if (parameters->options().user_set_Tdata() 1312*a9fa9459Szrj && this->segment_name_ == ".data") 1313*a9fa9459Szrj return parameters->options().Tdata(); 1314*a9fa9459Szrj else if (parameters->options().user_set_Tbss() 1315*a9fa9459Szrj && this->segment_name_ == ".bss") 1316*a9fa9459Szrj return parameters->options().Tbss(); 1317*a9fa9459Szrj else 1318*a9fa9459Szrj { 1319*a9fa9459Szrj uint64_t ret = this->arg_value(eei, NULL); 1320*a9fa9459Szrj // Force the value to be absolute. 1321*a9fa9459Szrj if (eei->result_section_pointer != NULL) 1322*a9fa9459Szrj *eei->result_section_pointer = NULL; 1323*a9fa9459Szrj return ret; 1324*a9fa9459Szrj } 1325*a9fa9459Szrj } 1326*a9fa9459Szrj 1327*a9fa9459Szrj extern "C" Expression* 1328*a9fa9459Szrj script_exp_function_segment_start(const char* segment_name, 1329*a9fa9459Szrj size_t segment_name_len, 1330*a9fa9459Szrj Expression* default_value) 1331*a9fa9459Szrj { 1332*a9fa9459Szrj return new Segment_start_expression(segment_name, segment_name_len, 1333*a9fa9459Szrj default_value); 1334*a9fa9459Szrj } 1335*a9fa9459Szrj 1336*a9fa9459Szrj } // End namespace gold. 1337