*** empty log message ***
[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
3802b2dd 27#include "elfcpp.h"
e5756efb
ILT
28#include "parameters.h"
29#include "symtab.h"
30#include "layout.h"
494e05f4 31#include "output.h"
e5756efb
ILT
32#include "script.h"
33#include "script-c.h"
34
35namespace gold
36{
37
38// This file holds the code which handles linker expressions.
39
a445fddf
ILT
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
e5756efb
ILT
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
51struct Expression::Expression_eval_info
52{
a445fddf 53 // The symbol table.
e5756efb 54 const Symbol_table* symtab;
a445fddf 55 // The layout--we use this to get section information.
e5756efb 56 const Layout* layout;
a445fddf
ILT
57 // Whether expressions can refer to the dot symbol. The dot symbol
58 // is only available within a SECTIONS clause.
59 bool is_dot_available;
60 // Whether the dot symbol currently has a value.
61 bool dot_has_value;
62 // The current value of the dot symbol.
63 uint64_t dot_value;
64 // Points to the IS_ABSOLUTE variable, which is set to false if the
65 // expression uses a value which is not absolute.
66 bool* is_absolute;
e5756efb
ILT
67};
68
69// Evaluate an expression.
70
71uint64_t
72Expression::eval(const Symbol_table* symtab, const Layout* layout)
a445fddf
ILT
73{
74 bool dummy;
75 return this->eval_maybe_dot(symtab, layout, false, false, 0, &dummy);
76}
77
78// Evaluate an expression which may refer to the dot symbol.
79
80uint64_t
81Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout,
82 bool dot_has_value, uint64_t dot_value,
83 bool* is_absolute)
84{
85 return this->eval_maybe_dot(symtab, layout, true, dot_has_value, dot_value,
86 is_absolute);
87}
88
89// Evaluate an expression which may or may not refer to the dot
90// symbol.
91
92uint64_t
93Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
94 bool is_dot_available, bool dot_has_value,
95 uint64_t dot_value, bool* is_absolute)
e5756efb
ILT
96{
97 Expression_eval_info eei;
98 eei.symtab = symtab;
99 eei.layout = layout;
a445fddf
ILT
100 eei.is_dot_available = is_dot_available;
101 eei.dot_has_value = dot_has_value;
102 eei.dot_value = dot_value;
103
104 // We assume the value is absolute, and only set this to false if we
105 // find a section relative reference.
106 *is_absolute = true;
107 eei.is_absolute = is_absolute;
108
e5756efb
ILT
109 return this->value(&eei);
110}
111
112// A number.
113
114class Integer_expression : public Expression
115{
116 public:
117 Integer_expression(uint64_t val)
118 : val_(val)
119 { }
120
121 uint64_t
122 value(const Expression_eval_info*)
123 { return this->val_; }
124
494e05f4
ILT
125 void
126 print(FILE* f) const
127 { fprintf(f, "0x%llx", static_cast<unsigned long long>(this->val_)); }
128
e5756efb
ILT
129 private:
130 uint64_t val_;
131};
132
133extern "C" Expression*
134script_exp_integer(uint64_t val)
135{
136 return new Integer_expression(val);
137}
138
139// An expression whose value is the value of a symbol.
140
141class Symbol_expression : public Expression
142{
143 public:
144 Symbol_expression(const char* name, size_t length)
145 : name_(name, length)
146 { }
147
148 uint64_t
149 value(const Expression_eval_info*);
150
494e05f4
ILT
151 void
152 print(FILE* f) const
153 { fprintf(f, "%s", this->name_.c_str()); }
154
e5756efb
ILT
155 private:
156 std::string name_;
157};
158
159uint64_t
160Symbol_expression::value(const Expression_eval_info* eei)
161{
162 Symbol* sym = eei->symtab->lookup(this->name_.c_str());
163 if (sym == NULL || !sym->is_defined())
164 {
165 gold_error(_("undefined symbol '%s' referenced in expression"),
166 this->name_.c_str());
167 return 0;
168 }
169
a445fddf
ILT
170 // If this symbol does not have an absolute value, then the whole
171 // expression does not have an absolute value. This is not strictly
172 // accurate: the subtraction of two symbols in the same section is
173 // absolute. This is unlikely to matter in practice, as this value
174 // is only used for error checking.
175 if (!sym->value_is_absolute())
176 *eei->is_absolute = false;
177
e5756efb
ILT
178 if (parameters->get_size() == 32)
179 return eei->symtab->get_sized_symbol<32>(sym)->value();
180 else if (parameters->get_size() == 64)
181 return eei->symtab->get_sized_symbol<64>(sym)->value();
182 else
183 gold_unreachable();
184}
185
186// An expression whose value is the value of the special symbol ".".
187// This is only valid within a SECTIONS clause.
188
189class Dot_expression : public Expression
190{
191 public:
192 Dot_expression()
193 { }
194
195 uint64_t
196 value(const Expression_eval_info*);
494e05f4
ILT
197
198 void
199 print(FILE* f) const
200 { fprintf(f, "."); }
e5756efb
ILT
201};
202
203uint64_t
a445fddf 204Dot_expression::value(const Expression_eval_info* eei)
e5756efb 205{
a445fddf
ILT
206 if (!eei->is_dot_available)
207 {
208 gold_error(_("invalid reference to dot symbol outside of "
209 "SECTIONS clause"));
210 return 0;
211 }
212 else if (!eei->dot_has_value)
213 {
214 gold_error(_("invalid reference to dot symbol before "
215 "it has been given a value"));
216 return 0;
217 }
218 return eei->dot_value;
e5756efb
ILT
219}
220
221// A string. This is either the name of a symbol, or ".".
222
223extern "C" Expression*
224script_exp_string(const char* name, size_t length)
225{
226 if (length == 1 && name[0] == '.')
227 return new Dot_expression();
228 else
229 return new Symbol_expression(name, length);
230}
231
232// A unary expression.
233
234class Unary_expression : public Expression
235{
236 public:
237 Unary_expression(Expression* arg)
238 : arg_(arg)
239 { }
240
241 ~Unary_expression()
242 { delete this->arg_; }
243
244 protected:
245 uint64_t
246 arg_value(const Expression_eval_info* eei) const
247 { return this->arg_->value(eei); }
248
494e05f4
ILT
249 void
250 arg_print(FILE* f) const
251 { this->arg_->print(f); }
252
e5756efb
ILT
253 private:
254 Expression* arg_;
255};
256
257// Handle unary operators. We use a preprocessor macro as a hack to
258// capture the C operator.
259
260#define UNARY_EXPRESSION(NAME, OPERATOR) \
261 class Unary_ ## NAME : public Unary_expression \
262 { \
263 public: \
264 Unary_ ## NAME(Expression* arg) \
265 : Unary_expression(arg) \
266 { } \
267 \
268 uint64_t \
269 value(const Expression_eval_info* eei) \
270 { return OPERATOR this->arg_value(eei); } \
494e05f4
ILT
271 \
272 void \
273 print(FILE* f) const \
274 { \
275 fprintf(f, "(%s ", #OPERATOR); \
276 this->arg_print(f); \
277 fprintf(f, ")"); \
278 } \
e5756efb
ILT
279 }; \
280 \
281 extern "C" Expression* \
282 script_exp_unary_ ## NAME(Expression* arg) \
283 { \
284 return new Unary_ ## NAME(arg); \
285 }
286
287UNARY_EXPRESSION(minus, -)
288UNARY_EXPRESSION(logical_not, !)
289UNARY_EXPRESSION(bitwise_not, ~)
290
291// A binary expression.
292
293class Binary_expression : public Expression
294{
295 public:
296 Binary_expression(Expression* left, Expression* right)
297 : left_(left), right_(right)
298 { }
299
300 ~Binary_expression()
301 {
302 delete this->left_;
303 delete this->right_;
304 }
305
306 protected:
307 uint64_t
308 left_value(const Expression_eval_info* eei) const
309 { return this->left_->value(eei); }
310
311 uint64_t
312 right_value(const Expression_eval_info* eei) const
313 { return this->right_->value(eei); }
314
494e05f4
ILT
315 void
316 left_print(FILE* f) const
317 { this->left_->print(f); }
318
319 void
320 right_print(FILE* f) const
321 { this->right_->print(f); }
322
323 // This is a call to function FUNCTION_NAME. Print it. This is for
324 // debugging.
325 void
326 print_function(FILE* f, const char *function_name) const
327 {
328 fprintf(f, "%s(", function_name);
329 this->left_print(f);
330 fprintf(f, ", ");
331 this->right_print(f);
332 fprintf(f, ")");
333 }
334
e5756efb
ILT
335 private:
336 Expression* left_;
337 Expression* right_;
338};
339
340// Handle binary operators. We use a preprocessor macro as a hack to
341// capture the C operator.
342
343#define BINARY_EXPRESSION(NAME, OPERATOR) \
344 class Binary_ ## NAME : public Binary_expression \
345 { \
346 public: \
347 Binary_ ## NAME(Expression* left, Expression* right) \
348 : Binary_expression(left, right) \
349 { } \
350 \
351 uint64_t \
352 value(const Expression_eval_info* eei) \
353 { \
354 return (this->left_value(eei) \
355 OPERATOR this->right_value(eei)); \
494e05f4
ILT
356 } \
357 \
358 void \
359 print(FILE* f) const \
360 { \
361 fprintf(f, "("); \
362 this->left_print(f); \
363 fprintf(f, " %s ", #OPERATOR); \
364 this->right_print(f); \
365 fprintf(f, ")"); \
e5756efb
ILT
366 } \
367 }; \
368 \
369 extern "C" Expression* \
370 script_exp_binary_ ## NAME(Expression* left, Expression* right) \
371 { \
372 return new Binary_ ## NAME(left, right); \
373 }
374
375BINARY_EXPRESSION(mult, *)
376BINARY_EXPRESSION(div, /)
377BINARY_EXPRESSION(mod, %)
378BINARY_EXPRESSION(add, +)
379BINARY_EXPRESSION(sub, -)
380BINARY_EXPRESSION(lshift, <<)
381BINARY_EXPRESSION(rshift, >>)
382BINARY_EXPRESSION(eq, ==)
383BINARY_EXPRESSION(ne, !=)
384BINARY_EXPRESSION(le, <=)
385BINARY_EXPRESSION(ge, >=)
386BINARY_EXPRESSION(lt, <)
387BINARY_EXPRESSION(gt, >)
388BINARY_EXPRESSION(bitwise_and, &)
389BINARY_EXPRESSION(bitwise_xor, ^)
390BINARY_EXPRESSION(bitwise_or, |)
391BINARY_EXPRESSION(logical_and, &&)
392BINARY_EXPRESSION(logical_or, ||)
393
394// A trinary expression.
395
396class Trinary_expression : public Expression
397{
398 public:
399 Trinary_expression(Expression* arg1, Expression* arg2, Expression* arg3)
400 : arg1_(arg1), arg2_(arg2), arg3_(arg3)
401 { }
402
403 ~Trinary_expression()
404 {
405 delete this->arg1_;
406 delete this->arg2_;
407 delete this->arg3_;
408 }
409
410 protected:
411 uint64_t
412 arg1_value(const Expression_eval_info* eei) const
413 { return this->arg1_->value(eei); }
414
415 uint64_t
416 arg2_value(const Expression_eval_info* eei) const
417 { return this->arg2_->value(eei); }
418
419 uint64_t
420 arg3_value(const Expression_eval_info* eei) const
421 { return this->arg3_->value(eei); }
422
494e05f4
ILT
423 void
424 arg1_print(FILE* f) const
425 { this->arg1_->print(f); }
426
427 void
428 arg2_print(FILE* f) const
429 { this->arg2_->print(f); }
430
431 void
432 arg3_print(FILE* f) const
433 { this->arg3_->print(f); }
434
e5756efb
ILT
435 private:
436 Expression* arg1_;
437 Expression* arg2_;
438 Expression* arg3_;
439};
440
441// The conditional operator.
442
443class Trinary_cond : public Trinary_expression
444{
445 public:
446 Trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
447 : Trinary_expression(arg1, arg2, arg3)
448 { }
449
450 uint64_t
451 value(const Expression_eval_info* eei)
452 {
453 return (this->arg1_value(eei)
454 ? this->arg2_value(eei)
455 : this->arg3_value(eei));
456 }
494e05f4
ILT
457
458 void
459 print(FILE* f) const
460 {
461 fprintf(f, "(");
462 this->arg1_print(f);
463 fprintf(f, " ? ");
464 this->arg2_print(f);
465 fprintf(f, " : ");
466 this->arg3_print(f);
467 fprintf(f, ")");
468 }
e5756efb
ILT
469};
470
471extern "C" Expression*
472script_exp_trinary_cond(Expression* arg1, Expression* arg2, Expression* arg3)
473{
474 return new Trinary_cond(arg1, arg2, arg3);
475}
476
477// Max function.
478
479class Max_expression : public Binary_expression
480{
481 public:
482 Max_expression(Expression* left, Expression* right)
483 : Binary_expression(left, right)
484 { }
485
486 uint64_t
487 value(const Expression_eval_info* eei)
488 { return std::max(this->left_value(eei), this->right_value(eei)); }
494e05f4
ILT
489
490 void
491 print(FILE* f) const
492 { this->print_function(f, "MAX"); }
e5756efb
ILT
493};
494
495extern "C" Expression*
496script_exp_function_max(Expression* left, Expression* right)
497{
498 return new Max_expression(left, right);
499}
500
501// Min function.
502
503class Min_expression : public Binary_expression
504{
505 public:
506 Min_expression(Expression* left, Expression* right)
507 : Binary_expression(left, right)
508 { }
509
510 uint64_t
511 value(const Expression_eval_info* eei)
512 { return std::min(this->left_value(eei), this->right_value(eei)); }
494e05f4
ILT
513
514 void
515 print(FILE* f) const
516 { this->print_function(f, "MIN"); }
e5756efb
ILT
517};
518
519extern "C" Expression*
520script_exp_function_min(Expression* left, Expression* right)
521{
522 return new Min_expression(left, right);
523}
524
525// Align function.
526
527class Align_expression : public Binary_expression
528{
529 public:
530 Align_expression(Expression* left, Expression* right)
531 : Binary_expression(left, right)
532 { }
533
534 uint64_t
535 value(const Expression_eval_info* eei)
536 {
537 uint64_t align = this->right_value(eei);
538 uint64_t value = this->left_value(eei);
539 if (align <= 1)
540 return value;
541 return ((value + align - 1) / align) * align;
542 }
494e05f4
ILT
543
544 void
545 print(FILE* f) const
546 { this->print_function(f, "ALIGN"); }
e5756efb
ILT
547};
548
549extern "C" Expression*
550script_exp_function_align(Expression* left, Expression* right)
551{
552 return new Align_expression(left, right);
553}
554
555// Assert function.
556
557class Assert_expression : public Unary_expression
558{
559 public:
560 Assert_expression(Expression* arg, const char* message, size_t length)
561 : Unary_expression(arg), message_(message, length)
562 { }
563
564 uint64_t
565 value(const Expression_eval_info* eei)
566 {
567 uint64_t value = this->arg_value(eei);
568 if (!value)
569 gold_error("%s", this->message_.c_str());
570 return value;
571 }
572
494e05f4
ILT
573 void
574 print(FILE* f) const
575 {
576 fprintf(f, "ASSERT(");
577 this->arg_print(f);
578 fprintf(f, ", %s)", this->message_.c_str());
579 }
580
e5756efb
ILT
581 private:
582 std::string message_;
583};
584
585extern "C" Expression*
586script_exp_function_assert(Expression* expr, const char* message,
587 size_t length)
588{
589 return new Assert_expression(expr, message, length);
590}
591
494e05f4
ILT
592// Addr function.
593
594class Addr_expression : public Expression
595{
596 public:
597 Addr_expression(const char* section_name, size_t section_name_len)
598 : section_name_(section_name, section_name_len)
599 { }
600
601 uint64_t
602 value(const Expression_eval_info*);
603
604 void
605 print(FILE* f) const
606 { fprintf(f, "ADDR(%s)", this->section_name_.c_str()); }
607
608 private:
609 std::string section_name_;
610};
611
612uint64_t
613Addr_expression::value(const Expression_eval_info* eei)
614{
615 const char* section_name = this->section_name_.c_str();
616 Output_section* os = eei->layout->find_output_section(section_name);
617 if (os == NULL)
618 {
619 gold_error("ADDR called on nonexistent output section '%s'",
620 section_name);
621 return 0;
622 }
a445fddf
ILT
623
624 // Note that the address of a section is an absolute address, and we
625 // should not clear *EEI->IS_ABSOLUTE here.
626
494e05f4
ILT
627 return os->address();
628}
629
630extern "C" Expression*
631script_exp_function_addr(const char* section_name, size_t section_name_len)
632{
633 return new Addr_expression(section_name, section_name_len);
634}
635
3802b2dd
ILT
636// CONSTANT. It would be nice if we could simply evaluate this
637// immediately and return an Integer_expression, but unfortunately we
638// don't know the target.
639
640class Constant_expression : public Expression
641{
642 public:
643 Constant_expression(const char* name, size_t length);
644
645 uint64_t
646 value(const Expression_eval_info*);
647
648 void
649 print(FILE* f) const;
650
651 private:
652 enum Constant_function
653 {
654 CONSTANT_MAXPAGESIZE,
655 CONSTANT_COMMONPAGESIZE
656 };
e5756efb 657
3802b2dd
ILT
658 Constant_function function_;
659};
660
661Constant_expression::Constant_expression(const char* name, size_t length)
662{
663 if (length == 11 && strncmp(name, "MAXPAGESIZE", length) == 0)
664 this->function_ = CONSTANT_MAXPAGESIZE;
665 else if (length == 14 && strncmp(name, "COMMONPAGESIZE", length) == 0)
666 this->function_ = CONSTANT_COMMONPAGESIZE;
667 else
668 {
669 std::string s(name, length);
670 gold_error(_("unknown constant %s"), s.c_str());
671 this->function_ = CONSTANT_MAXPAGESIZE;
672 }
673}
674
675uint64_t
676Constant_expression::value(const Expression_eval_info*)
677{
678 switch (this->function_)
679 {
680 case CONSTANT_MAXPAGESIZE:
681 return parameters->target()->abi_pagesize();
682 case CONSTANT_COMMONPAGESIZE:
683 return parameters->target()->common_pagesize();
684 default:
685 gold_unreachable();
686 }
687}
688
689void
690Constant_expression::print(FILE* f) const
691{
692 const char* name;
693 switch (this->function_)
694 {
695 case CONSTANT_MAXPAGESIZE:
696 name = "MAXPAGESIZE";
697 break;
698 case CONSTANT_COMMONPAGESIZE:
699 name = "COMMONPAGESIZE";
700 break;
701 default:
702 gold_unreachable();
703 }
704 fprintf(f, "CONSTANT(%s)", name);
705}
706
e5756efb 707extern "C" Expression*
3802b2dd 708script_exp_function_constant(const char* name, size_t length)
e5756efb 709{
3802b2dd 710 return new Constant_expression(name, length);
e5756efb
ILT
711}
712
3802b2dd
ILT
713// DATA_SEGMENT_ALIGN. FIXME: we don't implement this; we always fall
714// back to the general case.
715
e5756efb 716extern "C" Expression*
3802b2dd 717script_exp_function_data_segment_align(Expression* left, Expression*)
e5756efb 718{
3802b2dd
ILT
719 Expression* e1 = script_exp_function_align(script_exp_string(".", 1), left);
720 Expression* e2 = script_exp_binary_sub(left, script_exp_integer(1));
721 Expression* e3 = script_exp_binary_bitwise_and(script_exp_string(".", 1),
722 e2);
723 return script_exp_binary_add(e1, e3);
e5756efb
ILT
724}
725
3802b2dd
ILT
726// DATA_SEGMENT_RELRO. FIXME: This is not implemented.
727
e5756efb 728extern "C" Expression*
3802b2dd 729script_exp_function_data_segment_relro_end(Expression*, Expression* right)
e5756efb 730{
3802b2dd 731 return right;
e5756efb
ILT
732}
733
3802b2dd
ILT
734// DATA_SEGMENT_END. FIXME: This is not implemented.
735
e5756efb 736extern "C" Expression*
3802b2dd 737script_exp_function_data_segment_end(Expression* val)
e5756efb 738{
3802b2dd
ILT
739 return val;
740}
741
742// SIZEOF_HEADERS.
743
744class Sizeof_headers_expression : public Expression
745{
746 public:
747 Sizeof_headers_expression()
748 { }
749
750 uint64_t
751 value(const Expression_eval_info*);
752
753 void
754 print(FILE* f) const
755 { fprintf(f, "SIZEOF_HEADERS"); }
756};
757
758uint64_t
759Sizeof_headers_expression::value(const Expression_eval_info* eei)
760{
761 unsigned int ehdr_size;
762 unsigned int phdr_size;
763 if (parameters->get_size() == 32)
764 {
765 ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size;
766 phdr_size = elfcpp::Elf_sizes<32>::phdr_size;
767 }
768 else if (parameters->get_size() == 64)
769 {
770 ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size;
771 phdr_size = elfcpp::Elf_sizes<64>::phdr_size;
772 }
773 else
774 gold_unreachable();
775
776 return ehdr_size + phdr_size * eei->layout->expected_segment_count();
e5756efb
ILT
777}
778
e5756efb 779extern "C" Expression*
3802b2dd 780script_exp_function_sizeof_headers()
e5756efb 781{
3802b2dd 782 return new Sizeof_headers_expression();
e5756efb
ILT
783}
784
3802b2dd
ILT
785// Functions.
786
e5756efb 787extern "C" Expression*
3802b2dd 788script_exp_function_defined(const char*, size_t)
e5756efb 789{
3802b2dd 790 gold_fatal(_("DEFINED not implemented"));
e5756efb
ILT
791}
792
793extern "C" Expression*
3802b2dd 794script_exp_function_alignof(const char*, size_t)
e5756efb 795{
3802b2dd 796 gold_fatal(_("ALIGNOF not implemented"));
e5756efb
ILT
797}
798
799extern "C" Expression*
3802b2dd 800script_exp_function_sizeof(const char*, size_t)
e5756efb 801{
3802b2dd 802 gold_fatal(_("SIZEOF not implemented"));
e5756efb
ILT
803}
804
805extern "C" Expression*
3802b2dd 806script_exp_function_loadaddr(const char*, size_t)
e5756efb 807{
3802b2dd 808 gold_fatal(_("LOADADDR not implemented"));
e5756efb
ILT
809}
810
811extern "C" Expression*
3802b2dd 812script_exp_function_origin(const char*, size_t)
e5756efb 813{
3802b2dd 814 gold_fatal(_("ORIGIN not implemented"));
e5756efb
ILT
815}
816
817extern "C" Expression*
3802b2dd 818script_exp_function_length(const char*, size_t)
e5756efb 819{
3802b2dd 820 gold_fatal(_("LENGTH not implemented"));
e5756efb
ILT
821}
822
823extern "C" Expression*
3802b2dd 824script_exp_function_absolute(Expression*)
e5756efb 825{
3802b2dd 826 gold_fatal(_("ABSOLUTE not implemented"));
e5756efb
ILT
827}
828
829extern "C" Expression*
830script_exp_function_segment_start(const char*, size_t, Expression*)
831{
832 gold_fatal(_("SEGMENT_START not implemented"));
833}
834
835} // End namespace gold.
This page took 0.05969 seconds and 4 git commands to generate.