12159047fSniklas /* This module handles expression trees.
2b55d4692Sfgsch Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3*007c2a45Smiod 2001, 2002, 2003, 2004
4b305b0f1Sespie Free Software Foundation, Inc.
5b55d4692Sfgsch Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
62159047fSniklas
72159047fSniklas This file is part of GLD, the Gnu Linker.
82159047fSniklas
92159047fSniklas GLD is free software; you can redistribute it and/or modify
102159047fSniklas it under the terms of the GNU General Public License as published by
112159047fSniklas the Free Software Foundation; either version 2, or (at your option)
122159047fSniklas any later version.
132159047fSniklas
142159047fSniklas GLD is distributed in the hope that it will be useful,
152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
172159047fSniklas GNU General Public License for more details.
182159047fSniklas
192159047fSniklas You should have received a copy of the GNU General Public License
20b305b0f1Sespie along with GLD; see the file COPYING. If not, write to the Free
21b305b0f1Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22b305b0f1Sespie 02111-1307, USA. */
232159047fSniklas
24b55d4692Sfgsch /* This module is in charge of working out the contents of expressions.
252159047fSniklas
26b55d4692Sfgsch It has to keep track of the relative/absness of a symbol etc. This
27b55d4692Sfgsch is done by keeping all values in a struct (an etree_value_type)
28b55d4692Sfgsch which contains a value, a section to which it is relative and a
29b55d4692Sfgsch valid bit. */
302159047fSniklas
312159047fSniklas #include "bfd.h"
322159047fSniklas #include "sysdep.h"
332159047fSniklas #include "bfdlink.h"
342159047fSniklas
352159047fSniklas #include "ld.h"
362159047fSniklas #include "ldmain.h"
372159047fSniklas #include "ldmisc.h"
382159047fSniklas #include "ldexp.h"
39c074d1c9Sdrahn #include <ldgram.h>
402159047fSniklas #include "ldlang.h"
41c074d1c9Sdrahn #include "libiberty.h"
42c074d1c9Sdrahn #include "safe-ctype.h"
432159047fSniklas
442159047fSniklas static etree_value_type exp_fold_tree_no_dot
45*007c2a45Smiod (etree_type *, lang_output_section_statement_type *, lang_phase_type);
46*007c2a45Smiod static bfd_vma align_n
47*007c2a45Smiod (bfd_vma, bfd_vma);
482159047fSniklas
49c074d1c9Sdrahn struct exp_data_seg exp_data_seg;
50c074d1c9Sdrahn
51c074d1c9Sdrahn /* Print the string representation of the given token. Surround it
52c074d1c9Sdrahn with spaces if INFIX_P is TRUE. */
53c074d1c9Sdrahn
542159047fSniklas static void
exp_print_token(token_code_type code,int infix_p)55*007c2a45Smiod exp_print_token (token_code_type code, int infix_p)
562159047fSniklas {
57c074d1c9Sdrahn static const struct
58c074d1c9Sdrahn {
592159047fSniklas token_code_type code;
602159047fSniklas char * name;
61c074d1c9Sdrahn }
62c074d1c9Sdrahn table[] =
63c074d1c9Sdrahn {
642159047fSniklas { INT, "int" },
652159047fSniklas { NAME, "NAME" },
662159047fSniklas { PLUSEQ, "+=" },
672159047fSniklas { MINUSEQ, "-=" },
682159047fSniklas { MULTEQ, "*=" },
692159047fSniklas { DIVEQ, "/=" },
702159047fSniklas { LSHIFTEQ, "<<=" },
712159047fSniklas { RSHIFTEQ, ">>=" },
722159047fSniklas { ANDEQ, "&=" },
732159047fSniklas { OREQ, "|=" },
742159047fSniklas { OROR, "||" },
752159047fSniklas { ANDAND, "&&" },
762159047fSniklas { EQ, "==" },
772159047fSniklas { NE, "!=" },
782159047fSniklas { LE, "<=" },
792159047fSniklas { GE, ">=" },
802159047fSniklas { LSHIFT, "<<" },
81c074d1c9Sdrahn { RSHIFT, ">>" },
822159047fSniklas { ALIGN_K, "ALIGN" },
832159047fSniklas { BLOCK, "BLOCK" },
842159047fSniklas { QUAD, "QUAD" },
85b305b0f1Sespie { SQUAD, "SQUAD" },
862159047fSniklas { LONG, "LONG" },
872159047fSniklas { SHORT, "SHORT" },
882159047fSniklas { BYTE, "BYTE" },
89c074d1c9Sdrahn { SECTIONS, "SECTIONS" },
90c074d1c9Sdrahn { SIZEOF_HEADERS, "SIZEOF_HEADERS" },
91c074d1c9Sdrahn { MEMORY, "MEMORY" },
92c074d1c9Sdrahn { DEFINED, "DEFINED" },
93c074d1c9Sdrahn { TARGET_K, "TARGET" },
94c074d1c9Sdrahn { SEARCH_DIR, "SEARCH_DIR" },
95c074d1c9Sdrahn { MAP, "MAP" },
962159047fSniklas { ENTRY, "ENTRY" },
97c074d1c9Sdrahn { NEXT, "NEXT" },
98c074d1c9Sdrahn { SIZEOF, "SIZEOF" },
99c074d1c9Sdrahn { ADDR, "ADDR" },
100c074d1c9Sdrahn { LOADADDR, "LOADADDR" },
101c074d1c9Sdrahn { MAX_K, "MAX_K" },
102*007c2a45Smiod { REL, "relocatable" },
103c074d1c9Sdrahn { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
104c074d1c9Sdrahn { DATA_SEGMENT_END, "DATA_SEGMENT_END" }
1052159047fSniklas };
1062159047fSniklas unsigned int idx;
1072159047fSniklas
108c074d1c9Sdrahn for (idx = 0; idx < ARRAY_SIZE (table); idx++)
109b55d4692Sfgsch if (table[idx].code == code)
110c074d1c9Sdrahn break;
111c074d1c9Sdrahn
112c074d1c9Sdrahn if (infix_p)
113c074d1c9Sdrahn fputc (' ', config.map_file);
114c074d1c9Sdrahn
115c074d1c9Sdrahn if (idx < ARRAY_SIZE (table))
116c074d1c9Sdrahn fputs (table[idx].name, config.map_file);
117c074d1c9Sdrahn else if (code < 127)
118c074d1c9Sdrahn fputc (code, config.map_file);
119c074d1c9Sdrahn else
120c074d1c9Sdrahn fprintf (config.map_file, "<code %d>", code);
121c074d1c9Sdrahn
122c074d1c9Sdrahn if (infix_p)
123c074d1c9Sdrahn fputc (' ', config.map_file);
1242159047fSniklas }
1252159047fSniklas
1262159047fSniklas static void
make_abs(etree_value_type * ptr)127*007c2a45Smiod make_abs (etree_value_type *ptr)
1282159047fSniklas {
1292159047fSniklas asection *s = ptr->section->bfd_section;
1302159047fSniklas ptr->value += s->vma;
1312159047fSniklas ptr->section = abs_output_section;
1322159047fSniklas }
1332159047fSniklas
1342159047fSniklas static etree_value_type
new_abs(bfd_vma value)135*007c2a45Smiod new_abs (bfd_vma value)
1362159047fSniklas {
1372159047fSniklas etree_value_type new;
138c074d1c9Sdrahn new.valid_p = TRUE;
1392159047fSniklas new.section = abs_output_section;
1402159047fSniklas new.value = value;
1412159047fSniklas return new;
1422159047fSniklas }
1432159047fSniklas
1442159047fSniklas etree_type *
exp_intop(bfd_vma value)145*007c2a45Smiod exp_intop (bfd_vma value)
1462159047fSniklas {
147*007c2a45Smiod etree_type *new = stat_alloc (sizeof (new->value));
1482159047fSniklas new->type.node_code = INT;
1492159047fSniklas new->value.value = value;
150c074d1c9Sdrahn new->value.str = NULL;
1512159047fSniklas new->type.node_class = etree_value;
1522159047fSniklas return new;
153c074d1c9Sdrahn }
1542159047fSniklas
155c074d1c9Sdrahn etree_type *
exp_bigintop(bfd_vma value,char * str)156*007c2a45Smiod exp_bigintop (bfd_vma value, char *str)
157c074d1c9Sdrahn {
158*007c2a45Smiod etree_type *new = stat_alloc (sizeof (new->value));
159c074d1c9Sdrahn new->type.node_code = INT;
160c074d1c9Sdrahn new->value.value = value;
161c074d1c9Sdrahn new->value.str = str;
162c074d1c9Sdrahn new->type.node_class = etree_value;
163c074d1c9Sdrahn return new;
1642159047fSniklas }
1652159047fSniklas
166*007c2a45Smiod /* Build an expression representing an unnamed relocatable value. */
1672159047fSniklas
1682159047fSniklas etree_type *
exp_relop(asection * section,bfd_vma value)169*007c2a45Smiod exp_relop (asection *section, bfd_vma value)
1702159047fSniklas {
171*007c2a45Smiod etree_type *new = stat_alloc (sizeof (new->rel));
1722159047fSniklas new->type.node_code = REL;
1732159047fSniklas new->type.node_class = etree_rel;
1742159047fSniklas new->rel.section = section;
1752159047fSniklas new->rel.value = value;
1762159047fSniklas return new;
1772159047fSniklas }
1782159047fSniklas
1792159047fSniklas static etree_value_type
new_rel(bfd_vma value,char * str,lang_output_section_statement_type * section)180*007c2a45Smiod new_rel (bfd_vma value,
181*007c2a45Smiod char *str,
182*007c2a45Smiod lang_output_section_statement_type *section)
1832159047fSniklas {
1842159047fSniklas etree_value_type new;
185c074d1c9Sdrahn new.valid_p = TRUE;
1862159047fSniklas new.value = value;
187c074d1c9Sdrahn new.str = str;
1882159047fSniklas new.section = section;
1892159047fSniklas return new;
1902159047fSniklas }
1912159047fSniklas
1922159047fSniklas static etree_value_type
new_rel_from_section(bfd_vma value,lang_output_section_statement_type * section)193*007c2a45Smiod new_rel_from_section (bfd_vma value,
194*007c2a45Smiod lang_output_section_statement_type *section)
1952159047fSniklas {
1962159047fSniklas etree_value_type new;
197c074d1c9Sdrahn new.valid_p = TRUE;
1982159047fSniklas new.value = value;
199c074d1c9Sdrahn new.str = NULL;
2002159047fSniklas new.section = section;
2012159047fSniklas
2022159047fSniklas new.value -= section->bfd_section->vma;
2032159047fSniklas
2042159047fSniklas return new;
2052159047fSniklas }
2062159047fSniklas
2072159047fSniklas static etree_value_type
fold_unary(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)208*007c2a45Smiod fold_unary (etree_type *tree,
209*007c2a45Smiod lang_output_section_statement_type *current_section,
210*007c2a45Smiod lang_phase_type allocation_done,
211*007c2a45Smiod bfd_vma dot,
212*007c2a45Smiod bfd_vma *dotp)
213c074d1c9Sdrahn {
214c074d1c9Sdrahn etree_value_type result;
215c074d1c9Sdrahn
216c074d1c9Sdrahn result = exp_fold_tree (tree->unary.child,
217c074d1c9Sdrahn current_section,
218c074d1c9Sdrahn allocation_done, dot, dotp);
219c074d1c9Sdrahn if (result.valid_p)
220c074d1c9Sdrahn {
221c074d1c9Sdrahn switch (tree->type.node_code)
222c074d1c9Sdrahn {
223c074d1c9Sdrahn case ALIGN_K:
224c074d1c9Sdrahn if (allocation_done != lang_first_phase_enum)
225c074d1c9Sdrahn result = new_rel_from_section (align_n (dot, result.value),
226c074d1c9Sdrahn current_section);
227c074d1c9Sdrahn else
228c074d1c9Sdrahn result.valid_p = FALSE;
229c074d1c9Sdrahn break;
230c074d1c9Sdrahn
231c074d1c9Sdrahn case ABSOLUTE:
232c074d1c9Sdrahn if (allocation_done != lang_first_phase_enum)
233c074d1c9Sdrahn {
234c074d1c9Sdrahn result.value += result.section->bfd_section->vma;
235c074d1c9Sdrahn result.section = abs_output_section;
236c074d1c9Sdrahn }
237c074d1c9Sdrahn else
238c074d1c9Sdrahn result.valid_p = FALSE;
239c074d1c9Sdrahn break;
240c074d1c9Sdrahn
241c074d1c9Sdrahn case '~':
242c074d1c9Sdrahn make_abs (&result);
243c074d1c9Sdrahn result.value = ~result.value;
244c074d1c9Sdrahn break;
245c074d1c9Sdrahn
246c074d1c9Sdrahn case '!':
247c074d1c9Sdrahn make_abs (&result);
248c074d1c9Sdrahn result.value = !result.value;
249c074d1c9Sdrahn break;
250c074d1c9Sdrahn
251c074d1c9Sdrahn case '-':
252c074d1c9Sdrahn make_abs (&result);
253c074d1c9Sdrahn result.value = -result.value;
254c074d1c9Sdrahn break;
255c074d1c9Sdrahn
256c074d1c9Sdrahn case NEXT:
257c074d1c9Sdrahn /* Return next place aligned to value. */
258c074d1c9Sdrahn if (allocation_done == lang_allocating_phase_enum)
259c074d1c9Sdrahn {
260c074d1c9Sdrahn make_abs (&result);
261c074d1c9Sdrahn result.value = align_n (dot, result.value);
262c074d1c9Sdrahn }
263c074d1c9Sdrahn else
264c074d1c9Sdrahn result.valid_p = FALSE;
265c074d1c9Sdrahn break;
266c074d1c9Sdrahn
267c074d1c9Sdrahn case DATA_SEGMENT_END:
268c074d1c9Sdrahn if (allocation_done != lang_first_phase_enum
269c074d1c9Sdrahn && current_section == abs_output_section
270c074d1c9Sdrahn && (exp_data_seg.phase == exp_dataseg_align_seen
271c074d1c9Sdrahn || exp_data_seg.phase == exp_dataseg_adjust
272c074d1c9Sdrahn || allocation_done != lang_allocating_phase_enum))
273c074d1c9Sdrahn {
274c074d1c9Sdrahn if (exp_data_seg.phase == exp_dataseg_align_seen)
275c074d1c9Sdrahn {
276c074d1c9Sdrahn exp_data_seg.phase = exp_dataseg_end_seen;
277c074d1c9Sdrahn exp_data_seg.end = result.value;
278c074d1c9Sdrahn }
279c074d1c9Sdrahn }
280c074d1c9Sdrahn else
281c074d1c9Sdrahn result.valid_p = FALSE;
282c074d1c9Sdrahn break;
283c074d1c9Sdrahn
284c074d1c9Sdrahn default:
285c074d1c9Sdrahn FAIL ();
286c074d1c9Sdrahn break;
287c074d1c9Sdrahn }
288c074d1c9Sdrahn }
289c074d1c9Sdrahn
290c074d1c9Sdrahn return result;
291c074d1c9Sdrahn }
292c074d1c9Sdrahn
293c074d1c9Sdrahn static etree_value_type
fold_binary(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)294*007c2a45Smiod fold_binary (etree_type *tree,
295*007c2a45Smiod lang_output_section_statement_type *current_section,
296*007c2a45Smiod lang_phase_type allocation_done,
297*007c2a45Smiod bfd_vma dot,
298*007c2a45Smiod bfd_vma *dotp)
2992159047fSniklas {
3002159047fSniklas etree_value_type result;
3012159047fSniklas
3022159047fSniklas result = exp_fold_tree (tree->binary.lhs, current_section,
3032159047fSniklas allocation_done, dot, dotp);
304b305b0f1Sespie if (result.valid_p)
3052159047fSniklas {
3062159047fSniklas etree_value_type other;
3072159047fSniklas
3082159047fSniklas other = exp_fold_tree (tree->binary.rhs,
3092159047fSniklas current_section,
3102159047fSniklas allocation_done, dot, dotp);
311b305b0f1Sespie if (other.valid_p)
3122159047fSniklas {
3132159047fSniklas /* If the values are from different sections, or this is an
3142159047fSniklas absolute expression, make both the source arguments
3152159047fSniklas absolute. However, adding or subtracting an absolute
3162159047fSniklas value from a relative value is meaningful, and is an
3172159047fSniklas exception. */
3182159047fSniklas if (current_section != abs_output_section
319191aa565Sniklas && (other.section == abs_output_section
320191aa565Sniklas || (result.section == abs_output_section
321191aa565Sniklas && tree->type.node_code == '+'))
3222159047fSniklas && (tree->type.node_code == '+'
3232159047fSniklas || tree->type.node_code == '-'))
3242159047fSniklas {
325191aa565Sniklas if (other.section != abs_output_section)
3262159047fSniklas {
327c074d1c9Sdrahn /* Keep the section of the other term. */
328c074d1c9Sdrahn if (tree->type.node_code == '+')
329c074d1c9Sdrahn other.value = result.value + other.value;
330c074d1c9Sdrahn else
331c074d1c9Sdrahn other.value = result.value - other.value;
332c074d1c9Sdrahn return other;
3332159047fSniklas }
3342159047fSniklas }
3352159047fSniklas else if (result.section != other.section
3362159047fSniklas || current_section == abs_output_section)
3372159047fSniklas {
3382159047fSniklas make_abs (&result);
3392159047fSniklas make_abs (&other);
3402159047fSniklas }
3412159047fSniklas
3422159047fSniklas switch (tree->type.node_code)
3432159047fSniklas {
3442159047fSniklas case '%':
3452159047fSniklas if (other.value == 0)
346b305b0f1Sespie einfo (_("%F%S %% by zero\n"));
3472159047fSniklas result.value = ((bfd_signed_vma) result.value
3482159047fSniklas % (bfd_signed_vma) other.value);
3492159047fSniklas break;
3502159047fSniklas
3512159047fSniklas case '/':
3522159047fSniklas if (other.value == 0)
353b305b0f1Sespie einfo (_("%F%S / by zero\n"));
3542159047fSniklas result.value = ((bfd_signed_vma) result.value
3552159047fSniklas / (bfd_signed_vma) other.value);
3562159047fSniklas break;
3572159047fSniklas
3582159047fSniklas #define BOP(x,y) case x : result.value = result.value y other.value; break;
3592159047fSniklas BOP ('+', +);
3602159047fSniklas BOP ('*', *);
3612159047fSniklas BOP ('-', -);
3622159047fSniklas BOP (LSHIFT, <<);
3632159047fSniklas BOP (RSHIFT, >>);
3642159047fSniklas BOP (EQ, ==);
3652159047fSniklas BOP (NE, !=);
3662159047fSniklas BOP ('<', <);
3672159047fSniklas BOP ('>', >);
3682159047fSniklas BOP (LE, <=);
3692159047fSniklas BOP (GE, >=);
3702159047fSniklas BOP ('&', &);
3712159047fSniklas BOP ('^', ^);
3722159047fSniklas BOP ('|', |);
3732159047fSniklas BOP (ANDAND, &&);
3742159047fSniklas BOP (OROR, ||);
3752159047fSniklas
376b305b0f1Sespie case MAX_K:
3770c6d0228Sniklas if (result.value < other.value)
3780c6d0228Sniklas result = other;
3790c6d0228Sniklas break;
3800c6d0228Sniklas
381b305b0f1Sespie case MIN_K:
3820c6d0228Sniklas if (result.value > other.value)
3830c6d0228Sniklas result = other;
3840c6d0228Sniklas break;
3850c6d0228Sniklas
386*007c2a45Smiod case ALIGN_K:
387*007c2a45Smiod result.value = align_n (result.value, other.value);
388*007c2a45Smiod break;
389*007c2a45Smiod
390c074d1c9Sdrahn case DATA_SEGMENT_ALIGN:
391c074d1c9Sdrahn if (allocation_done != lang_first_phase_enum
392c074d1c9Sdrahn && current_section == abs_output_section
393c074d1c9Sdrahn && (exp_data_seg.phase == exp_dataseg_none
394c074d1c9Sdrahn || exp_data_seg.phase == exp_dataseg_adjust
395c074d1c9Sdrahn || allocation_done != lang_allocating_phase_enum))
396c074d1c9Sdrahn {
397c074d1c9Sdrahn bfd_vma maxpage = result.value;
398c074d1c9Sdrahn
399c074d1c9Sdrahn result.value = align_n (dot, maxpage);
400c074d1c9Sdrahn if (exp_data_seg.phase != exp_dataseg_adjust)
401c074d1c9Sdrahn {
402c074d1c9Sdrahn result.value += dot & (maxpage - 1);
403c074d1c9Sdrahn if (allocation_done == lang_allocating_phase_enum)
404c074d1c9Sdrahn {
405c074d1c9Sdrahn exp_data_seg.phase = exp_dataseg_align_seen;
406c074d1c9Sdrahn exp_data_seg.base = result.value;
407c074d1c9Sdrahn exp_data_seg.pagesize = other.value;
408c074d1c9Sdrahn }
409c074d1c9Sdrahn }
410c074d1c9Sdrahn else if (other.value < maxpage)
411c074d1c9Sdrahn result.value += (dot + other.value - 1)
412c074d1c9Sdrahn & (maxpage - other.value);
413c074d1c9Sdrahn }
414c074d1c9Sdrahn else
415c074d1c9Sdrahn result.valid_p = FALSE;
416c074d1c9Sdrahn break;
417c074d1c9Sdrahn
4182159047fSniklas default:
4192159047fSniklas FAIL ();
4202159047fSniklas }
4212159047fSniklas }
4222159047fSniklas else
4232159047fSniklas {
424c074d1c9Sdrahn result.valid_p = FALSE;
4252159047fSniklas }
4262159047fSniklas }
4272159047fSniklas
4282159047fSniklas return result;
4292159047fSniklas }
4302159047fSniklas
431c074d1c9Sdrahn static etree_value_type
fold_trinary(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)432*007c2a45Smiod fold_trinary (etree_type *tree,
433*007c2a45Smiod lang_output_section_statement_type *current_section,
434*007c2a45Smiod lang_phase_type allocation_done,
435*007c2a45Smiod bfd_vma dot,
436*007c2a45Smiod bfd_vma *dotp)
437c074d1c9Sdrahn {
438c074d1c9Sdrahn etree_value_type result;
439c074d1c9Sdrahn
440c074d1c9Sdrahn result = exp_fold_tree (tree->trinary.cond, current_section,
441c074d1c9Sdrahn allocation_done, dot, dotp);
442c074d1c9Sdrahn if (result.valid_p)
443c074d1c9Sdrahn result = exp_fold_tree ((result.value
444c074d1c9Sdrahn ? tree->trinary.lhs
445c074d1c9Sdrahn : tree->trinary.rhs),
446c074d1c9Sdrahn current_section,
447c074d1c9Sdrahn allocation_done, dot, dotp);
448c074d1c9Sdrahn
449c074d1c9Sdrahn return result;
450c074d1c9Sdrahn }
451c074d1c9Sdrahn
4522159047fSniklas static etree_value_type
fold_name(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot)453*007c2a45Smiod fold_name (etree_type *tree,
454*007c2a45Smiod lang_output_section_statement_type *current_section,
455*007c2a45Smiod lang_phase_type allocation_done,
456*007c2a45Smiod bfd_vma dot)
4572159047fSniklas {
4582159047fSniklas etree_value_type result;
459c074d1c9Sdrahn
460*007c2a45Smiod result.valid_p = FALSE;
461*007c2a45Smiod
4622159047fSniklas switch (tree->type.node_code)
4632159047fSniklas {
4642159047fSniklas case SIZEOF_HEADERS:
4652159047fSniklas if (allocation_done != lang_first_phase_enum)
466*007c2a45Smiod result = new_abs (bfd_sizeof_headers (output_bfd,
467*007c2a45Smiod link_info.relocatable));
4682159047fSniklas break;
4692159047fSniklas case DEFINED:
4702159047fSniklas if (allocation_done == lang_first_phase_enum)
471*007c2a45Smiod lang_track_definedness (tree->name.name);
4722159047fSniklas else
4732159047fSniklas {
4742159047fSniklas struct bfd_link_hash_entry *h;
475*007c2a45Smiod int def_iteration
476*007c2a45Smiod = lang_symbol_definition_iteration (tree->name.name);
4772159047fSniklas
478191aa565Sniklas h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
479191aa565Sniklas tree->name.name,
480c074d1c9Sdrahn FALSE, FALSE, TRUE);
481*007c2a45Smiod result.value = (h != NULL
4822159047fSniklas && (h->type == bfd_link_hash_defined
4832159047fSniklas || h->type == bfd_link_hash_defweak
484*007c2a45Smiod || h->type == bfd_link_hash_common)
485*007c2a45Smiod && (def_iteration == lang_statement_iteration
486*007c2a45Smiod || def_iteration == -1));
487*007c2a45Smiod result.section = abs_output_section;
488c074d1c9Sdrahn result.valid_p = TRUE;
4892159047fSniklas }
4902159047fSniklas break;
4912159047fSniklas case NAME:
4922159047fSniklas if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
4932159047fSniklas {
4942159047fSniklas if (allocation_done != lang_first_phase_enum)
4952159047fSniklas result = new_rel_from_section (dot, current_section);
4962159047fSniklas }
4972159047fSniklas else if (allocation_done != lang_first_phase_enum)
4982159047fSniklas {
4992159047fSniklas struct bfd_link_hash_entry *h;
5002159047fSniklas
501191aa565Sniklas h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
502191aa565Sniklas tree->name.name,
503*007c2a45Smiod TRUE, FALSE, TRUE);
504*007c2a45Smiod if (!h)
505*007c2a45Smiod einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
506*007c2a45Smiod else if (h->type == bfd_link_hash_defined
507*007c2a45Smiod || h->type == bfd_link_hash_defweak)
5082159047fSniklas {
5092159047fSniklas if (bfd_is_abs_section (h->u.def.section))
5102159047fSniklas result = new_abs (h->u.def.value);
511191aa565Sniklas else if (allocation_done == lang_final_phase_enum
512191aa565Sniklas || allocation_done == lang_allocating_phase_enum)
5132159047fSniklas {
514b305b0f1Sespie asection *output_section;
515b305b0f1Sespie
516b305b0f1Sespie output_section = h->u.def.section->output_section;
517b305b0f1Sespie if (output_section == NULL)
518b305b0f1Sespie einfo (_("%X%S: unresolvable symbol `%s' referenced in expression\n"),
519b305b0f1Sespie tree->name.name);
520b305b0f1Sespie else
521b305b0f1Sespie {
5222159047fSniklas lang_output_section_statement_type *os;
5232159047fSniklas
5242159047fSniklas os = (lang_output_section_statement_lookup
525b305b0f1Sespie (bfd_get_section_name (output_bfd,
526b305b0f1Sespie output_section)));
5272159047fSniklas
528b305b0f1Sespie /* FIXME: Is this correct if this section is
529b305b0f1Sespie being linked with -R? */
5302159047fSniklas result = new_rel ((h->u.def.value
5312159047fSniklas + h->u.def.section->output_offset),
532c074d1c9Sdrahn NULL,
5332159047fSniklas os);
5342159047fSniklas }
5352159047fSniklas }
536b305b0f1Sespie }
5372159047fSniklas else if (allocation_done == lang_final_phase_enum)
538b305b0f1Sespie einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
5392159047fSniklas tree->name.name);
540*007c2a45Smiod else if (h->type == bfd_link_hash_new)
541*007c2a45Smiod {
542*007c2a45Smiod h->type = bfd_link_hash_undefined;
543*007c2a45Smiod h->u.undef.abfd = NULL;
544*007c2a45Smiod bfd_link_add_undef (link_info.hash, h);
545*007c2a45Smiod }
5462159047fSniklas }
5472159047fSniklas break;
5482159047fSniklas
5492159047fSniklas case ADDR:
5500c6d0228Sniklas if (allocation_done != lang_first_phase_enum)
5510c6d0228Sniklas {
5520c6d0228Sniklas lang_output_section_statement_type *os;
5532159047fSniklas
5540c6d0228Sniklas os = lang_output_section_find (tree->name.name);
555*007c2a45Smiod if (os && os->processed > 0)
556c074d1c9Sdrahn result = new_rel (0, NULL, os);
5572159047fSniklas }
5582159047fSniklas break;
5590c6d0228Sniklas
5600c6d0228Sniklas case LOADADDR:
5610c6d0228Sniklas if (allocation_done != lang_first_phase_enum)
5620c6d0228Sniklas {
5630c6d0228Sniklas lang_output_section_statement_type *os;
5640c6d0228Sniklas
5650c6d0228Sniklas os = lang_output_section_find (tree->name.name);
566*007c2a45Smiod if (os && os->processed != 0)
567*007c2a45Smiod {
5680c6d0228Sniklas if (os->load_base == NULL)
569c074d1c9Sdrahn result = new_rel (0, NULL, os);
5700c6d0228Sniklas else
5710c6d0228Sniklas result = exp_fold_tree_no_dot (os->load_base,
5720c6d0228Sniklas abs_output_section,
5730c6d0228Sniklas allocation_done);
5742159047fSniklas }
575*007c2a45Smiod }
5760c6d0228Sniklas break;
5770c6d0228Sniklas
5780c6d0228Sniklas case SIZEOF:
5790c6d0228Sniklas if (allocation_done != lang_first_phase_enum)
5800c6d0228Sniklas {
581b305b0f1Sespie int opb = bfd_octets_per_byte (output_bfd);
5820c6d0228Sniklas lang_output_section_statement_type *os;
5830c6d0228Sniklas
5840c6d0228Sniklas os = lang_output_section_find (tree->name.name);
585*007c2a45Smiod if (os && os->processed > 0)
586b305b0f1Sespie result = new_abs (os->bfd_section->_raw_size / opb);
5872159047fSniklas }
5882159047fSniklas break;
5892159047fSniklas
5902159047fSniklas default:
5912159047fSniklas FAIL ();
5922159047fSniklas break;
5932159047fSniklas }
5942159047fSniklas
5952159047fSniklas return result;
5962159047fSniklas }
597b55d4692Sfgsch
5982159047fSniklas etree_value_type
exp_fold_tree(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)599*007c2a45Smiod exp_fold_tree (etree_type *tree,
600*007c2a45Smiod lang_output_section_statement_type *current_section,
601*007c2a45Smiod lang_phase_type allocation_done,
602*007c2a45Smiod bfd_vma dot,
603*007c2a45Smiod bfd_vma *dotp)
6042159047fSniklas {
6052159047fSniklas etree_value_type result;
6062159047fSniklas
6070c6d0228Sniklas if (tree == NULL)
6080c6d0228Sniklas {
609c074d1c9Sdrahn result.valid_p = FALSE;
6100c6d0228Sniklas return result;
6112159047fSniklas }
6120c6d0228Sniklas
6132159047fSniklas switch (tree->type.node_class)
6142159047fSniklas {
6152159047fSniklas case etree_value:
616c074d1c9Sdrahn result = new_rel (tree->value.value, tree->value.str, current_section);
6172159047fSniklas break;
6180c6d0228Sniklas
6192159047fSniklas case etree_rel:
6202159047fSniklas if (allocation_done != lang_final_phase_enum)
621c074d1c9Sdrahn result.valid_p = FALSE;
6222159047fSniklas else
6232159047fSniklas result = new_rel ((tree->rel.value
6242159047fSniklas + tree->rel.section->output_section->vma
6252159047fSniklas + tree->rel.section->output_offset),
626c074d1c9Sdrahn NULL,
6272159047fSniklas current_section);
6282159047fSniklas break;
6290c6d0228Sniklas
630b305b0f1Sespie case etree_assert:
631b305b0f1Sespie result = exp_fold_tree (tree->assert_s.child,
632b305b0f1Sespie current_section,
633b305b0f1Sespie allocation_done, dot, dotp);
634b305b0f1Sespie if (result.valid_p)
635b305b0f1Sespie {
636b305b0f1Sespie if (! result.value)
637b305b0f1Sespie einfo ("%F%P: %s\n", tree->assert_s.message);
638b305b0f1Sespie return result;
639b305b0f1Sespie }
640b305b0f1Sespie break;
641b305b0f1Sespie
6422159047fSniklas case etree_unary:
643c074d1c9Sdrahn result = fold_unary (tree, current_section, allocation_done,
644c074d1c9Sdrahn dot, dotp);
6452159047fSniklas break;
6460c6d0228Sniklas
6472159047fSniklas case etree_binary:
6482159047fSniklas result = fold_binary (tree, current_section, allocation_done,
6492159047fSniklas dot, dotp);
6502159047fSniklas break;
6510c6d0228Sniklas
652c074d1c9Sdrahn case etree_trinary:
653c074d1c9Sdrahn result = fold_trinary (tree, current_section, allocation_done,
654c074d1c9Sdrahn dot, dotp);
655c074d1c9Sdrahn break;
656c074d1c9Sdrahn
6572159047fSniklas case etree_assign:
6582159047fSniklas case etree_provide:
659b55d4692Sfgsch case etree_provided:
6600c6d0228Sniklas if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
6610c6d0228Sniklas {
662c074d1c9Sdrahn /* Assignment to dot can only be done during allocation. */
663b55d4692Sfgsch if (tree->type.node_class != etree_assign)
664b305b0f1Sespie einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
665191aa565Sniklas if (allocation_done == lang_allocating_phase_enum
666191aa565Sniklas || (allocation_done == lang_final_phase_enum
6670c6d0228Sniklas && current_section == abs_output_section))
6680c6d0228Sniklas {
6692159047fSniklas result = exp_fold_tree (tree->assign.src,
6702159047fSniklas current_section,
671c074d1c9Sdrahn allocation_done, dot,
6720c6d0228Sniklas dotp);
673b305b0f1Sespie if (! result.valid_p)
674b305b0f1Sespie einfo (_("%F%S invalid assignment to location counter\n"));
6750c6d0228Sniklas else
6760c6d0228Sniklas {
6770c6d0228Sniklas if (current_section == NULL)
678b305b0f1Sespie einfo (_("%F%S assignment to location counter invalid outside of SECTION\n"));
6790c6d0228Sniklas else
6800c6d0228Sniklas {
6810c6d0228Sniklas bfd_vma nextdot;
6820c6d0228Sniklas
6830c6d0228Sniklas nextdot = (result.value
6840c6d0228Sniklas + current_section->bfd_section->vma);
6850c6d0228Sniklas if (nextdot < dot
6860c6d0228Sniklas && current_section != abs_output_section)
687b305b0f1Sespie einfo (_("%F%S cannot move location counter backwards (from %V to %V)\n"),
6880c6d0228Sniklas dot, nextdot);
6890c6d0228Sniklas else
6902159047fSniklas *dotp = nextdot;
6912159047fSniklas }
6922159047fSniklas }
6932159047fSniklas }
6942159047fSniklas }
6952159047fSniklas else
6962159047fSniklas {
6972159047fSniklas result = exp_fold_tree (tree->assign.src,
6982159047fSniklas current_section, allocation_done,
6992159047fSniklas dot, dotp);
700b305b0f1Sespie if (result.valid_p)
7012159047fSniklas {
702c074d1c9Sdrahn bfd_boolean create;
7032159047fSniklas struct bfd_link_hash_entry *h;
7042159047fSniklas
7050c6d0228Sniklas if (tree->type.node_class == etree_assign)
706c074d1c9Sdrahn create = TRUE;
7070c6d0228Sniklas else
708c074d1c9Sdrahn create = FALSE;
7092159047fSniklas h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
710*007c2a45Smiod create, FALSE, TRUE);
711*007c2a45Smiod if (h == NULL)
7122159047fSniklas {
713*007c2a45Smiod if (create)
714b305b0f1Sespie einfo (_("%P%F:%s: hash creation failed\n"),
7152159047fSniklas tree->assign.dst);
7162159047fSniklas }
7172159047fSniklas else if (tree->type.node_class == etree_provide
718*007c2a45Smiod && h->type != bfd_link_hash_new
7192159047fSniklas && h->type != bfd_link_hash_undefined
7202159047fSniklas && h->type != bfd_link_hash_common)
7212159047fSniklas {
7222159047fSniklas /* Do nothing. The symbol was defined by some
7232159047fSniklas object. */
7242159047fSniklas }
7252159047fSniklas else
7262159047fSniklas {
7272159047fSniklas /* FIXME: Should we worry if the symbol is already
7282159047fSniklas defined? */
729*007c2a45Smiod lang_update_definedness (tree->assign.dst, h);
7302159047fSniklas h->type = bfd_link_hash_defined;
7312159047fSniklas h->u.def.value = result.value;
7322159047fSniklas h->u.def.section = result.section->bfd_section;
733b55d4692Sfgsch if (tree->type.node_class == etree_provide)
734b55d4692Sfgsch tree->type.node_class = etree_provided;
7352159047fSniklas }
7362159047fSniklas }
7372159047fSniklas }
7382159047fSniklas break;
7390c6d0228Sniklas
7402159047fSniklas case etree_name:
7412159047fSniklas result = fold_name (tree, current_section, allocation_done, dot);
7422159047fSniklas break;
7432159047fSniklas
7440c6d0228Sniklas default:
7450c6d0228Sniklas FAIL ();
7460c6d0228Sniklas break;
7472159047fSniklas }
7482159047fSniklas
7492159047fSniklas return result;
7502159047fSniklas }
7512159047fSniklas
7522159047fSniklas static etree_value_type
exp_fold_tree_no_dot(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done)753*007c2a45Smiod exp_fold_tree_no_dot (etree_type *tree,
754*007c2a45Smiod lang_output_section_statement_type *current_section,
755*007c2a45Smiod lang_phase_type allocation_done)
7562159047fSniklas {
757*007c2a45Smiod return exp_fold_tree (tree, current_section, allocation_done, 0, NULL);
7582159047fSniklas }
7592159047fSniklas
7602159047fSniklas etree_type *
exp_binop(int code,etree_type * lhs,etree_type * rhs)761*007c2a45Smiod exp_binop (int code, etree_type *lhs, etree_type *rhs)
7622159047fSniklas {
7632159047fSniklas etree_type value, *new;
7642159047fSniklas etree_value_type r;
7652159047fSniklas
7662159047fSniklas value.type.node_code = code;
7672159047fSniklas value.binary.lhs = lhs;
7682159047fSniklas value.binary.rhs = rhs;
7692159047fSniklas value.type.node_class = etree_binary;
7702159047fSniklas r = exp_fold_tree_no_dot (&value,
7712159047fSniklas abs_output_section,
7722159047fSniklas lang_first_phase_enum);
773b305b0f1Sespie if (r.valid_p)
7742159047fSniklas {
7752159047fSniklas return exp_intop (r.value);
7762159047fSniklas }
777*007c2a45Smiod new = stat_alloc (sizeof (new->binary));
778*007c2a45Smiod memcpy (new, &value, sizeof (new->binary));
7792159047fSniklas return new;
7802159047fSniklas }
7812159047fSniklas
7822159047fSniklas etree_type *
exp_trinop(int code,etree_type * cond,etree_type * lhs,etree_type * rhs)783*007c2a45Smiod exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
7842159047fSniklas {
7852159047fSniklas etree_type value, *new;
7862159047fSniklas etree_value_type r;
7872159047fSniklas value.type.node_code = code;
7882159047fSniklas value.trinary.lhs = lhs;
7892159047fSniklas value.trinary.cond = cond;
7902159047fSniklas value.trinary.rhs = rhs;
7912159047fSniklas value.type.node_class = etree_trinary;
792*007c2a45Smiod r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
793b55d4692Sfgsch if (r.valid_p)
7942159047fSniklas return exp_intop (r.value);
795c074d1c9Sdrahn
796*007c2a45Smiod new = stat_alloc (sizeof (new->trinary));
797*007c2a45Smiod memcpy (new, &value, sizeof (new->trinary));
7982159047fSniklas return new;
7992159047fSniklas }
8002159047fSniklas
8012159047fSniklas etree_type *
exp_unop(int code,etree_type * child)802*007c2a45Smiod exp_unop (int code, etree_type *child)
8032159047fSniklas {
8042159047fSniklas etree_type value, *new;
8052159047fSniklas
8062159047fSniklas etree_value_type r;
8072159047fSniklas value.unary.type.node_code = code;
8082159047fSniklas value.unary.child = child;
8092159047fSniklas value.unary.type.node_class = etree_unary;
8102159047fSniklas r = exp_fold_tree_no_dot (&value, abs_output_section,
8112159047fSniklas lang_first_phase_enum);
812b55d4692Sfgsch if (r.valid_p)
8132159047fSniklas return exp_intop (r.value);
814c074d1c9Sdrahn
815*007c2a45Smiod new = stat_alloc (sizeof (new->unary));
816*007c2a45Smiod memcpy (new, &value, sizeof (new->unary));
8172159047fSniklas return new;
8182159047fSniklas }
8192159047fSniklas
8202159047fSniklas etree_type *
exp_nameop(int code,const char * name)821*007c2a45Smiod exp_nameop (int code, const char *name)
8222159047fSniklas {
8232159047fSniklas etree_type value, *new;
8242159047fSniklas etree_value_type r;
8252159047fSniklas value.name.type.node_code = code;
8262159047fSniklas value.name.name = name;
8272159047fSniklas value.name.type.node_class = etree_name;
8282159047fSniklas
829*007c2a45Smiod r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
830b55d4692Sfgsch if (r.valid_p)
8312159047fSniklas return exp_intop (r.value);
832c074d1c9Sdrahn
833*007c2a45Smiod new = stat_alloc (sizeof (new->name));
834*007c2a45Smiod memcpy (new, &value, sizeof (new->name));
8352159047fSniklas return new;
8362159047fSniklas
8372159047fSniklas }
8382159047fSniklas
8392159047fSniklas etree_type *
exp_assop(int code,const char * dst,etree_type * src)840*007c2a45Smiod exp_assop (int code, const char *dst, etree_type *src)
8412159047fSniklas {
8422159047fSniklas etree_type value, *new;
8432159047fSniklas
8442159047fSniklas value.assign.type.node_code = code;
8452159047fSniklas
8462159047fSniklas value.assign.src = src;
8472159047fSniklas value.assign.dst = dst;
8482159047fSniklas value.assign.type.node_class = etree_assign;
8492159047fSniklas
8502159047fSniklas #if 0
851b55d4692Sfgsch if (exp_fold_tree_no_dot (&value, &result))
8522159047fSniklas return exp_intop (result);
8532159047fSniklas #endif
854*007c2a45Smiod new = stat_alloc (sizeof (new->assign));
855*007c2a45Smiod memcpy (new, &value, sizeof (new->assign));
8562159047fSniklas return new;
8572159047fSniklas }
8582159047fSniklas
8592159047fSniklas /* Handle PROVIDE. */
8602159047fSniklas
8612159047fSniklas etree_type *
exp_provide(const char * dst,etree_type * src)862*007c2a45Smiod exp_provide (const char *dst, etree_type *src)
8632159047fSniklas {
8642159047fSniklas etree_type *n;
8652159047fSniklas
866*007c2a45Smiod n = stat_alloc (sizeof (n->assign));
8672159047fSniklas n->assign.type.node_code = '=';
8682159047fSniklas n->assign.type.node_class = etree_provide;
8692159047fSniklas n->assign.src = src;
8702159047fSniklas n->assign.dst = dst;
8712159047fSniklas return n;
8722159047fSniklas }
8732159047fSniklas
874b305b0f1Sespie /* Handle ASSERT. */
875b305b0f1Sespie
876b305b0f1Sespie etree_type *
exp_assert(etree_type * exp,const char * message)877*007c2a45Smiod exp_assert (etree_type *exp, const char *message)
878b305b0f1Sespie {
879b305b0f1Sespie etree_type *n;
880b305b0f1Sespie
881*007c2a45Smiod n = stat_alloc (sizeof (n->assert_s));
882b305b0f1Sespie n->assert_s.type.node_code = '!';
883b305b0f1Sespie n->assert_s.type.node_class = etree_assert;
884b305b0f1Sespie n->assert_s.child = exp;
885b305b0f1Sespie n->assert_s.message = message;
886b305b0f1Sespie return n;
887b305b0f1Sespie }
888b305b0f1Sespie
8892159047fSniklas void
exp_print_tree(etree_type * tree)890*007c2a45Smiod exp_print_tree (etree_type *tree)
8912159047fSniklas {
892c074d1c9Sdrahn if (config.map_file == NULL)
893c074d1c9Sdrahn config.map_file = stderr;
894c074d1c9Sdrahn
895c074d1c9Sdrahn if (tree == NULL)
896c074d1c9Sdrahn {
897c074d1c9Sdrahn minfo ("NULL TREE\n");
898c074d1c9Sdrahn return;
899c074d1c9Sdrahn }
900c074d1c9Sdrahn
901b55d4692Sfgsch switch (tree->type.node_class)
902b55d4692Sfgsch {
9032159047fSniklas case etree_value:
904191aa565Sniklas minfo ("0x%v", tree->value.value);
9052159047fSniklas return;
9062159047fSniklas case etree_rel:
9072159047fSniklas if (tree->rel.section->owner != NULL)
908191aa565Sniklas minfo ("%B:", tree->rel.section->owner);
909191aa565Sniklas minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
9102159047fSniklas return;
9112159047fSniklas case etree_assign:
9122159047fSniklas #if 0
913*007c2a45Smiod if (tree->assign.dst->sdefs != NULL)
9142159047fSniklas fprintf (config.map_file, "%s (%x) ", tree->assign.dst->name,
9152159047fSniklas tree->assign.dst->sdefs->value);
916b55d4692Sfgsch else
9172159047fSniklas fprintf (config.map_file, "%s (UNDEFINED)", tree->assign.dst->name);
9182159047fSniklas #endif
9192159047fSniklas fprintf (config.map_file, "%s", tree->assign.dst);
920c074d1c9Sdrahn exp_print_token (tree->type.node_code, TRUE);
9212159047fSniklas exp_print_tree (tree->assign.src);
9222159047fSniklas break;
9232159047fSniklas case etree_provide:
924b55d4692Sfgsch case etree_provided:
9252159047fSniklas fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
9262159047fSniklas exp_print_tree (tree->assign.src);
9272159047fSniklas fprintf (config.map_file, ")");
9282159047fSniklas break;
9292159047fSniklas case etree_binary:
9302159047fSniklas fprintf (config.map_file, "(");
9312159047fSniklas exp_print_tree (tree->binary.lhs);
932c074d1c9Sdrahn exp_print_token (tree->type.node_code, TRUE);
9332159047fSniklas exp_print_tree (tree->binary.rhs);
9342159047fSniklas fprintf (config.map_file, ")");
9352159047fSniklas break;
9362159047fSniklas case etree_trinary:
9372159047fSniklas exp_print_tree (tree->trinary.cond);
9382159047fSniklas fprintf (config.map_file, "?");
9392159047fSniklas exp_print_tree (tree->trinary.lhs);
9402159047fSniklas fprintf (config.map_file, ":");
9412159047fSniklas exp_print_tree (tree->trinary.rhs);
9422159047fSniklas break;
9432159047fSniklas case etree_unary:
944c074d1c9Sdrahn exp_print_token (tree->unary.type.node_code, FALSE);
9452159047fSniklas if (tree->unary.child)
9462159047fSniklas {
9472159047fSniklas fprintf (config.map_file, " (");
9482159047fSniklas exp_print_tree (tree->unary.child);
9492159047fSniklas fprintf (config.map_file, ")");
9502159047fSniklas }
9512159047fSniklas break;
952b305b0f1Sespie
953b305b0f1Sespie case etree_assert:
954b305b0f1Sespie fprintf (config.map_file, "ASSERT (");
955b305b0f1Sespie exp_print_tree (tree->assert_s.child);
956b305b0f1Sespie fprintf (config.map_file, ", %s)", tree->assert_s.message);
957b305b0f1Sespie break;
958b305b0f1Sespie
9592159047fSniklas case etree_undef:
9602159047fSniklas fprintf (config.map_file, "????????");
9612159047fSniklas break;
9622159047fSniklas case etree_name:
963b55d4692Sfgsch if (tree->type.node_code == NAME)
964b55d4692Sfgsch {
9652159047fSniklas fprintf (config.map_file, "%s", tree->name.name);
9662159047fSniklas }
967b55d4692Sfgsch else
968b55d4692Sfgsch {
969c074d1c9Sdrahn exp_print_token (tree->type.node_code, FALSE);
9702159047fSniklas if (tree->name.name)
9712159047fSniklas fprintf (config.map_file, " (%s)", tree->name.name);
9722159047fSniklas }
9732159047fSniklas break;
9742159047fSniklas default:
9752159047fSniklas FAIL ();
9762159047fSniklas break;
9772159047fSniklas }
9782159047fSniklas }
9792159047fSniklas
9802159047fSniklas bfd_vma
exp_get_vma(etree_type * tree,bfd_vma def,char * name,lang_phase_type allocation_done)981*007c2a45Smiod exp_get_vma (etree_type *tree,
982*007c2a45Smiod bfd_vma def,
983*007c2a45Smiod char *name,
984*007c2a45Smiod lang_phase_type allocation_done)
9852159047fSniklas {
9862159047fSniklas etree_value_type r;
9872159047fSniklas
9880c6d0228Sniklas if (tree != NULL)
9890c6d0228Sniklas {
9900c6d0228Sniklas r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
991b305b0f1Sespie if (! r.valid_p && name != NULL)
992b305b0f1Sespie einfo (_("%F%S nonconstant expression for %s\n"), name);
9932159047fSniklas return r.value;
9942159047fSniklas }
9950c6d0228Sniklas else
9962159047fSniklas return def;
9972159047fSniklas }
9982159047fSniklas
9992159047fSniklas int
exp_get_value_int(etree_type * tree,int def,char * name,lang_phase_type allocation_done)1000*007c2a45Smiod exp_get_value_int (etree_type *tree,
1001*007c2a45Smiod int def,
1002*007c2a45Smiod char *name,
1003*007c2a45Smiod lang_phase_type allocation_done)
10042159047fSniklas {
1005*007c2a45Smiod return exp_get_vma (tree, def, name, allocation_done);
10062159047fSniklas }
10072159047fSniklas
1008c074d1c9Sdrahn fill_type *
exp_get_fill(etree_type * tree,fill_type * def,char * name,lang_phase_type allocation_done)1009*007c2a45Smiod exp_get_fill (etree_type *tree,
1010*007c2a45Smiod fill_type *def,
1011*007c2a45Smiod char *name,
1012*007c2a45Smiod lang_phase_type allocation_done)
1013c074d1c9Sdrahn {
1014c074d1c9Sdrahn fill_type *fill;
1015c074d1c9Sdrahn etree_value_type r;
1016c074d1c9Sdrahn size_t len;
1017c074d1c9Sdrahn unsigned int val;
1018c074d1c9Sdrahn
1019c074d1c9Sdrahn if (tree == NULL)
1020c074d1c9Sdrahn return def;
1021c074d1c9Sdrahn
1022c074d1c9Sdrahn r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
1023c074d1c9Sdrahn if (! r.valid_p && name != NULL)
1024c074d1c9Sdrahn einfo (_("%F%S nonconstant expression for %s\n"), name);
1025c074d1c9Sdrahn
1026c074d1c9Sdrahn if (r.str != NULL && (len = strlen (r.str)) != 0)
1027c074d1c9Sdrahn {
1028c074d1c9Sdrahn unsigned char *dst;
1029c074d1c9Sdrahn unsigned char *s;
1030*007c2a45Smiod fill = xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
1031c074d1c9Sdrahn fill->size = (len + 1) / 2;
1032c074d1c9Sdrahn dst = fill->data;
1033c074d1c9Sdrahn s = r.str;
1034c074d1c9Sdrahn val = 0;
1035c074d1c9Sdrahn do
1036c074d1c9Sdrahn {
1037c074d1c9Sdrahn unsigned int digit;
1038c074d1c9Sdrahn
1039c074d1c9Sdrahn digit = *s++ - '0';
1040c074d1c9Sdrahn if (digit > 9)
1041c074d1c9Sdrahn digit = (digit - 'A' + '0' + 10) & 0xf;
1042c074d1c9Sdrahn val <<= 4;
1043c074d1c9Sdrahn val += digit;
1044c074d1c9Sdrahn --len;
1045c074d1c9Sdrahn if ((len & 1) == 0)
1046c074d1c9Sdrahn {
1047c074d1c9Sdrahn *dst++ = val;
1048c074d1c9Sdrahn val = 0;
1049c074d1c9Sdrahn }
1050c074d1c9Sdrahn }
1051c074d1c9Sdrahn while (len != 0);
1052c074d1c9Sdrahn }
1053c074d1c9Sdrahn else
1054c074d1c9Sdrahn {
1055*007c2a45Smiod fill = xmalloc (4 + sizeof (*fill) - 1);
1056c074d1c9Sdrahn val = r.value;
1057c074d1c9Sdrahn fill->data[0] = (val >> 24) & 0xff;
1058c074d1c9Sdrahn fill->data[1] = (val >> 16) & 0xff;
1059c074d1c9Sdrahn fill->data[2] = (val >> 8) & 0xff;
1060c074d1c9Sdrahn fill->data[3] = (val >> 0) & 0xff;
1061c074d1c9Sdrahn fill->size = 4;
1062c074d1c9Sdrahn }
1063c074d1c9Sdrahn return fill;
1064c074d1c9Sdrahn }
1065c074d1c9Sdrahn
10662159047fSniklas bfd_vma
exp_get_abs_int(etree_type * tree,int def ATTRIBUTE_UNUSED,char * name,lang_phase_type allocation_done)1067*007c2a45Smiod exp_get_abs_int (etree_type *tree,
1068*007c2a45Smiod int def ATTRIBUTE_UNUSED,
1069*007c2a45Smiod char *name,
1070*007c2a45Smiod lang_phase_type allocation_done)
10712159047fSniklas {
10722159047fSniklas etree_value_type res;
10732159047fSniklas res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
10742159047fSniklas
1075b305b0f1Sespie if (res.valid_p)
10762159047fSniklas res.value += res.section->bfd_section->vma;
1077b55d4692Sfgsch else
1078b305b0f1Sespie einfo (_("%F%S non constant expression for %s\n"), name);
1079c074d1c9Sdrahn
10802159047fSniklas return res.value;
10812159047fSniklas }
1082c074d1c9Sdrahn
1083*007c2a45Smiod static bfd_vma
align_n(bfd_vma value,bfd_vma align)1084*007c2a45Smiod align_n (bfd_vma value, bfd_vma align)
1085c074d1c9Sdrahn {
1086c074d1c9Sdrahn if (align <= 1)
1087c074d1c9Sdrahn return value;
1088c074d1c9Sdrahn
1089c074d1c9Sdrahn value = (value + align - 1) / align;
1090c074d1c9Sdrahn return value * align;
1091c074d1c9Sdrahn }
1092