1 /* This module handles expression trees.
2 Copyright (C) 1991 Free Software Foundation, Inc.
3 Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com).
5 This file is part of GLD, the Gnu Linker.
7 GLD is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GLD is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GLD; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 This module is in charge of working out the contents of expressions.
24 It has to keep track of the relative/absness of a symbol etc. This is
25 done by keeping all values in a struct (an etree_value_type) which
26 contains a value, a section to which it is relative and a valid bit.
42 extern bfd
*output_bfd
;
43 extern bfd_size_type largest_section
;
44 extern lang_statement_list_type file_chain
;
45 extern ld_config_type config
;
47 extern lang_input_statement_type
*script_file
;
48 extern lang_output_section_statement_type
*abs_output_section
;
49 extern bfd_vma print_dot
;
53 exp_print_token (code
)
82 SIZEOF_HEADERS
,"SIZEOF_HEADERS",
94 SEARCH_DIR
,"SEARCH_DIR",
105 for (idx
= 0; table
[idx
].name
!= (char*)NULL
; idx
++) {
106 if (table
[idx
].code
== code
) {
107 fprintf(config
.map_file
, "%s", table
[idx
].name
);
111 /* Not in table, just print it alone */
112 fprintf(config
.map_file
, "%c",code
);
117 etree_value_type
*ptr
;
119 asection
*s
= ptr
->section
->bfd_section
;
120 ptr
->value
+= s
->vma
;
121 ptr
->section
= abs_output_section
;
124 static etree_value_type
128 etree_value_type
new;
130 new.section
= abs_output_section
;
137 lang_output_section_statement_type
*os
;
141 if (os
== (lang_output_section_statement_type
*)NULL
) {
142 einfo("%F%P %s uses undefined section %s\n", op
, name
);
144 if (os
->processed
== false) {
145 einfo("%F%P %s forward reference of section %s\n",op
, name
);
153 etree_type
*new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->value
)));
154 new->type
.node_code
= INT
;
155 new->value
.value
= value
;
156 new->type
.node_class
= etree_value
;
162 static etree_value_type
163 new_rel (value
, section
)
165 lang_output_section_statement_type
*section
;
167 etree_value_type
new;
170 new.section
= section
;
174 static etree_value_type
175 new_rel_from_section (value
, section
)
177 lang_output_section_statement_type
*section
;
179 etree_value_type
new;
182 new.section
= section
;
184 new.value
-= section
->bfd_section
->vma
;
189 static etree_value_type
190 fold_binary (tree
, current_section
, allocation_done
, dot
, dotp
)
192 lang_output_section_statement_type
*current_section
;
193 lang_phase_type allocation_done
;
197 etree_value_type result
;
199 result
= exp_fold_tree(tree
->binary
.lhs
, current_section
,
200 allocation_done
, dot
, dotp
);
202 etree_value_type other
;
203 other
= exp_fold_tree(tree
->binary
.rhs
,
205 allocation_done
, dot
,dotp
) ;
207 /* If values are from different sections, or this is an */
208 /* absolute expression, make both source args absolute */
209 if (result
.section
!= other
.section
||
210 current_section
== abs_output_section
)
216 switch (tree
->type
.node_code
)
219 /* Mod, both absolule*/
221 if (other
.value
== 0) {
222 einfo("%F%S % by zero\n");
224 result
.value
= (int)result
.value
% (int)other
.value
;
227 if (other
.value
== 0) {
228 einfo("%F%S / by zero\n");
230 result
.value
= (int)result
.value
/ (int) other
.value
;
232 #define BOP(x,y) case x : result.value = result.value y other.value;break;
254 result
.valid
= false;
262 etree_value_type
new;
268 fold_name (tree
, current_section
, allocation_done
, dot
)
270 lang_output_section_statement_type
*current_section
;
271 lang_phase_type allocation_done
;
274 etree_value_type result
;
275 switch (tree
->type
.node_code
)
278 if (allocation_done
!= lang_first_phase_enum
)
280 result
= new_abs(bfd_sizeof_headers(output_bfd
,
281 config
.relocateable_output
));
285 result
.valid
= false;
290 ldsym_get_soft(tree
->name
.name
) != (ldsym_type
*)NULL
;
295 result
.valid
= false;
296 if (tree
->name
.name
[0] == '.' && tree
->name
.name
[1] == 0) {
298 if (allocation_done
!= lang_first_phase_enum
) {
299 result
= new_rel_from_section(dot
, current_section
);
306 if (allocation_done
== lang_final_phase_enum
) {
307 ldsym_type
*sy
= ldsym_get_soft(tree
->name
.name
);
310 asymbol
**sdefp
= sy
->sdefs_chain
;
313 asymbol
*sdef
= *sdefp
;
315 if (sdef
->section
== (asection
*)NULL
) {
316 /* This is an absolute symbol */
317 result
= new_abs(sdef
->value
);
322 lang_output_section_statement_type
*os
=
323 lang_output_section_statement_lookup(
324 sdef
->section
->output_section
->name
);
325 /* If the symbol is from a file which we are not
326 relocating (-R) then return an absolute for its
328 if (bfd_asymbol_bfd(sdef
)->usrdata
&&
329 ((lang_input_statement_type
*)(bfd_asymbol_bfd(sdef
)->usrdata
))->just_syms_flag
== true)
331 result
= new_abs(sdef
->value
+sdef
->section
->vma
);
335 result
= new_rel(sdef
->value
+ sdef
->section
->output_offset
, os
);
340 if (result
.valid
== false) {
341 einfo("%F%S: undefined symbol `%s' referenced in expression.\n",
352 if (allocation_done
!= lang_first_phase_enum
) {
353 lang_output_section_statement_type
*os
=
354 lang_output_section_find(tree
->name
.name
);
355 check(os
,tree
->name
.name
,"ADDR");
356 result
= new_rel((bfd_vma
)0, os
);
363 if(allocation_done
!= lang_first_phase_enum
) {
364 lang_output_section_statement_type
*os
=
365 lang_output_section_find(tree
->name
.name
);
366 check(os
,tree
->name
.name
,"SIZEOF");
367 result
= new_abs((bfd_vma
)(os
->bfd_section
->_raw_size
));
382 exp_fold_tree (tree
, current_section
, allocation_done
, dot
, dotp
)
384 lang_output_section_statement_type
*current_section
;
385 lang_phase_type allocation_done
;
389 etree_value_type result
;
391 if (tree
== (etree_type
*)NULL
) {
392 result
.valid
= false;
395 switch (tree
->type
.node_class
)
398 result
= new_rel(tree
->value
.value
, current_section
);
401 result
= exp_fold_tree(tree
->unary
.child
,
403 allocation_done
, dot
, dotp
);
404 if (result
.valid
== true)
406 switch(tree
->type
.node_code
)
409 if (allocation_done
!= lang_first_phase_enum
) {
410 result
= new_rel_from_section(ALIGN_N(dot
,
416 result
.valid
= false;
420 if (allocation_done
!= lang_first_phase_enum
)
423 == (lang_output_section_statement_type
*)NULL
)
425 /* Outside a section, so it's all ok */
429 /* Inside a section, subtract the base of the section,
430 so when it's added again (in an assignment), everything comes out fine
432 result
.section
= abs_output_section
;
433 result
.value
-= current_section
->bfd_section
->vma
;
439 result
.valid
= false;
445 result
.value
= ~result
.value
;
449 result
.value
= !result
.value
;
453 result
.value
= -result
.value
;
456 if (allocation_done
==lang_allocating_phase_enum
) {
458 result
.value
= ALIGN_N(dot
, result
.value
);
461 /* Return next place aligned to value */
462 result
.valid
= false;
473 result
= exp_fold_tree(tree
->trinary
.cond
,
475 allocation_done
, dot
, dotp
);
477 result
= exp_fold_tree(result
.value
?
478 tree
->trinary
.lhs
:tree
->trinary
.rhs
,
480 allocation_done
, dot
, dotp
);
485 result
= fold_binary(tree
, current_section
, allocation_done
,
489 if (tree
->assign
.dst
[0] == '.' && tree
->assign
.dst
[1] == 0) {
490 /* Assignment to dot can only be done during allocation */
491 if (allocation_done
== lang_allocating_phase_enum
) {
492 result
= exp_fold_tree(tree
->assign
.src
,
494 lang_allocating_phase_enum
, dot
, dotp
);
495 if (result
.valid
== false) {
496 einfo("%F%S invalid assignment to location counter\n");
499 if (current_section
==
500 (lang_output_section_statement_type
*)NULL
) {
501 einfo("%F%S assignment to location counter invalid outside of SECTION\n");
504 bfd_vma nextdot
=result
.value
+
505 current_section
->bfd_section
->vma
;
507 einfo("%F%S cannot move location counter backwards (from %V to %V)\n", dot
, nextdot
);
517 ldsym_type
*sy
= ldsym_get(tree
->assign
.dst
);
519 /* If this symbol has just been created then we'll place it into
520 * a section of our choice
522 result
= exp_fold_tree(tree
->assign
.src
,
523 current_section
, allocation_done
,
529 /* Add this definition to script file */
532 def_ptr
= sy
->sdefs_chain
;
538 def_ptr
= (asymbol
**)stat_alloc((bfd_size_type
)(sizeof(asymbol
**)));
539 def
= (asymbol
*)bfd_make_empty_symbol(script_file
->the_bfd
);
544 sy
->sdefs_chain
= def_ptr
;
548 def
->value
= result
.value
;
550 def
->section
= result
.section
->bfd_section
;
551 def
->flags
|= BSF_GLOBAL
| BSF_EXPORT
;
554 def
->udata
= (PTR
)NULL
;
555 def
->name
= sy
->name
;
557 if (sy
->sdefs_chain
== 0)
558 enter_global_ref(def_ptr
, sy
->name
);
566 result
= fold_name(tree
, current_section
, allocation_done
, dot
);
569 einfo("%F%S Need more of these %d\n",tree
->type
.node_class
);
579 exp_fold_tree_no_dot (tree
, current_section
, allocation_done
)
581 lang_output_section_statement_type
*current_section
;
582 lang_phase_type allocation_done
;
584 return exp_fold_tree(tree
, current_section
, allocation_done
, (bfd_vma
)
589 exp_binop (code
, lhs
, rhs
)
594 etree_type value
, *new;
597 value
.type
.node_code
= code
;
598 value
.binary
.lhs
= lhs
;
599 value
.binary
.rhs
= rhs
;
600 value
.type
.node_class
= etree_binary
;
601 r
= exp_fold_tree_no_dot(&value
,
603 lang_first_phase_enum
);
606 return exp_intop(r
.value
);
608 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->binary
)));
609 memcpy((char *)new, (char *)&value
, sizeof(new->binary
));
614 exp_trinop (code
, cond
, lhs
, rhs
)
620 etree_type value
, *new;
622 value
.type
.node_code
= code
;
623 value
.trinary
.lhs
= lhs
;
624 value
.trinary
.cond
= cond
;
625 value
.trinary
.rhs
= rhs
;
626 value
.type
.node_class
= etree_trinary
;
627 r
= exp_fold_tree_no_dot(&value
, (lang_output_section_statement_type
628 *)NULL
,lang_first_phase_enum
);
630 return exp_intop(r
.value
);
632 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->trinary
)));
633 memcpy((char *)new,(char *) &value
, sizeof(new->trinary
));
639 exp_unop (code
, child
)
643 etree_type value
, *new;
646 value
.unary
.type
.node_code
= code
;
647 value
.unary
.child
= child
;
648 value
.unary
.type
.node_class
= etree_unary
;
649 r
= exp_fold_tree_no_dot(&value
,abs_output_section
,
650 lang_first_phase_enum
);
652 return exp_intop(r
.value
);
654 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->unary
)));
655 memcpy((char *)new, (char *)&value
, sizeof(new->unary
));
661 exp_nameop (code
, name
)
665 etree_type value
, *new;
667 value
.name
.type
.node_code
= code
;
668 value
.name
.name
= name
;
669 value
.name
.type
.node_class
= etree_name
;
672 r
= exp_fold_tree_no_dot(&value
,
673 (lang_output_section_statement_type
*)NULL
,
674 lang_first_phase_enum
);
676 return exp_intop(r
.value
);
678 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->name
)));
679 memcpy((char *)new, (char *)&value
, sizeof(new->name
));
688 exp_assop (code
, dst
, src
)
693 etree_type value
, *new;
695 value
.assign
.type
.node_code
= code
;
698 value
.assign
.src
= src
;
699 value
.assign
.dst
= dst
;
700 value
.assign
.type
.node_class
= etree_assign
;
703 if (exp_fold_tree_no_dot(&value
, &result
)) {
704 return exp_intop(result
);
707 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->assign
)));
708 memcpy((char *)new, (char *)&value
, sizeof(new->assign
));
713 exp_print_tree (tree
)
716 switch (tree
->type
.node_class
) {
718 print_address(tree
->value
.value
);
723 if (tree
->assign
.dst
->sdefs
!= (asymbol
*)NULL
){
724 fprintf(config
.map_file
,"%s (%x) ",tree
->assign
.dst
->name
,
725 tree
->assign
.dst
->sdefs
->value
);
728 fprintf(config
.map_file
,"%s (UNDEFINED)",tree
->assign
.dst
->name
);
731 fprintf(config
.map_file
,"%s ",tree
->assign
.dst
);
732 exp_print_token(tree
->type
.node_code
);
733 exp_print_tree(tree
->assign
.src
);
736 fprintf(config
.map_file
,"(");
737 exp_print_tree(tree
->binary
.lhs
);
738 exp_print_token(tree
->type
.node_code
);
739 exp_print_tree(tree
->binary
.rhs
);
740 fprintf(config
.map_file
,")");
743 exp_print_tree(tree
->trinary
.cond
);
744 fprintf(config
.map_file
,"?");
745 exp_print_tree(tree
->trinary
.lhs
);
746 fprintf(config
.map_file
,":");
747 exp_print_tree(tree
->trinary
.rhs
);
750 exp_print_token(tree
->unary
.type
.node_code
);
751 if (tree
->unary
.child
)
754 fprintf(config
.map_file
,"(");
755 exp_print_tree(tree
->unary
.child
);
756 fprintf(config
.map_file
,")");
761 fprintf(config
.map_file
,"????????");
764 if (tree
->type
.node_code
== NAME
) {
765 fprintf(config
.map_file
,"%s", tree
->name
.name
);
768 exp_print_token(tree
->type
.node_code
);
770 fprintf(config
.map_file
,"(%s)", tree
->name
.name
);
783 exp_get_vma (tree
, def
, name
, allocation_done
)
787 lang_phase_type allocation_done
;
791 if (tree
!= (etree_type
*)NULL
) {
792 r
= exp_fold_tree_no_dot(tree
,
795 if (r
.valid
== false && name
) {
796 einfo("%F%S Nonconstant expression for %s\n",name
);
806 exp_get_value_int (tree
,def
,name
, allocation_done
)
810 lang_phase_type allocation_done
;
812 return (int)exp_get_vma(tree
,(bfd_vma
)def
,name
, allocation_done
);