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