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