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