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.
43 exp_print_token (code
)
72 SIZEOF_HEADERS
,"SIZEOF_HEADERS",
84 SEARCH_DIR
,"SEARCH_DIR",
95 for (idx
= 0; table
[idx
].name
!= (char*)NULL
; idx
++) {
96 if (table
[idx
].code
== code
) {
97 fprintf(config
.map_file
, "%s", table
[idx
].name
);
101 /* Not in table, just print it alone */
102 fprintf(config
.map_file
, "%c",code
);
107 etree_value_type
*ptr
;
109 asection
*s
= ptr
->section
->bfd_section
;
110 ptr
->value
+= s
->vma
;
111 ptr
->section
= abs_output_section
;
114 static etree_value_type
118 etree_value_type
new;
120 new.section
= abs_output_section
;
127 lang_output_section_statement_type
*os
;
131 if (os
== (lang_output_section_statement_type
*)NULL
) {
132 einfo("%F%P: %s uses undefined section %s\n", op
, name
);
134 if (os
->processed
== false) {
135 einfo("%F%P: %s forward reference of section %s\n",op
, name
);
143 etree_type
*new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->value
)));
144 new->type
.node_code
= INT
;
145 new->value
.value
= value
;
146 new->type
.node_class
= etree_value
;
152 static etree_value_type
153 new_rel (value
, section
)
155 lang_output_section_statement_type
*section
;
157 etree_value_type
new;
160 new.section
= section
;
164 static etree_value_type
165 new_rel_from_section (value
, section
)
167 lang_output_section_statement_type
*section
;
169 etree_value_type
new;
172 new.section
= section
;
174 new.value
-= section
->bfd_section
->vma
;
179 static etree_value_type
180 fold_binary (tree
, current_section
, allocation_done
, dot
, dotp
)
182 lang_output_section_statement_type
*current_section
;
183 lang_phase_type allocation_done
;
187 etree_value_type result
;
189 result
= exp_fold_tree(tree
->binary
.lhs
, current_section
,
190 allocation_done
, dot
, dotp
);
192 etree_value_type other
;
193 other
= exp_fold_tree(tree
->binary
.rhs
,
195 allocation_done
, dot
,dotp
) ;
197 /* If values are from different sections, or this is an */
198 /* absolute expression, make both source args absolute */
199 if (result
.section
!= other
.section
||
200 current_section
== abs_output_section
)
206 switch (tree
->type
.node_code
)
209 /* Mod, both absolule*/
211 if (other
.value
== 0) {
212 einfo("%F%S %% by zero\n");
214 result
.value
= (int)result
.value
% (int)other
.value
;
217 if (other
.value
== 0) {
218 einfo("%F%S / by zero\n");
220 result
.value
= (int)result
.value
/ (int) other
.value
;
222 #define BOP(x,y) case x : result.value = result.value y other.value;break;
244 result
.valid
= false;
252 etree_value_type
new;
258 fold_name (tree
, current_section
, allocation_done
, dot
)
260 lang_output_section_statement_type
*current_section
;
261 lang_phase_type allocation_done
;
264 etree_value_type result
;
265 switch (tree
->type
.node_code
)
268 if (allocation_done
!= lang_first_phase_enum
)
270 result
= new_abs(bfd_sizeof_headers(output_bfd
,
271 config
.relocateable_output
));
275 result
.valid
= false;
280 ldsym_get_soft(tree
->name
.name
) != (ldsym_type
*)NULL
;
285 result
.valid
= false;
286 if (tree
->name
.name
[0] == '.' && tree
->name
.name
[1] == 0) {
288 if (allocation_done
!= lang_first_phase_enum
) {
289 result
= new_rel_from_section(dot
, current_section
);
296 if (allocation_done
== lang_final_phase_enum
) {
297 ldsym_type
*sy
= ldsym_get_soft(tree
->name
.name
);
300 asymbol
**sdefp
= sy
->sdefs_chain
;
303 asymbol
*sdef
= *sdefp
;
305 if (sdef
->section
== (asection
*)NULL
) {
306 /* This is an absolute symbol */
307 result
= new_abs(sdef
->value
);
312 lang_output_section_statement_type
*os
=
313 lang_output_section_statement_lookup(
314 sdef
->section
->output_section
->name
);
315 /* If the symbol is from a file which we are not
316 relocating (-R) then return an absolute for its
318 if (bfd_asymbol_bfd(sdef
)->usrdata
&&
319 ((lang_input_statement_type
*)(bfd_asymbol_bfd(sdef
)->usrdata
))->just_syms_flag
== true)
321 result
= new_abs(sdef
->value
+sdef
->section
->vma
);
325 result
= new_rel(sdef
->value
+ sdef
->section
->output_offset
, os
);
330 if (result
.valid
== false) {
331 einfo("%F%S: undefined symbol `%s' referenced in expression\n",
342 if (allocation_done
!= lang_first_phase_enum
) {
343 lang_output_section_statement_type
*os
=
344 lang_output_section_find(tree
->name
.name
);
345 check(os
,tree
->name
.name
,"ADDR");
346 result
= new_rel((bfd_vma
)0, os
);
353 if(allocation_done
!= lang_first_phase_enum
) {
354 lang_output_section_statement_type
*os
=
355 lang_output_section_find(tree
->name
.name
);
356 check(os
,tree
->name
.name
,"SIZEOF");
357 result
= new_abs((bfd_vma
)(os
->bfd_section
->_raw_size
));
372 exp_fold_tree (tree
, current_section
, allocation_done
, dot
, dotp
)
374 lang_output_section_statement_type
*current_section
;
375 lang_phase_type allocation_done
;
379 etree_value_type result
;
381 if (tree
== (etree_type
*)NULL
) {
382 result
.valid
= false;
385 switch (tree
->type
.node_class
)
388 result
= new_rel(tree
->value
.value
, current_section
);
391 result
= exp_fold_tree(tree
->unary
.child
,
393 allocation_done
, dot
, dotp
);
394 if (result
.valid
== true)
396 switch(tree
->type
.node_code
)
399 if (allocation_done
!= lang_first_phase_enum
) {
400 result
= new_rel_from_section(ALIGN_N(dot
,
406 result
.valid
= false;
410 if (allocation_done
!= lang_first_phase_enum
)
413 == (lang_output_section_statement_type
*)NULL
)
415 /* Outside a section, so it's all ok */
419 /* Inside a section, subtract the base of the section,
420 so when it's added again (in an assignment), everything comes out fine
422 result
.section
= abs_output_section
;
423 result
.value
-= current_section
->bfd_section
->vma
;
429 result
.valid
= false;
435 result
.value
= ~result
.value
;
439 result
.value
= !result
.value
;
443 result
.value
= -result
.value
;
446 if (allocation_done
==lang_allocating_phase_enum
) {
448 result
.value
= ALIGN_N(dot
, result
.value
);
451 /* Return next place aligned to value */
452 result
.valid
= false;
463 result
= exp_fold_tree(tree
->trinary
.cond
,
465 allocation_done
, dot
, dotp
);
467 result
= exp_fold_tree(result
.value
?
468 tree
->trinary
.lhs
:tree
->trinary
.rhs
,
470 allocation_done
, dot
, dotp
);
475 result
= fold_binary(tree
, current_section
, allocation_done
,
479 if (tree
->assign
.dst
[0] == '.' && tree
->assign
.dst
[1] == 0) {
480 /* Assignment to dot can only be done during allocation */
481 if (allocation_done
== lang_allocating_phase_enum
) {
482 result
= exp_fold_tree(tree
->assign
.src
,
484 lang_allocating_phase_enum
, dot
, dotp
);
485 if (result
.valid
== false) {
486 einfo("%F%S invalid assignment to location counter\n");
489 if (current_section
==
490 (lang_output_section_statement_type
*)NULL
) {
491 einfo("%F%S assignment to location counter invalid outside of SECTION\n");
494 bfd_vma nextdot
=result
.value
+
495 current_section
->bfd_section
->vma
;
497 einfo("%F%S cannot move location counter backwards (from %V to %V)\n", dot
, nextdot
);
507 ldsym_type
*sy
= ldsym_get(tree
->assign
.dst
);
509 /* If this symbol has just been created then we'll place it into
510 * a section of our choice
512 result
= exp_fold_tree(tree
->assign
.src
,
513 current_section
, allocation_done
,
519 /* Add this definition to script file */
522 def_ptr
= sy
->sdefs_chain
;
528 def_ptr
= (asymbol
**)stat_alloc((bfd_size_type
)(sizeof(asymbol
**)));
529 def
= (asymbol
*)bfd_make_empty_symbol(script_file
->the_bfd
);
534 sy
->sdefs_chain
= def_ptr
;
538 def
->value
= result
.value
;
540 def
->section
= result
.section
->bfd_section
;
541 def
->flags
|= BSF_GLOBAL
| BSF_EXPORT
;
544 def
->udata
= (PTR
)NULL
;
545 def
->name
= sy
->name
;
547 if (sy
->sdefs_chain
== 0)
548 enter_global_ref(def_ptr
, sy
->name
);
556 result
= fold_name(tree
, current_section
, allocation_done
, dot
);
559 einfo("%F%S need more of these %d\n",tree
->type
.node_class
);
569 exp_fold_tree_no_dot (tree
, current_section
, allocation_done
)
571 lang_output_section_statement_type
*current_section
;
572 lang_phase_type allocation_done
;
574 return exp_fold_tree(tree
, current_section
, allocation_done
, (bfd_vma
)
579 exp_binop (code
, lhs
, rhs
)
584 etree_type value
, *new;
587 value
.type
.node_code
= code
;
588 value
.binary
.lhs
= lhs
;
589 value
.binary
.rhs
= rhs
;
590 value
.type
.node_class
= etree_binary
;
591 r
= exp_fold_tree_no_dot(&value
,
593 lang_first_phase_enum
);
596 return exp_intop(r
.value
);
598 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->binary
)));
599 memcpy((char *)new, (char *)&value
, sizeof(new->binary
));
604 exp_trinop (code
, cond
, lhs
, rhs
)
610 etree_type value
, *new;
612 value
.type
.node_code
= code
;
613 value
.trinary
.lhs
= lhs
;
614 value
.trinary
.cond
= cond
;
615 value
.trinary
.rhs
= rhs
;
616 value
.type
.node_class
= etree_trinary
;
617 r
= exp_fold_tree_no_dot(&value
, (lang_output_section_statement_type
618 *)NULL
,lang_first_phase_enum
);
620 return exp_intop(r
.value
);
622 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->trinary
)));
623 memcpy((char *)new,(char *) &value
, sizeof(new->trinary
));
629 exp_unop (code
, child
)
633 etree_type value
, *new;
636 value
.unary
.type
.node_code
= code
;
637 value
.unary
.child
= child
;
638 value
.unary
.type
.node_class
= etree_unary
;
639 r
= exp_fold_tree_no_dot(&value
,abs_output_section
,
640 lang_first_phase_enum
);
642 return exp_intop(r
.value
);
644 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->unary
)));
645 memcpy((char *)new, (char *)&value
, sizeof(new->unary
));
651 exp_nameop (code
, name
)
655 etree_type value
, *new;
657 value
.name
.type
.node_code
= code
;
658 value
.name
.name
= name
;
659 value
.name
.type
.node_class
= etree_name
;
662 r
= exp_fold_tree_no_dot(&value
,
663 (lang_output_section_statement_type
*)NULL
,
664 lang_first_phase_enum
);
666 return exp_intop(r
.value
);
668 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->name
)));
669 memcpy((char *)new, (char *)&value
, sizeof(new->name
));
678 exp_assop (code
, dst
, src
)
683 etree_type value
, *new;
685 value
.assign
.type
.node_code
= code
;
688 value
.assign
.src
= src
;
689 value
.assign
.dst
= dst
;
690 value
.assign
.type
.node_class
= etree_assign
;
693 if (exp_fold_tree_no_dot(&value
, &result
)) {
694 return exp_intop(result
);
697 new = (etree_type
*)stat_alloc((bfd_size_type
)(sizeof(new->assign
)));
698 memcpy((char *)new, (char *)&value
, sizeof(new->assign
));
703 exp_print_tree (tree
)
706 switch (tree
->type
.node_class
) {
708 print_address(tree
->value
.value
);
713 if (tree
->assign
.dst
->sdefs
!= (asymbol
*)NULL
){
714 fprintf(config
.map_file
,"%s (%x) ",tree
->assign
.dst
->name
,
715 tree
->assign
.dst
->sdefs
->value
);
718 fprintf(config
.map_file
,"%s (UNDEFINED)",tree
->assign
.dst
->name
);
721 fprintf(config
.map_file
,"%s ",tree
->assign
.dst
);
722 exp_print_token(tree
->type
.node_code
);
723 exp_print_tree(tree
->assign
.src
);
726 fprintf(config
.map_file
,"(");
727 exp_print_tree(tree
->binary
.lhs
);
728 exp_print_token(tree
->type
.node_code
);
729 exp_print_tree(tree
->binary
.rhs
);
730 fprintf(config
.map_file
,")");
733 exp_print_tree(tree
->trinary
.cond
);
734 fprintf(config
.map_file
,"?");
735 exp_print_tree(tree
->trinary
.lhs
);
736 fprintf(config
.map_file
,":");
737 exp_print_tree(tree
->trinary
.rhs
);
740 exp_print_token(tree
->unary
.type
.node_code
);
741 if (tree
->unary
.child
)
744 fprintf(config
.map_file
,"(");
745 exp_print_tree(tree
->unary
.child
);
746 fprintf(config
.map_file
,")");
751 fprintf(config
.map_file
,"????????");
754 if (tree
->type
.node_code
== NAME
) {
755 fprintf(config
.map_file
,"%s", tree
->name
.name
);
758 exp_print_token(tree
->type
.node_code
);
760 fprintf(config
.map_file
,"(%s)", tree
->name
.name
);
773 exp_get_vma (tree
, def
, name
, allocation_done
)
777 lang_phase_type allocation_done
;
781 if (tree
!= (etree_type
*)NULL
) {
782 r
= exp_fold_tree_no_dot(tree
,
785 if (r
.valid
== false && name
) {
786 einfo("%F%S nonconstant expression for %s\n",name
);
796 exp_get_value_int (tree
,def
,name
, allocation_done
)
800 lang_phase_type allocation_done
;
802 return (int)exp_get_vma(tree
,(bfd_vma
)def
,name
, allocation_done
);