Home | History | Annotate | Line # | Download | only in bfd
elf32-xstormy16.c revision 1.6
      1  1.1  christos /* Xstormy16-specific support for 32-bit ELF.
      2  1.6  christos    Copyright (C) 2000-2018 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      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 #include "sysdep.h"
     22  1.1  christos #include "bfd.h"
     23  1.1  christos #include "libbfd.h"
     24  1.1  christos #include "elf-bfd.h"
     25  1.1  christos #include "elf/xstormy16.h"
     26  1.1  christos #include "libiberty.h"
     27  1.1  christos 
     28  1.1  christos /* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement.  */
     29  1.1  christos 
     30  1.1  christos static bfd_reloc_status_type
     31  1.1  christos xstormy16_elf_24_reloc (bfd *abfd,
     32  1.1  christos 			arelent *reloc_entry,
     33  1.1  christos 			asymbol *symbol,
     34  1.1  christos 			void * data,
     35  1.1  christos 			asection *input_section,
     36  1.1  christos 			bfd *output_bfd,
     37  1.1  christos 			char **error_message ATTRIBUTE_UNUSED)
     38  1.1  christos {
     39  1.1  christos   bfd_vma relocation, x;
     40  1.1  christos 
     41  1.1  christos   if (output_bfd != NULL)
     42  1.1  christos     {
     43  1.1  christos       reloc_entry->address += input_section->output_offset;
     44  1.1  christos       return bfd_reloc_ok;
     45  1.1  christos     }
     46  1.1  christos 
     47  1.1  christos   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     48  1.1  christos     return bfd_reloc_outofrange;
     49  1.1  christos 
     50  1.1  christos   if (bfd_is_com_section (symbol->section))
     51  1.1  christos     relocation = 0;
     52  1.1  christos   else
     53  1.1  christos     relocation = symbol->value;
     54  1.1  christos 
     55  1.1  christos   relocation += symbol->section->output_section->vma;
     56  1.1  christos   relocation += symbol->section->output_offset;
     57  1.1  christos   relocation += reloc_entry->addend;
     58  1.1  christos 
     59  1.1  christos   x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
     60  1.1  christos   x &= 0x0000ff00;
     61  1.1  christos   x |= relocation & 0xff;
     62  1.1  christos   x |= (relocation << 8) & 0xffff0000;
     63  1.1  christos   bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
     64  1.1  christos 
     65  1.1  christos   if (relocation & ~ (bfd_vma) 0xffffff)
     66  1.1  christos     return bfd_reloc_overflow;
     67  1.1  christos 
     68  1.1  christos   return bfd_reloc_ok;
     69  1.1  christos }
     70  1.1  christos 
     71  1.1  christos static reloc_howto_type xstormy16_elf_howto_table [] =
     72  1.1  christos {
     73  1.1  christos   /* This reloc does nothing.  */
     74  1.1  christos   HOWTO (R_XSTORMY16_NONE,	/* type */
     75  1.1  christos 	 0,			/* rightshift */
     76  1.3  christos 	 3,			/* size (0 = byte, 1 = short, 2 = long) */
     77  1.3  christos 	 0,			/* bitsize */
     78  1.1  christos 	 FALSE,			/* pc_relative */
     79  1.1  christos 	 0,			/* bitpos */
     80  1.3  christos 	 complain_overflow_dont, /* complain_on_overflow */
     81  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
     82  1.1  christos 	 "R_XSTORMY16_NONE",	/* name */
     83  1.1  christos 	 FALSE,			/* partial_inplace */
     84  1.1  christos 	 0,			/* src_mask */
     85  1.1  christos 	 0,			/* dst_mask */
     86  1.1  christos 	 FALSE),		/* pcrel_offset */
     87  1.1  christos 
     88  1.1  christos   /* A 32 bit absolute relocation.  */
     89  1.1  christos   HOWTO (R_XSTORMY16_32,	/* type */
     90  1.1  christos 	 0,			/* rightshift */
     91  1.1  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
     92  1.1  christos 	 32,			/* bitsize */
     93  1.1  christos 	 FALSE,			/* pc_relative */
     94  1.1  christos 	 0,			/* bitpos */
     95  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
     96  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
     97  1.1  christos 	 "R_XSTORMY16_32",	/* name */
     98  1.1  christos 	 FALSE,			/* partial_inplace */
     99  1.1  christos 	 0,			/* src_mask */
    100  1.1  christos 	 0xffffffff,		/* dst_mask */
    101  1.1  christos 	 FALSE),		/* pcrel_offset */
    102  1.1  christos 
    103  1.1  christos   /* A 16 bit absolute relocation.  */
    104  1.1  christos   HOWTO (R_XSTORMY16_16,	/* type */
    105  1.1  christos 	 0,			/* rightshift */
    106  1.1  christos 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    107  1.1  christos 	 16,			/* bitsize */
    108  1.1  christos 	 FALSE,			/* pc_relative */
    109  1.1  christos 	 0,			/* bitpos */
    110  1.1  christos 	 complain_overflow_bitfield, /* complain_on_overflow */
    111  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    112  1.1  christos 	 "R_XSTORMY16_16",	/* name */
    113  1.1  christos 	 FALSE,			/* partial_inplace */
    114  1.1  christos 	 0,			/* src_mask */
    115  1.1  christos 	 0xffff,		/* dst_mask */
    116  1.1  christos 	 FALSE),		/* pcrel_offset */
    117  1.1  christos 
    118  1.1  christos   /* An 8 bit absolute relocation.  */
    119  1.1  christos   HOWTO (R_XSTORMY16_8,		/* type */
    120  1.1  christos 	 0,			/* rightshift */
    121  1.1  christos 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    122  1.1  christos 	 8,			/* bitsize */
    123  1.1  christos 	 FALSE,			/* pc_relative */
    124  1.1  christos 	 0,			/* bitpos */
    125  1.1  christos 	 complain_overflow_unsigned, /* complain_on_overflow */
    126  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    127  1.1  christos 	 "R_XSTORMY16_8",	/* name */
    128  1.1  christos 	 FALSE,			/* partial_inplace */
    129  1.1  christos 	 0,			/* src_mask */
    130  1.1  christos 	 0xff,			/* dst_mask */
    131  1.1  christos 	 FALSE),		/* pcrel_offset */
    132  1.1  christos 
    133  1.1  christos   /* A 32 bit pc-relative relocation.  */
    134  1.1  christos   HOWTO (R_XSTORMY16_PC32,	/* type */
    135  1.1  christos 	 0,			/* rightshift */
    136  1.1  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    137  1.1  christos 	 32,			/* bitsize */
    138  1.1  christos 	 TRUE,			/* pc_relative */
    139  1.1  christos 	 0,			/* bitpos */
    140  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    141  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    142  1.1  christos 	 "R_XSTORMY16_PC32",	/* name */
    143  1.1  christos 	 FALSE,			/* partial_inplace */
    144  1.1  christos 	 0,			/* src_mask */
    145  1.1  christos 	 0xffffffff,		/* dst_mask */
    146  1.1  christos 	 TRUE),			/* pcrel_offset */
    147  1.1  christos 
    148  1.1  christos   /* A 16 bit pc-relative relocation.  */
    149  1.1  christos   HOWTO (R_XSTORMY16_PC16,	/* type */
    150  1.1  christos 	 0,			/* rightshift */
    151  1.1  christos 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    152  1.1  christos 	 16,			/* bitsize */
    153  1.1  christos 	 TRUE,			/* pc_relative */
    154  1.1  christos 	 0,			/* bitpos */
    155  1.1  christos 	 complain_overflow_signed, /* complain_on_overflow */
    156  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    157  1.1  christos 	 "R_XSTORMY16_PC16",	/* name */
    158  1.1  christos 	 FALSE,			/* partial_inplace */
    159  1.1  christos 	 0,			/* src_mask */
    160  1.1  christos 	 0xffffffff,		/* dst_mask */
    161  1.1  christos 	 TRUE),			/* pcrel_offset */
    162  1.1  christos 
    163  1.1  christos   /* An 8 bit pc-relative relocation.  */
    164  1.1  christos   HOWTO (R_XSTORMY16_PC8,	/* type */
    165  1.1  christos 	 0,			/* rightshift */
    166  1.1  christos 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    167  1.1  christos 	 8,			/* bitsize */
    168  1.1  christos 	 TRUE,			/* pc_relative */
    169  1.1  christos 	 0,			/* bitpos */
    170  1.1  christos 	 complain_overflow_signed, /* complain_on_overflow */
    171  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    172  1.1  christos 	 "R_XSTORMY16_PC8",	/* name */
    173  1.1  christos 	 FALSE,			/* partial_inplace */
    174  1.1  christos 	 0,			/* src_mask */
    175  1.1  christos 	 0xffffffff,		/* dst_mask */
    176  1.1  christos 	 TRUE),			/* pcrel_offset */
    177  1.1  christos 
    178  1.1  christos   /* A 12-bit pc-relative relocation suitable for the branch instructions.  */
    179  1.1  christos   HOWTO (R_XSTORMY16_REL_12,	/* type */
    180  1.1  christos 	 1,			/* rightshift */
    181  1.1  christos 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    182  1.1  christos 	 11,			/* bitsize */
    183  1.1  christos 	 TRUE,			/* pc_relative */
    184  1.1  christos 	 1,			/* bitpos */
    185  1.1  christos 	 complain_overflow_signed, /* complain_on_overflow */
    186  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    187  1.1  christos 	 "R_XSTORMY16_REL_12",	/* name */
    188  1.1  christos 	 FALSE,			/* partial_inplace */
    189  1.1  christos 	 0,			/* src_mask */
    190  1.1  christos 	 0x0ffe,		/* dst_mask */
    191  1.1  christos 	 TRUE),			/* pcrel_offset */
    192  1.1  christos 
    193  1.1  christos   /* A 24-bit absolute relocation suitable for the jump instructions.  */
    194  1.1  christos   HOWTO (R_XSTORMY16_24,	/* type */
    195  1.1  christos 	 0,			/* rightshift */
    196  1.1  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    197  1.1  christos 	 24,			/* bitsize */
    198  1.1  christos 	 FALSE,			/* pc_relative */
    199  1.1  christos 	 0,			/* bitpos */
    200  1.1  christos 	 complain_overflow_unsigned, /* complain_on_overflow */
    201  1.1  christos 	 xstormy16_elf_24_reloc,	/* special_function */
    202  1.1  christos 	 "R_XSTORMY16_24",	/* name */
    203  1.1  christos 	 TRUE,			/* partial_inplace */
    204  1.1  christos 	 0,			/* src_mask */
    205  1.1  christos 	 0xffff00ff,		/* dst_mask */
    206  1.1  christos 	 TRUE),			/* pcrel_offset */
    207  1.1  christos 
    208  1.1  christos   /* A 16 bit absolute relocation to a function pointer.  */
    209  1.1  christos   HOWTO (R_XSTORMY16_FPTR16,	/* type */
    210  1.1  christos 	 0,			/* rightshift */
    211  1.1  christos 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    212  1.1  christos 	 16,			/* bitsize */
    213  1.1  christos 	 FALSE,			/* pc_relative */
    214  1.1  christos 	 0,			/* bitpos */
    215  1.1  christos 	 complain_overflow_bitfield, /* complain_on_overflow */
    216  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    217  1.1  christos 	 "R_XSTORMY16_FPTR16",	/* name */
    218  1.1  christos 	 FALSE,			/* partial_inplace */
    219  1.1  christos 	 0,			/* src_mask */
    220  1.1  christos 	 0xffffffff,		/* dst_mask */
    221  1.1  christos 	 FALSE),		/* pcrel_offset */
    222  1.1  christos 
    223  1.1  christos   /* Low order 16 bit value of a high memory address.  */
    224  1.1  christos   HOWTO (R_XSTORMY16_LO16,	/* type */
    225  1.1  christos 	 0,			/* rightshift */
    226  1.1  christos 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    227  1.1  christos 	 16,			/* bitsize */
    228  1.1  christos 	 FALSE,			/* pc_relative */
    229  1.1  christos 	 0,			/* bitpos */
    230  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    231  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    232  1.1  christos 	 "R_XSTORMY16_LO16",	/* name */
    233  1.1  christos 	 FALSE,			/* partial_inplace */
    234  1.1  christos 	 0,			/* src_mask */
    235  1.1  christos 	 0xffff,		/* dst_mask */
    236  1.1  christos 	 FALSE),		/* pcrel_offset */
    237  1.1  christos 
    238  1.1  christos   /* High order 16 bit value of a high memory address.  */
    239  1.1  christos   HOWTO (R_XSTORMY16_HI16,	/* type */
    240  1.1  christos 	 16,			/* rightshift */
    241  1.1  christos 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    242  1.1  christos 	 16,			/* bitsize */
    243  1.1  christos 	 FALSE,			/* pc_relative */
    244  1.1  christos 	 0,			/* bitpos */
    245  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    246  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    247  1.1  christos 	 "R_XSTORMY16_HI16",	/* name */
    248  1.1  christos 	 FALSE,			/* partial_inplace */
    249  1.1  christos 	 0,			/* src_mask */
    250  1.1  christos 	 0xffff,		/* dst_mask */
    251  1.1  christos 	 FALSE),		/* pcrel_offset */
    252  1.1  christos 
    253  1.1  christos   /* A 12 bit absolute relocation.  */
    254  1.1  christos   HOWTO (R_XSTORMY16_12,	/* type */
    255  1.1  christos 	 0,			/* rightshift */
    256  1.1  christos 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    257  1.1  christos 	 12,			/* bitsize */
    258  1.1  christos 	 FALSE,			/* pc_relative */
    259  1.1  christos 	 0,			/* bitpos */
    260  1.1  christos 	 complain_overflow_signed, /* complain_on_overflow */
    261  1.1  christos 	 bfd_elf_generic_reloc,	/* special_function */
    262  1.1  christos 	 "R_XSTORMY16_12",	/* name */
    263  1.1  christos 	 FALSE,			/* partial_inplace */
    264  1.1  christos 	 0x0000,		/* src_mask */
    265  1.1  christos 	 0x0fff,		/* dst_mask */
    266  1.1  christos 	 FALSE),		/* pcrel_offset */
    267  1.1  christos };
    268  1.1  christos 
    269  1.1  christos static reloc_howto_type xstormy16_elf_howto_table2 [] =
    270  1.1  christos {
    271  1.1  christos   /* GNU extension to record C++ vtable hierarchy */
    272  1.1  christos   HOWTO (R_XSTORMY16_GNU_VTINHERIT, /* type */
    273  1.6  christos 	 0,			/* rightshift */
    274  1.6  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    275  1.6  christos 	 0,			/* bitsize */
    276  1.6  christos 	 FALSE,			/* pc_relative */
    277  1.6  christos 	 0,			/* bitpos */
    278  1.6  christos 	 complain_overflow_dont, /* complain_on_overflow */
    279  1.6  christos 	 NULL,			/* special_function */
    280  1.6  christos 	 "R_XSTORMY16_GNU_VTINHERIT", /* name */
    281  1.6  christos 	 FALSE,			/* partial_inplace */
    282  1.6  christos 	 0,			/* src_mask */
    283  1.6  christos 	 0,			/* dst_mask */
    284  1.6  christos 	 FALSE),		/* pcrel_offset */
    285  1.1  christos 
    286  1.1  christos   /* GNU extension to record C++ vtable member usage */
    287  1.1  christos   HOWTO (R_XSTORMY16_GNU_VTENTRY,     /* type */
    288  1.6  christos 	 0,			/* rightshift */
    289  1.6  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    290  1.6  christos 	 0,			/* bitsize */
    291  1.6  christos 	 FALSE,			/* pc_relative */
    292  1.6  christos 	 0,			/* bitpos */
    293  1.6  christos 	 complain_overflow_dont, /* complain_on_overflow */
    294  1.6  christos 	 _bfd_elf_rel_vtable_reloc_fn,	/* special_function */
    295  1.6  christos 	 "R_XSTORMY16_GNU_VTENTRY",   /* name */
    296  1.6  christos 	 FALSE,			/* partial_inplace */
    297  1.6  christos 	 0,			/* src_mask */
    298  1.6  christos 	 0,			/* dst_mask */
    299  1.6  christos 	 FALSE),		/* pcrel_offset */
    300  1.1  christos 
    301  1.1  christos };
    302  1.1  christos 
    303  1.1  christos /* Map BFD reloc types to XSTORMY16 ELF reloc types.  */
    305  1.1  christos 
    306  1.1  christos typedef struct xstormy16_reloc_map
    307  1.1  christos {
    308  1.6  christos   bfd_reloc_code_real_type  bfd_reloc_val;
    309  1.6  christos   unsigned int		    xstormy16_reloc_val;
    310  1.1  christos   reloc_howto_type *	    table;
    311  1.1  christos } reloc_map;
    312  1.1  christos 
    313  1.1  christos static const reloc_map xstormy16_reloc_map [] =
    314  1.6  christos {
    315  1.6  christos   { BFD_RELOC_NONE,		    R_XSTORMY16_NONE,	       xstormy16_elf_howto_table },
    316  1.6  christos   { BFD_RELOC_32,		    R_XSTORMY16_32,	       xstormy16_elf_howto_table },
    317  1.6  christos   { BFD_RELOC_16,		    R_XSTORMY16_16,	       xstormy16_elf_howto_table },
    318  1.6  christos   { BFD_RELOC_8,		    R_XSTORMY16_8,	       xstormy16_elf_howto_table },
    319  1.6  christos   { BFD_RELOC_32_PCREL,		    R_XSTORMY16_PC32,	       xstormy16_elf_howto_table },
    320  1.6  christos   { BFD_RELOC_16_PCREL,		    R_XSTORMY16_PC16,	       xstormy16_elf_howto_table },
    321  1.6  christos   { BFD_RELOC_8_PCREL,		    R_XSTORMY16_PC8,	       xstormy16_elf_howto_table },
    322  1.6  christos   { BFD_RELOC_XSTORMY16_REL_12,	    R_XSTORMY16_REL_12,	       xstormy16_elf_howto_table },
    323  1.6  christos   { BFD_RELOC_XSTORMY16_24,	    R_XSTORMY16_24,	       xstormy16_elf_howto_table },
    324  1.6  christos   { BFD_RELOC_XSTORMY16_FPTR16,	    R_XSTORMY16_FPTR16,	       xstormy16_elf_howto_table },
    325  1.6  christos   { BFD_RELOC_LO16,		    R_XSTORMY16_LO16,	       xstormy16_elf_howto_table },
    326  1.6  christos   { BFD_RELOC_HI16,		    R_XSTORMY16_HI16,	       xstormy16_elf_howto_table },
    327  1.6  christos   { BFD_RELOC_XSTORMY16_12,	    R_XSTORMY16_12,	       xstormy16_elf_howto_table },
    328  1.6  christos   { BFD_RELOC_VTABLE_INHERIT,	    R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 },
    329  1.1  christos   { BFD_RELOC_VTABLE_ENTRY,	    R_XSTORMY16_GNU_VTENTRY,   xstormy16_elf_howto_table2 },
    330  1.1  christos };
    331  1.1  christos 
    332  1.1  christos static reloc_howto_type *
    333  1.1  christos xstormy16_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
    334  1.1  christos 			     bfd_reloc_code_real_type code)
    335  1.1  christos {
    336  1.1  christos   unsigned int i;
    337  1.3  christos 
    338  1.1  christos   for (i = ARRAY_SIZE (xstormy16_reloc_map); i--;)
    339  1.1  christos     {
    340  1.1  christos       const reloc_map * entry;
    341  1.1  christos 
    342  1.1  christos       entry = xstormy16_reloc_map + i;
    343  1.1  christos 
    344  1.1  christos       if (entry->bfd_reloc_val == code)
    345  1.1  christos 	return entry->table + (entry->xstormy16_reloc_val
    346  1.1  christos 			       - entry->table[0].type);
    347  1.1  christos     }
    348  1.1  christos 
    349  1.1  christos   return NULL;
    350  1.1  christos }
    351  1.1  christos 
    352  1.1  christos static reloc_howto_type *
    353  1.1  christos xstormy16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    354  1.1  christos 			     const char *r_name)
    355  1.1  christos {
    356  1.1  christos   unsigned int i;
    357  1.1  christos 
    358  1.1  christos   for (i = 0;
    359  1.1  christos        i < (sizeof (xstormy16_elf_howto_table)
    360  1.1  christos 	    / sizeof (xstormy16_elf_howto_table[0]));
    361  1.1  christos        i++)
    362  1.1  christos     if (xstormy16_elf_howto_table[i].name != NULL
    363  1.1  christos 	&& strcasecmp (xstormy16_elf_howto_table[i].name, r_name) == 0)
    364  1.1  christos       return &xstormy16_elf_howto_table[i];
    365  1.1  christos 
    366  1.1  christos   for (i = 0;
    367  1.1  christos        i < (sizeof (xstormy16_elf_howto_table2)
    368  1.1  christos 	    / sizeof (xstormy16_elf_howto_table2[0]));
    369  1.1  christos        i++)
    370  1.1  christos     if (xstormy16_elf_howto_table2[i].name != NULL
    371  1.1  christos 	&& strcasecmp (xstormy16_elf_howto_table2[i].name, r_name) == 0)
    372  1.1  christos       return &xstormy16_elf_howto_table2[i];
    373  1.1  christos 
    374  1.1  christos   return NULL;
    375  1.1  christos }
    376  1.1  christos 
    377  1.1  christos /* Set the howto pointer for an XSTORMY16 ELF reloc.  */
    378  1.6  christos 
    379  1.6  christos static bfd_boolean
    380  1.1  christos xstormy16_info_to_howto_rela (bfd * abfd,
    381  1.1  christos 			      arelent * cache_ptr,
    382  1.1  christos 			      Elf_Internal_Rela * dst)
    383  1.1  christos {
    384  1.1  christos   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
    385  1.1  christos 
    386  1.1  christos   if (r_type <= (unsigned int) R_XSTORMY16_12)
    387  1.1  christos     cache_ptr->howto = &xstormy16_elf_howto_table [r_type];
    388  1.6  christos   else if (r_type - R_XSTORMY16_GNU_VTINHERIT
    389  1.6  christos 	   <= ((unsigned int) R_XSTORMY16_GNU_VTENTRY
    390  1.1  christos 	       - (unsigned int) R_XSTORMY16_GNU_VTINHERIT))
    391  1.1  christos     cache_ptr->howto
    392  1.1  christos       = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
    393  1.6  christos   else
    394  1.6  christos     {
    395  1.6  christos       /* xgettext:c-format */
    396  1.6  christos       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    397  1.6  christos 			  abfd, r_type);
    398  1.6  christos       bfd_set_error (bfd_error_bad_value);
    399  1.6  christos       return FALSE;
    400  1.6  christos     }
    401  1.1  christos   return TRUE;
    402  1.1  christos }
    403  1.1  christos 
    404  1.1  christos /* We support 16-bit pointers to code above 64k by generating a thunk
    406  1.1  christos    below 64k containing a JMPF instruction to the final address.  We
    407  1.1  christos    cannot, unfortunately, minimize the number of thunks unless the
    408  1.1  christos    -relax switch is given, as otherwise we have no idea where the
    409  1.1  christos    sections will fall in the address space.  */
    410  1.1  christos 
    411  1.1  christos static bfd_boolean
    412  1.1  christos xstormy16_elf_check_relocs (bfd *abfd,
    413  1.1  christos 			    struct bfd_link_info *info,
    414  1.1  christos 			    asection *sec,
    415  1.1  christos 			    const Elf_Internal_Rela *relocs)
    416  1.1  christos {
    417  1.1  christos   const Elf_Internal_Rela *rel, *relend;
    418  1.1  christos   struct elf_link_hash_entry **sym_hashes;
    419  1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    420  1.1  christos   bfd_vma *local_plt_offsets;
    421  1.1  christos   asection *splt;
    422  1.3  christos   bfd *dynobj;
    423  1.1  christos 
    424  1.1  christos   if (bfd_link_relocatable (info))
    425  1.1  christos     return TRUE;
    426  1.1  christos 
    427  1.1  christos   symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
    428  1.1  christos   sym_hashes = elf_sym_hashes (abfd);
    429  1.1  christos   local_plt_offsets = elf_local_got_offsets (abfd);
    430  1.1  christos   dynobj = elf_hash_table(info)->dynobj;
    431  1.1  christos 
    432  1.1  christos   relend = relocs + sec->reloc_count;
    433  1.1  christos   for (rel = relocs; rel < relend; ++rel)
    434  1.1  christos     {
    435  1.1  christos       unsigned long r_symndx;
    436  1.1  christos       struct elf_link_hash_entry *h;
    437  1.1  christos       bfd_vma *offset;
    438  1.1  christos 
    439  1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    440  1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    441  1.1  christos 	h = NULL;
    442  1.1  christos       else
    443  1.1  christos 	{
    444  1.1  christos 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    445  1.1  christos 	  while (h->root.type == bfd_link_hash_indirect
    446  1.1  christos 		 || h->root.type == bfd_link_hash_warning)
    447  1.1  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    448  1.1  christos 	}
    449  1.6  christos 
    450  1.1  christos       switch (ELF32_R_TYPE (rel->r_info))
    451  1.1  christos 	{
    452  1.1  christos 	  /* This relocation describes a 16-bit pointer to a function.
    453  1.1  christos 	     We may need to allocate a thunk in low memory; reserve memory
    454  1.1  christos 	     for it now.  */
    455  1.1  christos 	case R_XSTORMY16_FPTR16:
    456  1.1  christos 	  if (rel->r_addend != 0)
    457  1.1  christos 	    {
    458  1.1  christos 	      (*info->callbacks->warning)
    459  1.1  christos 		(info, _("non-zero addend in @fptr reloc"), 0,
    460  1.1  christos 		 abfd, 0, 0);
    461  1.1  christos 	    }
    462  1.1  christos 
    463  1.6  christos 	  if (dynobj == NULL)
    464  1.1  christos 	    elf_hash_table (info)->dynobj = dynobj = abfd;
    465  1.1  christos 	  splt = elf_hash_table (info)->splt;
    466  1.6  christos 	  if (splt == NULL)
    467  1.6  christos 	    {
    468  1.6  christos 	      flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
    469  1.6  christos 				| SEC_IN_MEMORY | SEC_LINKER_CREATED
    470  1.6  christos 				| SEC_READONLY | SEC_CODE);
    471  1.6  christos 
    472  1.6  christos 	      splt = bfd_make_section_anyway_with_flags (dynobj, ".plt",
    473  1.6  christos 							 flags);
    474  1.6  christos 	      elf_hash_table (info)->splt = splt;
    475  1.6  christos 	      if (splt == NULL
    476  1.1  christos 		  || ! bfd_set_section_alignment (dynobj, splt, 1))
    477  1.1  christos 		return FALSE;
    478  1.1  christos 	    }
    479  1.1  christos 
    480  1.1  christos 	  if (h != NULL)
    481  1.1  christos 	    offset = &h->plt.offset;
    482  1.1  christos 	  else
    483  1.1  christos 	    {
    484  1.1  christos 	      if (local_plt_offsets == NULL)
    485  1.1  christos 		{
    486  1.1  christos 		  size_t size;
    487  1.1  christos 		  unsigned int i;
    488  1.1  christos 
    489  1.1  christos 		  size = symtab_hdr->sh_info * sizeof (bfd_vma);
    490  1.1  christos 		  local_plt_offsets = bfd_alloc (abfd, size);
    491  1.1  christos 		  if (local_plt_offsets == NULL)
    492  1.1  christos 		    return FALSE;
    493  1.1  christos 		  elf_local_got_offsets (abfd) = local_plt_offsets;
    494  1.1  christos 
    495  1.1  christos 		  for (i = 0; i < symtab_hdr->sh_info; i++)
    496  1.1  christos 		    local_plt_offsets[i] = (bfd_vma) -1;
    497  1.1  christos 		}
    498  1.1  christos 	      offset = &local_plt_offsets[r_symndx];
    499  1.1  christos 	    }
    500  1.1  christos 
    501  1.1  christos 	  if (*offset == (bfd_vma) -1)
    502  1.1  christos 	    {
    503  1.1  christos 	      *offset = splt->size;
    504  1.1  christos 	      splt->size += 4;
    505  1.1  christos 	    }
    506  1.1  christos 	  break;
    507  1.1  christos 
    508  1.6  christos 	  /* This relocation describes the C++ object vtable hierarchy.
    509  1.6  christos 	     Reconstruct it for later use during GC.  */
    510  1.6  christos 	case R_XSTORMY16_GNU_VTINHERIT:
    511  1.6  christos 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
    512  1.1  christos 	    return FALSE;
    513  1.1  christos 	  break;
    514  1.1  christos 
    515  1.6  christos 	  /* This relocation describes which C++ vtable entries are actually
    516  1.6  christos 	     used.  Record for later use during GC.  */
    517  1.6  christos 	case R_XSTORMY16_GNU_VTENTRY:
    518  1.6  christos 	  BFD_ASSERT (h != NULL);
    519  1.6  christos 	  if (h != NULL
    520  1.6  christos 	      && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
    521  1.1  christos 	    return FALSE;
    522  1.1  christos 	  break;
    523  1.1  christos 	}
    524  1.1  christos     }
    525  1.1  christos 
    526  1.1  christos   return TRUE;
    527  1.1  christos }
    528  1.1  christos 
    529  1.1  christos /* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
    530  1.1  christos    is within the low 64k, remove any entry for it in the plt.  */
    531  1.1  christos 
    532  1.1  christos struct relax_plt_data
    533  1.1  christos {
    534  1.1  christos   asection *splt;
    535  1.1  christos   bfd_boolean *again;
    536  1.1  christos };
    537  1.1  christos 
    538  1.1  christos static bfd_boolean
    539  1.1  christos xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata)
    540  1.1  christos {
    541  1.1  christos   struct relax_plt_data *data = (struct relax_plt_data *) xdata;
    542  1.1  christos 
    543  1.1  christos   if (h->plt.offset != (bfd_vma) -1)
    544  1.1  christos     {
    545  1.1  christos       bfd_vma address;
    546  1.1  christos 
    547  1.1  christos       if (h->root.type == bfd_link_hash_undefined
    548  1.1  christos 	  || h->root.type == bfd_link_hash_undefweak)
    549  1.1  christos 	address = 0;
    550  1.1  christos       else
    551  1.1  christos 	address = (h->root.u.def.section->output_section->vma
    552  1.1  christos 		   + h->root.u.def.section->output_offset
    553  1.1  christos 		   + h->root.u.def.value);
    554  1.1  christos 
    555  1.1  christos       if (address <= 0xffff)
    556  1.1  christos 	{
    557  1.1  christos 	  h->plt.offset = -1;
    558  1.1  christos 	  data->splt->size -= 4;
    559  1.1  christos 	  *data->again = TRUE;
    560  1.1  christos 	}
    561  1.1  christos     }
    562  1.1  christos 
    563  1.1  christos   return TRUE;
    564  1.1  christos }
    565  1.1  christos 
    566  1.1  christos /* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
    567  1.1  christos    previously had a plt entry, give it a new entry offset.  */
    568  1.1  christos 
    569  1.1  christos static bfd_boolean
    570  1.1  christos xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata)
    571  1.1  christos {
    572  1.1  christos   bfd_vma *entry = (bfd_vma *) xdata;
    573  1.1  christos 
    574  1.1  christos   if (h->plt.offset != (bfd_vma) -1)
    575  1.1  christos     {
    576  1.1  christos       h->plt.offset = *entry;
    577  1.1  christos       *entry += 4;
    578  1.1  christos     }
    579  1.1  christos 
    580  1.1  christos   return TRUE;
    581  1.1  christos }
    582  1.1  christos 
    583  1.1  christos static bfd_boolean
    584  1.1  christos xstormy16_elf_relax_section (bfd *dynobj,
    585  1.1  christos 			     asection *splt,
    586  1.1  christos 			     struct bfd_link_info *info,
    587  1.1  christos 			     bfd_boolean *again)
    588  1.1  christos {
    589  1.1  christos   struct relax_plt_data relax_plt_data;
    590  1.1  christos   bfd *ibfd;
    591  1.1  christos 
    592  1.1  christos   /* Assume nothing changes.  */
    593  1.3  christos   *again = FALSE;
    594  1.1  christos 
    595  1.1  christos   if (bfd_link_relocatable (info))
    596  1.1  christos     return TRUE;
    597  1.1  christos 
    598  1.1  christos   /* We only relax the .plt section at the moment.  */
    599  1.1  christos   if (dynobj != elf_hash_table (info)->dynobj
    600  1.1  christos       || strcmp (splt->name, ".plt") != 0)
    601  1.1  christos     return TRUE;
    602  1.1  christos 
    603  1.1  christos   /* Quick check for an empty plt.  */
    604  1.1  christos   if (splt->size == 0)
    605  1.1  christos     return TRUE;
    606  1.1  christos 
    607  1.1  christos   /* Map across all global symbols; see which ones happen to
    608  1.1  christos      fall in the low 64k.  */
    609  1.1  christos   relax_plt_data.splt = splt;
    610  1.1  christos   relax_plt_data.again = again;
    611  1.1  christos   elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
    612  1.1  christos 			  &relax_plt_data);
    613  1.1  christos 
    614  1.3  christos   /* Likewise for local symbols, though that's somewhat less convenient
    615  1.1  christos      as we have to walk the list of input bfds and swap in symbol data.  */
    616  1.1  christos   for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next)
    617  1.1  christos     {
    618  1.1  christos       bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
    619  1.1  christos       Elf_Internal_Shdr *symtab_hdr;
    620  1.1  christos       Elf_Internal_Sym *isymbuf = NULL;
    621  1.1  christos       unsigned int idx;
    622  1.1  christos 
    623  1.1  christos       if (! local_plt_offsets)
    624  1.1  christos 	continue;
    625  1.1  christos 
    626  1.1  christos       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
    627  1.1  christos       if (symtab_hdr->sh_info != 0)
    628  1.1  christos 	{
    629  1.1  christos 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
    630  1.1  christos 	  if (isymbuf == NULL)
    631  1.1  christos 	    isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
    632  1.1  christos 					    symtab_hdr->sh_info, 0,
    633  1.1  christos 					    NULL, NULL, NULL);
    634  1.1  christos 	  if (isymbuf == NULL)
    635  1.1  christos 	    return FALSE;
    636  1.1  christos 	}
    637  1.1  christos 
    638  1.1  christos       for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
    639  1.1  christos 	{
    640  1.1  christos 	  Elf_Internal_Sym *isym;
    641  1.1  christos 	  asection *tsec;
    642  1.1  christos 	  bfd_vma address;
    643  1.1  christos 
    644  1.1  christos 	  if (local_plt_offsets[idx] == (bfd_vma) -1)
    645  1.1  christos 	    continue;
    646  1.1  christos 
    647  1.1  christos 	  isym = &isymbuf[idx];
    648  1.1  christos 	  if (isym->st_shndx == SHN_UNDEF)
    649  1.1  christos 	    continue;
    650  1.1  christos 	  else if (isym->st_shndx == SHN_ABS)
    651  1.1  christos 	    tsec = bfd_abs_section_ptr;
    652  1.1  christos 	  else if (isym->st_shndx == SHN_COMMON)
    653  1.1  christos 	    tsec = bfd_com_section_ptr;
    654  1.1  christos 	  else
    655  1.1  christos 	    tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
    656  1.1  christos 
    657  1.1  christos 	  address = (tsec->output_section->vma
    658  1.1  christos 		     + tsec->output_offset
    659  1.1  christos 		     + isym->st_value);
    660  1.1  christos 	  if (address <= 0xffff)
    661  1.1  christos 	    {
    662  1.1  christos 	      local_plt_offsets[idx] = -1;
    663  1.1  christos 	      splt->size -= 4;
    664  1.1  christos 	      *again = TRUE;
    665  1.1  christos 	    }
    666  1.1  christos 	}
    667  1.1  christos 
    668  1.1  christos       if (isymbuf != NULL
    669  1.1  christos 	  && symtab_hdr->contents != (unsigned char *) isymbuf)
    670  1.1  christos 	{
    671  1.1  christos 	  if (! info->keep_memory)
    672  1.1  christos 	    free (isymbuf);
    673  1.1  christos 	  else
    674  1.1  christos 	    {
    675  1.1  christos 	      /* Cache the symbols for elf_link_input_bfd.  */
    676  1.1  christos 	      symtab_hdr->contents = (unsigned char *) isymbuf;
    677  1.1  christos 	    }
    678  1.1  christos 	}
    679  1.1  christos     }
    680  1.1  christos 
    681  1.1  christos   /* If we changed anything, walk the symbols again to reallocate
    682  1.1  christos      .plt entry addresses.  */
    683  1.1  christos   if (*again && splt->size > 0)
    684  1.1  christos     {
    685  1.1  christos       bfd_vma entry = 0;
    686  1.1  christos 
    687  1.1  christos       elf_link_hash_traverse (elf_hash_table (info),
    688  1.3  christos 			      xstormy16_relax_plt_realloc, &entry);
    689  1.1  christos 
    690  1.1  christos       for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next)
    691  1.1  christos 	{
    692  1.1  christos 	  bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
    693  1.1  christos 	  unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
    694  1.1  christos 	  unsigned int idx;
    695  1.1  christos 
    696  1.1  christos 	  if (! local_plt_offsets)
    697  1.1  christos 	    continue;
    698  1.1  christos 
    699  1.1  christos 	  for (idx = 0; idx < nlocals; ++idx)
    700  1.6  christos 	    if (local_plt_offsets[idx] != (bfd_vma) -1)
    701  1.1  christos 	      {
    702  1.1  christos 		local_plt_offsets[idx] = entry;
    703  1.1  christos 		entry += 4;
    704  1.1  christos 	      }
    705  1.1  christos 	}
    706  1.1  christos     }
    707  1.1  christos 
    708  1.1  christos   return TRUE;
    709  1.1  christos }
    710  1.1  christos 
    711  1.1  christos static bfd_boolean
    712  1.1  christos xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
    713  1.1  christos 				    struct bfd_link_info *info)
    714  1.1  christos {
    715  1.1  christos   bfd *dynobj;
    716  1.3  christos   asection *splt;
    717  1.1  christos 
    718  1.1  christos   if (bfd_link_relocatable (info))
    719  1.1  christos     return TRUE;
    720  1.1  christos 
    721  1.1  christos   dynobj = elf_hash_table (info)->dynobj;
    722  1.1  christos   if (dynobj == NULL)
    723  1.6  christos     return TRUE;
    724  1.1  christos 
    725  1.1  christos   splt = elf_hash_table (info)->splt;
    726  1.1  christos   BFD_ASSERT (splt != NULL);
    727  1.1  christos 
    728  1.1  christos   splt->contents = bfd_zalloc (dynobj, splt->size);
    729  1.1  christos   if (splt->contents == NULL)
    730  1.1  christos     return FALSE;
    731  1.1  christos 
    732  1.1  christos   return TRUE;
    733  1.1  christos }
    734  1.1  christos 
    735  1.1  christos /* Relocate an XSTORMY16 ELF section.
    737  1.1  christos 
    738  1.1  christos    The RELOCATE_SECTION function is called by the new ELF backend linker
    739  1.1  christos    to handle the relocations for a section.
    740  1.1  christos 
    741  1.1  christos    The relocs are always passed as Rela structures; if the section
    742  1.1  christos    actually uses Rel structures, the r_addend field will always be
    743  1.1  christos    zero.
    744  1.1  christos 
    745  1.1  christos    This function is responsible for adjusting the section contents as
    746  1.1  christos    necessary, and (if using Rela relocs and generating a relocatable
    747  1.1  christos    output file) adjusting the reloc addend as necessary.
    748  1.1  christos 
    749  1.1  christos    This function does not have to worry about setting the reloc
    750  1.1  christos    address or the reloc symbol index.
    751  1.1  christos 
    752  1.1  christos    LOCAL_SYMS is a pointer to the swapped in local symbols.
    753  1.1  christos 
    754  1.1  christos    LOCAL_SECTIONS is an array giving the section in the input file
    755  1.1  christos    corresponding to the st_shndx field of each local symbol.
    756  1.1  christos 
    757  1.1  christos    The global hash table entry for the global symbols can be found
    758  1.1  christos    via elf_sym_hashes (input_bfd).
    759  1.1  christos 
    760  1.1  christos    When generating relocatable output, this function must handle
    761  1.1  christos    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    762  1.1  christos    going to be the section symbol corresponding to the output
    763  1.1  christos    section, which means that the addend must be adjusted
    764  1.6  christos    accordingly.  */
    765  1.6  christos 
    766  1.6  christos static bfd_boolean
    767  1.6  christos xstormy16_elf_relocate_section (bfd *			output_bfd ATTRIBUTE_UNUSED,
    768  1.6  christos 				struct bfd_link_info *	info,
    769  1.6  christos 				bfd *			input_bfd,
    770  1.6  christos 				asection *		input_section,
    771  1.6  christos 				bfd_byte *		contents,
    772  1.1  christos 				Elf_Internal_Rela *	relocs,
    773  1.6  christos 				Elf_Internal_Sym *	local_syms,
    774  1.1  christos 				asection **		local_sections)
    775  1.6  christos {
    776  1.6  christos   Elf_Internal_Shdr *		symtab_hdr;
    777  1.1  christos   struct elf_link_hash_entry ** sym_hashes;
    778  1.1  christos   Elf_Internal_Rela *		rel;
    779  1.1  christos   Elf_Internal_Rela *		relend;
    780  1.1  christos   asection *splt;
    781  1.1  christos 
    782  1.1  christos   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    783  1.6  christos   sym_hashes = elf_sym_hashes (input_bfd);
    784  1.1  christos   relend     = relocs + input_section->reloc_count;
    785  1.1  christos 
    786  1.1  christos   splt = elf_hash_table (info)->splt;
    787  1.6  christos 
    788  1.6  christos   for (rel = relocs; rel < relend; rel ++)
    789  1.6  christos     {
    790  1.6  christos       reloc_howto_type *	   howto;
    791  1.1  christos       unsigned long		   r_symndx;
    792  1.6  christos       Elf_Internal_Sym *	   sym;
    793  1.6  christos       asection *		   sec;
    794  1.6  christos       struct elf_link_hash_entry * h;
    795  1.6  christos       bfd_vma			   relocation;
    796  1.1  christos       bfd_reloc_status_type	   r;
    797  1.1  christos       const char *		   name = NULL;
    798  1.1  christos       int			   r_type;
    799  1.1  christos 
    800  1.1  christos       r_type = ELF32_R_TYPE (rel->r_info);
    801  1.1  christos 
    802  1.1  christos       if (   r_type == R_XSTORMY16_GNU_VTINHERIT
    803  1.1  christos 	  || r_type == R_XSTORMY16_GNU_VTENTRY)
    804  1.1  christos 	continue;
    805  1.1  christos 
    806  1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    807  1.1  christos       howto  = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
    808  1.1  christos       h      = NULL;
    809  1.1  christos       sym    = NULL;
    810  1.1  christos       sec    = NULL;
    811  1.1  christos 
    812  1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    813  1.1  christos 	{
    814  1.1  christos 	  sym = local_syms + r_symndx;
    815  1.1  christos 	  sec = local_sections [r_symndx];
    816  1.1  christos 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    817  1.3  christos 	}
    818  1.1  christos       else
    819  1.1  christos 	{
    820  1.1  christos 	  bfd_boolean unresolved_reloc, warned, ignored;
    821  1.1  christos 
    822  1.3  christos 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    823  1.1  christos 				   r_symndx, symtab_hdr, sym_hashes,
    824  1.1  christos 				   h, sec, relocation,
    825  1.1  christos 				   unresolved_reloc, warned, ignored);
    826  1.1  christos 	}
    827  1.1  christos 
    828  1.1  christos       if (sec != NULL && discarded_section (sec))
    829  1.3  christos 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    830  1.1  christos 					 rel, 1, relend, howto, 0, contents);
    831  1.1  christos 
    832  1.1  christos       if (bfd_link_relocatable (info))
    833  1.1  christos 	continue;
    834  1.1  christos 
    835  1.1  christos       if (h != NULL)
    836  1.1  christos 	name = h->root.root.string;
    837  1.1  christos       else
    838  1.1  christos 	{
    839  1.1  christos 	  name = (bfd_elf_string_from_elf_section
    840  1.1  christos 		  (input_bfd, symtab_hdr->sh_link, sym->st_name));
    841  1.1  christos 	  if (name == NULL || *name == '\0')
    842  1.1  christos 	    name = bfd_section_name (input_bfd, sec);
    843  1.1  christos 	}
    844  1.1  christos 
    845  1.1  christos       switch (ELF32_R_TYPE (rel->r_info))
    846  1.1  christos 	{
    847  1.1  christos 	case R_XSTORMY16_24:
    848  1.1  christos 	  {
    849  1.1  christos 	    bfd_vma reloc = relocation + rel->r_addend;
    850  1.1  christos 	    unsigned int x;
    851  1.1  christos 
    852  1.1  christos 	    x = bfd_get_32 (input_bfd, contents + rel->r_offset);
    853  1.1  christos 	    x &= 0x0000ff00;
    854  1.1  christos 	    x |= reloc & 0xff;
    855  1.1  christos 	    x |= (reloc << 8) & 0xffff0000;
    856  1.1  christos 	    bfd_put_32 (input_bfd, x, contents + rel->r_offset);
    857  1.1  christos 
    858  1.1  christos 	    if (reloc & ~0xffffff)
    859  1.1  christos 	      r = bfd_reloc_overflow;
    860  1.1  christos 	    else
    861  1.1  christos 	      r = bfd_reloc_ok;
    862  1.1  christos 	    break;
    863  1.1  christos 	  }
    864  1.1  christos 
    865  1.1  christos 	case R_XSTORMY16_FPTR16:
    866  1.1  christos 	  {
    867  1.1  christos 	    bfd_vma *plt_offset;
    868  1.1  christos 
    869  1.1  christos 	    if (h != NULL)
    870  1.1  christos 	      plt_offset = &h->plt.offset;
    871  1.1  christos 	    else
    872  1.1  christos 	      plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
    873  1.6  christos 
    874  1.1  christos 	    if (relocation <= 0xffff)
    875  1.6  christos 	      {
    876  1.1  christos 		/* If the symbol is in range for a 16-bit address, we should
    877  1.1  christos 		   have deallocated the plt entry in relax_section.  */
    878  1.1  christos 		BFD_ASSERT (*plt_offset == (bfd_vma) -1);
    879  1.1  christos 	      }
    880  1.1  christos 	    else
    881  1.1  christos 	      {
    882  1.1  christos 		/* If the symbol is out of range for a 16-bit address,
    883  1.1  christos 		   we must have allocated a plt entry.  */
    884  1.1  christos 		BFD_ASSERT (*plt_offset != (bfd_vma) -1);
    885  1.1  christos 
    886  1.1  christos 		/* If this is the first time we've processed this symbol,
    887  1.1  christos 		   fill in the plt entry with the correct symbol address.  */
    888  1.1  christos 		if ((*plt_offset & 1) == 0)
    889  1.1  christos 		  {
    890  1.1  christos 		    unsigned int x;
    891  1.1  christos 
    892  1.1  christos 		    x = 0x00000200;  /* jmpf */
    893  1.1  christos 		    x |= relocation & 0xff;
    894  1.1  christos 		    x |= (relocation << 8) & 0xffff0000;
    895  1.1  christos 		    bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
    896  1.1  christos 		    *plt_offset |= 1;
    897  1.1  christos 		  }
    898  1.1  christos 
    899  1.1  christos 		relocation = (splt->output_section->vma
    900  1.1  christos 			      + splt->output_offset
    901  1.1  christos 			      + (*plt_offset & -2));
    902  1.1  christos 	      }
    903  1.1  christos 	    r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    904  1.1  christos 					  contents, rel->r_offset,
    905  1.1  christos 					  relocation, 0);
    906  1.1  christos 	    break;
    907  1.1  christos 	  }
    908  1.1  christos 
    909  1.1  christos 	default:
    910  1.1  christos 	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    911  1.1  christos 					contents, rel->r_offset,
    912  1.1  christos 					relocation, rel->r_addend);
    913  1.1  christos 	  break;
    914  1.1  christos 	}
    915  1.1  christos 
    916  1.1  christos       if (r != bfd_reloc_ok)
    917  1.1  christos 	{
    918  1.1  christos 	  const char * msg = NULL;
    919  1.1  christos 
    920  1.5  christos 	  switch (r)
    921  1.1  christos 	    {
    922  1.1  christos 	    case bfd_reloc_overflow:
    923  1.1  christos 	      (*info->callbacks->reloc_overflow)
    924  1.1  christos 		(info, (h ? &h->root : NULL), name, howto->name,
    925  1.1  christos 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    926  1.5  christos 	      break;
    927  1.5  christos 
    928  1.1  christos 	    case bfd_reloc_undefined:
    929  1.1  christos 	      (*info->callbacks->undefined_symbol)
    930  1.1  christos 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
    931  1.1  christos 	      break;
    932  1.1  christos 
    933  1.1  christos 	    case bfd_reloc_outofrange:
    934  1.1  christos 	      msg = _("internal error: out of range error");
    935  1.1  christos 	      break;
    936  1.1  christos 
    937  1.1  christos 	    case bfd_reloc_notsupported:
    938  1.1  christos 	      msg = _("internal error: unsupported relocation error");
    939  1.1  christos 	      break;
    940  1.1  christos 
    941  1.1  christos 	    case bfd_reloc_dangerous:
    942  1.1  christos 	      msg = _("internal error: dangerous relocation");
    943  1.1  christos 	      break;
    944  1.1  christos 
    945  1.1  christos 	    default:
    946  1.1  christos 	      msg = _("internal error: unknown error");
    947  1.1  christos 	      break;
    948  1.5  christos 	    }
    949  1.5  christos 
    950  1.1  christos 	  if (msg)
    951  1.1  christos 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    952  1.1  christos 					 input_section, rel->r_offset);
    953  1.1  christos 	}
    954  1.1  christos     }
    955  1.1  christos 
    956  1.1  christos   return TRUE;
    957  1.1  christos }
    958  1.1  christos 
    959  1.1  christos /* This must exist if dynobj is ever set.  */
    960  1.1  christos 
    961  1.1  christos static bfd_boolean
    962  1.6  christos xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
    963  1.6  christos 				       struct bfd_link_info *info)
    964  1.1  christos {
    965  1.1  christos   bfd *dynobj = elf_hash_table (info)->dynobj;
    966  1.1  christos   asection *splt = elf_hash_table (info)->splt;
    967  1.1  christos 
    968  1.6  christos   /* As an extra sanity check, verify that all plt entries have
    969  1.1  christos      been filled in.  */
    970  1.1  christos 
    971  1.1  christos   if (dynobj != NULL && splt != NULL)
    972  1.1  christos     {
    973  1.1  christos       bfd_byte *contents = splt->contents;
    974  1.1  christos       unsigned int i, size = splt->size;
    975  1.1  christos 
    976  1.1  christos       for (i = 0; i < size; i += 4)
    977  1.1  christos 	{
    978  1.1  christos 	  unsigned int x = bfd_get_32 (dynobj, contents + i);
    979  1.1  christos 
    980  1.1  christos 	  BFD_ASSERT (x != 0);
    981  1.1  christos 	}
    982  1.1  christos     }
    983  1.1  christos 
    984  1.1  christos   return TRUE;
    985  1.1  christos }
    986  1.1  christos 
    987  1.1  christos /* Return the section that should be marked against GC for a given
    989  1.1  christos    relocation.  */
    990  1.1  christos 
    991  1.1  christos static asection *
    992  1.1  christos xstormy16_elf_gc_mark_hook (asection *sec,
    993  1.1  christos 			    struct bfd_link_info *info,
    994  1.1  christos 			    Elf_Internal_Rela *rel,
    995  1.1  christos 			    struct elf_link_hash_entry *h,
    996  1.1  christos 			    Elf_Internal_Sym *sym)
    997  1.1  christos {
    998  1.1  christos   if (h != NULL)
    999  1.1  christos     switch (ELF32_R_TYPE (rel->r_info))
   1000  1.1  christos       {
   1001  1.1  christos       case R_XSTORMY16_GNU_VTINHERIT:
   1002  1.1  christos       case R_XSTORMY16_GNU_VTENTRY:
   1003  1.1  christos 	return NULL;
   1004  1.1  christos       }
   1005  1.1  christos 
   1006  1.1  christos   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
   1007  1.1  christos }
   1008  1.1  christos 
   1009  1.3  christos #define ELF_ARCH		bfd_arch_xstormy16
   1011  1.1  christos #define ELF_MACHINE_CODE	EM_XSTORMY16
   1012  1.1  christos #define ELF_MAXPAGESIZE		0x100
   1013  1.1  christos 
   1014  1.1  christos #define TARGET_LITTLE_SYM       xstormy16_elf32_vec
   1015  1.1  christos #define TARGET_LITTLE_NAME	"elf32-xstormy16"
   1016  1.6  christos 
   1017  1.1  christos #define elf_info_to_howto_rel			NULL
   1018  1.1  christos #define elf_info_to_howto			xstormy16_info_to_howto_rela
   1019  1.1  christos #define elf_backend_relocate_section		xstormy16_elf_relocate_section
   1020  1.6  christos #define elf_backend_gc_mark_hook		xstormy16_elf_gc_mark_hook
   1021  1.1  christos #define elf_backend_check_relocs		xstormy16_elf_check_relocs
   1022  1.1  christos #define elf_backend_always_size_sections \
   1023  1.1  christos   xstormy16_elf_always_size_sections
   1024  1.1  christos #define elf_backend_omit_section_dynsym \
   1025  1.1  christos   _bfd_elf_omit_section_dynsym_all
   1026  1.1  christos #define elf_backend_finish_dynamic_sections \
   1027  1.1  christos   xstormy16_elf_finish_dynamic_sections
   1028  1.1  christos 
   1029  1.1  christos #define elf_backend_can_gc_sections		1
   1030  1.1  christos #define elf_backend_rela_normal			1
   1031  1.1  christos 
   1032  1.1  christos #define bfd_elf32_bfd_reloc_type_lookup		xstormy16_reloc_type_lookup
   1033                #define bfd_elf32_bfd_reloc_name_lookup \
   1034                  xstormy16_reloc_name_lookup
   1035                #define bfd_elf32_bfd_relax_section		xstormy16_elf_relax_section
   1036                
   1037                #include "elf32-target.h"
   1038