OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [expression.cc] - Blame information for rev 166

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 khays
// expression.cc -- expressions in linker scripts for gold
2
 
3 166 khays
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 27 khays
// 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 "elfcpp.h"
28
#include "parameters.h"
29
#include "symtab.h"
30
#include "layout.h"
31
#include "output.h"
32
#include "script.h"
33
#include "script-c.h"
34
 
35
namespace gold
36
{
37
 
38
// This file holds the code which handles linker expressions.
39
 
40
// The dot symbol, which linker scripts refer to simply as ".",
41
// requires special treatment.  The dot symbol is set several times,
42
// section addresses will refer to it, output sections will change it,
43
// and it can be set based on the value of other symbols.  We simplify
44
// the handling by prohibiting setting the dot symbol to the value of
45
// a non-absolute symbol.
46
 
47
// When evaluating the value of an expression, we pass in a pointer to
48
// this struct, so that the expression evaluation can find the
49
// information it needs.
50
 
51
struct Expression::Expression_eval_info
52
{
53
  // The symbol table.
54
  const Symbol_table* symtab;
55
  // The layout--we use this to get section information.
56
  const Layout* layout;
57
  // Whether to check assertions.
58
  bool check_assertions;
59
  // Whether expressions can refer to the dot symbol.  The dot symbol
60
  // is only available within a SECTIONS clause.
61
  bool is_dot_available;
62
  // The current value of the dot symbol.
63
  uint64_t dot_value;
64
  // The section in which the dot symbol is defined; this is NULL if
65
  // it is absolute.
66
  Output_section* dot_section;
67
  // Points to where the section of the result should be stored.
68
  Output_section** result_section_pointer;
69
  // Pointer to where the alignment of the result should be stored.
70
  uint64_t* result_alignment_pointer;
71
};
72
 
73
// Evaluate an expression.
74
 
75
uint64_t
76
Expression::eval(const Symbol_table* symtab, const Layout* layout,
77
                 bool check_assertions)
78
{
79
  return this->eval_maybe_dot(symtab, layout, check_assertions,
80 163 khays
                              false, 0, NULL, NULL, NULL, false);
81 27 khays
}
82
 
83
// Evaluate an expression which may refer to the dot symbol.
84
 
85
uint64_t
86
Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout,
87
                          bool check_assertions, uint64_t dot_value,
88
                          Output_section* dot_section,
89
                          Output_section** result_section_pointer,
90 163 khays
                          uint64_t* result_alignment_pointer,
91
                          bool is_section_dot_assignment)
92 27 khays
{
93
  return this->eval_maybe_dot(symtab, layout, check_assertions, true,
94
                              dot_value, dot_section, result_section_pointer,
95 163 khays
                              result_alignment_pointer,
96
                              is_section_dot_assignment);
97 27 khays
}
98
 
99
// Evaluate an expression which may or may not refer to the dot
100
// symbol.
101
 
102
uint64_t
103
Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
104
                           bool check_assertions, bool is_dot_available,
105
                           uint64_t dot_value, Output_section* dot_section,
106
                           Output_section** result_section_pointer,
107 163 khays
                           uint64_t* result_alignment_pointer,
108
                           bool is_section_dot_assignment)
109 27 khays
{
110
  Expression_eval_info eei;
111
  eei.symtab = symtab;
112
  eei.layout = layout;
113
  eei.check_assertions = check_assertions;
114
  eei.is_dot_available = is_dot_available;
115
  eei.dot_value = dot_value;
116
  eei.dot_section = dot_section;
117
 
118
  // We assume the value is absolute, and only set this to a section
119 163 khays
  // if we find a section-relative reference.
120 27 khays
  if (result_section_pointer != NULL)
121
    *result_section_pointer = NULL;
122
  eei.result_section_pointer = result_section_pointer;
123
 
124
  eei.result_alignment_pointer = result_alignment_pointer;
125
 
126 163 khays
  uint64_t val = this->value(&eei);
127
 
128
  // If this is an assignment to dot within a section, and the value
129
  // is absolute, treat it as a section-relative offset.
130
  if (is_section_dot_assignment && *result_section_pointer == NULL)
131
    {
132
      gold_assert(dot_section != NULL);
133
      val += dot_section->address();
134
      *result_section_pointer = dot_section;
135
    }
136
  return val;
137 27 khays
}
138
 
139
// A number.
140
 
141
class Integer_expression : public Expression
142
{
143
 public:
144
  Integer_expression(uint64_t val)
145
    : val_(val)
146
  { }
147
 
148
  uint64_t
149
  value(const Expression_eval_info*)
150
  { return this->val_; }
151
 
152
  void
153
  print(FILE* f) const
154
  { fprintf(f, "0x%llx", static_cast<unsigned long long>(this->val_)); }
155
 
156
 private:
157
  uint64_t val_;
158
};
159
 
160
extern "C" Expression*
161
script_exp_integer(uint64_t val)
162
{
163
  return new Integer_expression(val);
164
}
165
 
166
// An expression whose value is the value of a symbol.
167
 
168
class Symbol_expression : public Expression
169
{
170
 public:
171
  Symbol_expression(const char* name, size_t length)
172
    : name_(name, length)
173
  { }
174
 
175
  uint64_t
176
  value(const Expression_eval_info*);
177
 
178
  void
179
  print(FILE* f) const
180
  { fprintf(f, "%s", this->name_.c_str()); }
181
 
182
 private:
183
  std::string name_;
184
};
185
 
