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