1 /* Copyright (C) 1991 Free Software Foundation, Inc.
3 This file is part of GLD, the Gnu Linker.
5 GLD is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 1, or (at your option)
10 GLD is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GLD; see the file COPYING. If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 * Written by Steve Chamberlain
27 * This module handles expression trees.
38 #include "ldgram.tab.h"
42 extern char *output_filename;
43 extern unsigned int undefined_global_sym_count;
44 extern unsigned int defined_global_sym_count;
45 extern bfd *output_bfd;
46 extern size_t largest_section;
47 extern lang_statement_list_type file_chain;
48 extern args_type command_line;
49 extern ld_config_type config;
51 extern lang_input_statement_type *script_file;
52 extern unsigned int defined_global_sym_count;
54 extern bfd_vma print_dot;
58 exp_print_token(outfile, code)
88 SIZEOF_HEADERS,"SIZEOF_HEADERS",
100 SEARCH_DIR,"SEARCH_DIR",
111 for (idx = 0; table[idx].name != (char*)NULL; idx++) {
112 if (table[idx].code == code) {
113 fprintf(outfile, "%s", table[idx].name);
117 /* Not in table, just print it alone */
118 fprintf(outfile, "%c",code);
123 etree_value_type *ptr;
125 if (ptr->section != (lang_output_section_statement_type *)NULL) {
126 asection *s = ptr->section->bfd_section;
127 ptr->value += s->vma;
128 ptr->section = (lang_output_section_statement_type *)NULL;
133 etree_value_type new_abs(value)
136 etree_value_type new;
138 new.section = (lang_output_section_statement_type *)NULL;
144 DEFUN(check, (os, name, op),
145 lang_output_section_statement_type *os AND
149 if (os == (lang_output_section_statement_type *)NULL) {
150 info("%F%P %s uses undefined section %s\n", op, name);
152 if (os->processed == false) {
153 info("%F%P %s forward reference of section %s\n",op, name);
157 etree_type *exp_intop(value)
160 etree_type *new = (etree_type *)ldmalloc(sizeof(new->value));
161 new->type.node_code = INT;
162 new->value.value = value;
163 new->type.node_class = etree_value;
170 etree_value_type new_rel(value, section)
172 lang_output_section_statement_type *section;
174 etree_value_type new;
177 new.section = section;
182 etree_value_type new_rel_from_section(value, section)
184 lang_output_section_statement_type *section;
186 etree_value_type new;
189 new.section = section;
190 if (new.section != (lang_output_section_statement_type *)NULL) {
191 new.value -= section->bfd_section->vma;
196 static etree_value_type
197 fold_binary(tree, current_section, allocation_done, dot, dotp)
199 lang_output_section_statement_type *current_section;
200 lang_phase_type allocation_done;
204 etree_value_type result;
206 result = exp_fold_tree(tree->binary.lhs, current_section,
207 allocation_done, dot, dotp);
209 etree_value_type other;
210 other = exp_fold_tree(tree->binary.rhs,
212 allocation_done, dot,dotp) ;
214 /* If values are from different sections, or this is an */
215 /* absolute expression, make both source args absolute */
216 if (result.section != other.section ||
217 current_section == (lang_output_section_statement_type *)NULL) {
223 switch (tree->type.node_code)
226 /* Mod, both absolule*/
228 if (other.value == 0) {
229 info("%F%S % by zero\n");
231 result.value %= other.value;
234 if (other.value == 0) {
235 info("%F%S / by zero\n");
237 result.value /= other.value;
239 #define BOP(x,y) case x : result.value = result.value y other.value;break;
261 result.valid = false;
266 etree_value_type invalid()
268 etree_value_type new;
273 etree_value_type fold_name(tree, current_section, allocation_done, dot)
275 lang_output_section_statement_type *current_section;
276 lang_phase_type allocation_done;
280 etree_value_type result;
281 switch (tree->type.node_code)
284 if (allocation_done != lang_first_phase_enum)
286 result = new_abs(bfd_sizeof_headers(output_bfd,
287 config.relocateable_output));
291 result.valid = false;
296 ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL;
301 result.valid = false;
302 if (tree->name.name[0] == '.' && tree->name.name[1] == 0) {
304 if (allocation_done != lang_first_phase_enum) {
305 result = new_rel_from_section(dot, current_section);
312 if (allocation_done == lang_final_phase_enum) {
313 ldsym_type *sy = ldsym_get_soft(tree->name.name);
316 asymbol **sdefp = sy->sdefs_chain;
319 asymbol *sdef = *sdefp;
320 if (sdef->section == (asection *)NULL) {
321 /* This is an absolute symbol */
322 result = new_abs(sdef->value);
325 lang_output_section_statement_type *os =
326 lang_output_section_statement_lookup(
327 sdef->section->output_section->name);
328 /* If the symbol is from a file which we are not
329 relocating (-R) then return an absolute for its
331 if (sdef->the_bfd->usrdata &&
332 ((lang_input_statement_type*)(sdef->the_bfd->usrdata))->just_syms_flag == true)
334 result = new_abs(sdef->value + (sdef->section ?
335 sdef->section->vma : 0));
338 result = new_rel(sdef->value + sdef->section->output_offset, os);
343 if (result.valid == false) {
344 info("%F%S: undefined symbol `%s' referenced in expression.\n",
355 if (allocation_done != lang_first_phase_enum) {
356 lang_output_section_statement_type *os =
357 lang_output_section_find(tree->name.name);
358 check(os,tree->name.name,"ADDR");
359 result = new_rel((bfd_vma)0, os);
366 if(allocation_done != lang_first_phase_enum) {
367 lang_output_section_statement_type *os =
368 lang_output_section_find(tree->name.name);
369 check(os,tree->name.name,"SIZEOF");
370 result = new_abs((bfd_vma)(os->bfd_section->size));
384 etree_value_type exp_fold_tree(tree, current_section, allocation_done,
387 lang_output_section_statement_type *current_section;
388 lang_phase_type allocation_done;
392 etree_value_type result;
394 if (tree == (etree_type *)NULL) {
395 result.valid = false;
398 switch (tree->type.node_class)
401 result = new_rel(tree->value.value, current_section);
404 result = exp_fold_tree(tree->unary.child,
406 allocation_done, dot, dotp);
407 if (result.valid == true)
409 switch(tree->type.node_code)
412 if (allocation_done != lang_first_phase_enum) {
413 result = new_rel_from_section(ALIGN(dot,
419 result.valid = false;
424 result.value = ~result.value;
428 result.value = !result.value;
432 result.value = -result.value;
435 if (allocation_done ==lang_allocating_phase_enum) {
437 result.value = ALIGN(dot, result.value);
440 /* Return next place aligned to value */
441 result.valid = false;
452 result = exp_fold_tree(tree->trinary.cond,
454 allocation_done, dot, dotp);
456 result = exp_fold_tree(result.value ?
457 tree->trinary.lhs:tree->trinary.rhs,
459 allocation_done, dot, dotp);
464 result = fold_binary(tree, current_section, allocation_done,
468 if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) {
469 /* Assignment to dot can only be done during allocation */
470 if (allocation_done == lang_allocating_phase_enum) {
471 result = exp_fold_tree(tree->assign.src,
473 lang_allocating_phase_enum, dot, dotp);
474 if (result.valid == false) {
475 info("%F%S invalid assignment to location counter\n");
478 if (current_section ==
479 (lang_output_section_statement_type *)NULL) {
480 info("%F%S assignment to location counter invalid outside of SECTION\n");
483 unsigned long nextdot =result.value +
484 current_section->bfd_section->vma;
486 info("%F%S cannot move location counter backwards");
496 ldsym_type *sy = ldsym_get(tree->assign.dst);
498 /* If this symbol has just been created then we'll place it into
499 * a section of our choice
501 result = exp_fold_tree(tree->assign.src,
502 current_section, allocation_done,
507 asymbol **def_ptr = (asymbol **)ldmalloc(sizeof(asymbol **));
508 /* Add this definition to script file */
509 def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd);
513 def->value = result.value;
514 if (result.section !=
515 (lang_output_section_statement_type *)NULL) {
516 if (current_section !=
517 (lang_output_section_statement_type *)NULL) {
519 def->section = result.section->bfd_section;
520 def->flags = BSF_GLOBAL | BSF_EXPORT;
523 /* Force to absolute */
524 def->value += result.section->bfd_section->vma;
525 def->section = (asection *)NULL;
526 def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
532 def->section = (asection *)NULL;
533 def->flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
537 def->udata = (PTR)NULL;
538 def->name = sy->name;
539 Q_enter_global_ref(def_ptr);
547 result = fold_name(tree, current_section, allocation_done, dot);
550 info("%F%S Need more of these %d",tree->type.node_class );
559 etree_value_type exp_fold_tree_no_dot(tree, current_section, allocation_done)
561 lang_output_section_statement_type *current_section;
562 lang_phase_type allocation_done;
564 return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
569 exp_binop(code, lhs, rhs)
574 etree_type value, *new;
577 value.type.node_code = code;
578 value.binary.lhs = lhs;
579 value.binary.rhs = rhs;
580 value.type.node_class = etree_binary;
581 r = exp_fold_tree_no_dot(&value, (lang_output_section_statement_type *)NULL,
582 lang_first_phase_enum );
585 return exp_intop(r.value);
587 new = (etree_type *)ldmalloc(sizeof(new->binary));
588 memcpy((char *)new, (char *)&value, sizeof(new->binary));
593 exp_trinop(code, cond, lhs, rhs)
599 etree_type value, *new;
601 value.type.node_code = code;
602 value.trinary.lhs = lhs;
603 value.trinary.cond = cond;
604 value.trinary.rhs = rhs;
605 value.type.node_class = etree_trinary;
606 r= exp_fold_tree_no_dot(&value, (lang_output_section_statement_type
607 *)NULL,lang_first_phase_enum);
609 return exp_intop(r.value);
611 new = (etree_type *)ldmalloc(sizeof(new->trinary));
612 memcpy((char *)new,(char *) &value, sizeof(new->trinary));
618 exp_unop(code, child)
622 etree_type value, *new;
625 value.unary.type.node_code = code;
626 value.unary.child = child;
627 value.unary.type.node_class = etree_unary;
628 r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
629 lang_first_phase_enum);
631 return exp_intop(r.value);
633 new = (etree_type *)ldmalloc(sizeof(new->unary));
634 memcpy((char *)new, (char *)&value, sizeof(new->unary));
640 exp_nameop(code, name)
645 etree_type value, *new;
648 value.name.type.node_code = code;
649 value.name.name = name;
650 value.name.type.node_class = etree_name;
653 r = exp_fold_tree_no_dot(&value,(lang_output_section_statement_type *)NULL,
654 lang_first_phase_enum);
656 return exp_intop(r.value);
658 new = (etree_type *)ldmalloc(sizeof(new->name));
659 memcpy((char *)new, (char *)&value, sizeof(new->name));
668 exp_assop(code, dst, src)
673 etree_type value, *new;
675 value.assign.type.node_code = code;
678 value.assign.src = src;
679 value.assign.dst = dst;
680 value.assign.type.node_class = etree_assign;
683 if (exp_fold_tree_no_dot(&value, &result)) {
684 return exp_intop(result);
687 new = (etree_type*)ldmalloc(sizeof(new->assign));
688 memcpy((char *)new, (char *)&value, sizeof(new->assign));
693 exp_print_tree(outfile, tree)
697 switch (tree->type.node_class) {
699 fprintf(outfile,"0x%08lx",(bfd_vma)(tree->value.value));
703 if (tree->assign.dst->sdefs != (asymbol *)NULL){
704 fprintf(outfile,"%s (%x) ",tree->assign.dst->name,
705 tree->assign.dst->sdefs->value);
708 fprintf(outfile,"%s (UNDEFINED)",tree->assign.dst->name);
711 fprintf(outfile,"%s ",tree->assign.dst);
712 exp_print_token(outfile,tree->type.node_code);
713 exp_print_tree(outfile,tree->assign.src);
716 exp_print_tree(outfile,tree->binary.lhs);
717 exp_print_token(outfile,tree->type.node_code);
718 exp_print_tree(outfile,tree->binary.rhs);
721 exp_print_tree(outfile,tree->trinary.cond);
722 fprintf(outfile,"?");
723 exp_print_tree(outfile,tree->trinary.lhs);
724 fprintf(outfile,":");
725 exp_print_tree(outfile,tree->trinary.rhs);
728 exp_print_token(outfile,tree->unary.type.node_code);
729 fprintf(outfile,"(");
730 exp_print_tree(outfile,tree->unary.child);
731 fprintf(outfile,")");
734 fprintf(outfile,"????????");
737 if (tree->type.node_code == NAME) {
738 fprintf(outfile,"%s", tree->name.name);
741 exp_print_token(outfile,tree->type.node_code);
742 fprintf(outfile,"(%s)", tree->name.name);
755 exp_get_vma(tree, def, name, allocation_done)
759 lang_phase_type allocation_done;
763 if (tree != (etree_type *)NULL) {
764 r = exp_fold_tree_no_dot(tree,
765 (lang_output_section_statement_type *)NULL,
767 if (r.valid == false && name) {
768 info("%F%S Nonconstant expression for %s\n",name);
778 exp_get_value_int(tree,def,name, allocation_done)
782 lang_phase_type allocation_done;
784 return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);