Home | History | Annotate | Line # | Download | only in emultempl
mipself.em revision 1.3
      1  1.1  christos # This shell script emits a C file. -*- C -*-
      2  1.3  christos #   Copyright (C) 2004-2015 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.3  christos 
     38  1.1  christos static void
     39  1.1  christos mips_after_parse (void)
     40  1.1  christos {
     41  1.1  christos   /* .gnu.hash and the MIPS ABI require .dynsym to be sorted in different
     42  1.1  christos      ways.  .gnu.hash needs symbols to be grouped by hash code whereas the
     43  1.1  christos      MIPS ABI requires a mapping between the GOT and the symbol table.  */
     44  1.1  christos   if (link_info.emit_gnu_hash)
     45  1.1  christos     {
     46  1.1  christos       einfo ("%X%P: .gnu.hash is incompatible with the MIPS ABI\n");
     47  1.1  christos       link_info.emit_hash = TRUE;
     48  1.1  christos       link_info.emit_gnu_hash = FALSE;
     49  1.1  christos     }
     50  1.3  christos   gld${EMULATION_NAME}_after_parse ();
     51  1.1  christos }
     52  1.1  christos 
     53  1.1  christos struct hook_stub_info
     54  1.1  christos {
     55  1.1  christos   lang_statement_list_type add;
     56  1.1  christos   asection *input_section;
     57  1.1  christos };
     58  1.1  christos 
     59  1.1  christos /* Traverse the linker tree to find the spot where the stub goes.  */
     60  1.1  christos 
     61  1.1  christos static bfd_boolean
     62  1.1  christos hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
     63  1.1  christos {
     64  1.1  christos   lang_statement_union_type *l;
     65  1.1  christos   bfd_boolean ret;
     66  1.1  christos 
     67  1.1  christos   for (; (l = *lp) != NULL; lp = &l->header.next)
     68  1.1  christos     {
     69  1.1  christos       switch (l->header.type)
     70  1.1  christos 	{
     71  1.1  christos 	case lang_constructors_statement_enum:
     72  1.1  christos 	  ret = hook_in_stub (info, &constructor_list.head);
     73  1.1  christos 	  if (ret)
     74  1.1  christos 	    return ret;
     75  1.1  christos 	  break;
     76  1.1  christos 
     77  1.1  christos 	case lang_output_section_statement_enum:
     78  1.1  christos 	  ret = hook_in_stub (info,
     79  1.1  christos 			      &l->output_section_statement.children.head);
     80  1.1  christos 	  if (ret)
     81  1.1  christos 	    return ret;
     82  1.1  christos 	  break;
     83  1.1  christos 
     84  1.1  christos 	case lang_wild_statement_enum:
     85  1.1  christos 	  ret = hook_in_stub (info, &l->wild_statement.children.head);
     86  1.1  christos 	  if (ret)
     87  1.1  christos 	    return ret;
     88  1.1  christos 	  break;
     89  1.1  christos 
     90  1.1  christos 	case lang_group_statement_enum:
     91  1.1  christos 	  ret = hook_in_stub (info, &l->group_statement.children.head);
     92  1.1  christos 	  if (ret)
     93  1.1  christos 	    return ret;
     94  1.1  christos 	  break;
     95  1.1  christos 
     96  1.1  christos 	case lang_input_section_enum:
     97  1.1  christos 	  if (info->input_section == NULL
     98  1.1  christos 	      || l->input_section.section == info->input_section)
     99  1.1  christos 	    {
    100  1.1  christos 	      /* We've found our section.  Insert the stub immediately
    101  1.1  christos 		 before its associated input section.  */
    102  1.1  christos 	      *lp = info->add.head;
    103  1.1  christos 	      *(info->add.tail) = l;
    104  1.1  christos 	      return TRUE;
    105  1.1  christos 	    }
    106  1.1  christos 	  break;
    107  1.1  christos 
    108  1.1  christos 	case lang_data_statement_enum:
    109  1.1  christos 	case lang_reloc_statement_enum:
    110  1.1  christos 	case lang_object_symbols_statement_enum:
    111  1.1  christos 	case lang_output_statement_enum:
    112  1.1  christos 	case lang_target_statement_enum:
    113  1.1  christos 	case lang_input_statement_enum:
    114  1.1  christos 	case lang_assignment_statement_enum:
    115  1.1  christos 	case lang_padding_statement_enum:
    116  1.1  christos 	case lang_address_statement_enum:
    117  1.1  christos 	case lang_fill_statement_enum:
    118  1.1  christos 	  break;
    119  1.1  christos 
    120  1.1  christos 	default:
    121  1.1  christos 	  FAIL ();
    122  1.1  christos 	  break;
    123  1.1  christos 	}
    124  1.1  christos     }
    125  1.1  christos   return FALSE;
    126  1.1  christos }
    127  1.1  christos 
    128  1.1  christos /* Create a new stub section called STUB_SEC_NAME and arrange for it to
    129  1.1  christos    be linked in OUTPUT_SECTION.  The section should go at the beginning of
    130  1.1  christos    OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
    131  1.1  christos    before INPUT_SECTION.  */
    132  1.1  christos 
    133  1.1  christos static asection *
    134  1.1  christos mips_add_stub_section (const char *stub_sec_name, asection *input_section,
    135  1.1  christos 		       asection *output_section)
    136  1.1  christos {
    137  1.1  christos   asection *stub_sec;
    138  1.1  christos   flagword flags;
    139  1.1  christos   lang_output_section_statement_type *os;
    140  1.1  christos   struct hook_stub_info info;
    141  1.1  christos 
    142  1.1  christos   /* PR 12845: If the input section has been garbage collected it will
    143  1.1  christos      not have its output section set to *ABS*.  */
    144  1.1  christos   if (bfd_is_abs_section (output_section))
    145  1.1  christos     return NULL;
    146  1.1  christos 
    147  1.1  christos   /* Create the stub file, if we haven't already.  */
    148  1.1  christos   if (stub_file == NULL)
    149  1.1  christos     {
    150  1.1  christos       stub_file = lang_add_input_file ("linker stubs",
    151  1.1  christos 				       lang_input_file_is_fake_enum,
    152  1.1  christos 				       NULL);
    153  1.1  christos       stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
    154  1.1  christos       if (stub_bfd == NULL
    155  1.1  christos 	  || !bfd_set_arch_mach (stub_bfd,
    156  1.1  christos 				 bfd_get_arch (link_info.output_bfd),
    157  1.1  christos 				 bfd_get_mach (link_info.output_bfd)))
    158  1.1  christos 	{
    159  1.1  christos 	  einfo ("%F%P: can not create BFD %E\n");
    160  1.1  christos 	  return NULL;
    161  1.1  christos 	}
    162  1.1  christos       stub_bfd->flags |= BFD_LINKER_CREATED;
    163  1.1  christos       stub_file->the_bfd = stub_bfd;
    164  1.1  christos       ldlang_add_file (stub_file);
    165  1.1  christos     }
    166  1.1  christos 
    167  1.1  christos   /* Create the section.  */
    168  1.1  christos   stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
    169  1.1  christos   if (stub_sec == NULL)
    170  1.1  christos     goto err_ret;
    171  1.1  christos 
    172  1.1  christos   /* Set the flags.  */
    173  1.1  christos   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
    174  1.1  christos 	   | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
    175  1.1  christos   if (!bfd_set_section_flags (stub_bfd, stub_sec, flags))
    176  1.1  christos     goto err_ret;
    177  1.1  christos 
    178  1.3  christos   os = lang_output_section_get (output_section);
    179  1.1  christos 
    180  1.1  christos   /* Initialize a statement list that contains only the new statement.  */
    181  1.1  christos   lang_list_init (&info.add);
    182  1.1  christos   lang_add_section (&info.add, stub_sec, NULL, os);
    183  1.1  christos   if (info.add.head == NULL)
    184  1.1  christos     goto err_ret;
    185  1.1  christos 
    186  1.1  christos   /* Insert the new statement in the appropriate place.  */
    187  1.1  christos   info.input_section = input_section;
    188  1.1  christos   if (hook_in_stub (&info, &os->children.head))
    189  1.1  christos     return stub_sec;
    190  1.1  christos 
    191  1.1  christos  err_ret:
    192  1.1  christos   einfo ("%X%P: can not make stub section: %E\n");
    193  1.1  christos   return NULL;
    194  1.1  christos }
    195  1.1  christos 
    196  1.1  christos /* This is called before the input files are opened.  */
    197  1.1  christos 
    198  1.1  christos static void
    199  1.1  christos mips_create_output_section_statements (void)
    200  1.1  christos {
    201  1.3  christos   struct elf_link_hash_table *htab;
    202  1.3  christos 
    203  1.3  christos   htab = elf_hash_table (&link_info);
    204  1.3  christos   if (is_elf_hash_table (htab) && is_mips_elf (link_info.output_bfd))
    205  1.3  christos     _bfd_mips_elf_insn32 (&link_info, insn32);
    206  1.3  christos 
    207  1.1  christos   if (is_mips_elf (link_info.output_bfd))
    208  1.1  christos     _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
    209  1.1  christos }
    210  1.1  christos 
    211  1.1  christos /* This is called after we have merged the private data of the input bfds.  */
    212  1.1  christos 
    213  1.1  christos static void
    214  1.1  christos mips_before_allocation (void)
    215  1.1  christos {
    216  1.1  christos   flagword flags;
    217  1.1  christos 
    218  1.1  christos   flags = elf_elfheader (link_info.output_bfd)->e_flags;
    219  1.3  christos   if (!bfd_link_pic (&link_info)
    220  1.1  christos       && !link_info.nocopyreloc
    221  1.1  christos       && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
    222  1.1  christos     _bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
    223  1.1  christos 
    224  1.1  christos   gld${EMULATION_NAME}_before_allocation ();
    225  1.1  christos }
    226  1.1  christos 
    227  1.1  christos /* Avoid processing the fake stub_file in vercheck, stat_needed and
    228  1.1  christos    check_needed routines.  */
    229  1.1  christos 
    230  1.1  christos static void (*real_func) (lang_input_statement_type *);
    231  1.1  christos 
    232  1.1  christos static void mips_for_each_input_file_wrapper (lang_input_statement_type *l)
    233  1.1  christos {
    234  1.1  christos   if (l != stub_file)
    235  1.1  christos     (*real_func) (l);
    236  1.1  christos }
    237  1.1  christos 
    238  1.1  christos static void
    239  1.1  christos mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
    240  1.1  christos {
    241  1.1  christos   real_func = func;
    242  1.1  christos   lang_for_each_input_file (&mips_for_each_input_file_wrapper);
    243  1.1  christos }
    244  1.1  christos 
    245  1.1  christos #define lang_for_each_input_file mips_lang_for_each_input_file
    246  1.1  christos 
    247  1.1  christos EOF
    248  1.1  christos 
    249  1.3  christos # Define some shell vars to insert bits of code into the standard elf
    250  1.3  christos # parse_args and list_options functions.
    251  1.3  christos #
    252  1.3  christos PARSE_AND_LIST_PROLOGUE='
    253  1.3  christos #define OPTION_INSN32			301
    254  1.3  christos #define OPTION_NO_INSN32		(OPTION_INSN32 + 1)
    255  1.3  christos '
    256  1.3  christos 
    257  1.3  christos PARSE_AND_LIST_LONGOPTS='
    258  1.3  christos   { "insn32", no_argument, NULL, OPTION_INSN32 },
    259  1.3  christos   { "no-insn32", no_argument, NULL, OPTION_NO_INSN32 },
    260  1.3  christos '
    261  1.3  christos 
    262  1.3  christos PARSE_AND_LIST_OPTIONS='
    263  1.3  christos   fprintf (file, _("\
    264  1.3  christos   --insn32                    Only generate 32-bit microMIPS instructions\n"
    265  1.3  christos 		   ));
    266  1.3  christos   fprintf (file, _("\
    267  1.3  christos   --no-insn32                 Generate all microMIPS instructions\n"
    268  1.3  christos 		   ));
    269  1.3  christos '
    270  1.3  christos 
    271  1.3  christos PARSE_AND_LIST_ARGS_CASES='
    272  1.3  christos     case OPTION_INSN32:
    273  1.3  christos       insn32 = TRUE;
    274  1.3  christos       break;
    275  1.3  christos 
    276  1.3  christos     case OPTION_NO_INSN32:
    277  1.3  christos       insn32 = FALSE;
    278  1.3  christos       break;
    279  1.3  christos '
    280  1.3  christos 
    281  1.1  christos LDEMUL_AFTER_PARSE=mips_after_parse
    282  1.1  christos LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
    283  1.1  christos LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
    284