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