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 41

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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