Home | History | Annotate | Line # | Download | only in bfd
elf32-xstormy16.c revision 1.8
      1  1.1  christos /* Xstormy16-specific support for 32-bit ELF.
      2  1.8  christos    Copyright (C) 2000-2022 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.8  christos 	 0,			/* size */
     77  1.3  christos 	 0,			/* bitsize */
     78  1.8  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.8  christos 	 false,			/* partial_inplace */
     84  1.1  christos 	 0,			/* src_mask */
     85  1.1  christos 	 0,			/* dst_mask */
     86  1.8  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.8  christos 	 4,			/* size */
     92  1.1  christos 	 32,			/* bitsize */
     93  1.8  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.8  christos 	 false,			/* partial_inplace */
     99  1.1  christos 	 0,			/* src_mask */
    100  1.1  christos 	 0xffffffff,		/* dst_mask */
    101  1.8  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.8  christos 	 2,			/* size */
    107  1.1  christos 	 16,			/* bitsize */
    108  1.8  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.8  christos 	 false,			/* partial_inplace */
    114  1.1  christos 	 0,			/* src_mask */
    115  1.1  christos 	 0xffff,		/* dst_mask */
    116  1.8  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.8  christos 	 1,			/* size */
    122  1.1  christos 	 8,			/* bitsize */
    123  1.8  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.8  christos 	 false,			/* partial_inplace */
    129  1.1  christos 	 0,			/* src_mask */
    130  1.1  christos 	 0xff,			/* dst_mask */
    131  1.8  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.8  christos 	 4,			/* size */
    137  1.1  christos 	 32,			/* bitsize */
    138  1.8  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.8  christos 	 false,			/* partial_inplace */
    144  1.1  christos 	 0,			/* src_mask */
    145  1.1  christos 	 0xffffffff,		/* dst_mask */
    146  1.8  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.8  christos 	 2,			/* size */
    152  1.1  christos 	 16,			/* bitsize */
    153  1.8  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.8  christos 	 false,			/* partial_inplace */
    159  1.1  christos 	 0,			/* src_mask */
    160  1.1  christos 	 0xffffffff,		/* dst_mask */
    161  1.8  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.8  christos 	 1,			/* size */
    167  1.1  christos 	 8,			/* bitsize */
    168  1.8  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.8  christos 	 false,			/* partial_inplace */
    174  1.1  christos 	 0,			/* src_mask */
    175  1.1  christos 	 0xffffffff,		/* dst_mask */
    176  1.8  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.8  christos 	 2,			/* size */
    182  1.1  christos 	 11,			/* bitsize */
    183  1.8  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.8  christos 	 false,			/* partial_inplace */
    189  1.1  christos 	 0,			/* src_mask */
    190  1.1  christos 	 0x0ffe,		/* dst_mask */
    191  1.8  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.8  christos 	 4,			/* size */
    197  1.1  christos 	 24,			/* bitsize */
    198  1.8  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.8  christos 	 true,			/* partial_inplace */
    204  1.1  christos 	 0,			/* src_mask */
    205  1.1  christos 	 0xffff00ff,		/* dst_mask */
    206  1.8  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.8  christos 	 2,			/* size */
    212  1.1  christos 	 16,			/* bitsize */
    213  1.8  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.8  christos 	 false,			/* partial_inplace */
    219  1.1  christos 	 0,			/* src_mask */
    220  1.1  christos 	 0xffffffff,		/* dst_mask */
    221  1.8  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.8  christos 	 2,			/* size */
    227  1.1  christos 	 16,			/* bitsize */
    228  1.8  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.8  christos 	 false,			/* partial_inplace */
    234  1.1  christos 	 0,			/* src_mask */
    235  1.1  christos 	 0xffff,		/* dst_mask */
    236  1.8  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.8  christos 	 2,			/* size */
    242  1.1  christos 	 16,			/* bitsize */
    243  1.8  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.8  christos 	 false,			/* partial_inplace */
    249  1.1  christos 	 0,			/* src_mask */
    250  1.1  christos 	 0xffff,		/* dst_mask */
    251  1.8  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.8  christos 	 2,			/* size */
    257  1.1  christos 	 12,			/* bitsize */
    258  1.8  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.8  christos 	 false,			/* partial_inplace */
    264  1.1  christos 	 0x0000,		/* src_mask */
    265  1.1  christos 	 0x0fff,		/* dst_mask */
    266  1.8  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.8  christos 	 4,			/* size */
    275  1.6  christos 	 0,			/* bitsize */
    276  1.8  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.8  christos 	 false,			/* partial_inplace */
    282  1.6  christos 	 0,			/* src_mask */
    283  1.6  christos 	 0,			/* dst_mask */
    284  1.8  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.8  christos 	 4,			/* size */
    290  1.6  christos 	 0,			/* bitsize */
    291  1.8  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.8  christos 	 false,			/* partial_inplace */
    297  1.6  christos 	 0,			/* src_mask */
    298  1.6  christos 	 0,			/* dst_mask */
    299  1.8  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.8  christos 
    379  1.6  christos static bool
    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.8  christos       bfd_set_error (bfd_error_bad_value);
    399  1.6  christos       return false;
    400  1.8  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.8  christos    sections will fall in the address space.  */
    410  1.1  christos 
    411  1.1  christos static bool
    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.8  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.7  christos 	      elf_hash_table (info)->splt = splt;
    475  1.8  christos 	      if (splt == NULL
    476  1.1  christos 		  || !bfd_set_section_alignment (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.8  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.8  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.7  christos 	     used.  Record for later use during GC.  */
    517  1.8  christos 	case R_XSTORMY16_GNU_VTENTRY:
    518  1.6  christos 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
    519  1.1  christos 	    return false;
    520  1.1  christos 	  break;
    521  1.1  christos 	}
    522  1.8  christos     }
    523  1.1  christos 
    524  1.1  christos   return true;
    525  1.1  christos }
    526  1.1  christos 
    527  1.1  christos /* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
    528  1.1  christos    is within the low 64k, remove any entry for it in the plt.  */
    529  1.1  christos 
    530  1.1  christos struct relax_plt_data
    531  1.8  christos {
    532  1.1  christos   asection *splt;
    533  1.1  christos   bool *again;
    534  1.8  christos };
    535  1.1  christos 
    536  1.1  christos static bool
    537  1.1  christos xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata)
    538  1.1  christos {
    539  1.1  christos   struct relax_plt_data *data = (struct relax_plt_data *) xdata;
    540  1.1  christos 
    541  1.1  christos   if (h->plt.offset != (bfd_vma) -1)
    542  1.1  christos     {
    543  1.1  christos       bfd_vma address;
    544  1.1  christos 
    545  1.1  christos       if (h->root.type == bfd_link_hash_undefined
    546  1.1  christos 	  || h->root.type == bfd_link_hash_undefweak)
    547  1.1  christos 	address = 0;
    548  1.1  christos       else
    549  1.1  christos 	address = (h->root.u.def.section->output_section->vma
    550  1.1  christos 		   + h->root.u.def.section->output_offset
    551  1.1  christos 		   + h->root.u.def.value);
    552  1.1  christos 
    553  1.1  christos       if (address <= 0xffff)
    554  1.1  christos 	{
    555  1.8  christos 	  h->plt.offset = -1;
    556  1.1  christos 	  data->splt->size -= 4;
    557  1.1  christos 	  *data->again = true;
    558  1.1  christos 	}
    559  1.8  christos     }
    560  1.1  christos 
    561  1.1  christos   return true;
    562  1.1  christos }
    563  1.1  christos 
    564  1.1  christos /* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
    565  1.8  christos    previously had a plt entry, give it a new entry offset.  */
    566  1.1  christos 
    567  1.1  christos static bool
    568  1.1  christos xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata)
    569  1.1  christos {
    570  1.1  christos   bfd_vma *entry = (bfd_vma *) xdata;
    571  1.1  christos 
    572  1.1  christos   if (h->plt.offset != (bfd_vma) -1)
    573  1.1  christos     {
    574  1.1  christos       h->plt.offset = *entry;
    575  1.1  christos       *entry += 4;
    576  1.8  christos     }
    577  1.1  christos 
    578  1.1  christos   return true;
    579  1.8  christos }
    580  1.1  christos 
    581  1.1  christos static bool
    582  1.1  christos xstormy16_elf_relax_section (bfd *dynobj,
    583  1.8  christos 			     asection *splt,
    584  1.1  christos 			     struct bfd_link_info *info,
    585  1.1  christos 			     bool *again)
    586  1.1  christos {
    587  1.1  christos   struct relax_plt_data relax_plt_data;
    588  1.1  christos   bfd *ibfd;
    589  1.8  christos 
    590  1.1  christos   /* Assume nothing changes.  */
    591  1.8  christos   *again = false;
    592  1.8  christos 
    593  1.8  christos   if (bfd_link_relocatable (info)
    594  1.1  christos       || !is_elf_hash_table (info->hash))
    595  1.1  christos     return true;
    596  1.1  christos 
    597  1.1  christos   /* We only relax the .plt section at the moment.  */
    598  1.8  christos   if (dynobj != elf_hash_table (info)->dynobj
    599  1.1  christos       || strcmp (splt->name, ".plt") != 0)
    600  1.1  christos     return true;
    601  1.1  christos 
    602  1.8  christos   /* Quick check for an empty plt.  */
    603  1.1  christos   if (splt->size == 0)
    604  1.1  christos     return true;
    605  1.1  christos 
    606  1.1  christos   /* Map across all global symbols; see which ones happen to
    607  1.1  christos      fall in the low 64k.  */
    608  1.1  christos   relax_plt_data.splt = splt;
    609  1.1  christos   relax_plt_data.again = again;
    610  1.1  christos   elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
    611  1.1  christos 			  &relax_plt_data);
    612  1.1  christos 
    613  1.3  christos   /* Likewise for local symbols, though that's somewhat less convenient
    614  1.1  christos      as we have to walk the list of input bfds and swap in symbol data.  */
    615  1.1  christos   for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next)
    616  1.1  christos     {
    617  1.1  christos       bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
    618  1.1  christos       Elf_Internal_Shdr *symtab_hdr;
    619  1.1  christos       Elf_Internal_Sym *isymbuf = NULL;
    620  1.1  christos       unsigned int idx;
    621  1.1  christos 
    622  1.1  christos       if (! local_plt_offsets)
    623  1.1  christos 	continue;
    624  1.1  christos 
    625  1.1  christos       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
    626  1.1  christos       if (symtab_hdr->sh_info != 0)
    627  1.1  christos 	{
    628  1.1  christos 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
    629  1.1  christos 	  if (isymbuf == NULL)
    630  1.1  christos 	    isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
    631  1.1  christos 					    symtab_hdr->sh_info, 0,
    632  1.8  christos 					    NULL, NULL, NULL);
    633  1.1  christos 	  if (isymbuf == NULL)
    634  1.1  christos 	    return false;
    635  1.1  christos 	}
    636  1.1  christos 
    637  1.1  christos       for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
    638  1.1  christos 	{
    639  1.1  christos 	  Elf_Internal_Sym *isym;
    640  1.1  christos 	  asection *tsec;
    641  1.1  christos 	  bfd_vma address;
    642  1.1  christos 
    643  1.1  christos 	  if (local_plt_offsets[idx] == (bfd_vma) -1)
    644  1.1  christos 	    continue;
    645  1.1  christos 
    646  1.1  christos 	  isym = &isymbuf[idx];
    647  1.1  christos 	  if (isym->st_shndx == SHN_UNDEF)
    648  1.1  christos 	    continue;
    649  1.1  christos 	  else if (isym->st_shndx == SHN_ABS)
    650  1.1  christos 	    tsec = bfd_abs_section_ptr;
    651  1.1  christos 	  else if (isym->st_shndx == SHN_COMMON)
    652  1.1  christos 	    tsec = bfd_com_section_ptr;
    653  1.1  christos 	  else
    654  1.1  christos 	    tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
    655  1.1  christos 
    656  1.1  christos 	  address = (tsec->output_section->vma
    657  1.1  christos 		     + tsec->output_offset
    658  1.1  christos 		     + isym->st_value);
    659  1.1  christos 	  if (address <= 0xffff)
    660  1.1  christos 	    {
    661  1.8  christos 	      local_plt_offsets[idx] = -1;
    662  1.1  christos 	      splt->size -= 4;
    663  1.1  christos 	      *again = true;
    664  1.1  christos 	    }
    665  1.1  christos 	}
    666  1.1  christos 
    667  1.1  christos       if (isymbuf != NULL
    668  1.1  christos 	  && symtab_hdr->contents != (unsigned char *) isymbuf)
    669  1.1  christos 	{
    670  1.1  christos 	  if (! info->keep_memory)
    671  1.1  christos 	    free (isymbuf);
    672  1.1  christos 	  else
    673  1.1  christos 	    {
    674  1.1  christos 	      /* Cache the symbols for elf_link_input_bfd.  */
    675  1.1  christos 	      symtab_hdr->contents = (unsigned char *) isymbuf;
    676  1.1  christos 	    }
    677  1.1  christos 	}
    678  1.1  christos     }
    679  1.1  christos 
    680  1.1  christos   /* If we changed anything, walk the symbols again to reallocate
    681  1.1  christos      .plt entry addresses.  */
    682  1.1  christos   if (*again && splt->size > 0)
    683  1.1  christos     {
    684  1.1  christos       bfd_vma entry = 0;
    685  1.1  christos 
    686  1.1  christos       elf_link_hash_traverse (elf_hash_table (info),
    687  1.3  christos 			      xstormy16_relax_plt_realloc, &entry);
    688  1.1  christos 
    689  1.1  christos       for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next)
    690  1.1  christos 	{
    691  1.1  christos 	  bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
    692  1.1  christos 	  unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
    693  1.1  christos 	  unsigned int idx;
    694  1.1  christos 
    695  1.1  christos 	  if (! local_plt_offsets)
    696  1.1  christos 	    continue;
    697  1.1  christos 
    698  1.1  christos 	  for (idx = 0; idx < nlocals; ++idx)
    699  1.6  christos 	    if (local_plt_offsets[idx] != (bfd_vma) -1)
    700  1.1  christos 	      {
    701  1.1  christos 		local_plt_offsets[idx] = entry;
    702  1.1  christos 		entry += 4;
    703  1.1  christos 	      }
    704  1.1  christos 	}
    705  1.8  christos     }
    706  1.1  christos 
    707  1.1  christos   return true;
    708  1.8  christos }
    709  1.1  christos 
    710  1.1  christos static bool
    711  1.1  christos xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
    712  1.1  christos 				    struct bfd_link_info *info)
    713  1.1  christos {
    714  1.1  christos   bfd *dynobj;
    715  1.3  christos   asection *splt;
    716  1.8  christos 
    717  1.1  christos   if (bfd_link_relocatable (info))
    718  1.1  christos     return true;
    719  1.1  christos 
    720  1.8  christos   dynobj = elf_hash_table (info)->dynobj;
    721  1.1  christos   if (dynobj == NULL)
    722  1.6  christos     return true;
    723  1.1  christos 
    724  1.1  christos   splt = elf_hash_table (info)->splt;
    725  1.1  christos   BFD_ASSERT (splt != NULL);
    726  1.1  christos 
    727  1.8  christos   splt->contents = bfd_zalloc (dynobj, splt->size);
    728  1.1  christos   if (splt->contents == NULL)
    729  1.8  christos     return false;
    730  1.1  christos 
    731  1.1  christos   return true;
    732  1.1  christos }
    733  1.1  christos 
    734  1.1  christos /* Relocate an XSTORMY16 ELF section.
    736  1.1  christos 
    737  1.1  christos    The RELOCATE_SECTION function is called by the new ELF backend linker
    738  1.1  christos    to handle the relocations for a section.
    739  1.1  christos 
    740  1.1  christos    The relocs are always passed as Rela structures; if the section
    741  1.1  christos    actually uses Rel structures, the r_addend field will always be
    742  1.1  christos    zero.
    743  1.1  christos 
    744  1.1  christos    This function is responsible for adjusting the section contents as
    745  1.1  christos    necessary, and (if using Rela relocs and generating a relocatable
    746  1.1  christos    output file) adjusting the reloc addend as necessary.
    747  1.1  christos 
    748  1.1  christos    This function does not have to worry about setting the reloc
    749  1.1  christos    address or the reloc symbol index.
    750  1.1  christos 
    751  1.1  christos    LOCAL_SYMS is a pointer to the swapped in local symbols.
    752  1.1  christos 
    753  1.1  christos    LOCAL_SECTIONS is an array giving the section in the input file
    754  1.1  christos    corresponding to the st_shndx field of each local symbol.
    755  1.1  christos 
    756  1.1  christos    The global hash table entry for the global symbols can be found
    757  1.1  christos    via elf_sym_hashes (input_bfd).
    758  1.1  christos 
    759  1.1  christos    When generating relocatable output, this function must handle
    760  1.1  christos    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    761  1.1  christos    going to be the section symbol corresponding to the output
    762  1.8  christos    section, which means that the addend must be adjusted
    763  1.6  christos    accordingly.  */
    764  1.6  christos 
    765  1.6  christos static int
    766  1.6  christos xstormy16_elf_relocate_section (bfd *			output_bfd ATTRIBUTE_UNUSED,
    767  1.6  christos 				struct bfd_link_info *	info,
    768  1.6  christos 				bfd *			input_bfd,
    769  1.6  christos 				asection *		input_section,
    770  1.6  christos 				bfd_byte *		contents,
    771  1.1  christos 				Elf_Internal_Rela *	relocs,
    772  1.6  christos 				Elf_Internal_Sym *	local_syms,
    773  1.1  christos 				asection **		local_sections)
    774  1.6  christos {
    775  1.6  christos   Elf_Internal_Shdr *		symtab_hdr;
    776  1.1  christos   struct elf_link_hash_entry ** sym_hashes;
    777  1.1  christos   Elf_Internal_Rela *		rel;
    778  1.1  christos   Elf_Internal_Rela *		relend;
    779  1.1  christos   asection *splt;
    780  1.1  christos 
    781  1.1  christos   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    782  1.6  christos   sym_hashes = elf_sym_hashes (input_bfd);
    783  1.1  christos   relend     = relocs + input_section->reloc_count;
    784  1.1  christos 
    785  1.1  christos   splt = elf_hash_table (info)->splt;
    786  1.6  christos 
    787  1.6  christos   for (rel = relocs; rel < relend; rel ++)
    788  1.6  christos     {
    789  1.6  christos       reloc_howto_type *	   howto;
    790  1.1  christos       unsigned long		   r_symndx;
    791  1.6  christos       Elf_Internal_Sym *	   sym;
    792  1.6  christos       asection *		   sec;
    793  1.6  christos       struct elf_link_hash_entry * h;
    794  1.6  christos       bfd_vma			   relocation;
    795  1.1  christos       bfd_reloc_status_type	   r;
    796  1.1  christos       const char *		   name = NULL;
    797  1.1  christos       int			   r_type;
    798  1.1  christos 
    799  1.1  christos       r_type = ELF32_R_TYPE (rel->r_info);
    800  1.1  christos 
    801  1.1  christos       if (   r_type == R_XSTORMY16_GNU_VTINHERIT
    802  1.1  christos 	  || r_type == R_XSTORMY16_GNU_VTENTRY)
    803  1.1  christos 	continue;
    804  1.1  christos 
    805  1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    806  1.1  christos       howto  = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
    807  1.1  christos       h      = NULL;
    808  1.1  christos       sym    = NULL;
    809  1.1  christos       sec    = NULL;
    810  1.1  christos 
    811  1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    812  1.1  christos 	{
    813  1.1  christos 	  sym = local_syms + r_symndx;
    814  1.1  christos 	  sec = local_sections [r_symndx];
    815  1.1  christos 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    816  1.8  christos 	}
    817  1.1  christos       else
    818  1.1  christos 	{
    819  1.1  christos 	  bool unresolved_reloc, warned, ignored;
    820  1.1  christos 
    821  1.3  christos 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    822  1.1  christos 				   r_symndx, symtab_hdr, sym_hashes,
    823  1.1  christos 				   h, sec, relocation,
    824  1.1  christos 				   unresolved_reloc, warned, ignored);
    825  1.1  christos 	}
    826  1.1  christos 
    827  1.1  christos       if (sec != NULL && discarded_section (sec))
    828  1.3  christos 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    829  1.1  christos 					 rel, 1, relend, howto, 0, contents);
    830  1.1  christos 
    831  1.1  christos       if (bfd_link_relocatable (info))
    832  1.1  christos 	continue;
    833  1.1  christos 
    834  1.1  christos       if (h != NULL)
    835  1.1  christos 	name = h->root.root.string;
    836  1.1  christos       else
    837  1.1  christos 	{
    838  1.7  christos 	  name = (bfd_elf_string_from_elf_section
    839  1.1  christos 		  (input_bfd, symtab_hdr->sh_link, sym->st_name));
    840  1.1  christos 	  if (name == NULL || *name == '\0')
    841  1.1  christos 	    name = bfd_section_name (sec);
    842  1.1  christos 	}
    843  1.1  christos 
    844  1.1  christos       switch (ELF32_R_TYPE (rel->r_info))
    845  1.1  christos 	{
    846  1.1  christos 	case R_XSTORMY16_24:
    847  1.1  christos 	  {
    848  1.1  christos 	    bfd_vma reloc = relocation + rel->r_addend;
    849  1.1  christos 	    unsigned int x;
    850  1.1  christos 
    851  1.1  christos 	    x = bfd_get_32 (input_bfd, contents + rel->r_offset);
    852  1.1  christos 	    x &= 0x0000ff00;
    853  1.1  christos 	    x |= reloc & 0xff;
    854  1.1  christos 	    x |= (reloc << 8) & 0xffff0000;
    855  1.1  christos 	    bfd_put_32 (input_bfd, x, contents + rel->r_offset);
    856  1.1  christos 
    857  1.1  christos 	    if (reloc & ~0xffffff)
    858  1.1  christos 	      r = bfd_reloc_overflow;
    859  1.1  christos 	    else
    860  1.1  christos 	      r = bfd_reloc_ok;
    861  1.1  christos 	    break;
    862  1.1  christos 	  }
    863  1.1  christos 
    864  1.1  christos 	case R_XSTORMY16_FPTR16:
    865  1.1  christos 	  {
    866  1.1  christos 	    bfd_vma *plt_offset;
    867  1.1  christos 
    868  1.1  christos 	    if (h != NULL)
    869  1.1  christos 	      plt_offset = &h->plt.offset;
    870  1.1  christos 	    else
    871  1.1  christos 	      plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
    872  1.6  christos 
    873  1.1  christos 	    if (relocation <= 0xffff)
    874  1.6  christos 	      {
    875  1.1  christos 		/* If the symbol is in range for a 16-bit address, we should
    876  1.1  christos 		   have deallocated the plt entry in relax_section.  */
    877  1.1  christos 		BFD_ASSERT (*plt_offset == (bfd_vma) -1);
    878  1.1  christos 	      }
    879  1.1  christos 	    else
    880  1.1  christos 	      {
    881  1.1  christos 		/* If the symbol is out of range for a 16-bit address,
    882  1.1  christos 		   we must have allocated a plt entry.  */
    883  1.1  christos 		BFD_ASSERT (*plt_offset != (bfd_vma) -1);
    884  1.1  christos 
    885  1.1  christos 		/* If this is the first time we've processed this symbol,
    886  1.1  christos 		   fill in the plt entry with the correct symbol address.  */
    887  1.1  christos 		if ((*plt_offset & 1) == 0)
    888  1.1  christos 		  {
    889  1.1  christos 		    unsigned int x;
    890  1.1  christos 
    891  1.1  christos 		    x = 0x00000200;  /* jmpf */
    892  1.1  christos 		    x |= relocation & 0xff;
    893  1.1  christos 		    x |= (relocation << 8) & 0xffff0000;
    894  1.1  christos 		    bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
    895  1.1  christos 		    *plt_offset |= 1;
    896  1.1  christos 		  }
    897  1.1  christos 
    898  1.1  christos 		relocation = (splt->output_section->vma
    899  1.1  christos 			      + splt->output_offset
    900  1.1  christos 			      + (*plt_offset & -2));
    901  1.1  christos 	      }
    902  1.1  christos 	    r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    903  1.1  christos 					  contents, rel->r_offset,
    904  1.1  christos 					  relocation, 0);
    905  1.1  christos 	    break;
    906  1.1  christos 	  }
    907  1.1  christos 
    908  1.1  christos 	default:
    909  1.1  christos 	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    910  1.1  christos 					contents, rel->r_offset,
    911  1.1  christos 					relocation, rel->r_addend);
    912  1.1  christos 	  break;
    913  1.1  christos 	}
    914  1.1  christos 
    915  1.1  christos       if (r != bfd_reloc_ok)
    916  1.1  christos 	{
    917  1.1  christos 	  const char * msg = NULL;
    918  1.1  christos 
    919  1.5  christos 	  switch (r)
    920  1.1  christos 	    {
    921  1.1  christos 	    case bfd_reloc_overflow:
    922  1.1  christos 	      (*info->callbacks->reloc_overflow)
    923  1.1  christos 		(info, (h ? &h->root : NULL), name, howto->name,
    924  1.1  christos 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    925  1.5  christos 	      break;
    926  1.8  christos 
    927  1.1  christos 	    case bfd_reloc_undefined:
    928  1.1  christos 	      (*info->callbacks->undefined_symbol)
    929  1.1  christos 		(info, name, input_bfd, input_section, rel->r_offset, true);
    930  1.1  christos 	      break;
    931  1.1  christos 
    932  1.1  christos 	    case bfd_reloc_outofrange:
    933  1.1  christos 	      msg = _("internal error: out of range error");
    934  1.1  christos 	      break;
    935  1.1  christos 
    936  1.1  christos 	    case bfd_reloc_notsupported:
    937  1.1  christos 	      msg = _("internal error: unsupported relocation error");
    938  1.1  christos 	      break;
    939  1.1  christos 
    940  1.1  christos 	    case bfd_reloc_dangerous:
    941  1.1  christos 	      msg = _("internal error: dangerous relocation");
    942  1.1  christos 	      break;
    943  1.1  christos 
    944  1.1  christos 	    default:
    945  1.1  christos 	      msg = _("internal error: unknown error");
    946  1.1  christos 	      break;
    947  1.5  christos 	    }
    948  1.5  christos 
    949  1.1  christos 	  if (msg)
    950  1.1  christos 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    951  1.1  christos 					 input_section, rel->r_offset);
    952  1.8  christos 	}
    953  1.1  christos     }
    954  1.1  christos 
    955  1.1  christos   return true;
    956  1.1  christos }
    957  1.8  christos 
    958  1.1  christos /* This must exist if dynobj is ever set.  */
    959  1.1  christos 
    960  1.1  christos static bool
    961  1.6  christos xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
    962  1.6  christos 				       struct bfd_link_info *info)
    963  1.1  christos {
    964  1.1  christos   bfd *dynobj = elf_hash_table (info)->dynobj;
    965  1.1  christos   asection *splt = elf_hash_table (info)->splt;
    966  1.1  christos 
    967  1.6  christos   /* As an extra sanity check, verify that all plt entries have
    968  1.1  christos      been filled in.  */
    969  1.1  christos 
    970  1.1  christos   if (dynobj != NULL && splt != NULL)
    971  1.1  christos     {
    972  1.1  christos       bfd_byte *contents = splt->contents;
    973  1.1  christos       unsigned int i, size = splt->size;
    974  1.1  christos 
    975  1.1  christos       for (i = 0; i < size; i += 4)
    976  1.1  christos 	{
    977  1.1  christos 	  unsigned int x = bfd_get_32 (dynobj, contents + i);
    978  1.1  christos 
    979  1.1  christos 	  BFD_ASSERT (x != 0);
    980  1.8  christos 	}
    981  1.1  christos     }
    982  1.1  christos 
    983  1.1  christos   return true;
    984  1.1  christos }
    985  1.1  christos 
    986  1.1  christos /* Return the section that should be marked against GC for a given
    988  1.1  christos    relocation.  */
    989  1.1  christos 
    990  1.1  christos static asection *
    991  1.1  christos xstormy16_elf_gc_mark_hook (asection *sec,
    992  1.1  christos 			    struct bfd_link_info *info,
    993  1.1  christos 			    Elf_Internal_Rela *rel,
    994  1.1  christos 			    struct elf_link_hash_entry *h,
    995  1.1  christos 			    Elf_Internal_Sym *sym)
    996  1.1  christos {
    997  1.1  christos   if (h != NULL)
    998  1.1  christos     switch (ELF32_R_TYPE (rel->r_info))
    999  1.1  christos       {
   1000  1.1  christos       case R_XSTORMY16_GNU_VTINHERIT:
   1001  1.1  christos       case R_XSTORMY16_GNU_VTENTRY:
   1002  1.1  christos 	return NULL;
   1003  1.1  christos       }
   1004  1.1  christos 
   1005  1.1  christos   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
   1006  1.1  christos }
   1007  1.1  christos 
   1008  1.3  christos #define ELF_ARCH		bfd_arch_xstormy16
   1010  1.1  christos #define ELF_MACHINE_CODE	EM_XSTORMY16
   1011  1.1  christos #define ELF_MAXPAGESIZE		0x100
   1012  1.1  christos 
   1013  1.1  christos #define TARGET_LITTLE_SYM       xstormy16_elf32_vec
   1014  1.1  christos #define TARGET_LITTLE_NAME	"elf32-xstormy16"
   1015  1.6  christos 
   1016  1.1  christos #define elf_info_to_howto_rel			NULL
   1017  1.1  christos #define elf_info_to_howto			xstormy16_info_to_howto_rela
   1018  1.1  christos #define elf_backend_relocate_section		xstormy16_elf_relocate_section
   1019  1.6  christos #define elf_backend_gc_mark_hook		xstormy16_elf_gc_mark_hook
   1020  1.1  christos #define elf_backend_check_relocs		xstormy16_elf_check_relocs
   1021  1.1  christos #define elf_backend_always_size_sections \
   1022  1.1  christos   xstormy16_elf_always_size_sections
   1023  1.1  christos #define elf_backend_omit_section_dynsym \
   1024  1.1  christos   _bfd_elf_omit_section_dynsym_all
   1025  1.1  christos #define elf_backend_finish_dynamic_sections \
   1026  1.1  christos   xstormy16_elf_finish_dynamic_sections
   1027  1.1  christos 
   1028  1.1  christos #define elf_backend_can_gc_sections		1
   1029  1.1  christos #define elf_backend_rela_normal			1
   1030  1.1  christos 
   1031  1.1  christos #define bfd_elf32_bfd_reloc_type_lookup		xstormy16_reloc_type_lookup
   1032                #define bfd_elf32_bfd_reloc_name_lookup \
   1033                  xstormy16_reloc_name_lookup
   1034                #define bfd_elf32_bfd_relax_section		xstormy16_elf_relax_section
   1035                
   1036                #include "elf32-target.h"
   1037