1/* Morpho Technologies MT specific support for 32-bit ELF
2   Copyright (C) 2001-2020 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.  */
28static reloc_howto_type * mt_reloc_type_lookup
29  (bfd *, bfd_reloc_code_real_type);
30
31static bfd_boolean 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 bfd_boolean
231mt_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
253static bfd_reloc_status_type
254mt_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
300static bfd_boolean
301mt_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	  bfd_boolean unresolved_reloc;
354	  bfd_boolean 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
427static bfd_boolean
428mt_elf_check_relocs
429    (bfd *		       abfd,
430     struct bfd_link_info *    info,
431     asection *		       sec,
432     const Elf_Internal_Rela * relocs)
433{
434  Elf_Internal_Shdr *		symtab_hdr;
435  struct elf_link_hash_entry ** sym_hashes;
436  const Elf_Internal_Rela *	rel;
437  const Elf_Internal_Rela *	rel_end;
438
439  if (bfd_link_relocatable (info))
440    return TRUE;
441
442  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
443  sym_hashes = elf_sym_hashes (abfd);
444
445  rel_end = relocs + sec->reloc_count;
446  for (rel = relocs; rel < rel_end; rel++)
447    {
448      struct elf_link_hash_entry *h;
449      unsigned long r_symndx;
450
451      r_symndx = ELF32_R_SYM (rel->r_info);
452      if (r_symndx < symtab_hdr->sh_info)
453	h = NULL;
454      else
455	{
456	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
457	  while (h->root.type == bfd_link_hash_indirect
458		 || h->root.type == bfd_link_hash_warning)
459	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
460	}
461    }
462
463  return TRUE;
464}
465
466/* Return the MACH for an e_flags value.  */
467
468static int
469elf32_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
481static bfd_boolean
482mt_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
491static bfd_boolean
492mt_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
503static bfd_boolean
504mt_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
505{
506  bfd *obfd = info->output_bfd;
507  flagword     old_flags, new_flags;
508  bfd_boolean  ok = TRUE;
509
510  /* Check if we have the same endianness.  */
511  if (!_bfd_generic_verify_endian_match (ibfd, info))
512    return FALSE;
513
514  /* If they're not both mt, then merging is meaningless, so just
515     don't do it.  */
516  if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
517    return TRUE;
518  if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
519    return TRUE;
520
521  new_flags = elf_elfheader (ibfd)->e_flags;
522  old_flags = elf_elfheader (obfd)->e_flags;
523
524#ifdef DEBUG
525  _bfd_error_handler ("%pB: old_flags = 0x%.8x, new_flags = 0x%.8x, init = %s",
526		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
527#endif
528
529  if (!elf_flags_init (obfd))
530    {
531      old_flags = new_flags;
532      elf_flags_init (obfd) = TRUE;
533    }
534  else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
535    {
536      /* CPU has changed.  This is invalid, because MRISC, MRISC2 and
537	 MS2 are not subsets of each other.   */
538      ok = FALSE;
539    }
540
541  if (ok)
542    {
543      obfd->arch_info = ibfd->arch_info;
544      elf_elfheader (obfd)->e_flags = old_flags;
545    }
546
547  return ok;
548}
549
550static bfd_boolean
551mt_elf_print_private_bfd_data (bfd * abfd, void * ptr)
552{
553  FILE *   file = (FILE *) ptr;
554  flagword flags;
555
556  BFD_ASSERT (abfd != NULL && ptr != NULL);
557
558  /* Print normal ELF private data.  */
559  _bfd_elf_print_private_bfd_data (abfd, ptr);
560
561  flags = elf_elfheader (abfd)->e_flags;
562  fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
563
564  switch (flags & EF_MT_CPU_MASK)
565    {
566    default:
567    case EF_MT_CPU_MRISC:   fprintf (file, " ms1-16-002");	break;
568    case EF_MT_CPU_MRISC2:  fprintf (file, " ms1-16-003");	break;
569    case EF_MT_CPU_MS2:     fprintf (file, " ms2");	break;
570    }
571
572  fputc ('\n', file);
573
574  return TRUE;
575}
576
577
578#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