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