* configure: Regenerate.
[deliverable/binutils-gdb.git] / ld / emultempl / xtensaelf.em
CommitLineData
e0001a05 1# This shell script emits a C file. -*- C -*-
aef6203b 2# Copyright 2003, 2004, 2005
e0001a05
NC
3# Free Software Foundation, Inc.
4#
5# This file is part of GLD, the Gnu Linker.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
75be928b 19# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
e0001a05
NC
20#
21
22# This file is sourced from elf32.em, and defines extra xtensa-elf
23# specific routines.
24#
25cat >>e${EMULATION_NAME}.c <<EOF
26
27#include <xtensa-config.h>
43cd72b9
BW
28#include "../bfd/elf-bfd.h"
29#include "../bfd/libbfd.h"
30#include "elf/xtensa.h"
31#include "bfd.h"
e0001a05 32
0c7a8e5a
AM
33static void xtensa_wild_group_interleave (lang_statement_union_type *);
34static void xtensa_colocate_output_literals (lang_statement_union_type *);
e0001a05
NC
35
36
37/* Flag for the emulation-specific "--no-relax" option. */
38static bfd_boolean disable_relaxation = FALSE;
39
40/* This number is irrelevant until we turn on use_literal_pages */
41static bfd_vma xtensa_page_power = 12; /* 4K pages. */
42
43/* To force a page break between literals and text, change
43cd72b9 44 xtensa_use_literal_pages to "TRUE". */
e0001a05
NC
45static bfd_boolean xtensa_use_literal_pages = FALSE;
46
47#define EXTRA_VALIDATION 0
48
49
50static char *
0c7a8e5a
AM
51elf_xtensa_choose_target (int argc ATTRIBUTE_UNUSED,
52 char **argv ATTRIBUTE_UNUSED)
e0001a05
NC
53{
54 if (XCHAL_HAVE_BE)
55 return "${BIG_OUTPUT_FORMAT}";
56 else
57 return "${LITTLE_OUTPUT_FORMAT}";
58}
59
60
e0001a05 61static void
0c7a8e5a 62elf_xtensa_before_parse (void)
e0001a05
NC
63{
64 /* Just call the default hook.... Tensilica's version of this function
65 does some other work that isn't relevant here. */
66 gld${EMULATION_NAME}_before_parse ();
67}
68
69
7fa3d080
BW
70static void
71remove_section (bfd *abfd, asection *os)
43cd72b9
BW
72{
73 asection **spp;
74 for (spp = &abfd->sections; *spp; spp = &(*spp)->next)
75 if (*spp == os)
76 {
77 *spp = os->next;
78 os->owner->section_count--;
79 break;
80 }
81}
82
83
7fa3d080
BW
84static bfd_boolean
85replace_insn_sec_with_prop_sec (bfd *abfd,
86 const char *insn_sec_name,
87 const char *prop_sec_name,
88 char **error_message)
43cd72b9
BW
89{
90 asection *insn_sec;
91 asection *prop_sec;
92 bfd_byte *prop_contents = NULL;
93 bfd_byte *insn_contents = NULL;
94 unsigned entry_count;
95 unsigned entry;
96 Elf_Internal_Shdr *symtab_hdr;
97 Elf_Internal_Rela *internal_relocs = NULL;
98 unsigned reloc_count;
99
100 *error_message = "";
101 insn_sec = bfd_get_section_by_name (abfd, insn_sec_name);
102 if (insn_sec == NULL)
103 return TRUE;
104 entry_count = insn_sec->size / 8;
105
106 prop_sec = bfd_get_section_by_name (abfd, prop_sec_name);
107 if (prop_sec != NULL && insn_sec != NULL)
108 {
109 *error_message = _("file already has property tables");
110 return FALSE;
111 }
112
113 if (insn_sec->size != 0)
114 {
115 insn_contents = (bfd_byte *) bfd_malloc (insn_sec->size);
116 if (insn_contents == NULL)
117 {
118 *error_message = _("out of memory");
119 goto cleanup;
120 }
121 if (! bfd_get_section_contents (abfd, insn_sec, insn_contents,
122 (file_ptr) 0, insn_sec->size))
123 {
124 *error_message = _("failed to read section contents");
125 goto cleanup;
126 }
127 }
128
129 /* Create a Property table section and relocation section for it. */
130 prop_sec_name = strdup (prop_sec_name);
131 prop_sec = bfd_make_section (abfd, prop_sec_name);
132 if (prop_sec == NULL
133 || ! bfd_set_section_flags (abfd, prop_sec,
134 bfd_get_section_flags (abfd, insn_sec))
135 || ! bfd_set_section_alignment (abfd, prop_sec, 2))
136 {
137 *error_message = _("could not create new section");
138 goto cleanup;
139 }
140
141 if (! bfd_set_section_flags (abfd, prop_sec,
142 bfd_get_section_flags (abfd, insn_sec))
143 || ! bfd_set_section_alignment (abfd, prop_sec, 2))
144 {
145 *error_message = _("could not set new section properties");
146 goto cleanup;
147 }
148 prop_sec->size = entry_count * 12;
149 prop_contents = (bfd_byte *) bfd_zalloc (abfd, prop_sec->size);
150 elf_section_data (prop_sec)->this_hdr.contents = prop_contents;
151
152 /* The entry size and size must be set to allow the linker to compute
153 the number of relocations since it does not use reloc_count. */
154 elf_section_data (prop_sec)->rel_hdr.sh_entsize =
155 sizeof (Elf32_External_Rela);
156 elf_section_data (prop_sec)->rel_hdr.sh_size =
157 elf_section_data (insn_sec)->rel_hdr.sh_size;
158
159 if (prop_contents == NULL && prop_sec->size != 0)
160 {
161 *error_message = _("could not allocate section contents");
162 goto cleanup;
163 }
164
165 /* Read the relocations. */
166 reloc_count = insn_sec->reloc_count;
167 if (reloc_count != 0)
168 {
169 /* If there is already an internal_reloc, then save it so that the
170 read_relocs function freshly allocates a copy. */
171 Elf_Internal_Rela *saved_relocs = elf_section_data (insn_sec)->relocs;
172
173 elf_section_data (insn_sec)->relocs = NULL;
174 internal_relocs =
175 _bfd_elf_link_read_relocs (abfd, insn_sec, NULL, NULL, FALSE);
176 elf_section_data (insn_sec)->relocs = saved_relocs;
177
178 if (internal_relocs == NULL)
179 {
180 *error_message = _("out of memory");
181 goto cleanup;
182 }
183 }
184
185 /* Create a relocation section for the property section. */
186 if (internal_relocs != NULL)
187 {
188 elf_section_data (prop_sec)->relocs = internal_relocs;
189 prop_sec->reloc_count = reloc_count;
190 }
191
192 /* Now copy each insn table entry to the prop table entry with
193 appropriate flags. */
194 for (entry = 0; entry < entry_count; ++entry)
195 {
196 unsigned value;
197 unsigned flags = (XTENSA_PROP_INSN | XTENSA_PROP_INSN_NO_TRANSFORM
198 | XTENSA_PROP_INSN_NO_REORDER);
199 value = bfd_get_32 (abfd, insn_contents + entry * 8 + 0);
200 bfd_put_32 (abfd, value, prop_contents + entry * 12 + 0);
201 value = bfd_get_32 (abfd, insn_contents + entry * 8 + 4);
202 bfd_put_32 (abfd, value, prop_contents + entry * 12 + 4);
203 bfd_put_32 (abfd, flags, prop_contents + entry * 12 + 8);
204 }
205
206 /* Now copy all of the relocations. Change offsets for the
207 instruction table section to offsets in the property table
208 section. */
209 if (internal_relocs)
210 {
211 unsigned i;
212 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
213
214 for (i = 0; i < reloc_count; i++)
215 {
216 Elf_Internal_Rela *rela;
217 unsigned r_offset;
218
219 rela = &internal_relocs[i];
220
221 /* If this relocation is to the .xt.insn section,
222 change the section number and the offset. */
223 r_offset = rela->r_offset;
224 r_offset += 4 * (r_offset / 8);
225 rela->r_offset = r_offset;
226 }
227 }
228
229 remove_section (abfd, insn_sec);
230
231 if (insn_contents)
232 free (insn_contents);
233
234 return TRUE;
235
236 cleanup:
237 if (prop_sec && prop_sec->owner)
238 remove_section (abfd, prop_sec);
239 if (insn_contents)
240 free (insn_contents);
241 if (internal_relocs)
242 free (internal_relocs);
243
244 return FALSE;
245}
246
247
248#define PROP_SEC_BASE_NAME ".xt.prop"
249#define INSN_SEC_BASE_NAME ".xt.insn"
250#define LINKONCE_SEC_OLD_TEXT_BASE_NAME ".gnu.linkonce.x."
251
252
7fa3d080
BW
253static void
254replace_instruction_table_sections (bfd *abfd, asection *sec)
43cd72b9
BW
255{
256 char *message = "";
257 const char *insn_sec_name = NULL;
258 char *prop_sec_name = NULL;
259 char *owned_prop_sec_name = NULL;
260 const char *sec_name;
261
262 sec_name = bfd_get_section_name (abfd, sec);
263 if (strcmp (sec_name, INSN_SEC_BASE_NAME) == 0)
264 {
265 insn_sec_name = INSN_SEC_BASE_NAME;
266 prop_sec_name = PROP_SEC_BASE_NAME;
267 }
268 else if (strncmp (sec_name, LINKONCE_SEC_OLD_TEXT_BASE_NAME,
269 strlen (LINKONCE_SEC_OLD_TEXT_BASE_NAME)) == 0)
270 {
271 insn_sec_name = sec_name;
272 owned_prop_sec_name = (char *) xmalloc (strlen (sec_name) + 20);
273 prop_sec_name = owned_prop_sec_name;
274 strcpy (prop_sec_name, ".gnu.linkonce.prop.t.");
275 strcat (prop_sec_name,
276 sec_name + strlen (LINKONCE_SEC_OLD_TEXT_BASE_NAME));
277 }
278 if (insn_sec_name != NULL)
279 {
280 if (! replace_insn_sec_with_prop_sec (abfd, insn_sec_name, prop_sec_name,
281 &message))
282 {
283 einfo (_("%P: warning: failed to convert %s table in %B (%s); subsequent disassembly may be incomplete\n"),
284 insn_sec_name, abfd, message);
285 }
286 }
287 if (owned_prop_sec_name)
288 free (owned_prop_sec_name);
289}
290
291
292/* This is called after all input sections have been opened to convert
293 instruction tables (.xt.insn, gnu.linkonce.x.*) tables into property
294 tables (.xt.prop) before any section placement. */
295
296static void
297elf_xtensa_after_open (void)
298{
299 bfd *abfd;
300
301 /* First call the ELF version. */
302 gld${EMULATION_NAME}_after_open ();
303
304 /* Now search the input files looking for instruction table sections. */
305 for (abfd = link_info.input_bfds;
306 abfd != NULL;
307 abfd = abfd->link_next)
308 {
309 asection *sec = abfd->sections;
310 asection *next_sec;
311
312 /* Do not use bfd_map_over_sections here since we are removing
313 sections as we iterate. */
314 while (sec != NULL)
315 {
316 next_sec = sec->next;
317 replace_instruction_table_sections (abfd, sec);
318 sec = next_sec;
319 }
320 }
321}
322
323
e0001a05
NC
324/* This is called after the sections have been attached to output
325 sections, but before any sizes or addresses have been set. */
326
0c7a8e5a
AM
327static void
328elf_xtensa_before_allocation (void)
e0001a05
NC
329{
330 bfd *in_bfd;
331 bfd_boolean is_big_endian = XCHAL_HAVE_BE;
332
333 /* Check that the output endianness matches the Xtensa
334 configuration. The BFD library always includes both big and
335 little endian target vectors for Xtensa, but it only supports the
336 detailed instruction encode/decode operations (such as are
337 required to process relocations) for the selected Xtensa
338 configuration. */
339
340 if (is_big_endian && output_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
341 {
342 einfo (_("%F%P: little endian output does not match "
343 "Xtensa configuration\n"));
344 }
345 if (!is_big_endian && output_bfd->xvec->byteorder == BFD_ENDIAN_BIG)
346 {
347 einfo (_("%F%P: big endian output does not match "
348 "Xtensa configuration\n"));
349 }
350
351 /* Check that the endianness for each input file matches the output.
352 The merge_private_bfd_data hook has already reported any mismatches
353 as errors, but those errors are not fatal. At this point, we
354 cannot go any further if there are any mismatches. */
355
356 for (in_bfd = link_info.input_bfds;
357 in_bfd != NULL;
358 in_bfd = in_bfd->link_next)
359 {
360 if ((is_big_endian && in_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
361 || (!is_big_endian && in_bfd->xvec->byteorder == BFD_ENDIAN_BIG))
362 einfo (_("%F%P: cross-endian linking not supported\n"));
363 }
364
365 /* Enable relaxation by default if the "--no-relax" option was not
366 specified. This is done here instead of in the before_parse hook
367 because there is a check in main() to prohibit use of --relax and
368 -r together and that combination should be allowed for Xtensa. */
369
370 if (!disable_relaxation)
371 command_line.relax = TRUE;
372
373 gld${EMULATION_NAME}_before_allocation ();
374
375 xtensa_wild_group_interleave (stat_ptr->head);
0c7a8e5a 376 if (command_line.relax)
e0001a05
NC
377 xtensa_colocate_output_literals (stat_ptr->head);
378
379 /* TBD: We need to force the page alignments to here and only do
380 them as needed for the entire output section. Finally, if this
1049f94e 381 is a relocatable link then we need to add alignment notes so
e0001a05
NC
382 that the literals can be separated later. */
383}
384
385
386typedef struct wildcard_list section_name_list;
387
388typedef struct reloc_deps_e_t reloc_deps_e;
389typedef struct reloc_deps_section_t reloc_deps_section;
390typedef struct reloc_deps_graph_t reloc_deps_graph;
391
392
393struct reloc_deps_e_t
394{
395 asection *src; /* Contains l32rs. */
396 asection *tgt; /* Contains literals. */
397 reloc_deps_e *next;
398};
399
400/* Place these in the userdata field. */
401struct reloc_deps_section_t
402{
403 reloc_deps_e *preds;
404 reloc_deps_e *succs;
405 bfd_boolean is_only_literal;
406};
407
408
409struct reloc_deps_graph_t
410{
411 size_t count;
412 size_t size;
413 asection **sections;
414};
415
416static void xtensa_layout_wild
0c7a8e5a 417 (const reloc_deps_graph *, lang_wild_statement_type *);
e0001a05 418
0c7a8e5a
AM
419typedef void (*deps_callback_t) (asection *, /* src_sec */
420 bfd_vma, /* src_offset */
421 asection *, /* target_sec */
422 bfd_vma, /* target_offset */
423 void *); /* closure */
e0001a05 424
e0001a05 425extern bfd_boolean xtensa_callback_required_dependence
0c7a8e5a 426 (bfd *, asection *, struct bfd_link_info *, deps_callback_t, void *);
7fa3d080 427static void xtensa_ldlang_clear_addresses (lang_statement_union_type *);
e0001a05 428static bfd_boolean ld_local_file_relocations_fit
0c7a8e5a 429 (lang_statement_union_type *, const reloc_deps_graph *);
e0001a05 430static bfd_vma ld_assign_relative_paged_dot
0c7a8e5a
AM
431 (bfd_vma, lang_statement_union_type *, const reloc_deps_graph *,
432 bfd_boolean);
e0001a05 433static bfd_vma ld_xtensa_insert_page_offsets
0c7a8e5a 434 (bfd_vma, lang_statement_union_type *, reloc_deps_graph *, bfd_boolean);
e0001a05 435#if EXTRA_VALIDATION
7fa3d080 436static size_t ld_count_children (lang_statement_union_type *);
e0001a05 437#endif
e0001a05
NC
438
439extern lang_statement_list_type constructor_list;
440
441/* Begin verbatim code from ldlang.c:
442 the following are copied from ldlang.c because they are defined
443 there statically. */
444
445static void
0c7a8e5a
AM
446lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
447 lang_statement_union_type *s)
e0001a05
NC
448{
449 for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
450 {
451 func (s);
452
453 switch (s->header.type)
0c7a8e5a
AM
454 {
455 case lang_constructors_statement_enum:
456 lang_for_each_statement_worker (func, constructor_list.head);
457 break;
458 case lang_output_section_statement_enum:
459 lang_for_each_statement_worker
460 (func,
461 s->output_section_statement.children.head);
462 break;
463 case lang_wild_statement_enum:
464 lang_for_each_statement_worker
465 (func,
466 s->wild_statement.children.head);
467 break;
468 case lang_group_statement_enum:
469 lang_for_each_statement_worker (func,
470 s->group_statement.children.head);
471 break;
472 case lang_data_statement_enum:
473 case lang_reloc_statement_enum:
474 case lang_object_symbols_statement_enum:
475 case lang_output_statement_enum:
476 case lang_target_statement_enum:
477 case lang_input_section_enum:
478 case lang_input_statement_enum:
479 case lang_assignment_statement_enum:
480 case lang_padding_statement_enum:
481 case lang_address_statement_enum:
482 case lang_fill_statement_enum:
483 break;
484 default:
485 FAIL ();
486 break;
487 }
e0001a05
NC
488 }
489}
490
491/* End of verbatim code from ldlang.c. */
492
493
0c7a8e5a
AM
494static reloc_deps_section *
495xtensa_get_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
496 asection *sec)
e0001a05
NC
497{
498 /* We have a separate function for this so that
499 we could in the future keep a completely independent
500 structure that maps a section to its dependence edges.
501 For now, we place these in the sec->userdata field. */
0c7a8e5a 502 reloc_deps_section *sec_deps = sec->userdata;
e0001a05
NC
503 return sec_deps;
504}
505
0c7a8e5a
AM
506static void
507xtensa_set_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
508 asection *sec,
509 reloc_deps_section *deps_section)
e0001a05 510{
0c7a8e5a 511 sec->userdata = deps_section;
e0001a05
NC
512}
513
514
515/* This is used to keep a list of all of the sections participating in
516 the graph so we can clean them up quickly. */
517
0c7a8e5a
AM
518static void
519xtensa_append_section_deps (reloc_deps_graph *deps, asection *sec)
e0001a05
NC
520{
521 if (deps->size <= deps->count)
522 {
523 asection **new_sections;
524 size_t i;
525 size_t new_size;
0c7a8e5a 526
e0001a05
NC
527 new_size = deps->size * 2;
528 if (new_size == 0)
529 new_size = 20;
0c7a8e5a
AM
530
531 new_sections = xmalloc (sizeof (asection *) * new_size);
532 memset (new_sections, 0, sizeof (asection *) * new_size);
533 for (i = 0; i < deps->count; i++)
e0001a05
NC
534 {
535 new_sections[i] = deps->sections[i];
536 }
537 if (deps->sections != NULL)
538 free (deps->sections);
539 deps->sections = new_sections;
540 deps->size = new_size;
541 }
542 deps->sections[deps->count] = sec;
543 deps->count++;
544}
545
546
0c7a8e5a
AM
547static void
548free_reloc_deps_graph (reloc_deps_graph *deps)
e0001a05
NC
549{
550 size_t i;
551 for (i = 0; i < deps->count; i++)
552 {
553 asection *sec = deps->sections[i];
554 reloc_deps_section *sec_deps;
555 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 556 if (sec_deps)
e0001a05
NC
557 {
558 reloc_deps_e *next;
559 while (sec_deps->succs != NULL)
560 {
561 next = sec_deps->succs->next;
562 free (sec_deps->succs);
563 sec_deps->succs = next;
564 }
0c7a8e5a 565
e0001a05
NC
566 while (sec_deps->preds != NULL)
567 {
568 next = sec_deps->preds->next;
569 free (sec_deps->preds);
570 sec_deps->preds = next;
571 }
572 free (sec_deps);
573 }
574 xtensa_set_section_deps (deps, sec, NULL);
575 }
576 if (deps->sections)
577 free (deps->sections);
578
579 free (deps);
580}
581
582
0c7a8e5a
AM
583static bfd_boolean
584section_is_source (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
585 lang_statement_union_type *s)
e0001a05
NC
586{
587 asection *sec;
588 const reloc_deps_section *sec_deps;
589
590 if (s->header.type != lang_input_section_enum)
591 return FALSE;
592 sec = s->input_section.section;
593
594 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 595 return sec_deps && sec_deps->succs != NULL;
e0001a05
NC
596}
597
598
0c7a8e5a
AM
599static bfd_boolean
600section_is_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
601 lang_statement_union_type *s)
e0001a05
NC
602{
603 asection *sec;
604 const reloc_deps_section *sec_deps;
605
606 if (s->header.type != lang_input_section_enum)
607 return FALSE;
608 sec = s->input_section.section;
609
610 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 611 return sec_deps && sec_deps->preds != NULL;
e0001a05
NC
612}
613
7fa3d080 614
0c7a8e5a
AM
615static bfd_boolean
616section_is_source_or_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
617 lang_statement_union_type *s)
e0001a05
NC
618{
619 return (section_is_source (deps, s)
620 || section_is_target (deps, s));
621}
622
623
624typedef struct xtensa_ld_iter_stack_t xtensa_ld_iter_stack;
625typedef struct xtensa_ld_iter_t xtensa_ld_iter;
626
627struct xtensa_ld_iter_t
628{
629 lang_statement_union_type *parent; /* Parent of the list. */
630 lang_statement_list_type *l; /* List that holds it. */
631 lang_statement_union_type **loc; /* Place in the list. */
632};
633
634struct xtensa_ld_iter_stack_t
635{
636 xtensa_ld_iter iterloc; /* List that hold it. */
0c7a8e5a 637
e0001a05
NC
638 xtensa_ld_iter_stack *next; /* Next in the stack. */
639 xtensa_ld_iter_stack *prev; /* Back pointer for stack. */
640};
641
e0001a05 642
0c7a8e5a
AM
643static void
644ld_xtensa_move_section_after (xtensa_ld_iter *to, xtensa_ld_iter *current)
e0001a05
NC
645{
646 lang_statement_union_type *to_next;
647 lang_statement_union_type *current_next;
648 lang_statement_union_type **e;
649
650#if EXTRA_VALIDATION
651 size_t old_to_count, new_to_count;
652 size_t old_current_count, new_current_count;
653#endif
654
655 if (to == current)
656 return;
0c7a8e5a 657
e0001a05
NC
658#if EXTRA_VALIDATION
659 old_to_count = ld_count_children (to->parent);
660 old_current_count = ld_count_children (current->parent);
661#endif
662
663 to_next = *(to->loc);
664 current_next = (*current->loc)->header.next;
0c7a8e5a 665
e0001a05 666 *(to->loc) = *(current->loc);
0c7a8e5a 667
e0001a05
NC
668 *(current->loc) = current_next;
669 (*(to->loc))->header.next = to_next;
670
671 /* reset "to" list tail */
672 for (e = &to->l->head; *e != NULL; e = &(*e)->header.next)
673 ;
674 to->l->tail = e;
675
676 /* reset "current" list tail */
677 for (e = &current->l->head; *e != NULL; e = &(*e)->header.next)
678 ;
679 current->l->tail = e;
680
681#if EXTRA_VALIDATION
682 new_to_count = ld_count_children (to->parent);
683 new_current_count = ld_count_children (current->parent);
684
0c7a8e5a 685 ASSERT ((old_to_count + old_current_count)
e0001a05
NC
686 == (new_to_count + new_current_count));
687#endif
688}
689
690
691/* Can only be called with lang_statements that have lists. Returns
43cd72b9 692 FALSE if the list is empty. */
e0001a05 693
0c7a8e5a
AM
694static bfd_boolean
695iter_stack_empty (xtensa_ld_iter_stack **stack_p)
e0001a05 696{
0c7a8e5a 697 return *stack_p == NULL;
e0001a05
NC
698}
699
700
701static bfd_boolean
0c7a8e5a
AM
702iter_stack_push (xtensa_ld_iter_stack **stack_p,
703 lang_statement_union_type *parent)
e0001a05
NC
704{
705 xtensa_ld_iter_stack *stack;
706 lang_statement_list_type *l = NULL;
707
0c7a8e5a 708 switch (parent->header.type)
e0001a05
NC
709 {
710 case lang_output_section_statement_enum:
711 l = &parent->output_section_statement.children;
712 break;
713 case lang_wild_statement_enum:
714 l = &parent->wild_statement.children;
715 break;
716 case lang_group_statement_enum:
717 l = &parent->group_statement.children;
718 break;
719 default:
720 ASSERT (0);
721 return FALSE;
722 }
723
724 /* Empty. do not push. */
0c7a8e5a 725 if (l->tail == &l->head)
e0001a05
NC
726 return FALSE;
727
0c7a8e5a 728 stack = xmalloc (sizeof (xtensa_ld_iter_stack));
e0001a05
NC
729 memset (stack, 0, sizeof (xtensa_ld_iter_stack));
730 stack->iterloc.parent = parent;
731 stack->iterloc.l = l;
732 stack->iterloc.loc = &l->head;
733
734 stack->next = *stack_p;
735 stack->prev = NULL;
0c7a8e5a 736 if (*stack_p != NULL)
e0001a05
NC
737 (*stack_p)->prev = stack;
738 *stack_p = stack;
739 return TRUE;
740}
741
742
0c7a8e5a
AM
743static void
744iter_stack_pop (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
745{
746 xtensa_ld_iter_stack *stack;
747
748 stack = *stack_p;
749
0c7a8e5a 750 if (stack == NULL)
e0001a05
NC
751 {
752 ASSERT (stack != NULL);
753 return;
754 }
755
0c7a8e5a 756 if (stack->next != NULL)
e0001a05
NC
757 stack->next->prev = NULL;
758
759 *stack_p = stack->next;
760 free (stack);
761}
762
763
764/* This MUST be called if, during iteration, the user changes the
765 underlying structure. It will check for a NULL current and advance
766 accordingly. */
767
768static void
0c7a8e5a 769iter_stack_update (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
770{
771 if (!iter_stack_empty (stack_p)
0c7a8e5a 772 && (*(*stack_p)->iterloc.loc) == NULL)
e0001a05
NC
773 {
774 iter_stack_pop (stack_p);
775
776 while (!iter_stack_empty (stack_p)
777 && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
778 {
779 iter_stack_pop (stack_p);
780 }
781 if (!iter_stack_empty (stack_p))
782 (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
783 }
784}
785
786
0c7a8e5a
AM
787static void
788iter_stack_next (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
789{
790 xtensa_ld_iter_stack *stack;
791 lang_statement_union_type *current;
792 stack = *stack_p;
793
794 current = *stack->iterloc.loc;
795 /* If we are on the first element. */
0c7a8e5a 796 if (current != NULL)
e0001a05 797 {
0c7a8e5a 798 switch (current->header.type)
e0001a05
NC
799 {
800 case lang_output_section_statement_enum:
801 case lang_wild_statement_enum:
802 case lang_group_statement_enum:
803 /* If the list if not empty, we are done. */
804 if (iter_stack_push (stack_p, *stack->iterloc.loc))
805 return;
806 /* Otherwise increment the pointer as normal. */
807 break;
808 default:
809 break;
810 }
811 }
812
813 while (!iter_stack_empty (stack_p)
814 && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
815 {
816 iter_stack_pop (stack_p);
817 }
818 if (!iter_stack_empty (stack_p))
819 (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
820}
821
822
823static lang_statement_union_type *
0c7a8e5a 824iter_stack_current (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
825{
826 return *((*stack_p)->iterloc.loc);
827}
828
829
830/* The iter stack is a preorder. */
831
0c7a8e5a
AM
832static void
833iter_stack_create (xtensa_ld_iter_stack **stack_p,
834 lang_statement_union_type *parent)
e0001a05
NC
835{
836 iter_stack_push (stack_p, parent);
837}
838
839
0c7a8e5a 840static void
7fa3d080 841iter_stack_copy_current (xtensa_ld_iter_stack **stack_p, xtensa_ld_iter *front)
e0001a05
NC
842{
843 *front = (*stack_p)->iterloc;
844}
845
846
0c7a8e5a
AM
847static void
848xtensa_colocate_literals (reloc_deps_graph *deps,
849 lang_statement_union_type *statement)
e0001a05
NC
850{
851 /* Keep a stack of pointers to control iteration through the contours. */
852 xtensa_ld_iter_stack *stack = NULL;
853 xtensa_ld_iter_stack **stack_p = &stack;
854
855 xtensa_ld_iter front; /* Location where new insertion should occur. */
856 xtensa_ld_iter *front_p = NULL;
857
858 xtensa_ld_iter current; /* Location we are checking. */
859 xtensa_ld_iter *current_p = NULL;
860 bfd_boolean in_literals = FALSE;
861
862 if (deps->count == 0)
863 return;
864
e0001a05
NC
865 iter_stack_create (stack_p, statement);
866
0c7a8e5a 867 while (!iter_stack_empty (stack_p))
e0001a05
NC
868 {
869 bfd_boolean skip_increment = FALSE;
870 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a
AM
871
872 switch (l->header.type)
e0001a05
NC
873 {
874 case lang_assignment_statement_enum:
875 /* Any assignment statement should block reordering across it. */
876 front_p = NULL;
877 in_literals = FALSE;
878 break;
879
880 case lang_input_section_enum:
881 if (front_p == NULL)
882 {
883 in_literals = (section_is_target (deps, l)
884 && !section_is_source (deps, l));
0c7a8e5a 885 if (in_literals)
e0001a05
NC
886 {
887 front_p = &front;
888 iter_stack_copy_current (stack_p, front_p);
889 }
0c7a8e5a 890 }
e0001a05
NC
891 else
892 {
893 bfd_boolean is_target;
894 current_p = &current;
895 iter_stack_copy_current (stack_p, current_p);
896 is_target = (section_is_target (deps, l)
897 && !section_is_source (deps, l));
898
899 if (in_literals)
900 {
901 iter_stack_copy_current (stack_p, front_p);
902 if (!is_target)
903 in_literals = FALSE;
904 }
905 else
906 {
0c7a8e5a 907 if (is_target)
e0001a05
NC
908 {
909 /* Try to insert in place. */
910 ld_xtensa_move_section_after (front_p, current_p);
0c7a8e5a 911 ld_assign_relative_paged_dot (0x100000,
e0001a05
NC
912 statement,
913 deps,
914 xtensa_use_literal_pages);
0c7a8e5a 915
e0001a05
NC
916 /* We use this code because it's already written. */
917 if (!ld_local_file_relocations_fit (statement, deps))
918 {
919 /* Move it back. */
920 ld_xtensa_move_section_after (current_p, front_p);
921 /* Reset the literal placement. */
922 iter_stack_copy_current (stack_p, front_p);
923 }
0c7a8e5a 924 else
e0001a05
NC
925 {
926 /* Move front pointer up by one. */
927 front_p->loc = &(*front_p->loc)->header.next;
928
929 /* Do not increment the current pointer. */
930 skip_increment = TRUE;
931 }
932 }
933 }
934 }
935 break;
936 default:
937 break;
938 }
939
940 if (!skip_increment)
941 iter_stack_next (stack_p);
942 else
943 /* Be careful to update the stack_p if it now is a null. */
944 iter_stack_update (stack_p);
945 }
0c7a8e5a 946
e0001a05
NC
947 lang_for_each_statement_worker (xtensa_ldlang_clear_addresses, statement);
948}
949
950
0c7a8e5a
AM
951static void
952xtensa_move_dependencies_to_front (reloc_deps_graph *deps,
953 lang_wild_statement_type *w)
e0001a05
NC
954{
955 /* Keep a front pointer and a current pointer. */
956 lang_statement_union_type **front;
957 lang_statement_union_type **current;
958
959 /* Walk to the end of the targets. */
960 for (front = &w->children.head;
961 (*front != NULL) && section_is_source_or_target (deps, *front);
962 front = &(*front)->header.next)
963 ;
964
965 if (*front == NULL)
966 return;
967
968 current = &(*front)->header.next;
0c7a8e5a 969 while (*current != NULL)
e0001a05
NC
970 {
971 if (section_is_source_or_target (deps, *current))
972 {
973 /* Insert in place. */
974 xtensa_ld_iter front_iter;
975 xtensa_ld_iter current_iter;
976
977 front_iter.parent = (lang_statement_union_type *) w;
978 front_iter.l = &w->children;
979 front_iter.loc = front;
980
981 current_iter.parent = (lang_statement_union_type *) w;
982 current_iter.l = &w->children;
983 current_iter.loc = current;
984
985 ld_xtensa_move_section_after (&front_iter, &current_iter);
986 front = &(*front)->header.next;
987 }
988 else
989 {
990 current = &(*current)->header.next;
991 }
992 }
993}
994
995
996static bfd_boolean
7fa3d080 997deps_has_sec_edge (const reloc_deps_graph *deps, asection *src, asection *tgt)
e0001a05
NC
998{
999 const reloc_deps_section *sec_deps;
1000 const reloc_deps_e *sec_deps_e;
1001
1002 sec_deps = xtensa_get_section_deps (deps, src);
1003 if (sec_deps == NULL)
1004 return FALSE;
0c7a8e5a 1005
e0001a05 1006 for (sec_deps_e = sec_deps->succs;
0c7a8e5a 1007 sec_deps_e != NULL;
e0001a05
NC
1008 sec_deps_e = sec_deps_e->next)
1009 {
1010 ASSERT (sec_deps_e->src == src);
0c7a8e5a 1011 if (sec_deps_e->tgt == tgt)
e0001a05
NC
1012 return TRUE;
1013 }
1014 return FALSE;
1015}
1016
1017
1018static bfd_boolean
0c7a8e5a
AM
1019deps_has_edge (const reloc_deps_graph *deps,
1020 lang_statement_union_type *src,
1021 lang_statement_union_type *tgt)
e0001a05
NC
1022{
1023 if (!section_is_source (deps, src))
1024 return FALSE;
1025 if (!section_is_target (deps, tgt))
1026 return FALSE;
1027
1028 if (src->header.type != lang_input_section_enum)
1029 return FALSE;
1030 if (tgt->header.type != lang_input_section_enum)
1031 return FALSE;
0c7a8e5a 1032
e0001a05
NC
1033 return deps_has_sec_edge (deps, src->input_section.section,
1034 tgt->input_section.section);
1035}
1036
1037
1038static void
7fa3d080 1039add_deps_edge (reloc_deps_graph *deps, asection *src_sec, asection *tgt_sec)
e0001a05
NC
1040{
1041 reloc_deps_section *src_sec_deps;
1042 reloc_deps_section *tgt_sec_deps;
1043
1044 reloc_deps_e *src_edge;
1045 reloc_deps_e *tgt_edge;
1046
1047 if (deps_has_sec_edge (deps, src_sec, tgt_sec))
1048 return;
0c7a8e5a 1049
e0001a05
NC
1050 src_sec_deps = xtensa_get_section_deps (deps, src_sec);
1051 if (src_sec_deps == NULL)
1052 {
1053 /* Add a section. */
0c7a8e5a 1054 src_sec_deps = xmalloc (sizeof (reloc_deps_section));
e0001a05
NC
1055 memset (src_sec_deps, 0, sizeof (reloc_deps_section));
1056 src_sec_deps->is_only_literal = 0;
1057 src_sec_deps->preds = NULL;
1058 src_sec_deps->succs = NULL;
1059 xtensa_set_section_deps (deps, src_sec, src_sec_deps);
1060 xtensa_append_section_deps (deps, src_sec);
1061 }
1062
1063 tgt_sec_deps = xtensa_get_section_deps (deps, tgt_sec);
1064 if (tgt_sec_deps == NULL)
1065 {
1066 /* Add a section. */
0c7a8e5a 1067 tgt_sec_deps = xmalloc (sizeof (reloc_deps_section));
e0001a05
NC
1068 memset (tgt_sec_deps, 0, sizeof (reloc_deps_section));
1069 tgt_sec_deps->is_only_literal = 0;
1070 tgt_sec_deps->preds = NULL;
1071 tgt_sec_deps->succs = NULL;
1072 xtensa_set_section_deps (deps, tgt_sec, tgt_sec_deps);
1073 xtensa_append_section_deps (deps, tgt_sec);
1074 }
1075
1076 /* Add the edges. */
0c7a8e5a 1077 src_edge = xmalloc (sizeof (reloc_deps_e));
e0001a05
NC
1078 memset (src_edge, 0, sizeof (reloc_deps_e));
1079 src_edge->src = src_sec;
1080 src_edge->tgt = tgt_sec;
1081 src_edge->next = src_sec_deps->succs;
1082 src_sec_deps->succs = src_edge;
1083
0c7a8e5a 1084 tgt_edge = xmalloc (sizeof (reloc_deps_e));
e0001a05
NC
1085 memset (tgt_edge, 0, sizeof (reloc_deps_e));
1086 tgt_edge->src = src_sec;
1087 tgt_edge->tgt = tgt_sec;
1088 tgt_edge->next = tgt_sec_deps->preds;
1089 tgt_sec_deps->preds = tgt_edge;
1090}
1091
1092
0c7a8e5a
AM
1093static void
1094build_deps_graph_callback (asection *src_sec,
1095 bfd_vma src_offset ATTRIBUTE_UNUSED,
1096 asection *target_sec,
1097 bfd_vma target_offset ATTRIBUTE_UNUSED,
1098 void *closure)
e0001a05 1099{
0c7a8e5a 1100 reloc_deps_graph *deps = closure;
e0001a05
NC
1101
1102 /* If the target is defined. */
1103 if (target_sec != NULL)
1104 add_deps_edge (deps, src_sec, target_sec);
1105}
1106
1107
0c7a8e5a
AM
1108static reloc_deps_graph *
1109ld_build_required_section_dependence (lang_statement_union_type *s)
e0001a05
NC
1110{
1111 reloc_deps_graph *deps;
1112 xtensa_ld_iter_stack *stack = NULL;
1113
0c7a8e5a 1114 deps = xmalloc (sizeof (reloc_deps_graph));
e0001a05
NC
1115 deps->sections = NULL;
1116 deps->count = 0;
1117 deps->size = 0;
0c7a8e5a 1118
e0001a05
NC
1119 for (iter_stack_create (&stack, s);
1120 !iter_stack_empty (&stack);
0c7a8e5a 1121 iter_stack_next (&stack))
e0001a05
NC
1122 {
1123 lang_statement_union_type *l = iter_stack_current (&stack);
1124
1125 if (l->header.type == lang_input_section_enum)
1126 {
1127 lang_input_section_type *input;
1128 input = &l->input_section;
7b986e99 1129 xtensa_callback_required_dependence (input->section->owner,
e0001a05
NC
1130 input->section,
1131 &link_info,
1132 /* Use the same closure. */
1133 build_deps_graph_callback,
0c7a8e5a 1134 deps);
e0001a05
NC
1135 }
1136 }
1137 return deps;
1138}
1139
1140
1141#if EXTRA_VALIDATION
0c7a8e5a
AM
1142static size_t
1143ld_count_children (lang_statement_union_type *s)
e0001a05
NC
1144{
1145 size_t count = 0;
1146 xtensa_ld_iter_stack *stack = NULL;
1147 for (iter_stack_create (&stack, s);
1148 !iter_stack_empty (&stack);
0c7a8e5a 1149 iter_stack_next (&stack))
e0001a05
NC
1150 {
1151 lang_statement_union_type *l = iter_stack_current (&stack);
1152 ASSERT (l != NULL);
1153 count++;
1154 }
1155 return count;
1156}
1157#endif /* EXTRA_VALIDATION */
1158
1159
0c7a8e5a
AM
1160static void
1161xtensa_wild_group_interleave_callback (lang_statement_union_type *statement)
e0001a05
NC
1162{
1163 lang_wild_statement_type *w;
1164 reloc_deps_graph *deps;
1165 if (statement->header.type == lang_wild_statement_enum)
1166 {
1167#if EXTRA_VALIDATION
1168 size_t old_child_count;
1169 size_t new_child_count;
1170#endif
1171 bfd_boolean no_reorder;
1172
1173 w = &statement->wild_statement;
1174
1175 no_reorder = FALSE;
1176
1177 /* If it has 0 or 1 section bound, then do not reorder. */
1178 if (w->children.head == NULL
1179 || (w->children.head->header.type == lang_input_section_enum
1180 && w->children.head->header.next == NULL))
1181 no_reorder = TRUE;
1182
1183 if (w->filenames_sorted)
1184 no_reorder = TRUE;
1185
1186 /* Check for sorting in a section list wildcard spec as well. */
1187 if (!no_reorder)
1188 {
1189 struct wildcard_list *l;
1190 for (l = w->section_list; l != NULL; l = l->next)
1191 {
1192 if (l->spec.sorted == TRUE)
1193 {
1194 no_reorder = TRUE;
1195 break;
1196 }
1197 }
0c7a8e5a 1198 }
e0001a05
NC
1199
1200 /* Special case until the NOREORDER linker directive is supported:
0c7a8e5a 1201 *(.init) output sections and *(.fini) specs may NOT be reordered. */
e0001a05
NC
1202
1203 /* Check for sorting in a section list wildcard spec as well. */
0c7a8e5a 1204 if (!no_reorder)
e0001a05
NC
1205 {
1206 struct wildcard_list *l;
1207 for (l = w->section_list; l != NULL; l = l->next)
1208 {
1209 if (l->spec.name
1210 && ((strcmp (".init", l->spec.name) == 0)
1211 || (strcmp (".fini", l->spec.name) == 0)))
1212 {
1213 no_reorder = TRUE;
1214 break;
1215 }
1216 }
1217 }
1218
1219#if EXTRA_VALIDATION
1220 old_child_count = ld_count_children (statement);
1221#endif
1222
1223 /* It is now officially a target. Build the graph of source
0c7a8e5a 1224 section -> target section (kept as a list of edges). */
e0001a05
NC
1225 deps = ld_build_required_section_dependence (statement);
1226
1227 /* If this wildcard does not reorder.... */
1228 if (!no_reorder && deps->count != 0)
1229 {
1230 /* First check for reverse dependences. Fix if possible. */
1231 xtensa_layout_wild (deps, w);
1232
1233 xtensa_move_dependencies_to_front (deps, w);
1234#if EXTRA_VALIDATION
1235 new_child_count = ld_count_children (statement);
1236 ASSERT (new_child_count == old_child_count);
1237#endif
1238
1239 xtensa_colocate_literals (deps, statement);
1240
1241#if EXTRA_VALIDATION
1242 new_child_count = ld_count_children (statement);
1243 ASSERT (new_child_count == old_child_count);
1244#endif
1245 }
1246
1247 /* Clean up. */
1248 free_reloc_deps_graph (deps);
1249 }
1250}
1251
1252
0c7a8e5a
AM
1253static void
1254xtensa_wild_group_interleave (lang_statement_union_type *s)
e0001a05
NC
1255{
1256 lang_for_each_statement_worker (xtensa_wild_group_interleave_callback, s);
1257}
1258
1259
0c7a8e5a 1260static void
7fa3d080 1261xtensa_layout_wild (const reloc_deps_graph *deps, lang_wild_statement_type *w)
e0001a05
NC
1262{
1263 /* If it does not fit initially, we need to do this step. Move all
1264 of the wild literal sections to a new list, then move each of
1265 them back in just before the first section they depend on. */
1266 lang_statement_union_type **s_p;
1267#if EXTRA_VALIDATION
1268 size_t old_count, new_count;
1269 size_t ct1, ct2;
1270#endif
0c7a8e5a 1271
e0001a05
NC
1272 lang_wild_statement_type literal_wild;
1273 literal_wild.header.next = NULL;
1274 literal_wild.header.type = lang_wild_statement_enum;
1275 literal_wild.filename = NULL;
1276 literal_wild.filenames_sorted = FALSE;
1277 literal_wild.section_list = NULL;
1278 literal_wild.keep_sections = FALSE;
1279 literal_wild.children.head = NULL;
1280 literal_wild.children.tail = &literal_wild.children.head;
1281
1282#if EXTRA_VALIDATION
1283 old_count = ld_count_children ((lang_statement_union_type*) w);
1284#endif
1285
1286 s_p = &w->children.head;
1287 while (*s_p != NULL)
1288 {
1289 lang_statement_union_type *l = *s_p;
1290 if (l->header.type == lang_input_section_enum)
1291 {
1292 if (section_is_target (deps, l)
0c7a8e5a 1293 && ! section_is_source (deps, l))
e0001a05
NC
1294 {
1295 /* Detach. */
1296 *s_p = l->header.next;
1297 if (*s_p == NULL)
1298 w->children.tail = s_p;
1299 l->header.next = NULL;
1300
1301 /* Append. */
1302 *literal_wild.children.tail = l;
1303 literal_wild.children.tail = &l->header.next;
1304 continue;
0c7a8e5a 1305 }
e0001a05
NC
1306 }
1307 s_p = &(*s_p)->header.next;
1308 }
1309
1310#if EXTRA_VALIDATION
1311 ct1 = ld_count_children ((lang_statement_union_type*) w);
1312 ct2 = ld_count_children ((lang_statement_union_type*) &literal_wild);
0c7a8e5a 1313
e0001a05
NC
1314 ASSERT (old_count == (ct1 + ct2));
1315#endif
0c7a8e5a 1316
e0001a05
NC
1317 /* Now place them back in front of their dependent sections. */
1318
1319 while (literal_wild.children.head != NULL)
1320 {
1321 lang_statement_union_type *lit = literal_wild.children.head;
1322 bfd_boolean placed = FALSE;
1323
1324#if EXTRA_VALIDATION
1325 ASSERT (ct2 > 0);
1326 ct2--;
1327#endif
1328
1329 /* Detach. */
1330 literal_wild.children.head = lit->header.next;
0c7a8e5a 1331 if (literal_wild.children.head == NULL)
e0001a05
NC
1332 literal_wild.children.tail = &literal_wild.children.head;
1333 lit->header.next = NULL;
1334
1335 /* Find a spot to place it. */
0c7a8e5a 1336 for (s_p = &w->children.head; *s_p != NULL; s_p = &(*s_p)->header.next)
e0001a05
NC
1337 {
1338 lang_statement_union_type *src = *s_p;
1339 if (deps_has_edge (deps, src, lit))
1340 {
1341 /* Place it here. */
1342 lit->header.next = *s_p;
1343 *s_p = lit;
1344 placed = TRUE;
1345 break;
1346 }
1347 }
0c7a8e5a 1348
e0001a05
NC
1349 if (!placed)
1350 {
1351 /* Put it at the end. */
1352 *w->children.tail = lit;
1353 w->children.tail = &lit->header.next;
1354 }
1355 }
1356
1357#if EXTRA_VALIDATION
1358 new_count = ld_count_children ((lang_statement_union_type*) w);
1359 ASSERT (new_count == old_count);
1360#endif
1361}
1362
1363
0c7a8e5a
AM
1364static void
1365xtensa_colocate_output_literals_callback (lang_statement_union_type *statement)
e0001a05
NC
1366{
1367 lang_output_section_statement_type *os;
1368 reloc_deps_graph *deps;
1369 if (statement->header.type == lang_output_section_statement_enum)
1370 {
1371 /* Now, we walk over the contours of the output section statement.
1372
1373 First we build the literal section dependences as before.
1374
1375 At the first uniquely_literal section, we mark it as a good
1376 spot to place other literals. Continue walking (and counting
1377 sizes) until we find the next literal section. If this
1378 section can be moved to the first one, then we move it. If
1379 we every find a modification of ".", start over. If we find
1380 a labeling of the current location, start over. Finally, at
1381 the end, if we require page alignment, add page alignments. */
1382
1383#if EXTRA_VALIDATION
1384 size_t old_child_count;
1385 size_t new_child_count;
1386#endif
1387 bfd_boolean no_reorder = FALSE;
1388
1389 os = &statement->output_section_statement;
1390
1391#if EXTRA_VALIDATION
1392 old_child_count = ld_count_children (statement);
1393#endif
1394
1395 /* It is now officially a target. Build the graph of source
0c7a8e5a 1396 section -> target section (kept as a list of edges). */
e0001a05
NC
1397
1398 deps = ld_build_required_section_dependence (statement);
1399
1400 /* If this wildcard does not reorder.... */
1401 if (!no_reorder)
1402 {
1403 /* First check for reverse dependences. Fix if possible. */
1404 xtensa_colocate_literals (deps, statement);
1405
1406#if EXTRA_VALIDATION
1407 new_child_count = ld_count_children (statement);
1408 ASSERT (new_child_count == old_child_count);
1409#endif
1410 }
1411
1412 /* Insert align/offset assignment statement. */
1413 if (xtensa_use_literal_pages)
1414 {
0c7a8e5a 1415 ld_xtensa_insert_page_offsets (0, statement, deps,
e0001a05
NC
1416 xtensa_use_literal_pages);
1417 lang_for_each_statement_worker (xtensa_ldlang_clear_addresses,
1418 statement);
1419 }
1420
1421 /* Clean up. */
1422 free_reloc_deps_graph (deps);
1423 }
1424}
1425
1426
0c7a8e5a
AM
1427static void
1428xtensa_colocate_output_literals (lang_statement_union_type *s)
e0001a05
NC
1429{
1430 lang_for_each_statement_worker (xtensa_colocate_output_literals_callback, s);
1431}
1432
1433
0c7a8e5a
AM
1434static void
1435xtensa_ldlang_clear_addresses (lang_statement_union_type *statement)
e0001a05
NC
1436{
1437 switch (statement->header.type)
1438 {
0c7a8e5a 1439 case lang_input_section_enum:
e0001a05
NC
1440 {
1441 asection *bfd_section = statement->input_section.section;
1442 bfd_section->output_offset = 0;
1443 }
1444 break;
1445 default:
1446 break;
1447 }
1448}
1449
1450
0c7a8e5a
AM
1451static bfd_vma
1452ld_assign_relative_paged_dot (bfd_vma dot,
1453 lang_statement_union_type *s,
1454 const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
1455 bfd_boolean lit_align)
e0001a05
NC
1456{
1457 /* Walk through all of the input statements in this wild statement
1458 assign dot to all of them. */
0c7a8e5a 1459
e0001a05
NC
1460 xtensa_ld_iter_stack *stack = NULL;
1461 xtensa_ld_iter_stack **stack_p = &stack;
1462
1463 bfd_boolean first_section = FALSE;
1464 bfd_boolean in_literals = FALSE;
1465
1466 for (iter_stack_create (stack_p, s);
1467 !iter_stack_empty (stack_p);
0c7a8e5a 1468 iter_stack_next (stack_p))
e0001a05
NC
1469 {
1470 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a
AM
1471
1472 switch (l->header.type)
e0001a05
NC
1473 {
1474 case lang_input_section_enum:
1475 {
1476 asection *section = l->input_section.section;
1477 size_t align_pow = section->alignment_power;
1478 bfd_boolean do_xtensa_alignment = FALSE;
0c7a8e5a 1479
e0001a05
NC
1480 if (lit_align)
1481 {
1482 bfd_boolean sec_is_target = section_is_target (deps, l);
1483 bfd_boolean sec_is_source = section_is_source (deps, l);
1484
eea6121a 1485 if (section->size != 0
e0001a05
NC
1486 && (first_section
1487 || (in_literals && !sec_is_target)
1488 || (!in_literals && sec_is_target)))
1489 {
1490 do_xtensa_alignment = TRUE;
1491 }
1492 first_section = FALSE;
eea6121a 1493 if (section->size != 0)
e0001a05
NC
1494 in_literals = (sec_is_target && !sec_is_source);
1495 }
1496
1497 if (do_xtensa_alignment && xtensa_page_power != 0)
1498 dot += (1 << xtensa_page_power);
1499
1500 dot = align_power (dot, align_pow);
1501 section->output_offset = dot;
eea6121a 1502 dot += section->size;
e0001a05
NC
1503 }
1504 break;
1505 case lang_fill_statement_enum:
1506 dot += l->fill_statement.size;
1507 break;
1508 case lang_padding_statement_enum:
1509 dot += l->padding_statement.size;
1510 break;
1511 default:
1512 break;
1513 }
1514 }
1515 return dot;
1516}
1517
1518
0c7a8e5a
AM
1519static bfd_boolean
1520ld_local_file_relocations_fit (lang_statement_union_type *statement,
1521 const reloc_deps_graph *deps ATTRIBUTE_UNUSED)
e0001a05
NC
1522{
1523 /* Walk over all of the dependencies that we identified and make
1524 sure that IF the source and target are here (addr != 0):
1525 1) target addr < source addr
0c7a8e5a 1526 2) (roundup(source + source_size, 4) - rounddown(target, 4))
e0001a05
NC
1527 < (256K - (1 << bad align))
1528 Need a worst-case proof.... */
0c7a8e5a 1529
e0001a05
NC
1530 xtensa_ld_iter_stack *stack = NULL;
1531 xtensa_ld_iter_stack **stack_p = &stack;
1532 size_t max_align_power = 0;
1533 size_t align_penalty = 256;
1534 reloc_deps_e *e;
1535 size_t i;
1536
1537 /* Find the worst-case alignment requirement for this set of statements. */
1538 for (iter_stack_create (stack_p, statement);
1539 !iter_stack_empty (stack_p);
0c7a8e5a 1540 iter_stack_next (stack_p))
e0001a05
NC
1541 {
1542 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a 1543 if (l->header.type == lang_input_section_enum)
e0001a05
NC
1544 {
1545 lang_input_section_type *input = &l->input_section;
1546 asection *section = input->section;
1547 if (section->alignment_power > max_align_power)
1548 max_align_power = section->alignment_power;
1549 }
1550 }
1551
1552 /* Now check that everything fits. */
1553 for (i = 0; i < deps->count; i++)
1554 {
1555 asection *sec = deps->sections[i];
0c7a8e5a 1556 const reloc_deps_section *deps_section =
e0001a05
NC
1557 xtensa_get_section_deps (deps, sec);
1558 if (deps_section)
1559 {
1560 /* We choose to walk through the successors. */
1561 for (e = deps_section->succs; e != NULL; e = e->next)
1562 {
0c7a8e5a 1563 if (e->src != e->tgt
e0001a05
NC
1564 && e->src->output_section == e->tgt->output_section
1565 && e->src->output_offset != 0
1566 && e->tgt->output_offset != 0)
1567 {
0c7a8e5a 1568 bfd_vma l32r_addr =
eea6121a 1569 align_power (e->src->output_offset + e->src->size, 2);
0c7a8e5a 1570 bfd_vma target_addr = e->tgt->output_offset & ~3;
e0001a05
NC
1571 if (l32r_addr < target_addr)
1572 {
1573 fprintf (stderr, "Warning: "
1574 "l32r target section before l32r\n");
1575 return FALSE;
1576 }
1577
0c7a8e5a 1578 if (l32r_addr - target_addr > 256 * 1024 - align_penalty)
e0001a05
NC
1579 return FALSE;
1580 }
1581 }
1582 }
1583 }
1584
1585 return TRUE;
1586}
1587
1588
0c7a8e5a
AM
1589static bfd_vma
1590ld_xtensa_insert_page_offsets (bfd_vma dot,
1591 lang_statement_union_type *s,
1592 reloc_deps_graph *deps,
1593 bfd_boolean lit_align)
e0001a05
NC
1594{
1595 xtensa_ld_iter_stack *stack = NULL;
1596 xtensa_ld_iter_stack **stack_p = &stack;
1597
1598 bfd_boolean first_section = FALSE;
1599 bfd_boolean in_literals = FALSE;
0c7a8e5a 1600
e0001a05
NC
1601 if (!lit_align)
1602 return FALSE;
1603
1604 for (iter_stack_create (stack_p, s);
1605 !iter_stack_empty (stack_p);
0c7a8e5a 1606 iter_stack_next (stack_p))
e0001a05
NC
1607 {
1608 lang_statement_union_type *l = iter_stack_current (stack_p);
1609
0c7a8e5a
AM
1610 switch (l->header.type)
1611 {
e0001a05
NC
1612 case lang_input_section_enum:
1613 {
1614 asection *section = l->input_section.section;
1615 bfd_boolean do_xtensa_alignment = FALSE;
0c7a8e5a 1616
e0001a05
NC
1617 if (lit_align)
1618 {
eea6121a 1619 if (section->size != 0
e0001a05
NC
1620 && (first_section
1621 || (in_literals && !section_is_target (deps, l))
1622 || (!in_literals && section_is_target (deps, l))))
1623 {
1624 do_xtensa_alignment = TRUE;
1625 }
1626 first_section = FALSE;
eea6121a 1627 if (section->size != 0)
e0001a05
NC
1628 {
1629 in_literals = (section_is_target (deps, l)
1630 && !section_is_source (deps, l));
1631 }
1632 }
1633
1634 if (do_xtensa_alignment && xtensa_page_power != 0)
1635 {
1636 /* Create an expression that increments the current address,
1637 i.e., "dot", by (1 << xtensa_align_power). */
1638 etree_type *name_op = exp_nameop (NAME, ".");
1639 etree_type *addend_op = exp_intop (1 << xtensa_page_power);
1640 etree_type *add_op = exp_binop ('+', name_op, addend_op);
1641 etree_type *assign_op = exp_assop ('=', ".", add_op);
1642
1643 lang_assignment_statement_type *assign_stmt;
1644 lang_statement_union_type *assign_union;
1645 lang_statement_list_type tmplist;
1646 lang_statement_list_type *old_stat_ptr = stat_ptr;
0c7a8e5a 1647
e0001a05
NC
1648 /* There is hidden state in "lang_add_assignment". It
1649 appends the new assignment statement to the stat_ptr
1650 list. Thus, we swap it before and after the call. */
1651
1652 tmplist.head = NULL;
1653 tmplist.tail = &tmplist.head;
1654
1655 stat_ptr = &tmplist;
1656 /* Warning: side effect; statement appended to stat_ptr. */
1657 assign_stmt = lang_add_assignment (assign_op);
1658 assign_union = (lang_statement_union_type *) assign_stmt;
1659 stat_ptr = old_stat_ptr;
1660
1661 assign_union->header.next = l;
1662 *(*stack_p)->iterloc.loc = assign_union;
1663 iter_stack_next (stack_p);
0c7a8e5a
AM
1664 }
1665 }
1666 break;
1667 default:
1668 break;
1669 }
e0001a05
NC
1670 }
1671 return dot;
1672}
1673
1674EOF
1675
43cd72b9 1676# Define some shell vars to insert bits of code into the standard ELF
e0001a05
NC
1677# parse_args and list_options functions.
1678#
1679PARSE_AND_LIST_PROLOGUE='
43cd72b9
BW
1680#define OPTION_OPT_SIZEOPT (300)
1681#define OPTION_NO_RELAX (OPTION_OPT_SIZEOPT + 1)
1682#define OPTION_LITERAL_MOVEMENT (OPTION_NO_RELAX + 1)
1683#define OPTION_NO_LITERAL_MOVEMENT (OPTION_LITERAL_MOVEMENT + 1)
1684extern int elf32xtensa_size_opt;
1685extern int elf32xtensa_no_literal_movement;
e0001a05
NC
1686'
1687
1688PARSE_AND_LIST_LONGOPTS='
43cd72b9 1689 { "size-opt", no_argument, NULL, OPTION_OPT_SIZEOPT},
e0001a05 1690 { "no-relax", no_argument, NULL, OPTION_NO_RELAX},
43cd72b9
BW
1691 { "literal-movement", no_argument, NULL, OPTION_LITERAL_MOVEMENT},
1692 { "no-literal-movement", no_argument, NULL, OPTION_NO_LITERAL_MOVEMENT},
e0001a05
NC
1693'
1694
1695PARSE_AND_LIST_OPTIONS='
43cd72b9 1696 fprintf (file, _(" --size-opt\t\tWhen relaxing longcalls, prefer size optimization\n\t\t\t over branch target alignment\n"));
e0001a05
NC
1697 fprintf (file, _(" --no-relax\t\tDo not relax branches or coalesce literals\n"));
1698'
1699
1700PARSE_AND_LIST_ARGS_CASES='
43cd72b9
BW
1701 case OPTION_OPT_SIZEOPT:
1702 elf32xtensa_size_opt = 1;
1703 break;
e0001a05
NC
1704 case OPTION_NO_RELAX:
1705 disable_relaxation = TRUE;
1706 break;
43cd72b9
BW
1707 case OPTION_LITERAL_MOVEMENT:
1708 elf32xtensa_no_literal_movement = 0;
1709 break;
1710 case OPTION_NO_LITERAL_MOVEMENT:
1711 elf32xtensa_no_literal_movement = 1;
1712 break;
e0001a05
NC
1713'
1714
1715# Replace some of the standard ELF functions with our own versions.
1716#
1717LDEMUL_BEFORE_PARSE=elf_xtensa_before_parse
43cd72b9 1718LDEMUL_AFTER_OPEN=elf_xtensa_after_open
e0001a05 1719LDEMUL_CHOOSE_TARGET=elf_xtensa_choose_target
e0001a05
NC
1720LDEMUL_BEFORE_ALLOCATION=elf_xtensa_before_allocation
1721
This page took 0.203732 seconds and 4 git commands to generate.