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