9896a208d6b7e8b7c09d92ba05ea3cef6659b4c3
[platform/upstream/binutils.git] / bfd / elf32-mt.c
1 /* Morpho Technologies MT specific support for 32-bit ELF
2    Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
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 3 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,
20    MA 02111-1307, USA.  */
21
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/mt.h"
27
28 /* Prototypes.  */
29 static reloc_howto_type * mt_reloc_type_lookup 
30   (bfd *, bfd_reloc_code_real_type);
31
32 static void mt_info_to_howto_rela
33   (bfd *, arelent *, Elf_Internal_Rela *);
34
35 static bfd_reloc_status_type mt_elf_relocate_hi16
36   (bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma);
37
38 static bfd_reloc_status_type mt_final_link_relocate
39   (reloc_howto_type *, bfd *, asection *, bfd_byte *, 
40    Elf_Internal_Rela *, bfd_vma);
41
42 static bfd_boolean mt_elf_relocate_section
43   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 
44    Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
45
46 /* Relocation tables.  */
47 static reloc_howto_type mt_elf_howto_table [] =
48 {
49   /* This reloc does nothing.  */
50   HOWTO (R_MT_NONE,           /* type */
51           0,                      /* rightshift */ 
52           2,                      /* size (0 = byte, 1 = short, 2 = long) */ 
53           32,                     /* bitsize */
54           FALSE,                  /* pc_relative */ 
55           0,                      /* bitpos */ 
56           complain_overflow_dont, /* complain_on_overflow */ 
57           bfd_elf_generic_reloc,  /* special_function */ 
58           "R_MT_NONE",          /* name */ 
59           FALSE,                  /* partial_inplace */ 
60           0 ,                     /* src_mask */ 
61           0,                      /* dst_mask */ 
62           FALSE),                 /* pcrel_offset */
63
64   /* A 16 bit absolute relocation.  */
65   HOWTO (R_MT_16,             /* type */
66           0,                      /* rightshift */ 
67           2,                      /* size (0 = byte, 1 = short, 2 = long) */ 
68           16,                     /* bitsize */
69           FALSE,                  /* pc_relative */ 
70           0,                      /* bitpos */ 
71           complain_overflow_dont, /* complain_on_overflow */ 
72           bfd_elf_generic_reloc,  /* special_function */ 
73           "R_MT_16",            /* name */ 
74           FALSE,                  /* partial_inplace */ 
75           0 ,                     /* src_mask */ 
76           0xffff,                 /* dst_mask */ 
77           FALSE),                 /* pcrel_offset */
78
79   /* A 32 bit absolute relocation.  */
80   HOWTO (R_MT_32,             /* type */
81           0,                      /* rightshift */ 
82           2,                      /* size (0 = byte, 1 = short, 2 = long) */ 
83           32,                     /* bitsize */
84           FALSE,                  /* pc_relative */ 
85           0,                      /* bitpos */ 
86           complain_overflow_dont, /* complain_on_overflow */ 
87           bfd_elf_generic_reloc,  /* special_function */ 
88           "R_MT_32",            /* name */ 
89           FALSE,                  /* partial_inplace */ 
90           0 ,                     /* src_mask */ 
91           0xffffffff,             /* dst_mask */ 
92           FALSE),                 /* pcrel_offset */
93
94   /* A 32 bit pc-relative relocation.  */
95   HOWTO (R_MT_32_PCREL,       /* type */
96           0,                      /* rightshift */ 
97           2,                      /* size (0 = byte, 1 = short, 2 = long) */ 
98           32,                     /* bitsize */
99           TRUE,                   /* pc_relative */ 
100           0,                      /* bitpos */ 
101           complain_overflow_dont, /* complain_on_overflow */ 
102           bfd_elf_generic_reloc,  /* special_function */ 
103           "R_MT_32_PCREL",    /* name */ 
104           FALSE,                  /* partial_inplace */ 
105           0 ,                     /* src_mask */ 
106           0xffffffff,             /* dst_mask */ 
107           TRUE),                  /* pcrel_offset */
108
109   /* A 16 bit pc-relative relocation.  */
110   HOWTO (R_MT_PC16,           /* type */
111           0,                      /* rightshift */ 
112           2,                      /* size (0 = byte, 1 = short, 2 = long) */ 
113           16,                     /* bitsize */
114           TRUE,                   /* pc_relative */ 
115           0,                      /* bitpos */ 
116           complain_overflow_signed, /* complain_on_overflow */ 
117           bfd_elf_generic_reloc,  /* special_function */ 
118           "R_MT_PC16",          /* name */ 
119           FALSE,                  /* partial_inplace */ 
120           0,                      /* src_mask */ 
121           0xffff,                 /* dst_mask */ 
122           TRUE),                  /* pcrel_offset */
123
124   /* high 16 bits of symbol value.  */
125   HOWTO (R_MT_HI16,          /* type */
126          0,                     /* rightshift */
127          2,                     /* size (0 = byte, 1 = short, 2 = long) */
128          16,                    /* bitsize */
129          FALSE,                 /* pc_relative */
130          0,                     /* bitpos */
131          complain_overflow_dont, /* complain_on_overflow */
132          bfd_elf_generic_reloc, /* special_function */
133          "R_MT_HI16",        /* name */
134          FALSE,                  /* partial_inplace */
135          0xffff0000,            /* src_mask */
136          0xffff0000,            /* dst_mask */
137          FALSE),                /* pcrel_offset */
138
139   /* Low 16 bits of symbol value.  */
140   HOWTO (R_MT_LO16,          /* type */
141          0,                     /* rightshift */
142          2,                     /* size (0 = byte, 1 = short, 2 = long) */
143          16,                    /* bitsize */
144          FALSE,                 /* pc_relative */
145          0,                     /* bitpos */
146          complain_overflow_dont, /* complain_on_overflow */
147          bfd_elf_generic_reloc, /* special_function */
148          "R_MT_LO16",        /* name */
149          FALSE,                  /* partial_inplace */
150          0xffff,                /* src_mask */
151          0xffff,                /* dst_mask */
152          FALSE),                /* pcrel_offset */
153 };
154
155 /* Map BFD reloc types to MT ELF reloc types.  */
156
157 static reloc_howto_type *
158 mt_reloc_type_lookup
159     (bfd *                    abfd ATTRIBUTE_UNUSED,
160      bfd_reloc_code_real_type code)
161 {
162   /* Note that the mt_elf_howto_table is indxed by the R_
163      constants.  Thus, the order that the howto records appear in the
164      table *must* match the order of the relocation types defined in
165      include/elf/mt.h.  */
166
167   switch (code)
168     {
169     case BFD_RELOC_NONE:
170       return &mt_elf_howto_table[ (int) R_MT_NONE];
171     case BFD_RELOC_16:
172       return &mt_elf_howto_table[ (int) R_MT_16];
173     case BFD_RELOC_32:
174       return &mt_elf_howto_table[ (int) R_MT_32];
175     case BFD_RELOC_32_PCREL:
176       return &mt_elf_howto_table[ (int) R_MT_32_PCREL];
177     case BFD_RELOC_16_PCREL:
178       return &mt_elf_howto_table[ (int) R_MT_PC16];
179     case BFD_RELOC_HI16:
180       return &mt_elf_howto_table[ (int) R_MT_HI16];
181     case BFD_RELOC_LO16:
182       return &mt_elf_howto_table[ (int) R_MT_LO16];
183
184     default:
185       /* Pacify gcc -Wall.  */
186       return NULL;
187     }
188   return NULL;
189 }
190
191 static reloc_howto_type *
192 mt_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
193                       const char *r_name)
194 {
195   unsigned int i;
196
197   for (i = 0;
198        i < sizeof (mt_elf_howto_table) / sizeof (mt_elf_howto_table[0]);
199        i++)
200     if (mt_elf_howto_table[i].name != NULL
201         && strcasecmp (mt_elf_howto_table[i].name, r_name) == 0)
202       return &mt_elf_howto_table[i];
203
204   return NULL;
205 }
206
207 bfd_reloc_status_type
208 mt_elf_relocate_hi16
209     (bfd *               input_bfd,
210      Elf_Internal_Rela * relhi,
211      bfd_byte *          contents,
212      bfd_vma             value)
213 {
214   bfd_vma insn;
215
216   insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
217
218   value += relhi->r_addend;
219   value >>= 16;
220   insn = ((insn & ~0xFFFF) | value);
221
222   bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
223   return bfd_reloc_ok;
224 }
225 \f
226 /* 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;
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);
353
354           name = h->root.root.string;
355         }
356
357       if (sec != NULL && elf_discarded_section (sec))
358         {
359           /* For relocs against symbols from removed linkonce sections,
360              or sections discarded by a linker script, we just want the
361              section contents zeroed.  Avoid any special processing.  */
362           _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
363           rel->r_info = 0;
364           rel->r_addend = 0;
365           continue;
366         }
367
368       if (info->relocatable)
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               r = 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               r = 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             r = info->callbacks->warning
416               (info, msg, name, input_bfd, input_section, rel->r_offset);
417
418           if (! r)
419             return FALSE;
420         }
421     }
422
423   return TRUE;
424 }
425
426 /* Look through the relocs for a section during the first phase.
427    Since we don't do .gots or .plts, we just need to consider the
428    virtual table relocs for gc.  */
429  
430 static bfd_boolean
431 mt_elf_check_relocs
432     (bfd *                     abfd,
433      struct bfd_link_info *    info,
434      asection *                sec,
435      const Elf_Internal_Rela * relocs)
436 {
437   Elf_Internal_Shdr *           symtab_hdr;
438   struct elf_link_hash_entry ** sym_hashes;
439   struct elf_link_hash_entry ** sym_hashes_end;
440   const Elf_Internal_Rela *     rel;
441   const Elf_Internal_Rela *     rel_end;
442   
443   if (info->relocatable)
444     return TRUE;
445   
446   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
447   sym_hashes = elf_sym_hashes (abfd);
448   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
449   if (!elf_bad_symtab (abfd))
450     sym_hashes_end -= symtab_hdr->sh_info;
451   
452   rel_end = relocs + sec->reloc_count;
453   for (rel = relocs; rel < rel_end; rel++)
454     {
455       struct elf_link_hash_entry *h;
456       unsigned long r_symndx;
457       
458       r_symndx = ELF32_R_SYM (rel->r_info);
459       if (r_symndx < symtab_hdr->sh_info)
460         h = NULL;
461       else
462         {
463           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
464           while (h->root.type == bfd_link_hash_indirect
465                  || h->root.type == bfd_link_hash_warning)
466             h = (struct elf_link_hash_entry *) h->root.u.i.link;
467         }
468     }
469
470   return TRUE;
471 }
472
473 /* Return the MACH for an e_flags value.  */
474
475 static int
476 elf32_mt_machine (bfd *abfd)
477 {
478   switch (elf_elfheader (abfd)->e_flags & EF_MT_CPU_MASK)
479     {
480     case EF_MT_CPU_MRISC:       return bfd_mach_ms1;
481     case EF_MT_CPU_MRISC2:      return bfd_mach_mrisc2;
482     case EF_MT_CPU_MS2:         return bfd_mach_ms2;
483     }
484
485   return bfd_mach_ms1;
486 }
487
488 static bfd_boolean
489 mt_elf_object_p (bfd * abfd)
490 {
491   bfd_default_set_arch_mach (abfd, bfd_arch_mt, elf32_mt_machine (abfd));
492
493   return TRUE;
494 }
495
496 /* Function to set the ELF flag bits.  */
497
498 static bfd_boolean
499 mt_elf_set_private_flags (bfd *    abfd,
500                            flagword flags)
501 {
502   elf_elfheader (abfd)->e_flags = flags;
503   elf_flags_init (abfd) = TRUE;
504   return TRUE;
505 }
506
507 static bfd_boolean
508 mt_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
509 {
510   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
511       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
512     return TRUE;
513   
514   BFD_ASSERT (!elf_flags_init (obfd)
515               || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
516
517   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
518   elf_flags_init (obfd) = TRUE;
519
520   /* Copy object attributes.  */
521   _bfd_elf_copy_obj_attributes (ibfd, obfd);
522
523   return TRUE;
524 }
525
526 /* Merge backend specific data from an object file to the output
527    object file when linking.  */
528
529 static bfd_boolean
530 mt_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
531 {
532   flagword     old_flags, new_flags;
533   bfd_boolean  ok = TRUE;
534
535   /* Check if we have the same endianess.  */
536   if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
537     return FALSE;
538
539   /* If they're not both mt, then merging is meaningless, so just
540      don't do it.  */
541   if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
542     return TRUE;
543   if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
544     return TRUE;
545
546   new_flags = elf_elfheader (ibfd)->e_flags;
547   old_flags = elf_elfheader (obfd)->e_flags;
548
549 #ifdef DEBUG
550   _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
551                       ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
552 #endif
553
554   if (!elf_flags_init (obfd))
555     {
556       old_flags = new_flags;
557       elf_flags_init (obfd) = TRUE;
558     }
559   else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
560     {
561       /* CPU has changed.  This is invalid, because MRISC, MRISC2 and
562          MS2 are not subsets of each other.   */
563       ok = FALSE;
564     }
565   
566   if (ok)
567     {
568       obfd->arch_info = ibfd->arch_info;
569       elf_elfheader (obfd)->e_flags = old_flags;
570     }
571
572   return ok;
573 }
574
575 static bfd_boolean
576 mt_elf_print_private_bfd_data (bfd * abfd, void * ptr)
577 {
578   FILE *   file = (FILE *) ptr;
579   flagword flags;
580
581   BFD_ASSERT (abfd != NULL && ptr != NULL);
582   
583   /* Print normal ELF private data.  */
584   _bfd_elf_print_private_bfd_data (abfd, ptr);
585
586   flags = elf_elfheader (abfd)->e_flags;
587   fprintf (file, _("private flags = 0x%lx:"), (long)flags);
588
589   switch (flags & EF_MT_CPU_MASK)
590     {
591     default:
592     case EF_MT_CPU_MRISC:   fprintf (file, " ms1-16-002");      break;
593     case EF_MT_CPU_MRISC2:  fprintf (file, " ms1-16-003");      break;
594     case EF_MT_CPU_MS2:     fprintf (file, " ms2");     break;
595     }
596
597   fputc ('\n', file);
598
599   return TRUE;
600 }
601
602 \f
603 #define TARGET_BIG_SYM   bfd_elf32_mt_vec
604 #define TARGET_BIG_NAME  "elf32-mt"
605
606 #define ELF_ARCH         bfd_arch_mt
607 #define ELF_MACHINE_CODE EM_MT
608 #define ELF_MAXPAGESIZE  1 /* No pages on the MT.  */
609
610 #define elf_info_to_howto_rel                   NULL
611 #define elf_info_to_howto                       mt_info_to_howto_rela
612
613 #define elf_backend_relocate_section            mt_elf_relocate_section
614
615 #define bfd_elf32_bfd_reloc_type_lookup         mt_reloc_type_lookup
616 #define bfd_elf32_bfd_reloc_name_lookup   mt_reloc_name_lookup
617
618 #define elf_backend_check_relocs                mt_elf_check_relocs
619 #define elf_backend_object_p                    mt_elf_object_p
620 #define elf_backend_rela_normal                 1
621
622 #define elf_backend_can_gc_sections             1
623
624 #define bfd_elf32_bfd_set_private_flags         mt_elf_set_private_flags
625 #define bfd_elf32_bfd_copy_private_bfd_data     mt_elf_copy_private_bfd_data
626 #define bfd_elf32_bfd_merge_private_bfd_data    mt_elf_merge_private_bfd_data
627 #define bfd_elf32_bfd_print_private_bfd_data    mt_elf_print_private_bfd_data
628
629 #include "elf32-target.h"