Support assignments and expressions in linker scripts.
[deliverable/binutils-gdb.git] / gold / expression.cc
CommitLineData
e5756efb
ILT
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
33namespace 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
42struct Expression::Expression_eval_info
43{
44 const Symbol_table* symtab;
45 const Layout* layout;
46};
47
48// Evaluate an expression.
49
50uint64_t
51Expression::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
61class 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
76extern "C" Expression*
77script_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
84class 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
98uint64_t
99Symbol_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
120class Dot_expression : public Expression
121{
122 public:
123 Dot_expression()
124 { }
125
126 uint64_t
127 value(const Expression_eval_info*);
128};
129
130uint64_t
131Dot_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
139extern "C" Expression*
140script_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
150class 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
191UNARY_EXPRESSION(minus, -)
192UNARY_EXPRESSION(logical_not, !)
193UNARY_EXPRESSION(bitwise_not, ~)
194
195// A binary expression.
196
197class 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
249BINARY_EXPRESSION(mult, *)
250BINARY_EXPRESSION(div, /)
251BINARY_EXPRESSION(mod, %)
252BINARY_EXPRESSION(add, +)
253BINARY_EXPRESSION(sub, -)
254BINARY_EXPRESSION(lshift, <<)
255BINARY_EXPRESSION(rshift, >>)
256BINARY_EXPRESSION(eq, ==)
257BINARY_EXPRESSION(ne, !=)
258BINARY_EXPRESSION(le, <=)
259BINARY_EXPRESSION(ge, >=)
260BINARY_EXPRESSION(lt, <)
261BINARY_EXPRESSION(gt, >)
262BINARY_EXPRESSION(bitwise_and, &)
263BINARY_EXPRESSION(bitwise_xor, ^)
264BINARY_EXPRESSION(bitwise_or, |)
265BINARY_EXPRESSION(logical_and, &&)
266BINARY_EXPRESSION(logical_or, ||)
267
268// A trinary expression.
269
270class 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
305class 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
321extern "C" Expression*
322script_exp_trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
323{
324 return new Trinary_cond(arg1, arg2, arg3);
325}
326
327// Max function.
328
329class 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
341extern "C" Expression*
342script_exp_function_max(Expression* left, Expression* right)
343{
344 return new Max_expression(left, right);
345}
346
347// Min function.
348
349class 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
361extern "C" Expression*
362script_exp_function_min(Expression* left, Expression* right)
363{
364 return new Min_expression(left, right);
365}
366
367// Align function.
368
369class 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
387extern "C" Expression*
388script_exp_function_align(Expression* left, Expression* right)
389{
390 return new Align_expression(left, right);
391}
392
393// Assert function.
394
395class 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
415extern "C" Expression*
416script_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
424extern "C" Expression*
425script_exp_function_defined(const char*, size_t)
426{
427 gold_fatal(_("DEFINED not implemented"));
428}
429
430extern "C" Expression*
431script_exp_function_sizeof_headers()
432{
433 gold_fatal(_("SIZEOF_HEADERS not implemented"));
434}
435
436extern "C" Expression*
437script_exp_function_alignof(const char*, size_t)
438{
439 gold_fatal(_("ALIGNOF not implemented"));
440}
441
442extern "C" Expression*
443script_exp_function_sizeof(const char*, size_t)
444{
445 gold_fatal(_("SIZEOF not implemented"));
446}
447
448extern "C" Expression*
449script_exp_function_addr(const char*, size_t)
450{
451 gold_fatal(_("ADDR not implemented"));
452}
453
454extern "C" Expression*
455script_exp_function_loadaddr(const char*, size_t)
456{
457 gold_fatal(_("LOADADDR not implemented"));
458}
459
460extern "C" Expression*
461script_exp_function_origin(const char*, size_t)
462{
463 gold_fatal(_("ORIGIN not implemented"));
464}
465
466extern "C" Expression*
467script_exp_function_length(const char*, size_t)
468{
469 gold_fatal(_("LENGTH not implemented"));
470}
471
472extern "C" Expression*
473script_exp_function_constant(const char*, size_t)
474{
475 gold_fatal(_("CONSTANT not implemented"));
476}
477
478extern "C" Expression*
479script_exp_function_absolute(Expression*)
480{
481 gold_fatal(_("ABSOLUTE not implemented"));
482}
483
484extern "C" Expression*
485script_exp_function_data_segment_align(Expression*, Expression*)
486{
487 gold_fatal(_("DATA_SEGMENT_ALIGN not implemented"));
488}
489
490extern "C" Expression*
491script_exp_function_data_segment_relro_end(Expression*, Expression*)
492{
493 gold_fatal(_("DATA_SEGMENT_RELRO_END not implemented"));
494}
495
496extern "C" Expression*
497script_exp_function_data_segment_end(Expression*)
498{
499 gold_fatal(_("DATA_SEGMENT_END not implemented"));
500}
501
502extern "C" Expression*
503script_exp_function_segment_start(const char*, size_t, Expression*)
504{
505 gold_fatal(_("SEGMENT_START not implemented"));
506}
507
508} // End namespace gold.
This page took 0.045157 seconds and 4 git commands to generate.