186
uint64_t
187
Symbol_expression::value(const Expression_eval_info* eei)
188
{
189
  Symbol* sym = eei->symtab->lookup(this->name_.c_str());
190
  if (sym == NULL || !sym->is_defined())
191
    {
192
      gold_error(_("undefined symbol '%s' referenced in expression"),
193
                 this->name_.c_str());
194
      return 0;
195
    }
196
 
197
  if (eei->result_section_pointer != NULL)
198
    *eei->result_section_pointer = sym->output_section();
199
 
200
  if (parameters->target().get_size() == 32)
201
    return eei->symtab->get_sized_symbol<32>(sym)->value();
202
  else if (parameters->target().get_size() == 64)
203
    return eei->symtab->get_sized_symbol<64>(sym)->value();
204
  else
205
    gold_unreachable();
206
}
207
 
208
// An expression whose value is the value of the special symbol ".".
209
// This is only valid within a SECTIONS clause.
210
 
211
class Dot_expression : public Expression
212
{
213
 public:
214
  Dot_expression()
215
  { }
216
 
217
  uint64_t
218
  value(const Expression_eval_info*);
219
 
220
  void
221
  print(FILE* f) const
222
  { fprintf(f, "."); }
223
};
224
 
225
uint64_t
226
Dot_expression::value(const Expression_eval_info* eei)
227
{
228
  if (!eei->is_dot_available)
229
    {
230
      gold_error(_("invalid reference to dot symbol outside of "
231
                   "SECTIONS clause"));
232
      return 0;
233
    }
234
  if (eei->result_section_pointer != NULL)
235
    *eei->result_section_pointer = eei->dot_section;
236
  return eei->dot_value;
237
}
238
 
239
// A string.  This is either the name of a symbol, or ".".
240
 
241
extern "C" Expression*
242
script_exp_string(const char* name, size_t length)
243
{
244
  if (length == 1 && name[0] == '.')
245
    return new Dot_expression();
246
  else
247
    return new Symbol_expression(name, length);
248
}
249
 
250
// A unary expression.
251
 
252
class Unary_expression : public Expression
253
{
254
 public:
255
  Unary_expression(Expression* arg)
256
    : arg_(arg)
257
  { }
258
 
259
  ~Unary_expression()
260
  { delete this->arg_; }
261
 
262
 protected:
263
  uint64_t
264
  arg_value(const Expression_eval_info* eei,
265
            Output_section** arg_section_pointer) const
266
  {
267
    return this->arg_->eval_maybe_dot(eei->symtab, eei->layout,
268
                                      eei->check_assertions,
269
                                      eei->is_dot_available,
270
                                      eei->dot_value,
271
                                      eei->dot_section,
272
                                      arg_section_pointer,
273 163 khays
                                      eei->result_alignment_pointer,
274
                                      false);
275 27 khays
  }
276
 
277
  void
278
  arg_print(FILE* f) const
279
  { this->arg_->print(f); }
280
 
281
 private:
282
  Expression* arg_;
283
};
284
 
285
// Handle unary operators.  We use a preprocessor macro as a hack to
286
// capture the C operator.
287
 
288
#define UNARY_EXPRESSION(NAME, OPERATOR)                                \
289
  class Unary_ ## NAME : public Unary_expression                        \
