1/* Morpho Technologies MT specific support for 32-bit ELF
2   Copyright 2001, 2002, 2003, 2004, 2005
3   Free Software Foundation, Inc.
4
5   This file is part of BFD, the Binary File Descriptor library.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21#include "bfd.h"
22#include "sysdep.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          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
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
190bfd_reloc_status_type
191mt_elf_relocate_hi16
192    (bfd *               input_bfd,
193     Elf_Internal_Rela * relhi,
194     bfd_byte *          contents,
195     bfd_vma             value)
196{
197  bfd_vma insn;
198
199  insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
200
201  value += relhi->r_addend;
202  value >>= 16;
203  insn = ((insn & ~0xFFFF) | value);
204
205  bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
206  return bfd_reloc_ok;
207}
208
209/* XXX: The following code is the result of a cut&paste.  This unfortunate
210   practice is very widespread in the various target back-end files.  */
211
212/* Set the howto pointer for a MT ELF reloc.  */
213
214static void
215mt_info_to_howto_rela
216    (bfd *               abfd ATTRIBUTE_UNUSED,
217     arelent *           cache_ptr,
218     Elf_Internal_Rela * dst)
219{
220  unsigned int r_type;
221
222  r_type = ELF32_R_TYPE (dst->r_info);
223  cache_ptr->howto = & mt_elf_howto_table [r_type];
224}
225
226/* Perform a single relocation.  By default we use the standard BFD
227   routines.  */
228
229static bfd_reloc_status_type
230mt_final_link_relocate
231    (reloc_howto_type *  howto,
232     bfd *               input_bfd,
233     asection *          input_section,
234     bfd_byte *          contents,
235     Elf_Internal_Rela * rel,
236     bfd_vma             relocation)
237{
238  return _bfd_final_link_relocate (howto, input_bfd, input_section,
239				   contents, rel->r_offset,
240				   relocation, rel->r_addend);
241}
242
243/* Relocate a MT ELF section.
244   There is some attempt to make this function usable for many architectures,
245   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
246   if only to serve as a learning tool.
247
248   The RELOCATE_SECTION function is called by the new ELF backend linker
249   to handle the relocations for a section.
250
251   The relocs are always passed as Rela structures; if the section
252   actually uses Rel structures, the r_addend field will always be
253   zero.
254
255   This function is responsible for adjusting the section contents as
256   necessary, and (if using Rela relocs and generating a relocatable
257   output file) adjusting the reloc addend as necessary.
258
259   This function does not have to worry about setting the reloc
260   address or the reloc symbol index.
261
262   LOCAL_SYMS is a pointer to the swapped in local symbols.
263
264   LOCAL_SECTIONS is an array giving the section in the input file
265   corresponding to the st_shndx field of each local symbol.
266
267   The global hash table entry for the global symbols can be found
268   via elf_sym_hashes (input_bfd).
269
270   When generating relocatable output, this function must handle
271   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
272   going to be the section symbol corresponding to the output
273   section, which means that the addend must be adjusted
274   accordingly.  */
275
276static bfd_boolean
277mt_elf_relocate_section
278    (bfd *                   output_bfd ATTRIBUTE_UNUSED,
279     struct bfd_link_info *  info,
280     bfd *                   input_bfd,
281     asection *              input_section,
282     bfd_byte *              contents,
283     Elf_Internal_Rela *     relocs,
284     Elf_Internal_Sym *      local_syms,
285     asection **             local_sections)
286{
287  Elf_Internal_Shdr *           symtab_hdr;
288  struct elf_link_hash_entry ** sym_hashes;
289  Elf_Internal_Rela *           rel;
290  Elf_Internal_Rela *           relend;
291
292  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
293  sym_hashes = elf_sym_hashes (input_bfd);
294  relend     = relocs + input_section->reloc_count;
295
296  for (rel = relocs; rel < relend; rel ++)
297    {
298      reloc_howto_type *           howto;
299      unsigned long                r_symndx;
300      Elf_Internal_Sym *           sym;
301      asection *                   sec;
302      struct elf_link_hash_entry * h;
303      bfd_vma                      relocation;
304      bfd_reloc_status_type        r;
305      const char *                 name = NULL;
306      int                          r_type;
307
308      r_type = ELF32_R_TYPE (rel->r_info);
309
310      r_symndx = ELF32_R_SYM (rel->r_info);
311
312      /* This is a final link.  */
313      howto  = mt_elf_howto_table + ELF32_R_TYPE (rel->r_info);
314      h      = NULL;
315      sym    = NULL;
316      sec    = NULL;
317
318      if (r_symndx < symtab_hdr->sh_info)
319	{
320	  sym = local_syms + r_symndx;
321	  sec = local_sections [r_symndx];
322	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
323
324	  name = bfd_elf_string_from_elf_section
325	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
326	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
327	}
328      else
329	{
330	  bfd_boolean unresolved_reloc;
331	  bfd_boolean warned;
332
333	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
334				   r_symndx, symtab_hdr, sym_hashes,
335				   h, sec, relocation,
336				   unresolved_reloc, warned);
337
338	  name = h->root.root.string;
339	}
340
341
342      /* Finally, the sole MT-specific part.  */
343      switch (r_type)
344        {
345        case R_MT_HI16:
346          r = mt_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
347          break;
348	default:
349          r = mt_final_link_relocate (howto, input_bfd, input_section,
350		        		  contents, rel, relocation);
351          break;
352        }
353
354
355      if (r != bfd_reloc_ok)
356	{
357	  const char * msg = (const char *) NULL;
358
359	  switch (r)
360	    {
361	    case bfd_reloc_overflow:
362	      r = info->callbacks->reloc_overflow
363		(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
364		 input_bfd, input_section, rel->r_offset);
365	      break;
366
367	    case bfd_reloc_undefined:
368	      r = info->callbacks->undefined_symbol
369		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
370	      break;
371
372	    case bfd_reloc_outofrange:
373	      msg = _("internal error: out of range error");
374	      break;
375
376	    case bfd_reloc_dangerous:
377	      msg = _("internal error: dangerous relocation");
378	      break;
379
380	    default:
381	      msg = _("internal error: unknown error");
382	      break;
383	    }
384
385	  if (msg)
386	    r = info->callbacks->warning
387	      (info, msg, name, input_bfd, input_section, rel->r_offset);
388
389	  if (! r)
390	    return FALSE;
391	}
392    }
393
394  return TRUE;
395}
396
397/* Return the section that should be marked against GC for a given
398   relocation.  */
399
400static asection *
401mt_elf_gc_mark_hook
402    (asection *                   sec,
403     struct bfd_link_info *       info ATTRIBUTE_UNUSED,
404     Elf_Internal_Rela *          rel ATTRIBUTE_UNUSED,
405     struct elf_link_hash_entry * h,
406     Elf_Internal_Sym *           sym)
407{
408  if (h != NULL)
409    {
410      switch (h->root.type)
411	{
412	case bfd_link_hash_defined:
413	case bfd_link_hash_defweak:
414	  return h->root.u.def.section;
415
416	case bfd_link_hash_common:
417	  return h->root.u.c.p->section;
418
419	default:
420	  break;
421	}
422    }
423  else
424    {
425      if (!(elf_bad_symtab (sec->owner)
426	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
427	  && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
428		&& sym->st_shndx != SHN_COMMON))
429	return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
430    }
431
432  return NULL;
433}
434
435/* Update the got entry reference counts for the section being
436   removed.  */
437
438static bfd_boolean
439mt_elf_gc_sweep_hook
440    (bfd *                     abfd ATTRIBUTE_UNUSED,
441     struct bfd_link_info *    info ATTRIBUTE_UNUSED,
442     asection *                sec ATTRIBUTE_UNUSED,
443     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
444{
445  return TRUE;
446}
447
448/* Look through the relocs for a section during the first phase.
449   Since we don't do .gots or .plts, we just need to consider the
450   virtual table relocs for gc.  */
451
452static bfd_boolean
453mt_elf_check_relocs
454    (bfd *                     abfd,
455     struct bfd_link_info *    info,
456     asection *                sec,
457     const Elf_Internal_Rela * relocs)
458{
459  Elf_Internal_Shdr *           symtab_hdr;
460  struct elf_link_hash_entry ** sym_hashes;
461  struct elf_link_hash_entry ** sym_hashes_end;
462  const Elf_Internal_Rela *     rel;
463  const Elf_Internal_Rela *     rel_end;
464
465  if (info->relocatable)
466    return TRUE;
467
468  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
469  sym_hashes = elf_sym_hashes (abfd);
470  sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
471  if (!elf_bad_symtab (abfd))
472    sym_hashes_end -= symtab_hdr->sh_info;
473
474  rel_end = relocs + sec->reloc_count;
475  for (rel = relocs; rel < rel_end; rel++)
476    {
477      struct elf_link_hash_entry *h;
478      unsigned long r_symndx;
479
480      r_symndx = ELF32_R_SYM (rel->r_info);
481      if (r_symndx < symtab_hdr->sh_info)
482        h = NULL;
483      else
484	{
485	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
486	  while (h->root.type == bfd_link_hash_indirect
487		 || h->root.type == bfd_link_hash_warning)
488	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
489	}
490    }
491
492  return TRUE;
493}
494
495/* Return the MACH for an e_flags value.  */
496
497static int
498elf32_mt_machine (bfd *abfd)
499{
500  switch (elf_elfheader (abfd)->e_flags & EF_MT_CPU_MASK)
501    {
502    case EF_MT_CPU_MRISC:	return bfd_mach_ms1;
503    case EF_MT_CPU_MRISC2:	return bfd_mach_mrisc2;
504    case EF_MT_CPU_MS2:		return bfd_mach_ms2;
505    }
506
507  return bfd_mach_ms1;
508}
509
510static bfd_boolean
511mt_elf_object_p (bfd * abfd)
512{
513  bfd_default_set_arch_mach (abfd, bfd_arch_mt, elf32_mt_machine (abfd));
514
515  return TRUE;
516}
517
518/* Function to set the ELF flag bits.  */
519
520static bfd_boolean
521mt_elf_set_private_flags (bfd *    abfd,
522			   flagword flags)
523{
524  elf_elfheader (abfd)->e_flags = flags;
525  elf_flags_init (abfd) = TRUE;
526  return TRUE;
527}
528
529static bfd_boolean
530mt_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
531{
532  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
533      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
534    return TRUE;
535
536  BFD_ASSERT (!elf_flags_init (obfd)
537	      || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
538
539  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
540  elf_flags_init (obfd) = TRUE;
541  return TRUE;
542}
543
544/* Merge backend specific data from an object file to the output
545   object file when linking.  */
546
547static bfd_boolean
548mt_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
549{
550  flagword     old_flags, new_flags;
551  bfd_boolean  ok = TRUE;
552
553  /* Check if we have the same endianess.  */
554  if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
555    return FALSE;
556
557  /* If they're not both mt, then merging is meaningless, so just
558     don't do it.  */
559  if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
560    return TRUE;
561  if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
562    return TRUE;
563
564  new_flags = elf_elfheader (ibfd)->e_flags;
565  old_flags = elf_elfheader (obfd)->e_flags;
566
567#ifdef DEBUG
568  _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
569		      ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
570#endif
571
572  if (!elf_flags_init (obfd))
573    {
574      old_flags = new_flags;
575      elf_flags_init (obfd) = TRUE;
576    }
577  else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
578    {
579      /* CPU has changed.  This is invalid, because MRISC, MRISC2 and
580	 MS2 are not subsets of each other.   */
581      ok = FALSE;
582    }
583
584  if (ok)
585    {
586      obfd->arch_info = ibfd->arch_info;
587      elf_elfheader (obfd)->e_flags = old_flags;
588    }
589
590  return ok;
591}
592
593static bfd_boolean
594mt_elf_print_private_bfd_data (bfd * abfd, void * ptr)
595{
596  FILE *   file = (FILE *) ptr;
597  flagword flags;
598
599  BFD_ASSERT (abfd != NULL && ptr != NULL);
600
601  /* Print normal ELF private data.  */
602  _bfd_elf_print_private_bfd_data (abfd, ptr);
603
604  flags = elf_elfheader (abfd)->e_flags;
605  fprintf (file, _("private flags = 0x%lx:"), (long)flags);
606
607  switch (flags & EF_MT_CPU_MASK)
608    {
609    default:
610    case EF_MT_CPU_MRISC:   fprintf (file, " ms1-16-002");	break;
611    case EF_MT_CPU_MRISC2:  fprintf (file, " ms1-16-003");	break;
612    case EF_MT_CPU_MS2:     fprintf (file, " ms2");	break;
613    }
614
615  fputc ('\n', file);
616
617  return TRUE;
618}
619
620
621#define TARGET_BIG_SYM	 bfd_elf32_mt_vec
622#define TARGET_BIG_NAME  "elf32-mt"
623
624#define ELF_ARCH	 bfd_arch_mt
625#define ELF_MACHINE_CODE EM_MT
626#define ELF_MAXPAGESIZE  1 /* No pages on the MT.  */
627
628#define elf_info_to_howto_rel			NULL
629#define elf_info_to_howto			mt_info_to_howto_rela
630
631#define elf_backend_relocate_section		mt_elf_relocate_section
632
633#define bfd_elf32_bfd_reloc_type_lookup	        mt_reloc_type_lookup
634
635#define elf_backend_gc_mark_hook		mt_elf_gc_mark_hook
636#define elf_backend_gc_sweep_hook		mt_elf_gc_sweep_hook
637#define elf_backend_check_relocs                mt_elf_check_relocs
638#define elf_backend_object_p		        mt_elf_object_p
639#define elf_backend_rela_normal			1
640
641#define elf_backend_can_gc_sections		1
642
643#define bfd_elf32_bfd_set_private_flags		mt_elf_set_private_flags
644#define bfd_elf32_bfd_copy_private_bfd_data	mt_elf_copy_private_bfd_data
645#define bfd_elf32_bfd_merge_private_bfd_data	mt_elf_merge_private_bfd_data
646#define bfd_elf32_bfd_print_private_bfd_data	mt_elf_print_private_bfd_data
647
648#include "elf32-target.h"
649