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