xref: /netbsd-src/external/gpl3/binutils.old/dist/ld/emultempl/msp430.em (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1# This shell script emits a C file. -*- C -*-
2# It does some substitutions.
3fragment <<EOF
4/* This file is is generated by a shell script.  DO NOT EDIT! */
5
6/* Emulate the original gld for the given ${EMULATION_NAME}
7   Copyright (C) 2014-2022 Free Software Foundation, Inc.
8   Written by Steve Chamberlain steve@cygnus.com
9   Extended for the MSP430 by Nick Clifton  nickc@redhat.com
10
11   This file is part of the GNU Binutils.
12
13   This program is free software; you can redistribute it and/or modify
14   it under the terms of the GNU General Public License as published by
15   the Free Software Foundation; either version 3 of the License, or
16   (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
26   MA 02110-1301, USA.  */
27
28#define TARGET_IS_${EMULATION_NAME}
29
30#include "sysdep.h"
31#include "bfd.h"
32#include "bfdlink.h"
33#include "ctf-api.h"
34
35#include "ld.h"
36#include "getopt.h"
37#include "ldmain.h"
38#include "ldmisc.h"
39#include "ldexp.h"
40#include "ldlang.h"
41#include "ldfile.h"
42#include "ldemul.h"
43#include "libiberty.h"
44#include <ldgram.h>
45
46enum regions
47{
48  REGION_NONE = 0,
49  REGION_LOWER,
50  REGION_UPPER,
51  REGION_EITHER = 3,
52};
53
54enum either_placement_stage
55{
56  LOWER_TO_UPPER,
57  UPPER_TO_LOWER,
58};
59
60enum { ROM, RAM };
61
62static int data_region = REGION_NONE;
63static int code_region = REGION_NONE;
64static bool disable_sec_transformation = false;
65
66#define MAX_PREFIX_LENGTH 7
67
68EOF
69
70# Import any needed special functions and/or overrides.
71#
72if test -n "$EXTRA_EM_FILE" ; then
73  source_em ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
74fi
75
76if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
77fragment <<EOF
78
79static void
80gld${EMULATION_NAME}_before_parse (void)
81{
82#ifndef TARGET_			/* I.e., if not generic.  */
83  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
84#endif /* not TARGET_ */
85
86  /* The MSP430 port *needs* linker relaxtion in order to cope with large
87     functions where conditional branches do not fit into a +/- 1024 byte range.  */
88  if (!bfd_link_relocatable (&link_info))
89    TARGET_ENABLE_RELAXATION;
90}
91
92EOF
93fi
94
95if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
96fragment <<EOF
97
98static char *
99gld${EMULATION_NAME}_get_script (int *isfile)
100EOF
101
102if test x"$COMPILE_IN" = xyes
103then
104# Scripts compiled in.
105
106# sed commands to quote an ld script as a C string.
107sc="-f stringify.sed"
108
109fragment <<EOF
110{
111  *isfile = 0;
112
113  if (bfd_link_relocatable (&link_info) && config.build_constructors)
114    return
115EOF
116sed $sc ldscripts/${EMULATION_NAME}.xu                 >> e${EMULATION_NAME}.c
117echo '  ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c
118sed $sc ldscripts/${EMULATION_NAME}.xr                 >> e${EMULATION_NAME}.c
119echo '  ; else if (!config.text_read_only) return'     >> e${EMULATION_NAME}.c
120sed $sc ldscripts/${EMULATION_NAME}.xbn                >> e${EMULATION_NAME}.c
121echo '  ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
122sed $sc ldscripts/${EMULATION_NAME}.xn                 >> e${EMULATION_NAME}.c
123echo '  ; else return'                                 >> e${EMULATION_NAME}.c
124sed $sc ldscripts/${EMULATION_NAME}.x                  >> e${EMULATION_NAME}.c
125echo '; }'                                             >> e${EMULATION_NAME}.c
126
127else
128# Scripts read from the filesystem.
129
130fragment <<EOF
131{
132  *isfile = 1;
133
134  if (bfd_link_relocatable (&link_info) && config.build_constructors)
135    return "ldscripts/${EMULATION_NAME}.xu";
136  else if (bfd_link_relocatable (&link_info))
137    return "ldscripts/${EMULATION_NAME}.xr";
138  else if (!config.text_read_only)
139    return "ldscripts/${EMULATION_NAME}.xbn";
140  else if (!config.magic_demand_paged)
141    return "ldscripts/${EMULATION_NAME}.xn";
142  else
143    return "ldscripts/${EMULATION_NAME}.x";
144}
145EOF
146fi
147fi
148
149if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
150fragment <<EOF
151
152static unsigned int
153data_statement_size (lang_data_statement_type *d)
154{
155  unsigned int size = 0;
156  switch (d->type)
157    {
158    case QUAD:
159    case SQUAD:
160      size = QUAD_SIZE;
161      break;
162    case LONG:
163      size = LONG_SIZE;
164      break;
165    case SHORT:
166      size = SHORT_SIZE;
167      break;
168    case BYTE:
169      size = BYTE_SIZE;
170      break;
171    default:
172      einfo (_("%P: error: unhandled data_statement size\n"));
173      FAIL ();
174    }
175  return size;
176}
177
178/* Helper function for place_orphan that computes the size
179   of sections already mapped to the given statement.  */
180
181static bfd_size_type
182scan_children (lang_statement_union_type * l)
183{
184  bfd_size_type amount = 0;
185
186  while (l != NULL)
187    {
188      switch (l->header.type)
189	{
190	case lang_input_section_enum:
191	  if (l->input_section.section->flags & SEC_ALLOC)
192	    amount += l->input_section.section->size;
193	  break;
194
195	case lang_constructors_statement_enum:
196	case lang_assignment_statement_enum:
197	case lang_padding_statement_enum:
198	  break;
199
200	case lang_wild_statement_enum:
201	  amount += scan_children (l->wild_statement.children.head);
202	  break;
203
204	case lang_data_statement_enum:
205	  amount += data_statement_size (&l->data_statement);
206	  break;
207
208	default:
209	  fprintf (stderr, "msp430 orphan placer: unhandled lang type %d\n", l->header.type);
210	  break;
211	}
212
213      l = l->header.next;
214    }
215
216  return amount;
217}
218
219#define WARN_UPPER 0
220#define WARN_LOWER 1
221#define WARN_TEXT 0
222#define WARN_DATA 1
223#define WARN_BSS 2
224#define WARN_RODATA 3
225
226/* Warn only once per output section.
227 * NAME starts with ".upper." or ".lower.".  */
228static void
229warn_no_output_section (const char *name)
230{
231  static bool warned[2][4] = {{false, false, false, false},
232			      {false, false, false, false}};
233  int i = WARN_LOWER;
234
235  if (strncmp (name, ".upper.", 7) == 0)
236    i = WARN_UPPER;
237
238  if (!warned[i][WARN_TEXT] && strcmp (name + 6, ".text") == 0)
239    warned[i][WARN_TEXT] = true;
240  else if (!warned[i][WARN_DATA] && strcmp (name + 6, ".data") == 0)
241    warned[i][WARN_DATA] = true;
242  else if (!warned[i][WARN_BSS] && strcmp (name + 6, ".bss") == 0)
243    warned[i][WARN_BSS] = true;
244  else if (!warned[i][WARN_RODATA] && strcmp (name + 6, ".rodata") == 0)
245    warned[i][WARN_RODATA] = true;
246  else
247    return;
248  einfo ("%P: warning: no input section rule matches %s in linker script\n",
249	 name);
250}
251
252
253/* Place an orphan section.  We use this to put .either sections
254   into either their lower or their upper equivalents.  */
255
256static lang_output_section_statement_type *
257gld${EMULATION_NAME}_place_orphan (asection * s,
258				   const char * secname,
259				   int constraint)
260{
261  char * lower_name;
262  char * upper_name;
263  char * name;
264  lang_output_section_statement_type * lower;
265  lang_output_section_statement_type * upper;
266
267  if ((s->flags & SEC_ALLOC) == 0)
268    return NULL;
269
270  if (bfd_link_relocatable (&link_info))
271    return NULL;
272
273  /* If constraints are involved let the linker handle the placement normally.  */
274  if (constraint != 0)
275    return NULL;
276
277  if (strncmp (secname, ".upper.", 7) == 0
278      || strncmp (secname, ".lower.", 7) == 0)
279    {
280      warn_no_output_section (secname);
281      return NULL;
282    }
283
284  /* We only need special handling for .either sections.  */
285  if (strncmp (secname, ".either.", 8) != 0)
286    return NULL;
287
288  /* Skip the .either prefix.  */
289  secname += 7;
290
291  /* Compute the names of the corresponding upper and lower
292     sections.  If the input section name contains another period,
293     only use the part of the name before the second dot.  */
294  if (strchr (secname + 1, '.') != NULL)
295    {
296      name = xstrdup (secname);
297
298      * strchr (name + 1, '.') = 0;
299    }
300  else
301    name = (char *) secname;
302
303  lower_name = concat (".lower", name, NULL);
304  upper_name = concat (".upper", name, NULL);
305
306  /* Find the corresponding lower and upper sections.  */
307  lower = lang_output_section_find (lower_name);
308  upper = lang_output_section_find (upper_name);
309
310  if (lower == NULL && upper == NULL)
311    {
312      einfo (_("%P: error: no section named %s or %s in linker script\n"),
313	     lower_name, upper_name);
314      goto end;
315    }
316  else if (lower == NULL)
317    {
318      lower = lang_output_section_find (name);
319      if (lower == NULL)
320	{
321	  einfo (_("%P: error: no section named %s in linker script\n"), name);
322	  goto end;
323	}
324    }
325
326  /* Always place orphaned sections in lower.  Optimal placement of either
327     sections is performed later, once section sizes have been finalized.  */
328  lang_add_section (& lower->children, s, NULL, NULL, lower);
329 end:
330  free (upper_name);
331  free (lower_name);
332  return lower;
333}
334EOF
335fi
336
337fragment <<EOF
338
339static bool
340change_output_section (lang_statement_union_type **head,
341		       asection *s,
342		       lang_output_section_statement_type *new_os,
343		       lang_output_section_statement_type *old_os)
344{
345  asection *is;
346  lang_statement_union_type * prev = NULL;
347  lang_statement_union_type * curr;
348
349  curr = *head;
350  while (curr != NULL)
351    {
352      switch (curr->header.type)
353	{
354	case lang_input_section_enum:
355	  is = curr->input_section.section;
356	  if (is == s)
357	    {
358	      lang_statement_list_type *old_list
359		= (lang_statement_list_type *) &old_os->children;
360	      s->output_section = NULL;
361	      lang_add_section (&new_os->children, s,
362				curr->input_section.pattern, NULL, new_os);
363
364	      /* Remove the section from the old output section.  */
365	      if (prev == NULL)
366		*head = curr->header.next;
367	      else
368		prev->header.next = curr->header.next;
369	      /* If the input section we just moved is the tail of the old
370		 output section, then we also need to adjust that tail.  */
371	      if (old_list->tail == (lang_statement_union_type **) curr)
372		old_list->tail = (lang_statement_union_type **) prev;
373
374	      return true;
375	    }
376	  break;
377	case lang_wild_statement_enum:
378	  if (change_output_section (&(curr->wild_statement.children.head),
379				     s, new_os, old_os))
380	    return true;
381	  break;
382	default:
383	  break;
384	}
385      prev = curr;
386      curr = curr->header.next;
387    }
388  return false;
389}
390
391static void
392add_region_prefix (bfd *abfd ATTRIBUTE_UNUSED, asection *s,
393		   void *unused ATTRIBUTE_UNUSED)
394{
395  const char *curr_name = bfd_section_name (s);
396  int region = REGION_NONE;
397
398  if (strncmp (curr_name, ".text", 5) == 0)
399    region = code_region;
400  else if (strncmp (curr_name, ".data", 5) == 0)
401    region = data_region;
402  else if (strncmp (curr_name, ".bss", 4) == 0)
403    region = data_region;
404  else if (strncmp (curr_name, ".rodata", 7) == 0)
405    region = data_region;
406  else
407    return;
408
409  switch (region)
410    {
411    case REGION_NONE:
412      break;
413    case REGION_UPPER:
414      bfd_rename_section (s, concat (".upper", curr_name, NULL));
415      break;
416    case REGION_LOWER:
417      bfd_rename_section (s, concat (".lower", curr_name, NULL));
418      break;
419    case REGION_EITHER:
420      s->name = concat (".either", curr_name, NULL);
421      break;
422    default:
423      /* Unreachable.  */
424      FAIL ();
425      break;
426    }
427}
428
429static void
430msp430_elf_after_open (void)
431{
432  bfd *abfd;
433
434  gld${EMULATION_NAME}_after_open ();
435
436  /* If neither --code-region or --data-region have been passed, do not
437     transform sections names.  */
438  if ((code_region == REGION_NONE && data_region == REGION_NONE)
439      || disable_sec_transformation)
440    return;
441
442  for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next)
443    bfd_map_over_sections (abfd, add_region_prefix, NULL);
444}
445
446#define OPTION_CODE_REGION		321
447#define OPTION_DATA_REGION		(OPTION_CODE_REGION + 1)
448#define OPTION_DISABLE_TRANS		(OPTION_CODE_REGION + 2)
449
450static void
451gld${EMULATION_NAME}_add_options
452  (int ns, char **shortopts, int nl, struct option **longopts,
453   int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
454{
455  static const char xtra_short[] = { };
456
457  static const struct option xtra_long[] =
458    {
459      { "code-region", required_argument, NULL, OPTION_CODE_REGION },
460      { "data-region", required_argument, NULL, OPTION_DATA_REGION },
461      { "disable-sec-transformation", no_argument, NULL,
462	OPTION_DISABLE_TRANS },
463      { NULL, no_argument, NULL, 0 }
464    };
465
466  *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
467  memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
468  *longopts = (struct option *)
469    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
470  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
471}
472
473static void
474gld${EMULATION_NAME}_list_options (FILE * file)
475{
476  fprintf (file, _("  --code-region={either,lower,upper,none}\n\
477        Transform .text* sections to {either,lower,upper,none}.text* sections\n"));
478  fprintf (file, _("  --data-region={either,lower,upper,none}\n\
479        Transform .data*, .rodata* and .bss* sections to\n\
480        {either,lower,upper,none}.{bss,data,rodata}* sections\n"));
481  fprintf (file, _("  --disable-sec-transformation\n\
482        Disable transformation of .{text,data,bss,rodata}* sections to\n\
483        add the {either,lower,upper,none} prefixes\n"));
484}
485
486static bool
487gld${EMULATION_NAME}_handle_option (int optc)
488{
489  switch (optc)
490    {
491    case OPTION_CODE_REGION:
492      if (strcmp (optarg, "upper") == 0)
493	code_region = REGION_UPPER;
494      else if (strcmp (optarg, "lower") == 0)
495	code_region = REGION_LOWER;
496      else if (strcmp (optarg, "either") == 0)
497	code_region = REGION_EITHER;
498      else if (strcmp (optarg, "none") == 0)
499	code_region = REGION_NONE;
500      else if (strlen (optarg) == 0)
501	{
502	  einfo (_("%P: --code-region requires an argument: "
503		   "{upper,lower,either,none}\n"));
504	  return false;
505	}
506      else
507	{
508	  einfo (_("%P: error: unrecognized argument to --code-region= option: "
509		   "\"%s\"\n"), optarg);
510	  return false;
511	}
512      break;
513
514    case OPTION_DATA_REGION:
515      if (strcmp (optarg, "upper") == 0)
516	data_region = REGION_UPPER;
517      else if (strcmp (optarg, "lower") == 0)
518	data_region = REGION_LOWER;
519      else if (strcmp (optarg, "either") == 0)
520	data_region = REGION_EITHER;
521      else if (strcmp (optarg, "none") == 0)
522	data_region = REGION_NONE;
523      else if (strlen (optarg) == 0)
524	{
525	  einfo (_("%P: --data-region requires an argument: "
526		   "{upper,lower,either,none}\n"));
527	  return false;
528	}
529      else
530	{
531	  einfo (_("%P: error: unrecognized argument to --data-region= option: "
532		   "\"%s\"\n"), optarg);
533	  return false;
534	}
535      break;
536
537    case OPTION_DISABLE_TRANS:
538      disable_sec_transformation = true;
539      break;
540
541    default:
542      return false;
543    }
544  return true;
545}
546
547static void
548eval_upper_either_sections (bfd *abfd ATTRIBUTE_UNUSED,
549			    asection *s, void *data)
550{
551  const char * base_sec_name;
552  const char * curr_name;
553  char * either_name;
554  int curr_region;
555
556  lang_output_section_statement_type * lower;
557  lang_output_section_statement_type * upper;
558  static bfd_size_type *lower_size = 0;
559  static bfd_size_type *upper_size = 0;
560  static bfd_size_type lower_size_rom = 0;
561  static bfd_size_type lower_size_ram = 0;
562  static bfd_size_type upper_size_rom = 0;
563  static bfd_size_type upper_size_ram = 0;
564
565  if ((s->flags & SEC_ALLOC) == 0)
566    return;
567  if (bfd_link_relocatable (&link_info))
568    return;
569
570  base_sec_name = (const char *) data;
571  curr_name = bfd_section_name (s);
572
573  /* Only concerned with .either input sections in the upper output section.  */
574  either_name = concat (".either", base_sec_name, NULL);
575  if (strncmp (curr_name, either_name, strlen (either_name)) != 0
576      || strncmp (s->output_section->name, ".upper", 6) != 0)
577    goto end;
578
579  lower = lang_output_section_find (concat (".lower", base_sec_name, NULL));
580  upper = lang_output_section_find (concat (".upper", base_sec_name, NULL));
581
582  if (upper == NULL || upper->region == NULL)
583    goto end;
584  else if (lower == NULL)
585    lower = lang_output_section_find (base_sec_name);
586  if (lower == NULL || lower->region == NULL)
587    goto end;
588
589  if (strcmp (base_sec_name, ".text") == 0
590      || strcmp (base_sec_name, ".rodata") == 0)
591    curr_region = ROM;
592  else
593    curr_region = RAM;
594
595  if (curr_region == ROM)
596    {
597      if (lower_size_rom == 0)
598	{
599	  lower_size_rom = lower->region->current - lower->region->origin;
600	  upper_size_rom = upper->region->current - upper->region->origin;
601	}
602      lower_size = &lower_size_rom;
603      upper_size = &upper_size_rom;
604    }
605  else if (curr_region == RAM)
606    {
607      if (lower_size_ram == 0)
608	{
609	  lower_size_ram = lower->region->current - lower->region->origin;
610	  upper_size_ram = upper->region->current - upper->region->origin;
611	}
612      lower_size = &lower_size_ram;
613      upper_size = &upper_size_ram;
614    }
615
616  /* If the upper region is overflowing, try moving sections to the lower
617     region.
618     Note that there isn't any general benefit to using lower memory over upper
619     memory, so we only move sections around with the goal of making the program
620     fit.  */
621  if (*upper_size > upper->region->length
622      && *lower_size + s->size < lower->region->length)
623    {
624      if (change_output_section (&(upper->children.head), s, lower, upper))
625	{
626	  *upper_size -= s->size;
627	  *lower_size += s->size;
628	}
629    }
630 end:
631  free (either_name);
632}
633
634static void
635eval_lower_either_sections (bfd *abfd ATTRIBUTE_UNUSED,
636			    asection *s, void *data)
637{
638  const char * base_sec_name;
639  const char * curr_name;
640  char * either_name;
641  int curr_region;
642  lang_output_section_statement_type * output_sec;
643  lang_output_section_statement_type * lower;
644  lang_output_section_statement_type * upper;
645
646  static bfd_size_type *lower_size = 0;
647  static bfd_size_type lower_size_rom = 0;
648  static bfd_size_type lower_size_ram = 0;
649
650  if ((s->flags & SEC_ALLOC) == 0)
651    return;
652  if (bfd_link_relocatable (&link_info))
653    return;
654
655  base_sec_name = (const char *) data;
656  curr_name = bfd_section_name (s);
657
658  /* Only concerned with .either input sections in the lower or "default"
659     output section i.e. not in the upper output section.  */
660  either_name = concat (".either", base_sec_name, NULL);
661  if (strncmp (curr_name, either_name, strlen (either_name)) != 0
662      || strncmp (s->output_section->name, ".upper", 6) == 0)
663    return;
664
665  if (strcmp (base_sec_name, ".text") == 0
666      || strcmp (base_sec_name, ".rodata") == 0)
667    curr_region = ROM;
668  else
669    curr_region = RAM;
670
671  output_sec = lang_output_section_find (s->output_section->name);
672
673  /* If the output_section doesn't exist, this has already been reported in
674     place_orphan, so don't need to warn again.  */
675  if (output_sec == NULL || output_sec->region == NULL)
676    goto end;
677
678  /* lower and output_sec might be the same, but in some cases an .either
679     section can end up in base_sec_name if it hasn't been placed by
680     place_orphan.  */
681  lower = lang_output_section_find (concat (".lower", base_sec_name, NULL));
682  upper = lang_output_section_find (concat (".upper", base_sec_name, NULL));
683  if (upper == NULL)
684    goto end;
685
686  if (curr_region == ROM)
687    {
688      if (lower_size_rom == 0)
689	{
690	  /* Get the size of other items in the lower region that aren't the
691	     sections to be moved around.  */
692	  lower_size_rom
693	    = (output_sec->region->current - output_sec->region->origin)
694	    - scan_children (output_sec->children.head);
695	  if (output_sec != lower && lower != NULL)
696	    lower_size_rom -= scan_children (lower->children.head);
697	}
698      lower_size = &lower_size_rom;
699    }
700  else if (curr_region == RAM)
701    {
702      if (lower_size_ram == 0)
703	{
704	  lower_size_ram
705	    = (output_sec->region->current - output_sec->region->origin)
706	    - scan_children (output_sec->children.head);
707	  if (output_sec != lower && lower != NULL)
708	    lower_size_ram -= scan_children (lower->children.head);
709	}
710      lower_size = &lower_size_ram;
711    }
712  /* Move sections that cause the lower region to overflow to the upper region.  */
713  if (*lower_size + s->size > output_sec->region->length)
714    change_output_section (&(output_sec->children.head), s, upper, output_sec);
715  else
716    *lower_size += s->size;
717 end:
718  free (either_name);
719}
720
721/* This function is similar to lang_relax_sections, but without the size
722   evaluation code that is always executed after relaxation.  */
723static void
724intermediate_relax_sections (void)
725{
726  int i = link_info.relax_pass;
727
728  /* The backend can use it to determine the current pass.  */
729  link_info.relax_pass = 0;
730
731  while (i--)
732    {
733      bool relax_again;
734
735      link_info.relax_trip = -1;
736      do
737	{
738	  link_info.relax_trip++;
739
740	  lang_do_assignments (lang_assigning_phase_enum);
741
742	  lang_reset_memory_regions ();
743
744	  relax_again = false;
745	  lang_size_sections (&relax_again, false);
746	}
747      while (relax_again);
748
749      link_info.relax_pass++;
750    }
751}
752
753static void
754msp430_elf_after_allocation (void)
755{
756  int relax_count = 0;
757  unsigned int i;
758  /* Go over each section twice, once to place either sections that don't fit
759     in lower into upper, and then again to move any sections in upper that
760     fit in lower into lower.  */
761  for (i = 0; i < 8; i++)
762    {
763      int placement_stage = (i < 4) ? LOWER_TO_UPPER : UPPER_TO_LOWER;
764      const char * base_sec_name;
765      lang_output_section_statement_type * upper;
766
767      switch (i % 4)
768	{
769	default:
770	case 0:
771	  base_sec_name = ".text";
772	  break;
773	case 1:
774	  base_sec_name = ".data";
775	  break;
776	case 2:
777	  base_sec_name = ".bss";
778	  break;
779	case 3:
780	  base_sec_name = ".rodata";
781	  break;
782	}
783      upper = lang_output_section_find (concat (".upper", base_sec_name, NULL));
784      if (upper != NULL)
785	{
786	  /* Can't just use one iteration over the all the sections to make
787	     both lower->upper and upper->lower transformations because the
788	     iterator encounters upper sections before all lower sections have
789	     been examined.  */
790	  bfd *abfd;
791
792	  if (placement_stage == LOWER_TO_UPPER)
793	    {
794	      /* Perform relaxation and get the final size of sections
795		 before trying to fit .either sections in the correct
796		 ouput sections.  */
797	      if (relax_count == 0)
798		{
799		  intermediate_relax_sections ();
800		  relax_count++;
801		}
802	      for (abfd = link_info.input_bfds; abfd != NULL;
803		   abfd = abfd->link.next)
804		{
805		  bfd_map_over_sections (abfd, eval_lower_either_sections,
806					 (void *) base_sec_name);
807		}
808	    }
809	  else if (placement_stage == UPPER_TO_LOWER)
810	    {
811	      /* Relax again before moving upper->lower.  */
812	      if (relax_count == 1)
813		{
814		  intermediate_relax_sections ();
815		  relax_count++;
816		}
817	      for (abfd = link_info.input_bfds; abfd != NULL;
818		   abfd = abfd->link.next)
819		{
820		  bfd_map_over_sections (abfd, eval_upper_either_sections,
821					 (void *) base_sec_name);
822		}
823	    }
824
825	}
826    }
827  gld${EMULATION_NAME}_after_allocation ();
828}
829
830/* Return TRUE if a non-debug input section in L has positive size and matches
831   the given name.  */
832static int
833input_section_exists (lang_statement_union_type * l, const char * name)
834{
835  while (l != NULL)
836    {
837      switch (l->header.type)
838	{
839	case lang_input_section_enum:
840	  if ((l->input_section.section->flags & SEC_ALLOC)
841	      && l->input_section.section->size > 0
842	      && !strcmp (l->input_section.section->name, name))
843	    return true;
844	  break;
845
846	case lang_wild_statement_enum:
847	  if (input_section_exists (l->wild_statement.children.head, name))
848	    return true;
849	  break;
850
851	default:
852	  break;
853	}
854      l = l->header.next;
855    }
856  return false;
857}
858
859/* Some MSP430 linker scripts do not include ALIGN directives to ensure
860   __preinit_array_start, __init_array_start or __fini_array_start are word
861   aligned.
862   If __*_array_start symbols are not word aligned, the code in crt0 to run
863   through the array and call the functions will crash.
864   To avoid warning unnecessarily when the .*_array sections are not being
865   used for running constructors/destructors, only emit the warning if
866   the associated section exists and has size.  */
867static void
868check_array_section_alignment (void)
869{
870  int i;
871  lang_output_section_statement_type * rodata_sec;
872  lang_output_section_statement_type * rodata2_sec;
873  const char * array_names[3][2] = { { ".init_array", "__init_array_start" },
874	{ ".preinit_array", "__preinit_array_start" },
875	{ ".fini_array", "__fini_array_start" } };
876
877  /* .{preinit,init,fini}_array could be in either .rodata or .rodata2.  */
878  rodata_sec = lang_output_section_find (".rodata");
879  rodata2_sec = lang_output_section_find (".rodata2");
880  if (rodata_sec == NULL && rodata2_sec == NULL)
881    return;
882
883  /* There are 3 .*_array sections which must be checked for alignment.  */
884  for (i = 0; i < 3; i++)
885    {
886      struct bfd_link_hash_entry * sym;
887      if (((rodata_sec && input_section_exists (rodata_sec->children.head,
888						array_names[i][0]))
889	   || (rodata2_sec && input_section_exists (rodata2_sec->children.head,
890						    array_names[i][0])))
891	  && (sym = bfd_link_hash_lookup (link_info.hash, array_names[i][1],
892					  false, false, true))
893	  && sym->type == bfd_link_hash_defined
894	  && sym->u.def.value % 2)
895	{
896	  einfo ("%P: warning: \"%s\" symbol (%pU) is not word aligned\n",
897		 array_names[i][1], NULL);
898	}
899    }
900}
901
902static void
903gld${EMULATION_NAME}_finish (void)
904{
905  finish_default ();
906  check_array_section_alignment ();
907}
908EOF
909
910LDEMUL_AFTER_OPEN=msp430_elf_after_open
911LDEMUL_AFTER_ALLOCATION=msp430_elf_after_allocation
912LDEMUL_PLACE_ORPHAN=${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}
913LDEMUL_FINISH=gld${EMULATION_NAME}_finish
914LDEMUL_ADD_OPTIONS=gld${EMULATION_NAME}_add_options
915LDEMUL_HANDLE_OPTION=gld${EMULATION_NAME}_handle_option
916LDEMUL_LIST_OPTIONS=gld${EMULATION_NAME}_list_options
917
918source_em ${srcdir}/emultempl/emulation.em
919#
920# Local Variables:
921# mode: c
922# End:
923