(root)/
binutils-2.41/
bfd/
elf32-moxie.c
       1  /* moxie-specific support for 32-bit ELF.
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       3  
       4     Copied from elf32-fr30.c which is..
       5     Copyright (C) 1998-2023 Free Software Foundation, Inc.
       6  
       7     This file is part of BFD, the Binary File Descriptor library.
       8  
       9     This program is free software; you can redistribute it and/or modify
      10     it under the terms of the GNU General Public License as published by
      11     the Free Software Foundation; either version 3 of the License, or
      12     (at your option) any later version.
      13  
      14     This program is distributed in the hope that it will be useful,
      15     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17     GNU General Public License for more details.
      18  
      19     You should have received a copy of the GNU General Public License
      20     along with this program; if not, write to the Free Software
      21     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      22     MA 02110-1301, USA.  */
      23  
      24  #include "sysdep.h"
      25  #include "bfd.h"
      26  #include "libbfd.h"
      27  #include "elf-bfd.h"
      28  #include "elf/moxie.h"
      29  
      30  /* Forward declarations.  */
      31  
      32  static reloc_howto_type moxie_elf_howto_table [] =
      33  {
      34    /* This reloc does nothing.  */
      35    HOWTO (R_MOXIE_NONE,		/* type */
      36  	 0,			/* rightshift */
      37  	 0,			/* size */
      38  	 0,			/* bitsize */
      39  	 false,			/* pc_relative */
      40  	 0,			/* bitpos */
      41  	 complain_overflow_dont, /* complain_on_overflow */
      42  	 bfd_elf_generic_reloc,	/* special_function */
      43  	 "R_MOXIE_NONE",		/* name */
      44  	 false,			/* partial_inplace */
      45  	 0,			/* src_mask */
      46  	 0,			/* dst_mask */
      47  	 false),		/* pcrel_offset */
      48  
      49    /* A 32 bit absolute relocation.  */
      50    HOWTO (R_MOXIE_32,		/* type */
      51  	 0,			/* rightshift */
      52  	 4,			/* size */
      53  	 32,			/* bitsize */
      54  	 false,			/* pc_relative */
      55  	 0,			/* bitpos */
      56  	 complain_overflow_bitfield, /* complain_on_overflow */
      57  	 bfd_elf_generic_reloc,	/* special_function */
      58  	 "R_MOXIE_32",		/* name */
      59  	 false,			/* partial_inplace */
      60  	 0x00000000,		/* src_mask */
      61  	 0xffffffff,		/* dst_mask */
      62  	 false),		/* pcrel_offset */
      63  
      64    /* A 10 bit PC-relative relocation.  */
      65    HOWTO (R_MOXIE_PCREL10,	/* type.  */
      66  	 1,			/* rightshift.  */
      67  	 2,			/* size.  */
      68  	 10,			/* bitsize.  */
      69  	 true,			/* pc_relative.  */
      70  	 0,			/* bitpos.  */
      71  	 complain_overflow_signed, /* complain_on_overflow.  */
      72  	 bfd_elf_generic_reloc,	/* special_function.  */
      73  	 "R_MOXIE_PCREL10",		/* name.  */
      74  	 false,			/* partial_inplace.  */
      75  	 0,			/* src_mask.  */
      76  	 0x000003FF,		/* dst_mask.  */
      77  	 true),			/* pcrel_offset.  */
      78  };
      79  
      80  /* Map BFD reloc types to MOXIE ELF reloc types.  */
      81  
      82  struct moxie_reloc_map
      83  {
      84    bfd_reloc_code_real_type bfd_reloc_val;
      85    unsigned int moxie_reloc_val;
      86  };
      87  
      88  static const struct moxie_reloc_map moxie_reloc_map [] =
      89  {
      90    { BFD_RELOC_NONE,	       R_MOXIE_NONE },
      91    { BFD_RELOC_32,	       R_MOXIE_32 },
      92    { BFD_RELOC_MOXIE_10_PCREL,  R_MOXIE_PCREL10 },
      93  };
      94  
      95  static reloc_howto_type *
      96  moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
      97  			 bfd_reloc_code_real_type code)
      98  {
      99    unsigned int i;
     100  
     101    for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
     102         i--;)
     103      if (moxie_reloc_map [i].bfd_reloc_val == code)
     104        return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
     105  
     106    return NULL;
     107  }
     108  
     109  static reloc_howto_type *
     110  moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
     111  {
     112    unsigned int i;
     113  
     114    for (i = 0;
     115         i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]);
     116         i++)
     117      if (moxie_elf_howto_table[i].name != NULL
     118  	&& strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0)
     119        return &moxie_elf_howto_table[i];
     120  
     121    return NULL;
     122  }
     123  
     124  /* Set the howto pointer for an MOXIE ELF reloc.  */
     125  
     126  static bool
     127  moxie_info_to_howto_rela (bfd *abfd,
     128  			  arelent *cache_ptr,
     129  			  Elf_Internal_Rela *dst)
     130  {
     131    unsigned int r_type;
     132  
     133    r_type = ELF32_R_TYPE (dst->r_info);
     134    if (r_type >= (unsigned int) R_MOXIE_max)
     135      {
     136        /* xgettext:c-format */
     137        _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
     138  			  abfd, r_type);
     139        bfd_set_error (bfd_error_bad_value);
     140        return false;
     141      }
     142    cache_ptr->howto = & moxie_elf_howto_table [r_type];
     143    return true;
     144  }
     145  
     146  /* Perform a single relocation.  By default we use the standard BFD
     147     routines, but a few relocs, we have to do them ourselves.  */
     148  
     149  static bfd_reloc_status_type
     150  moxie_final_link_relocate (reloc_howto_type *howto,
     151  			   bfd *input_bfd,
     152  			   asection *input_section,
     153  			   bfd_byte *contents,
     154  			   Elf_Internal_Rela *rel,
     155  			   bfd_vma relocation)
     156  {
     157    bfd_reloc_status_type r = bfd_reloc_ok;
     158  
     159    switch (howto->type)
     160      {
     161      default:
     162        r = _bfd_final_link_relocate (howto, input_bfd, input_section,
     163  				    contents, rel->r_offset,
     164  				    relocation, rel->r_addend);
     165      }
     166  
     167    return r;
     168  }
     169  
     170  /* Relocate an MOXIE ELF section.
     171  
     172     The RELOCATE_SECTION function is called by the new ELF backend linker
     173     to handle the relocations for a section.
     174  
     175     The relocs are always passed as Rela structures; if the section
     176     actually uses Rel structures, the r_addend field will always be
     177     zero.
     178  
     179     This function is responsible for adjusting the section contents as
     180     necessary, and (if using Rela relocs and generating a relocatable
     181     output file) adjusting the reloc addend as necessary.
     182  
     183     This function does not have to worry about setting the reloc
     184     address or the reloc symbol index.
     185  
     186     LOCAL_SYMS is a pointer to the swapped in local symbols.
     187  
     188     LOCAL_SECTIONS is an array giving the section in the input file
     189     corresponding to the st_shndx field of each local symbol.
     190  
     191     The global hash table entry for the global symbols can be found
     192     via elf_sym_hashes (input_bfd).
     193  
     194     When generating relocatable output, this function must handle
     195     STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
     196     going to be the section symbol corresponding to the output
     197     section, which means that the addend must be adjusted
     198     accordingly.  */
     199  
     200  static int
     201  moxie_elf_relocate_section (bfd *output_bfd,
     202  			    struct bfd_link_info *info,
     203  			    bfd *input_bfd,
     204  			    asection *input_section,
     205  			    bfd_byte *contents,
     206  			    Elf_Internal_Rela *relocs,
     207  			    Elf_Internal_Sym *local_syms,
     208  			    asection **local_sections)
     209  {
     210    Elf_Internal_Shdr *symtab_hdr;
     211    struct elf_link_hash_entry **sym_hashes;
     212    Elf_Internal_Rela *rel;
     213    Elf_Internal_Rela *relend;
     214  
     215    symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
     216    sym_hashes = elf_sym_hashes (input_bfd);
     217    relend     = relocs + input_section->reloc_count;
     218  
     219    for (rel = relocs; rel < relend; rel ++)
     220      {
     221        reloc_howto_type *howto;
     222        unsigned long r_symndx;
     223        Elf_Internal_Sym *sym;
     224        asection *sec;
     225        struct elf_link_hash_entry *h;
     226        bfd_vma relocation;
     227        bfd_reloc_status_type r;
     228        const char *name;
     229        int r_type;
     230  
     231        r_type = ELF32_R_TYPE (rel->r_info);
     232        r_symndx = ELF32_R_SYM (rel->r_info);
     233        howto  = moxie_elf_howto_table + r_type;
     234        h      = NULL;
     235        sym    = NULL;
     236        sec    = NULL;
     237  
     238        if (r_symndx < symtab_hdr->sh_info)
     239  	{
     240  	  sym = local_syms + r_symndx;
     241  	  sec = local_sections [r_symndx];
     242  	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
     243  
     244  	  name = bfd_elf_string_from_elf_section
     245  	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
     246  	  name = name == NULL ? bfd_section_name (sec) : name;
     247  	}
     248        else
     249  	{
     250  	  bool unresolved_reloc, warned, ignored;
     251  
     252  	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
     253  				   r_symndx, symtab_hdr, sym_hashes,
     254  				   h, sec, relocation,
     255  				   unresolved_reloc, warned, ignored);
     256  
     257  	  name = h->root.root.string;
     258  	}
     259  
     260        if (sec != NULL && discarded_section (sec))
     261  	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
     262  					 rel, 1, relend, howto, 0, contents);
     263  
     264        if (bfd_link_relocatable (info))
     265  	continue;
     266  
     267        r = moxie_final_link_relocate (howto, input_bfd, input_section,
     268  				     contents, rel, relocation);
     269  
     270        if (r != bfd_reloc_ok)
     271  	{
     272  	  const char * msg = NULL;
     273  
     274  	  switch (r)
     275  	    {
     276  	    case bfd_reloc_overflow:
     277  	      (*info->callbacks->reloc_overflow)
     278  		(info, (h ? &h->root : NULL), name, howto->name,
     279  		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
     280  	      break;
     281  
     282  	    case bfd_reloc_undefined:
     283  	      (*info->callbacks->undefined_symbol)
     284  		(info, name, input_bfd, input_section, rel->r_offset, true);
     285  	      break;
     286  
     287  	    case bfd_reloc_outofrange:
     288  	      msg = _("internal error: out of range error");
     289  	      break;
     290  
     291  	    case bfd_reloc_notsupported:
     292  	      msg = _("internal error: unsupported relocation error");
     293  	      break;
     294  
     295  	    case bfd_reloc_dangerous:
     296  	      msg = _("internal error: dangerous relocation");
     297  	      break;
     298  
     299  	    default:
     300  	      msg = _("internal error: unknown error");
     301  	      break;
     302  	    }
     303  
     304  	  if (msg)
     305  	    (*info->callbacks->warning) (info, msg, name, input_bfd,
     306  					 input_section, rel->r_offset);
     307  	}
     308      }
     309  
     310    return true;
     311  }
     312  
     313  /* Return the section that should be marked against GC for a given
     314     relocation.  */
     315  
     316  static asection *
     317  moxie_elf_gc_mark_hook (asection *sec,
     318  			struct bfd_link_info *info,
     319  			Elf_Internal_Rela *rel,
     320  			struct elf_link_hash_entry *h,
     321  			Elf_Internal_Sym *sym)
     322  {
     323    return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
     324  }
     325  
     326  /* Look through the relocs for a section during the first phase.
     327     Since we don't do .gots or .plts, we just need to consider the
     328     virtual table relocs for gc.  */
     329  
     330  static bool
     331  moxie_elf_check_relocs (bfd *abfd,
     332  			struct bfd_link_info *info,
     333  			asection *sec,
     334  			const Elf_Internal_Rela *relocs)
     335  {
     336    Elf_Internal_Shdr *symtab_hdr;
     337    struct elf_link_hash_entry **sym_hashes;
     338    const Elf_Internal_Rela *rel;
     339    const Elf_Internal_Rela *rel_end;
     340  
     341    if (bfd_link_relocatable (info))
     342      return true;
     343  
     344    symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
     345    sym_hashes = elf_sym_hashes (abfd);
     346  
     347    rel_end = relocs + sec->reloc_count;
     348    for (rel = relocs; rel < rel_end; rel++)
     349      {
     350        struct elf_link_hash_entry *h;
     351        unsigned long r_symndx;
     352  
     353        r_symndx = ELF32_R_SYM (rel->r_info);
     354        if (r_symndx < symtab_hdr->sh_info)
     355  	h = NULL;
     356        else
     357  	{
     358  	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
     359  	  while (h->root.type == bfd_link_hash_indirect
     360  		 || h->root.type == bfd_link_hash_warning)
     361  	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
     362  	}
     363      }
     364  
     365    return true;
     366  }
     367  
     368  #define ELF_ARCH		bfd_arch_moxie
     369  #define ELF_MACHINE_CODE	EM_MOXIE
     370  #define ELF_MACHINE_ALT1	EM_MOXIE_OLD
     371  #define ELF_MAXPAGESIZE		0x1
     372  
     373  #define TARGET_BIG_SYM		moxie_elf32_be_vec
     374  #define TARGET_BIG_NAME		"elf32-bigmoxie"
     375  #define TARGET_LITTLE_SYM	moxie_elf32_le_vec
     376  #define TARGET_LITTLE_NAME	"elf32-littlemoxie"
     377  
     378  #define elf_info_to_howto_rel			NULL
     379  #define elf_info_to_howto			moxie_info_to_howto_rela
     380  #define elf_backend_relocate_section		moxie_elf_relocate_section
     381  #define elf_backend_gc_mark_hook		moxie_elf_gc_mark_hook
     382  #define elf_backend_check_relocs		moxie_elf_check_relocs
     383  
     384  #define elf_backend_can_gc_sections		1
     385  #define elf_backend_rela_normal			1
     386  
     387  #define bfd_elf32_bfd_reloc_type_lookup		moxie_reloc_type_lookup
     388  #define bfd_elf32_bfd_reloc_name_lookup		moxie_reloc_name_lookup
     389  
     390  #include "elf32-target.h"