Home | History | Annotate | Download | only in emultempl
      1 # This shell script emits a C file. -*- C -*-
      2 #   Copyright (C) 2011-2014 Free Software Foundation, Inc.
      3 #
      4 # This file is part of the GNU Binutils.
      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
      8 # the Free Software Foundation; either version 3 of the License, or
      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
     18 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19 # MA 02110-1301, USA.
     20 #
     21 
     22 # This file is sourced from elf32.em, and defines extra C6X DSBT specific
     23 # features.
     24 #
     25 fragment <<EOF
     26 #include "ldctor.h"
     27 #include "elf32-tic6x.h"
     28 
     29 static struct elf32_tic6x_params params =
     30 {
     31   0, 64
     32 };
     33 
     34 static int merge_exidx_entries = -1;
     35 
     36 static int
     37 is_tic6x_target (void)
     38 {
     39   extern const bfd_target tic6x_elf32_le_vec;
     40   extern const bfd_target tic6x_elf32_be_vec;
     41   extern const bfd_target tic6x_elf32_linux_le_vec;
     42   extern const bfd_target tic6x_elf32_linux_be_vec;
     43   extern const bfd_target tic6x_elf32_c6000_le_vec;
     44   extern const bfd_target tic6x_elf32_c6000_be_vec;
     45 
     46   return (link_info.output_bfd->xvec == &tic6x_elf32_le_vec
     47 	  || link_info.output_bfd->xvec == &tic6x_elf32_be_vec
     48 	  || link_info.output_bfd->xvec == &tic6x_elf32_linux_le_vec
     49 	  || link_info.output_bfd->xvec == &tic6x_elf32_linux_be_vec
     50 	  || link_info.output_bfd->xvec == &tic6x_elf32_c6000_le_vec
     51 	  || link_info.output_bfd->xvec == &tic6x_elf32_c6000_be_vec);
     52 }
     53 
     54 /* Pass params to backend.  */
     55 
     56 static void
     57 tic6x_after_open (void)
     58 {
     59   if (is_tic6x_target ())
     60     {
     61       if (params.dsbt_index >= params.dsbt_size)
     62 	{
     63 	  einfo (_("%P%F: invalid --dsbt-index %d, outside DSBT size.\n"),
     64 		 params.dsbt_index);
     65 	}
     66       elf32_tic6x_setup (&link_info, &params);
     67     }
     68 
     69   gld${EMULATION_NAME}_after_open ();
     70 }
     71 
     72 static int
     73 compare_output_sec_vma (const void *a, const void *b)
     74 {
     75   asection *asec = *(asection **) a, *bsec = *(asection **) b;
     76   asection *aout = asec->output_section, *bout = bsec->output_section;
     77   bfd_vma avma, bvma;
     78 
     79   /* If there's no output section for some reason, compare equal.  */
     80   if (!aout || !bout)
     81     return 0;
     82 
     83   avma = aout->vma + asec->output_offset;
     84   bvma = bout->vma + bsec->output_offset;
     85 
     86   if (avma > bvma)
     87     return 1;
     88   else if (avma < bvma)
     89     return -1;
     90 
     91   return 0;
     92 }
     93 
     94 static void
     95 gld${EMULATION_NAME}_after_allocation (void)
     96 {
     97   int layout_changed = 0;
     98   int ret;
     99 
    100   if (!link_info.relocatable)
    101     {
    102       /* Build a sorted list of input text sections, then use that to process
    103 	 the unwind table index.  */
    104       unsigned int list_size = 10;
    105       asection **sec_list = (asection **)
    106           xmalloc (list_size * sizeof (asection *));
    107       unsigned int sec_count = 0;
    108 
    109       LANG_FOR_EACH_INPUT_STATEMENT (is)
    110 	{
    111 	  bfd *abfd = is->the_bfd;
    112 	  asection *sec;
    113 
    114 	  if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
    115 	    continue;
    116 
    117 	  for (sec = abfd->sections; sec != NULL; sec = sec->next)
    118 	    {
    119 	      asection *out_sec = sec->output_section;
    120 
    121 	      if (out_sec
    122 		  && elf_section_data (sec)
    123 		  && elf_section_type (sec) == SHT_PROGBITS
    124 		  && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
    125 		  && (sec->flags & SEC_EXCLUDE) == 0
    126 		  && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
    127 		  && out_sec != bfd_abs_section_ptr)
    128 		{
    129 		  if (sec_count == list_size)
    130 		    {
    131 		      list_size *= 2;
    132 		      sec_list = (asection **)
    133                           xrealloc (sec_list, list_size * sizeof (asection *));
    134 		    }
    135 
    136 		  sec_list[sec_count++] = sec;
    137 		}
    138 	    }
    139 	}
    140 
    141       qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
    142 
    143       if (elf32_tic6x_fix_exidx_coverage (sec_list, sec_count, &link_info,
    144 					   merge_exidx_entries))
    145 	layout_changed = 1;
    146 
    147       free (sec_list);
    148     }
    149 
    150   /* bfd_elf32_discard_info just plays with debugging sections,
    151      ie. doesn't affect any code, so we can delay resizing the
    152      sections.  */
    153   ret = bfd_elf_discard_info (link_info.output_bfd, & link_info);
    154   if (ret < 0)
    155     {
    156       einfo ("%X%P: .eh_frame/.stab edit: %E\n");
    157       return;
    158     }
    159   else if (ret > 0)
    160     layout_changed = 1;
    161 
    162   gld${EMULATION_NAME}_map_segments (layout_changed);
    163 }
    164 EOF
    165 
    166 # This code gets inserted into the generic elf32.sc linker script
    167 # and allows us to define our own command line switches.
    168 PARSE_AND_LIST_PROLOGUE='
    169 #define OPTION_DSBT_INDEX		300
    170 #define OPTION_DSBT_SIZE		301
    171 #define OPTION_NO_MERGE_EXIDX_ENTRIES   302
    172 '
    173 
    174 PARSE_AND_LIST_LONGOPTS='
    175   {"dsbt-index", required_argument, NULL, OPTION_DSBT_INDEX},
    176   {"dsbt-size", required_argument, NULL, OPTION_DSBT_SIZE},
    177   { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES },
    178 '
    179 
    180 PARSE_AND_LIST_OPTIONS='
    181   fprintf (file, _("  --dsbt-index <index>\n"));
    182   fprintf (file, _("\t\t\tUse this as the DSBT index for the output object\n"));
    183   fprintf (file, _("  --dsbt-size <index>\n"));
    184   fprintf (file, _("\t\t\tUse this as the number of entries in the DSBT table\n"));
    185   fprintf (file, _("  --no-merge-exidx-entries    Disable merging exidx entries\n"));
    186 '
    187 
    188 PARSE_AND_LIST_ARGS_CASES='
    189     case OPTION_DSBT_INDEX:
    190       {
    191 	char *end;
    192 	params.dsbt_index = strtol (optarg, &end, 0);
    193 	if (*end == 0
    194 	    && params.dsbt_index >= 0 && params.dsbt_index < 0x7fff)
    195 	  break;
    196 	einfo (_("%P%F: invalid --dsbt-index %s\n"), optarg);
    197       }
    198       break;
    199     case OPTION_DSBT_SIZE:
    200       {
    201 	char *end;
    202 	params.dsbt_size = strtol (optarg, &end, 0);
    203 	if (*end == 0
    204 	    && params.dsbt_size >= 0 && params.dsbt_size < 0x7fff)
    205 	  break;
    206 	einfo (_("%P%F: invalid --dsbt-size %s\n"), optarg);
    207       }
    208       break;
    209    case OPTION_NO_MERGE_EXIDX_ENTRIES:
    210       merge_exidx_entries = 0;
    211 '
    212 
    213 LDEMUL_AFTER_OPEN=tic6x_after_open
    214 LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
    215