Home | History | Annotate | Download | only in emultempl
      1 # This shell script emits a C file. -*- C -*-
      2 #   Copyright (C) 1991-2016 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 hppa-elf
     23 # specific routines.
     24 #
     25 fragment <<EOF
     26 
     27 #include "ldctor.h"
     28 #include "elf32-hppa.h"
     29 
     30 
     31 /* Fake input file for stubs.  */
     32 static lang_input_statement_type *stub_file;
     33 
     34 /* Type of import/export stubs to build.  For a single sub-space model,
     35    we can build smaller import stubs and there is no need for export
     36    stubs.  */
     37 static int multi_subspace = 0;
     38 
     39 /* Whether we need to call hppa_layout_sections_again.  */
     40 static int need_laying_out = 0;
     41 
     42 /* Maximum size of a group of input sections that can be handled by
     43    one stub section.  A value of +/-1 indicates the bfd back-end
     44    should use a suitable default size.  */
     45 static bfd_signed_vma group_size = 1;
     46 
     47 /* Stops the linker merging .text sections on a relocatable link,
     48    and adds millicode library to the list of input files.  */
     49 
     50 static void
     51 hppaelf_after_parse (void)
     52 {
     53   if (bfd_link_relocatable (&link_info))
     54     lang_add_unique (".text");
     55 
     56   /* Enable this once we split millicode stuff from libgcc:
     57      lang_add_input_file ("milli",
     58      			  lang_input_file_is_l_enum,
     59 			  NULL);
     60   */
     61 
     62   gld${EMULATION_NAME}_after_parse ();
     63 }
     64 
     65 /* This is called before the input files are opened.  We create a new
     66    fake input file to hold the stub sections.  */
     67 
     68 static void
     69 hppaelf_create_output_section_statements (void)
     70 {
     71   if (!(bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
     72 	&& (elf_object_id (link_info.output_bfd) == HPPA32_ELF_DATA
     73 	    || elf_object_id (link_info.output_bfd) == HPPA64_ELF_DATA)))
     74     return;
     75 
     76   stub_file = lang_add_input_file ("linker stubs",
     77 				   lang_input_file_is_fake_enum,
     78 				   NULL);
     79   stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
     80   if (stub_file->the_bfd == NULL
     81       || ! bfd_set_arch_mach (stub_file->the_bfd,
     82 			      bfd_get_arch (link_info.output_bfd),
     83 			      bfd_get_mach (link_info.output_bfd)))
     84     {
     85       einfo ("%X%P: can not create BFD %E\n");
     86       return;
     87     }
     88 
     89   stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
     90   ldlang_add_file (stub_file);
     91   elf32_hppa_init_stub_bfd (stub_file->the_bfd, &link_info);
     92 }
     93 
     94 
     95 struct hook_stub_info
     96 {
     97   lang_statement_list_type add;
     98   asection *input_section;
     99 };
    100 
    101 /* Traverse the linker tree to find the spot where the stub goes.  */
    102 
    103 static bfd_boolean
    104 hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
    105 {
    106   lang_statement_union_type *l;
    107   bfd_boolean ret;
    108 
    109   for (; (l = *lp) != NULL; lp = &l->header.next)
    110     {
    111       switch (l->header.type)
    112 	{
    113 	case lang_constructors_statement_enum:
    114 	  ret = hook_in_stub (info, &constructor_list.head);
    115 	  if (ret)
    116 	    return ret;
    117 	  break;
    118 
    119 	case lang_output_section_statement_enum:
    120 	  ret = hook_in_stub (info,
    121 			      &l->output_section_statement.children.head);
    122 	  if (ret)
    123 	    return ret;
    124 	  break;
    125 
    126 	case lang_wild_statement_enum:
    127 	  ret = hook_in_stub (info, &l->wild_statement.children.head);
    128 	  if (ret)
    129 	    return ret;
    130 	  break;
    131 
    132 	case lang_group_statement_enum:
    133 	  ret = hook_in_stub (info, &l->group_statement.children.head);
    134 	  if (ret)
    135 	    return ret;
    136 	  break;
    137 
    138 	case lang_input_section_enum:
    139 	  if (l->input_section.section == info->input_section)
    140 	    {
    141 	      /* We've found our section.  Insert the stub immediately
    142 		 before its associated input section.  */
    143 	      *lp = info->add.head;
    144 	      *(info->add.tail) = l;
    145 	      return TRUE;
    146 	    }
    147 	  break;
    148 
    149 	case lang_data_statement_enum:
    150 	case lang_reloc_statement_enum:
    151 	case lang_object_symbols_statement_enum:
    152 	case lang_output_statement_enum:
    153 	case lang_target_statement_enum:
    154 	case lang_input_statement_enum:
    155 	case lang_assignment_statement_enum:
    156 	case lang_padding_statement_enum:
    157 	case lang_address_statement_enum:
    158 	case lang_fill_statement_enum:
    159 	  break;
    160 
    161 	default:
    162 	  FAIL ();
    163 	  break;
    164 	}
    165     }
    166   return FALSE;
    167 }
    168 
    169 
    170 /* Call-back for elf32_hppa_size_stubs.  */
    171 
    172 /* Create a new stub section, and arrange for it to be linked
    173    immediately before INPUT_SECTION.  */
    174 
    175 static asection *
    176 hppaelf_add_stub_section (const char *stub_sec_name, asection *input_section)
    177 {
    178   asection *stub_sec;
    179   flagword flags;
    180   asection *output_section;
    181   lang_output_section_statement_type *os;
    182   struct hook_stub_info info;
    183 
    184   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
    185 	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
    186   stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
    187 						 stub_sec_name, flags);
    188   if (stub_sec == NULL)
    189     goto err_ret;
    190 
    191   output_section = input_section->output_section;
    192   os = lang_output_section_get (output_section);
    193 
    194   info.input_section = input_section;
    195   lang_list_init (&info.add);
    196   lang_add_section (&info.add, stub_sec, NULL, os);
    197 
    198   if (info.add.head == NULL)
    199     goto err_ret;
    200 
    201   if (hook_in_stub (&info, &os->children.head))
    202     return stub_sec;
    203 
    204  err_ret:
    205   einfo ("%X%P: can not make stub section: %E\n");
    206   return NULL;
    207 }
    208 
    209 
    210 /* Another call-back for elf32_hppa_size_stubs.  */
    211 
    212 static void
    213 hppaelf_layout_sections_again (void)
    214 {
    215   /* If we have changed sizes of the stub sections, then we need
    216      to recalculate all the section offsets.  This may mean we need to
    217      add even more stubs.  */
    218   gld${EMULATION_NAME}_map_segments (TRUE);
    219   need_laying_out = -1;
    220 }
    221 
    222 
    223 static void
    224 build_section_lists (lang_statement_union_type *statement)
    225 {
    226   if (statement->header.type == lang_input_section_enum)
    227     {
    228       asection *i = statement->input_section.section;
    229 
    230       if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
    231 	  && (i->flags & SEC_EXCLUDE) == 0
    232 	  && i->output_section != NULL
    233 	  && i->output_section->owner == link_info.output_bfd)
    234 	{
    235 	  elf32_hppa_next_input_section (&link_info, i);
    236 	}
    237     }
    238 }
    239 
    240 
    241 /* For the PA we use this opportunity to size and build linker stubs.  */
    242 
    243 static void
    244 gld${EMULATION_NAME}_after_allocation (void)
    245 {
    246   int ret;
    247 
    248   /* bfd_elf_discard_info just plays with data and debugging sections,
    249      ie. doesn't affect code size, so we can delay resizing the
    250      sections.  It's likely we'll resize everything in the process of
    251      adding stubs.  */
    252   ret = bfd_elf_discard_info (link_info.output_bfd, &link_info);
    253   if (ret < 0)
    254     {
    255       einfo ("%X%P: .eh_frame/.stab edit: %E\n");
    256       return;
    257     }
    258   else if (ret > 0)
    259     need_laying_out = 1;
    260 
    261   /* If generating a relocatable output file, then we don't
    262      have to examine the relocs.  */
    263   if (stub_file != NULL && !bfd_link_relocatable (&link_info))
    264     {
    265       ret = elf32_hppa_setup_section_lists (link_info.output_bfd, &link_info);
    266       if (ret != 0)
    267 	{
    268 	  if (ret < 0)
    269 	    {
    270 	      einfo ("%X%P: can not size stub section: %E\n");
    271 	      return;
    272 	    }
    273 
    274 	  lang_for_each_statement (build_section_lists);
    275 
    276 	  /* Call into the BFD backend to do the real work.  */
    277 	  if (! elf32_hppa_size_stubs (link_info.output_bfd,
    278 				       stub_file->the_bfd,
    279 				       &link_info,
    280 				       multi_subspace,
    281 				       group_size,
    282 				       &hppaelf_add_stub_section,
    283 				       &hppaelf_layout_sections_again))
    284 	    {
    285 	      einfo ("%X%P: can not size stub section: %E\n");
    286 	      return;
    287 	    }
    288 	}
    289     }
    290 
    291   if (need_laying_out != -1)
    292     gld${EMULATION_NAME}_map_segments (need_laying_out);
    293 
    294   if (!bfd_link_relocatable (&link_info))
    295     {
    296       /* Set the global data pointer.  */
    297       if (! elf32_hppa_set_gp (link_info.output_bfd, &link_info))
    298 	{
    299 	  einfo ("%X%P: can not set gp\n");
    300 	  return;
    301 	}
    302 
    303       /* Now build the linker stubs.  */
    304       if (stub_file != NULL && stub_file->the_bfd->sections != NULL)
    305 	{
    306 	  if (! elf32_hppa_build_stubs (&link_info))
    307 	    einfo ("%X%P: can not build stubs: %E\n");
    308 	}
    309     }
    310 }
    311 
    312 
    313 /* Avoid processing the fake stub_file in vercheck, stat_needed and
    314    check_needed routines.  */
    315 
    316 static void (*real_func) (lang_input_statement_type *);
    317 
    318 static void hppa_for_each_input_file_wrapper (lang_input_statement_type *l)
    319 {
    320   if (l != stub_file)
    321     (*real_func) (l);
    322 }
    323 
    324 static void
    325 hppa_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
    326 {
    327   real_func = func;
    328   lang_for_each_input_file (&hppa_for_each_input_file_wrapper);
    329 }
    330 
    331 #define lang_for_each_input_file hppa_lang_for_each_input_file
    332 
    333 EOF
    334 
    335 # Define some shell vars to insert bits of code into the standard elf
    336 # parse_args and list_options functions.
    337 #
    338 PARSE_AND_LIST_PROLOGUE='
    339 #define OPTION_MULTI_SUBSPACE		301
    340 #define OPTION_STUBGROUP_SIZE		(OPTION_MULTI_SUBSPACE + 1)
    341 '
    342 
    343 PARSE_AND_LIST_LONGOPTS='
    344   { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE },
    345   { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
    346 '
    347 
    348 PARSE_AND_LIST_OPTIONS='
    349   fprintf (file, _("\
    350   --multi-subspace            Generate import and export stubs to support\n\
    351                                 multiple sub-space shared libraries\n"
    352 		   ));
    353   fprintf (file, _("\
    354   --stub-group-size=N         Maximum size of a group of input sections that\n\
    355                                 can be handled by one stub section.  A negative\n\
    356                                 value locates all stubs before their branches\n\
    357                                 (with a group size of -N), while a positive\n\
    358                                 value allows two groups of input sections, one\n\
    359                                 before, and one after each stub section.\n\
    360                                 Values of +/-1 indicate the linker should\n\
    361                                 choose suitable defaults.\n"
    362 		   ));
    363 '
    364 
    365 PARSE_AND_LIST_ARGS_CASES='
    366     case OPTION_MULTI_SUBSPACE:
    367       multi_subspace = 1;
    368       break;
    369 
    370     case OPTION_STUBGROUP_SIZE:
    371       {
    372 	const char *end;
    373         group_size = bfd_scan_vma (optarg, &end, 0);
    374         if (*end)
    375 	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
    376       }
    377       break;
    378 '
    379 
    380 # Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation
    381 #
    382 LDEMUL_AFTER_PARSE=hppaelf_after_parse
    383 LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
    384 LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=hppaelf_create_output_section_statements
    385