Home | History | Annotate | Line # | Download | only in bfd
      1 /* Morpho Technologies MT specific support for 32-bit ELF
      2    Copyright (C) 2001-2024 Free Software Foundation, Inc.
      3 
      4    This file is part of BFD, the Binary File Descriptor library.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, write to the Free Software
     18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19    MA 02110-1301, USA.  */
     20 
     21 #include "sysdep.h"
     22 #include "bfd.h"
     23 #include "libbfd.h"
     24 #include "elf-bfd.h"
     25 #include "elf/mt.h"
     26 
     27 /* Prototypes.  */
     28 static reloc_howto_type * mt_reloc_type_lookup
     29   (bfd *, bfd_reloc_code_real_type);
     30 
     31 static bool mt_info_to_howto_rela
     32   (bfd *, arelent *, Elf_Internal_Rela *);
     33 
     34 static bfd_reloc_status_type mt_elf_relocate_hi16
     35   (bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma);
     36 
     37 static bfd_reloc_status_type mt_final_link_relocate
     38   (reloc_howto_type *, bfd *, asection *, bfd_byte *,
     39    Elf_Internal_Rela *, bfd_vma);
     40 
     41 static int mt_elf_relocate_section
     42   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
     43    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
     44 
     45 /* Relocation tables.  */
     46 static reloc_howto_type mt_elf_howto_table [] =
     47 {
     48   /* This reloc does nothing.  */
     49   HOWTO (R_MT_NONE,	      /* type */
     50 	  0,			  /* rightshift */
     51 	  0,			  /* size */
     52 	  0,			  /* bitsize */
     53 	  false,		  /* pc_relative */
     54 	  0,			  /* bitpos */
     55 	  complain_overflow_dont, /* complain_on_overflow */
     56 	  bfd_elf_generic_reloc,  /* special_function */
     57 	  "R_MT_NONE",		/* name */
     58 	  false,		  /* partial_inplace */
     59 	  0 ,			  /* src_mask */
     60 	  0,			  /* dst_mask */
     61 	  false),		  /* pcrel_offset */
     62 
     63   /* A 16 bit absolute relocation.  */
     64   HOWTO (R_MT_16,	      /* type */
     65 	  0,			  /* rightshift */
     66 	  4,			  /* size */
     67 	  16,			  /* bitsize */
     68 	  false,		  /* pc_relative */
     69 	  0,			  /* bitpos */
     70 	  complain_overflow_dont, /* complain_on_overflow */
     71 	  bfd_elf_generic_reloc,  /* special_function */
     72 	  "R_MT_16",		/* name */
     73 	  false,		  /* partial_inplace */
     74 	  0 ,			  /* src_mask */
     75 	  0xffff,		  /* dst_mask */
     76 	  false),		  /* pcrel_offset */
     77 
     78   /* A 32 bit absolute relocation.  */
     79   HOWTO (R_MT_32,	      /* type */
     80 	  0,			  /* rightshift */
     81 	  4,			  /* size */
     82 	  32,			  /* bitsize */
     83 	  false,		  /* pc_relative */
     84 	  0,			  /* bitpos */
     85 	  complain_overflow_dont, /* complain_on_overflow */
     86 	  bfd_elf_generic_reloc,  /* special_function */
     87 	  "R_MT_32",		/* name */
     88 	  false,		  /* partial_inplace */
     89 	  0 ,			  /* src_mask */
     90 	  0xffffffff,		  /* dst_mask */
     91 	  false),		  /* pcrel_offset */
     92 
     93   /* A 32 bit pc-relative relocation.  */
     94   HOWTO (R_MT_32_PCREL,	      /* type */
     95 	  0,			  /* rightshift */
     96 	  4,			  /* size */
     97 	  32,			  /* bitsize */
     98 	  true,			  /* pc_relative */
     99 	  0,			  /* bitpos */
    100 	  complain_overflow_dont, /* complain_on_overflow */
    101 	  bfd_elf_generic_reloc,  /* special_function */
    102 	  "R_MT_32_PCREL",    /* name */
    103 	  false,		  /* partial_inplace */
    104 	  0 ,			  /* src_mask */
    105 	  0xffffffff,		  /* dst_mask */
    106 	  true),		  /* pcrel_offset */
    107 
    108   /* A 16 bit pc-relative relocation.  */
    109   HOWTO (R_MT_PC16,	      /* type */
    110 	  0,			  /* rightshift */
    111 	  4,			  /* size */
    112 	  16,			  /* bitsize */
    113 	  true,			  /* pc_relative */
    114 	  0,			  /* bitpos */
    115 	  complain_overflow_signed, /* complain_on_overflow */
    116 	  bfd_elf_generic_reloc,  /* special_function */
    117 	  "R_MT_PC16",		/* name */
    118 	  false,		  /* partial_inplace */
    119 	  0,			  /* src_mask */
    120 	  0xffff,		  /* dst_mask */
    121 	  true),		  /* pcrel_offset */
    122 
    123   /* high 16 bits of symbol value.  */
    124   HOWTO (R_MT_HI16,	     /* type */
    125 	 0,			/* rightshift */
    126 	 4,			/* size */
    127 	 16,			/* bitsize */
    128 	 false,			/* pc_relative */
    129 	 0,			/* bitpos */
    130 	 complain_overflow_dont, /* complain_on_overflow */
    131 	 bfd_elf_generic_reloc, /* special_function */
    132 	 "R_MT_HI16",	     /* name */
    133 	 false,			 /* partial_inplace */
    134 	 0xffff0000,		/* src_mask */
    135 	 0xffff0000,		/* dst_mask */
    136 	 false),		/* pcrel_offset */
    137 
    138   /* Low 16 bits of symbol value.  */
    139   HOWTO (R_MT_LO16,	     /* type */
    140 	 0,			/* rightshift */
    141 	 4,			/* size */
    142 	 16,			/* bitsize */
    143 	 false,			/* pc_relative */
    144 	 0,			/* bitpos */
    145 	 complain_overflow_dont, /* complain_on_overflow */
    146 	 bfd_elf_generic_reloc, /* special_function */
    147 	 "R_MT_LO16",	     /* name */
    148 	 false,			 /* partial_inplace */
    149 	 0xffff,		/* src_mask */
    150 	 0xffff,		/* dst_mask */
    151 	 false),		/* pcrel_offset */
    152 };
    153 
    154 /* Map BFD reloc types to MT ELF reloc types.  */
    155 
    156 static reloc_howto_type *
    157 mt_reloc_type_lookup
    158     (bfd *		      abfd ATTRIBUTE_UNUSED,
    159      bfd_reloc_code_real_type code)
    160 {
    161   /* Note that the mt_elf_howto_table is indxed by the R_
    162      constants.  Thus, the order that the howto records appear in the
    163      table *must* match the order of the relocation types defined in
    164      include/elf/mt.h.  */
    165 
    166   switch (code)
    167     {
    168     case BFD_RELOC_NONE:
    169       return &mt_elf_howto_table[ (int) R_MT_NONE];
    170     case BFD_RELOC_16:
    171       return &mt_elf_howto_table[ (int) R_MT_16];
    172     case BFD_RELOC_32:
    173       return &mt_elf_howto_table[ (int) R_MT_32];
    174     case BFD_RELOC_32_PCREL:
    175       return &mt_elf_howto_table[ (int) R_MT_32_PCREL];
    176     case BFD_RELOC_16_PCREL:
    177       return &mt_elf_howto_table[ (int) R_MT_PC16];
    178     case BFD_RELOC_HI16:
    179       return &mt_elf_howto_table[ (int) R_MT_HI16];
    180     case BFD_RELOC_LO16:
    181       return &mt_elf_howto_table[ (int) R_MT_LO16];
    182 
    183     default:
    184       /* Pacify gcc -Wall.  */
    185       return NULL;
    186     }
    187   return NULL;
    188 }
    189 
    190 static reloc_howto_type *
    191 mt_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    192 		      const char *r_name)
    193 {
    194   unsigned int i;
    195 
    196   for (i = 0;
    197        i < sizeof (mt_elf_howto_table) / sizeof (mt_elf_howto_table[0]);
    198        i++)
    199     if (mt_elf_howto_table[i].name != NULL
    200 	&& strcasecmp (mt_elf_howto_table[i].name, r_name) == 0)
    201       return &mt_elf_howto_table[i];
    202 
    203   return NULL;
    204 }
    205 
    206 bfd_reloc_status_type
    207 mt_elf_relocate_hi16
    208     (bfd *		 input_bfd,
    209      Elf_Internal_Rela * relhi,
    210      bfd_byte *		 contents,
    211      bfd_vma		 value)
    212 {
    213   bfd_vma insn;
    214 
    215   insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
    216 
    217   value += relhi->r_addend;
    218   value >>= 16;
    219   insn = ((insn & ~0xFFFF) | value);
    220 
    221   bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
    222   return bfd_reloc_ok;
    223 }
    224 
    225 /* XXX: The following code is the result of a cut&paste.  This unfortunate
    227    practice is very widespread in the various target back-end files.  */
    228 
    229 /* Set the howto pointer for a MT ELF reloc.  */
    230 
    231 static bool
    232 mt_info_to_howto_rela (bfd *abfd,
    233 		       arelent *cache_ptr,
    234 		       Elf_Internal_Rela *dst)
    235 {
    236   unsigned int r_type;
    237 
    238   r_type = ELF32_R_TYPE (dst->r_info);
    239   if (r_type >= (unsigned int) R_MT_max)
    240     {
    241       /* xgettext:c-format */
    242       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    243 			  abfd, r_type);
    244       bfd_set_error (bfd_error_bad_value);
    245       return false;
    246     }
    247   cache_ptr->howto = & mt_elf_howto_table [r_type];
    248   return true;
    249 }
    250 
    251 /* Perform a single relocation.  By default we use the standard BFD
    252    routines.  */
    253 
    254 static bfd_reloc_status_type
    255 mt_final_link_relocate
    256     (reloc_howto_type *	 howto,
    257      bfd *		 input_bfd,
    258      asection *		 input_section,
    259      bfd_byte *		 contents,
    260      Elf_Internal_Rela * rel,
    261      bfd_vma		 relocation)
    262 {
    263   return _bfd_final_link_relocate (howto, input_bfd, input_section,
    264 				   contents, rel->r_offset,
    265 				   relocation, rel->r_addend);
    266 }
    267 
    268 /* Relocate a MT ELF section.
    269    There is some attempt to make this function usable for many architectures,
    270    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
    271    if only to serve as a learning tool.
    272 
    273    The RELOCATE_SECTION function is called by the new ELF backend linker
    274    to handle the relocations for a section.
    275 
    276    The relocs are always passed as Rela structures; if the section
    277    actually uses Rel structures, the r_addend field will always be
    278    zero.
    279 
    280    This function is responsible for adjusting the section contents as
    281    necessary, and (if using Rela relocs and generating a relocatable
    282    output file) adjusting the reloc addend as necessary.
    283 
    284    This function does not have to worry about setting the reloc
    285    address or the reloc symbol index.
    286 
    287    LOCAL_SYMS is a pointer to the swapped in local symbols.
    288 
    289    LOCAL_SECTIONS is an array giving the section in the input file
    290    corresponding to the st_shndx field of each local symbol.
    291 
    292    The global hash table entry for the global symbols can be found
    293    via elf_sym_hashes (input_bfd).
    294 
    295    When generating relocatable output, this function must handle
    296    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    297    going to be the section symbol corresponding to the output
    298    section, which means that the addend must be adjusted
    299    accordingly.  */
    300 
    301 static int
    302 mt_elf_relocate_section
    303     (bfd *		     output_bfd ATTRIBUTE_UNUSED,
    304      struct bfd_link_info *  info,
    305      bfd *		     input_bfd,
    306      asection *		     input_section,
    307      bfd_byte *		     contents,
    308      Elf_Internal_Rela *     relocs,
    309      Elf_Internal_Sym *	     local_syms,
    310      asection **	     local_sections)
    311 {
    312   Elf_Internal_Shdr *		symtab_hdr;
    313   struct elf_link_hash_entry ** sym_hashes;
    314   Elf_Internal_Rela *		rel;
    315   Elf_Internal_Rela *		relend;
    316 
    317   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    318   sym_hashes = elf_sym_hashes (input_bfd);
    319   relend     = relocs + input_section->reloc_count;
    320 
    321   for (rel = relocs; rel < relend; rel ++)
    322     {
    323       reloc_howto_type *	   howto;
    324       unsigned long		   r_symndx;
    325       Elf_Internal_Sym *	   sym;
    326       asection *		   sec;
    327       struct elf_link_hash_entry * h;
    328       bfd_vma			   relocation;
    329       bfd_reloc_status_type	   r;
    330       const char *		   name = NULL;
    331       int			   r_type;
    332 
    333       r_type = ELF32_R_TYPE (rel->r_info);
    334 
    335       r_symndx = ELF32_R_SYM (rel->r_info);
    336 
    337       howto  = mt_elf_howto_table + ELF32_R_TYPE (rel->r_info);
    338       h      = NULL;
    339       sym    = NULL;
    340       sec    = NULL;
    341 
    342       if (r_symndx < symtab_hdr->sh_info)
    343 	{
    344 	  sym = local_syms + r_symndx;
    345 	  sec = local_sections [r_symndx];
    346 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    347 
    348 	  name = bfd_elf_string_from_elf_section
    349 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    350 	  name = name == NULL ? bfd_section_name (sec) : name;
    351 	}
    352       else
    353 	{
    354 	  bool unresolved_reloc;
    355 	  bool warned, ignored;
    356 
    357 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    358 				   r_symndx, symtab_hdr, sym_hashes,
    359 				   h, sec, relocation,
    360 				   unresolved_reloc, warned, ignored);
    361 
    362 	  name = h->root.root.string;
    363 	}
    364 
    365       if (sec != NULL && discarded_section (sec))
    366 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    367 					 rel, 1, relend, howto, 0, contents);
    368 
    369       if (bfd_link_relocatable (info))
    370 	continue;
    371 
    372       /* Finally, the sole MT-specific part.  */
    373       switch (r_type)
    374 	{
    375 	case R_MT_HI16:
    376 	  r = mt_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
    377 	  break;
    378 	default:
    379 	  r = mt_final_link_relocate (howto, input_bfd, input_section,
    380 					  contents, rel, relocation);
    381 	  break;
    382 	}
    383 
    384 
    385       if (r != bfd_reloc_ok)
    386 	{
    387 	  const char * msg = (const char *) NULL;
    388 
    389 	  switch (r)
    390 	    {
    391 	    case bfd_reloc_overflow:
    392 	      (*info->callbacks->reloc_overflow)
    393 		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
    394 		 input_bfd, input_section, rel->r_offset);
    395 	      break;
    396 
    397 	    case bfd_reloc_undefined:
    398 	      (*info->callbacks->undefined_symbol)
    399 		(info, name, input_bfd, input_section, rel->r_offset, true);
    400 	      break;
    401 
    402 	    case bfd_reloc_outofrange:
    403 	      msg = _("internal error: out of range error");
    404 	      break;
    405 
    406 	    case bfd_reloc_dangerous:
    407 	      msg = _("internal error: dangerous relocation");
    408 	      break;
    409 
    410 	    default:
    411 	      msg = _("internal error: unknown error");
    412 	      break;
    413 	    }
    414 
    415 	  if (msg)
    416 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    417 					 input_section, rel->r_offset);
    418 	}
    419     }
    420 
    421   return true;
    422 }
    423 
    424 /* Look through the relocs for a section during the first phase.
    425    Since we don't do .gots or .plts, we just need to consider the
    426    virtual table relocs for gc.  */
    427 
    428 static bool
    429 mt_elf_check_relocs (bfd *abfd,
    430 		     struct bfd_link_info *info,
    431 		     asection *sec,
    432 		     const Elf_Internal_Rela *relocs)
    433 {
    434   Elf_Internal_Shdr *symtab_hdr;
    435   struct elf_link_hash_entry **sym_hashes;
    436   const Elf_Internal_Rela *rel;
    437   const Elf_Internal_Rela *rel_end;
    438 
    439   if (bfd_link_relocatable (info))
    440     return true;
    441 
    442   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    443   sym_hashes = elf_sym_hashes (abfd);
    444 
    445   rel_end = relocs + sec->reloc_count;
    446   for (rel = relocs; rel < rel_end; rel++)
    447     {
    448       struct elf_link_hash_entry *h;
    449       unsigned long r_symndx;
    450 
    451       r_symndx = ELF32_R_SYM (rel->r_info);
    452       if (r_symndx < symtab_hdr->sh_info)
    453 	h = NULL;
    454       else
    455 	{
    456 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    457 	  while (h->root.type == bfd_link_hash_indirect
    458 		 || h->root.type == bfd_link_hash_warning)
    459 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    460 	}
    461     }
    462 
    463   return true;
    464 }
    465 
    466 /* Return the MACH for an e_flags value.  */
    467 
    468 static int
    469 elf32_mt_machine (bfd *abfd)
    470 {
    471   switch (elf_elfheader (abfd)->e_flags & EF_MT_CPU_MASK)
    472     {
    473     case EF_MT_CPU_MRISC:	return bfd_mach_ms1;
    474     case EF_MT_CPU_MRISC2:	return bfd_mach_mrisc2;
    475     case EF_MT_CPU_MS2:		return bfd_mach_ms2;
    476     }
    477 
    478   return bfd_mach_ms1;
    479 }
    480 
    481 static bool
    482 mt_elf_object_p (bfd *abfd)
    483 {
    484   bfd_default_set_arch_mach (abfd, bfd_arch_mt, elf32_mt_machine (abfd));
    485 
    486   return true;
    487 }
    488 
    489 /* Function to set the ELF flag bits.  */
    490 
    491 static bool
    492 mt_elf_set_private_flags (bfd *abfd, flagword flags)
    493 {
    494   elf_elfheader (abfd)->e_flags = flags;
    495   elf_flags_init (abfd) = true;
    496   return true;
    497 }
    498 
    499 /* Merge backend specific data from an object file to the output
    500    object file when linking.  */
    501 
    502 static bool
    503 mt_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
    504 {
    505   bfd *obfd = info->output_bfd;
    506   flagword old_flags, new_flags;
    507   bool ok = true;
    508 
    509   /* Check if we have the same endianness.  */
    510   if (!_bfd_generic_verify_endian_match (ibfd, info))
    511     return false;
    512 
    513   /* If they're not both mt, then merging is meaningless, so just
    514      don't do it.  */
    515   if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
    516     return true;
    517   if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
    518     return true;
    519 
    520   new_flags = elf_elfheader (ibfd)->e_flags;
    521   old_flags = elf_elfheader (obfd)->e_flags;
    522 
    523 #ifdef DEBUG
    524   _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
    525 		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
    526 #endif
    527 
    528   if (!elf_flags_init (obfd))
    529     {
    530       old_flags = new_flags;
    531       elf_flags_init (obfd) = true;
    532     }
    533   else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
    534     {
    535       /* CPU has changed.  This is invalid, because MRISC, MRISC2 and
    536 	 MS2 are not subsets of each other.   */
    537       ok = false;
    538     }
    539 
    540   if (ok)
    541     {
    542       obfd->arch_info = ibfd->arch_info;
    543       elf_elfheader (obfd)->e_flags = old_flags;
    544     }
    545 
    546   return ok;
    547 }
    548 
    549 static bool
    550 mt_elf_print_private_bfd_data (bfd *abfd, void *ptr)
    551 {
    552   FILE *file = (FILE *) ptr;
    553   flagword flags;
    554 
    555   BFD_ASSERT (abfd != NULL && ptr != NULL);
    556 
    557   /* Print normal ELF private data.  */
    558   _bfd_elf_print_private_bfd_data (abfd, ptr);
    559 
    560   flags = elf_elfheader (abfd)->e_flags;
    561   fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
    562 
    563   switch (flags & EF_MT_CPU_MASK)
    564     {
    565     default:
    566     case EF_MT_CPU_MRISC:   fprintf (file, " ms1-16-002");	break;
    567     case EF_MT_CPU_MRISC2:  fprintf (file, " ms1-16-003");	break;
    568     case EF_MT_CPU_MS2:     fprintf (file, " ms2");	break;
    569     }
    570 
    571   fputc ('\n', file);
    572 
    573   return true;
    574 }
    575 
    576 
    577 #define TARGET_BIG_SYM	 mt_elf32_vec
    579 #define TARGET_BIG_NAME	 "elf32-mt"
    580 
    581 #define ELF_ARCH	 bfd_arch_mt
    582 #define ELF_MACHINE_CODE EM_MT
    583 #define ELF_MAXPAGESIZE	 1 /* No pages on the MT.  */
    584 
    585 #define elf_info_to_howto_rel			NULL
    586 #define elf_info_to_howto			mt_info_to_howto_rela
    587 
    588 #define elf_backend_relocate_section		mt_elf_relocate_section
    589 
    590 #define bfd_elf32_bfd_reloc_type_lookup		mt_reloc_type_lookup
    591 #define bfd_elf32_bfd_reloc_name_lookup	  mt_reloc_name_lookup
    592 
    593 #define elf_backend_check_relocs		mt_elf_check_relocs
    594 #define elf_backend_object_p			mt_elf_object_p
    595 #define elf_backend_rela_normal			1
    596 
    597 #define elf_backend_can_gc_sections		1
    598 
    599 #define bfd_elf32_bfd_set_private_flags		mt_elf_set_private_flags
    600 #define bfd_elf32_bfd_merge_private_bfd_data	mt_elf_merge_private_bfd_data
    601 #define bfd_elf32_bfd_print_private_bfd_data	mt_elf_print_private_bfd_data
    602 
    603 #include "elf32-target.h"
    604