Home | History | Annotate | Line # | Download | only in bfd
      1 /* Morpho Technologies MT specific support for 32-bit ELF
      2    Copyright (C) 2001-2026 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, R_MT_NONE,
    368 					 howto, 0, contents);
    369 
    370       if (bfd_link_relocatable (info))
    371 	continue;
    372 
    373       /* Finally, the sole MT-specific part.  */
    374       switch (r_type)
    375 	{
    376 	case R_MT_HI16:
    377 	  r = mt_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
    378 	  break;
    379 	default:
    380 	  r = mt_final_link_relocate (howto, input_bfd, input_section,
    381 					  contents, rel, relocation);
    382 	  break;
    383 	}
    384 
    385 
    386       if (r != bfd_reloc_ok)
    387 	{
    388 	  const char * msg = (const char *) NULL;
    389 
    390 	  switch (r)
    391 	    {
    392 	    case bfd_reloc_overflow:
    393 	      (*info->callbacks->reloc_overflow)
    394 		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
    395 		 input_bfd, input_section, rel->r_offset);
    396 	      break;
    397 
    398 	    case bfd_reloc_undefined:
    399 	      (*info->callbacks->undefined_symbol)
    400 		(info, name, input_bfd, input_section, rel->r_offset, true);
    401 	      break;
    402 
    403 	    case bfd_reloc_outofrange:
    404 	      msg = _("internal error: out of range error");
    405 	      break;
    406 
    407 	    case bfd_reloc_dangerous:
    408 	      msg = _("internal error: dangerous relocation");
    409 	      break;
    410 
    411 	    default:
    412 	      msg = _("internal error: unknown error");
    413 	      break;
    414 	    }
    415 
    416 	  if (msg)
    417 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    418 					 input_section, rel->r_offset);
    419 	}
    420     }
    421 
    422   return true;
    423 }
    424 
    425 /* Look through the relocs for a section during the first phase.
    426    Since we don't do .gots or .plts, we just need to consider the
    427    virtual table relocs for gc.  */
    428 
    429 static bool
    430 mt_elf_check_relocs (bfd *abfd,
    431 		     struct bfd_link_info *info,
    432 		     asection *sec,
    433 		     const Elf_Internal_Rela *relocs)
    434 {
    435   Elf_Internal_Shdr *symtab_hdr;
    436   struct elf_link_hash_entry **sym_hashes;
    437   const Elf_Internal_Rela *rel;
    438   const Elf_Internal_Rela *rel_end;
    439 
    440   if (bfd_link_relocatable (info))
    441     return true;
    442 
    443   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    444   sym_hashes = elf_sym_hashes (abfd);
    445 
    446   rel_end = relocs + sec->reloc_count;
    447   for (rel = relocs; rel < rel_end; rel++)
    448     {
    449       struct elf_link_hash_entry *h;
    450       unsigned long r_symndx;
    451 
    452       r_symndx = ELF32_R_SYM (rel->r_info);
    453       if (r_symndx < symtab_hdr->sh_info)
    454 	h = NULL;
    455       else
    456 	{
    457 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    458 	  while (h->root.type == bfd_link_hash_indirect
    459 		 || h->root.type == bfd_link_hash_warning)
    460 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    461 	}
    462     }
    463 
    464   return true;
    465 }
    466 
    467 /* Return the MACH for an e_flags value.  */
    468 
    469 static int
    470 elf32_mt_machine (bfd *abfd)
    471 {
    472   switch (elf_elfheader (abfd)->e_flags & EF_MT_CPU_MASK)
    473     {
    474     case EF_MT_CPU_MRISC:	return bfd_mach_ms1;
    475     case EF_MT_CPU_MRISC2:	return bfd_mach_mrisc2;
    476     case EF_MT_CPU_MS2:		return bfd_mach_ms2;
    477     }
    478 
    479   return bfd_mach_ms1;
    480 }
    481 
    482 static bool
    483 mt_elf_object_p (bfd *abfd)
    484 {
    485   bfd_default_set_arch_mach (abfd, bfd_arch_mt, elf32_mt_machine (abfd));
    486 
    487   return true;
    488 }
    489 
    490 /* Function to set the ELF flag bits.  */
    491 
    492 static bool
    493 mt_elf_set_private_flags (bfd *abfd, flagword flags)
    494 {
    495   elf_elfheader (abfd)->e_flags = flags;
    496   elf_flags_init (abfd) = true;
    497   return true;
    498 }
    499 
    500 /* Merge backend specific data from an object file to the output
    501    object file when linking.  */
    502 
    503 static bool
    504 mt_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
    505 {
    506   bfd *obfd = info->output_bfd;
    507   flagword old_flags, new_flags;
    508   bool ok = true;
    509 
    510   /* Check if we have the same endianness.  */
    511   if (!_bfd_generic_verify_endian_match (ibfd, info))
    512     return false;
    513 
    514   /* If they're not both mt, then merging is meaningless, so just
    515      don't do it.  */
    516   if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
    517     return true;
    518   if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
    519     return true;
    520 
    521   new_flags = elf_elfheader (ibfd)->e_flags;
    522   old_flags = elf_elfheader (obfd)->e_flags;
    523 
    524 #ifdef DEBUG
    525   _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
    526 		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
    527 #endif
    528 
    529   if (!elf_flags_init (obfd))
    530     {
    531       old_flags = new_flags;
    532       elf_flags_init (obfd) = true;
    533     }
    534   else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
    535     {
    536       /* CPU has changed.  This is invalid, because MRISC, MRISC2 and
    537 	 MS2 are not subsets of each other.   */
    538       ok = false;
    539     }
    540 
    541   if (ok)
    542     {
    543       obfd->arch_info = ibfd->arch_info;
    544       elf_elfheader (obfd)->e_flags = old_flags;
    545     }
    546 
    547   return ok;
    548 }
    549 
    550 static bool
    551 mt_elf_print_private_bfd_data (bfd *abfd, void *ptr)
    552 {
    553   FILE *file = (FILE *) ptr;
    554   flagword flags;
    555 
    556   BFD_ASSERT (abfd != NULL && ptr != NULL);
    557 
    558   /* Print normal ELF private data.  */
    559   _bfd_elf_print_private_bfd_data (abfd, ptr);
    560 
    561   flags = elf_elfheader (abfd)->e_flags;
    562   fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
    563 
    564   switch (flags & EF_MT_CPU_MASK)
    565     {
    566     default:
    567     case EF_MT_CPU_MRISC:   fprintf (file, " ms1-16-002");	break;
    568     case EF_MT_CPU_MRISC2:  fprintf (file, " ms1-16-003");	break;
    569     case EF_MT_CPU_MS2:     fprintf (file, " ms2");	break;
    570     }
    571 
    572   fputc ('\n', file);
    573 
    574   return true;
    575 }
    576 
    577 
    578 #define TARGET_BIG_SYM	 mt_elf32_vec
    580 #define TARGET_BIG_NAME	 "elf32-mt"
    581 
    582 #define ELF_ARCH	 bfd_arch_mt
    583 #define ELF_MACHINE_CODE EM_MT
    584 #define ELF_MAXPAGESIZE	 1 /* No pages on the MT.  */
    585 
    586 #define elf_info_to_howto_rel			NULL
    587 #define elf_info_to_howto			mt_info_to_howto_rela
    588 
    589 #define elf_backend_relocate_section		mt_elf_relocate_section
    590 
    591 #define bfd_elf32_bfd_reloc_type_lookup		mt_reloc_type_lookup
    592 #define bfd_elf32_bfd_reloc_name_lookup	  mt_reloc_name_lookup
    593 
    594 #define elf_backend_check_relocs		mt_elf_check_relocs
    595 #define elf_backend_object_p			mt_elf_object_p
    596 #define elf_backend_rela_normal			1
    597 
    598 #define elf_backend_can_gc_sections		1
    599 
    600 #define bfd_elf32_bfd_set_private_flags		mt_elf_set_private_flags
    601 #define bfd_elf32_bfd_merge_private_bfd_data	mt_elf_merge_private_bfd_data
    602 #define bfd_elf32_bfd_print_private_bfd_data	mt_elf_print_private_bfd_data
    603 
    604 #include "elf32-target.h"
    605