Home | History | Annotate | Line # | Download | only in bfd
elf32-xstormy16.c revision 1.3
      1  1.1  christos /* Xstormy16-specific support for 32-bit ELF.
      2  1.3  christos    Copyright (C) 2000-2015 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.1  christos          0,                     /* rightshift */
    274  1.1  christos          2,                     /* size (0 = byte, 1 = short, 2 = long) */
    275  1.1  christos          0,                     /* bitsize */
    276  1.1  christos          FALSE,                 /* pc_relative */
    277  1.1  christos          0,                     /* bitpos */
    278  1.1  christos          complain_overflow_dont, /* complain_on_overflow */
    279  1.1  christos          NULL,                  /* special_function */
    280  1.1  christos          "R_XSTORMY16_GNU_VTINHERIT", /* name */
    281  1.1  christos          FALSE,                 /* partial_inplace */
    282  1.1  christos          0,                     /* src_mask */
    283  1.1  christos          0,                     /* dst_mask */
    284  1.1  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.1  christos          0,                     /* rightshift */
    289  1.1  christos          2,                     /* size (0 = byte, 1 = short, 2 = long) */
    290  1.1  christos          0,                     /* bitsize */
    291  1.1  christos          FALSE,                 /* pc_relative */
    292  1.1  christos          0,                     /* bitpos */
    293  1.1  christos          complain_overflow_dont, /* complain_on_overflow */
    294  1.1  christos          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
    295  1.1  christos          "R_XSTORMY16_GNU_VTENTRY",   /* name */
    296  1.1  christos          FALSE,                 /* partial_inplace */
    297  1.1  christos          0,                     /* src_mask */
    298  1.1  christos          0,                     /* dst_mask */
    299  1.1  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.1  christos   bfd_reloc_code_real_type  bfd_reloc_val;
    309  1.1  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.1  christos {
    315  1.1  christos   { BFD_RELOC_NONE,                 R_XSTORMY16_NONE,          xstormy16_elf_howto_table },
    316  1.1  christos   { BFD_RELOC_32,                   R_XSTORMY16_32,            xstormy16_elf_howto_table },
    317  1.1  christos   { BFD_RELOC_16,                   R_XSTORMY16_16,            xstormy16_elf_howto_table },
    318  1.1  christos   { BFD_RELOC_8,                    R_XSTORMY16_8,             xstormy16_elf_howto_table },
    319  1.1  christos   { BFD_RELOC_32_PCREL,             R_XSTORMY16_PC32,          xstormy16_elf_howto_table },
    320  1.1  christos   { BFD_RELOC_16_PCREL,             R_XSTORMY16_PC16,          xstormy16_elf_howto_table },
    321  1.1  christos   { BFD_RELOC_8_PCREL,              R_XSTORMY16_PC8,           xstormy16_elf_howto_table },
    322  1.1  christos   { BFD_RELOC_XSTORMY16_REL_12,     R_XSTORMY16_REL_12,        xstormy16_elf_howto_table },
    323  1.1  christos   { BFD_RELOC_XSTORMY16_24,	    R_XSTORMY16_24,            xstormy16_elf_howto_table },
    324  1.1  christos   { BFD_RELOC_XSTORMY16_FPTR16,	    R_XSTORMY16_FPTR16,        xstormy16_elf_howto_table },
    325  1.1  christos   { BFD_RELOC_LO16,                 R_XSTORMY16_LO16,          xstormy16_elf_howto_table },
    326  1.1  christos   { BFD_RELOC_HI16,                 R_XSTORMY16_HI16,          xstormy16_elf_howto_table },
    327  1.1  christos   { BFD_RELOC_XSTORMY16_12,         R_XSTORMY16_12,            xstormy16_elf_howto_table },
    328  1.1  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.1  christos 
    379  1.1  christos static void
    380  1.1  christos xstormy16_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
    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.1  christos   else if (r_type - R_XSTORMY16_GNU_VTINHERIT
    389  1.1  christos 	   <= (unsigned int) R_XSTORMY16_GNU_VTENTRY)
    390  1.1  christos     cache_ptr->howto
    391  1.1  christos       = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
    392  1.1  christos   else
    393  1.1  christos     abort ();
    394  1.1  christos }
    395  1.1  christos 
    396  1.1  christos /* We support 16-bit pointers to code above 64k by generating a thunk
    398  1.1  christos    below 64k containing a JMPF instruction to the final address.  We
    399  1.1  christos    cannot, unfortunately, minimize the number of thunks unless the
    400  1.1  christos    -relax switch is given, as otherwise we have no idea where the
    401  1.1  christos    sections will fall in the address space.  */
    402  1.1  christos 
    403  1.1  christos static bfd_boolean
    404  1.1  christos xstormy16_elf_check_relocs (bfd *abfd,
    405  1.1  christos 			    struct bfd_link_info *info,
    406  1.1  christos 			    asection *sec,
    407  1.1  christos 			    const Elf_Internal_Rela *relocs)
    408  1.1  christos {
    409  1.1  christos   const Elf_Internal_Rela *rel, *relend;
    410  1.1  christos   struct elf_link_hash_entry **sym_hashes;
    411  1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    412  1.1  christos   bfd_vma *local_plt_offsets;
    413  1.1  christos   asection *splt;
    414  1.3  christos   bfd *dynobj;
    415  1.1  christos 
    416  1.1  christos   if (bfd_link_relocatable (info))
    417  1.1  christos     return TRUE;
    418  1.1  christos 
    419  1.1  christos   symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
    420  1.1  christos   sym_hashes = elf_sym_hashes (abfd);
    421  1.1  christos   local_plt_offsets = elf_local_got_offsets (abfd);
    422  1.1  christos   splt = NULL;
    423  1.1  christos   dynobj = elf_hash_table(info)->dynobj;
    424  1.1  christos 
    425  1.1  christos   relend = relocs + sec->reloc_count;
    426  1.1  christos   for (rel = relocs; rel < relend; ++rel)
    427  1.1  christos     {
    428  1.1  christos       unsigned long r_symndx;
    429  1.1  christos       struct elf_link_hash_entry *h;
    430  1.1  christos       bfd_vma *offset;
    431  1.1  christos 
    432  1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    433  1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    434  1.1  christos 	h = NULL;
    435  1.1  christos       else
    436  1.1  christos 	{
    437  1.1  christos 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    438  1.1  christos 	  while (h->root.type == bfd_link_hash_indirect
    439  1.3  christos 		 || h->root.type == bfd_link_hash_warning)
    440  1.3  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    441  1.3  christos 
    442  1.3  christos 	  /* PR15323, ref flags aren't set for references in the same
    443  1.1  christos 	     object.  */
    444  1.1  christos 	  h->root.non_ir_ref = 1;
    445  1.1  christos 	}
    446  1.1  christos 
    447  1.1  christos       switch (ELF32_R_TYPE (rel->r_info))
    448  1.1  christos         {
    449  1.1  christos 	  /* This relocation describes a 16-bit pointer to a function.
    450  1.1  christos 	     We may need to allocate a thunk in low memory; reserve memory
    451  1.1  christos 	     for it now.  */
    452  1.1  christos 	case R_XSTORMY16_FPTR16:
    453  1.1  christos 	  if (rel->r_addend != 0)
    454  1.1  christos 	    {
    455  1.1  christos 	      (*info->callbacks->warning)
    456  1.1  christos 		(info, _("non-zero addend in @fptr reloc"), 0,
    457  1.1  christos 		 abfd, 0, 0);
    458  1.1  christos 	    }
    459  1.1  christos 
    460  1.1  christos 	  if (dynobj == NULL)
    461  1.1  christos 	    elf_hash_table (info)->dynobj = dynobj = abfd;
    462  1.1  christos 	  if (splt == NULL)
    463  1.1  christos 	    {
    464  1.1  christos 	      splt = bfd_get_linker_section (dynobj, ".plt");
    465  1.1  christos 	      if (splt == NULL)
    466  1.1  christos 		{
    467  1.1  christos 		  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
    468  1.1  christos 				    | SEC_IN_MEMORY | SEC_LINKER_CREATED
    469  1.1  christos 				    | SEC_READONLY | SEC_CODE);
    470  1.1  christos 
    471  1.1  christos 		  splt = bfd_make_section_anyway_with_flags (dynobj, ".plt",
    472  1.1  christos 							     flags);
    473  1.1  christos 		  if (splt == NULL
    474  1.1  christos 		      || ! bfd_set_section_alignment (dynobj, splt, 1))
    475  1.1  christos 		    return FALSE;
    476  1.1  christos 		}
    477  1.1  christos 	    }
    478  1.1  christos 
    479  1.1  christos 	  if (h != NULL)
    480  1.1  christos 	    offset = &h->plt.offset;
    481  1.1  christos 	  else
    482  1.1  christos 	    {
    483  1.1  christos 	      if (local_plt_offsets == NULL)
    484  1.1  christos 		{
    485  1.1  christos 		  size_t size;
    486  1.1  christos 		  unsigned int i;
    487  1.1  christos 
    488  1.1  christos 		  size = symtab_hdr->sh_info * sizeof (bfd_vma);
    489  1.1  christos 		  local_plt_offsets = bfd_alloc (abfd, size);
    490  1.1  christos 		  if (local_plt_offsets == NULL)
    491  1.1  christos 		    return FALSE;
    492  1.1  christos 		  elf_local_got_offsets (abfd) = local_plt_offsets;
    493  1.1  christos 
    494  1.1  christos 		  for (i = 0; i < symtab_hdr->sh_info; i++)
    495  1.1  christos 		    local_plt_offsets[i] = (bfd_vma) -1;
    496  1.1  christos 		}
    497  1.1  christos 	      offset = &local_plt_offsets[r_symndx];
    498  1.1  christos 	    }
    499  1.1  christos 
    500  1.1  christos 	  if (*offset == (bfd_vma) -1)
    501  1.1  christos 	    {
    502  1.1  christos 	      *offset = splt->size;
    503  1.1  christos 	      splt->size += 4;
    504  1.1  christos 	    }
    505  1.1  christos 	  break;
    506  1.1  christos 
    507  1.1  christos 	  /* This relocation describes the C++ object vtable hierarchy.
    508  1.1  christos 	     Reconstruct it for later use during GC.  */
    509  1.1  christos         case R_XSTORMY16_GNU_VTINHERIT:
    510  1.1  christos           if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
    511  1.1  christos             return FALSE;
    512  1.1  christos           break;
    513  1.1  christos 
    514  1.1  christos 	  /* This relocation describes which C++ vtable entries are actually
    515  1.1  christos 	     used.  Record for later use during GC.  */
    516  1.1  christos         case R_XSTORMY16_GNU_VTENTRY:
    517  1.1  christos           BFD_ASSERT (h != NULL);
    518  1.1  christos           if (h != NULL
    519  1.1  christos               && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
    520  1.1  christos             return FALSE;
    521  1.1  christos           break;
    522  1.1  christos 	}
    523  1.1  christos     }
    524  1.1  christos 
    525  1.1  christos   return TRUE;
    526  1.1  christos }
    527  1.1  christos 
    528  1.1  christos /* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
    529  1.1  christos    is within the low 64k, remove any entry for it in the plt.  */
    530  1.1  christos 
    531  1.1  christos struct relax_plt_data
    532  1.1  christos {
    533  1.1  christos   asection *splt;
    534  1.1  christos   bfd_boolean *again;
    535  1.1  christos };
    536  1.1  christos 
    537  1.1  christos static bfd_boolean
    538  1.1  christos xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata)
    539  1.1  christos {
    540  1.1  christos   struct relax_plt_data *data = (struct relax_plt_data *) xdata;
    541  1.1  christos 
    542  1.1  christos   if (h->plt.offset != (bfd_vma) -1)
    543  1.1  christos     {
    544  1.1  christos       bfd_vma address;
    545  1.1  christos 
    546  1.1  christos       if (h->root.type == bfd_link_hash_undefined
    547  1.1  christos 	  || h->root.type == bfd_link_hash_undefweak)
    548  1.1  christos 	address = 0;
    549  1.1  christos       else
    550  1.1  christos 	address = (h->root.u.def.section->output_section->vma
    551  1.1  christos 		   + h->root.u.def.section->output_offset
    552  1.1  christos 		   + h->root.u.def.value);
    553  1.1  christos 
    554  1.1  christos       if (address <= 0xffff)
    555  1.1  christos 	{
    556  1.1  christos 	  h->plt.offset = -1;
    557  1.1  christos 	  data->splt->size -= 4;
    558  1.1  christos 	  *data->again = TRUE;
    559  1.1  christos 	}
    560  1.1  christos     }
    561  1.1  christos 
    562  1.1  christos   return TRUE;
    563  1.1  christos }
    564  1.1  christos 
    565  1.1  christos /* A subroutine of xstormy16_elf_relax_section.  If the global symbol H
    566  1.1  christos    previously had a plt entry, give it a new entry offset.  */
    567  1.1  christos 
    568  1.1  christos static bfd_boolean
    569  1.1  christos xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata)
    570  1.1  christos {
    571  1.1  christos   bfd_vma *entry = (bfd_vma *) xdata;
    572  1.1  christos 
    573  1.1  christos   if (h->plt.offset != (bfd_vma) -1)
    574  1.1  christos     {
    575  1.1  christos       h->plt.offset = *entry;
    576  1.1  christos       *entry += 4;
    577  1.1  christos     }
    578  1.1  christos 
    579  1.1  christos   return TRUE;
    580  1.1  christos }
    581  1.1  christos 
    582  1.1  christos static bfd_boolean
    583  1.1  christos xstormy16_elf_relax_section (bfd *dynobj,
    584  1.1  christos 			     asection *splt,
    585  1.1  christos 			     struct bfd_link_info *info,
    586  1.1  christos 			     bfd_boolean *again)
    587  1.1  christos {
    588  1.1  christos   struct relax_plt_data relax_plt_data;
    589  1.1  christos   bfd *ibfd;
    590  1.1  christos 
    591  1.1  christos   /* Assume nothing changes.  */
    592  1.3  christos   *again = FALSE;
    593  1.1  christos 
    594  1.1  christos   if (bfd_link_relocatable (info))
    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.1  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.1  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.1  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.1  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.1  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.1  christos     }
    706  1.1  christos 
    707  1.1  christos   return TRUE;
    708  1.1  christos }
    709  1.1  christos 
    710  1.1  christos static bfd_boolean
    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.1  christos 
    717  1.1  christos   if (bfd_link_relocatable (info))
    718  1.1  christos     return TRUE;
    719  1.1  christos 
    720  1.1  christos   dynobj = elf_hash_table (info)->dynobj;
    721  1.1  christos   if (dynobj == NULL)
    722  1.1  christos     return TRUE;
    723  1.1  christos 
    724  1.1  christos   splt = bfd_get_linker_section (dynobj, ".plt");
    725  1.1  christos   BFD_ASSERT (splt != NULL);
    726  1.1  christos 
    727  1.1  christos   splt->contents = bfd_zalloc (dynobj, splt->size);
    728  1.1  christos   if (splt->contents == NULL)
    729  1.1  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.1  christos    section, which means that the addend must be adjusted
    763  1.1  christos    accordingly.  */
    764  1.1  christos 
    765  1.1  christos static bfd_boolean
    766  1.1  christos xstormy16_elf_relocate_section (bfd *                   output_bfd ATTRIBUTE_UNUSED,
    767  1.1  christos 				struct bfd_link_info *  info,
    768  1.1  christos 				bfd *                   input_bfd,
    769  1.1  christos 				asection *              input_section,
    770  1.1  christos 				bfd_byte *              contents,
    771  1.1  christos 				Elf_Internal_Rela *     relocs,
    772  1.1  christos 				Elf_Internal_Sym *      local_syms,
    773  1.1  christos 				asection **             local_sections)
    774  1.1  christos {
    775  1.1  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   bfd *dynobj;
    780  1.1  christos   asection *splt;
    781  1.1  christos 
    782  1.1  christos   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    783  1.1  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   dynobj = elf_hash_table (info)->dynobj;
    787  1.1  christos   splt = NULL;
    788  1.1  christos   if (dynobj != NULL)
    789  1.1  christos     splt = bfd_get_linker_section (dynobj, ".plt");
    790  1.1  christos 
    791  1.1  christos   for (rel = relocs; rel < relend; rel ++)
    792  1.1  christos     {
    793  1.1  christos       reloc_howto_type *           howto;
    794  1.1  christos       unsigned long                r_symndx;
    795  1.1  christos       Elf_Internal_Sym *           sym;
    796  1.1  christos       asection *                   sec;
    797  1.1  christos       struct elf_link_hash_entry * h;
    798  1.1  christos       bfd_vma                      relocation;
    799  1.1  christos       bfd_reloc_status_type        r;
    800  1.1  christos       const char *                 name = NULL;
    801  1.1  christos       int                          r_type;
    802  1.1  christos 
    803  1.1  christos       r_type = ELF32_R_TYPE (rel->r_info);
    804  1.1  christos 
    805  1.1  christos       if (   r_type == R_XSTORMY16_GNU_VTINHERIT
    806  1.1  christos 	  || r_type == R_XSTORMY16_GNU_VTENTRY)
    807  1.1  christos 	continue;
    808  1.1  christos 
    809  1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    810  1.1  christos       howto  = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
    811  1.1  christos       h      = NULL;
    812  1.1  christos       sym    = NULL;
    813  1.1  christos       sec    = NULL;
    814  1.1  christos 
    815  1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    816  1.1  christos 	{
    817  1.1  christos 	  sym = local_syms + r_symndx;
    818  1.1  christos 	  sec = local_sections [r_symndx];
    819  1.1  christos 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    820  1.3  christos 	}
    821  1.1  christos       else
    822  1.1  christos 	{
    823  1.1  christos 	  bfd_boolean unresolved_reloc, warned, ignored;
    824  1.1  christos 
    825  1.3  christos 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    826  1.1  christos 				   r_symndx, symtab_hdr, sym_hashes,
    827  1.1  christos 				   h, sec, relocation,
    828  1.1  christos 				   unresolved_reloc, warned, ignored);
    829  1.1  christos 	}
    830  1.1  christos 
    831  1.1  christos       if (sec != NULL && discarded_section (sec))
    832  1.3  christos 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    833  1.1  christos 					 rel, 1, relend, howto, 0, contents);
    834  1.1  christos 
    835  1.1  christos       if (bfd_link_relocatable (info))
    836  1.1  christos 	continue;
    837  1.1  christos 
    838  1.1  christos       if (h != NULL)
    839  1.1  christos 	name = h->root.root.string;
    840  1.1  christos       else
    841  1.1  christos 	{
    842  1.1  christos 	  name = (bfd_elf_string_from_elf_section
    843  1.1  christos 		  (input_bfd, symtab_hdr->sh_link, sym->st_name));
    844  1.1  christos 	  if (name == NULL || *name == '\0')
    845  1.1  christos 	    name = bfd_section_name (input_bfd, sec);
    846  1.1  christos 	}
    847  1.1  christos 
    848  1.1  christos       switch (ELF32_R_TYPE (rel->r_info))
    849  1.1  christos 	{
    850  1.1  christos 	case R_XSTORMY16_24:
    851  1.1  christos 	  {
    852  1.1  christos 	    bfd_vma reloc = relocation + rel->r_addend;
    853  1.1  christos 	    unsigned int x;
    854  1.1  christos 
    855  1.1  christos 	    x = bfd_get_32 (input_bfd, contents + rel->r_offset);
    856  1.1  christos 	    x &= 0x0000ff00;
    857  1.1  christos 	    x |= reloc & 0xff;
    858  1.1  christos 	    x |= (reloc << 8) & 0xffff0000;
    859  1.1  christos 	    bfd_put_32 (input_bfd, x, contents + rel->r_offset);
    860  1.1  christos 
    861  1.1  christos 	    if (reloc & ~0xffffff)
    862  1.1  christos 	      r = bfd_reloc_overflow;
    863  1.1  christos 	    else
    864  1.1  christos 	      r = bfd_reloc_ok;
    865  1.1  christos 	    break;
    866  1.1  christos 	  }
    867  1.1  christos 
    868  1.1  christos 	case R_XSTORMY16_FPTR16:
    869  1.1  christos 	  {
    870  1.1  christos 	    bfd_vma *plt_offset;
    871  1.1  christos 
    872  1.1  christos 	    if (h != NULL)
    873  1.1  christos 	      plt_offset = &h->plt.offset;
    874  1.1  christos 	    else
    875  1.1  christos 	      plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
    876  1.1  christos 
    877  1.1  christos 	    if (relocation <= 0xffff)
    878  1.1  christos 	      {
    879  1.1  christos 	        /* If the symbol is in range for a 16-bit address, we should
    880  1.1  christos 		   have deallocated the plt entry in relax_section.  */
    881  1.1  christos 	        BFD_ASSERT (*plt_offset == (bfd_vma) -1);
    882  1.1  christos 	      }
    883  1.1  christos 	    else
    884  1.1  christos 	      {
    885  1.1  christos 		/* If the symbol is out of range for a 16-bit address,
    886  1.1  christos 		   we must have allocated a plt entry.  */
    887  1.1  christos 		BFD_ASSERT (*plt_offset != (bfd_vma) -1);
    888  1.1  christos 
    889  1.1  christos 		/* If this is the first time we've processed this symbol,
    890  1.1  christos 		   fill in the plt entry with the correct symbol address.  */
    891  1.1  christos 		if ((*plt_offset & 1) == 0)
    892  1.1  christos 		  {
    893  1.1  christos 		    unsigned int x;
    894  1.1  christos 
    895  1.1  christos 		    x = 0x00000200;  /* jmpf */
    896  1.1  christos 		    x |= relocation & 0xff;
    897  1.1  christos 		    x |= (relocation << 8) & 0xffff0000;
    898  1.1  christos 		    bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
    899  1.1  christos 		    *plt_offset |= 1;
    900  1.1  christos 		  }
    901  1.1  christos 
    902  1.1  christos 		relocation = (splt->output_section->vma
    903  1.1  christos 			      + splt->output_offset
    904  1.1  christos 			      + (*plt_offset & -2));
    905  1.1  christos 	      }
    906  1.1  christos 	    r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    907  1.1  christos 					  contents, rel->r_offset,
    908  1.1  christos 					  relocation, 0);
    909  1.1  christos 	    break;
    910  1.1  christos 	  }
    911  1.1  christos 
    912  1.1  christos 	default:
    913  1.1  christos 	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
    914  1.1  christos 					contents, rel->r_offset,
    915  1.1  christos 					relocation, rel->r_addend);
    916  1.1  christos 	  break;
    917  1.1  christos 	}
    918  1.1  christos 
    919  1.1  christos       if (r != bfd_reloc_ok)
    920  1.1  christos 	{
    921  1.1  christos 	  const char * msg = NULL;
    922  1.1  christos 
    923  1.1  christos 	  switch (r)
    924  1.1  christos 	    {
    925  1.1  christos 	    case bfd_reloc_overflow:
    926  1.1  christos 	      r = info->callbacks->reloc_overflow
    927  1.1  christos 		(info, (h ? &h->root : NULL), name, howto->name,
    928  1.1  christos 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    929  1.1  christos 	      break;
    930  1.1  christos 
    931  1.1  christos 	    case bfd_reloc_undefined:
    932  1.1  christos 	      r = info->callbacks->undefined_symbol
    933  1.1  christos 		(info, name, input_bfd, input_section, rel->r_offset,
    934  1.1  christos 		 TRUE);
    935  1.1  christos 	      break;
    936  1.1  christos 
    937  1.1  christos 	    case bfd_reloc_outofrange:
    938  1.1  christos 	      msg = _("internal error: out of range error");
    939  1.1  christos 	      break;
    940  1.1  christos 
    941  1.1  christos 	    case bfd_reloc_notsupported:
    942  1.1  christos 	      msg = _("internal error: unsupported relocation error");
    943  1.1  christos 	      break;
    944  1.1  christos 
    945  1.1  christos 	    case bfd_reloc_dangerous:
    946  1.1  christos 	      msg = _("internal error: dangerous relocation");
    947  1.1  christos 	      break;
    948  1.1  christos 
    949  1.1  christos 	    default:
    950  1.1  christos 	      msg = _("internal error: unknown error");
    951  1.1  christos 	      break;
    952  1.1  christos 	    }
    953  1.1  christos 
    954  1.1  christos 	  if (msg)
    955  1.1  christos 	    r = info->callbacks->warning
    956  1.1  christos 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
    957  1.1  christos 
    958  1.1  christos 	  if (! r)
    959  1.1  christos 	    return FALSE;
    960  1.1  christos 	}
    961  1.1  christos     }
    962  1.1  christos 
    963  1.1  christos   return TRUE;
    964  1.1  christos }
    965  1.1  christos 
    966  1.1  christos /* This must exist if dynobj is ever set.  */
    967  1.1  christos 
    968  1.1  christos static bfd_boolean
    969  1.1  christos xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
    970  1.1  christos 				       struct bfd_link_info *info)
    971  1.1  christos {
    972  1.1  christos   bfd *dynobj;
    973  1.1  christos   asection *splt;
    974  1.1  christos 
    975  1.1  christos   /* As an extra sanity check, verify that all plt entries have
    976  1.1  christos      been filled in.  */
    977  1.1  christos 
    978  1.1  christos   if ((dynobj = elf_hash_table (info)->dynobj) != NULL
    979  1.1  christos       && (splt = bfd_get_linker_section (dynobj, ".plt")) != NULL)
    980  1.1  christos     {
    981  1.1  christos       bfd_byte *contents = splt->contents;
    982  1.1  christos       unsigned int i, size = splt->size;
    983  1.1  christos 
    984  1.1  christos       for (i = 0; i < size; i += 4)
    985  1.1  christos 	{
    986  1.1  christos 	  unsigned int x = bfd_get_32 (dynobj, contents + i);
    987  1.1  christos 
    988  1.1  christos 	  BFD_ASSERT (x != 0);
    989  1.1  christos 	}
    990  1.1  christos     }
    991  1.1  christos 
    992  1.1  christos   return TRUE;
    993  1.1  christos }
    994  1.1  christos 
    995  1.1  christos /* Return the section that should be marked against GC for a given
    997  1.1  christos    relocation.  */
    998  1.1  christos 
    999  1.1  christos static asection *
   1000  1.1  christos xstormy16_elf_gc_mark_hook (asection *sec,
   1001  1.1  christos 			    struct bfd_link_info *info,
   1002  1.1  christos 			    Elf_Internal_Rela *rel,
   1003  1.1  christos 			    struct elf_link_hash_entry *h,
   1004  1.1  christos 			    Elf_Internal_Sym *sym)
   1005  1.1  christos {
   1006  1.1  christos   if (h != NULL)
   1007  1.1  christos     switch (ELF32_R_TYPE (rel->r_info))
   1008  1.1  christos       {
   1009  1.1  christos       case R_XSTORMY16_GNU_VTINHERIT:
   1010  1.1  christos       case R_XSTORMY16_GNU_VTENTRY:
   1011  1.1  christos 	return NULL;
   1012  1.1  christos       }
   1013  1.1  christos 
   1014  1.1  christos   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
   1015  1.1  christos }
   1016  1.1  christos 
   1017  1.3  christos #define ELF_ARCH		bfd_arch_xstormy16
   1019  1.1  christos #define ELF_MACHINE_CODE	EM_XSTORMY16
   1020  1.1  christos #define ELF_MAXPAGESIZE		0x100
   1021  1.1  christos 
   1022  1.1  christos #define TARGET_LITTLE_SYM       xstormy16_elf32_vec
   1023  1.1  christos #define TARGET_LITTLE_NAME	"elf32-xstormy16"
   1024  1.1  christos 
   1025  1.1  christos #define elf_info_to_howto_rel			NULL
   1026  1.1  christos #define elf_info_to_howto			xstormy16_info_to_howto_rela
   1027  1.1  christos #define elf_backend_relocate_section		xstormy16_elf_relocate_section
   1028  1.1  christos #define elf_backend_gc_mark_hook		xstormy16_elf_gc_mark_hook
   1029  1.1  christos #define elf_backend_check_relocs                xstormy16_elf_check_relocs
   1030  1.1  christos #define elf_backend_always_size_sections \
   1031  1.1  christos   xstormy16_elf_always_size_sections
   1032  1.1  christos #define elf_backend_omit_section_dynsym \
   1033  1.1  christos   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
   1034  1.1  christos #define elf_backend_finish_dynamic_sections \
   1035  1.1  christos   xstormy16_elf_finish_dynamic_sections
   1036  1.1  christos 
   1037  1.1  christos #define elf_backend_can_gc_sections		1
   1038  1.1  christos #define elf_backend_rela_normal			1
   1039  1.1  christos 
   1040  1.1  christos #define bfd_elf32_bfd_reloc_type_lookup		xstormy16_reloc_type_lookup
   1041                #define bfd_elf32_bfd_reloc_name_lookup \
   1042                  xstormy16_reloc_name_lookup
   1043                #define bfd_elf32_bfd_relax_section		xstormy16_elf_relax_section
   1044                
   1045                #include "elf32-target.h"
   1046