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