1*3d8817e4Smiod /* This module handles expression trees.
2*3d8817e4Smiod Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3*3d8817e4Smiod 2001, 2002, 2003, 2004, 2005
4*3d8817e4Smiod Free Software Foundation, Inc.
5*3d8817e4Smiod Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
6*3d8817e4Smiod
7*3d8817e4Smiod This file is part of GLD, the Gnu Linker.
8*3d8817e4Smiod
9*3d8817e4Smiod GLD is free software; you can redistribute it and/or modify
10*3d8817e4Smiod it under the terms of the GNU General Public License as published by
11*3d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
12*3d8817e4Smiod any later version.
13*3d8817e4Smiod
14*3d8817e4Smiod GLD is distributed in the hope that it will be useful,
15*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
16*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*3d8817e4Smiod GNU General Public License for more details.
18*3d8817e4Smiod
19*3d8817e4Smiod You should have received a copy of the GNU General Public License
20*3d8817e4Smiod along with GLD; see the file COPYING. If not, write to the Free
21*3d8817e4Smiod Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
22*3d8817e4Smiod 02110-1301, USA. */
23*3d8817e4Smiod
24*3d8817e4Smiod /* This module is in charge of working out the contents of expressions.
25*3d8817e4Smiod
26*3d8817e4Smiod It has to keep track of the relative/absness of a symbol etc. This
27*3d8817e4Smiod is done by keeping all values in a struct (an etree_value_type)
28*3d8817e4Smiod which contains a value, a section to which it is relative and a
29*3d8817e4Smiod valid bit. */
30*3d8817e4Smiod
31*3d8817e4Smiod #include "bfd.h"
32*3d8817e4Smiod #include "sysdep.h"
33*3d8817e4Smiod #include "bfdlink.h"
34*3d8817e4Smiod
35*3d8817e4Smiod #include "ld.h"
36*3d8817e4Smiod #include "ldmain.h"
37*3d8817e4Smiod #include "ldmisc.h"
38*3d8817e4Smiod #include "ldexp.h"
39*3d8817e4Smiod #include <ldgram.h>
40*3d8817e4Smiod #include "ldlang.h"
41*3d8817e4Smiod #include "libiberty.h"
42*3d8817e4Smiod #include "safe-ctype.h"
43*3d8817e4Smiod
44*3d8817e4Smiod static void exp_fold_tree_1 (etree_type *);
45*3d8817e4Smiod static void exp_fold_tree_no_dot (etree_type *);
46*3d8817e4Smiod static bfd_vma align_n (bfd_vma, bfd_vma);
47*3d8817e4Smiod
48*3d8817e4Smiod segment_type *segments;
49*3d8817e4Smiod
50*3d8817e4Smiod struct ldexp_control expld;
51*3d8817e4Smiod
52*3d8817e4Smiod /* Print the string representation of the given token. Surround it
53*3d8817e4Smiod with spaces if INFIX_P is TRUE. */
54*3d8817e4Smiod
55*3d8817e4Smiod static void
exp_print_token(token_code_type code,int infix_p)56*3d8817e4Smiod exp_print_token (token_code_type code, int infix_p)
57*3d8817e4Smiod {
58*3d8817e4Smiod static const struct
59*3d8817e4Smiod {
60*3d8817e4Smiod token_code_type code;
61*3d8817e4Smiod char * name;
62*3d8817e4Smiod }
63*3d8817e4Smiod table[] =
64*3d8817e4Smiod {
65*3d8817e4Smiod { INT, "int" },
66*3d8817e4Smiod { NAME, "NAME" },
67*3d8817e4Smiod { PLUSEQ, "+=" },
68*3d8817e4Smiod { MINUSEQ, "-=" },
69*3d8817e4Smiod { MULTEQ, "*=" },
70*3d8817e4Smiod { DIVEQ, "/=" },
71*3d8817e4Smiod { LSHIFTEQ, "<<=" },
72*3d8817e4Smiod { RSHIFTEQ, ">>=" },
73*3d8817e4Smiod { ANDEQ, "&=" },
74*3d8817e4Smiod { OREQ, "|=" },
75*3d8817e4Smiod { OROR, "||" },
76*3d8817e4Smiod { ANDAND, "&&" },
77*3d8817e4Smiod { EQ, "==" },
78*3d8817e4Smiod { NE, "!=" },
79*3d8817e4Smiod { LE, "<=" },
80*3d8817e4Smiod { GE, ">=" },
81*3d8817e4Smiod { LSHIFT, "<<" },
82*3d8817e4Smiod { RSHIFT, ">>" },
83*3d8817e4Smiod { ALIGN_K, "ALIGN" },
84*3d8817e4Smiod { BLOCK, "BLOCK" },
85*3d8817e4Smiod { QUAD, "QUAD" },
86*3d8817e4Smiod { SQUAD, "SQUAD" },
87*3d8817e4Smiod { LONG, "LONG" },
88*3d8817e4Smiod { SHORT, "SHORT" },
89*3d8817e4Smiod { BYTE, "BYTE" },
90*3d8817e4Smiod { SECTIONS, "SECTIONS" },
91*3d8817e4Smiod { SIZEOF_HEADERS, "SIZEOF_HEADERS" },
92*3d8817e4Smiod { MEMORY, "MEMORY" },
93*3d8817e4Smiod { DEFINED, "DEFINED" },
94*3d8817e4Smiod { TARGET_K, "TARGET" },
95*3d8817e4Smiod { SEARCH_DIR, "SEARCH_DIR" },
96*3d8817e4Smiod { MAP, "MAP" },
97*3d8817e4Smiod { ENTRY, "ENTRY" },
98*3d8817e4Smiod { NEXT, "NEXT" },
99*3d8817e4Smiod { SIZEOF, "SIZEOF" },
100*3d8817e4Smiod { ADDR, "ADDR" },
101*3d8817e4Smiod { LOADADDR, "LOADADDR" },
102*3d8817e4Smiod { MAX_K, "MAX_K" },
103*3d8817e4Smiod { REL, "relocatable" },
104*3d8817e4Smiod { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
105*3d8817e4Smiod { DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
106*3d8817e4Smiod { DATA_SEGMENT_END, "DATA_SEGMENT_END" },
107*3d8817e4Smiod { ORIGIN, "ORIGIN" },
108*3d8817e4Smiod { LENGTH, "LENGTH" },
109*3d8817e4Smiod { SEGMENT_START, "SEGMENT_START" }
110*3d8817e4Smiod };
111*3d8817e4Smiod unsigned int idx;
112*3d8817e4Smiod
113*3d8817e4Smiod for (idx = 0; idx < ARRAY_SIZE (table); idx++)
114*3d8817e4Smiod if (table[idx].code == code)
115*3d8817e4Smiod break;
116*3d8817e4Smiod
117*3d8817e4Smiod if (infix_p)
118*3d8817e4Smiod fputc (' ', config.map_file);
119*3d8817e4Smiod
120*3d8817e4Smiod if (idx < ARRAY_SIZE (table))
121*3d8817e4Smiod fputs (table[idx].name, config.map_file);
122*3d8817e4Smiod else if (code < 127)
123*3d8817e4Smiod fputc (code, config.map_file);
124*3d8817e4Smiod else
125*3d8817e4Smiod fprintf (config.map_file, "<code %d>", code);
126*3d8817e4Smiod
127*3d8817e4Smiod if (infix_p)
128*3d8817e4Smiod fputc (' ', config.map_file);
129*3d8817e4Smiod }
130*3d8817e4Smiod
131*3d8817e4Smiod static void
make_abs(void)132*3d8817e4Smiod make_abs (void)
133*3d8817e4Smiod {
134*3d8817e4Smiod expld.result.value += expld.result.section->vma;
135*3d8817e4Smiod expld.result.section = bfd_abs_section_ptr;
136*3d8817e4Smiod }
137*3d8817e4Smiod
138*3d8817e4Smiod static void
new_abs(bfd_vma value)139*3d8817e4Smiod new_abs (bfd_vma value)
140*3d8817e4Smiod {
141*3d8817e4Smiod expld.result.valid_p = TRUE;
142*3d8817e4Smiod expld.result.section = bfd_abs_section_ptr;
143*3d8817e4Smiod expld.result.value = value;
144*3d8817e4Smiod expld.result.str = NULL;
145*3d8817e4Smiod }
146*3d8817e4Smiod
147*3d8817e4Smiod etree_type *
exp_intop(bfd_vma value)148*3d8817e4Smiod exp_intop (bfd_vma value)
149*3d8817e4Smiod {
150*3d8817e4Smiod etree_type *new = stat_alloc (sizeof (new->value));
151*3d8817e4Smiod new->type.node_code = INT;
152*3d8817e4Smiod new->value.value = value;
153*3d8817e4Smiod new->value.str = NULL;
154*3d8817e4Smiod new->type.node_class = etree_value;
155*3d8817e4Smiod return new;
156*3d8817e4Smiod }
157*3d8817e4Smiod
158*3d8817e4Smiod etree_type *
exp_bigintop(bfd_vma value,char * str)159*3d8817e4Smiod exp_bigintop (bfd_vma value, char *str)
160*3d8817e4Smiod {
161*3d8817e4Smiod etree_type *new = stat_alloc (sizeof (new->value));
162*3d8817e4Smiod new->type.node_code = INT;
163*3d8817e4Smiod new->value.value = value;
164*3d8817e4Smiod new->value.str = str;
165*3d8817e4Smiod new->type.node_class = etree_value;
166*3d8817e4Smiod return new;
167*3d8817e4Smiod }
168*3d8817e4Smiod
169*3d8817e4Smiod /* Build an expression representing an unnamed relocatable value. */
170*3d8817e4Smiod
171*3d8817e4Smiod etree_type *
exp_relop(asection * section,bfd_vma value)172*3d8817e4Smiod exp_relop (asection *section, bfd_vma value)
173*3d8817e4Smiod {
174*3d8817e4Smiod etree_type *new = stat_alloc (sizeof (new->rel));
175*3d8817e4Smiod new->type.node_code = REL;
176*3d8817e4Smiod new->type.node_class = etree_rel;
177*3d8817e4Smiod new->rel.section = section;
178*3d8817e4Smiod new->rel.value = value;
179*3d8817e4Smiod return new;
180*3d8817e4Smiod }
181*3d8817e4Smiod
182*3d8817e4Smiod static void
new_rel(bfd_vma value,char * str,asection * section)183*3d8817e4Smiod new_rel (bfd_vma value, char *str, asection *section)
184*3d8817e4Smiod {
185*3d8817e4Smiod expld.result.valid_p = TRUE;
186*3d8817e4Smiod expld.result.value = value;
187*3d8817e4Smiod expld.result.str = str;
188*3d8817e4Smiod expld.result.section = section;
189*3d8817e4Smiod }
190*3d8817e4Smiod
191*3d8817e4Smiod static void
new_rel_from_abs(bfd_vma value)192*3d8817e4Smiod new_rel_from_abs (bfd_vma value)
193*3d8817e4Smiod {
194*3d8817e4Smiod expld.result.valid_p = TRUE;
195*3d8817e4Smiod expld.result.value = value - expld.section->vma;
196*3d8817e4Smiod expld.result.str = NULL;
197*3d8817e4Smiod expld.result.section = expld.section;
198*3d8817e4Smiod }
199*3d8817e4Smiod
200*3d8817e4Smiod static void
fold_unary(etree_type * tree)201*3d8817e4Smiod fold_unary (etree_type *tree)
202*3d8817e4Smiod {
203*3d8817e4Smiod exp_fold_tree_1 (tree->unary.child);
204*3d8817e4Smiod if (expld.result.valid_p)
205*3d8817e4Smiod {
206*3d8817e4Smiod switch (tree->type.node_code)
207*3d8817e4Smiod {
208*3d8817e4Smiod case ALIGN_K:
209*3d8817e4Smiod if (expld.phase != lang_first_phase_enum)
210*3d8817e4Smiod new_rel_from_abs (align_n (expld.dot, expld.result.value));
211*3d8817e4Smiod else
212*3d8817e4Smiod expld.result.valid_p = FALSE;
213*3d8817e4Smiod break;
214*3d8817e4Smiod
215*3d8817e4Smiod case ABSOLUTE:
216*3d8817e4Smiod make_abs ();
217*3d8817e4Smiod break;
218*3d8817e4Smiod
219*3d8817e4Smiod case '~':
220*3d8817e4Smiod make_abs ();
221*3d8817e4Smiod expld.result.value = ~expld.result.value;
222*3d8817e4Smiod break;
223*3d8817e4Smiod
224*3d8817e4Smiod case '!':
225*3d8817e4Smiod make_abs ();
226*3d8817e4Smiod expld.result.value = !expld.result.value;
227*3d8817e4Smiod break;
228*3d8817e4Smiod
229*3d8817e4Smiod case '-':
230*3d8817e4Smiod make_abs ();
231*3d8817e4Smiod expld.result.value = -expld.result.value;
232*3d8817e4Smiod break;
233*3d8817e4Smiod
234*3d8817e4Smiod case NEXT:
235*3d8817e4Smiod /* Return next place aligned to value. */
236*3d8817e4Smiod if (expld.phase != lang_first_phase_enum)
237*3d8817e4Smiod {
238*3d8817e4Smiod make_abs ();
239*3d8817e4Smiod expld.result.value = align_n (expld.dot, expld.result.value);
240*3d8817e4Smiod }
241*3d8817e4Smiod else
242*3d8817e4Smiod expld.result.valid_p = FALSE;
243*3d8817e4Smiod break;
244*3d8817e4Smiod
245*3d8817e4Smiod case DATA_SEGMENT_END:
246*3d8817e4Smiod if (expld.phase != lang_first_phase_enum
247*3d8817e4Smiod && expld.section == bfd_abs_section_ptr
248*3d8817e4Smiod && (expld.dataseg.phase == exp_dataseg_align_seen
249*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_relro_seen
250*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_adjust
251*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_relro_adjust
252*3d8817e4Smiod || expld.phase == lang_final_phase_enum))
253*3d8817e4Smiod {
254*3d8817e4Smiod if (expld.dataseg.phase == exp_dataseg_align_seen
255*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_relro_seen)
256*3d8817e4Smiod {
257*3d8817e4Smiod expld.dataseg.phase = exp_dataseg_end_seen;
258*3d8817e4Smiod expld.dataseg.end = expld.result.value;
259*3d8817e4Smiod }
260*3d8817e4Smiod }
261*3d8817e4Smiod else
262*3d8817e4Smiod expld.result.valid_p = FALSE;
263*3d8817e4Smiod break;
264*3d8817e4Smiod
265*3d8817e4Smiod default:
266*3d8817e4Smiod FAIL ();
267*3d8817e4Smiod break;
268*3d8817e4Smiod }
269*3d8817e4Smiod }
270*3d8817e4Smiod }
271*3d8817e4Smiod
272*3d8817e4Smiod static void
fold_binary(etree_type * tree)273*3d8817e4Smiod fold_binary (etree_type *tree)
274*3d8817e4Smiod {
275*3d8817e4Smiod exp_fold_tree_1 (tree->binary.lhs);
276*3d8817e4Smiod
277*3d8817e4Smiod /* The SEGMENT_START operator is special because its first
278*3d8817e4Smiod operand is a string, not the name of a symbol. */
279*3d8817e4Smiod if (expld.result.valid_p && tree->type.node_code == SEGMENT_START)
280*3d8817e4Smiod {
281*3d8817e4Smiod const char *segment_name;
282*3d8817e4Smiod segment_type *seg;
283*3d8817e4Smiod /* Check to see if the user has overridden the default
284*3d8817e4Smiod value. */
285*3d8817e4Smiod segment_name = tree->binary.rhs->name.name;
286*3d8817e4Smiod for (seg = segments; seg; seg = seg->next)
287*3d8817e4Smiod if (strcmp (seg->name, segment_name) == 0)
288*3d8817e4Smiod {
289*3d8817e4Smiod seg->used = TRUE;
290*3d8817e4Smiod expld.result.value = seg->value;
291*3d8817e4Smiod expld.result.str = NULL;
292*3d8817e4Smiod expld.result.section = NULL;
293*3d8817e4Smiod break;
294*3d8817e4Smiod }
295*3d8817e4Smiod }
296*3d8817e4Smiod else if (expld.result.valid_p)
297*3d8817e4Smiod {
298*3d8817e4Smiod etree_value_type lhs = expld.result;
299*3d8817e4Smiod
300*3d8817e4Smiod exp_fold_tree_1 (tree->binary.rhs);
301*3d8817e4Smiod if (expld.result.valid_p)
302*3d8817e4Smiod {
303*3d8817e4Smiod /* If the values are from different sections, or this is an
304*3d8817e4Smiod absolute expression, make both the source arguments
305*3d8817e4Smiod absolute. However, adding or subtracting an absolute
306*3d8817e4Smiod value from a relative value is meaningful, and is an
307*3d8817e4Smiod exception. */
308*3d8817e4Smiod if (expld.section != bfd_abs_section_ptr
309*3d8817e4Smiod && lhs.section == bfd_abs_section_ptr
310*3d8817e4Smiod && tree->type.node_code == '+')
311*3d8817e4Smiod {
312*3d8817e4Smiod /* Keep the section of the rhs term. */
313*3d8817e4Smiod expld.result.value = lhs.value + expld.result.value;
314*3d8817e4Smiod return;
315*3d8817e4Smiod }
316*3d8817e4Smiod else if (expld.section != bfd_abs_section_ptr
317*3d8817e4Smiod && expld.result.section == bfd_abs_section_ptr
318*3d8817e4Smiod && (tree->type.node_code == '+'
319*3d8817e4Smiod || tree->type.node_code == '-'))
320*3d8817e4Smiod {
321*3d8817e4Smiod /* Keep the section of the lhs term. */
322*3d8817e4Smiod expld.result.section = lhs.section;
323*3d8817e4Smiod }
324*3d8817e4Smiod else if (expld.result.section != lhs.section
325*3d8817e4Smiod || expld.section == bfd_abs_section_ptr)
326*3d8817e4Smiod {
327*3d8817e4Smiod make_abs ();
328*3d8817e4Smiod lhs.value += lhs.section->vma;
329*3d8817e4Smiod }
330*3d8817e4Smiod
331*3d8817e4Smiod switch (tree->type.node_code)
332*3d8817e4Smiod {
333*3d8817e4Smiod case '%':
334*3d8817e4Smiod if (expld.result.value != 0)
335*3d8817e4Smiod expld.result.value = ((bfd_signed_vma) lhs.value
336*3d8817e4Smiod % (bfd_signed_vma) expld.result.value);
337*3d8817e4Smiod else if (expld.phase != lang_mark_phase_enum)
338*3d8817e4Smiod einfo (_("%F%S %% by zero\n"));
339*3d8817e4Smiod break;
340*3d8817e4Smiod
341*3d8817e4Smiod case '/':
342*3d8817e4Smiod if (expld.result.value != 0)
343*3d8817e4Smiod expld.result.value = ((bfd_signed_vma) lhs.value
344*3d8817e4Smiod / (bfd_signed_vma) expld.result.value);
345*3d8817e4Smiod else if (expld.phase != lang_mark_phase_enum)
346*3d8817e4Smiod einfo (_("%F%S / by zero\n"));
347*3d8817e4Smiod break;
348*3d8817e4Smiod
349*3d8817e4Smiod #define BOP(x, y) \
350*3d8817e4Smiod case x: \
351*3d8817e4Smiod expld.result.value = lhs.value y expld.result.value; \
352*3d8817e4Smiod break;
353*3d8817e4Smiod
354*3d8817e4Smiod BOP ('+', +);
355*3d8817e4Smiod BOP ('*', *);
356*3d8817e4Smiod BOP ('-', -);
357*3d8817e4Smiod BOP (LSHIFT, <<);
358*3d8817e4Smiod BOP (RSHIFT, >>);
359*3d8817e4Smiod BOP (EQ, ==);
360*3d8817e4Smiod BOP (NE, !=);
361*3d8817e4Smiod BOP ('<', <);
362*3d8817e4Smiod BOP ('>', >);
363*3d8817e4Smiod BOP (LE, <=);
364*3d8817e4Smiod BOP (GE, >=);
365*3d8817e4Smiod BOP ('&', &);
366*3d8817e4Smiod BOP ('^', ^);
367*3d8817e4Smiod BOP ('|', |);
368*3d8817e4Smiod BOP (ANDAND, &&);
369*3d8817e4Smiod BOP (OROR, ||);
370*3d8817e4Smiod
371*3d8817e4Smiod case MAX_K:
372*3d8817e4Smiod if (lhs.value > expld.result.value)
373*3d8817e4Smiod expld.result.value = lhs.value;
374*3d8817e4Smiod break;
375*3d8817e4Smiod
376*3d8817e4Smiod case MIN_K:
377*3d8817e4Smiod if (lhs.value < expld.result.value)
378*3d8817e4Smiod expld.result.value = lhs.value;
379*3d8817e4Smiod break;
380*3d8817e4Smiod
381*3d8817e4Smiod case ALIGN_K:
382*3d8817e4Smiod expld.result.value = align_n (lhs.value, expld.result.value);
383*3d8817e4Smiod break;
384*3d8817e4Smiod
385*3d8817e4Smiod case DATA_SEGMENT_ALIGN:
386*3d8817e4Smiod if (expld.phase != lang_first_phase_enum
387*3d8817e4Smiod && expld.section == bfd_abs_section_ptr
388*3d8817e4Smiod && (expld.dataseg.phase == exp_dataseg_none
389*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_adjust
390*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_relro_adjust
391*3d8817e4Smiod || expld.phase == lang_final_phase_enum))
392*3d8817e4Smiod {
393*3d8817e4Smiod bfd_vma maxpage = lhs.value;
394*3d8817e4Smiod bfd_vma commonpage = expld.result.value;
395*3d8817e4Smiod
396*3d8817e4Smiod expld.result.value = align_n (expld.dot, maxpage);
397*3d8817e4Smiod if (expld.dataseg.phase == exp_dataseg_relro_adjust)
398*3d8817e4Smiod expld.result.value = expld.dataseg.base;
399*3d8817e4Smiod else if (expld.dataseg.phase != exp_dataseg_adjust)
400*3d8817e4Smiod {
401*3d8817e4Smiod expld.result.value += expld.dot & (maxpage - 1);
402*3d8817e4Smiod if (expld.phase == lang_allocating_phase_enum)
403*3d8817e4Smiod {
404*3d8817e4Smiod expld.dataseg.phase = exp_dataseg_align_seen;
405*3d8817e4Smiod expld.dataseg.min_base = align_n (expld.dot, maxpage);
406*3d8817e4Smiod expld.dataseg.base = expld.result.value;
407*3d8817e4Smiod expld.dataseg.pagesize = commonpage;
408*3d8817e4Smiod expld.dataseg.maxpagesize = maxpage;
409*3d8817e4Smiod expld.dataseg.relro_end = 0;
410*3d8817e4Smiod }
411*3d8817e4Smiod }
412*3d8817e4Smiod else if (commonpage < maxpage)
413*3d8817e4Smiod expld.result.value += ((expld.dot + commonpage - 1)
414*3d8817e4Smiod & (maxpage - commonpage));
415*3d8817e4Smiod }
416*3d8817e4Smiod else
417*3d8817e4Smiod expld.result.valid_p = FALSE;
418*3d8817e4Smiod break;
419*3d8817e4Smiod
420*3d8817e4Smiod case DATA_SEGMENT_RELRO_END:
421*3d8817e4Smiod if (expld.phase != lang_first_phase_enum
422*3d8817e4Smiod && (expld.dataseg.phase == exp_dataseg_align_seen
423*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_adjust
424*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_relro_adjust
425*3d8817e4Smiod || expld.phase == lang_final_phase_enum))
426*3d8817e4Smiod {
427*3d8817e4Smiod if (expld.dataseg.phase == exp_dataseg_align_seen
428*3d8817e4Smiod || expld.dataseg.phase == exp_dataseg_relro_adjust)
429*3d8817e4Smiod expld.dataseg.relro_end = lhs.value + expld.result.value;
430*3d8817e4Smiod
431*3d8817e4Smiod if (expld.dataseg.phase == exp_dataseg_relro_adjust
432*3d8817e4Smiod && (expld.dataseg.relro_end
433*3d8817e4Smiod & (expld.dataseg.pagesize - 1)))
434*3d8817e4Smiod {
435*3d8817e4Smiod expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
436*3d8817e4Smiod expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
437*3d8817e4Smiod expld.result.value = (expld.dataseg.relro_end
438*3d8817e4Smiod - expld.result.value);
439*3d8817e4Smiod }
440*3d8817e4Smiod else
441*3d8817e4Smiod expld.result.value = lhs.value;
442*3d8817e4Smiod
443*3d8817e4Smiod if (expld.dataseg.phase == exp_dataseg_align_seen)
444*3d8817e4Smiod expld.dataseg.phase = exp_dataseg_relro_seen;
445*3d8817e4Smiod }
446*3d8817e4Smiod else
447*3d8817e4Smiod expld.result.valid_p = FALSE;
448*3d8817e4Smiod break;
449*3d8817e4Smiod
450*3d8817e4Smiod default:
451*3d8817e4Smiod FAIL ();
452*3d8817e4Smiod }
453*3d8817e4Smiod }
454*3d8817e4Smiod else
455*3d8817e4Smiod expld.result.valid_p = FALSE;
456*3d8817e4Smiod }
457*3d8817e4Smiod }
458*3d8817e4Smiod
459*3d8817e4Smiod static void
fold_trinary(etree_type * tree)460*3d8817e4Smiod fold_trinary (etree_type *tree)
461*3d8817e4Smiod {
462*3d8817e4Smiod exp_fold_tree_1 (tree->trinary.cond);
463*3d8817e4Smiod if (expld.result.valid_p)
464*3d8817e4Smiod exp_fold_tree_1 (expld.result.value
465*3d8817e4Smiod ? tree->trinary.lhs
466*3d8817e4Smiod : tree->trinary.rhs);
467*3d8817e4Smiod }
468*3d8817e4Smiod
469*3d8817e4Smiod static void
fold_name(etree_type * tree)470*3d8817e4Smiod fold_name (etree_type *tree)
471*3d8817e4Smiod {
472*3d8817e4Smiod memset (&expld.result, 0, sizeof (expld.result));
473*3d8817e4Smiod
474*3d8817e4Smiod switch (tree->type.node_code)
475*3d8817e4Smiod {
476*3d8817e4Smiod case SIZEOF_HEADERS:
477*3d8817e4Smiod if (expld.phase != lang_first_phase_enum)
478*3d8817e4Smiod {
479*3d8817e4Smiod bfd_vma hdr_size = 0;
480*3d8817e4Smiod /* Don't find the real header size if only marking sections;
481*3d8817e4Smiod The bfd function may cache incorrect data. */
482*3d8817e4Smiod if (expld.phase != lang_mark_phase_enum)
483*3d8817e4Smiod hdr_size = bfd_sizeof_headers (output_bfd, link_info.relocatable);
484*3d8817e4Smiod new_abs (hdr_size);
485*3d8817e4Smiod }
486*3d8817e4Smiod break;
487*3d8817e4Smiod case DEFINED:
488*3d8817e4Smiod if (expld.phase == lang_first_phase_enum)
489*3d8817e4Smiod lang_track_definedness (tree->name.name);
490*3d8817e4Smiod else
491*3d8817e4Smiod {
492*3d8817e4Smiod struct bfd_link_hash_entry *h;
493*3d8817e4Smiod int def_iteration
494*3d8817e4Smiod = lang_symbol_definition_iteration (tree->name.name);
495*3d8817e4Smiod
496*3d8817e4Smiod h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
497*3d8817e4Smiod tree->name.name,
498*3d8817e4Smiod FALSE, FALSE, TRUE);
499*3d8817e4Smiod expld.result.value = (h != NULL
500*3d8817e4Smiod && (h->type == bfd_link_hash_defined
501*3d8817e4Smiod || h->type == bfd_link_hash_defweak
502*3d8817e4Smiod || h->type == bfd_link_hash_common)
503*3d8817e4Smiod && (def_iteration == lang_statement_iteration
504*3d8817e4Smiod || def_iteration == -1));
505*3d8817e4Smiod expld.result.section = bfd_abs_section_ptr;
506*3d8817e4Smiod expld.result.valid_p = TRUE;
507*3d8817e4Smiod }
508*3d8817e4Smiod break;
509*3d8817e4Smiod case NAME:
510*3d8817e4Smiod if (expld.phase == lang_first_phase_enum)
511*3d8817e4Smiod ;
512*3d8817e4Smiod else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
513*3d8817e4Smiod new_rel_from_abs (expld.dot);
514*3d8817e4Smiod else
515*3d8817e4Smiod {
516*3d8817e4Smiod struct bfd_link_hash_entry *h;
517*3d8817e4Smiod
518*3d8817e4Smiod h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
519*3d8817e4Smiod tree->name.name,
520*3d8817e4Smiod TRUE, FALSE, TRUE);
521*3d8817e4Smiod if (!h)
522*3d8817e4Smiod einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
523*3d8817e4Smiod else if (h->type == bfd_link_hash_defined
524*3d8817e4Smiod || h->type == bfd_link_hash_defweak)
525*3d8817e4Smiod {
526*3d8817e4Smiod if (bfd_is_abs_section (h->u.def.section))
527*3d8817e4Smiod new_abs (h->u.def.value);
528*3d8817e4Smiod else
529*3d8817e4Smiod {
530*3d8817e4Smiod asection *output_section;
531*3d8817e4Smiod
532*3d8817e4Smiod output_section = h->u.def.section->output_section;
533*3d8817e4Smiod if (output_section == NULL)
534*3d8817e4Smiod {
535*3d8817e4Smiod if (expld.phase != lang_mark_phase_enum)
536*3d8817e4Smiod einfo (_("%X%S: unresolvable symbol `%s'"
537*3d8817e4Smiod " referenced in expression\n"),
538*3d8817e4Smiod tree->name.name);
539*3d8817e4Smiod }
540*3d8817e4Smiod else
541*3d8817e4Smiod new_rel (h->u.def.value + h->u.def.section->output_offset,
542*3d8817e4Smiod NULL, output_section);
543*3d8817e4Smiod }
544*3d8817e4Smiod }
545*3d8817e4Smiod else if (expld.phase == lang_final_phase_enum
546*3d8817e4Smiod || expld.assigning_to_dot)
547*3d8817e4Smiod einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
548*3d8817e4Smiod tree->name.name);
549*3d8817e4Smiod else if (h->type == bfd_link_hash_new)
550*3d8817e4Smiod {
551*3d8817e4Smiod h->type = bfd_link_hash_undefined;
552*3d8817e4Smiod h->u.undef.abfd = NULL;
553*3d8817e4Smiod if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
554*3d8817e4Smiod bfd_link_add_undef (link_info.hash, h);
555*3d8817e4Smiod }
556*3d8817e4Smiod }
557*3d8817e4Smiod break;
558*3d8817e4Smiod
559*3d8817e4Smiod case ADDR:
560*3d8817e4Smiod if (expld.phase != lang_first_phase_enum)
561*3d8817e4Smiod {
562*3d8817e4Smiod lang_output_section_statement_type *os;
563*3d8817e4Smiod
564*3d8817e4Smiod os = lang_output_section_find (tree->name.name);
565*3d8817e4Smiod if (os != NULL && os->processed)
566*3d8817e4Smiod new_rel (0, NULL, os->bfd_section);
567*3d8817e4Smiod }
568*3d8817e4Smiod break;
569*3d8817e4Smiod
570*3d8817e4Smiod case LOADADDR:
571*3d8817e4Smiod if (expld.phase != lang_first_phase_enum)
572*3d8817e4Smiod {
573*3d8817e4Smiod lang_output_section_statement_type *os;
574*3d8817e4Smiod
575*3d8817e4Smiod os = lang_output_section_find (tree->name.name);
576*3d8817e4Smiod if (os != NULL && os->processed)
577*3d8817e4Smiod {
578*3d8817e4Smiod if (os->load_base == NULL)
579*3d8817e4Smiod new_rel (0, NULL, os->bfd_section);
580*3d8817e4Smiod else
581*3d8817e4Smiod exp_fold_tree_1 (os->load_base);
582*3d8817e4Smiod }
583*3d8817e4Smiod }
584*3d8817e4Smiod break;
585*3d8817e4Smiod
586*3d8817e4Smiod case SIZEOF:
587*3d8817e4Smiod if (expld.phase != lang_first_phase_enum)
588*3d8817e4Smiod {
589*3d8817e4Smiod int opb = bfd_octets_per_byte (output_bfd);
590*3d8817e4Smiod lang_output_section_statement_type *os;
591*3d8817e4Smiod
592*3d8817e4Smiod os = lang_output_section_find (tree->name.name);
593*3d8817e4Smiod if (os == NULL)
594*3d8817e4Smiod new_abs (0);
595*3d8817e4Smiod else if (os->processed)
596*3d8817e4Smiod new_abs (os->bfd_section->size / opb);
597*3d8817e4Smiod }
598*3d8817e4Smiod break;
599*3d8817e4Smiod
600*3d8817e4Smiod case LENGTH:
601*3d8817e4Smiod {
602*3d8817e4Smiod lang_memory_region_type *mem;
603*3d8817e4Smiod
604*3d8817e4Smiod mem = lang_memory_region_lookup (tree->name.name, FALSE);
605*3d8817e4Smiod if (mem != NULL)
606*3d8817e4Smiod new_abs (mem->length);
607*3d8817e4Smiod else
608*3d8817e4Smiod einfo (_("%F%S: undefined MEMORY region `%s'"
609*3d8817e4Smiod " referenced in expression\n"), tree->name.name);
610*3d8817e4Smiod }
611*3d8817e4Smiod break;
612*3d8817e4Smiod
613*3d8817e4Smiod case ORIGIN:
614*3d8817e4Smiod {
615*3d8817e4Smiod lang_memory_region_type *mem;
616*3d8817e4Smiod
617*3d8817e4Smiod mem = lang_memory_region_lookup (tree->name.name, FALSE);
618*3d8817e4Smiod if (mem != NULL)
619*3d8817e4Smiod new_abs (mem->origin);
620*3d8817e4Smiod else
621*3d8817e4Smiod einfo (_("%F%S: undefined MEMORY region `%s'"
622*3d8817e4Smiod " referenced in expression\n"), tree->name.name);
623*3d8817e4Smiod }
624*3d8817e4Smiod break;
625*3d8817e4Smiod
626*3d8817e4Smiod default:
627*3d8817e4Smiod FAIL ();
628*3d8817e4Smiod break;
629*3d8817e4Smiod }
630*3d8817e4Smiod }
631*3d8817e4Smiod
632*3d8817e4Smiod static void
exp_fold_tree_1(etree_type * tree)633*3d8817e4Smiod exp_fold_tree_1 (etree_type *tree)
634*3d8817e4Smiod {
635*3d8817e4Smiod if (tree == NULL)
636*3d8817e4Smiod {
637*3d8817e4Smiod memset (&expld.result, 0, sizeof (expld.result));
638*3d8817e4Smiod return;
639*3d8817e4Smiod }
640*3d8817e4Smiod
641*3d8817e4Smiod switch (tree->type.node_class)
642*3d8817e4Smiod {
643*3d8817e4Smiod case etree_value:
644*3d8817e4Smiod new_rel (tree->value.value, tree->value.str, expld.section);
645*3d8817e4Smiod break;
646*3d8817e4Smiod
647*3d8817e4Smiod case etree_rel:
648*3d8817e4Smiod if (expld.phase != lang_first_phase_enum)
649*3d8817e4Smiod {
650*3d8817e4Smiod asection *output_section = tree->rel.section->output_section;
651*3d8817e4Smiod new_rel (tree->rel.value + tree->rel.section->output_offset,
652*3d8817e4Smiod NULL, output_section);
653*3d8817e4Smiod }
654*3d8817e4Smiod else
655*3d8817e4Smiod memset (&expld.result, 0, sizeof (expld.result));
656*3d8817e4Smiod break;
657*3d8817e4Smiod
658*3d8817e4Smiod case etree_assert:
659*3d8817e4Smiod exp_fold_tree_1 (tree->assert_s.child);
660*3d8817e4Smiod if (expld.phase == lang_final_phase_enum && !expld.result.value)
661*3d8817e4Smiod einfo ("%X%P: %s\n", tree->assert_s.message);
662*3d8817e4Smiod break;
663*3d8817e4Smiod
664*3d8817e4Smiod case etree_unary:
665*3d8817e4Smiod fold_unary (tree);
666*3d8817e4Smiod break;
667*3d8817e4Smiod
668*3d8817e4Smiod case etree_binary:
669*3d8817e4Smiod fold_binary (tree);
670*3d8817e4Smiod break;
671*3d8817e4Smiod
672*3d8817e4Smiod case etree_trinary:
673*3d8817e4Smiod fold_trinary (tree);
674*3d8817e4Smiod break;
675*3d8817e4Smiod
676*3d8817e4Smiod case etree_assign:
677*3d8817e4Smiod case etree_provide:
678*3d8817e4Smiod case etree_provided:
679*3d8817e4Smiod if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
680*3d8817e4Smiod {
681*3d8817e4Smiod /* Assignment to dot can only be done during allocation. */
682*3d8817e4Smiod if (tree->type.node_class != etree_assign)
683*3d8817e4Smiod einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
684*3d8817e4Smiod if (expld.phase == lang_mark_phase_enum
685*3d8817e4Smiod || expld.phase == lang_allocating_phase_enum
686*3d8817e4Smiod || (expld.phase == lang_final_phase_enum
687*3d8817e4Smiod && expld.section == bfd_abs_section_ptr))
688*3d8817e4Smiod {
689*3d8817e4Smiod /* Notify the folder that this is an assignment to dot. */
690*3d8817e4Smiod expld.assigning_to_dot = TRUE;
691*3d8817e4Smiod exp_fold_tree_1 (tree->assign.src);
692*3d8817e4Smiod expld.assigning_to_dot = FALSE;
693*3d8817e4Smiod
694*3d8817e4Smiod if (!expld.result.valid_p)
695*3d8817e4Smiod {
696*3d8817e4Smiod if (expld.phase != lang_mark_phase_enum)
697*3d8817e4Smiod einfo (_("%F%S invalid assignment to location counter\n"));
698*3d8817e4Smiod }
699*3d8817e4Smiod else if (expld.dotp == NULL)
700*3d8817e4Smiod einfo (_("%F%S assignment to location counter"
701*3d8817e4Smiod " invalid outside of SECTION\n"));
702*3d8817e4Smiod else
703*3d8817e4Smiod {
704*3d8817e4Smiod bfd_vma nextdot;
705*3d8817e4Smiod
706*3d8817e4Smiod nextdot = expld.result.value + expld.section->vma;
707*3d8817e4Smiod if (nextdot < expld.dot
708*3d8817e4Smiod && expld.section != bfd_abs_section_ptr)
709*3d8817e4Smiod einfo (_("%F%S cannot move location counter backwards"
710*3d8817e4Smiod " (from %V to %V)\n"), expld.dot, nextdot);
711*3d8817e4Smiod else
712*3d8817e4Smiod {
713*3d8817e4Smiod expld.dot = nextdot;
714*3d8817e4Smiod *expld.dotp = nextdot;
715*3d8817e4Smiod }
716*3d8817e4Smiod }
717*3d8817e4Smiod }
718*3d8817e4Smiod else
719*3d8817e4Smiod memset (&expld.result, 0, sizeof (expld.result));
720*3d8817e4Smiod }
721*3d8817e4Smiod else
722*3d8817e4Smiod {
723*3d8817e4Smiod struct bfd_link_hash_entry *h = NULL;
724*3d8817e4Smiod
725*3d8817e4Smiod if (tree->type.node_class == etree_provide)
726*3d8817e4Smiod {
727*3d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
728*3d8817e4Smiod FALSE, FALSE, TRUE);
729*3d8817e4Smiod if (h == NULL
730*3d8817e4Smiod || (h->type != bfd_link_hash_new
731*3d8817e4Smiod && h->type != bfd_link_hash_undefined
732*3d8817e4Smiod && h->type != bfd_link_hash_common))
733*3d8817e4Smiod {
734*3d8817e4Smiod /* Do nothing. The symbol was never referenced, or was
735*3d8817e4Smiod defined by some object. */
736*3d8817e4Smiod break;
737*3d8817e4Smiod }
738*3d8817e4Smiod }
739*3d8817e4Smiod
740*3d8817e4Smiod exp_fold_tree_1 (tree->assign.src);
741*3d8817e4Smiod if (expld.result.valid_p)
742*3d8817e4Smiod {
743*3d8817e4Smiod if (h == NULL)
744*3d8817e4Smiod {
745*3d8817e4Smiod h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
746*3d8817e4Smiod TRUE, FALSE, TRUE);
747*3d8817e4Smiod if (h == NULL)
748*3d8817e4Smiod einfo (_("%P%F:%s: hash creation failed\n"),
749*3d8817e4Smiod tree->assign.dst);
750*3d8817e4Smiod }
751*3d8817e4Smiod
752*3d8817e4Smiod /* FIXME: Should we worry if the symbol is already
753*3d8817e4Smiod defined? */
754*3d8817e4Smiod lang_update_definedness (tree->assign.dst, h);
755*3d8817e4Smiod h->type = bfd_link_hash_defined;
756*3d8817e4Smiod h->u.def.value = expld.result.value;
757*3d8817e4Smiod h->u.def.section = expld.result.section;
758*3d8817e4Smiod if (tree->type.node_class == etree_provide)
759*3d8817e4Smiod tree->type.node_class = etree_provided;
760*3d8817e4Smiod }
761*3d8817e4Smiod }
762*3d8817e4Smiod break;
763*3d8817e4Smiod
764*3d8817e4Smiod case etree_name:
765*3d8817e4Smiod fold_name (tree);
766*3d8817e4Smiod break;
767*3d8817e4Smiod
768*3d8817e4Smiod default:
769*3d8817e4Smiod FAIL ();
770*3d8817e4Smiod memset (&expld.result, 0, sizeof (expld.result));
771*3d8817e4Smiod break;
772*3d8817e4Smiod }
773*3d8817e4Smiod }
774*3d8817e4Smiod
775*3d8817e4Smiod void
exp_fold_tree(etree_type * tree,asection * current_section,bfd_vma * dotp)776*3d8817e4Smiod exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
777*3d8817e4Smiod {
778*3d8817e4Smiod expld.dot = *dotp;
779*3d8817e4Smiod expld.dotp = dotp;
780*3d8817e4Smiod expld.section = current_section;
781*3d8817e4Smiod exp_fold_tree_1 (tree);
782*3d8817e4Smiod }
783*3d8817e4Smiod
784*3d8817e4Smiod static void
exp_fold_tree_no_dot(etree_type * tree)785*3d8817e4Smiod exp_fold_tree_no_dot (etree_type *tree)
786*3d8817e4Smiod {
787*3d8817e4Smiod expld.dot = 0;
788*3d8817e4Smiod expld.dotp = NULL;
789*3d8817e4Smiod expld.section = bfd_abs_section_ptr;
790*3d8817e4Smiod exp_fold_tree_1 (tree);
791*3d8817e4Smiod }
792*3d8817e4Smiod
793*3d8817e4Smiod etree_type *
exp_binop(int code,etree_type * lhs,etree_type * rhs)794*3d8817e4Smiod exp_binop (int code, etree_type *lhs, etree_type *rhs)
795*3d8817e4Smiod {
796*3d8817e4Smiod etree_type value, *new;
797*3d8817e4Smiod
798*3d8817e4Smiod value.type.node_code = code;
799*3d8817e4Smiod value.binary.lhs = lhs;
800*3d8817e4Smiod value.binary.rhs = rhs;
801*3d8817e4Smiod value.type.node_class = etree_binary;
802*3d8817e4Smiod exp_fold_tree_no_dot (&value);
803*3d8817e4Smiod if (expld.result.valid_p)
804*3d8817e4Smiod return exp_intop (expld.result.value);
805*3d8817e4Smiod
806*3d8817e4Smiod new = stat_alloc (sizeof (new->binary));
807*3d8817e4Smiod memcpy (new, &value, sizeof (new->binary));
808*3d8817e4Smiod return new;
809*3d8817e4Smiod }
810*3d8817e4Smiod
811*3d8817e4Smiod etree_type *
exp_trinop(int code,etree_type * cond,etree_type * lhs,etree_type * rhs)812*3d8817e4Smiod exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
813*3d8817e4Smiod {
814*3d8817e4Smiod etree_type value, *new;
815*3d8817e4Smiod
816*3d8817e4Smiod value.type.node_code = code;
817*3d8817e4Smiod value.trinary.lhs = lhs;
818*3d8817e4Smiod value.trinary.cond = cond;
819*3d8817e4Smiod value.trinary.rhs = rhs;
820*3d8817e4Smiod value.type.node_class = etree_trinary;
821*3d8817e4Smiod exp_fold_tree_no_dot (&value);
822*3d8817e4Smiod if (expld.result.valid_p)
823*3d8817e4Smiod return exp_intop (expld.result.value);
824*3d8817e4Smiod
825*3d8817e4Smiod new = stat_alloc (sizeof (new->trinary));
826*3d8817e4Smiod memcpy (new, &value, sizeof (new->trinary));
827*3d8817e4Smiod return new;
828*3d8817e4Smiod }
829*3d8817e4Smiod
830*3d8817e4Smiod etree_type *
exp_unop(int code,etree_type * child)831*3d8817e4Smiod exp_unop (int code, etree_type *child)
832*3d8817e4Smiod {
833*3d8817e4Smiod etree_type value, *new;
834*3d8817e4Smiod
835*3d8817e4Smiod value.unary.type.node_code = code;
836*3d8817e4Smiod value.unary.child = child;
837*3d8817e4Smiod value.unary.type.node_class = etree_unary;
838*3d8817e4Smiod exp_fold_tree_no_dot (&value);
839*3d8817e4Smiod if (expld.result.valid_p)
840*3d8817e4Smiod return exp_intop (expld.result.value);
841*3d8817e4Smiod
842*3d8817e4Smiod new = stat_alloc (sizeof (new->unary));
843*3d8817e4Smiod memcpy (new, &value, sizeof (new->unary));
844*3d8817e4Smiod return new;
845*3d8817e4Smiod }
846*3d8817e4Smiod
847*3d8817e4Smiod etree_type *
exp_nameop(int code,const char * name)848*3d8817e4Smiod exp_nameop (int code, const char *name)
849*3d8817e4Smiod {
850*3d8817e4Smiod etree_type value, *new;
851*3d8817e4Smiod
852*3d8817e4Smiod value.name.type.node_code = code;
853*3d8817e4Smiod value.name.name = name;
854*3d8817e4Smiod value.name.type.node_class = etree_name;
855*3d8817e4Smiod
856*3d8817e4Smiod exp_fold_tree_no_dot (&value);
857*3d8817e4Smiod if (expld.result.valid_p)
858*3d8817e4Smiod return exp_intop (expld.result.value);
859*3d8817e4Smiod
860*3d8817e4Smiod new = stat_alloc (sizeof (new->name));
861*3d8817e4Smiod memcpy (new, &value, sizeof (new->name));
862*3d8817e4Smiod return new;
863*3d8817e4Smiod
864*3d8817e4Smiod }
865*3d8817e4Smiod
866*3d8817e4Smiod etree_type *
exp_assop(int code,const char * dst,etree_type * src)867*3d8817e4Smiod exp_assop (int code, const char *dst, etree_type *src)
868*3d8817e4Smiod {
869*3d8817e4Smiod etree_type *new;
870*3d8817e4Smiod
871*3d8817e4Smiod new = stat_alloc (sizeof (new->assign));
872*3d8817e4Smiod new->type.node_code = code;
873*3d8817e4Smiod new->type.node_class = etree_assign;
874*3d8817e4Smiod new->assign.src = src;
875*3d8817e4Smiod new->assign.dst = dst;
876*3d8817e4Smiod return new;
877*3d8817e4Smiod }
878*3d8817e4Smiod
879*3d8817e4Smiod /* Handle PROVIDE. */
880*3d8817e4Smiod
881*3d8817e4Smiod etree_type *
exp_provide(const char * dst,etree_type * src,bfd_boolean hidden)882*3d8817e4Smiod exp_provide (const char *dst, etree_type *src, bfd_boolean hidden)
883*3d8817e4Smiod {
884*3d8817e4Smiod etree_type *n;
885*3d8817e4Smiod
886*3d8817e4Smiod n = stat_alloc (sizeof (n->assign));
887*3d8817e4Smiod n->assign.type.node_code = '=';
888*3d8817e4Smiod n->assign.type.node_class = etree_provide;
889*3d8817e4Smiod n->assign.src = src;
890*3d8817e4Smiod n->assign.dst = dst;
891*3d8817e4Smiod n->assign.hidden = hidden;
892*3d8817e4Smiod return n;
893*3d8817e4Smiod }
894*3d8817e4Smiod
895*3d8817e4Smiod /* Handle ASSERT. */
896*3d8817e4Smiod
897*3d8817e4Smiod etree_type *
exp_assert(etree_type * exp,const char * message)898*3d8817e4Smiod exp_assert (etree_type *exp, const char *message)
899*3d8817e4Smiod {
900*3d8817e4Smiod etree_type *n;
901*3d8817e4Smiod
902*3d8817e4Smiod n = stat_alloc (sizeof (n->assert_s));
903*3d8817e4Smiod n->assert_s.type.node_code = '!';
904*3d8817e4Smiod n->assert_s.type.node_class = etree_assert;
905*3d8817e4Smiod n->assert_s.child = exp;
906*3d8817e4Smiod n->assert_s.message = message;
907*3d8817e4Smiod return n;
908*3d8817e4Smiod }
909*3d8817e4Smiod
910*3d8817e4Smiod void
exp_print_tree(etree_type * tree)911*3d8817e4Smiod exp_print_tree (etree_type *tree)
912*3d8817e4Smiod {
913*3d8817e4Smiod if (config.map_file == NULL)
914*3d8817e4Smiod config.map_file = stderr;
915*3d8817e4Smiod
916*3d8817e4Smiod if (tree == NULL)
917*3d8817e4Smiod {
918*3d8817e4Smiod minfo ("NULL TREE\n");
919*3d8817e4Smiod return;
920*3d8817e4Smiod }
921*3d8817e4Smiod
922*3d8817e4Smiod switch (tree->type.node_class)
923*3d8817e4Smiod {
924*3d8817e4Smiod case etree_value:
925*3d8817e4Smiod minfo ("0x%v", tree->value.value);
926*3d8817e4Smiod return;
927*3d8817e4Smiod case etree_rel:
928*3d8817e4Smiod if (tree->rel.section->owner != NULL)
929*3d8817e4Smiod minfo ("%B:", tree->rel.section->owner);
930*3d8817e4Smiod minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
931*3d8817e4Smiod return;
932*3d8817e4Smiod case etree_assign:
933*3d8817e4Smiod fprintf (config.map_file, "%s", tree->assign.dst);
934*3d8817e4Smiod exp_print_token (tree->type.node_code, TRUE);
935*3d8817e4Smiod exp_print_tree (tree->assign.src);
936*3d8817e4Smiod break;
937*3d8817e4Smiod case etree_provide:
938*3d8817e4Smiod case etree_provided:
939*3d8817e4Smiod fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
940*3d8817e4Smiod exp_print_tree (tree->assign.src);
941*3d8817e4Smiod fprintf (config.map_file, ")");
942*3d8817e4Smiod break;
943*3d8817e4Smiod case etree_binary:
944*3d8817e4Smiod fprintf (config.map_file, "(");
945*3d8817e4Smiod exp_print_tree (tree->binary.lhs);
946*3d8817e4Smiod exp_print_token (tree->type.node_code, TRUE);
947*3d8817e4Smiod exp_print_tree (tree->binary.rhs);
948*3d8817e4Smiod fprintf (config.map_file, ")");
949*3d8817e4Smiod break;
950*3d8817e4Smiod case etree_trinary:
951*3d8817e4Smiod exp_print_tree (tree->trinary.cond);
952*3d8817e4Smiod fprintf (config.map_file, "?");
953*3d8817e4Smiod exp_print_tree (tree->trinary.lhs);
954*3d8817e4Smiod fprintf (config.map_file, ":");
955*3d8817e4Smiod exp_print_tree (tree->trinary.rhs);
956*3d8817e4Smiod break;
957*3d8817e4Smiod case etree_unary:
958*3d8817e4Smiod exp_print_token (tree->unary.type.node_code, FALSE);
959*3d8817e4Smiod if (tree->unary.child)
960*3d8817e4Smiod {
961*3d8817e4Smiod fprintf (config.map_file, " (");
962*3d8817e4Smiod exp_print_tree (tree->unary.child);
963*3d8817e4Smiod fprintf (config.map_file, ")");
964*3d8817e4Smiod }
965*3d8817e4Smiod break;
966*3d8817e4Smiod
967*3d8817e4Smiod case etree_assert:
968*3d8817e4Smiod fprintf (config.map_file, "ASSERT (");
969*3d8817e4Smiod exp_print_tree (tree->assert_s.child);
970*3d8817e4Smiod fprintf (config.map_file, ", %s)", tree->assert_s.message);
971*3d8817e4Smiod break;
972*3d8817e4Smiod
973*3d8817e4Smiod case etree_name:
974*3d8817e4Smiod if (tree->type.node_code == NAME)
975*3d8817e4Smiod {
976*3d8817e4Smiod fprintf (config.map_file, "%s", tree->name.name);
977*3d8817e4Smiod }
978*3d8817e4Smiod else
979*3d8817e4Smiod {
980*3d8817e4Smiod exp_print_token (tree->type.node_code, FALSE);
981*3d8817e4Smiod if (tree->name.name)
982*3d8817e4Smiod fprintf (config.map_file, " (%s)", tree->name.name);
983*3d8817e4Smiod }
984*3d8817e4Smiod break;
985*3d8817e4Smiod default:
986*3d8817e4Smiod FAIL ();
987*3d8817e4Smiod break;
988*3d8817e4Smiod }
989*3d8817e4Smiod }
990*3d8817e4Smiod
991*3d8817e4Smiod bfd_vma
exp_get_vma(etree_type * tree,bfd_vma def,char * name)992*3d8817e4Smiod exp_get_vma (etree_type *tree, bfd_vma def, char *name)
993*3d8817e4Smiod {
994*3d8817e4Smiod if (tree != NULL)
995*3d8817e4Smiod {
996*3d8817e4Smiod exp_fold_tree_no_dot (tree);
997*3d8817e4Smiod if (expld.result.valid_p)
998*3d8817e4Smiod return expld.result.value;
999*3d8817e4Smiod else if (name != NULL && expld.phase != lang_mark_phase_enum)
1000*3d8817e4Smiod einfo (_("%F%S nonconstant expression for %s\n"), name);
1001*3d8817e4Smiod }
1002*3d8817e4Smiod return def;
1003*3d8817e4Smiod }
1004*3d8817e4Smiod
1005*3d8817e4Smiod int
exp_get_value_int(etree_type * tree,int def,char * name)1006*3d8817e4Smiod exp_get_value_int (etree_type *tree, int def, char *name)
1007*3d8817e4Smiod {
1008*3d8817e4Smiod return exp_get_vma (tree, def, name);
1009*3d8817e4Smiod }
1010*3d8817e4Smiod
1011*3d8817e4Smiod fill_type *
exp_get_fill(etree_type * tree,fill_type * def,char * name)1012*3d8817e4Smiod exp_get_fill (etree_type *tree, fill_type *def, char *name)
1013*3d8817e4Smiod {
1014*3d8817e4Smiod fill_type *fill;
1015*3d8817e4Smiod size_t len;
1016*3d8817e4Smiod unsigned int val;
1017*3d8817e4Smiod
1018*3d8817e4Smiod if (tree == NULL)
1019*3d8817e4Smiod return def;
1020*3d8817e4Smiod
1021*3d8817e4Smiod exp_fold_tree_no_dot (tree);
1022*3d8817e4Smiod if (!expld.result.valid_p)
1023*3d8817e4Smiod {
1024*3d8817e4Smiod if (name != NULL && expld.phase != lang_mark_phase_enum)
1025*3d8817e4Smiod einfo (_("%F%S nonconstant expression for %s\n"), name);
1026*3d8817e4Smiod return def;
1027*3d8817e4Smiod }
1028*3d8817e4Smiod
1029*3d8817e4Smiod if (expld.result.str != NULL && (len = strlen (expld.result.str)) != 0)
1030*3d8817e4Smiod {
1031*3d8817e4Smiod unsigned char *dst;
1032*3d8817e4Smiod unsigned char *s;
1033*3d8817e4Smiod fill = xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
1034*3d8817e4Smiod fill->size = (len + 1) / 2;
1035*3d8817e4Smiod dst = fill->data;
1036*3d8817e4Smiod s = (unsigned char *) expld.result.str;
1037*3d8817e4Smiod val = 0;
1038*3d8817e4Smiod do
1039*3d8817e4Smiod {
1040*3d8817e4Smiod unsigned int digit;
1041*3d8817e4Smiod
1042*3d8817e4Smiod digit = *s++ - '0';
1043*3d8817e4Smiod if (digit > 9)
1044*3d8817e4Smiod digit = (digit - 'A' + '0' + 10) & 0xf;
1045*3d8817e4Smiod val <<= 4;
1046*3d8817e4Smiod val += digit;
1047*3d8817e4Smiod --len;
1048*3d8817e4Smiod if ((len & 1) == 0)
1049*3d8817e4Smiod {
1050*3d8817e4Smiod *dst++ = val;
1051*3d8817e4Smiod val = 0;
1052*3d8817e4Smiod }
1053*3d8817e4Smiod }
1054*3d8817e4Smiod while (len != 0);
1055*3d8817e4Smiod }
1056*3d8817e4Smiod else
1057*3d8817e4Smiod {
1058*3d8817e4Smiod fill = xmalloc (4 + sizeof (*fill) - 1);
1059*3d8817e4Smiod val = expld.result.value;
1060*3d8817e4Smiod fill->data[0] = (val >> 24) & 0xff;
1061*3d8817e4Smiod fill->data[1] = (val >> 16) & 0xff;
1062*3d8817e4Smiod fill->data[2] = (val >> 8) & 0xff;
1063*3d8817e4Smiod fill->data[3] = (val >> 0) & 0xff;
1064*3d8817e4Smiod fill->size = 4;
1065*3d8817e4Smiod }
1066*3d8817e4Smiod return fill;
1067*3d8817e4Smiod }
1068*3d8817e4Smiod
1069*3d8817e4Smiod bfd_vma
exp_get_abs_int(etree_type * tree,int def,char * name)1070*3d8817e4Smiod exp_get_abs_int (etree_type *tree, int def, char *name)
1071*3d8817e4Smiod {
1072*3d8817e4Smiod if (tree != NULL)
1073*3d8817e4Smiod {
1074*3d8817e4Smiod exp_fold_tree_no_dot (tree);
1075*3d8817e4Smiod
1076*3d8817e4Smiod if (expld.result.valid_p)
1077*3d8817e4Smiod {
1078*3d8817e4Smiod expld.result.value += expld.result.section->vma;
1079*3d8817e4Smiod return expld.result.value;
1080*3d8817e4Smiod }
1081*3d8817e4Smiod else if (name != NULL && expld.phase != lang_mark_phase_enum)
1082*3d8817e4Smiod einfo (_("%F%S non constant expression for %s\n"), name);
1083*3d8817e4Smiod }
1084*3d8817e4Smiod return def;
1085*3d8817e4Smiod }
1086*3d8817e4Smiod
1087*3d8817e4Smiod static bfd_vma
align_n(bfd_vma value,bfd_vma align)1088*3d8817e4Smiod align_n (bfd_vma value, bfd_vma align)
1089*3d8817e4Smiod {
1090*3d8817e4Smiod if (align <= 1)
1091*3d8817e4Smiod return value;
1092*3d8817e4Smiod
1093*3d8817e4Smiod value = (value + align - 1) / align;
1094*3d8817e4Smiod return value * align;
1095*3d8817e4Smiod }
1096