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