Home | History | Annotate | Line # | Download | only in emultempl
mipself.em revision 1.1
      1  1.1  christos # This shell script emits a C file. -*- C -*-
      2  1.1  christos #   Copyright 2004, 2006, 2007, 2008 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.1  christos static void
     37  1.1  christos mips_after_parse (void)
     38  1.1  christos {
     39  1.1  christos   /* .gnu.hash and the MIPS ABI require .dynsym to be sorted in different
     40  1.1  christos      ways.  .gnu.hash needs symbols to be grouped by hash code whereas the
     41  1.1  christos      MIPS ABI requires a mapping between the GOT and the symbol table.  */
     42  1.1  christos   if (link_info.emit_gnu_hash)
     43  1.1  christos     {
     44  1.1  christos       einfo ("%X%P: .gnu.hash is incompatible with the MIPS ABI\n");
     45  1.1  christos       link_info.emit_hash = TRUE;
     46  1.1  christos       link_info.emit_gnu_hash = FALSE;
     47  1.1  christos     }
     48  1.1  christos   after_parse_default ();
     49  1.1  christos }
     50  1.1  christos 
     51  1.1  christos struct hook_stub_info
     52  1.1  christos {
     53  1.1  christos   lang_statement_list_type add;
     54  1.1  christos   asection *input_section;
     55  1.1  christos };
     56  1.1  christos 
     57  1.1  christos /* Traverse the linker tree to find the spot where the stub goes.  */
     58  1.1  christos 
     59  1.1  christos static bfd_boolean
     60  1.1  christos hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
     61  1.1  christos {
     62  1.1  christos   lang_statement_union_type *l;
     63  1.1  christos   bfd_boolean ret;
     64  1.1  christos 
     65  1.1  christos   for (; (l = *lp) != NULL; lp = &l->header.next)
     66  1.1  christos     {
     67  1.1  christos       switch (l->header.type)
     68  1.1  christos 	{
     69  1.1  christos 	case lang_constructors_statement_enum:
     70  1.1  christos 	  ret = hook_in_stub (info, &constructor_list.head);
     71  1.1  christos 	  if (ret)
     72  1.1  christos 	    return ret;
     73  1.1  christos 	  break;
     74  1.1  christos 
     75  1.1  christos 	case lang_output_section_statement_enum:
     76  1.1  christos 	  ret = hook_in_stub (info,
     77  1.1  christos 			      &l->output_section_statement.children.head);
     78  1.1  christos 	  if (ret)
     79  1.1  christos 	    return ret;
     80  1.1  christos 	  break;
     81  1.1  christos 
     82  1.1  christos 	case lang_wild_statement_enum:
     83  1.1  christos 	  ret = hook_in_stub (info, &l->wild_statement.children.head);
     84  1.1  christos 	  if (ret)
     85  1.1  christos 	    return ret;
     86  1.1  christos 	  break;
     87  1.1  christos 
     88  1.1  christos 	case lang_group_statement_enum:
     89  1.1  christos 	  ret = hook_in_stub (info, &l->group_statement.children.head);
     90  1.1  christos 	  if (ret)
     91  1.1  christos 	    return ret;
     92  1.1  christos 	  break;
     93  1.1  christos 
     94  1.1  christos 	case lang_input_section_enum:
     95  1.1  christos 	  if (info->input_section == NULL
     96  1.1  christos 	      || l->input_section.section == info->input_section)
     97  1.1  christos 	    {
     98  1.1  christos 	      /* We've found our section.  Insert the stub immediately
     99  1.1  christos 		 before its associated input section.  */
    100  1.1  christos 	      *lp = info->add.head;
    101  1.1  christos 	      *(info->add.tail) = l;
    102  1.1  christos 	      return TRUE;
    103  1.1  christos 	    }
    104  1.1  christos 	  break;
    105  1.1  christos 
    106  1.1  christos 	case lang_data_statement_enum:
    107  1.1  christos 	case lang_reloc_statement_enum:
    108  1.1  christos 	case lang_object_symbols_statement_enum:
    109  1.1  christos 	case lang_output_statement_enum:
    110  1.1  christos 	case lang_target_statement_enum:
    111  1.1  christos 	case lang_input_statement_enum:
    112  1.1  christos 	case lang_assignment_statement_enum:
    113  1.1  christos 	case lang_padding_statement_enum:
    114  1.1  christos 	case lang_address_statement_enum:
    115  1.1  christos 	case lang_fill_statement_enum:
    116  1.1  christos 	  break;
    117  1.1  christos 
    118  1.1  christos 	default:
    119  1.1  christos 	  FAIL ();
    120  1.1  christos 	  break;
    121  1.1  christos 	}
    122  1.1  christos     }
    123  1.1  christos   return FALSE;
    124  1.1  christos }
    125  1.1  christos 
    126  1.1  christos /* Create a new stub section called STUB_SEC_NAME and arrange for it to
    127  1.1  christos    be linked in OUTPUT_SECTION.  The section should go at the beginning of
    128  1.1  christos    OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
    129  1.1  christos    before INPUT_SECTION.  */
    130  1.1  christos 
    131  1.1  christos static asection *
    132  1.1  christos mips_add_stub_section (const char *stub_sec_name, asection *input_section,
    133  1.1  christos 		       asection *output_section)
    134  1.1  christos {
    135  1.1  christos   asection *stub_sec;
    136  1.1  christos   flagword flags;
    137  1.1  christos   const char *secname;
    138  1.1  christos   lang_output_section_statement_type *os;
    139  1.1  christos   struct hook_stub_info info;
    140  1.1  christos 
    141  1.1  christos   /* PR 12845: If the input section has been garbage collected it will
    142  1.1  christos      not have its output section set to *ABS*.  */
    143  1.1  christos   if (bfd_is_abs_section (output_section))
    144  1.1  christos     return NULL;
    145  1.1  christos 
    146  1.1  christos   /* Create the stub file, if we haven't already.  */
    147  1.1  christos   if (stub_file == NULL)
    148  1.1  christos     {
    149  1.1  christos       stub_file = lang_add_input_file ("linker stubs",
    150  1.1  christos 				       lang_input_file_is_fake_enum,
    151  1.1  christos 				       NULL);
    152  1.1  christos       stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
    153  1.1  christos       if (stub_bfd == NULL
    154  1.1  christos 	  || !bfd_set_arch_mach (stub_bfd,
    155  1.1  christos 				 bfd_get_arch (link_info.output_bfd),
    156  1.1  christos 				 bfd_get_mach (link_info.output_bfd)))
    157  1.1  christos 	{
    158  1.1  christos 	  einfo ("%F%P: can not create BFD %E\n");
    159  1.1  christos 	  return NULL;
    160  1.1  christos 	}
    161  1.1  christos       stub_bfd->flags |= BFD_LINKER_CREATED;
    162  1.1  christos       stub_file->the_bfd = stub_bfd;
    163  1.1  christos       ldlang_add_file (stub_file);
    164  1.1  christos     }
    165  1.1  christos 
    166  1.1  christos   /* Create the section.  */
    167  1.1  christos   stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
    168  1.1  christos   if (stub_sec == NULL)
    169  1.1  christos     goto err_ret;
    170  1.1  christos 
    171  1.1  christos   /* Set the flags.  */
    172  1.1  christos   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
    173  1.1  christos 	   | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
    174  1.1  christos   if (!bfd_set_section_flags (stub_bfd, stub_sec, flags))
    175  1.1  christos     goto err_ret;
    176  1.1  christos 
    177  1.1  christos   /* Create an output section statement.  */
    178  1.1  christos   secname = bfd_get_section_name (output_section->owner, output_section);
    179  1.1  christos   os = lang_output_section_find (secname);
    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.1  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.1  christos   if (is_mips_elf (link_info.output_bfd))
    203  1.1  christos     _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
    204  1.1  christos }
    205  1.1  christos 
    206  1.1  christos /* This is called after we have merged the private data of the input bfds.  */
    207  1.1  christos 
    208  1.1  christos static void
    209  1.1  christos mips_before_allocation (void)
    210  1.1  christos {
    211  1.1  christos   flagword flags;
    212  1.1  christos 
    213  1.1  christos   flags = elf_elfheader (link_info.output_bfd)->e_flags;
    214  1.1  christos   if (!link_info.shared
    215  1.1  christos       && !link_info.nocopyreloc
    216  1.1  christos       && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
    217  1.1  christos     _bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
    218  1.1  christos 
    219  1.1  christos   gld${EMULATION_NAME}_before_allocation ();
    220  1.1  christos }
    221  1.1  christos 
    222  1.1  christos /* Avoid processing the fake stub_file in vercheck, stat_needed and
    223  1.1  christos    check_needed routines.  */
    224  1.1  christos 
    225  1.1  christos static void (*real_func) (lang_input_statement_type *);
    226  1.1  christos 
    227  1.1  christos static void mips_for_each_input_file_wrapper (lang_input_statement_type *l)
    228  1.1  christos {
    229  1.1  christos   if (l != stub_file)
    230  1.1  christos     (*real_func) (l);
    231  1.1  christos }
    232  1.1  christos 
    233  1.1  christos static void
    234  1.1  christos mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
    235  1.1  christos {
    236  1.1  christos   real_func = func;
    237  1.1  christos   lang_for_each_input_file (&mips_for_each_input_file_wrapper);
    238  1.1  christos }
    239  1.1  christos 
    240  1.1  christos #define lang_for_each_input_file mips_lang_for_each_input_file
    241  1.1  christos 
    242  1.1  christos EOF
    243  1.1  christos 
    244  1.1  christos LDEMUL_AFTER_PARSE=mips_after_parse
    245  1.1  christos LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
    246  1.1  christos LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
    247