Home | History | Annotate | Download | only in bfd
      1 /* Morpho Technologies MT specific support for 32-bit ELF
      2    Copyright (C) 2001-2014 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., 59 Temple Place - Suite 330, Boston,
     19    MA 02111-1307, 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 void 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 bfd_boolean 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           2,                      /* size (0 = byte, 1 = short, 2 = long) */
     52           32,                     /* 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           2,                      /* size (0 = byte, 1 = short, 2 = long) */
     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           2,                      /* size (0 = byte, 1 = short, 2 = long) */
     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           2,                      /* size (0 = byte, 1 = short, 2 = long) */
     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           2,                      /* size (0 = byte, 1 = short, 2 = long) */
    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          2,                     /* size (0 = byte, 1 = short, 2 = long) */
    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          2,                     /* size (0 = byte, 1 = short, 2 = long) */
    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 void
    232 mt_info_to_howto_rela
    233     (bfd *               abfd ATTRIBUTE_UNUSED,
    234      arelent *           cache_ptr,
    235      Elf_Internal_Rela * dst)
    236 {
    237   unsigned int r_type;
    238 
    239   r_type = ELF32_R_TYPE (dst->r_info);
    240   cache_ptr->howto = & mt_elf_howto_table [r_type];
    241 }
    242 
    243 /* Perform a single relocation.  By default we use the standard BFD
    244    routines.  */
    245 
    246 static bfd_reloc_status_type
    247 mt_final_link_relocate
    248     (reloc_howto_type *  howto,
    249      bfd *               input_bfd,
    250      asection *          input_section,
    251      bfd_byte *          contents,
    252      Elf_Internal_Rela * rel,
    253      bfd_vma             relocation)
    254 {
    255   return _bfd_final_link_relocate (howto, input_bfd, input_section,
    256 				   contents, rel->r_offset,
    257 				   relocation, rel->r_addend);
    258 }
    259 
    260 /* Relocate a MT ELF section.
    261    There is some attempt to make this function usable for many architectures,
    262    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
    263    if only to serve as a learning tool.
    264 
    265    The RELOCATE_SECTION function is called by the new ELF backend linker
    266    to handle the relocations for a section.
    267 
    268    The relocs are always passed as Rela structures; if the section
    269    actually uses Rel structures, the r_addend field will always be
    270    zero.
    271 
    272    This function is responsible for adjusting the section contents as
    273    necessary, and (if using Rela relocs and generating a relocatable
    274    output file) adjusting the reloc addend as necessary.
    275 
    276    This function does not have to worry about setting the reloc
    277    address or the reloc symbol index.
    278 
    279    LOCAL_SYMS is a pointer to the swapped in local symbols.
    280 
    281    LOCAL_SECTIONS is an array giving the section in the input file
    282    corresponding to the st_shndx field of each local symbol.
    283 
    284    The global hash table entry for the global symbols can be found
    285    via elf_sym_hashes (input_bfd).
    286 
    287    When generating relocatable output, this function must handle
    288    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    289    going to be the section symbol corresponding to the output
    290    section, which means that the addend must be adjusted
    291    accordingly.  */
    292 
    293 static bfd_boolean
    294 mt_elf_relocate_section
    295     (bfd *                   output_bfd ATTRIBUTE_UNUSED,
    296      struct bfd_link_info *  info,
    297      bfd *                   input_bfd,
    298      asection *              input_section,
    299      bfd_byte *              contents,
    300      Elf_Internal_Rela *     relocs,
    301      Elf_Internal_Sym *      local_syms,
    302      asection **             local_sections)
    303 {
    304   Elf_Internal_Shdr *           symtab_hdr;
    305   struct elf_link_hash_entry ** sym_hashes;
    306   Elf_Internal_Rela *           rel;
    307   Elf_Internal_Rela *           relend;
    308 
    309   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    310   sym_hashes = elf_sym_hashes (input_bfd);
    311   relend     = relocs + input_section->reloc_count;
    312 
    313   for (rel = relocs; rel < relend; rel ++)
    314     {
    315       reloc_howto_type *           howto;
    316       unsigned long                r_symndx;
    317       Elf_Internal_Sym *           sym;
    318       asection *                   sec;
    319       struct elf_link_hash_entry * h;
    320       bfd_vma                      relocation;
    321       bfd_reloc_status_type        r;
    322       const char *                 name = NULL;
    323       int                          r_type;
    324 
    325       r_type = ELF32_R_TYPE (rel->r_info);
    326 
    327       r_symndx = ELF32_R_SYM (rel->r_info);
    328 
    329       howto  = mt_elf_howto_table + ELF32_R_TYPE (rel->r_info);
    330       h      = NULL;
    331       sym    = NULL;
    332       sec    = NULL;
    333 
    334       if (r_symndx < symtab_hdr->sh_info)
    335 	{
    336 	  sym = local_syms + r_symndx;
    337 	  sec = local_sections [r_symndx];
    338 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
    339 
    340 	  name = bfd_elf_string_from_elf_section
    341 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    342 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
    343 	}
    344       else
    345 	{
    346 	  bfd_boolean unresolved_reloc;
    347 	  bfd_boolean warned, ignored;
    348 
    349 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    350 				   r_symndx, symtab_hdr, sym_hashes,
    351 				   h, sec, relocation,
    352 				   unresolved_reloc, warned, ignored);
    353 
    354 	  name = h->root.root.string;
    355 	}
    356 
    357       if (sec != NULL && discarded_section (sec))
    358 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    359 					 rel, 1, relend, howto, 0, contents);
    360 
    361       if (info->relocatable)
    362 	continue;
    363 
    364       /* Finally, the sole MT-specific part.  */
    365       switch (r_type)
    366         {
    367         case R_MT_HI16:
    368           r = mt_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
    369           break;
    370 	default:
    371           r = mt_final_link_relocate (howto, input_bfd, input_section,
    372 		        		  contents, rel, relocation);
    373           break;
    374         }
    375 
    376 
    377       if (r != bfd_reloc_ok)
    378 	{
    379 	  const char * msg = (const char *) NULL;
    380 
    381 	  switch (r)
    382 	    {
    383 	    case bfd_reloc_overflow:
    384 	      r = info->callbacks->reloc_overflow
    385 		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
    386 		 input_bfd, input_section, rel->r_offset);
    387 	      break;
    388 
    389 	    case bfd_reloc_undefined:
    390 	      r = info->callbacks->undefined_symbol
    391 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
    392 	      break;
    393 
    394 	    case bfd_reloc_outofrange:
    395 	      msg = _("internal error: out of range error");
    396 	      break;
    397 
    398 	    case bfd_reloc_dangerous:
    399 	      msg = _("internal error: dangerous relocation");
    400 	      break;
    401 
    402 	    default:
    403 	      msg = _("internal error: unknown error");
    404 	      break;
    405 	    }
    406 
    407 	  if (msg)
    408 	    r = info->callbacks->warning
    409 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
    410 
    411 	  if (! r)
    412 	    return FALSE;
    413 	}
    414     }
    415 
    416   return TRUE;
    417 }
    418 
    419 /* Look through the relocs for a section during the first phase.
    420    Since we don't do .gots or .plts, we just need to consider the
    421    virtual table relocs for gc.  */
    422 
    423 static bfd_boolean
    424 mt_elf_check_relocs
    425     (bfd *                     abfd,
    426      struct bfd_link_info *    info,
    427      asection *                sec,
    428      const Elf_Internal_Rela * relocs)
    429 {
    430   Elf_Internal_Shdr *           symtab_hdr;
    431   struct elf_link_hash_entry ** sym_hashes;
    432   const Elf_Internal_Rela *     rel;
    433   const Elf_Internal_Rela *     rel_end;
    434 
    435   if (info->relocatable)
    436     return TRUE;
    437 
    438   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    439   sym_hashes = elf_sym_hashes (abfd);
    440 
    441   rel_end = relocs + sec->reloc_count;
    442   for (rel = relocs; rel < rel_end; rel++)
    443     {
    444       struct elf_link_hash_entry *h;
    445       unsigned long r_symndx;
    446 
    447       r_symndx = ELF32_R_SYM (rel->r_info);
    448       if (r_symndx < symtab_hdr->sh_info)
    449         h = NULL;
    450       else
    451 	{
    452 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
    453 	  while (h->root.type == bfd_link_hash_indirect
    454 		 || h->root.type == bfd_link_hash_warning)
    455 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    456 
    457 	  /* PR15323, ref flags aren't set for references in the same
    458 	     object.  */
    459 	  h->root.non_ir_ref = 1;
    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 bfd_boolean
    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 bfd_boolean
    492 mt_elf_set_private_flags (bfd *    abfd,
    493 			   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 bfd_boolean
    504 mt_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
    505 {
    506   flagword     old_flags, new_flags;
    507   bfd_boolean  ok = TRUE;
    508 
    509   /* Check if we have the same endianness.  */
    510   if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
    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 ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, 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 bfd_boolean
    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