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
eval(const Symbol_table * symtab,const Layout * layout,bool check_assertions)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
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*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
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*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:
Integer_expression(uint64_t val)174*a9fa9459Szrj Integer_expression(uint64_t val)
175*a9fa9459Szrj : val_(val)
176*a9fa9459Szrj { }
177*a9fa9459Szrj
178*a9fa9459Szrj uint64_t
value(const Expression_eval_info *)179*a9fa9459Szrj value(const Expression_eval_info*)
180*a9fa9459Szrj { return this->val_; }
181*a9fa9459Szrj
182*a9fa9459Szrj void
print(FILE * f) const183*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*
script_exp_integer(uint64_t val)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:
Symbol_expression(const char * name,size_t length)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
print(FILE * f) const209*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
value(const Expression_eval_info * eei)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:
Dot_expression()250*a9fa9459Szrj Dot_expression()
251*a9fa9459Szrj { }
252*a9fa9459Szrj
253*a9fa9459Szrj uint64_t
254*a9fa9459Szrj value(const Expression_eval_info*);
255*a9fa9459Szrj
256*a9fa9459Szrj void
print(FILE * f) const257*a9fa9459Szrj print(FILE* f) const
258*a9fa9459Szrj { fprintf(f, "."); }
259*a9fa9459Szrj };
260*a9fa9459Szrj
261*a9fa9459Szrj uint64_t
value(const Expression_eval_info * eei)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*
script_exp_string(const char * name,size_t length)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:
Unary_expression(Expression * arg)291*a9fa9459Szrj Unary_expression(Expression* arg)
292*a9fa9459Szrj : arg_(arg)
293*a9fa9459Szrj { }
294*a9fa9459Szrj
~Unary_expression()295*a9fa9459Szrj ~Unary_expression()
296*a9fa9459Szrj { delete this->arg_; }
297*a9fa9459Szrj
298*a9fa9459Szrj protected:
299*a9fa9459Szrj uint64_t
arg_value(const Expression_eval_info * eei,Output_section ** arg_section_pointer) const300*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
arg_print(FILE * f) const318*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:
Binary_expression(Expression * left,Expression * right)371*a9fa9459Szrj Binary_expression(Expression* left, Expression* right)
372*a9fa9459Szrj : left_(left), right_(right)
373*a9fa9459Szrj { }
374*a9fa9459Szrj
~Binary_expression()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
left_value(const Expression_eval_info * eei,Output_section ** section_pointer,uint64_t * alignment_pointer) const383*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
right_value(const Expression_eval_info * eei,Output_section ** section_pointer,uint64_t * alignment_pointer) const402*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
left_print(FILE * f) const421*a9fa9459Szrj left_print(FILE* f) const
422*a9fa9459Szrj { this->left_->print(f); }
423*a9fa9459Szrj
424*a9fa9459Szrj void
right_print(FILE * f) const425*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
print_function(FILE * f,const char * function_name) const431*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:
Trinary_expression(Expression * arg1,Expression * arg2,Expression * arg3)545*a9fa9459Szrj Trinary_expression(Expression* arg1, Expression* arg2, Expression* arg3)
546*a9fa9459Szrj : arg1_(arg1), arg2_(arg2), arg3_(arg3)
547*a9fa9459Szrj { }
548*a9fa9459Szrj
~Trinary_expression()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
arg1_value(const Expression_eval_info * eei,Output_section ** section_pointer) const558*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
arg2_value(const Expression_eval_info * eei,Output_section ** section_pointer,uint64_t * alignment_pointer) const576*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
arg3_value(const Expression_eval_info * eei,Output_section ** section_pointer,uint64_t * alignment_pointer) const595*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
arg1_print(FILE * f) const614*a9fa9459Szrj arg1_print(FILE* f) const
615*a9fa9459Szrj { this->arg1_->print(f); }
616*a9fa9459Szrj
617*a9fa9459Szrj void
arg2_print(FILE * f) const618*a9fa9459Szrj arg2_print(FILE* f) const
619*a9fa9459Szrj { this->arg2_->print(f); }
620*a9fa9459Szrj
621*a9fa9459Szrj void
arg3_print(FILE * f) const622*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:
Trinary_cond(Expression * arg1,Expression * arg2,Expression * arg3)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
value(const Expression_eval_info * eei)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
print(FILE * f) const653*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*
script_exp_trinary_cond(Expression * arg1,Expression * arg2,Expression * arg3)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:
Max_expression(Expression * left,Expression * right)676*a9fa9459Szrj Max_expression(Expression* left, Expression* right)
677*a9fa9459Szrj : Binary_expression(left, right)
678*a9fa9459Szrj { }
679*a9fa9459Szrj
680*a9fa9459Szrj uint64_t
value(const Expression_eval_info * eei)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
print(FILE * f) const712*a9fa9459Szrj print(FILE* f) const
713*a9fa9459Szrj { this->print_function(f, "MAX"); }
714*a9fa9459Szrj };
715*a9fa9459Szrj
716*a9fa9459Szrj extern "C" Expression*
script_exp_function_max(Expression * left,Expression * right)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:
Min_expression(Expression * left,Expression * right)727*a9fa9459Szrj Min_expression(Expression* left, Expression* right)
728*a9fa9459Szrj : Binary_expression(left, right)
729*a9fa9459Szrj { }
730*a9fa9459Szrj
731*a9fa9459Szrj uint64_t
value(const Expression_eval_info * eei)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
print(FILE * f) const763*a9fa9459Szrj print(FILE* f) const
764*a9fa9459Szrj { this->print_function(f, "MIN"); }
765*a9fa9459Szrj };
766*a9fa9459Szrj
767*a9fa9459Szrj extern "C" Expression*
script_exp_function_min(Expression * left,Expression * right)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:
Section_expression(const char * section_name,size_t section_name_len)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
print(FILE * f) const787*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
value(const Expression_eval_info * eei)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:
Absolute_expression(Expression * arg)843*a9fa9459Szrj Absolute_expression(Expression* arg)
844*a9fa9459Szrj : Unary_expression(arg)
845*a9fa9459Szrj { }
846*a9fa9459Szrj
847*a9fa9459Szrj uint64_t
value(const Expression_eval_info * eei)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
print(FILE * f) const858*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*
script_exp_function_absolute(Expression * arg)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:
Align_expression(Expression * left,Expression * right)877*a9fa9459Szrj Align_expression(Expression* left, Expression* right)
878*a9fa9459Szrj : Binary_expression(left, right)
879*a9fa9459Szrj { }
880*a9fa9459Szrj
881*a9fa9459Szrj uint64_t
value(const Expression_eval_info * eei)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
print(FILE * f) const906*a9fa9459Szrj print(FILE* f) const
907*a9fa9459Szrj { this->print_function(f, "ALIGN"); }
908*a9fa9459Szrj };
909*a9fa9459Szrj
910*a9fa9459Szrj extern "C" Expression*
script_exp_function_align(Expression * left,Expression * right)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:
Assert_expression(Expression * arg,const char * message,size_t length)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
value(const Expression_eval_info * eei)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
print(FILE * f) const935*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*
script_exp_function_assert(Expression * expr,const char * message,size_t length)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:
Addr_expression(const char * section_name,size_t section_name_len)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
value_from_output_section(const Expression_eval_info * eei,Output_section * os)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
value_from_script_output_section(uint64_t address,uint64_t,uint64_t,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*
function_name() const981*a9fa9459Szrj function_name() const
982*a9fa9459Szrj { return "ADDR"; }
983*a9fa9459Szrj };
984*a9fa9459Szrj
985*a9fa9459Szrj extern "C" Expression*
script_exp_function_addr(const char * section_name,size_t section_name_len)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:
Alignof_expression(const char * section_name,size_t section_name_len)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
value_from_output_section(const Expression_eval_info *,Output_section * os)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
value_from_script_output_section(uint64_t,uint64_t,uint64_t addralign,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*
function_name() const1012*a9fa9459Szrj function_name() const
1013*a9fa9459Szrj { return "ALIGNOF"; }
1014*a9fa9459Szrj };
1015*a9fa9459Szrj
1016*a9fa9459Szrj extern "C" Expression*
script_exp_function_alignof(const char * section_name,size_t section_name_len)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
Constant_expression(const char * name,size_t length)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
value(const Expression_eval_info *)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
print(FILE * f) const1076*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*
script_exp_function_constant(const char * name,size_t length)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*
script_exp_function_data_segment_align(Expression * left,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*
script_exp_function_data_segment_relro_end(Expression *,Expression * right)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*
script_exp_function_data_segment_end(Expression * val)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:
Defined_expression(const char * symbol_name,size_t symbol_name_len)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
value(const Expression_eval_info * eei)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
print(FILE * f) const1145*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*
script_exp_function_defined(const char * symbol_name,size_t symbol_name_len)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:
Loadaddr_expression(const char * section_name,size_t section_name_len)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
value_from_output_section(const Expression_eval_info * eei,Output_section * os)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
value_from_script_output_section(uint64_t,uint64_t load_address,uint64_t,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*
function_name() const1188*a9fa9459Szrj function_name() const
1189*a9fa9459Szrj { return "LOADADDR"; }
1190*a9fa9459Szrj };
1191*a9fa9459Szrj
1192*a9fa9459Szrj extern "C" Expression*
script_exp_function_loadaddr(const char * section_name,size_t section_name_len)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:
Sizeof_expression(const char * section_name,size_t section_name_len)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
value_from_output_section(const Expression_eval_info *,Output_section * os)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
value_from_script_output_section(uint64_t,uint64_t,uint64_t,uint64_t size)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*
function_name() const1225*a9fa9459Szrj function_name() const
1226*a9fa9459Szrj { return "SIZEOF"; }
1227*a9fa9459Szrj };
1228*a9fa9459Szrj
1229*a9fa9459Szrj extern "C" Expression*
script_exp_function_sizeof(const char * section_name,size_t section_name_len)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:
Sizeof_headers_expression()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
print(FILE * f) const1247*a9fa9459Szrj print(FILE* f) const
1248*a9fa9459Szrj { fprintf(f, "SIZEOF_HEADERS"); }
1249*a9fa9459Szrj };
1250*a9fa9459Szrj
1251*a9fa9459Szrj uint64_t
value(const Expression_eval_info * eei)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*
script_exp_function_sizeof_headers()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:
Segment_start_expression(const char * segment_name,size_t segment_name_len,Expression * default_value)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
print(FILE * f) const1293*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
value(const Expression_eval_info * eei)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*
script_exp_function_segment_start(const char * segment_name,size_t segment_name_len,Expression * default_value)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