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 // When evaluating the value of an expression, we pass in a pointer to
40 // this struct, so that the expression evaluation can find the
41 // information it needs.
43 struct Expression::Expression_eval_info
45 const Symbol_table
* symtab
;
49 // Evaluate an expression.
52 Expression::eval(const Symbol_table
* symtab
, const Layout
* layout
)
54 Expression_eval_info eei
;
57 return this->value(&eei
);
62 class Integer_expression
: public Expression
65 Integer_expression(uint64_t val
)
70 value(const Expression_eval_info
*)
71 { return this->val_
; }
75 { fprintf(f
, "0x%llx", static_cast<unsigned long long>(this->val_
)); }
81 extern "C" Expression
*
82 script_exp_integer(uint64_t val
)
84 return new Integer_expression(val
);
87 // An expression whose value is the value of a symbol.
89 class Symbol_expression
: public Expression
92 Symbol_expression(const char* name
, size_t length
)
97 value(const Expression_eval_info
*);
101 { fprintf(f
, "%s", this->name_
.c_str()); }
108 Symbol_expression::value(const Expression_eval_info
* eei
)
110 Symbol
* sym
= eei
->symtab
->lookup(this->name_
.c_str());
111 if (sym
== NULL
|| !sym
->is_defined())
113 gold_error(_("undefined symbol '%s' referenced in expression"),
114 this->name_
.c_str());
118 if (parameters
->get_size() == 32)
119 return eei
->symtab
->get_sized_symbol
<32>(sym
)->value();
120 else if (parameters
->get_size() == 64)
121 return eei
->symtab
->get_sized_symbol
<64>(sym
)->value();
126 // An expression whose value is the value of the special symbol ".".
127 // This is only valid within a SECTIONS clause.
129 class Dot_expression
: public Expression
136 value(const Expression_eval_info
*);
144 Dot_expression::value(const Expression_eval_info
*)
146 gold_error("dot symbol unimplemented");
150 // A string. This is either the name of a symbol, or ".".
152 extern "C" Expression
*
153 script_exp_string(const char* name
, size_t length
)
155 if (length
== 1 && name
[0] == '.')
156 return new Dot_expression();
158 return new Symbol_expression(name
, length
);
161 // A unary expression.
163 class Unary_expression
: public Expression
166 Unary_expression(Expression
* arg
)
171 { delete this->arg_
; }
175 arg_value(const Expression_eval_info
* eei
) const
176 { return this->arg_
->value(eei
); }
179 arg_print(FILE* f
) const
180 { this->arg_
->print(f
); }
186 // Handle unary operators. We use a preprocessor macro as a hack to
187 // capture the C operator.
189 #define UNARY_EXPRESSION(NAME, OPERATOR) \
190 class Unary_ ## NAME : public Unary_expression \
193 Unary_ ## NAME(Expression* arg) \
194 : Unary_expression(arg) \
198 value(const Expression_eval_info* eei) \
199 { return OPERATOR this->arg_value(eei); } \
202 print(FILE* f) const \
204 fprintf(f, "(%s ", #OPERATOR); \
205 this->arg_print(f); \
210 extern "C" Expression* \
211 script_exp_unary_ ## NAME(Expression* arg) \
213 return new Unary_ ## NAME(arg); \
216 UNARY_EXPRESSION(minus
, -)
217 UNARY_EXPRESSION(logical_not
, !)
218 UNARY_EXPRESSION(bitwise_not
, ~)
220 // A binary expression.
222 class Binary_expression
: public Expression
225 Binary_expression(Expression
* left
, Expression
* right
)
226 : left_(left
), right_(right
)
237 left_value(const Expression_eval_info
* eei
) const
238 { return this->left_
->value(eei
); }
241 right_value(const Expression_eval_info
* eei
) const
242 { return this->right_
->value(eei
); }
245 left_print(FILE* f
) const
246 { this->left_
->print(f
); }
249 right_print(FILE* f
) const
250 { this->right_
->print(f
); }
252 // This is a call to function FUNCTION_NAME. Print it. This is for
255 print_function(FILE* f
, const char *function_name
) const
257 fprintf(f
, "%s(", function_name
);
260 this->right_print(f
);
269 // Handle binary operators. We use a preprocessor macro as a hack to
270 // capture the C operator.
272 #define BINARY_EXPRESSION(NAME, OPERATOR) \
273 class Binary_ ## NAME : public Binary_expression \
276 Binary_ ## NAME(Expression* left, Expression* right) \
277 : Binary_expression(left, right) \
281 value(const Expression_eval_info* eei) \
283 return (this->left_value(eei) \
284 OPERATOR this->right_value(eei)); \
288 print(FILE* f) const \
291 this->left_print(f); \
292 fprintf(f, " %s ", #OPERATOR); \
293 this->right_print(f); \
298 extern "C" Expression* \
299 script_exp_binary_ ## NAME(Expression* left, Expression* right) \
301 return new Binary_ ## NAME(left, right); \
304 BINARY_EXPRESSION(mult
, *)
305 BINARY_EXPRESSION(div
, /)
306 BINARY_EXPRESSION(mod
, %)
307 BINARY_EXPRESSION(add
, +)
308 BINARY_EXPRESSION(sub
, -)
309 BINARY_EXPRESSION(lshift
, <<)
310 BINARY_EXPRESSION(rshift
, >>)
311 BINARY_EXPRESSION(eq
, ==)
312 BINARY_EXPRESSION(ne
, !=)
313 BINARY_EXPRESSION(le
, <=)
314 BINARY_EXPRESSION(ge
, >=)
315 BINARY_EXPRESSION(lt
, <)
316 BINARY_EXPRESSION(gt
, >)
317 BINARY_EXPRESSION(bitwise_and
, &)
318 BINARY_EXPRESSION(bitwise_xor
, ^)
319 BINARY_EXPRESSION(bitwise_or
, |)
320 BINARY_EXPRESSION(logical_and
, &&)
321 BINARY_EXPRESSION(logical_or
, ||)
323 // A trinary expression.
325 class Trinary_expression
: public Expression
328 Trinary_expression(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
329 : arg1_(arg1
), arg2_(arg2
), arg3_(arg3
)
332 ~Trinary_expression()
341 arg1_value(const Expression_eval_info
* eei
) const
342 { return this->arg1_
->value(eei
); }
345 arg2_value(const Expression_eval_info
* eei
) const
346 { return this->arg2_
->value(eei
); }
349 arg3_value(const Expression_eval_info
* eei
) const
350 { return this->arg3_
->value(eei
); }
353 arg1_print(FILE* f
) const
354 { this->arg1_
->print(f
); }
357 arg2_print(FILE* f
) const
358 { this->arg2_
->print(f
); }
361 arg3_print(FILE* f
) const
362 { this->arg3_
->print(f
); }
370 // The conditional operator.
372 class Trinary_cond
: public Trinary_expression
375 Trinary_cond(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
376 : Trinary_expression(arg1
, arg2
, arg3
)
380 value(const Expression_eval_info
* eei
)
382 return (this->arg1_value(eei
)
383 ? this->arg2_value(eei
)
384 : this->arg3_value(eei
));
400 extern "C" Expression
*
401 script_exp_trinary_cond(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
403 return new Trinary_cond(arg1
, arg2
, arg3
);
408 class Max_expression
: public Binary_expression
411 Max_expression(Expression
* left
, Expression
* right
)
412 : Binary_expression(left
, right
)
416 value(const Expression_eval_info
* eei
)
417 { return std::max(this->left_value(eei
), this->right_value(eei
)); }
421 { this->print_function(f
, "MAX"); }
424 extern "C" Expression
*
425 script_exp_function_max(Expression
* left
, Expression
* right
)
427 return new Max_expression(left
, right
);
432 class Min_expression
: public Binary_expression
435 Min_expression(Expression
* left
, Expression
* right
)
436 : Binary_expression(left
, right
)
440 value(const Expression_eval_info
* eei
)
441 { return std::min(this->left_value(eei
), this->right_value(eei
)); }
445 { this->print_function(f
, "MIN"); }
448 extern "C" Expression
*
449 script_exp_function_min(Expression
* left
, Expression
* right
)
451 return new Min_expression(left
, right
);
456 class Align_expression
: public Binary_expression
459 Align_expression(Expression
* left
, Expression
* right
)
460 : Binary_expression(left
, right
)
464 value(const Expression_eval_info
* eei
)
466 uint64_t align
= this->right_value(eei
);
467 uint64_t value
= this->left_value(eei
);
470 return ((value
+ align
- 1) / align
) * align
;
475 { this->print_function(f
, "ALIGN"); }
478 extern "C" Expression
*
479 script_exp_function_align(Expression
* left
, Expression
* right
)
481 return new Align_expression(left
, right
);
486 class Assert_expression
: public Unary_expression
489 Assert_expression(Expression
* arg
, const char* message
, size_t length
)
490 : Unary_expression(arg
), message_(message
, length
)
494 value(const Expression_eval_info
* eei
)
496 uint64_t value
= this->arg_value(eei
);
498 gold_error("%s", this->message_
.c_str());
505 fprintf(f
, "ASSERT(");
507 fprintf(f
, ", %s)", this->message_
.c_str());
511 std::string message_
;
514 extern "C" Expression
*
515 script_exp_function_assert(Expression
* expr
, const char* message
,
518 return new Assert_expression(expr
, message
, length
);
523 class Addr_expression
: public Expression
526 Addr_expression(const char* section_name
, size_t section_name_len
)
527 : section_name_(section_name
, section_name_len
)
531 value(const Expression_eval_info
*);
535 { fprintf(f
, "ADDR(%s)", this->section_name_
.c_str()); }
538 std::string section_name_
;
542 Addr_expression::value(const Expression_eval_info
* eei
)
544 const char* section_name
= this->section_name_
.c_str();
545 Output_section
* os
= eei
->layout
->find_output_section(section_name
);
548 gold_error("ADDR called on nonexistent output section '%s'",
552 return os
->address();
555 extern "C" Expression
*
556 script_exp_function_addr(const char* section_name
, size_t section_name_len
)
558 return new Addr_expression(section_name
, section_name_len
);
563 extern "C" Expression
*
564 script_exp_function_defined(const char*, size_t)
566 gold_fatal(_("DEFINED not implemented"));
569 extern "C" Expression
*
570 script_exp_function_sizeof_headers()
572 gold_fatal(_("SIZEOF_HEADERS not implemented"));
575 extern "C" Expression
*
576 script_exp_function_alignof(const char*, size_t)
578 gold_fatal(_("ALIGNOF not implemented"));
581 extern "C" Expression
*
582 script_exp_function_sizeof(const char*, size_t)
584 gold_fatal(_("SIZEOF not implemented"));
587 extern "C" Expression
*
588 script_exp_function_loadaddr(const char*, size_t)
590 gold_fatal(_("LOADADDR not implemented"));
593 extern "C" Expression
*
594 script_exp_function_origin(const char*, size_t)
596 gold_fatal(_("ORIGIN not implemented"));
599 extern "C" Expression
*
600 script_exp_function_length(const char*, size_t)
602 gold_fatal(_("LENGTH not implemented"));
605 extern "C" Expression
*
606 script_exp_function_constant(const char*, size_t)
608 gold_fatal(_("CONSTANT not implemented"));
611 extern "C" Expression
*
612 script_exp_function_absolute(Expression
*)
614 gold_fatal(_("ABSOLUTE not implemented"));
617 extern "C" Expression
*
618 script_exp_function_data_segment_align(Expression
*, Expression
*)
620 gold_fatal(_("DATA_SEGMENT_ALIGN not implemented"));
623 extern "C" Expression
*
624 script_exp_function_data_segment_relro_end(Expression
*, Expression
*)
626 gold_fatal(_("DATA_SEGMENT_RELRO_END not implemented"));
629 extern "C" Expression
*
630 script_exp_function_data_segment_end(Expression
*)
632 gold_fatal(_("DATA_SEGMENT_END not implemented"));
635 extern "C" Expression
*
636 script_exp_function_segment_start(const char*, size_t, Expression
*)
638 gold_fatal(_("SEGMENT_START not implemented"));
641 } // End namespace gold.
This page took 0.062875 seconds and 5 git commands to generate.