1 // expression.cc -- expressions in linker scripts for gold
3 // Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
4 // Written by Ian Lance Taylor <iant@google.com>.
6 // This file is part of gold.
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 // MA 02110-1301, USA.
27 #include "parameters.h"
37 // This file holds the code which handles linker expressions.
39 // The dot symbol, which linker scripts refer to simply as ".",
40 // requires special treatment. The dot symbol is set several times,
41 // section addresses will refer to it, output sections will change it,
42 // and it can be set based on the value of other symbols. We simplify
43 // the handling by prohibiting setting the dot symbol to the value of
44 // a non-absolute symbol.
46 // When evaluating the value of an expression, we pass in a pointer to
47 // this struct, so that the expression evaluation can find the
48 // information it needs.
50 struct Expression::Expression_eval_info
53 const Symbol_table
* symtab
;
54 // The layout--we use this to get section information.
56 // Whether expressions can refer to the dot symbol. The dot symbol
57 // is only available within a SECTIONS clause.
58 bool is_dot_available
;
59 // Whether the dot symbol currently has a value.
61 // The current value of the dot symbol.
63 // Points to the IS_ABSOLUTE variable, which is set to false if the
64 // expression uses a value which is not absolute.
68 // Evaluate an expression.
71 Expression::eval(const Symbol_table
* symtab
, const Layout
* layout
)
74 return this->eval_maybe_dot(symtab
, layout
, false, false, 0, &dummy
);
77 // Evaluate an expression which may refer to the dot symbol.
80 Expression::eval_with_dot(const Symbol_table
* symtab
, const Layout
* layout
,
81 bool dot_has_value
, uint64_t dot_value
,
84 return this->eval_maybe_dot(symtab
, layout
, true, dot_has_value
, dot_value
,
88 // Evaluate an expression which may or may not refer to the dot
92 Expression::eval_maybe_dot(const Symbol_table
* symtab
, const Layout
* layout
,
93 bool is_dot_available
, bool dot_has_value
,
94 uint64_t dot_value
, bool* is_absolute
)
96 Expression_eval_info eei
;
99 eei
.is_dot_available
= is_dot_available
;
100 eei
.dot_has_value
= dot_has_value
;
101 eei
.dot_value
= dot_value
;
103 // We assume the value is absolute, and only set this to false if we
104 // find a section relative reference.
106 eei
.is_absolute
= is_absolute
;
108 return this->value(&eei
);
113 class Integer_expression
: public Expression
116 Integer_expression(uint64_t val
)
121 value(const Expression_eval_info
*)
122 { return this->val_
; }
126 { fprintf(f
, "0x%llx", static_cast<unsigned long long>(this->val_
)); }
132 extern "C" Expression
*
133 script_exp_integer(uint64_t val
)
135 return new Integer_expression(val
);
138 // An expression whose value is the value of a symbol.
140 class Symbol_expression
: public Expression
143 Symbol_expression(const char* name
, size_t length
)
144 : name_(name
, length
)
148 value(const Expression_eval_info
*);
152 { fprintf(f
, "%s", this->name_
.c_str()); }
159 Symbol_expression::value(const Expression_eval_info
* eei
)
161 Symbol
* sym
= eei
->symtab
->lookup(this->name_
.c_str());
162 if (sym
== NULL
|| !sym
->is_defined())
164 gold_error(_("undefined symbol '%s' referenced in expression"),
165 this->name_
.c_str());
169 // If this symbol does not have an absolute value, then the whole
170 // expression does not have an absolute value. This is not strictly
171 // accurate: the subtraction of two symbols in the same section is
172 // absolute. This is unlikely to matter in practice, as this value
173 // is only used for error checking.
174 if (!sym
->value_is_absolute())
175 *eei
->is_absolute
= false;
177 if (parameters
->get_size() == 32)
178 return eei
->symtab
->get_sized_symbol
<32>(sym
)->value();
179 else if (parameters
->get_size() == 64)
180 return eei
->symtab
->get_sized_symbol
<64>(sym
)->value();
185 // An expression whose value is the value of the special symbol ".".
186 // This is only valid within a SECTIONS clause.
188 class Dot_expression
: public Expression
195 value(const Expression_eval_info
*);
203 Dot_expression::value(const Expression_eval_info
* eei
)
205 if (!eei
->is_dot_available
)
207 gold_error(_("invalid reference to dot symbol outside of "
211 else if (!eei
->dot_has_value
)
213 gold_error(_("invalid reference to dot symbol before "
214 "it has been given a value"));
217 return eei
->dot_value
;
220 // A string. This is either the name of a symbol, or ".".
222 extern "C" Expression
*
223 script_exp_string(const char* name
, size_t length
)
225 if (length
== 1 && name
[0] == '.')
226 return new Dot_expression();
228 return new Symbol_expression(name
, length
);
231 // A unary expression.
233 class Unary_expression
: public Expression
236 Unary_expression(Expression
* arg
)
241 { delete this->arg_
; }
245 arg_value(const Expression_eval_info
* eei
) const
246 { return this->arg_
->value(eei
); }
249 arg_print(FILE* f
) const
250 { this->arg_
->print(f
); }
256 // Handle unary operators. We use a preprocessor macro as a hack to
257 // capture the C operator.
259 #define UNARY_EXPRESSION(NAME, OPERATOR) \
260 class Unary_ ## NAME : public Unary_expression \
263 Unary_ ## NAME(Expression* arg) \
264 : Unary_expression(arg) \
268 value(const Expression_eval_info* eei) \
269 { return OPERATOR this->arg_value(eei); } \
272 print(FILE* f) const \
274 fprintf(f, "(%s ", #OPERATOR); \
275 this->arg_print(f); \
280 extern "C" Expression* \
281 script_exp_unary_ ## NAME(Expression* arg) \
283 return new Unary_ ## NAME(arg); \
286 UNARY_EXPRESSION(minus
, -)
287 UNARY_EXPRESSION(logical_not
, !)
288 UNARY_EXPRESSION(bitwise_not
, ~)
290 // A binary expression.
292 class Binary_expression
: public Expression
295 Binary_expression(Expression
* left
, Expression
* right
)
296 : left_(left
), right_(right
)
307 left_value(const Expression_eval_info
* eei
) const
308 { return this->left_
->value(eei
); }
311 right_value(const Expression_eval_info
* eei
) const
312 { return this->right_
->value(eei
); }
315 left_print(FILE* f
) const
316 { this->left_
->print(f
); }
319 right_print(FILE* f
) const
320 { this->right_
->print(f
); }
322 // This is a call to function FUNCTION_NAME. Print it. This is for
325 print_function(FILE* f
, const char *function_name
) const
327 fprintf(f
, "%s(", function_name
);
330 this->right_print(f
);
339 // Handle binary operators. We use a preprocessor macro as a hack to
340 // capture the C operator.
342 #define BINARY_EXPRESSION(NAME, OPERATOR) \
343 class Binary_ ## NAME : public Binary_expression \
346 Binary_ ## NAME(Expression* left, Expression* right) \
347 : Binary_expression(left, right) \
351 value(const Expression_eval_info* eei) \
353 return (this->left_value(eei) \
354 OPERATOR this->right_value(eei)); \
358 print(FILE* f) const \
361 this->left_print(f); \
362 fprintf(f, " %s ", #OPERATOR); \
363 this->right_print(f); \
368 extern "C" Expression* \
369 script_exp_binary_ ## NAME(Expression* left, Expression* right) \
371 return new Binary_ ## NAME(left, right); \
374 BINARY_EXPRESSION(mult
, *)
375 BINARY_EXPRESSION(div
, /)
376 BINARY_EXPRESSION(mod
, %)
377 BINARY_EXPRESSION(add
, +)
378 BINARY_EXPRESSION(sub
, -)
379 BINARY_EXPRESSION(lshift
, <<)
380 BINARY_EXPRESSION(rshift
, >>)
381 BINARY_EXPRESSION(eq
, ==)
382 BINARY_EXPRESSION(ne
, !=)
383 BINARY_EXPRESSION(le
, <=)
384 BINARY_EXPRESSION(ge
, >=)
385 BINARY_EXPRESSION(lt
, <)
386 BINARY_EXPRESSION(gt
, >)
387 BINARY_EXPRESSION(bitwise_and
, &)
388 BINARY_EXPRESSION(bitwise_xor
, ^)
389 BINARY_EXPRESSION(bitwise_or
, |)
390 BINARY_EXPRESSION(logical_and
, &&)
391 BINARY_EXPRESSION(logical_or
, ||)
393 // A trinary expression.
395 class Trinary_expression
: public Expression
398 Trinary_expression(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
399 : arg1_(arg1
), arg2_(arg2
), arg3_(arg3
)
402 ~Trinary_expression()
411 arg1_value(const Expression_eval_info
* eei
) const
412 { return this->arg1_
->value(eei
); }
415 arg2_value(const Expression_eval_info
* eei
) const
416 { return this->arg2_
->value(eei
); }
419 arg3_value(const Expression_eval_info
* eei
) const
420 { return this->arg3_
->value(eei
); }
423 arg1_print(FILE* f
) const
424 { this->arg1_
->print(f
); }
427 arg2_print(FILE* f
) const
428 { this->arg2_
->print(f
); }
431 arg3_print(FILE* f
) const
432 { this->arg3_
->print(f
); }
440 // The conditional operator.
442 class Trinary_cond
: public Trinary_expression
445 Trinary_cond(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
446 : Trinary_expression(arg1
, arg2
, arg3
)
450 value(const Expression_eval_info
* eei
)
452 return (this->arg1_value(eei
)
453 ? this->arg2_value(eei
)
454 : this->arg3_value(eei
));
470 extern "C" Expression
*
471 script_exp_trinary_cond(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
473 return new Trinary_cond(arg1
, arg2
, arg3
);
478 class Max_expression
: public Binary_expression
481 Max_expression(Expression
* left
, Expression
* right
)
482 : Binary_expression(left
, right
)
486 value(const Expression_eval_info
* eei
)
487 { return std::max(this->left_value(eei
), this->right_value(eei
)); }
491 { this->print_function(f
, "MAX"); }
494 extern "C" Expression
*
495 script_exp_function_max(Expression
* left
, Expression
* right
)
497 return new Max_expression(left
, right
);
502 class Min_expression
: public Binary_expression
505 Min_expression(Expression
* left
, Expression
* right
)
506 : Binary_expression(left
, right
)
510 value(const Expression_eval_info
* eei
)
511 { return std::min(this->left_value(eei
), this->right_value(eei
)); }
515 { this->print_function(f
, "MIN"); }
518 extern "C" Expression
*
519 script_exp_function_min(Expression
* left
, Expression
* right
)
521 return new Min_expression(left
, right
);
526 class Align_expression
: public Binary_expression
529 Align_expression(Expression
* left
, Expression
* right
)
530 : Binary_expression(left
, right
)
534 value(const Expression_eval_info
* eei
)
536 uint64_t align
= this->right_value(eei
);
537 uint64_t value
= this->left_value(eei
);
540 return ((value
+ align
- 1) / align
) * align
;
545 { this->print_function(f
, "ALIGN"); }
548 extern "C" Expression
*
549 script_exp_function_align(Expression
* left
, Expression
* right
)
551 return new Align_expression(left
, right
);
556 class Assert_expression
: public Unary_expression
559 Assert_expression(Expression
* arg
, const char* message
, size_t length
)
560 : Unary_expression(arg
), message_(message
, length
)
564 value(const Expression_eval_info
* eei
)
566 uint64_t value
= this->arg_value(eei
);
568 gold_error("%s", this->message_
.c_str());
575 fprintf(f
, "ASSERT(");
577 fprintf(f
, ", %s)", this->message_
.c_str());
581 std::string message_
;
584 extern "C" Expression
*
585 script_exp_function_assert(Expression
* expr
, const char* message
,
588 return new Assert_expression(expr
, message
, length
);
593 class Addr_expression
: public Expression
596 Addr_expression(const char* section_name
, size_t section_name_len
)
597 : section_name_(section_name
, section_name_len
)
601 value(const Expression_eval_info
*);
605 { fprintf(f
, "ADDR(%s)", this->section_name_
.c_str()); }
608 std::string section_name_
;
612 Addr_expression::value(const Expression_eval_info
* eei
)
614 const char* section_name
= this->section_name_
.c_str();
615 Output_section
* os
= eei
->layout
->find_output_section(section_name
);
618 gold_error("ADDR called on nonexistent output section '%s'",
623 // Note that the address of a section is an absolute address, and we
624 // should not clear *EEI->IS_ABSOLUTE here.
626 return os
->address();
629 extern "C" Expression
*
630 script_exp_function_addr(const char* section_name
, size_t section_name_len
)
632 return new Addr_expression(section_name
, section_name_len
);
637 extern "C" Expression
*
638 script_exp_function_defined(const char*, size_t)
640 gold_fatal(_("DEFINED not implemented"));
643 extern "C" Expression
*
644 script_exp_function_sizeof_headers()
646 gold_fatal(_("SIZEOF_HEADERS not implemented"));
649 extern "C" Expression
*
650 script_exp_function_alignof(const char*, size_t)
652 gold_fatal(_("ALIGNOF not implemented"));
655 extern "C" Expression
*
656 script_exp_function_sizeof(const char*, size_t)
658 gold_fatal(_("SIZEOF not implemented"));
661 extern "C" Expression
*
662 script_exp_function_loadaddr(const char*, size_t)
664 gold_fatal(_("LOADADDR not implemented"));
667 extern "C" Expression
*
668 script_exp_function_origin(const char*, size_t)
670 gold_fatal(_("ORIGIN not implemented"));
673 extern "C" Expression
*
674 script_exp_function_length(const char*, size_t)
676 gold_fatal(_("LENGTH not implemented"));
679 extern "C" Expression
*
680 script_exp_function_constant(const char*, size_t)
682 gold_fatal(_("CONSTANT not implemented"));
685 extern "C" Expression
*
686 script_exp_function_absolute(Expression
*)
688 gold_fatal(_("ABSOLUTE not implemented"));
691 extern "C" Expression
*
692 script_exp_function_data_segment_align(Expression
*, Expression
*)
694 gold_fatal(_("DATA_SEGMENT_ALIGN not implemented"));
697 extern "C" Expression
*
698 script_exp_function_data_segment_relro_end(Expression
*, Expression
*)
700 gold_fatal(_("DATA_SEGMENT_RELRO_END not implemented"));
703 extern "C" Expression
*
704 script_exp_function_data_segment_end(Expression
*)
706 gold_fatal(_("DATA_SEGMENT_END not implemented"));
709 extern "C" Expression
*
710 script_exp_function_segment_start(const char*, size_t, Expression
*)
712 gold_fatal(_("SEGMENT_START not implemented"));
715 } // End namespace gold.
This page took 0.045281 seconds and 5 git commands to generate.