290
  {                                                                     \
291
  public:                                                               \
292
    Unary_ ## NAME(Expression* arg)                                     \
293
      : Unary_expression(arg)                                           \
294
    { }                                                                 \
295
                                                                        \
296
    uint64_t                                                            \
297
    value(const Expression_eval_info* eei)                              \
298
    {                                                                   \
299
      Output_section* arg_section;                                      \
300
      uint64_t ret = OPERATOR this->arg_value(eei, &arg_section);       \
301
      if (arg_section != NULL && parameters->options().relocatable())   \
302
        gold_warning(_("unary " #NAME " applied to section "            \
303
                       "relative value"));                              \
304
      return ret;                                                       \
305
    }                                                                   \
306
                                                                        \
307
    void                                                                \
308
    print(FILE* f) const                                                \
309
    {                                                                   \
310
      fprintf(f, "(%s ", #OPERATOR);                                    \
311
      this->arg_print(f);                                               \
312
      fprintf(f, ")");                                                  \
313
    }                                                                   \
314
  };                                                                    \
315
                                                                        \
316
  extern "C" Expression*                                                \
317
  script_exp_unary_ ## NAME(Expression* arg)                            \
318
  {                                                                     \
319
      return new Unary_ ## NAME(arg);                                   \
320
  }
321
 
322
UNARY_EXPRESSION(minus, -)
323
UNARY_EXPRESSION(logical_not, !)
324
UNARY_EXPRESSION(bitwise_not, ~)
325
 
326
// A binary expression.
327
 
328
class Binary_expression : public Expression
329
{
330
 public:
331
  Binary_expression(Expression* left, Expression* right)
332
    : left_(left), right_(right)
333
  { }
334
 
335
  ~Binary_expression()
336
  {
337
    delete this->left_;
338
    delete this->right_;
339
  }
340
 
341
 protected:
342
  uint64_t
343
  left_value(const Expression_eval_info* eei,
344
             Output_section** section_pointer,
345
             uint64_t* alignment_pointer) const
346
  {
347
    return this->left_->eval_maybe_dot(eei->symtab, eei->layout,
348
                                       eei->check_assertions,
349
                                       eei->is_dot_available,
350
                                       eei->dot_value,
351
                                       eei->dot_section,
352
                                       section_pointer,
353 163 khays
                                       alignment_pointer,
354
                                       false);
355 27 khays
  }
356
 
357
  uint64_t
358
  right_value(const Expression_eval_info* eei,
359
              Output_section** section_pointer,
360
              uint64_t* alignment_pointer) const
361
  {
362
    return this->right_->eval_maybe_dot(eei->symtab, eei->layout,
363
                                        eei->check_assertions,
364
                                        eei->is_dot_available,
365
                                        eei->dot_value,
366
                                        eei->dot_section,
367
                                        section_pointer,
368 163 khays
                                        alignment_pointer,
369
                                        false);
370 27 khays
  }
371
 
372
  void
373
  left_print(FILE* f) const
374
  { this->left_->print(f); }
375
 
376
  void
377
  right_print(FILE* f) const
378
  { this->right_->print(f); }
379
 
380
  // This is a call to function FUNCTION_NAME.  Print it.  This is for
381
  // debugging.
382
  void
383
  print_function(FILE* f, const char* function_name) const
384
  {
385
    fprintf(f, "%s(", function_name);
386
    this->left_print(f);
387
    fprintf(f, ", ");
388
    this->right_print(f);
389
    fprintf(f, ")");
390
  }
391
 
392
 private:
393
  Expression* left_;
394
  Expression* right_;
395
};
396
 
397
// Handle binary operators.  We use a preprocessor macro as a hack to
398
// capture the C operator.  KEEP_LEFT means that if the left operand
399
// is section relative and the right operand is not, the result uses
400
// the same section as the left operand.  KEEP_RIGHT is the same with
401
// left and right swapped.  IS_DIV means that we need to give an error
402
// if the right operand is zero.  WARN means that we should warn if
403
// used on section relative values in a relocatable link.  We always
404
// warn if used on values in different sections in a relocatable link.
405
 
406
#define BINARY_EXPRESSION(NAME, OPERATOR, KEEP_LEFT, KEEP_RIGHT, IS_DIV, WARN) \
407
  class Binary_ ## NAME : public Binary_expression                      \
408
  {                                                                     \
409
  public:                                                               \
410
    Binary_ ## NAME(Expression* left, Expression* right)                \
411
      : Binary_expression(left, right)                                  \
412
    { }                                                                 \
413
                                                                        \
414
    uint64_t                                                            \
415
    value(const Expression_eval_info* eei)                              \
416
    {                                                                   \
417
      Output_section* left_section;                                     \
418
      uint64_t left_alignment = 0;                                       \
419
      uint64_t left = this->left_value(eei, &left_section,              \
420
                                       &left_alignment);                \
421
      Output_section* right_section;                                    \
422
      uint64_t right_alignment = 0;                                      \
423
      uint64_t right = this->right_value(eei, &right_section,           \
424
                                         &right_alignment);             \
425
      if (KEEP_RIGHT && left_section == NULL && right_section != NULL)  \
426
        {                                                               \
427
          if (eei->result_section_pointer != NULL)                      \
428
            *eei->result_section_pointer = right_section;               \
429
          if (eei->result_alignment_pointer != NULL                     \
430
              && right_alignment > *eei->result_alignment_pointer)      \
431
            *eei->result_alignment_pointer = right_alignment;           \
432
        }                                                               \
433
      else if (KEEP_LEFT                                                \
434
               && left_section != NULL                                  \
435
               && right_section == NULL)                                \
436
        {                                                               \
437
          if (eei->result_section_pointer != NULL)                      \
438
            *eei->result_section_pointer = left_section;                \
439
          if (eei->result_alignment_pointer != NULL                     \
440
              && left_alignment > *eei->result_alignment_pointer)       \
441
            *eei->result_alignment_pointer = left_alignment;            \
442
        }                                                               \
443
      else if ((WARN || left_section != right_section)                  \
444
               && (left_section != NULL || right_section != NULL)       \
445
               && parameters->options().relocatable())                  \
446
        gold_warning(_("binary " #NAME " applied to section "           \
447
                       "relative value"));                              \
448
      if (IS_DIV && right == 0)                                          \
449
        {                                                               \
450
          gold_error(_(#NAME " by zero"));                              \
451
          return 0;                                                      \
452
        }                                                               \
453
      return left OPERATOR right;                                       \
454
    }                                                                   \
455
                                                                        \
456
    void                                                                \
457
    print(FILE* f) const                                                \
458
    {                                                                   \
459
      fprintf(f, "(");                                                  \
460
      this->left_print(f);                                              \
461
      fprintf(f, " %s ", #OPERATOR);                                    \
462
      this->right_print(f);                                             \
463
      fprintf(f, ")");                                                  \
464
    }                                                                   \
465
  };                                                                    \
466
                                                                        \
467
  extern "C" Expression*                                                \
468
  script_exp_binary_ ## NAME(Expression* left, Expression* right)       \
469
  {                                                                     \
470
    return new Binary_ ## NAME(left, right);                            \
471
  }
472
 
473
BINARY_EXPRESSION(mult, *, false, false, false, true)
474
BINARY_EXPRESSION(div, /, false, false, true, true)
475
BINARY_EXPRESSION(mod, %, false, false, true, true)
476
BINARY_EXPRESSION(add, +, true, true, false, true)
477
BINARY_EXPRESSION(sub, -, true, false, false, false)
478
BINARY_EXPRESSION(lshift, <<, false, false, false, true)
479
BINARY_EXPRESSION(rshift, >>, false, false, false, true)
480
BINARY_EXPRESSION(eq, ==, false, false, false, false)
481
BINARY_EXPRESSION(ne, !=, false, false, false, false)
482
BINARY_EXPRESSION(le, <=, false, false, false, false)
483
BINARY_EXPRESSION(ge, >=, false, false, false, false)
484
BINARY_EXPRESSION(lt, <, false, false, false, false)
485
BINARY_EXPRESSION(gt, >, false, false, false, false)
486
BINARY_EXPRESSION(bitwise_and, &, true, true, false, true)
487
BINARY_EXPRESSION(bitwise_xor, ^, true, true, false, true)
488
BINARY_EXPRESSION(bitwise_or, |, true, true, false, true)
489
BINARY_EXPRESSION(logical_and, &&, false, false, false, true)
490
BINARY_EXPRESSION(logical_or, ||, false, false, false, true)
491
 
492
// A trinary expression.
493
 
494
class Trinary_expression : public Expression
495
{
496
 public:
497
  Trinary_expression(Expression* arg1, Expression* arg2, Expression* arg3)
498
    : arg1_(arg1), arg2_(arg2), arg3_(arg3)
499
  { }
500
 
501
  ~Trinary_expression()
502
  {
503
    delete this->arg1_;
504
    delete this->arg2_;
505
    delete this->arg3_;
506
  }
507
 
508
 protected:
509
  uint64_t
510
  arg1_value(const Expression_eval_info* eei,
511
             Output_section** section_pointer) const
512
  {
513
    return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
514
                                       eei->check_assertions,
515
                                       eei->is_dot_available,
516
                                       eei->dot_value,
517
                                       eei->dot_section,
518
                                       section_pointer,
519 163 khays
                                       NULL,
520
                                       false);
521 27 khays
  }
522
 
523
  uint64_t
524
  arg2_value(const Expression_eval_info* eei,
525
             Output_section** section_pointer,
526
             uint64_t* alignment_pointer) const
527
  {
528
    return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
529
                                       eei->check_assertions,
530
                                       eei->is_dot_available,
531
                                       eei->dot_value,
532
                                       eei->dot_section,
533
                                       section_pointer,
534 163 khays
                                       alignment_pointer,
535
                                       false);
536 27 khays
  }
537
 
538
  uint64_t
539
  arg3_value(const Expression_eval_info* eei,
540
             Output_section** section_pointer,
541
             uint64_t* alignment_pointer) const
542
  {
543
    return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
544
                                       eei->check_assertions,
545
                                       eei->is_dot_available,
546
                                       eei->dot_value,
547
                                       eei->dot_section,
548
                                       section_pointer,
549 163 khays
                                       alignment_pointer,
550
                                       false);
551 27 khays
  }
552
 
553
  void
554
  arg1_print(FILE* f) const
555
  { this->arg1_->print(f); }
556
 
557
  void
558
  arg2_print(FILE* f) const
559
  { this->arg2_->print(f); }
560
 
561
  void
562
  arg3_print(FILE* f) const
563
  { this->arg3_->print(f); }
564
 
565
 private:
566
  Expression* arg1_;
567
  Expression* arg2_;
568
  Expression* arg3_;
569
};
570
 
571
// The conditional operator.
572
 
573
class Trinary_cond : public Trinary_expression
574
{
575
 public:
576
  Trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
577
    : Trinary_expression(arg1, arg2, arg3)
578
  { }
579
 
580
  uint64_t
581
  value(const Expression_eval_info* eei)
582
  {
583
    Output_section* arg1_section;
584
    uint64_t arg1 = this->arg1_value(eei, &arg1_section);
585
    return (arg1
586
            ? this->arg2_value(eei, eei->result_section_pointer,
587
                               eei->result_alignment_pointer)
588
            : this->arg3_value(eei, eei->result_section_pointer,
589
                               eei->result_alignment_pointer));
590
  }
591
 
592
  void
593
  print(FILE* f) const
594
  {
595
    fprintf(f, "(");
596
    this->arg1_print(f);
597
    fprintf(f, " ? ");
598
    this->arg2_print(f);
599
    fprintf(f, " : ");
600
    this->arg3_print(f);
601
    fprintf(f, ")");
602
  }
603
};
604
 
605
extern "C" Expression*
606
script_exp_trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
607
{
608
  return new Trinary_cond(arg1, arg2, arg3);
609
}
610
 
611
// Max function.
612
 
613
class Max_expression : public Binary_expression
614
{
615
 public:
616
  Max_expression(Expression* left, Expression* right)
617
    : Binary_expression(left, right)
618
  { }
619
 
620
  uint64_t
621
  value(const Expression_eval_info* eei)
622
  {
623
    Output_section* left_section;
624
    uint64_t left_alignment;
625
    uint64_t left = this->left_value(eei, &left_section, &left_alignment);
626
    Output_section* right_section;
627
    uint64_t right_alignment;
628
    uint64_t right = this->right_value(eei, &right_section, &right_alignment);
629
    if (left_section == right_section)
630
      {
631
        if (eei->result_section_pointer != NULL)
632
          *eei->result_section_pointer = left_section;
633
      }
634
    else if ((left_section != NULL || right_section != NULL)
635
             && parameters->options().relocatable())
636
      gold_warning(_("max applied to section relative value"));
637
    if (eei->result_alignment_pointer != NULL)
638
      {
639
        uint64_t ra = *eei->result_alignment_pointer;
640
        if (left > right)
641
          ra = std::max(ra, left_alignment);
642
        else if (right > left)
643
          ra = std::max(ra, right_alignment);
644
        else
645
          ra = std::max(ra, std::max(left_alignment, right_alignment));
646
        *eei->result_alignment_pointer = ra;
647
      }
648
    return std::max(left, right);
649
  }
650
 
651
  void
652
  print(FILE* f) const
653
  { this->print_function(f, "MAX"); }
654
};
655
 
656
extern "C" Expression*
657
script_exp_function_max(Expression* left, Expression* right)
658
{
659
  return new Max_expression(left, right);
660
}
661
 
662
// Min function.
663
 
664
class Min_expression : public Binary_expression
665
{
666
 public:
667
  Min_expression(Expression* left, Expression* right)
668
    : Binary_expression(left, right)
669
  { }
670
 
671
  uint64_t
672
  value(const Expression_eval_info* eei)
673
  {
674
    Output_section* left_section;
675
    uint64_t left_alignment;
676
    uint64_t left = this->left_value(eei, &left_section, &left_alignment);
677
    Output_section* right_section;
678
    uint64_t right_alignment;
679
    uint64_t right = this->right_value(eei, &right_section, &right_alignment);
680
    if (left_section == right_section)
681
      {
682
        if (eei->result_section_pointer != NULL)
683
          *eei->result_section_pointer = left_section;
684
      }
685
    else if ((left_section != NULL || right_section != NULL)
686
             && parameters->options().relocatable())
687
      gold_warning(_("min applied to section relative value"));
688
    if (eei->result_alignment_pointer != NULL)
689
      {
690
        uint64_t ra = *eei->result_alignment_pointer;
691
        if (left < right)
692
          ra = std::max(ra, left_alignment);
693
        else if (right < left)
694
          ra = std::max(ra, right_alignment);
695
        else
696
          ra = std::max(ra, std::max(left_alignment, right_alignment));
697
        *eei->result_alignment_pointer = ra;
698
      }
699
    return std::min(left, right);
700
  }
701
 
702
  void
703
  print(FILE* f) const
704
  { this->print_function(f, "MIN"); }
705
};
706
 
707
extern "C" Expression*
708
script_exp_function_min(Expression* left, Expression* right)
709
{
710
  return new Min_expression(left, right);
711
}
712
 
713
// Class Section_expression.  This is a parent class used for
714
// functions which take the name of an output section.
715
 
716
class Section_expression : public Expression
717
{
718
 public:
719
  Section_expression(const char* section_name, size_t section_name_len)
720
    : section_name_(section_name, section_name_len)
721
  { }
722
 
723
  uint64_t
724
  value(const Expression_eval_info*);
725
 
726
  void
727
  print(FILE* f) const
728
  { fprintf(f, "%s(%s)", this->function_name(), this->section_name_.c_str()); }
729
 
730
 protected:
731
  // The child class must implement this.
732
  virtual uint64_t
733
  value_from_output_section(const Expression_eval_info*,
734
                            Output_section*) = 0;
735
 
736
  // The child class must implement this.
737
  virtual uint64_t
738
  value_from_script_output_section(uint64_t address, uint64_t load_address,
739
                                   uint64_t addralign, uint64_t size) = 0;
740
 
741
  // The child class must implement this.
742
  virtual const char*
743
  function_name() const = 0;
744
 
745
 private:
746
  std::string section_name_;
747
};
748
 
749
uint64_t
750
Section_expression::value(const Expression_eval_info* eei)
751
{
752
  const char* section_name = this->section_name_.c_str();
753
  Output_section* os = eei->layout->find_output_section(section_name);
754
  if (os != NULL)
755
    return this->value_from_output_section(eei, os);
756
 
757
  uint64_t address;
758
  uint64_t load_address;
759
  uint64_t addralign;
760
  uint64_t size;
761
  const Script_options* ss = eei->layout->script_options();
762
  if (ss->saw_sections_clause())
763
    {
764
      if (ss->script_sections()->get_output_section_info(section_name,
765
                                                         &address,
766
                                                         &load_address,
767
                                                         &addralign,
768
                                                         &size))
769
        return this->value_from_script_output_section(address, load_address,
770
                                                      addralign, size);
771
    }
772
 
773
  gold_error("%s called on nonexistent output section '%s'",
774
             this->function_name(), section_name);
775
  return 0;
776
}
777
 
778
// ABSOLUTE function.
779
 
780
class Absolute_expression : public Unary_expression
781
{
782
 public:
783
  Absolute_expression(Expression* arg)
784
    : Unary_expression(arg)
785
  { }
786
 
787
  uint64_t
788
  value(const Expression_eval_info* eei)
789
  {
790
    uint64_t ret = this->arg_value(eei, NULL);
791
    // Force the value to be absolute.
792
    if (eei->result_section_pointer != NULL)
793
      *eei->result_section_pointer = NULL;
794
    return ret;
795
  }
796
 
797
  void
798
  print(FILE* f) const
799
  {
800
    fprintf(f, "ABSOLUTE(");
801
    this->arg_print(f);
802
    fprintf(f, ")");
803
  }
804
};
805
 
806
extern "C" Expression*
807
script_exp_function_absolute(Expression* arg)
808
{
809
  return new Absolute_expression(arg);
810
}
811
 
812
// ALIGN function.
813
 
814
class Align_expression : public Binary_expression
815
{
816
 public:
817
  Align_expression(Expression* left, Expression* right)
818
    : Binary_expression(left, right)
819
  { }
820
 
821
  uint64_t
822
  value(const Expression_eval_info* eei)
823
  {
824
    Output_section* align_section;
825
    uint64_t align = this->right_value(eei, &align_section, NULL);
826
    if (align_section != NULL
827
        && parameters->options().relocatable())
828
      gold_warning(_("aligning to section relative value"));
829
 
830
    if (eei->result_alignment_pointer != NULL
831
        && align > *eei->result_alignment_pointer)
832
      {
833
        uint64_t a = align;
834
        while ((a & (a - 1)) != 0)
835
          a &= a - 1;
836
        *eei->result_alignment_pointer = a;
837
      }
838
 
839
    uint64_t value = this->left_value(eei, eei->result_section_pointer, NULL);
840
    if (align <= 1)
841
      return value;
842
    return ((value + align - 1) / align) * align;
843
  }
844
 
845
  void
846
  print(FILE* f) const
847
  { this->print_function(f, "ALIGN"); }
848
};
849
 
850
extern "C" Expression*
851
script_exp_function_align(Expression* left, Expression* right)
852
{
853
  return new Align_expression(left, right);
854
}
855
 
856
// ASSERT function.
857
 
858
class Assert_expression : public Unary_expression
859
{
860
 public:
861
  Assert_expression(Expression* arg, const char* message, size_t length)
862
    : Unary_expression(arg), message_(message, length)
863
  { }
864
 
865
  uint64_t
866
  value(const Expression_eval_info* eei)
867
  {
868
    uint64_t value = this->arg_value(eei, eei->result_section_pointer);
869
    if (!value && eei->check_assertions)
870
      gold_error("%s", this->message_.c_str());
871
    return value;
872
  }
873
 
874
  void
875
  print(FILE* f) const
876
  {
877
    fprintf(f, "ASSERT(");
878
    this->arg_print(f);
879
    fprintf(f, ", %s)", this->message_.c_str());
880
  }
881
 
882
 private:
883
  std::string message_;
884
};
885
 
886
extern "C" Expression*
887
script_exp_function_assert(Expression* expr, const char* message,
888
                           size_t length)
889
{
890
  return new Assert_expression(expr, message, length);
891
}
892
 
893
// ADDR function.
894
 
895
class Addr_expression : public Section_expression
896
{
897
 public:
898
  Addr_expression(const char* section_name, size_t section_name_len)
899
    : Section_expression(section_name, section_name_len)
900
  { }
901
 
902
 protected:
903
  uint64_t
904
  value_from_output_section(const Expression_eval_info* eei,
905
                            Output_section* os)
906
  {
907
    if (eei->result_section_pointer != NULL)
908
      *eei->result_section_pointer = os;
909
    return os->address();
910
  }
911
 
912
  uint64_t
913
  value_from_script_output_section(uint64_t address, uint64_t, uint64_t,
914
                                   uint64_t)
915
  { return address; }
916
 
917
  const char*
918
  function_name() const
919
  { return "ADDR"; }
920
};
921
 
922
extern "C" Expression*
923
script_exp_function_addr(const char* section_name, size_t section_name_len)
924
{
925
  return new Addr_expression(section_name, section_name_len);
926
}
927
 
928
// ALIGNOF.
929
 
930
class Alignof_expression : public Section_expression
931
{
932
 public:
933
  Alignof_expression(const char* section_name, size_t section_name_len)
934
    : Section_expression(section_name, section_name_len)
935
  { }
936
 
937
 protected:
938
  uint64_t
939
  value_from_output_section(const Expression_eval_info*,
940
                            Output_section* os)
941
  { return os->addralign(); }
942
 
943
  uint64_t
944
  value_from_script_output_section(uint64_t, uint64_t, uint64_t addralign,
945
                                   uint64_t)
946
  { return addralign; }
947
 
948
  const char*
949
  function_name() const
950
  { return "ALIGNOF"; }
951
};
952
 
953
extern "C" Expression*
954
script_exp_function_alignof(const char* section_name, size_t section_name_len)
955
{
956
  return new Alignof_expression(section_name, section_name_len);
957
}
958
 
959
// CONSTANT.  It would be nice if we could simply evaluate this
960
// immediately and return an Integer_expression, but unfortunately we
961
// don't know the target.
962
 
963
class Constant_expression : public Expression
964
{
965
 public:
966
  Constant_expression(const char* name, size_t length);
967
 
968
  uint64_t
969
  value(const Expression_eval_info*);
970
 
971
  void
972
  print(FILE* f) const;
973
 
974
 private:
975
  enum Constant_function
976
  {
977
    CONSTANT_MAXPAGESIZE,
978
    CONSTANT_COMMONPAGESIZE
979
  };
980
 
981
  Constant_function function_;
982
};
983
 
984
Constant_expression::Constant_expression(const char* name, size_t length)
985
{
986
  if (length == 11 && strncmp(name, "MAXPAGESIZE", length) == 0)
987
    this->function_ = CONSTANT_MAXPAGESIZE;
988
  else if (length == 14 && strncmp(name, "COMMONPAGESIZE", length) == 0)
989
    this->function_ = CONSTANT_COMMONPAGESIZE;
990
  else
991
    {
992
      std::string s(name, length);
993
      gold_error(_("unknown constant %s"), s.c_str());
994
      this->function_ = CONSTANT_MAXPAGESIZE;
995
    }
996
}
997
 
998
uint64_t
999
Constant_expression::value(const Expression_eval_info*)
1000
{
1001
  switch (this->function_)
1002
    {
1003
    case CONSTANT_MAXPAGESIZE:
1004
      return parameters->target().abi_pagesize();
1005
    case CONSTANT_COMMONPAGESIZE:
1006
      return parameters->target().common_pagesize();
1007
    default:
1008
      gold_unreachable();
1009
    }
1010
}
1011
 
1012
void
1013
Constant_expression::print(FILE* f) const
1014
{
1015
  const char* name;
1016
  switch (this->function_)
1017
    {
1018
    case CONSTANT_MAXPAGESIZE:
1019
      name = "MAXPAGESIZE";
1020
      break;
1021
    case CONSTANT_COMMONPAGESIZE:
1022
      name = "COMMONPAGESIZE";
1023
      break;
1024
    default:
1025
      gold_unreachable();
1026
    }
1027
  fprintf(f, "CONSTANT(%s)", name);
1028
}
1029
 
1030
extern "C" Expression*
1031
script_exp_function_constant(const char* name, size_t length)
1032
{
1033
  return new Constant_expression(name, length);
1034
}
1035
 
1036
// DATA_SEGMENT_ALIGN.  FIXME: we don't implement this; we always fall
1037
// back to the general case.
1038
 
1039
extern "C" Expression*
1040
script_exp_function_data_segment_align(Expression* left, Expression*)
1041
{
1042
  Expression* e1 = script_exp_function_align(script_exp_string(".", 1), left);
1043
  Expression* e2 = script_exp_binary_sub(left, script_exp_integer(1));
1044
  Expression* e3 = script_exp_binary_bitwise_and(script_exp_string(".", 1),
1045
                                                 e2);
1046
  return script_exp_binary_add(e1, e3);
1047
}
1048
 
1049
// DATA_SEGMENT_RELRO.  FIXME: This is not implemented.
1050
 
1051
extern "C" Expression*
1052
script_exp_function_data_segment_relro_end(Expression*, Expression* right)
1053
{
1054
  return right;
1055
}
1056
 
1057
// DATA_SEGMENT_END.  FIXME: This is not implemented.
1058
 
1059
extern "C" Expression*
1060
script_exp_function_data_segment_end(Expression* val)
1061
{
1062
  return val;
1063
}
1064
 
1065
// DEFINED function.
1066
 
1067
class Defined_expression : public Expression
1068
{
1069
 public:
1070
  Defined_expression(const char* symbol_name, size_t symbol_name_len)
1071
    : symbol_name_(symbol_name, symbol_name_len)
1072
  { }
1073
 
1074
  uint64_t
1075
  value(const Expression_eval_info* eei)
1076
  {
1077
    Symbol* sym = eei->symtab->lookup(this->symbol_name_.c_str());
1078
    return sym != NULL && sym->is_defined();
1079
  }
1080
 
1081
  void
1082
  print(FILE* f) const
1083
  { fprintf(f, "DEFINED(%s)", this->symbol_name_.c_str()); }
1084
 
1085
 private:
1086
  std::string symbol_name_;
1087
};
1088
 
1089
extern "C" Expression*
1090
script_exp_function_defined(const char* symbol_name, size_t symbol_name_len)
1091
{
1092
  return new Defined_expression(symbol_name, symbol_name_len);
1093
}
1094
 
1095
// LOADADDR function
1096
 
1097
class Loadaddr_expression : public Section_expression
1098
{
1099
 public:
1100
  Loadaddr_expression(const char* section_name, size_t section_name_len)
1101
    : Section_expression(section_name, section_name_len)
1102
  { }
1103
 
1104
 protected:
1105
  uint64_t
1106
  value_from_output_section(const Expression_eval_info* eei,
1107
                            Output_section* os)
1108
  {
1109
    if (os->has_load_address())
1110
      return os->load_address();
1111
    else
1112
      {
1113
        if (eei->result_section_pointer != NULL)
1114
          *eei->result_section_pointer = os;
1115
        return os->address();
1116
      }
1117
  }
1118
 
1119
  uint64_t
1120
  value_from_script_output_section(uint64_t, uint64_t load_address, uint64_t,
1121
                                   uint64_t)
1122
  { return load_address; }
1123
 
1124
  const char*
1125
  function_name() const
1126
  { return "LOADADDR"; }
1127
};
1128
 
1129
extern "C" Expression*
1130
script_exp_function_loadaddr(const char* section_name, size_t section_name_len)
1131
{
1132
  return new Loadaddr_expression(section_name, section_name_len);
1133
}
1134
 
1135
// SIZEOF function
1136
 
1137
class Sizeof_expression : public Section_expression
1138
{
1139
 public:
1140
  Sizeof_expression(const char* section_name, size_t section_name_len)
1141
    : Section_expression(section_name, section_name_len)
1142
  { }
1143
 
1144
 protected:
1145
  uint64_t
1146
  value_from_output_section(const Expression_eval_info*,
1147
                            Output_section* os)
1148
  {
1149
    // We can not use data_size here, as the size of the section may
1150
    // not have been finalized.  Instead we get whatever the current
1151
    // size is.  This will work correctly for backward references in
1152
    // linker scripts.
1153
    return os->current_data_size();
1154
  }
1155
 
1156
  uint64_t
1157
  value_from_script_output_section(uint64_t, uint64_t, uint64_t,
1158
                                   uint64_t size)
1159
  { return size; }
1160
 
1161
  const char*
1162
  function_name() const
1163
  { return "SIZEOF"; }
1164
};
1165
 
1166
extern "C" Expression*
1167
script_exp_function_sizeof(const char* section_name, size_t section_name_len)
1168
{
1169
  return new Sizeof_expression(section_name, section_name_len);
1170
}
1171
 
1172
// SIZEOF_HEADERS.
1173
 
1174
class Sizeof_headers_expression : public Expression
1175
{
1176
 public:
1177
  Sizeof_headers_expression()
1178
  { }
1179
 
1180
  uint64_t
1181
  value(const Expression_eval_info*);
1182
 
1183
  void
1184
  print(FILE* f) const
1185
  { fprintf(f, "SIZEOF_HEADERS"); }
1186
};
1187
 
1188
uint64_t
1189
Sizeof_headers_expression::value(const Expression_eval_info* eei)
1190
{
1191
  unsigned int ehdr_size;
1192
  unsigned int phdr_size;
1193
  if (parameters->target().get_size() == 32)
1194
    {
1195
      ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size;
1196
      phdr_size = elfcpp::Elf_sizes<32>::phdr_size;
1197
    }
1198
  else if (parameters->target().get_size() == 64)
1199
    {
1200
      ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size;
1201
      phdr_size = elfcpp::Elf_sizes<64>::phdr_size;
1202
    }
1203
  else
1204
    gold_unreachable();
1205
 
1206
  return ehdr_size + phdr_size * eei->layout->expected_segment_count();
1207
}
1208
 
1209
extern "C" Expression*
1210
script_exp_function_sizeof_headers()
1211
{
1212
  return new Sizeof_headers_expression();
1213
}
1214
 
1215
// SEGMENT_START.
1216
 
1217
class Segment_start_expression : public Unary_expression
1218
{
1219
 public:
1220
  Segment_start_expression(const char* segment_name, size_t segment_name_len,
1221
                           Expression* default_value)
1222
    : Unary_expression(default_value),
1223
      segment_name_(segment_name, segment_name_len)
1224
  { }
1225
 
1226
  uint64_t
1227
  value(const Expression_eval_info*);
1228
 
1229
  void
1230
  print(FILE* f) const
1231
  {
1232
    fprintf(f, "SEGMENT_START(\"%s\", ", this->segment_name_.c_str());
1233
    this->arg_print(f);
1234
    fprintf(f, ")");
1235
  }
1236
 
1237
 private:
1238
  std::string segment_name_;
1239
};
1240
 
1241
uint64_t
1242
Segment_start_expression::value(const Expression_eval_info* eei)
1243
{
1244
  // Check for command line overrides.
1245
  if (parameters->options().user_set_Ttext()
1246
      && this->segment_name_ == ".text")
1247
    return parameters->options().Ttext();
1248
  else if (parameters->options().user_set_Tdata()
1249
           && this->segment_name_ == ".data")
1250
    return parameters->options().Tdata();
1251
  else if (parameters->options().user_set_Tbss()
1252
           && this->segment_name_ == ".bss")
1253
    return parameters->options().Tbss();
1254
  else
1255
    {
1256
      uint64_t ret = this->arg_value(eei, NULL);
1257
      // Force the value to be absolute.
1258
      if (eei->result_section_pointer != NULL)
1259
        *eei->result_section_pointer = NULL;
1260
      return ret;
1261
    }
1262
}
1263
 
1264
extern "C" Expression*
1265
script_exp_function_segment_start(const char* segment_name,
1266
                                  size_t segment_name_len,
1267
                                  Expression* default_value)
1268
{
1269
  return new Segment_start_expression(segment_name, segment_name_len,
1270
                                      default_value);
1271
}
1272
 
1273
} // End namespace gold.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.