Home | History | Annotate | Line # | Download | only in bfd
elf32-xgate.c revision 1.3
      1  1.1  christos /* Freescale XGATE-specific support for 32-bit ELF
      2  1.3  christos    Copyright (C) 2010-2015 Free Software Foundation, Inc.
      3  1.1  christos    Contributed by Sean Keys(skeys (at) ipdatasys.com)
      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 "bfdlink.h"
     25  1.1  christos #include "libbfd.h"
     26  1.1  christos #include "elf-bfd.h"
     27  1.1  christos #include "elf32-xgate.h"
     28  1.1  christos #include "elf/xgate.h"
     29  1.1  christos #include "opcode/xgate.h"
     30  1.1  christos #include "libiberty.h"
     31  1.1  christos 
     32  1.1  christos /* Relocation functions.  */
     33  1.1  christos static reloc_howto_type *
     34  1.1  christos bfd_elf32_bfd_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
     35  1.1  christos static reloc_howto_type *
     36  1.1  christos bfd_elf32_bfd_reloc_name_lookup (bfd *, const char *);
     37  1.1  christos static void
     38  1.1  christos xgate_info_to_howto_rel (bfd *, arelent *, Elf_Internal_Rela *);
     39  1.1  christos static bfd_boolean
     40  1.1  christos xgate_elf_set_mach_from_flags (bfd *);
     41  1.1  christos static struct bfd_hash_entry *
     42  1.1  christos stub_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *,
     43  1.1  christos     const char *);
     44  1.1  christos static struct bfd_link_hash_table*
     45  1.1  christos xgate_elf_bfd_link_hash_table_create (bfd *);
     46  1.1  christos 
     47  1.1  christos /* Use REL instead of RELA to save space */
     48  1.1  christos #define USE_REL	1
     49  1.1  christos 
     50  1.1  christos static reloc_howto_type elf_xgate_howto_table[] =
     51  1.1  christos {
     52  1.1  christos   /* This reloc does nothing.  */
     53  1.1  christos   HOWTO (R_XGATE_NONE, /* type */
     54  1.1  christos 	 0, /* rightshift */
     55  1.1  christos 	 2, /* size (0 = byte, 1 = short, 2 = long) */
     56  1.1  christos 	 32, /* bitsize */
     57  1.1  christos 	 FALSE, /* pc_relative */
     58  1.1  christos 	 0, /* bitpos */
     59  1.1  christos 	 complain_overflow_dont,/* complain_on_overflow */
     60  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
     61  1.1  christos 	 "R_XGATE_NONE", /* name */
     62  1.1  christos 	 FALSE, /* partial_inplace */
     63  1.1  christos 	 0, /* src_mask */
     64  1.1  christos 	 0, /* dst_mask */
     65  1.1  christos 	 FALSE), /* pcrel_offset */
     66  1.1  christos 
     67  1.1  christos   /* A 8 bit absolute relocation.  */
     68  1.1  christos   HOWTO (R_XGATE_8, /* type */
     69  1.1  christos 	 0, /* rightshift */
     70  1.1  christos 	 0, /* size (0 = byte, 1 = short, 2 = long) */
     71  1.1  christos 	 8, /* bitsize */
     72  1.1  christos 	 FALSE, /* pc_relative */
     73  1.1  christos 	 0, /* bitpos */
     74  1.1  christos 	 complain_overflow_bitfield, /* complain_on_overflow */
     75  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
     76  1.1  christos 	 "R_XGATE_8", /* name */
     77  1.1  christos 	 FALSE, /* partial_inplace */
     78  1.1  christos 	 0x00ff, /* src_mask */
     79  1.1  christos 	 0x00ff, /* dst_mask */
     80  1.1  christos 	 FALSE), /* pcrel_offset */
     81  1.1  christos 
     82  1.1  christos   /* A 8 bit PC-rel relocation.  */
     83  1.1  christos   HOWTO (R_XGATE_PCREL_8, /* type */
     84  1.1  christos 	 0, /* rightshift */
     85  1.1  christos 	 0, /* size (0 = byte, 1 = short, 2 = long) */
     86  1.1  christos 	 8, /* bitsize */
     87  1.1  christos 	 TRUE, /* pc_relative */
     88  1.1  christos 	 0, /* bitpos */
     89  1.1  christos 	 complain_overflow_bitfield, /* complain_on_overflow */
     90  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
     91  1.1  christos 	 "R_XGATE_PCREL_8", /* name */
     92  1.1  christos 	 FALSE, /* partial_inplace */
     93  1.1  christos 	 0x00ff, /* src_mask */
     94  1.1  christos 	 0x00ff, /* dst_mask */
     95  1.1  christos 	 TRUE), /* pcrel_offset */
     96  1.1  christos 
     97  1.1  christos   /* A 16 bit absolute relocation.  */
     98  1.1  christos   HOWTO (R_XGATE_16, /* type */
     99  1.1  christos 	 0, /* rightshift */
    100  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    101  1.1  christos 	 16, /* bitsize */
    102  1.1  christos 	 FALSE, /* pc_relative */
    103  1.1  christos 	 0, /* bitpos */
    104  1.1  christos 	 complain_overflow_dont /*bitfield */, /* complain_on_overflow */
    105  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    106  1.1  christos 	 "R_XGATE_16", /* name */
    107  1.1  christos 	 FALSE, /* partial_inplace */
    108  1.1  christos 	 0xffff, /* src_mask */
    109  1.1  christos 	 0xffff, /* dst_mask */
    110  1.1  christos 	 FALSE), /* pcrel_offset */
    111  1.1  christos 
    112  1.1  christos   /* A 32 bit absolute relocation.  This one is never used for the
    113  1.1  christos      code relocation.  It's used by gas for -gstabs generation.  */
    114  1.1  christos   HOWTO (R_XGATE_32, /* type */
    115  1.1  christos 	 0, /* rightshift */
    116  1.1  christos 	 2, /* size (0 = byte, 1 = short, 2 = long) */
    117  1.1  christos 	 32, /* bitsize */
    118  1.1  christos 	 FALSE, /* pc_relative */
    119  1.1  christos 	 0, /* bitpos */
    120  1.1  christos 	 complain_overflow_bitfield, /* complain_on_overflow */
    121  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    122  1.1  christos 	 "R_XGATE_32", /* name */
    123  1.1  christos 	 FALSE, /* partial_inplace */
    124  1.1  christos 	 0xffffffff, /* src_mask */
    125  1.1  christos 	 0xffffffff, /* dst_mask */
    126  1.1  christos 	 FALSE), /* pcrel_offset */
    127  1.1  christos 
    128  1.1  christos   /* A 16 bit PC-rel relocation.  */
    129  1.1  christos   HOWTO (R_XGATE_PCREL_16, /* type */
    130  1.1  christos 	 0, /* rightshift */
    131  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    132  1.1  christos 	 16, /* bitsize */
    133  1.1  christos 	 TRUE, /* pc_relative */
    134  1.1  christos 	 0, /* bitpos */
    135  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    136  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    137  1.1  christos 	 "R_XGATE_PCREL_16", /* name */
    138  1.1  christos 	 FALSE, /* partial_inplace */
    139  1.1  christos 	 0xffff, /* src_mask */
    140  1.1  christos 	 0xffff, /* dst_mask */
    141  1.1  christos 	 TRUE), /* pcrel_offset */
    142  1.1  christos 
    143  1.1  christos   /* GNU extension to record C++ vtable hierarchy.  */
    144  1.1  christos   HOWTO (R_XGATE_GNU_VTINHERIT, /* type */
    145  1.1  christos 	 0, /* rightshift */
    146  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    147  1.1  christos 	 0, /* bitsize */
    148  1.1  christos 	 FALSE, /* pc_relative */
    149  1.1  christos 	 0, /* bitpos */
    150  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    151  1.1  christos 	 NULL, /* special_function */
    152  1.1  christos 	 "R_XGATE_GNU_VTINHERIT", /* name */
    153  1.1  christos 	 FALSE, /* partial_inplace */
    154  1.1  christos 	 0, /* src_mask */
    155  1.1  christos 	 0, /* dst_mask */
    156  1.1  christos 	 FALSE), /* pcrel_offset */
    157  1.1  christos 
    158  1.1  christos   /* GNU extension to record C++ vtable member usage.  */
    159  1.1  christos   HOWTO (R_XGATE_GNU_VTENTRY, /* type */
    160  1.1  christos 	 0, /* rightshift */
    161  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    162  1.1  christos 	 0, /* bitsize */
    163  1.1  christos 	 FALSE, /* pc_relative */
    164  1.1  christos 	 0, /* bitpos */
    165  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    166  1.1  christos 	 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
    167  1.1  christos 	 "R_XGATE_GNU_VTENTRY", /* name */
    168  1.1  christos 	 FALSE, /* partial_inplace */
    169  1.1  christos 	 0, /* src_mask */
    170  1.1  christos 	 0, /* dst_mask */
    171  1.1  christos 	 FALSE), /* pcrel_offset */
    172  1.1  christos 
    173  1.1  christos   /* A 24 bit relocation.  */
    174  1.1  christos   HOWTO (R_XGATE_24, /* type */
    175  1.1  christos 	 0, /* rightshift */
    176  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    177  1.1  christos 	 16, /* bitsize */
    178  1.1  christos 	 FALSE, /* pc_relative */
    179  1.1  christos 	 0, /* bitpos */
    180  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    181  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    182  1.1  christos 	 "R_XGATE_IMM8_LO", /* name */
    183  1.1  christos 	 FALSE, /* partial_inplace */
    184  1.1  christos 	 0x00ff, /* src_mask */
    185  1.1  christos 	 0x00ff, /* dst_mask */
    186  1.1  christos 	 FALSE), /* pcrel_offset */
    187  1.1  christos 
    188  1.1  christos   /* A 16-bit low relocation.  */
    189  1.1  christos   HOWTO (R_XGATE_LO16, /* type */
    190  1.1  christos 	 8, /* rightshift */
    191  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    192  1.1  christos 	 16, /* bitsize */
    193  1.1  christos 	 FALSE, /* pc_relative */
    194  1.1  christos 	 0, /* bitpos */
    195  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    196  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    197  1.1  christos 	 "R_XGATE_IMM8_HI", /* name */
    198  1.1  christos 	 FALSE, /* partial_inplace */
    199  1.1  christos 	 0x00ff, /* src_mask */
    200  1.1  christos 	 0x00ff, /* dst_mask */
    201  1.1  christos 	 FALSE), /* pcrel_offset */
    202  1.1  christos 
    203  1.1  christos   /* A page relocation.  */
    204  1.1  christos   HOWTO (R_XGATE_GPAGE, /* type */
    205  1.1  christos 	 0, /* rightshift */
    206  1.1  christos 	 0, /* size (0 = byte, 1 = short, 2 = long) */
    207  1.1  christos 	 8, /* bitsize */
    208  1.1  christos 	 FALSE, /* pc_relative */
    209  1.1  christos 	 0, /* bitpos */
    210  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    211  1.1  christos 	 xgate_elf_special_reloc,/* special_function */
    212  1.1  christos 	 "R_XGATE_GPAGE", /* name */
    213  1.1  christos 	 FALSE, /* partial_inplace */
    214  1.1  christos 	 0x00ff, /* src_mask */
    215  1.1  christos 	 0x00ff, /* dst_mask */
    216  1.1  christos 	 FALSE), /* pcrel_offset */
    217  1.1  christos 
    218  1.1  christos   /* A 9 bit absolute relocation.   */
    219  1.1  christos   HOWTO (R_XGATE_PCREL_9, /* type */
    220  1.1  christos 	 0, /* rightshift */
    221  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    222  1.1  christos 	 9, /* bitsize */
    223  1.1  christos 	 TRUE, /* pc_relative */
    224  1.1  christos 	 0, /* bitpos */
    225  1.1  christos 	 complain_overflow_bitfield, /* complain_on_overflow */
    226  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    227  1.1  christos 	 "R_XGATE_PCREL_9", /* name */
    228  1.1  christos 	 FALSE, /* partial_inplace */
    229  1.1  christos 	 0xffff, /* src_mask */
    230  1.1  christos 	 0xffff, /* dst_mask */
    231  1.1  christos 	 TRUE), /* pcrel_offset */
    232  1.1  christos 
    233  1.1  christos   /* A 8 bit absolute relocation (upper address).  */
    234  1.1  christos   HOWTO (R_XGATE_PCREL_10, /* type */
    235  1.1  christos 	 8, /* rightshift */
    236  1.1  christos 	 0, /* size (0 = byte, 1 = short, 2 = long) */
    237  1.1  christos 	 10, /* bitsize */
    238  1.1  christos 	 TRUE, /* pc_relative */
    239  1.1  christos 	 0, /* bitpos */
    240  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    241  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    242  1.1  christos 	 "R_XGATE_PCREL_10", /* name */
    243  1.1  christos 	 FALSE, /* partial_inplace */
    244  1.1  christos 	 0x00ff, /* src_mask */
    245  1.1  christos 	 0x00ff, /* dst_mask */
    246  1.1  christos 	 TRUE), /* pcrel_offset */
    247  1.1  christos 
    248  1.1  christos   /* A 8 bit absolute relocation.  */
    249  1.1  christos   HOWTO (R_XGATE_IMM8_LO, /* type */
    250  1.1  christos 	 0, /* rightshift */
    251  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    252  1.1  christos 	 16, /* bitsize */
    253  1.1  christos 	 FALSE, /* pc_relative */
    254  1.1  christos 	 0, /* bitpos */
    255  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    256  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    257  1.1  christos 	 "R_XGATE_IMM8_LO", /* name */
    258  1.1  christos 	 FALSE, /* partial_inplace */
    259  1.1  christos 	 0xffff, /* src_mask */
    260  1.1  christos 	 0xffff, /* dst_mask */
    261  1.1  christos 	 FALSE), /* pcrel_offset */
    262  1.1  christos 
    263  1.1  christos   /* A 16 bit absolute relocation (upper address).  */
    264  1.1  christos   HOWTO (R_XGATE_IMM8_HI, /* type */
    265  1.1  christos 	 8, /* rightshift */
    266  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    267  1.1  christos 	 16, /* bitsize */
    268  1.1  christos 	 FALSE, /* pc_relative */
    269  1.1  christos 	 0, /* bitpos */
    270  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    271  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    272  1.1  christos 	 "R_XGATE_IMM8_HI", /* name */
    273  1.1  christos 	 FALSE, /* partial_inplace */
    274  1.1  christos 	 0x00ff, /* src_mask */
    275  1.1  christos 	 0x00ff, /* dst_mask */
    276  1.1  christos 	 FALSE), /* pcrel_offset */
    277  1.1  christos 
    278  1.1  christos   /* A 3 bit absolute relocation.  */
    279  1.1  christos   HOWTO (R_XGATE_IMM3, /* type */
    280  1.1  christos 	 8, /* rightshift */
    281  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    282  1.1  christos 	 16, /* bitsize */
    283  1.1  christos 	 FALSE, /* pc_relative */
    284  1.1  christos 	 0, /* bitpos */
    285  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    286  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    287  1.1  christos 	 "R_XGATE_IMM3", /* name */
    288  1.1  christos 	 FALSE, /* partial_inplace */
    289  1.1  christos 	 0x00ff, /* src_mask */
    290  1.1  christos 	 0x00ff, /* dst_mask */
    291  1.1  christos 	 FALSE), /* pcrel_offset */
    292  1.1  christos 
    293  1.1  christos   /* A 4 bit absolute relocation.  */
    294  1.1  christos   HOWTO (R_XGATE_IMM4, /* type */
    295  1.1  christos 	 8, /* rightshift */
    296  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    297  1.1  christos 	 16, /* bitsize */
    298  1.1  christos 	 FALSE, /* pc_relative */
    299  1.1  christos 	 0, /* bitpos */
    300  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    301  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    302  1.1  christos 	 "R_XGATE_IMM4", /* name */
    303  1.1  christos 	 FALSE, /* partial_inplace */
    304  1.1  christos 	 0x00ff, /* src_mask */
    305  1.1  christos 	 0x00ff, /* dst_mask */
    306  1.1  christos 	 FALSE), /* pcrel_offset */
    307  1.1  christos 
    308  1.1  christos   /* A 5 bit absolute relocation.  */
    309  1.1  christos   HOWTO (R_XGATE_IMM5, /* type */
    310  1.1  christos 	 8, /* rightshift */
    311  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    312  1.1  christos 	 16, /* bitsize */
    313  1.1  christos 	 FALSE, /* pc_relative */
    314  1.1  christos 	 0, /* bitpos */
    315  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    316  1.1  christos 	 bfd_elf_generic_reloc, /* special_function */
    317  1.1  christos 	 "R_XGATE_IMM5", /* name */
    318  1.1  christos 	 FALSE, /* partial_inplace */
    319  1.1  christos 	 0x00ff, /* src_mask */
    320  1.1  christos 	 0x00ff, /* dst_mask */
    321  1.1  christos 	 FALSE), /* pcrel_offset */
    322  1.1  christos 
    323  1.1  christos   /* Mark beginning of a jump instruction (any form).  */
    324  1.1  christos   HOWTO (R_XGATE_RL_JUMP, /* type */
    325  1.1  christos 	 0, /* rightshift */
    326  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    327  1.1  christos 	 0, /* bitsize */
    328  1.1  christos 	 FALSE, /* pc_relative */
    329  1.1  christos 	 0, /* bitpos */
    330  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    331  1.1  christos 	 xgate_elf_ignore_reloc, /* special_function */
    332  1.1  christos 	 "R_XGATE_RL_JUMP", /* name */
    333  1.1  christos 	 TRUE, /* partial_inplace */
    334  1.1  christos 	 0, /* src_mask */
    335  1.1  christos 	 0, /* dst_mask */
    336  1.1  christos 	 TRUE), /* pcrel_offset */
    337  1.1  christos 
    338  1.1  christos   /* Mark beginning of Gcc relaxation group instruction.  */
    339  1.1  christos   HOWTO (R_XGATE_RL_GROUP, /* type */
    340  1.1  christos 	 0, /* rightshift */
    341  1.1  christos 	 1, /* size (0 = byte, 1 = short, 2 = long) */
    342  1.1  christos 	 0, /* bitsize */
    343  1.1  christos 	 FALSE, /* pc_relative */
    344  1.1  christos 	 0, /* bitpos */
    345  1.1  christos 	 complain_overflow_dont, /* complain_on_overflow */
    346  1.1  christos 	 xgate_elf_ignore_reloc, /* special_function */
    347  1.1  christos 	 "R_XGATE_RL_GROUP", /* name */
    348  1.1  christos 	 TRUE, /* partial_inplace */
    349  1.1  christos 	 0, /* src_mask */
    350  1.1  christos 	 0, /* dst_mask */
    351  1.1  christos 	 TRUE), /* pcrel_offset */
    352  1.1  christos };
    353  1.1  christos 
    354  1.1  christos /* Map BFD reloc types to XGATE ELF reloc types.  */
    355  1.1  christos 
    356  1.1  christos struct xgate_reloc_map
    357  1.1  christos {
    358  1.1  christos   bfd_reloc_code_real_type bfd_reloc_val;
    359  1.1  christos   unsigned char elf_reloc_val;
    360  1.1  christos };
    361  1.1  christos 
    362  1.1  christos static const struct xgate_reloc_map xgate_reloc_map[] =
    363  1.1  christos {
    364  1.1  christos   {BFD_RELOC_NONE, R_XGATE_NONE},
    365  1.1  christos   {BFD_RELOC_8, R_XGATE_8},
    366  1.1  christos   {BFD_RELOC_8_PCREL, R_XGATE_PCREL_8},
    367  1.1  christos   {BFD_RELOC_16_PCREL, R_XGATE_PCREL_16},
    368  1.1  christos   {BFD_RELOC_16, R_XGATE_16},
    369  1.1  christos   {BFD_RELOC_32, R_XGATE_32},
    370  1.1  christos 
    371  1.1  christos   {BFD_RELOC_VTABLE_INHERIT, R_XGATE_GNU_VTINHERIT},
    372  1.1  christos   {BFD_RELOC_VTABLE_ENTRY, R_XGATE_GNU_VTENTRY},
    373  1.1  christos 
    374  1.1  christos   {BFD_RELOC_XGATE_LO16, R_XGATE_LO16},
    375  1.1  christos   {BFD_RELOC_XGATE_GPAGE, R_XGATE_GPAGE},
    376  1.1  christos   {BFD_RELOC_XGATE_24, R_XGATE_24},
    377  1.1  christos   {BFD_RELOC_XGATE_PCREL_9, R_XGATE_PCREL_9},
    378  1.1  christos   {BFD_RELOC_XGATE_PCREL_10,  R_XGATE_PCREL_10},
    379  1.1  christos   {BFD_RELOC_XGATE_IMM8_LO, R_XGATE_IMM8_LO},
    380  1.1  christos   {BFD_RELOC_XGATE_IMM8_HI, R_XGATE_IMM8_HI},
    381  1.1  christos   {BFD_RELOC_XGATE_IMM3, R_XGATE_IMM3},
    382  1.1  christos   {BFD_RELOC_XGATE_IMM4, R_XGATE_IMM4},
    383  1.1  christos   {BFD_RELOC_XGATE_IMM5, R_XGATE_IMM5},
    384  1.1  christos 
    385  1.1  christos   {BFD_RELOC_XGATE_RL_JUMP, R_XGATE_RL_JUMP},
    386  1.1  christos   {BFD_RELOC_XGATE_RL_GROUP, R_XGATE_RL_GROUP},
    387  1.1  christos };
    388  1.1  christos 
    389  1.1  christos static reloc_howto_type *
    390  1.1  christos bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    391  1.1  christos 				 bfd_reloc_code_real_type code)
    392  1.1  christos {
    393  1.1  christos   unsigned int i;
    394  1.1  christos 
    395  1.1  christos   for (i = 0; i < ARRAY_SIZE (xgate_reloc_map); i++)
    396  1.1  christos     if (xgate_reloc_map[i].bfd_reloc_val == code)
    397  1.1  christos       return &elf_xgate_howto_table[xgate_reloc_map[i].elf_reloc_val];
    398  1.1  christos 
    399  1.1  christos   return NULL;
    400  1.1  christos }
    401  1.1  christos 
    402  1.1  christos static reloc_howto_type *
    403  1.1  christos bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    404  1.1  christos {
    405  1.1  christos   unsigned int i;
    406  1.1  christos 
    407  1.1  christos   for (i = 0; i < ARRAY_SIZE (elf_xgate_howto_table); i++)
    408  1.1  christos     if (elf_xgate_howto_table[i].name != NULL
    409  1.1  christos         && strcasecmp (elf_xgate_howto_table[i].name, r_name) == 0)
    410  1.1  christos       return &elf_xgate_howto_table[i];
    411  1.1  christos 
    412  1.1  christos   return NULL;
    413  1.1  christos }
    414  1.1  christos 
    415  1.1  christos /* Set the howto pointer for an XGATE ELF reloc.  */
    416  1.1  christos 
    417  1.1  christos static void
    418  1.1  christos xgate_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
    419  1.1  christos 			 arelent *cache_ptr,
    420  1.1  christos 			 Elf_Internal_Rela *dst)
    421  1.1  christos {
    422  1.1  christos   unsigned int r_type;
    423  1.1  christos 
    424  1.1  christos   r_type = ELF32_R_TYPE (dst->r_info);
    425  1.3  christos   if (r_type >= (unsigned int) R_XGATE_max)
    426  1.3  christos     {
    427  1.3  christos       _bfd_error_handler (_("%A: invalid XGate reloc number: %d"), abfd, r_type);
    428  1.3  christos       r_type = 0;
    429  1.3  christos     }
    430  1.1  christos   cache_ptr->howto = &elf_xgate_howto_table[r_type];
    431  1.1  christos }
    432  1.1  christos 
    433  1.3  christos /* Destroy an XGATE ELF linker hash table.  */
    434  1.1  christos 
    435  1.3  christos static void
    436  1.3  christos xgate_elf_bfd_link_hash_table_free (bfd *obfd)
    437  1.1  christos {
    438  1.1  christos   struct xgate_elf_link_hash_table *ret =
    439  1.3  christos       (struct xgate_elf_link_hash_table *) obfd->link.hash;
    440  1.1  christos 
    441  1.1  christos   bfd_hash_table_free (ret->stub_hash_table);
    442  1.1  christos   free (ret->stub_hash_table);
    443  1.3  christos   _bfd_elf_link_hash_table_free (obfd);
    444  1.1  christos }
    445  1.1  christos 
    446  1.3  christos /* Create an XGATE ELF linker hash table.  */
    447  1.1  christos 
    448  1.1  christos static struct bfd_link_hash_table*
    449  1.1  christos xgate_elf_bfd_link_hash_table_create (bfd *abfd)
    450  1.1  christos {
    451  1.1  christos   struct xgate_elf_link_hash_table *ret;
    452  1.1  christos   bfd_size_type amt = sizeof(struct xgate_elf_link_hash_table);
    453  1.1  christos 
    454  1.1  christos   ret = (struct xgate_elf_link_hash_table *) bfd_zmalloc (amt);
    455  1.1  christos   if (ret == (struct xgate_elf_link_hash_table *) NULL)
    456  1.1  christos     return NULL;
    457  1.1  christos 
    458  1.1  christos   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
    459  1.1  christos       _bfd_elf_link_hash_newfunc, sizeof(struct elf_link_hash_entry),
    460  1.1  christos       XGATE_ELF_DATA))
    461  1.1  christos     {
    462  1.1  christos       free (ret);
    463  1.1  christos       return NULL;
    464  1.1  christos     }
    465  1.1  christos 
    466  1.1  christos   /* Init the stub hash table too.  */
    467  1.1  christos   amt = sizeof(struct bfd_hash_table);
    468  1.1  christos   ret->stub_hash_table = (struct bfd_hash_table*) bfd_zmalloc (amt);
    469  1.1  christos   if (ret->stub_hash_table == NULL)
    470  1.1  christos     {
    471  1.3  christos       _bfd_elf_link_hash_table_free (abfd);
    472  1.1  christos       return NULL;
    473  1.1  christos     }
    474  1.1  christos 
    475  1.1  christos   if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
    476  1.1  christos       sizeof(struct elf32_xgate_stub_hash_entry)))
    477  1.1  christos     {
    478  1.1  christos       free (ret->stub_hash_table);
    479  1.3  christos       _bfd_elf_link_hash_table_free (abfd);
    480  1.1  christos       return NULL;
    481  1.1  christos     }
    482  1.3  christos   ret->root.root.hash_table_free = xgate_elf_bfd_link_hash_table_free;
    483  1.1  christos 
    484  1.1  christos   return &ret->root.root;
    485  1.1  christos }
    486  1.1  christos 
    487  1.1  christos static bfd_boolean
    488  1.1  christos xgate_elf_set_mach_from_flags (bfd *abfd ATTRIBUTE_UNUSED)
    489  1.1  christos {
    490  1.1  christos   return TRUE;
    491  1.1  christos }
    492  1.1  christos 
    493  1.1  christos /* Specific sections:
    494  1.1  christos  - The .page0 is a data section that is mapped in [0x0000..0x00FF].
    495  1.1  christos    Page0 accesses are faster on the M68HC12.
    496  1.1  christos  - The .vectors is the section that represents the interrupt
    497  1.1  christos    vectors.
    498  1.1  christos  - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
    499  1.1  christos static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
    500  1.1  christos {
    501  1.1  christos   { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    502  1.1  christos   { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    503  1.1  christos   { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
    504  1.1  christos   { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
    505  1.1  christos /*{ STRING_COMMA_LEN (".xgate"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    506  1.1  christos   TODO finish this implementation */
    507  1.1  christos   { NULL, 0, 0, 0, 0 }
    508  1.1  christos };
    509  1.1  christos 
    510  1.1  christos struct xgate_scan_param
    511  1.1  christos {
    512  1.1  christos   struct xgate_page_info* pinfo;
    513  1.1  christos   bfd_boolean use_memory_banks;
    514  1.1  christos };
    515  1.1  christos 
    516  1.1  christos /* Assorted hash table functions.  */
    517  1.1  christos 
    518  1.1  christos /* Initialize an entry in the stub hash table.  */
    519  1.1  christos 
    520  1.1  christos static struct bfd_hash_entry *
    521  1.1  christos stub_hash_newfunc (struct bfd_hash_entry *entry,
    522  1.1  christos 		   struct bfd_hash_table *table ATTRIBUTE_UNUSED,
    523  1.1  christos 		   const char *string ATTRIBUTE_UNUSED)
    524  1.1  christos {
    525  1.1  christos   return entry;
    526  1.1  christos }
    527  1.1  christos 
    528  1.1  christos /* Hook called by the linker routine which adds symbols from an object
    529  1.1  christos    file. */
    530  1.1  christos 
    531  1.1  christos bfd_boolean
    532  1.1  christos elf32_xgate_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED,
    533  1.1  christos 			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
    534  1.1  christos 			     Elf_Internal_Sym *sym,
    535  1.1  christos 			     const char **namep ATTRIBUTE_UNUSED,
    536  1.1  christos 			     flagword *flagsp ATTRIBUTE_UNUSED,
    537  1.1  christos 			     asection **secp ATTRIBUTE_UNUSED,
    538  1.1  christos 			     bfd_vma *valp ATTRIBUTE_UNUSED)
    539  1.1  christos {
    540  1.1  christos   /* For some reason the st_target_internal value is not retained
    541  1.1  christos      after xgate_frob_symbol is called, hence this temp hack.  */
    542  1.1  christos   sym->st_target_internal = 1;
    543  1.1  christos   return TRUE;
    544  1.1  christos }
    545  1.1  christos 
    546  1.1  christos /* External entry points for sizing and building linker stubs.  */
    547  1.1  christos 
    548  1.1  christos /* Set up various things so that we can make a list of input sections
    549  1.1  christos    for each output section included in the link.  Returns -1 on error,
    550  1.1  christos    0 when no stubs will be needed, and 1 on success.  */
    551  1.1  christos 
    552  1.1  christos int
    553  1.1  christos elf32_xgate_setup_section_lists (bfd *output_bfd ATTRIBUTE_UNUSED,
    554  1.1  christos 				 struct bfd_link_info *info ATTRIBUTE_UNUSED)
    555  1.1  christos {
    556  1.1  christos   return 1;
    557  1.1  christos }
    558  1.1  christos 
    559  1.1  christos /* Determine and set the size of the stub section for a final link.
    560  1.1  christos    The basic idea here is to examine all the relocations looking for
    561  1.1  christos    PC-relative calls to a target that is unreachable with any "9-bit PC-REL"
    562  1.1  christos    instruction.  */
    563  1.1  christos 
    564  1.1  christos bfd_boolean
    565  1.1  christos elf32_xgate_size_stubs (bfd *output_bfd ATTRIBUTE_UNUSED,
    566  1.1  christos 			bfd *stub_bfd ATTRIBUTE_UNUSED,
    567  1.1  christos 			struct bfd_link_info *info ATTRIBUTE_UNUSED,
    568  1.1  christos 			asection * (*add_stub_section) (const char*, asection*) ATTRIBUTE_UNUSED)
    569  1.1  christos {
    570  1.1  christos   return FALSE;
    571  1.1  christos }
    572  1.1  christos 
    573  1.1  christos /* Build all the stubs associated with the current output file.  The
    574  1.1  christos    stubs are kept in a hash table attached to the main linker hash
    575  1.1  christos    table.  This function is called via xgateelf_finish in the
    576  1.1  christos    linker.  */
    577  1.1  christos 
    578  1.1  christos bfd_boolean
    579  1.1  christos elf32_xgate_build_stubs (bfd *abfd ATTRIBUTE_UNUSED,
    580  1.1  christos 			 struct bfd_link_info *info ATTRIBUTE_UNUSED)
    581  1.1  christos {
    582  1.1  christos   return TRUE;
    583  1.1  christos }
    584  1.1  christos 
    585  1.1  christos void
    586  1.1  christos xgate_elf_get_bank_parameters (struct bfd_link_info *info ATTRIBUTE_UNUSED)
    587  1.1  christos {
    588  1.1  christos   return;
    589  1.1  christos }
    590  1.1  christos 
    591  1.1  christos /* This function is used for relocs which are only used for relaxing,
    592  1.1  christos    which the linker should otherwise ignore.  */
    593  1.1  christos 
    594  1.1  christos bfd_reloc_status_type
    595  1.1  christos xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
    596  1.1  christos 			arelent *reloc_entry,
    597  1.1  christos 			asymbol *symbol ATTRIBUTE_UNUSED,
    598  1.1  christos 			void *data ATTRIBUTE_UNUSED,
    599  1.1  christos 			asection *input_section,
    600  1.1  christos 			bfd *output_bfd,
    601  1.1  christos 			char **error_message ATTRIBUTE_UNUSED)
    602  1.1  christos {
    603  1.1  christos   if (output_bfd != NULL)
    604  1.1  christos     reloc_entry->address += input_section->output_offset;
    605  1.1  christos   return bfd_reloc_ok;
    606  1.1  christos }
    607  1.1  christos 
    608  1.1  christos bfd_reloc_status_type
    609  1.1  christos xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
    610  1.1  christos 			 arelent *reloc_entry ATTRIBUTE_UNUSED,
    611  1.1  christos 			 asymbol *symbol ATTRIBUTE_UNUSED,
    612  1.1  christos 			 void *data ATTRIBUTE_UNUSED,
    613  1.1  christos 			 asection *input_section ATTRIBUTE_UNUSED,
    614  1.1  christos 			 bfd *output_bfd ATTRIBUTE_UNUSED,
    615  1.1  christos 			 char **error_message ATTRIBUTE_UNUSED)
    616  1.1  christos {
    617  1.1  christos   abort ();
    618  1.1  christos }
    619  1.1  christos 
    620  1.1  christos /* Look through the relocs for a section during the first phase.
    621  1.1  christos    Since we don't do .gots or .plts, we just need to consider the
    622  1.1  christos    virtual table relocs for gc.  */
    623  1.1  christos 
    624  1.1  christos bfd_boolean
    625  1.1  christos elf32_xgate_check_relocs (bfd *abfd ATTRIBUTE_UNUSED,
    626  1.1  christos 			  struct bfd_link_info *info ATTRIBUTE_UNUSED,
    627  1.1  christos 			  asection *sec ATTRIBUTE_UNUSED,
    628  1.1  christos 			  const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
    629  1.1  christos {
    630  1.1  christos   return TRUE;
    631  1.1  christos }
    632  1.1  christos 
    633  1.1  christos /* Relocate a XGATE/S12x ELF section.  */
    634  1.1  christos 
    635  1.1  christos bfd_boolean
    636  1.1  christos elf32_xgate_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
    637  1.1  christos 			      struct bfd_link_info *info ATTRIBUTE_UNUSED,
    638  1.1  christos 			      bfd *input_bfd ATTRIBUTE_UNUSED,
    639  1.1  christos 			      asection *input_section ATTRIBUTE_UNUSED,
    640  1.1  christos 			      bfd_byte *contents ATTRIBUTE_UNUSED,
    641  1.1  christos 			      Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED,
    642  1.1  christos 			      Elf_Internal_Sym *local_syms ATTRIBUTE_UNUSED,
    643  1.1  christos 			      asection **local_sections ATTRIBUTE_UNUSED)
    644  1.1  christos {
    645  1.1  christos   return TRUE;
    646  1.1  christos }
    647  1.1  christos 
    648  1.1  christos /* Set and control ELF flags in ELF header.  */
    649  1.1  christos 
    650  1.1  christos bfd_boolean
    651  1.1  christos _bfd_xgate_elf_set_private_flags (bfd *abfd ATTRIBUTE_UNUSED,
    652  1.1  christos 				  flagword flags ATTRIBUTE_UNUSED)
    653  1.1  christos {
    654  1.1  christos   return TRUE;
    655  1.1  christos }
    656  1.1  christos 
    657  1.1  christos /* Merge backend specific data from an object file to the output
    658  1.1  christos    object file when linking.  */
    659  1.1  christos 
    660  1.1  christos bfd_boolean
    661  1.1  christos _bfd_xgate_elf_merge_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
    662  1.1  christos 				       bfd *obfd ATTRIBUTE_UNUSED)
    663  1.1  christos {
    664  1.1  christos   return TRUE;
    665  1.1  christos }
    666  1.1  christos 
    667  1.1  christos bfd_boolean
    668  1.1  christos _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
    669  1.1  christos {
    670  1.1  christos   FILE *file = (FILE *) ptr;
    671  1.1  christos 
    672  1.1  christos   BFD_ASSERT (abfd != NULL && ptr != NULL);
    673  1.1  christos 
    674  1.1  christos   /* Print normal ELF private data.  */
    675  1.1  christos   _bfd_elf_print_private_bfd_data (abfd, ptr);
    676  1.1  christos 
    677  1.1  christos   /* xgettext:c-format */
    678  1.1  christos   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
    679  1.1  christos 
    680  1.1  christos   if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
    681  1.1  christos     fprintf (file, _("[abi=32-bit int, "));
    682  1.1  christos   else
    683  1.1  christos     fprintf (file, _("[abi=16-bit int, "));
    684  1.1  christos 
    685  1.1  christos   if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
    686  1.1  christos     fprintf (file, _("64-bit double, "));
    687  1.1  christos   else
    688  1.1  christos     fprintf (file, _("32-bit double, "));
    689  1.1  christos   if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
    690  1.1  christos     fprintf (file, _("cpu=XGATE]"));
    691  1.1  christos   else
    692  1.1  christos     fprintf (file, _("error reading cpu type from elf private data"));
    693  1.1  christos   fputc ('\n', file);
    694  1.1  christos 
    695  1.1  christos   return TRUE;
    696  1.1  christos }
    697  1.1  christos 
    698  1.1  christos void
    699  1.1  christos elf32_xgate_post_process_headers (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
    700  1.1  christos {
    701  1.1  christos 
    702  1.1  christos }
    703  1.1  christos 
    704  1.1  christos #define ELF_ARCH                             bfd_arch_xgate
    705  1.1  christos #define ELF_MACHINE_CODE                     EM_XGATE
    706  1.1  christos #define ELF_TARGET_ID                        XGATE_ELF_DATA
    707  1.1  christos 
    708  1.1  christos #define ELF_MAXPAGESIZE                      0x1000
    709  1.1  christos 
    710  1.3  christos #define TARGET_BIG_SYM                       xgate_elf32_vec
    711  1.1  christos #define TARGET_BIG_NAME                      "elf32-xgate"
    712  1.1  christos 
    713  1.1  christos #define elf_info_to_howto                    0
    714  1.1  christos #define elf_info_to_howto_rel                xgate_info_to_howto_rel
    715  1.1  christos #define elf_backend_check_relocs             elf32_xgate_check_relocs
    716  1.1  christos #define elf_backend_relocate_section         elf32_xgate_relocate_section
    717  1.1  christos #define elf_backend_object_p                 xgate_elf_set_mach_from_flags
    718  1.1  christos #define elf_backend_final_write_processing   0
    719  1.1  christos #define elf_backend_can_gc_sections          1
    720  1.1  christos #define elf_backend_special_sections         elf32_xgate_special_sections
    721  1.1  christos #define elf_backend_post_process_headers     elf32_xgate_post_process_headers
    722  1.1  christos #define elf_backend_add_symbol_hook          elf32_xgate_add_symbol_hook
    723  1.1  christos 
    724  1.1  christos #define bfd_elf32_bfd_link_hash_table_create xgate_elf_bfd_link_hash_table_create
    725  1.1  christos #define bfd_elf32_bfd_merge_private_bfd_data _bfd_xgate_elf_merge_private_bfd_data
    726  1.1  christos #define bfd_elf32_bfd_set_private_flags      _bfd_xgate_elf_set_private_flags
    727  1.1  christos #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
    728  1.1  christos 
    729  1.1  christos #define xgate_stub_hash_lookup(table, string, create, copy)	\
    730  1.1  christos     ((struct elf32_xgate_stub_hash_entry *) \
    731  1.1  christos         bfd_hash_lookup ((table), (string), (create), (copy)))
    732  1.1  christos 
    733  1.1  christos #include "elf32-target.h"
    734