Support assignments and expressions in linker scripts.
[external/binutils.git] / gold / expression.cc
1 // expression.cc -- expressions in linker scripts for gold
2
3 // Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
4 // Written by Ian Lance Taylor <iant@google.com>.
5
6 // This file is part of gold.
7
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.
12
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.
17
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.
22
23 #include "gold.h"
24
25 #include <string>
26
27 #include "parameters.h"
28 #include "symtab.h"
29 #include "layout.h"
30 #include "script.h"
31 #include "script-c.h"
32
33 namespace gold
34 {
35
36 // This file holds the code which handles linker expressions.
37
38 // When evaluating the value of an expression, we pass in a pointer to
39 // this struct, so that the expression evaluation can find the
40 // information it needs.
41
42 struct Expression::Expression_eval_info
43 {
44   const Symbol_table* symtab;
45   const Layout* layout;
46 };
47
48 // Evaluate an expression.
49
50 uint64_t
51 Expression::eval(const Symbol_table* symtab, const Layout* layout)
52 {
53   Expression_eval_info eei;
54   eei.symtab = symtab;
55   eei.layout = layout;
56   return this->value(&eei);
57 }
58
59 // A number.
60
61 class Integer_expression : public Expression
62 {
63  public:
64   Integer_expression(uint64_t val)
65     : val_(val)
66   { }
67
68   uint64_t
69   value(const Expression_eval_info*)
70   { return this->val_; }
71
72  private:
73   uint64_t val_;
74 };
75
76 extern "C" Expression*
77 script_exp_integer(uint64_t val)
78 {
79   return new Integer_expression(val);
80 }
81
82 // An expression whose value is the value of a symbol.
83
84 class Symbol_expression : public Expression
85 {
86  public:
87   Symbol_expression(const char* name, size_t length)
88     : name_(name, length)
89   { }
90
91   uint64_t
92   value(const Expression_eval_info*);
93
94  private:
95   std::string name_;
96 };
97
98 uint64_t
99 Symbol_expression::value(const Expression_eval_info* eei)
100 {
101   Symbol* sym = eei->symtab->lookup(this->name_.c_str());
102   if (sym == NULL || !sym->is_defined())
103     {
104       gold_error(_("undefined symbol '%s' referenced in expression"),
105                  this->name_.c_str());
106       return 0;
107     }
108
109   if (parameters->get_size() == 32)
110     return eei->symtab->get_sized_symbol<32>(sym)->value();
111   else if (parameters->get_size() == 64)
112     return eei->symtab->get_sized_symbol<64>(sym)->value();
113   else
114     gold_unreachable();
115 }
116
117 // An expression whose value is the value of the special symbol ".".
118 // This is only valid within a SECTIONS clause.
119
120 class Dot_expression : public Expression
121 {
122  public:
123   Dot_expression()
124   { }
125
126   uint64_t
127   value(const Expression_eval_info*);
128 };
129
130 uint64_t
131 Dot_expression::value(const Expression_eval_info*)
132 {
133   gold_error("dot symbol unimplemented");
134   return 0;
135 }
136
137 // A string.  This is either the name of a symbol, or ".".
138
139 extern "C" Expression*
140 script_exp_string(const char* name, size_t length)
141 {
142   if (length == 1 && name[0] == '.')
143     return new Dot_expression();
144   else
145     return new Symbol_expression(name, length);
146 }
147
148 // A unary expression.
149
150 class Unary_expression : public Expression
151 {
152  public:
153   Unary_expression(Expression* arg)
154     : arg_(arg)
155   { }
156
157   ~Unary_expression()
158   { delete this->arg_; }
159
160  protected:
161   uint64_t
162   arg_value(const Expression_eval_info* eei) const
163   { return this->arg_->value(eei); }
164
165  private:
166   Expression* arg_;
167 };
168
169 // Handle unary operators.  We use a preprocessor macro as a hack to
170 // capture the C operator.
171
172 #define UNARY_EXPRESSION(NAME, OPERATOR)                        \
173   class Unary_ ## NAME : public Unary_expression                \
174   {                                                             \
175    public:                                                      \
176     Unary_ ## NAME(Expression* arg)                             \
177       : Unary_expression(arg)                                   \
178     { }                                                         \
179                                                                 \
180     uint64_t                                                    \
181     value(const Expression_eval_info* eei)                      \
182     { return OPERATOR this->arg_value(eei); }                   \
183   };                                                            \
184                                                                 \
185   extern "C" Expression*                                        \
186   script_exp_unary_ ## NAME(Expression* arg)                    \
187   {                                                             \
188     return new Unary_ ## NAME(arg);                             \
189   }
190
191 UNARY_EXPRESSION(minus, -)
192 UNARY_EXPRESSION(logical_not, !)
193 UNARY_EXPRESSION(bitwise_not, ~)
194
195 // A binary expression.
196
197 class Binary_expression : public Expression
198 {
199  public:
200   Binary_expression(Expression* left, Expression* right)
201     : left_(left), right_(right)
202   { }
203
204   ~Binary_expression()
205   {
206     delete this->left_;
207     delete this->right_;
208   }
209
210  protected:
211   uint64_t
212   left_value(const Expression_eval_info* eei) const
213   { return this->left_->value(eei); }
214
215   uint64_t
216   right_value(const Expression_eval_info* eei) const
217   { return this->right_->value(eei); }
218
219  private:
220   Expression* left_;
221   Expression* right_;
222 };
223
224 // Handle binary operators.  We use a preprocessor macro as a hack to
225 // capture the C operator.
226
227 #define BINARY_EXPRESSION(NAME, OPERATOR)                               \
228   class Binary_ ## NAME : public Binary_expression                      \
229   {                                                                     \
230   public:                                                               \
231     Binary_ ## NAME(Expression* left, Expression* right)                \
232       : Binary_expression(left, right)                                  \
233     { }                                                                 \
234                                                                         \
235     uint64_t                                                            \
236     value(const Expression_eval_info* eei)                              \
237     {                                                                   \
238       return (this->left_value(eei)                                     \
239               OPERATOR this->right_value(eei));                         \
240     }                                                                   \
241   };                                                                    \
242                                                                         \
243   extern "C" Expression*                                                \
244   script_exp_binary_ ## NAME(Expression* left, Expression* right)       \
245   {                                                                     \
246     return new Binary_ ## NAME(left, right);                            \
247   }
248
249 BINARY_EXPRESSION(mult, *)
250 BINARY_EXPRESSION(div, /)
251 BINARY_EXPRESSION(mod, %)
252 BINARY_EXPRESSION(add, +)
253 BINARY_EXPRESSION(sub, -)
254 BINARY_EXPRESSION(lshift, <<)
255 BINARY_EXPRESSION(rshift, >>)
256 BINARY_EXPRESSION(eq, ==)
257 BINARY_EXPRESSION(ne, !=)
258 BINARY_EXPRESSION(le, <=)
259 BINARY_EXPRESSION(ge, >=)
260 BINARY_EXPRESSION(lt, <)
261 BINARY_EXPRESSION(gt, >)
262 BINARY_EXPRESSION(bitwise_and, &)
263 BINARY_EXPRESSION(bitwise_xor, ^)
264 BINARY_EXPRESSION(bitwise_or, |)
265 BINARY_EXPRESSION(logical_and, &&)
266 BINARY_EXPRESSION(logical_or, ||)
267
268 // A trinary expression.
269
270 class Trinary_expression : public Expression
271 {
272  public:
273   Trinary_expression(Expression* arg1, Expression* arg2, Expression* arg3)
274     : arg1_(arg1), arg2_(arg2), arg3_(arg3)
275   { }
276
277   ~Trinary_expression()
278   {
279     delete this->arg1_;
280     delete this->arg2_;
281     delete this->arg3_;
282   }
283
284  protected:
285   uint64_t
286   arg1_value(const Expression_eval_info* eei) const
287   { return this->arg1_->value(eei); }
288
289   uint64_t
290   arg2_value(const Expression_eval_info* eei) const
291   { return this->arg2_->value(eei); }
292
293   uint64_t
294   arg3_value(const Expression_eval_info* eei) const
295   { return this->arg3_->value(eei); }
296
297  private:
298   Expression* arg1_;
299   Expression* arg2_;
300   Expression* arg3_;
301 };
302
303 // The conditional operator.
304
305 class Trinary_cond : public Trinary_expression
306 {
307  public:
308   Trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
309     : Trinary_expression(arg1, arg2, arg3)
310   { }
311
312   uint64_t
313   value(const Expression_eval_info* eei)
314   {
315     return (this->arg1_value(eei)
316             ? this->arg2_value(eei)
317             : this->arg3_value(eei));
318   }
319 };
320
321 extern "C" Expression*
322 script_exp_trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
323 {
324   return new Trinary_cond(arg1, arg2, arg3);
325 }
326
327 // Max function.
328
329 class Max_expression : public Binary_expression
330 {
331  public:
332   Max_expression(Expression* left, Expression* right)
333     : Binary_expression(left, right)
334   { }
335
336   uint64_t
337   value(const Expression_eval_info* eei)
338   { return std::max(this->left_value(eei), this->right_value(eei)); }
339 };
340
341 extern "C" Expression*
342 script_exp_function_max(Expression* left, Expression* right)
343 {
344   return new Max_expression(left, right);
345 }
346
347 // Min function.
348
349 class Min_expression : public Binary_expression
350 {
351  public:
352   Min_expression(Expression* left, Expression* right)
353     : Binary_expression(left, right)
354   { }
355
356   uint64_t
357   value(const Expression_eval_info* eei)
358   { return std::min(this->left_value(eei), this->right_value(eei)); }
359 };
360
361 extern "C" Expression*
362 script_exp_function_min(Expression* left, Expression* right)
363 {
364   return new Min_expression(left, right);
365 }
366
367 // Align function.
368
369 class Align_expression : public Binary_expression
370 {
371  public:
372   Align_expression(Expression* left, Expression* right)
373     : Binary_expression(left, right)
374   { }
375
376   uint64_t
377   value(const Expression_eval_info* eei)
378   {
379     uint64_t align = this->right_value(eei);
380     uint64_t value = this->left_value(eei);
381     if (align <= 1)
382       return value;
383     return ((value + align - 1) / align) * align;
384   }
385 };
386
387 extern "C" Expression*
388 script_exp_function_align(Expression* left, Expression* right)
389 {
390   return new Align_expression(left, right);
391 }
392
393 // Assert function.
394
395 class Assert_expression : public Unary_expression
396 {
397  public:
398   Assert_expression(Expression* arg, const char* message, size_t length)
399     : Unary_expression(arg), message_(message, length)
400   { }
401
402   uint64_t
403   value(const Expression_eval_info* eei)
404   {
405     uint64_t value = this->arg_value(eei);
406     if (!value)
407       gold_error("%s", this->message_.c_str());
408     return value;
409   }
410
411  private:
412   std::string message_;
413 };
414
415 extern "C" Expression*
416 script_exp_function_assert(Expression* expr, const char* message,
417                            size_t length)
418 {
419   return new Assert_expression(expr, message, length);
420 }
421
422 // Functions.
423
424 extern "C" Expression*
425 script_exp_function_defined(const char*, size_t)
426 {
427   gold_fatal(_("DEFINED not implemented"));
428 }
429
430 extern "C" Expression*
431 script_exp_function_sizeof_headers()
432 {
433   gold_fatal(_("SIZEOF_HEADERS not implemented"));
434 }
435
436 extern "C" Expression*
437 script_exp_function_alignof(const char*, size_t)
438 {
439   gold_fatal(_("ALIGNOF not implemented"));
440 }
441
442 extern "C" Expression*
443 script_exp_function_sizeof(const char*, size_t)
444 {
445   gold_fatal(_("SIZEOF not implemented"));
446 }
447
448 extern "C" Expression*
449 script_exp_function_addr(const char*, size_t)
450 {
451   gold_fatal(_("ADDR not implemented"));
452 }
453
454 extern "C" Expression*
455 script_exp_function_loadaddr(const char*, size_t)
456 {
457   gold_fatal(_("LOADADDR not implemented"));
458 }
459
460 extern "C" Expression*
461 script_exp_function_origin(const char*, size_t)
462 {
463   gold_fatal(_("ORIGIN not implemented"));
464 }
465
466 extern "C" Expression*
467 script_exp_function_length(const char*, size_t)
468 {
469   gold_fatal(_("LENGTH not implemented"));
470 }
471
472 extern "C" Expression*
473 script_exp_function_constant(const char*, size_t)
474 {
475   gold_fatal(_("CONSTANT not implemented"));
476 }
477
478 extern "C" Expression*
479 script_exp_function_absolute(Expression*)
480 {
481   gold_fatal(_("ABSOLUTE not implemented"));
482 }
483
484 extern "C" Expression*
485 script_exp_function_data_segment_align(Expression*, Expression*)
486 {
487   gold_fatal(_("DATA_SEGMENT_ALIGN not implemented"));
488 }
489
490 extern "C" Expression*
491 script_exp_function_data_segment_relro_end(Expression*, Expression*)
492 {
493   gold_fatal(_("DATA_SEGMENT_RELRO_END not implemented"));
494 }
495
496 extern "C" Expression*
497 script_exp_function_data_segment_end(Expression*)
498 {
499   gold_fatal(_("DATA_SEGMENT_END not implemented"));
500 }
501
502 extern "C" Expression*
503 script_exp_function_segment_start(const char*, size_t, Expression*)
504 {
505   gold_fatal(_("SEGMENT_START not implemented"));
506 }
507
508 } // End namespace gold.