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