Home | History | Annotate | Line # | Download | only in bfd
elf32-xgate.c revision 1.1.1.5
      1      1.1  christos /* Freescale XGATE-specific support for 32-bit ELF
      2  1.1.1.5  christos    Copyright (C) 2010-2017 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.1.3  christos 	 3, /* size (0 = byte, 1 = short, 2 = long) */
     56  1.1.1.3  christos 	 0, /* 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.1.1.2  christos   if (r_type >= (unsigned int) R_XGATE_max)
    426  1.1.1.2  christos     {
    427  1.1.1.5  christos       /* xgettext:c-format */
    428  1.1.1.3  christos       _bfd_error_handler (_("%B: invalid XGate reloc number: %d"), abfd, r_type);
    429  1.1.1.2  christos       r_type = 0;
    430  1.1.1.2  christos     }
    431      1.1  christos   cache_ptr->howto = &elf_xgate_howto_table[r_type];
    432      1.1  christos }
    433      1.1  christos 
    434  1.1.1.2  christos /* Destroy an XGATE ELF linker hash table.  */
    435      1.1  christos 
    436  1.1.1.2  christos static void
    437  1.1.1.2  christos xgate_elf_bfd_link_hash_table_free (bfd *obfd)
    438      1.1  christos {
    439      1.1  christos   struct xgate_elf_link_hash_table *ret =
    440  1.1.1.2  christos       (struct xgate_elf_link_hash_table *) obfd->link.hash;
    441      1.1  christos 
    442      1.1  christos   bfd_hash_table_free (ret->stub_hash_table);
    443      1.1  christos   free (ret->stub_hash_table);
    444  1.1.1.2  christos   _bfd_elf_link_hash_table_free (obfd);
    445      1.1  christos }
    446      1.1  christos 
    447  1.1.1.2  christos /* Create an XGATE ELF linker hash table.  */
    448      1.1  christos 
    449      1.1  christos static struct bfd_link_hash_table*
    450      1.1  christos xgate_elf_bfd_link_hash_table_create (bfd *abfd)
    451      1.1  christos {
    452      1.1  christos   struct xgate_elf_link_hash_table *ret;
    453      1.1  christos   bfd_size_type amt = sizeof(struct xgate_elf_link_hash_table);
    454      1.1  christos 
    455      1.1  christos   ret = (struct xgate_elf_link_hash_table *) bfd_zmalloc (amt);
    456      1.1  christos   if (ret == (struct xgate_elf_link_hash_table *) NULL)
    457      1.1  christos     return NULL;
    458      1.1  christos 
    459      1.1  christos   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
    460      1.1  christos       _bfd_elf_link_hash_newfunc, sizeof(struct elf_link_hash_entry),
    461      1.1  christos       XGATE_ELF_DATA))
    462      1.1  christos     {
    463      1.1  christos       free (ret);
    464      1.1  christos       return NULL;
    465      1.1  christos     }
    466      1.1  christos 
    467      1.1  christos   /* Init the stub hash table too.  */
    468      1.1  christos   amt = sizeof(struct bfd_hash_table);
    469      1.1  christos   ret->stub_hash_table = (struct bfd_hash_table*) bfd_zmalloc (amt);
    470      1.1  christos   if (ret->stub_hash_table == NULL)
    471      1.1  christos     {
    472  1.1.1.2  christos       _bfd_elf_link_hash_table_free (abfd);
    473      1.1  christos       return NULL;
    474      1.1  christos     }
    475      1.1  christos 
    476      1.1  christos   if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc,
    477      1.1  christos       sizeof(struct elf32_xgate_stub_hash_entry)))
    478      1.1  christos     {
    479      1.1  christos       free (ret->stub_hash_table);
    480  1.1.1.2  christos       _bfd_elf_link_hash_table_free (abfd);
    481      1.1  christos       return NULL;
    482      1.1  christos     }
    483  1.1.1.2  christos   ret->root.root.hash_table_free = xgate_elf_bfd_link_hash_table_free;
    484      1.1  christos 
    485      1.1  christos   return &ret->root.root;
    486      1.1  christos }
    487      1.1  christos 
    488      1.1  christos static bfd_boolean
    489      1.1  christos xgate_elf_set_mach_from_flags (bfd *abfd ATTRIBUTE_UNUSED)
    490      1.1  christos {
    491      1.1  christos   return TRUE;
    492      1.1  christos }
    493      1.1  christos 
    494      1.1  christos /* Specific sections:
    495      1.1  christos  - The .page0 is a data section that is mapped in [0x0000..0x00FF].
    496      1.1  christos    Page0 accesses are faster on the M68HC12.
    497      1.1  christos  - The .vectors is the section that represents the interrupt
    498      1.1  christos    vectors.
    499      1.1  christos  - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
    500      1.1  christos static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
    501      1.1  christos {
    502      1.1  christos   { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    503      1.1  christos   { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    504      1.1  christos   { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
    505      1.1  christos   { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
    506      1.1  christos /*{ STRING_COMMA_LEN (".xgate"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    507      1.1  christos   TODO finish this implementation */
    508      1.1  christos   { NULL, 0, 0, 0, 0 }
    509      1.1  christos };
    510      1.1  christos 
    511      1.1  christos struct xgate_scan_param
    512      1.1  christos {
    513      1.1  christos   struct xgate_page_info* pinfo;
    514      1.1  christos   bfd_boolean use_memory_banks;
    515      1.1  christos };
    516      1.1  christos 
    517      1.1  christos /* Assorted hash table functions.  */
    518      1.1  christos 
    519      1.1  christos /* Initialize an entry in the stub hash table.  */
    520      1.1  christos 
    521      1.1  christos static struct bfd_hash_entry *
    522      1.1  christos stub_hash_newfunc (struct bfd_hash_entry *entry,
    523      1.1  christos 		   struct bfd_hash_table *table ATTRIBUTE_UNUSED,
    524      1.1  christos 		   const char *string ATTRIBUTE_UNUSED)
    525      1.1  christos {
    526      1.1  christos   return entry;
    527      1.1  christos }
    528      1.1  christos 
    529      1.1  christos /* Hook called by the linker routine which adds symbols from an object
    530      1.1  christos    file. */
    531      1.1  christos 
    532      1.1  christos bfd_boolean
    533      1.1  christos elf32_xgate_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED,
    534      1.1  christos 			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
    535      1.1  christos 			     Elf_Internal_Sym *sym,
    536      1.1  christos 			     const char **namep ATTRIBUTE_UNUSED,
    537      1.1  christos 			     flagword *flagsp ATTRIBUTE_UNUSED,
    538      1.1  christos 			     asection **secp ATTRIBUTE_UNUSED,
    539      1.1  christos 			     bfd_vma *valp ATTRIBUTE_UNUSED)
    540      1.1  christos {
    541      1.1  christos   /* For some reason the st_target_internal value is not retained
    542      1.1  christos      after xgate_frob_symbol is called, hence this temp hack.  */
    543      1.1  christos   sym->st_target_internal = 1;
    544      1.1  christos   return TRUE;
    545      1.1  christos }
    546      1.1  christos 
    547      1.1  christos /* External entry points for sizing and building linker stubs.  */
    548      1.1  christos 
    549      1.1  christos /* Set up various things so that we can make a list of input sections
    550      1.1  christos    for each output section included in the link.  Returns -1 on error,
    551      1.1  christos    0 when no stubs will be needed, and 1 on success.  */
    552      1.1  christos 
    553      1.1  christos int
    554      1.1  christos elf32_xgate_setup_section_lists (bfd *output_bfd ATTRIBUTE_UNUSED,
    555      1.1  christos 				 struct bfd_link_info *info ATTRIBUTE_UNUSED)
    556      1.1  christos {
    557      1.1  christos   return 1;
    558      1.1  christos }
    559      1.1  christos 
    560      1.1  christos /* Determine and set the size of the stub section for a final link.
    561      1.1  christos    The basic idea here is to examine all the relocations looking for
    562      1.1  christos    PC-relative calls to a target that is unreachable with any "9-bit PC-REL"
    563      1.1  christos    instruction.  */
    564      1.1  christos 
    565      1.1  christos bfd_boolean
    566      1.1  christos elf32_xgate_size_stubs (bfd *output_bfd ATTRIBUTE_UNUSED,
    567      1.1  christos 			bfd *stub_bfd ATTRIBUTE_UNUSED,
    568      1.1  christos 			struct bfd_link_info *info ATTRIBUTE_UNUSED,
    569      1.1  christos 			asection * (*add_stub_section) (const char*, asection*) ATTRIBUTE_UNUSED)
    570      1.1  christos {
    571      1.1  christos   return FALSE;
    572      1.1  christos }
    573      1.1  christos 
    574      1.1  christos /* Build all the stubs associated with the current output file.  The
    575      1.1  christos    stubs are kept in a hash table attached to the main linker hash
    576      1.1  christos    table.  This function is called via xgateelf_finish in the
    577      1.1  christos    linker.  */
    578      1.1  christos 
    579      1.1  christos bfd_boolean
    580      1.1  christos elf32_xgate_build_stubs (bfd *abfd ATTRIBUTE_UNUSED,
    581      1.1  christos 			 struct bfd_link_info *info ATTRIBUTE_UNUSED)
    582      1.1  christos {
    583      1.1  christos   return TRUE;
    584      1.1  christos }
    585      1.1  christos 
    586      1.1  christos void
    587      1.1  christos xgate_elf_get_bank_parameters (struct bfd_link_info *info ATTRIBUTE_UNUSED)
    588      1.1  christos {
    589      1.1  christos   return;
    590      1.1  christos }
    591      1.1  christos 
    592      1.1  christos /* This function is used for relocs which are only used for relaxing,
    593      1.1  christos    which the linker should otherwise ignore.  */
    594      1.1  christos 
    595      1.1  christos bfd_reloc_status_type
    596      1.1  christos xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
    597      1.1  christos 			arelent *reloc_entry,
    598      1.1  christos 			asymbol *symbol ATTRIBUTE_UNUSED,
    599      1.1  christos 			void *data ATTRIBUTE_UNUSED,
    600      1.1  christos 			asection *input_section,
    601      1.1  christos 			bfd *output_bfd,
    602      1.1  christos 			char **error_message ATTRIBUTE_UNUSED)
    603      1.1  christos {
    604      1.1  christos   if (output_bfd != NULL)
    605      1.1  christos     reloc_entry->address += input_section->output_offset;
    606      1.1  christos   return bfd_reloc_ok;
    607      1.1  christos }
    608      1.1  christos 
    609      1.1  christos bfd_reloc_status_type
    610      1.1  christos xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
    611      1.1  christos 			 arelent *reloc_entry ATTRIBUTE_UNUSED,
    612      1.1  christos 			 asymbol *symbol ATTRIBUTE_UNUSED,
    613      1.1  christos 			 void *data ATTRIBUTE_UNUSED,
    614      1.1  christos 			 asection *input_section ATTRIBUTE_UNUSED,
    615      1.1  christos 			 bfd *output_bfd ATTRIBUTE_UNUSED,
    616      1.1  christos 			 char **error_message ATTRIBUTE_UNUSED)
    617      1.1  christos {
    618      1.1  christos   abort ();
    619      1.1  christos }
    620      1.1  christos 
    621      1.1  christos /* Look through the relocs for a section during the first phase.
    622      1.1  christos    Since we don't do .gots or .plts, we just need to consider the
    623      1.1  christos    virtual table relocs for gc.  */
    624      1.1  christos 
    625      1.1  christos bfd_boolean
    626      1.1  christos elf32_xgate_check_relocs (bfd *abfd ATTRIBUTE_UNUSED,
    627      1.1  christos 			  struct bfd_link_info *info ATTRIBUTE_UNUSED,
    628      1.1  christos 			  asection *sec ATTRIBUTE_UNUSED,
    629      1.1  christos 			  const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
    630      1.1  christos {
    631      1.1  christos   return TRUE;
    632      1.1  christos }
    633      1.1  christos 
    634      1.1  christos /* Relocate a XGATE/S12x ELF section.  */
    635      1.1  christos 
    636      1.1  christos bfd_boolean
    637      1.1  christos elf32_xgate_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
    638      1.1  christos 			      struct bfd_link_info *info ATTRIBUTE_UNUSED,
    639      1.1  christos 			      bfd *input_bfd ATTRIBUTE_UNUSED,
    640      1.1  christos 			      asection *input_section ATTRIBUTE_UNUSED,
    641      1.1  christos 			      bfd_byte *contents ATTRIBUTE_UNUSED,
    642      1.1  christos 			      Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED,
    643      1.1  christos 			      Elf_Internal_Sym *local_syms ATTRIBUTE_UNUSED,
    644      1.1  christos 			      asection **local_sections ATTRIBUTE_UNUSED)
    645      1.1  christos {
    646      1.1  christos   return TRUE;
    647      1.1  christos }
    648      1.1  christos 
    649      1.1  christos /* Set and control ELF flags in ELF header.  */
    650      1.1  christos 
    651      1.1  christos bfd_boolean
    652      1.1  christos _bfd_xgate_elf_set_private_flags (bfd *abfd ATTRIBUTE_UNUSED,
    653      1.1  christos 				  flagword flags ATTRIBUTE_UNUSED)
    654      1.1  christos {
    655      1.1  christos   return TRUE;
    656      1.1  christos }
    657      1.1  christos 
    658      1.1  christos bfd_boolean
    659      1.1  christos _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
    660      1.1  christos {
    661      1.1  christos   FILE *file = (FILE *) ptr;
    662      1.1  christos 
    663      1.1  christos   BFD_ASSERT (abfd != NULL && ptr != NULL);
    664      1.1  christos 
    665      1.1  christos   /* Print normal ELF private data.  */
    666      1.1  christos   _bfd_elf_print_private_bfd_data (abfd, ptr);
    667      1.1  christos 
    668      1.1  christos   /* xgettext:c-format */
    669      1.1  christos   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
    670      1.1  christos 
    671      1.1  christos   if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
    672      1.1  christos     fprintf (file, _("[abi=32-bit int, "));
    673      1.1  christos   else
    674      1.1  christos     fprintf (file, _("[abi=16-bit int, "));
    675      1.1  christos 
    676      1.1  christos   if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
    677      1.1  christos     fprintf (file, _("64-bit double, "));
    678      1.1  christos   else
    679      1.1  christos     fprintf (file, _("32-bit double, "));
    680      1.1  christos   if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
    681      1.1  christos     fprintf (file, _("cpu=XGATE]"));
    682      1.1  christos   else
    683      1.1  christos     fprintf (file, _("error reading cpu type from elf private data"));
    684      1.1  christos   fputc ('\n', file);
    685      1.1  christos 
    686      1.1  christos   return TRUE;
    687      1.1  christos }
    688      1.1  christos 
    689      1.1  christos void
    690      1.1  christos elf32_xgate_post_process_headers (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
    691      1.1  christos {
    692      1.1  christos 
    693      1.1  christos }
    694      1.1  christos 
    695      1.1  christos #define ELF_ARCH                             bfd_arch_xgate
    696      1.1  christos #define ELF_MACHINE_CODE                     EM_XGATE
    697      1.1  christos #define ELF_TARGET_ID                        XGATE_ELF_DATA
    698      1.1  christos 
    699      1.1  christos #define ELF_MAXPAGESIZE                      0x1000
    700      1.1  christos 
    701  1.1.1.2  christos #define TARGET_BIG_SYM                       xgate_elf32_vec
    702      1.1  christos #define TARGET_BIG_NAME                      "elf32-xgate"
    703      1.1  christos 
    704      1.1  christos #define elf_info_to_howto                    0
    705      1.1  christos #define elf_info_to_howto_rel                xgate_info_to_howto_rel
    706      1.1  christos #define elf_backend_check_relocs             elf32_xgate_check_relocs
    707      1.1  christos #define elf_backend_relocate_section         elf32_xgate_relocate_section
    708      1.1  christos #define elf_backend_object_p                 xgate_elf_set_mach_from_flags
    709      1.1  christos #define elf_backend_final_write_processing   0
    710      1.1  christos #define elf_backend_can_gc_sections          1
    711      1.1  christos #define elf_backend_special_sections         elf32_xgate_special_sections
    712      1.1  christos #define elf_backend_post_process_headers     elf32_xgate_post_process_headers
    713      1.1  christos #define elf_backend_add_symbol_hook          elf32_xgate_add_symbol_hook
    714      1.1  christos 
    715      1.1  christos #define bfd_elf32_bfd_link_hash_table_create xgate_elf_bfd_link_hash_table_create
    716      1.1  christos #define bfd_elf32_bfd_set_private_flags      _bfd_xgate_elf_set_private_flags
    717      1.1  christos #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
    718      1.1  christos 
    719      1.1  christos #define xgate_stub_hash_lookup(table, string, create, copy)	\
    720      1.1  christos     ((struct elf32_xgate_stub_hash_entry *) \
    721      1.1  christos         bfd_hash_lookup ((table), (string), (create), (copy)))
    722      1.1  christos 
    723      1.1  christos #include "elf32-target.h"
    724