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