Home | History | Annotate | Line # | Download | only in bfd
elf32-xgate.c revision 1.1.1.9
      1 /* Freescale XGATE-specific support for 32-bit ELF
      2    Copyright (C) 2010-2024 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 "elf/xgate.h"
     28 #include "opcode/xgate.h"
     29 #include "libiberty.h"
     30 
     31 /* Forward declarations.  */
     32 static bfd_reloc_status_type xgate_elf_ignore_reloc
     33   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
     34 static bfd_reloc_status_type xgate_elf_special_reloc
     35   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
     36 
     37 /* Use REL instead of RELA to save space */
     38 #define USE_REL	1
     39 
     40 static reloc_howto_type elf_xgate_howto_table[] =
     41 {
     42   /* This reloc does nothing.  */
     43   HOWTO (R_XGATE_NONE, /* type */
     44 	 0, /* rightshift */
     45 	 0, /* size */
     46 	 0, /* bitsize */
     47 	 false, /* pc_relative */
     48 	 0, /* bitpos */
     49 	 complain_overflow_dont,/* complain_on_overflow */
     50 	 bfd_elf_generic_reloc, /* special_function */
     51 	 "R_XGATE_NONE", /* name */
     52 	 false, /* partial_inplace */
     53 	 0, /* src_mask */
     54 	 0, /* dst_mask */
     55 	 false), /* pcrel_offset */
     56 
     57   /* A 8 bit absolute relocation.  */
     58   HOWTO (R_XGATE_8, /* type */
     59 	 0, /* rightshift */
     60 	 1, /* size */
     61 	 8, /* bitsize */
     62 	 false, /* pc_relative */
     63 	 0, /* bitpos */
     64 	 complain_overflow_bitfield, /* complain_on_overflow */
     65 	 bfd_elf_generic_reloc, /* special_function */
     66 	 "R_XGATE_8", /* name */
     67 	 false, /* partial_inplace */
     68 	 0x00ff, /* src_mask */
     69 	 0x00ff, /* dst_mask */
     70 	 false), /* pcrel_offset */
     71 
     72   /* A 8 bit PC-rel relocation.  */
     73   HOWTO (R_XGATE_PCREL_8, /* type */
     74 	 0, /* rightshift */
     75 	 1, /* size */
     76 	 8, /* bitsize */
     77 	 true, /* pc_relative */
     78 	 0, /* bitpos */
     79 	 complain_overflow_bitfield, /* complain_on_overflow */
     80 	 bfd_elf_generic_reloc, /* special_function */
     81 	 "R_XGATE_PCREL_8", /* name */
     82 	 false, /* partial_inplace */
     83 	 0x00ff, /* src_mask */
     84 	 0x00ff, /* dst_mask */
     85 	 true), /* pcrel_offset */
     86 
     87   /* A 16 bit absolute relocation.  */
     88   HOWTO (R_XGATE_16, /* type */
     89 	 0, /* rightshift */
     90 	 2, /* size */
     91 	 16, /* bitsize */
     92 	 false, /* pc_relative */
     93 	 0, /* bitpos */
     94 	 complain_overflow_dont /*bitfield */, /* complain_on_overflow */
     95 	 bfd_elf_generic_reloc, /* special_function */
     96 	 "R_XGATE_16", /* name */
     97 	 false, /* partial_inplace */
     98 	 0xffff, /* src_mask */
     99 	 0xffff, /* dst_mask */
    100 	 false), /* pcrel_offset */
    101 
    102   /* A 32 bit absolute relocation.  This one is never used for the
    103      code relocation.  It's used by gas for -gstabs generation.  */
    104   HOWTO (R_XGATE_32, /* type */
    105 	 0, /* rightshift */
    106 	 4, /* size */
    107 	 32, /* bitsize */
    108 	 false, /* pc_relative */
    109 	 0, /* bitpos */
    110 	 complain_overflow_bitfield, /* complain_on_overflow */
    111 	 bfd_elf_generic_reloc, /* special_function */
    112 	 "R_XGATE_32", /* name */
    113 	 false, /* partial_inplace */
    114 	 0xffffffff, /* src_mask */
    115 	 0xffffffff, /* dst_mask */
    116 	 false), /* pcrel_offset */
    117 
    118   /* A 16 bit PC-rel relocation.  */
    119   HOWTO (R_XGATE_PCREL_16, /* type */
    120 	 0, /* rightshift */
    121 	 2, /* size */
    122 	 16, /* bitsize */
    123 	 true, /* pc_relative */
    124 	 0, /* bitpos */
    125 	 complain_overflow_dont, /* complain_on_overflow */
    126 	 bfd_elf_generic_reloc, /* special_function */
    127 	 "R_XGATE_PCREL_16", /* name */
    128 	 false, /* partial_inplace */
    129 	 0xffff, /* src_mask */
    130 	 0xffff, /* dst_mask */
    131 	 true), /* pcrel_offset */
    132 
    133   /* GNU extension to record C++ vtable hierarchy.  */
    134   HOWTO (R_XGATE_GNU_VTINHERIT, /* type */
    135 	 0, /* rightshift */
    136 	 2, /* size */
    137 	 0, /* bitsize */
    138 	 false, /* pc_relative */
    139 	 0, /* bitpos */
    140 	 complain_overflow_dont, /* complain_on_overflow */
    141 	 NULL, /* special_function */
    142 	 "R_XGATE_GNU_VTINHERIT", /* name */
    143 	 false, /* partial_inplace */
    144 	 0, /* src_mask */
    145 	 0, /* dst_mask */
    146 	 false), /* pcrel_offset */
    147 
    148   /* GNU extension to record C++ vtable member usage.  */
    149   HOWTO (R_XGATE_GNU_VTENTRY, /* type */
    150 	 0, /* rightshift */
    151 	 2, /* size */
    152 	 0, /* bitsize */
    153 	 false, /* pc_relative */
    154 	 0, /* bitpos */
    155 	 complain_overflow_dont, /* complain_on_overflow */
    156 	 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
    157 	 "R_XGATE_GNU_VTENTRY", /* name */
    158 	 false, /* partial_inplace */
    159 	 0, /* src_mask */
    160 	 0, /* dst_mask */
    161 	 false), /* pcrel_offset */
    162 
    163   /* A 24 bit relocation.  */
    164   HOWTO (R_XGATE_24, /* type */
    165 	 0, /* rightshift */
    166 	 2, /* size */
    167 	 16, /* bitsize */
    168 	 false, /* pc_relative */
    169 	 0, /* bitpos */
    170 	 complain_overflow_dont, /* complain_on_overflow */
    171 	 bfd_elf_generic_reloc, /* special_function */
    172 	 "R_XGATE_IMM8_LO", /* name */
    173 	 false, /* partial_inplace */
    174 	 0x00ff, /* src_mask */
    175 	 0x00ff, /* dst_mask */
    176 	 false), /* pcrel_offset */
    177 
    178   /* A 16-bit low relocation.  */
    179   HOWTO (R_XGATE_LO16, /* type */
    180 	 8, /* rightshift */
    181 	 2, /* size */
    182 	 16, /* bitsize */
    183 	 false, /* pc_relative */
    184 	 0, /* bitpos */
    185 	 complain_overflow_dont, /* complain_on_overflow */
    186 	 bfd_elf_generic_reloc, /* special_function */
    187 	 "R_XGATE_IMM8_HI", /* name */
    188 	 false, /* partial_inplace */
    189 	 0x00ff, /* src_mask */
    190 	 0x00ff, /* dst_mask */
    191 	 false), /* pcrel_offset */
    192 
    193   /* A page relocation.  */
    194   HOWTO (R_XGATE_GPAGE, /* type */
    195 	 0, /* rightshift */
    196 	 1, /* size */
    197 	 8, /* bitsize */
    198 	 false, /* pc_relative */
    199 	 0, /* bitpos */
    200 	 complain_overflow_dont, /* complain_on_overflow */
    201 	 xgate_elf_special_reloc,/* special_function */
    202 	 "R_XGATE_GPAGE", /* name */
    203 	 false, /* partial_inplace */
    204 	 0x00ff, /* src_mask */
    205 	 0x00ff, /* dst_mask */
    206 	 false), /* pcrel_offset */
    207 
    208   /* A 9 bit absolute relocation.   */
    209   HOWTO (R_XGATE_PCREL_9, /* type */
    210 	 0, /* rightshift */
    211 	 2, /* size */
    212 	 9, /* bitsize */
    213 	 true, /* pc_relative */
    214 	 0, /* bitpos */
    215 	 complain_overflow_bitfield, /* complain_on_overflow */
    216 	 bfd_elf_generic_reloc, /* special_function */
    217 	 "R_XGATE_PCREL_9", /* name */
    218 	 false, /* partial_inplace */
    219 	 0xffff, /* src_mask */
    220 	 0xffff, /* dst_mask */
    221 	 true), /* pcrel_offset */
    222 
    223   /* A 8 bit absolute relocation (upper address).  */
    224   HOWTO (R_XGATE_PCREL_10, /* type */
    225 	 8, /* rightshift */
    226 	 1, /* size */
    227 	 10, /* bitsize */
    228 	 true, /* pc_relative */
    229 	 0, /* bitpos */
    230 	 complain_overflow_dont, /* complain_on_overflow */
    231 	 bfd_elf_generic_reloc, /* special_function */
    232 	 "R_XGATE_PCREL_10", /* name */
    233 	 false, /* partial_inplace */
    234 	 0x00ff, /* src_mask */
    235 	 0x00ff, /* dst_mask */
    236 	 true), /* pcrel_offset */
    237 
    238   /* A 8 bit absolute relocation.  */
    239   HOWTO (R_XGATE_IMM8_LO, /* type */
    240 	 0, /* rightshift */
    241 	 2, /* size */
    242 	 16, /* bitsize */
    243 	 false, /* pc_relative */
    244 	 0, /* bitpos */
    245 	 complain_overflow_dont, /* complain_on_overflow */
    246 	 bfd_elf_generic_reloc, /* special_function */
    247 	 "R_XGATE_IMM8_LO", /* name */
    248 	 false, /* partial_inplace */
    249 	 0xffff, /* src_mask */
    250 	 0xffff, /* dst_mask */
    251 	 false), /* pcrel_offset */
    252 
    253   /* A 16 bit absolute relocation (upper address).  */
    254   HOWTO (R_XGATE_IMM8_HI, /* type */
    255 	 8, /* rightshift */
    256 	 2, /* size */
    257 	 16, /* bitsize */
    258 	 false, /* pc_relative */
    259 	 0, /* bitpos */
    260 	 complain_overflow_dont, /* complain_on_overflow */
    261 	 bfd_elf_generic_reloc, /* special_function */
    262 	 "R_XGATE_IMM8_HI", /* name */
    263 	 false, /* partial_inplace */
    264 	 0x00ff, /* src_mask */
    265 	 0x00ff, /* dst_mask */
    266 	 false), /* pcrel_offset */
    267 
    268   /* A 3 bit absolute relocation.  */
    269   HOWTO (R_XGATE_IMM3, /* type */
    270 	 8, /* rightshift */
    271 	 2, /* size */
    272 	 16, /* bitsize */
    273 	 false, /* pc_relative */
    274 	 0, /* bitpos */
    275 	 complain_overflow_dont, /* complain_on_overflow */
    276 	 bfd_elf_generic_reloc, /* special_function */
    277 	 "R_XGATE_IMM3", /* name */
    278 	 false, /* partial_inplace */
    279 	 0x00ff, /* src_mask */
    280 	 0x00ff, /* dst_mask */
    281 	 false), /* pcrel_offset */
    282 
    283   /* A 4 bit absolute relocation.  */
    284   HOWTO (R_XGATE_IMM4, /* type */
    285 	 8, /* rightshift */
    286 	 2, /* size */
    287 	 16, /* bitsize */
    288 	 false, /* pc_relative */
    289 	 0, /* bitpos */
    290 	 complain_overflow_dont, /* complain_on_overflow */
    291 	 bfd_elf_generic_reloc, /* special_function */
    292 	 "R_XGATE_IMM4", /* name */
    293 	 false, /* partial_inplace */
    294 	 0x00ff, /* src_mask */
    295 	 0x00ff, /* dst_mask */
    296 	 false), /* pcrel_offset */
    297 
    298   /* A 5 bit absolute relocation.  */
    299   HOWTO (R_XGATE_IMM5, /* type */
    300 	 8, /* rightshift */
    301 	 2, /* size */
    302 	 16, /* bitsize */
    303 	 false, /* pc_relative */
    304 	 0, /* bitpos */
    305 	 complain_overflow_dont, /* complain_on_overflow */
    306 	 bfd_elf_generic_reloc, /* special_function */
    307 	 "R_XGATE_IMM5", /* name */
    308 	 false, /* partial_inplace */
    309 	 0x00ff, /* src_mask */
    310 	 0x00ff, /* dst_mask */
    311 	 false), /* pcrel_offset */
    312 
    313   /* Mark beginning of a jump instruction (any form).  */
    314   HOWTO (R_XGATE_RL_JUMP, /* type */
    315 	 0, /* rightshift */
    316 	 2, /* size */
    317 	 0, /* bitsize */
    318 	 false, /* pc_relative */
    319 	 0, /* bitpos */
    320 	 complain_overflow_dont, /* complain_on_overflow */
    321 	 xgate_elf_ignore_reloc, /* special_function */
    322 	 "R_XGATE_RL_JUMP", /* name */
    323 	 true, /* partial_inplace */
    324 	 0, /* src_mask */
    325 	 0, /* dst_mask */
    326 	 true), /* pcrel_offset */
    327 
    328   /* Mark beginning of Gcc relaxation group instruction.  */
    329   HOWTO (R_XGATE_RL_GROUP, /* type */
    330 	 0, /* rightshift */
    331 	 2, /* size */
    332 	 0, /* bitsize */
    333 	 false, /* pc_relative */
    334 	 0, /* bitpos */
    335 	 complain_overflow_dont, /* complain_on_overflow */
    336 	 xgate_elf_ignore_reloc, /* special_function */
    337 	 "R_XGATE_RL_GROUP", /* name */
    338 	 true, /* partial_inplace */
    339 	 0, /* src_mask */
    340 	 0, /* dst_mask */
    341 	 true), /* pcrel_offset */
    342 };
    343 
    344 /* Map BFD reloc types to XGATE ELF reloc types.  */
    345 
    346 struct xgate_reloc_map
    347 {
    348   bfd_reloc_code_real_type bfd_reloc_val;
    349   unsigned char elf_reloc_val;
    350 };
    351 
    352 static const struct xgate_reloc_map xgate_reloc_map[] =
    353 {
    354   {BFD_RELOC_NONE, R_XGATE_NONE},
    355   {BFD_RELOC_8, R_XGATE_8},
    356   {BFD_RELOC_8_PCREL, R_XGATE_PCREL_8},
    357   {BFD_RELOC_16_PCREL, R_XGATE_PCREL_16},
    358   {BFD_RELOC_16, R_XGATE_16},
    359   {BFD_RELOC_32, R_XGATE_32},
    360 
    361   {BFD_RELOC_VTABLE_INHERIT, R_XGATE_GNU_VTINHERIT},
    362   {BFD_RELOC_VTABLE_ENTRY, R_XGATE_GNU_VTENTRY},
    363 
    364   {BFD_RELOC_XGATE_LO16, R_XGATE_LO16},
    365   {BFD_RELOC_XGATE_GPAGE, R_XGATE_GPAGE},
    366   {BFD_RELOC_XGATE_24, R_XGATE_24},
    367   {BFD_RELOC_XGATE_PCREL_9, R_XGATE_PCREL_9},
    368   {BFD_RELOC_XGATE_PCREL_10,  R_XGATE_PCREL_10},
    369   {BFD_RELOC_XGATE_IMM8_LO, R_XGATE_IMM8_LO},
    370   {BFD_RELOC_XGATE_IMM8_HI, R_XGATE_IMM8_HI},
    371   {BFD_RELOC_XGATE_IMM3, R_XGATE_IMM3},
    372   {BFD_RELOC_XGATE_IMM4, R_XGATE_IMM4},
    373   {BFD_RELOC_XGATE_IMM5, R_XGATE_IMM5},
    374 
    375   {BFD_RELOC_XGATE_RL_JUMP, R_XGATE_RL_JUMP},
    376   {BFD_RELOC_XGATE_RL_GROUP, R_XGATE_RL_GROUP},
    377 };
    378 
    379 static reloc_howto_type *
    380 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    381 				 bfd_reloc_code_real_type code)
    382 {
    383   unsigned int i;
    384 
    385   for (i = 0; i < ARRAY_SIZE (xgate_reloc_map); i++)
    386     if (xgate_reloc_map[i].bfd_reloc_val == code)
    387       return &elf_xgate_howto_table[xgate_reloc_map[i].elf_reloc_val];
    388 
    389   return NULL;
    390 }
    391 
    392 static reloc_howto_type *
    393 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    394 {
    395   unsigned int i;
    396 
    397   for (i = 0; i < ARRAY_SIZE (elf_xgate_howto_table); i++)
    398     if (elf_xgate_howto_table[i].name != NULL
    399 	&& strcasecmp (elf_xgate_howto_table[i].name, r_name) == 0)
    400       return &elf_xgate_howto_table[i];
    401 
    402   return NULL;
    403 }
    404 
    405 /* Set the howto pointer for an XGATE ELF reloc.  */
    406 
    407 static bool
    408 xgate_info_to_howto_rel (bfd *abfd,
    409 			 arelent *cache_ptr,
    410 			 Elf_Internal_Rela *dst)
    411 {
    412   unsigned int r_type;
    413 
    414   r_type = ELF32_R_TYPE (dst->r_info);
    415   if (r_type >= (unsigned int) R_XGATE_max)
    416     {
    417       /* xgettext:c-format */
    418       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    419 			  abfd, r_type);
    420       bfd_set_error (bfd_error_bad_value);
    421       return false;
    422     }
    423   cache_ptr->howto = &elf_xgate_howto_table[r_type];
    424   return true;
    425 }
    426 
    427 /* Specific sections:
    428  - The .page0 is a data section that is mapped in [0x0000..0x00FF].
    429    Page0 accesses are faster on the M68HC12.
    430  - The .vectors is the section that represents the interrupt
    431    vectors.
    432  - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
    433 static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
    434 {
    435   { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    436   { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    437   { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
    438   { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
    439 /*{ STRING_COMMA_LEN (".xgate"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
    440   TODO finish this implementation */
    441   { NULL, 0, 0, 0, 0 }
    442 };
    443 
    444 /* Hook called when reading symbols. */
    445 
    446 static void
    447 elf32_xgate_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
    448 				       asymbol *sym)
    449 {
    450   /* Mark xgate symbols.  */
    451   ((elf_symbol_type *) sym)->internal_elf_sym.st_target_internal = 1;
    452 }
    453 
    454 /* This function is used for relocs which are only used for relaxing,
    455    which the linker should otherwise ignore.  */
    456 
    457 static bfd_reloc_status_type
    458 xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
    459 			arelent *reloc_entry,
    460 			asymbol *symbol ATTRIBUTE_UNUSED,
    461 			void *data ATTRIBUTE_UNUSED,
    462 			asection *input_section,
    463 			bfd *output_bfd,
    464 			char **error_message ATTRIBUTE_UNUSED)
    465 {
    466   if (output_bfd != NULL)
    467     reloc_entry->address += input_section->output_offset;
    468   return bfd_reloc_ok;
    469 }
    470 
    471 static bfd_reloc_status_type
    472 xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
    473 			 arelent *reloc_entry ATTRIBUTE_UNUSED,
    474 			 asymbol *symbol ATTRIBUTE_UNUSED,
    475 			 void *data ATTRIBUTE_UNUSED,
    476 			 asection *input_section ATTRIBUTE_UNUSED,
    477 			 bfd *output_bfd ATTRIBUTE_UNUSED,
    478 			 char **error_message ATTRIBUTE_UNUSED)
    479 {
    480   abort ();
    481 }
    482 
    483 static bool
    484 _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
    485 {
    486   FILE *file = (FILE *) ptr;
    487 
    488   BFD_ASSERT (abfd != NULL && ptr != NULL);
    489 
    490   /* Print normal ELF private data.  */
    491   _bfd_elf_print_private_bfd_data (abfd, ptr);
    492 
    493   /* xgettext:c-format */
    494   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
    495 
    496   if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
    497     fprintf (file, _("[abi=32-bit int, "));
    498   else
    499     fprintf (file, _("[abi=16-bit int, "));
    500 
    501   if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
    502     fprintf (file, _("64-bit double, "));
    503   else
    504     fprintf (file, _("32-bit double, "));
    505   if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
    506     fprintf (file, _("cpu=XGATE]"));
    507   else
    508     fprintf (file, _("error reading cpu type from elf private data"));
    509   fputc ('\n', file);
    510 
    511   return true;
    512 }
    513 
    514 #define ELF_ARCH			     bfd_arch_xgate
    515 #define ELF_MACHINE_CODE		     EM_XGATE
    516 
    517 #define ELF_MAXPAGESIZE			     0x1000
    518 
    519 #define TARGET_BIG_SYM			     xgate_elf32_vec
    520 #define TARGET_BIG_NAME			     "elf32-xgate"
    521 
    522 #define elf_info_to_howto_rel		     xgate_info_to_howto_rel
    523 #define elf_backend_special_sections	     elf32_xgate_special_sections
    524 #define elf_backend_symbol_processing	     elf32_xgate_backend_symbol_processing
    525 #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
    526 
    527 #include "elf32-target.h"
    528