Home | History | Annotate | Line # | Download | only in emultempl
mipself.em revision 1.6
      1  1.1  christos # This shell script emits a C file. -*- C -*-
      2  1.6  christos #   Copyright (C) 2004-2018 Free Software Foundation, Inc.
      3  1.1  christos #
      4  1.1  christos # This file is part of the GNU Binutils.
      5  1.1  christos #
      6  1.1  christos # This program is free software; you can redistribute it and/or modify
      7  1.1  christos # it under the terms of the GNU General Public License as published by
      8  1.1  christos # the Free Software Foundation; either version 3 of the License, or
      9  1.1  christos # (at your option) any later version.
     10  1.1  christos #
     11  1.1  christos # This program is distributed in the hope that it will be useful,
     12  1.1  christos # but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  christos # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  christos # GNU General Public License for more details.
     15  1.1  christos #
     16  1.1  christos # You should have received a copy of the GNU General Public License
     17  1.1  christos # along with this program; if not, write to the Free Software
     18  1.1  christos # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19  1.1  christos # MA 02110-1301, USA.
     20  1.1  christos 
     21  1.1  christos fragment <<EOF
     22  1.1  christos 
     23  1.1  christos #include "ldctor.h"
     24  1.1  christos #include "elf/mips.h"
     25  1.1  christos #include "elfxx-mips.h"
     26  1.1  christos 
     27  1.1  christos #define is_mips_elf(bfd)				\
     28  1.1  christos   (bfd_get_flavour (bfd) == bfd_target_elf_flavour	\
     29  1.1  christos    && elf_tdata (bfd) != NULL				\
     30  1.1  christos    && elf_object_id (bfd) == MIPS_ELF_DATA)
     31  1.1  christos 
     32  1.1  christos /* Fake input file for stubs.  */
     33  1.1  christos static lang_input_statement_type *stub_file;
     34  1.1  christos static bfd *stub_bfd;
     35  1.1  christos 
     36  1.3  christos static bfd_boolean insn32;
     37  1.6  christos static bfd_boolean ignore_branch_isa;
     38  1.3  christos 
     39  1.1  christos static void
     40  1.1  christos mips_after_parse (void)
     41  1.1  christos {
     42  1.1  christos   /* .gnu.hash and the MIPS ABI require .dynsym to be sorted in different
     43  1.1  christos      ways.  .gnu.hash needs symbols to be grouped by hash code whereas the
     44  1.1  christos      MIPS ABI requires a mapping between the GOT and the symbol table.  */
     45  1.1  christos   if (link_info.emit_gnu_hash)
     46  1.1  christos     {
     47  1.6  christos       einfo (_("%X%P: .gnu.hash is incompatible with the MIPS ABI\n"));
     48  1.1  christos       link_info.emit_hash = TRUE;
     49  1.1  christos       link_info.emit_gnu_hash = FALSE;
     50  1.1  christos     }
     51  1.3  christos   gld${EMULATION_NAME}_after_parse ();
     52  1.1  christos }
     53  1.1  christos 
     54  1.1  christos struct hook_stub_info
     55  1.1  christos {
     56  1.1  christos   lang_statement_list_type add;
     57  1.1  christos   asection *input_section;
     58  1.1  christos };
     59  1.1  christos 
     60  1.1  christos /* Traverse the linker tree to find the spot where the stub goes.  */
     61  1.1  christos 
     62  1.1  christos static bfd_boolean
     63  1.1  christos hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
     64  1.1  christos {
     65  1.1  christos   lang_statement_union_type *l;
     66  1.1  christos   bfd_boolean ret;
     67  1.1  christos 
     68  1.1  christos   for (; (l = *lp) != NULL; lp = &l->header.next)
     69  1.1  christos     {
     70  1.1  christos       switch (l->header.type)
     71  1.1  christos 	{
     72  1.1  christos 	case lang_constructors_statement_enum:
     73  1.1  christos 	  ret = hook_in_stub (info, &constructor_list.head);
     74  1.1  christos 	  if (ret)
     75  1.1  christos 	    return ret;
     76  1.1  christos 	  break;
     77  1.1  christos 
     78  1.1  christos 	case lang_output_section_statement_enum:
     79  1.1  christos 	  ret = hook_in_stub (info,
     80  1.1  christos 			      &l->output_section_statement.children.head);
     81  1.1  christos 	  if (ret)
     82  1.1  christos 	    return ret;
     83  1.1  christos 	  break;
     84  1.1  christos 
     85  1.1  christos 	case lang_wild_statement_enum:
     86  1.1  christos 	  ret = hook_in_stub (info, &l->wild_statement.children.head);
     87  1.1  christos 	  if (ret)
     88  1.1  christos 	    return ret;
     89  1.1  christos 	  break;
     90  1.1  christos 
     91  1.1  christos 	case lang_group_statement_enum:
     92  1.1  christos 	  ret = hook_in_stub (info, &l->group_statement.children.head);
     93  1.1  christos 	  if (ret)
     94  1.1  christos 	    return ret;
     95  1.1  christos 	  break;
     96  1.1  christos 
     97  1.1  christos 	case lang_input_section_enum:
     98  1.1  christos 	  if (info->input_section == NULL
     99  1.1  christos 	      || l->input_section.section == info->input_section)
    100  1.1  christos 	    {
    101  1.1  christos 	      /* We've found our section.  Insert the stub immediately
    102  1.1  christos 		 before its associated input section.  */
    103  1.1  christos 	      *lp = info->add.head;
    104  1.1  christos 	      *(info->add.tail) = l;
    105  1.1  christos 	      return TRUE;
    106  1.1  christos 	    }
    107  1.1  christos 	  break;
    108  1.1  christos 
    109  1.1  christos 	case lang_data_statement_enum:
    110  1.1  christos 	case lang_reloc_statement_enum:
    111  1.1  christos 	case lang_object_symbols_statement_enum:
    112  1.1  christos 	case lang_output_statement_enum:
    113  1.1  christos 	case lang_target_statement_enum:
    114  1.1  christos 	case lang_input_statement_enum:
    115  1.1  christos 	case lang_assignment_statement_enum:
    116  1.1  christos 	case lang_padding_statement_enum:
    117  1.1  christos 	case lang_address_statement_enum:
    118  1.1  christos 	case lang_fill_statement_enum:
    119  1.1  christos 	  break;
    120  1.1  christos 
    121  1.1  christos 	default:
    122  1.1  christos 	  FAIL ();
    123  1.1  christos 	  break;
    124  1.1  christos 	}
    125  1.1  christos     }
    126  1.1  christos   return FALSE;
    127  1.1  christos }
    128  1.1  christos 
    129  1.1  christos /* Create a new stub section called STUB_SEC_NAME and arrange for it to
    130  1.1  christos    be linked in OUTPUT_SECTION.  The section should go at the beginning of
    131  1.1  christos    OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
    132  1.1  christos    before INPUT_SECTION.  */
    133  1.1  christos 
    134  1.1  christos static asection *
    135  1.1  christos mips_add_stub_section (const char *stub_sec_name, asection *input_section,
    136  1.1  christos 		       asection *output_section)
    137  1.1  christos {
    138  1.1  christos   asection *stub_sec;
    139  1.1  christos   flagword flags;
    140  1.1  christos   lang_output_section_statement_type *os;
    141  1.1  christos   struct hook_stub_info info;
    142  1.1  christos 
    143  1.1  christos   /* PR 12845: If the input section has been garbage collected it will
    144  1.1  christos      not have its output section set to *ABS*.  */
    145  1.1  christos   if (bfd_is_abs_section (output_section))
    146  1.1  christos     return NULL;
    147  1.1  christos 
    148  1.1  christos   /* Create the stub file, if we haven't already.  */
    149  1.1  christos   if (stub_file == NULL)
    150  1.1  christos     {
    151  1.1  christos       stub_file = lang_add_input_file ("linker stubs",
    152  1.1  christos 				       lang_input_file_is_fake_enum,
    153  1.1  christos 				       NULL);
    154  1.1  christos       stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
    155  1.1  christos       if (stub_bfd == NULL
    156  1.1  christos 	  || !bfd_set_arch_mach (stub_bfd,
    157  1.1  christos 				 bfd_get_arch (link_info.output_bfd),
    158  1.1  christos 				 bfd_get_mach (link_info.output_bfd)))
    159  1.1  christos 	{
    160  1.6  christos 	  einfo (_("%F%P: can not create BFD: %E\n"));
    161  1.1  christos 	  return NULL;
    162  1.1  christos 	}
    163  1.1  christos       stub_bfd->flags |= BFD_LINKER_CREATED;
    164  1.1  christos       stub_file->the_bfd = stub_bfd;
    165  1.1  christos       ldlang_add_file (stub_file);
    166  1.1  christos     }
    167  1.1  christos 
    168  1.1  christos   /* Create the section.  */
    169  1.1  christos   stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
    170  1.1  christos   if (stub_sec == NULL)
    171  1.1  christos     goto err_ret;
    172  1.1  christos 
    173  1.1  christos   /* Set the flags.  */
    174  1.1  christos   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
    175  1.1  christos 	   | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
    176  1.1  christos   if (!bfd_set_section_flags (stub_bfd, stub_sec, flags))
    177  1.1  christos     goto err_ret;
    178  1.1  christos 
    179  1.3  christos   os = lang_output_section_get (output_section);
    180  1.1  christos 
    181  1.1  christos   /* Initialize a statement list that contains only the new statement.  */
    182  1.1  christos   lang_list_init (&info.add);
    183  1.1  christos   lang_add_section (&info.add, stub_sec, NULL, os);
    184  1.1  christos   if (info.add.head == NULL)
    185  1.1  christos     goto err_ret;
    186  1.1  christos 
    187  1.1  christos   /* Insert the new statement in the appropriate place.  */
    188  1.1  christos   info.input_section = input_section;
    189  1.1  christos   if (hook_in_stub (&info, &os->children.head))
    190  1.1  christos     return stub_sec;
    191  1.1  christos 
    192  1.1  christos  err_ret:
    193  1.6  christos   einfo (_("%X%P: can not make stub section: %E\n"));
    194  1.1  christos   return NULL;
    195  1.1  christos }
    196  1.1  christos 
    197  1.1  christos /* This is called before the input files are opened.  */
    198  1.1  christos 
    199  1.1  christos static void
    200  1.1  christos mips_create_output_section_statements (void)
    201  1.1  christos {
    202  1.3  christos   struct elf_link_hash_table *htab;
    203  1.3  christos 
    204  1.3  christos   htab = elf_hash_table (&link_info);
    205  1.3  christos   if (is_elf_hash_table (htab) && is_mips_elf (link_info.output_bfd))
    206  1.6  christos     _bfd_mips_elf_linker_flags (&link_info, insn32, ignore_branch_isa);
    207  1.3  christos 
    208  1.1  christos   if (is_mips_elf (link_info.output_bfd))
    209  1.1  christos     _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
    210  1.1  christos }
    211  1.1  christos 
    212  1.1  christos /* This is called after we have merged the private data of the input bfds.  */
    213  1.1  christos 
    214  1.1  christos static void
    215  1.1  christos mips_before_allocation (void)
    216  1.1  christos {
    217  1.6  christos   if (is_mips_elf (link_info.output_bfd))
    218  1.6  christos     {
    219  1.6  christos       flagword flags;
    220  1.1  christos 
    221  1.6  christos       flags = elf_elfheader (link_info.output_bfd)->e_flags;
    222  1.6  christos       if (!bfd_link_pic (&link_info)
    223  1.6  christos 	  && !link_info.nocopyreloc
    224  1.6  christos 	  && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
    225  1.6  christos 	_bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
    226  1.6  christos     }
    227  1.1  christos 
    228  1.1  christos   gld${EMULATION_NAME}_before_allocation ();
    229  1.1  christos }
    230  1.1  christos 
    231  1.1  christos /* Avoid processing the fake stub_file in vercheck, stat_needed and
    232  1.1  christos    check_needed routines.  */
    233  1.1  christos 
    234  1.1  christos static void (*real_func) (lang_input_statement_type *);
    235  1.1  christos 
    236  1.1  christos static void mips_for_each_input_file_wrapper (lang_input_statement_type *l)
    237  1.1  christos {
    238  1.1  christos   if (l != stub_file)
    239  1.1  christos     (*real_func) (l);
    240  1.1  christos }
    241  1.1  christos 
    242  1.1  christos static void
    243  1.1  christos mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
    244  1.1  christos {
    245  1.1  christos   real_func = func;
    246  1.1  christos   lang_for_each_input_file (&mips_for_each_input_file_wrapper);
    247  1.1  christos }
    248  1.1  christos 
    249  1.1  christos #define lang_for_each_input_file mips_lang_for_each_input_file
    250  1.1  christos 
    251  1.1  christos EOF
    252  1.1  christos 
    253  1.3  christos # Define some shell vars to insert bits of code into the standard elf
    254  1.3  christos # parse_args and list_options functions.
    255  1.3  christos #
    256  1.3  christos PARSE_AND_LIST_PROLOGUE='
    257  1.5  christos enum
    258  1.5  christos   {
    259  1.5  christos     OPTION_INSN32 = 301,
    260  1.6  christos     OPTION_NO_INSN32,
    261  1.6  christos     OPTION_IGNORE_BRANCH_ISA,
    262  1.6  christos     OPTION_NO_IGNORE_BRANCH_ISA
    263  1.5  christos   };
    264  1.3  christos '
    265  1.3  christos 
    266  1.3  christos PARSE_AND_LIST_LONGOPTS='
    267  1.3  christos   { "insn32", no_argument, NULL, OPTION_INSN32 },
    268  1.3  christos   { "no-insn32", no_argument, NULL, OPTION_NO_INSN32 },
    269  1.6  christos   { "ignore-branch-isa", no_argument, NULL, OPTION_IGNORE_BRANCH_ISA },
    270  1.6  christos   { "no-ignore-branch-isa", no_argument, NULL, OPTION_NO_IGNORE_BRANCH_ISA },
    271  1.3  christos '
    272  1.3  christos 
    273  1.3  christos PARSE_AND_LIST_OPTIONS='
    274  1.3  christos   fprintf (file, _("\
    275  1.3  christos   --insn32                    Only generate 32-bit microMIPS instructions\n"
    276  1.3  christos 		   ));
    277  1.3  christos   fprintf (file, _("\
    278  1.3  christos   --no-insn32                 Generate all microMIPS instructions\n"
    279  1.3  christos 		   ));
    280  1.6  christos   fprintf (file, _("\
    281  1.6  christos   --ignore-branch-isa         Accept invalid branch relocations requiring\n\
    282  1.6  christos                               an ISA mode switch\n"
    283  1.6  christos 		   ));
    284  1.6  christos   fprintf (file, _("\
    285  1.6  christos   --no-ignore-branch-isa      Reject invalid branch relocations requiring\n\
    286  1.6  christos                               an ISA mode switch\n"
    287  1.6  christos 		   ));
    288  1.3  christos '
    289  1.3  christos 
    290  1.3  christos PARSE_AND_LIST_ARGS_CASES='
    291  1.3  christos     case OPTION_INSN32:
    292  1.3  christos       insn32 = TRUE;
    293  1.3  christos       break;
    294  1.3  christos 
    295  1.3  christos     case OPTION_NO_INSN32:
    296  1.3  christos       insn32 = FALSE;
    297  1.3  christos       break;
    298  1.6  christos 
    299  1.6  christos     case OPTION_IGNORE_BRANCH_ISA:
    300  1.6  christos       ignore_branch_isa = TRUE;
    301  1.6  christos       break;
    302  1.6  christos 
    303  1.6  christos     case OPTION_NO_IGNORE_BRANCH_ISA:
    304  1.6  christos       ignore_branch_isa = FALSE;
    305  1.6  christos       break;
    306  1.3  christos '
    307  1.3  christos 
    308  1.1  christos LDEMUL_AFTER_PARSE=mips_after_parse
    309  1.1  christos LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
    310  1.1  christos LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
    311