ldexp.c revision 33965
115920Speter/* This module handles expression trees.
215920SpeterCopyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
315920SpeterWritten by Steve Chamberlain of Cygnus Support (sac@cygnus.com).
415920Speter
515920SpeterThis file is part of GLD, the Gnu Linker.
615920Speter
715920SpeterGLD is free software; you can redistribute it and/or modify
815920Speterit under the terms of the GNU General Public License as published by
915920Speterthe Free Software Foundation; either version 2, or (at your option)
1015920Speterany later version.
1115920Speter
1215920SpeterGLD is distributed in the hope that it will be useful,
1315920Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1415920SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1515920SpeterGNU General Public License for more details.
1615920Speter
1715920SpeterYou should have received a copy of the GNU General Public License
1815920Speteralong with GLD; see the file COPYING.  If not, write to
1915920Speterthe Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2015920Speter
2115920Speter/*
2215920SpeterThis module is in charge of working out the contents of expressions.
2315920Speter
2415920SpeterIt has to keep track of the relative/absness of a symbol etc. This is
2515920Speterdone by keeping all values in a struct (an etree_value_type) which
2615920Spetercontains a value, a section to which it is relative and a valid bit.
2715920Speter
2815920Speter*/
2915920Speter
3015920Speter
3115920Speter#include "bfd.h"
3215920Speter#include "sysdep.h"
3315920Speter#include "bfdlink.h"
3415920Speter
3515920Speter#include "ld.h"
3615920Speter#include "ldmain.h"
3715920Speter#include "ldmisc.h"
3850471Speter#include "ldexp.h"
3915920Speter#include "ldgram.h"
4015920Speter#include "ldlang.h"
4115920Speter
4215920Speterstatic void exp_print_token PARAMS ((token_code_type code));
4315920Speterstatic void make_abs PARAMS ((etree_value_type *ptr));
4415920Speterstatic etree_value_type new_abs PARAMS ((bfd_vma value));
4515920Speterstatic void check PARAMS ((lang_output_section_statement_type *os,
4615920Speter			   const char *name, const char *op));
4715920Speterstatic etree_value_type new_rel
4815920Speter  PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
4915920Speterstatic etree_value_type new_rel_from_section
5015920Speter  PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
5115920Speterstatic etree_value_type fold_binary
5215920Speter  PARAMS ((etree_type *tree,
5315920Speter	   lang_output_section_statement_type *current_section,
5415920Speter	   lang_phase_type allocation_done,
5515920Speter	   bfd_vma dot, bfd_vma *dotp));
5615920Speterstatic etree_value_type fold_name
5715920Speter  PARAMS ((etree_type *tree,
5815920Speter	   lang_output_section_statement_type *current_section,
5915920Speter	   lang_phase_type allocation_done,
6015920Speter	   bfd_vma dot));
6115920Speterstatic etree_value_type exp_fold_tree_no_dot
6215920Speter  PARAMS ((etree_type *tree,
6315920Speter	   lang_output_section_statement_type *current_section,
6415920Speter	   lang_phase_type allocation_done));
6515920Speter
6615920Speterstatic void
6715920Speterexp_print_token (code)
6815920Speter     token_code_type code;
6915920Speter{
7015920Speter  static CONST struct
7115920Speter    {
7215920Speter      token_code_type code;
7315920Speter      char *name;
7415920Speter    } table[] =
7515920Speter      {
7618614Speter	{ INT,	"int" },
7715920Speter	{ REL, "relocateable" },
7815920Speter	{ NAME,"NAME" },
7915920Speter	{ PLUSEQ,"+=" },
8015920Speter	{ MINUSEQ,"-=" },
8115920Speter	{ MULTEQ,"*=" },
8215920Speter	{ DIVEQ,"/=" },
8315920Speter	{ LSHIFTEQ,"<<=" },
8415920Speter	{ RSHIFTEQ,">>=" },
8525235Ssteve	{ ANDEQ,"&=" },
8615920Speter	{ OREQ,"|=" },
8715920Speter	{ OROR,"||" },
8815920Speter	{ ANDAND,"&&" },
8915920Speter	{ EQ,"==" },
9015920Speter	{ NE,"!=" },
9115920Speter	{ LE,"<=" },
9215920Speter	{ GE,">=" },
93	{ LSHIFT,"<<" },
94	{ RSHIFT,">>=" },
95	{ ALIGN_K,"ALIGN" },
96	{ BLOCK,"BLOCK" },
97	{ SECTIONS,"SECTIONS" },
98	{ SIZEOF_HEADERS,"SIZEOF_HEADERS" },
99	{ NEXT,"NEXT" },
100	{ SIZEOF,"SIZEOF" },
101	{ ADDR,"ADDR" },
102	{ LOADADDR,"LOADADDR" },
103	{ MEMORY,"MEMORY" },
104	{ DEFINED,"DEFINED" },
105	{ TARGET_K,"TARGET" },
106	{ SEARCH_DIR,"SEARCH_DIR" },
107	{ MAP,"MAP" },
108	{ QUAD,"QUAD" },
109	{ LONG,"LONG" },
110	{ SHORT,"SHORT" },
111	{ BYTE,"BYTE" },
112	{ ENTRY,"ENTRY" },
113	{ 0,(char *)NULL }
114      };
115  unsigned int idx;
116
117  for (idx = 0; table[idx].name != (char*)NULL; idx++) {
118    if (table[idx].code == code) {
119      fprintf(config.map_file, "%s", table[idx].name);
120      return;
121    }
122  }
123  /* Not in table, just print it alone */
124  fprintf(config.map_file, "%c",code);
125}
126
127static void
128make_abs (ptr)
129     etree_value_type *ptr;
130{
131    asection *s = ptr->section->bfd_section;
132    ptr->value += s->vma;
133    ptr->section = abs_output_section;
134}
135
136static etree_value_type
137new_abs (value)
138     bfd_vma value;
139{
140  etree_value_type new;
141  new.valid = true;
142  new.section = abs_output_section;
143  new.value = value;
144  return new;
145}
146
147static void
148check (os, name, op)
149     lang_output_section_statement_type *os;
150     const char *name;
151     const char *op;
152{
153  if (os == NULL)
154    einfo ("%F%P: %s uses undefined section %s\n", op, name);
155  if (! os->processed)
156    einfo ("%F%P: %s forward reference of section %s\n", op, name);
157}
158
159etree_type *
160exp_intop (value)
161     bfd_vma value;
162{
163  etree_type *new = (etree_type *) stat_alloc(sizeof(new->value));
164  new->type.node_code = INT;
165  new->value.value = value;
166  new->type.node_class = etree_value;
167  return new;
168
169}
170
171/* Build an expression representing an unnamed relocateable value.  */
172
173etree_type *
174exp_relop (section, value)
175     asection *section;
176     bfd_vma value;
177{
178  etree_type *new = (etree_type *) stat_alloc (sizeof (new->rel));
179  new->type.node_code = REL;
180  new->type.node_class = etree_rel;
181  new->rel.section = section;
182  new->rel.value = value;
183  return new;
184}
185
186static etree_value_type
187new_rel (value, section)
188     bfd_vma value;
189     lang_output_section_statement_type *section;
190{
191  etree_value_type new;
192  new.valid = true;
193  new.value = value;
194  new.section = section;
195  return new;
196}
197
198static etree_value_type
199new_rel_from_section (value, section)
200     bfd_vma value;
201     lang_output_section_statement_type *section;
202{
203  etree_value_type new;
204  new.valid = true;
205  new.value = value;
206  new.section = section;
207
208    new.value -= section->bfd_section->vma;
209
210  return new;
211}
212
213static etree_value_type
214fold_binary (tree, current_section, allocation_done, dot, dotp)
215     etree_type *tree;
216     lang_output_section_statement_type *current_section;
217     lang_phase_type allocation_done;
218     bfd_vma dot;
219     bfd_vma *dotp;
220{
221  etree_value_type result;
222
223  result = exp_fold_tree (tree->binary.lhs, current_section,
224			  allocation_done, dot, dotp);
225  if (result.valid)
226    {
227      etree_value_type other;
228
229      other = exp_fold_tree (tree->binary.rhs,
230			     current_section,
231			     allocation_done, dot,dotp) ;
232      if (other.valid)
233	{
234	  /* If the values are from different sections, or this is an
235	     absolute expression, make both the source arguments
236	     absolute.  However, adding or subtracting an absolute
237	     value from a relative value is meaningful, and is an
238	     exception.  */
239	  if (current_section != abs_output_section
240	      && (other.section == abs_output_section
241		  || (result.section == abs_output_section
242		      && tree->type.node_code == '+'))
243	      && (tree->type.node_code == '+'
244		  || tree->type.node_code == '-'))
245	    {
246	      etree_value_type hold;
247
248	      /* If there is only one absolute term, make sure it is the
249		 second one.  */
250	      if (other.section != abs_output_section)
251		{
252		  hold = result;
253		  result = other;
254		  other = hold;
255		}
256	    }
257	  else if (result.section != other.section
258		   || current_section == abs_output_section)
259	    {
260	      make_abs(&result);
261	      make_abs(&other);
262	    }
263
264	  switch (tree->type.node_code)
265	    {
266	    case '%':
267	      if (other.value == 0)
268		einfo ("%F%S %% by zero\n");
269	      result.value = ((bfd_signed_vma) result.value
270			      % (bfd_signed_vma) other.value);
271	      break;
272
273	    case '/':
274	      if (other.value == 0)
275		einfo ("%F%S / by zero\n");
276	      result.value = ((bfd_signed_vma) result.value
277			      / (bfd_signed_vma) other.value);
278	      break;
279
280#define BOP(x,y) case x : result.value = result.value y other.value; break;
281	      BOP('+',+);
282	      BOP('*',*);
283	      BOP('-',-);
284	      BOP(LSHIFT,<<);
285	      BOP(RSHIFT,>>);
286	      BOP(EQ,==);
287	      BOP(NE,!=);
288	      BOP('<',<);
289	      BOP('>',>);
290	      BOP(LE,<=);
291	      BOP(GE,>=);
292	      BOP('&',&);
293	      BOP('^',^);
294	      BOP('|',|);
295	      BOP(ANDAND,&&);
296	      BOP(OROR,||);
297
298	    case MAX:
299	      if (result.value < other.value)
300		result = other;
301	      break;
302
303	    case MIN:
304	      if (result.value > other.value)
305		result = other;
306	      break;
307
308	    default:
309	      FAIL();
310	    }
311	}
312      else
313	{
314	  result.valid = false;
315	}
316    }
317
318  return result;
319}
320
321etree_value_type
322invalid ()
323{
324  etree_value_type new;
325  new.valid = false;
326  return new;
327}
328
329static etree_value_type
330fold_name (tree, current_section, allocation_done, dot)
331     etree_type *tree;
332     lang_output_section_statement_type *current_section;
333     lang_phase_type  allocation_done;
334     bfd_vma dot;
335{
336  etree_value_type result;
337  switch (tree->type.node_code)
338      {
339      case SIZEOF_HEADERS:
340	if (allocation_done != lang_first_phase_enum)
341	  {
342	    result = new_abs ((bfd_vma)
343			      bfd_sizeof_headers (output_bfd,
344						  link_info.relocateable));
345	  }
346	else
347	  {
348	    result.valid = false;
349	  }
350	break;
351      case DEFINED:
352	if (allocation_done == lang_first_phase_enum)
353	  result.valid = false;
354	else
355	  {
356	    struct bfd_link_hash_entry *h;
357
358	    h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
359					      tree->name.name,
360					      false, false, true);
361	    result.value = (h != (struct bfd_link_hash_entry *) NULL
362			    && (h->type == bfd_link_hash_defined
363				|| h->type == bfd_link_hash_defweak
364				|| h->type == bfd_link_hash_common));
365	    result.section = 0;
366	    result.valid = true;
367	  }
368	break;
369      case NAME:
370	result.valid = false;
371	if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
372	  {
373	    if (allocation_done != lang_first_phase_enum)
374	      result = new_rel_from_section(dot, current_section);
375	    else
376	      result = invalid();
377	  }
378	else if (allocation_done != lang_first_phase_enum)
379	  {
380	    struct bfd_link_hash_entry *h;
381
382	    h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
383					      tree->name.name,
384					      false, false, true);
385	    if (h != NULL
386		&& (h->type == bfd_link_hash_defined
387		    || h->type == bfd_link_hash_defweak))
388	      {
389		if (bfd_is_abs_section (h->u.def.section))
390		  result = new_abs (h->u.def.value);
391		else if (allocation_done == lang_final_phase_enum
392			 || allocation_done == lang_allocating_phase_enum)
393		  {
394		    lang_output_section_statement_type *os;
395
396		    os = (lang_output_section_statement_lookup
397			  (h->u.def.section->output_section->name));
398
399		    /* FIXME: Is this correct if this section is being
400		       linked with -R?  */
401		    result = new_rel ((h->u.def.value
402				       + h->u.def.section->output_offset),
403				      os);
404		  }
405	      }
406	    else if (allocation_done == lang_final_phase_enum)
407	      einfo ("%F%S: undefined symbol `%s' referenced in expression\n",
408		     tree->name.name);
409	  }
410	break;
411
412      case ADDR:
413	if (allocation_done != lang_first_phase_enum)
414	  {
415	    lang_output_section_statement_type *os;
416
417	    os = lang_output_section_find (tree->name.name);
418	    check (os, tree->name.name, "ADDR");
419	    result = new_rel (0, os);
420	  }
421	else
422	  result = invalid ();
423	break;
424
425      case LOADADDR:
426	if (allocation_done != lang_first_phase_enum)
427	  {
428	    lang_output_section_statement_type *os;
429
430	    os = lang_output_section_find (tree->name.name);
431	    check (os, tree->name.name, "LOADADDR");
432	    if (os->load_base == NULL)
433	      result = new_rel (0, os);
434	    else
435	      result = exp_fold_tree_no_dot (os->load_base,
436					     abs_output_section,
437					     allocation_done);
438	  }
439	else
440	  result = invalid ();
441	break;
442
443      case SIZEOF:
444	if (allocation_done != lang_first_phase_enum)
445	  {
446	    lang_output_section_statement_type *os;
447
448	    os = lang_output_section_find (tree->name.name);
449	    check (os, tree->name.name, "SIZEOF");
450	    result = new_abs (os->bfd_section->_raw_size);
451	  }
452	else
453	  result = invalid ();
454	break;
455
456      default:
457	FAIL();
458	break;
459      }
460
461  return result;
462}
463etree_value_type
464exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
465     etree_type *tree;
466     lang_output_section_statement_type *current_section;
467     lang_phase_type  allocation_done;
468     bfd_vma dot;
469     bfd_vma *dotp;
470{
471  etree_value_type result;
472
473  if (tree == NULL)
474    {
475      result.valid = false;
476      return result;
477    }
478
479  switch (tree->type.node_class)
480    {
481    case etree_value:
482      result = new_rel (tree->value.value, current_section);
483      break;
484
485    case etree_rel:
486      if (allocation_done != lang_final_phase_enum)
487	result.valid = false;
488      else
489	result = new_rel ((tree->rel.value
490			   + tree->rel.section->output_section->vma
491			   + tree->rel.section->output_offset),
492			  current_section);
493      break;
494
495    case etree_unary:
496      result = exp_fold_tree (tree->unary.child,
497			      current_section,
498			      allocation_done, dot, dotp);
499      if (result.valid)
500	{
501	  switch (tree->type.node_code)
502	    {
503	    case ALIGN_K:
504	      if (allocation_done != lang_first_phase_enum)
505		result = new_rel_from_section (ALIGN_N (dot, result.value),
506					       current_section);
507	      else
508		result.valid = false;
509	      break;
510
511	    case ABSOLUTE:
512	      if (allocation_done != lang_first_phase_enum && result.valid)
513		{
514		  result.value += result.section->bfd_section->vma;
515		  result.section = abs_output_section;
516		}
517	      else
518		result.valid = false;
519	      break;
520
521	    case '~':
522	      make_abs (&result);
523	      result.value = ~result.value;
524	      break;
525
526	    case '!':
527	      make_abs (&result);
528	      result.value = !result.value;
529	      break;
530
531	    case '-':
532	      make_abs (&result);
533	      result.value = -result.value;
534	      break;
535
536	    case NEXT:
537	      /* Return next place aligned to value.  */
538	      if (allocation_done == lang_allocating_phase_enum)
539		{
540		  make_abs (&result);
541		  result.value = ALIGN_N (dot, result.value);
542		}
543	      else
544		result.valid = false;
545	      break;
546
547	    default:
548	      FAIL ();
549	      break;
550	    }
551	}
552      break;
553
554    case etree_trinary:
555      result = exp_fold_tree (tree->trinary.cond, current_section,
556			      allocation_done, dot, dotp);
557      if (result.valid)
558	result = exp_fold_tree ((result.value
559				 ? tree->trinary.lhs
560				 : tree->trinary.rhs),
561				current_section,
562				allocation_done, dot, dotp);
563      break;
564
565    case etree_binary:
566      result = fold_binary (tree, current_section, allocation_done,
567			    dot, dotp);
568      break;
569
570    case etree_assign:
571    case etree_provide:
572      if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
573	{
574	  /* Assignment to dot can only be done during allocation */
575	  if (tree->type.node_class == etree_provide)
576	    einfo ("%F%S can not PROVIDE assignment to location counter\n");
577	  if (allocation_done == lang_allocating_phase_enum
578	      || (allocation_done == lang_final_phase_enum
579		  && current_section == abs_output_section))
580	    {
581	      result = exp_fold_tree (tree->assign.src,
582				      current_section,
583				      lang_allocating_phase_enum, dot,
584				      dotp);
585	      if (! result.valid)
586		einfo ("%F%S invalid assignment to location counter\n");
587	      else
588		{
589		  if (current_section == NULL)
590		    einfo ("%F%S assignment to location counter invalid outside of SECTION\n");
591		  else
592		    {
593		      bfd_vma nextdot;
594
595		      nextdot = (result.value
596				 + current_section->bfd_section->vma);
597		      if (nextdot < dot
598			  && current_section != abs_output_section)
599			{
600			  einfo ("%F%S cannot move location counter backwards (from %V to %V)\n",
601				 dot, nextdot);
602			}
603		      else
604			*dotp = nextdot;
605		    }
606		}
607	    }
608	}
609      else
610	{
611	  result = exp_fold_tree (tree->assign.src,
612				  current_section, allocation_done,
613				  dot, dotp);
614	  if (result.valid)
615	    {
616	      boolean create;
617	      struct bfd_link_hash_entry *h;
618
619	      if (tree->type.node_class == etree_assign)
620		create = true;
621	      else
622		create = false;
623	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
624					create, false, false);
625	      if (h == (struct bfd_link_hash_entry *) NULL)
626		{
627		  if (tree->type.node_class == etree_assign)
628		    einfo ("%P%F:%s: hash creation failed\n",
629			   tree->assign.dst);
630		}
631	      else if (tree->type.node_class == etree_provide
632		       && h->type != bfd_link_hash_undefined
633		       && h->type != bfd_link_hash_common)
634		{
635		  /* Do nothing.  The symbol was defined by some
636		     object.  */
637		}
638	      else
639		{
640		  /* FIXME: Should we worry if the symbol is already
641		     defined?  */
642		  h->type = bfd_link_hash_defined;
643		  h->u.def.value = result.value;
644		  h->u.def.section = result.section->bfd_section;
645		}
646	    }
647	}
648      break;
649
650    case etree_name:
651      result = fold_name (tree, current_section, allocation_done, dot);
652      break;
653
654    default:
655      FAIL ();
656      break;
657    }
658
659  return result;
660}
661
662static etree_value_type
663exp_fold_tree_no_dot (tree, current_section, allocation_done)
664     etree_type *tree;
665     lang_output_section_statement_type *current_section;
666     lang_phase_type allocation_done;
667{
668return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
669		     0, (bfd_vma *)NULL);
670}
671
672etree_type *
673exp_binop (code, lhs, rhs)
674     int code;
675     etree_type *lhs;
676     etree_type *rhs;
677{
678  etree_type value, *new;
679  etree_value_type r;
680
681  value.type.node_code = code;
682  value.binary.lhs = lhs;
683  value.binary.rhs = rhs;
684  value.type.node_class = etree_binary;
685  r = exp_fold_tree_no_dot(&value,
686			   abs_output_section,
687			   lang_first_phase_enum );
688  if (r.valid)
689    {
690      return exp_intop(r.value);
691    }
692  new = (etree_type *) stat_alloc (sizeof (new->binary));
693  memcpy((char *)new, (char *)&value, sizeof(new->binary));
694  return new;
695}
696
697etree_type *
698exp_trinop (code, cond, lhs, rhs)
699     int code;
700     etree_type *cond;
701     etree_type *lhs;
702     etree_type *rhs;
703{
704  etree_type value, *new;
705  etree_value_type r;
706  value.type.node_code = code;
707  value.trinary.lhs = lhs;
708  value.trinary.cond = cond;
709  value.trinary.rhs = rhs;
710  value.type.node_class = etree_trinary;
711  r= exp_fold_tree_no_dot(&value,  (lang_output_section_statement_type
712				    *)NULL,lang_first_phase_enum);
713  if (r.valid) {
714    return exp_intop(r.value);
715  }
716  new = (etree_type *) stat_alloc (sizeof (new->trinary));
717  memcpy((char *)new,(char *) &value, sizeof(new->trinary));
718  return new;
719}
720
721
722etree_type *
723exp_unop (code, child)
724     int code;
725     etree_type *child;
726{
727  etree_type value, *new;
728
729  etree_value_type r;
730  value.unary.type.node_code = code;
731  value.unary.child = child;
732  value.unary.type.node_class = etree_unary;
733  r = exp_fold_tree_no_dot(&value,abs_output_section,
734			   lang_first_phase_enum);
735  if (r.valid) {
736    return exp_intop(r.value);
737  }
738  new = (etree_type *) stat_alloc (sizeof (new->unary));
739  memcpy((char *)new, (char *)&value, sizeof(new->unary));
740  return new;
741}
742
743
744etree_type *
745exp_nameop (code, name)
746     int code;
747     CONST char *name;
748{
749  etree_type value, *new;
750  etree_value_type r;
751  value.name.type.node_code = code;
752  value.name.name = name;
753  value.name.type.node_class = etree_name;
754
755
756  r = exp_fold_tree_no_dot(&value,
757			   (lang_output_section_statement_type *)NULL,
758			   lang_first_phase_enum);
759  if (r.valid) {
760    return exp_intop(r.value);
761  }
762  new = (etree_type *) stat_alloc (sizeof (new->name));
763  memcpy((char *)new, (char *)&value, sizeof(new->name));
764  return new;
765
766}
767
768
769
770
771etree_type *
772exp_assop (code, dst, src)
773     int code;
774     CONST char *dst;
775     etree_type *src;
776{
777  etree_type value, *new;
778
779  value.assign.type.node_code = code;
780
781
782  value.assign.src = src;
783  value.assign.dst = dst;
784  value.assign.type.node_class = etree_assign;
785
786#if 0
787  if (exp_fold_tree_no_dot(&value, &result)) {
788    return exp_intop(result);
789  }
790#endif
791  new = (etree_type*) stat_alloc (sizeof (new->assign));
792  memcpy((char *)new, (char *)&value, sizeof(new->assign));
793  return new;
794}
795
796/* Handle PROVIDE.  */
797
798etree_type *
799exp_provide (dst, src)
800     const char *dst;
801     etree_type *src;
802{
803  etree_type *n;
804
805  n = (etree_type *) stat_alloc (sizeof (n->assign));
806  n->assign.type.node_code = '=';
807  n->assign.type.node_class = etree_provide;
808  n->assign.src = src;
809  n->assign.dst = dst;
810  return n;
811}
812
813void
814exp_print_tree (tree)
815     etree_type *tree;
816{
817  switch (tree->type.node_class) {
818  case etree_value:
819    minfo ("0x%v", tree->value.value);
820    return;
821  case etree_rel:
822    if (tree->rel.section->owner != NULL)
823      minfo ("%B:", tree->rel.section->owner);
824    minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
825    return;
826  case etree_assign:
827#if 0
828    if (tree->assign.dst->sdefs != (asymbol *)NULL){
829      fprintf(config.map_file,"%s (%x) ",tree->assign.dst->name,
830	      tree->assign.dst->sdefs->value);
831    }
832    else {
833      fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
834    }
835#endif
836    fprintf(config.map_file,"%s",tree->assign.dst);
837    exp_print_token(tree->type.node_code);
838    exp_print_tree(tree->assign.src);
839    break;
840  case etree_provide:
841    fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
842    exp_print_tree (tree->assign.src);
843    fprintf (config.map_file, ")");
844    break;
845  case etree_binary:
846    fprintf(config.map_file,"(");
847    exp_print_tree(tree->binary.lhs);
848    exp_print_token(tree->type.node_code);
849    exp_print_tree(tree->binary.rhs);
850    fprintf(config.map_file,")");
851    break;
852  case etree_trinary:
853    exp_print_tree(tree->trinary.cond);
854    fprintf(config.map_file,"?");
855    exp_print_tree(tree->trinary.lhs);
856    fprintf(config.map_file,":");
857    exp_print_tree(tree->trinary.rhs);
858    break;
859  case etree_unary:
860    exp_print_token(tree->unary.type.node_code);
861    if (tree->unary.child)
862    {
863
864    fprintf(config.map_file,"(");
865    exp_print_tree(tree->unary.child);
866    fprintf(config.map_file,")");
867  }
868
869    break;
870  case etree_undef:
871    fprintf(config.map_file,"????????");
872    break;
873  case etree_name:
874    if (tree->type.node_code == NAME) {
875      fprintf(config.map_file,"%s", tree->name.name);
876    }
877    else {
878      exp_print_token(tree->type.node_code);
879      if (tree->name.name)
880      fprintf(config.map_file,"(%s)", tree->name.name);
881    }
882    break;
883  default:
884    FAIL();
885    break;
886  }
887}
888
889bfd_vma
890exp_get_vma (tree, def, name, allocation_done)
891     etree_type *tree;
892     bfd_vma def;
893     char *name;
894     lang_phase_type allocation_done;
895{
896  etree_value_type r;
897
898  if (tree != NULL)
899    {
900      r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
901      if (! r.valid && name != NULL)
902	einfo ("%F%S nonconstant expression for %s\n", name);
903      return r.value;
904    }
905  else
906    return def;
907}
908
909int
910exp_get_value_int (tree,def,name, allocation_done)
911     etree_type *tree;
912     int def;
913     char *name;
914     lang_phase_type allocation_done;
915{
916  return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
917}
918
919
920bfd_vma
921exp_get_abs_int (tree, def, name, allocation_done)
922     etree_type *tree;
923     int def;
924     char *name;
925     lang_phase_type allocation_done;
926{
927  etree_value_type res;
928  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
929
930  if (res.valid)
931    {
932      res.value += res.section->bfd_section->vma;
933    }
934  else {
935    einfo ("%F%S non constant expression for %s\n",name);
936  }
937  return res.value;
938}
939