(root)/
binutils-2.41/
bfd/
elf32-mt.c
       1  /* Morpho Technologies MT specific support for 32-bit ELF
       2     Copyright (C) 2001-2023 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
     226     practice is very widespread in the various target back-end files.  */
     227  
     228  /* Set the howto pointer for a MT ELF reloc.  */
     229  
     230  static bool
     231  mt_info_to_howto_rela (bfd *abfd,
     232  		       arelent *cache_ptr,
     233  		       Elf_Internal_Rela *dst)
     234  {
     235    unsigned int r_type;
     236  
     237    r_type = ELF32_R_TYPE (dst->r_info);
     238    if (r_type >= (unsigned int) R_MT_max)
     239      {
     240        /* xgettext:c-format */
     241        _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
     242  			  abfd, r_type);
     243        bfd_set_error (bfd_error_bad_value);
     244        return false;
     245      }
     246    cache_ptr->howto = & mt_elf_howto_table [r_type];
     247    return true;
     248  }
     249  
     250  /* Perform a single relocation.  By default we use the standard BFD
     251     routines.  */
     252  
     253  static bfd_reloc_status_type
     254  mt_final_link_relocate
     255      (reloc_howto_type *	 howto,
     256       bfd *		 input_bfd,
     257       asection *		 input_section,
     258       bfd_byte *		 contents,
     259       Elf_Internal_Rela * rel,
     260       bfd_vma		 relocation)
     261  {
     262    return _bfd_final_link_relocate (howto, input_bfd, input_section,
     263  				   contents, rel->r_offset,
     264  				   relocation, rel->r_addend);
     265  }
     266  
     267  /* Relocate a MT ELF section.
     268     There is some attempt to make this function usable for many architectures,
     269     both USE_REL and USE_RELA ['twould be nice if such a critter existed],
     270     if only to serve as a learning tool.
     271  
     272     The RELOCATE_SECTION function is called by the new ELF backend linker
     273     to handle the relocations for a section.
     274  
     275     The relocs are always passed as Rela structures; if the section
     276     actually uses Rel structures, the r_addend field will always be
     277     zero.
     278  
     279     This function is responsible for adjusting the section contents as
     280     necessary, and (if using Rela relocs and generating a relocatable
     281     output file) adjusting the reloc addend as necessary.
     282  
     283     This function does not have to worry about setting the reloc
     284     address or the reloc symbol index.
     285  
     286     LOCAL_SYMS is a pointer to the swapped in local symbols.
     287  
     288     LOCAL_SECTIONS is an array giving the section in the input file
     289     corresponding to the st_shndx field of each local symbol.
     290  
     291     The global hash table entry for the global symbols can be found
     292     via elf_sym_hashes (input_bfd).
     293  
     294     When generating relocatable output, this function must handle
     295     STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
     296     going to be the section symbol corresponding to the output
     297     section, which means that the addend must be adjusted
     298     accordingly.  */
     299  
     300  static int
     301  mt_elf_relocate_section
     302      (bfd *		     output_bfd ATTRIBUTE_UNUSED,
     303       struct bfd_link_info *  info,
     304       bfd *		     input_bfd,
     305       asection *		     input_section,
     306       bfd_byte *		     contents,
     307       Elf_Internal_Rela *     relocs,
     308       Elf_Internal_Sym *	     local_syms,
     309       asection **	     local_sections)
     310  {
     311    Elf_Internal_Shdr *		symtab_hdr;
     312    struct elf_link_hash_entry ** sym_hashes;
     313    Elf_Internal_Rela *		rel;
     314    Elf_Internal_Rela *		relend;
     315  
     316    symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
     317    sym_hashes = elf_sym_hashes (input_bfd);
     318    relend     = relocs + input_section->reloc_count;
     319  
     320    for (rel = relocs; rel < relend; rel ++)
     321      {
     322        reloc_howto_type *	   howto;
     323        unsigned long		   r_symndx;
     324        Elf_Internal_Sym *	   sym;
     325        asection *		   sec;
     326        struct elf_link_hash_entry * h;
     327        bfd_vma			   relocation;
     328        bfd_reloc_status_type	   r;
     329        const char *		   name = NULL;
     330        int			   r_type;
     331  
     332        r_type = ELF32_R_TYPE (rel->r_info);
     333  
     334        r_symndx = ELF32_R_SYM (rel->r_info);
     335  
     336        howto  = mt_elf_howto_table + ELF32_R_TYPE (rel->r_info);
     337        h      = NULL;
     338        sym    = NULL;
     339        sec    = NULL;
     340  
     341        if (r_symndx < symtab_hdr->sh_info)
     342  	{
     343  	  sym = local_syms + r_symndx;
     344  	  sec = local_sections [r_symndx];
     345  	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
     346  
     347  	  name = bfd_elf_string_from_elf_section
     348  	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
     349  	  name = name == NULL ? bfd_section_name (sec) : name;
     350  	}
     351        else
     352  	{
     353  	  bool unresolved_reloc;
     354  	  bool warned, ignored;
     355  
     356  	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
     357  				   r_symndx, symtab_hdr, sym_hashes,
     358  				   h, sec, relocation,
     359  				   unresolved_reloc, warned, ignored);
     360  
     361  	  name = h->root.root.string;
     362  	}
     363  
     364        if (sec != NULL && discarded_section (sec))
     365  	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
     366  					 rel, 1, relend, howto, 0, contents);
     367  
     368        if (bfd_link_relocatable (info))
     369  	continue;
     370  
     371        /* Finally, the sole MT-specific part.  */
     372        switch (r_type)
     373  	{
     374  	case R_MT_HI16:
     375  	  r = mt_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
     376  	  break;
     377  	default:
     378  	  r = mt_final_link_relocate (howto, input_bfd, input_section,
     379  					  contents, rel, relocation);
     380  	  break;
     381  	}
     382  
     383  
     384        if (r != bfd_reloc_ok)
     385  	{
     386  	  const char * msg = (const char *) NULL;
     387  
     388  	  switch (r)
     389  	    {
     390  	    case bfd_reloc_overflow:
     391  	      (*info->callbacks->reloc_overflow)
     392  		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
     393  		 input_bfd, input_section, rel->r_offset);
     394  	      break;
     395  
     396  	    case bfd_reloc_undefined:
     397  	      (*info->callbacks->undefined_symbol)
     398  		(info, name, input_bfd, input_section, rel->r_offset, true);
     399  	      break;
     400  
     401  	    case bfd_reloc_outofrange:
     402  	      msg = _("internal error: out of range error");
     403  	      break;
     404  
     405  	    case bfd_reloc_dangerous:
     406  	      msg = _("internal error: dangerous relocation");
     407  	      break;
     408  
     409  	    default:
     410  	      msg = _("internal error: unknown error");
     411  	      break;
     412  	    }
     413  
     414  	  if (msg)
     415  	    (*info->callbacks->warning) (info, msg, name, input_bfd,
     416  					 input_section, rel->r_offset);
     417  	}
     418      }
     419  
     420    return true;
     421  }
     422  
     423  /* Look through the relocs for a section during the first phase.
     424     Since we don't do .gots or .plts, we just need to consider the
     425     virtual table relocs for gc.  */
     426  
     427  static bool
     428  mt_elf_check_relocs (bfd *abfd,
     429  		     struct bfd_link_info *info,
     430  		     asection *sec,
     431  		     const Elf_Internal_Rela *relocs)
     432  {
     433    Elf_Internal_Shdr *symtab_hdr;
     434    struct elf_link_hash_entry **sym_hashes;
     435    const Elf_Internal_Rela *rel;
     436    const Elf_Internal_Rela *rel_end;
     437  
     438    if (bfd_link_relocatable (info))
     439      return true;
     440  
     441    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
     442    sym_hashes = elf_sym_hashes (abfd);
     443  
     444    rel_end = relocs + sec->reloc_count;
     445    for (rel = relocs; rel < rel_end; rel++)
     446      {
     447        struct elf_link_hash_entry *h;
     448        unsigned long r_symndx;
     449  
     450        r_symndx = ELF32_R_SYM (rel->r_info);
     451        if (r_symndx < symtab_hdr->sh_info)
     452  	h = NULL;
     453        else
     454  	{
     455  	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
     456  	  while (h->root.type == bfd_link_hash_indirect
     457  		 || h->root.type == bfd_link_hash_warning)
     458  	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
     459  	}
     460      }
     461  
     462    return true;
     463  }
     464  
     465  /* Return the MACH for an e_flags value.  */
     466  
     467  static int
     468  elf32_mt_machine (bfd *abfd)
     469  {
     470    switch (elf_elfheader (abfd)->e_flags & EF_MT_CPU_MASK)
     471      {
     472      case EF_MT_CPU_MRISC:	return bfd_mach_ms1;
     473      case EF_MT_CPU_MRISC2:	return bfd_mach_mrisc2;
     474      case EF_MT_CPU_MS2:		return bfd_mach_ms2;
     475      }
     476  
     477    return bfd_mach_ms1;
     478  }
     479  
     480  static bool
     481  mt_elf_object_p (bfd *abfd)
     482  {
     483    bfd_default_set_arch_mach (abfd, bfd_arch_mt, elf32_mt_machine (abfd));
     484  
     485    return true;
     486  }
     487  
     488  /* Function to set the ELF flag bits.  */
     489  
     490  static bool
     491  mt_elf_set_private_flags (bfd *abfd, flagword flags)
     492  {
     493    elf_elfheader (abfd)->e_flags = flags;
     494    elf_flags_init (abfd) = true;
     495    return true;
     496  }
     497  
     498  /* Merge backend specific data from an object file to the output
     499     object file when linking.  */
     500  
     501  static bool
     502  mt_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
     503  {
     504    bfd *obfd = info->output_bfd;
     505    flagword old_flags, new_flags;
     506    bool ok = true;
     507  
     508    /* Check if we have the same endianness.  */
     509    if (!_bfd_generic_verify_endian_match (ibfd, info))
     510      return false;
     511  
     512    /* If they're not both mt, then merging is meaningless, so just
     513       don't do it.  */
     514    if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
     515      return true;
     516    if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
     517      return true;
     518  
     519    new_flags = elf_elfheader (ibfd)->e_flags;
     520    old_flags = elf_elfheader (obfd)->e_flags;
     521  
     522  #ifdef DEBUG
     523    _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
     524  		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
     525  #endif
     526  
     527    if (!elf_flags_init (obfd))
     528      {
     529        old_flags = new_flags;
     530        elf_flags_init (obfd) = true;
     531      }
     532    else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
     533      {
     534        /* CPU has changed.  This is invalid, because MRISC, MRISC2 and
     535  	 MS2 are not subsets of each other.   */
     536        ok = false;
     537      }
     538  
     539    if (ok)
     540      {
     541        obfd->arch_info = ibfd->arch_info;
     542        elf_elfheader (obfd)->e_flags = old_flags;
     543      }
     544  
     545    return ok;
     546  }
     547  
     548  static bool
     549  mt_elf_print_private_bfd_data (bfd *abfd, void *ptr)
     550  {
     551    FILE *file = (FILE *) ptr;
     552    flagword flags;
     553  
     554    BFD_ASSERT (abfd != NULL && ptr != NULL);
     555  
     556    /* Print normal ELF private data.  */
     557    _bfd_elf_print_private_bfd_data (abfd, ptr);
     558  
     559    flags = elf_elfheader (abfd)->e_flags;
     560    fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
     561  
     562    switch (flags & EF_MT_CPU_MASK)
     563      {
     564      default:
     565      case EF_MT_CPU_MRISC:   fprintf (file, " ms1-16-002");	break;
     566      case EF_MT_CPU_MRISC2:  fprintf (file, " ms1-16-003");	break;
     567      case EF_MT_CPU_MS2:     fprintf (file, " ms2");	break;
     568      }
     569  
     570    fputc ('\n', file);
     571  
     572    return true;
     573  }
     574  
     575  
     576  #define TARGET_BIG_SYM	 mt_elf32_vec
     577  #define TARGET_BIG_NAME	 "elf32-mt"
     578  
     579  #define ELF_ARCH	 bfd_arch_mt
     580  #define ELF_MACHINE_CODE EM_MT
     581  #define ELF_MAXPAGESIZE	 1 /* No pages on the MT.  */
     582  
     583  #define elf_info_to_howto_rel			NULL
     584  #define elf_info_to_howto			mt_info_to_howto_rela
     585  
     586  #define elf_backend_relocate_section		mt_elf_relocate_section
     587  
     588  #define bfd_elf32_bfd_reloc_type_lookup		mt_reloc_type_lookup
     589  #define bfd_elf32_bfd_reloc_name_lookup	  mt_reloc_name_lookup
     590  
     591  #define elf_backend_check_relocs		mt_elf_check_relocs
     592  #define elf_backend_object_p			mt_elf_object_p
     593  #define elf_backend_rela_normal			1
     594  
     595  #define elf_backend_can_gc_sections		1
     596  
     597  #define bfd_elf32_bfd_set_private_flags		mt_elf_set_private_flags
     598  #define bfd_elf32_bfd_merge_private_bfd_data	mt_elf_merge_private_bfd_data
     599  #define bfd_elf32_bfd_print_private_bfd_data	mt_elf_print_private_bfd_data
     600  
     601  #include "elf32-target.h"