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