* elf32-h8300.c: Put all prototypes together.
[external/binutils.git] / bfd / elf32-h8300.c
1 /* Generic support for 32-bit ELF
2    Copyright 1993, 1995, 1998, 1999 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 2 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, MA 02111-1307, USA.  */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23 #include "elf-bfd.h"
24 #include "elf/h8.h"
25
26 static reloc_howto_type *elf32_h8_reloc_type_lookup
27   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28 static void elf32_h8_info_to_howto
29   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
30 static void elf32_h8_info_to_howto_rel
31   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
32 static int elf32_h8_mach
33   PARAMS ((flagword));
34 static bfd_reloc_status_type elf32_h8_final_link_relocate
35   PARAMS ((unsigned long, bfd *, bfd *, asection *,
36            bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
37            struct bfd_link_info *, asection *, int));
38 static boolean elf32_h8_relocate_section
39   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
40            bfd_byte *, Elf_Internal_Rela *,
41            Elf_Internal_Sym *, asection **));
42
43 /* This does not include any relocation information, but should be
44    good enough for GDB or objdump to read the file.  */
45
46 static reloc_howto_type h8_elf_howto_table[] =
47 {
48 #define R_H8_NONE_X 0
49   HOWTO (R_H8_NONE,             /* type */
50          0,                     /* rightshift */
51          0,                     /* 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          NULL,                  /* special_function */
57          "R_H8_NONE",           /* name */
58          false,                 /* partial_inplace */
59          0,                     /* src_mask */
60          0,                     /* dst_mask */
61          false),                /* pcrel_offset */
62 #define R_H8_DIR32_X (R_H8_NONE_X + 1)
63   HOWTO (R_H8_DIR32,            /* type */
64          0,                     /* rightshift */
65          2,                     /* size (0 = byte, 1 = short, 2 = long) */
66          32,                    /* bitsize */
67          false,                 /* pc_relative */
68          0,                     /* bitpos */
69          complain_overflow_dont, /* complain_on_overflow */
70          NULL,                  /* special_function */
71          "R_H8_DIR32",          /* name */
72          false,                 /* partial_inplace */
73          0,                     /* src_mask */
74          0xffffffff,            /* dst_mask */
75          false),                /* pcrel_offset */
76 #define R_H8_DIR16_X (R_H8_DIR32_X + 1)
77   HOWTO (R_H8_DIR16,            /* type */
78          0,                     /* rightshift */
79          1,                     /* size (0 = byte, 1 = short, 2 = long) */
80          16,                    /* bitsize */
81          false,                 /* pc_relative */
82          0,                     /* bitpos */
83          complain_overflow_dont, /* complain_on_overflow */
84          NULL,                  /* special_function */
85          "R_H8_DIR16",          /* name */
86          false,                 /* partial_inplace */
87          0,                     /* src_mask */
88          0x0000ffff,            /* dst_mask */
89          false),                /* pcrel_offset */
90 #define R_H8_DIR8_X (R_H8_DIR16_X + 1)
91   HOWTO (R_H8_DIR8,             /* type */
92          0,                     /* rightshift */
93          0,                     /* size (0 = byte, 1 = short, 2 = long) */
94          8,                     /* bitsize */
95          false,                 /* pc_relative */
96          0,                     /* bitpos */
97          complain_overflow_dont, /* complain_on_overflow */
98          NULL,                  /* special_function */
99          "R_H8_DIR16",          /* name */
100          false,                 /* partial_inplace */
101          0,                     /* src_mask */
102          0x000000ff,            /* dst_mask */
103          false),                /* pcrel_offset */
104 #define R_H8_DIR16A8_X (R_H8_DIR8_X + 1)
105   HOWTO (R_H8_DIR16A8,          /* type */
106          0,                     /* rightshift */
107          1,                     /* size (0 = byte, 1 = short, 2 = long) */
108          16,                    /* bitsize */
109          false,                 /* pc_relative */
110          0,                     /* bitpos */
111          complain_overflow_bitfield, /* complain_on_overflow */
112          NULL,                  /* special_function */
113          "R_H8_DIR16A8",        /* name */
114          false,                 /* partial_inplace */
115          0,                     /* src_mask */
116          0x0000ffff,            /* dst_mask */
117          false),                /* pcrel_offset */
118 #define R_H8_DIR16R8_X (R_H8_DIR16A8_X + 1)
119   HOWTO (R_H8_DIR16R8,          /* type */
120          0,                     /* rightshift */
121          1,                     /* size (0 = byte, 1 = short, 2 = long) */
122          16,                    /* bitsize */
123          false,                 /* pc_relative */
124          0,                     /* bitpos */
125          complain_overflow_bitfield, /* complain_on_overflow */
126          NULL,                  /* special_function */
127          "R_H8_DIR16R8",        /* name */
128          false,                 /* partial_inplace */
129          0,                     /* src_mask */
130          0x0000ffff,            /* dst_mask */
131          false),                /* pcrel_offset */
132 #define R_H8_DIR24A8_X (R_H8_DIR16R8_X + 1)
133   HOWTO (R_H8_DIR24A8,          /* type */
134          0,                     /* rightshift */
135          2,                     /* size (0 = byte, 1 = short, 2 = long) */
136          24,                    /* bitsize */
137          false,                 /* pc_relative */
138          0,                     /* bitpos */
139          complain_overflow_bitfield, /* complain_on_overflow */
140          NULL,                  /* special_function */
141          "R_H8_DIR24A8",        /* name */
142          true,                  /* partial_inplace */
143          0xff000000,            /* src_mask */
144          0x00ffffff,            /* dst_mask */
145          false),                /* pcrel_offset */
146 #define R_H8_DIR24R8_X (R_H8_DIR24A8_X + 1)
147   HOWTO (R_H8_DIR24R8,          /* type */
148          0,                     /* rightshift */
149          2,                     /* size (0 = byte, 1 = short, 2 = long) */
150          24,                    /* bitsize */
151          false,                 /* pc_relative */
152          0,                     /* bitpos */
153          complain_overflow_bitfield, /* complain_on_overflow */
154          NULL,                  /* special_function */
155          "R_H8_DIR24R8",        /* name */
156          true,                  /* partial_inplace */
157          0xff000000,            /* src_mask */
158          0x00ffffff,            /* dst_mask */
159          false),                /* pcrel_offset */
160 #define R_H8_DIR32A16_X (R_H8_DIR24R8_X + 1)
161   HOWTO (R_H8_DIR32A16,         /* type */
162          0,                     /* rightshift */
163          2,                     /* size (0 = byte, 1 = short, 2 = long) */
164          32,                    /* bitsize */
165          false,                 /* pc_relative */
166          0,                     /* bitpos */
167          complain_overflow_dont, /* complain_on_overflow */
168          NULL,                  /* special_function */
169          "R_H8_DIR32",          /* name */
170          false,                 /* partial_inplace */
171          0,                     /* src_mask */
172          0xffffffff,            /* dst_mask */
173          false),                /* pcrel_offset */
174 };
175
176 /* This structure is used to map BFD reloc codes to H8 ELF relocs.  */
177
178 struct elf_reloc_map
179 {
180   bfd_reloc_code_real_type bfd_reloc_val;
181   unsigned char howto_index;
182 };
183
184 /* An array mapping BFD reloc codes to SH ELF relocs.  */
185
186 static const struct elf_reloc_map h8_reloc_map[] =
187 {
188   { BFD_RELOC_NONE, R_H8_NONE_X },
189   { BFD_RELOC_32, R_H8_DIR32_X },
190   { BFD_RELOC_16, R_H8_DIR16_X },
191   { BFD_RELOC_8, R_H8_DIR8_X },
192   { BFD_RELOC_H8_DIR16A8, R_H8_DIR16A8_X },
193   { BFD_RELOC_H8_DIR16R8, R_H8_DIR16R8_X },
194   { BFD_RELOC_H8_DIR24A8, R_H8_DIR24A8_X },
195   { BFD_RELOC_H8_DIR24R8, R_H8_DIR24R8_X },
196   { BFD_RELOC_H8_DIR32A16, R_H8_DIR32A16_X },
197 };
198
199
200 static reloc_howto_type *
201 elf32_h8_reloc_type_lookup (abfd, code)
202      bfd *abfd ATTRIBUTE_UNUSED;
203      bfd_reloc_code_real_type code;
204 {
205   unsigned int i;
206
207   for (i = 0; i < sizeof (h8_reloc_map) / sizeof (struct elf_reloc_map); i++)
208     {
209       if (h8_reloc_map[i].bfd_reloc_val == code)
210         return &h8_elf_howto_table[(int) h8_reloc_map[i].howto_index];
211     }
212   return NULL;
213 }
214
215 static void
216 elf32_h8_info_to_howto (abfd, bfd_reloc, elf_reloc)
217      bfd *abfd ATTRIBUTE_UNUSED;
218      arelent *bfd_reloc;
219      Elf32_Internal_Rela *elf_reloc;
220 {
221   unsigned int r;
222   unsigned int i;
223
224   r = ELF32_R_TYPE (elf_reloc->r_info);
225   for (i = 0; i < sizeof (h8_elf_howto_table) / sizeof (reloc_howto_type); i++)
226     if (h8_elf_howto_table[i].type== r)
227       {
228         bfd_reloc->howto = &h8_elf_howto_table[i];
229         return;
230       }
231   abort ();
232 }
233
234 static void
235 elf32_h8_info_to_howto_rel (abfd, bfd_reloc, elf_reloc)
236      bfd *abfd ATTRIBUTE_UNUSED;
237      arelent *bfd_reloc;
238      Elf32_Internal_Rel *elf_reloc ATTRIBUTE_UNUSED;
239 {
240   unsigned int r;
241
242   abort ();
243   r = ELF32_R_TYPE (elf_reloc->r_info);
244   bfd_reloc->howto = &h8_elf_howto_table[r];
245 }
246
247
248 /* Perform a relocation as part of a final link.  */
249 static bfd_reloc_status_type
250 elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
251                               input_section, contents, offset, value,
252                               addend, info, sym_sec, is_local)
253      unsigned long r_type;
254      bfd *input_bfd;
255      bfd *output_bfd ATTRIBUTE_UNUSED;
256      asection *input_section ATTRIBUTE_UNUSED;
257      bfd_byte *contents;
258      bfd_vma offset;
259      bfd_vma value;
260      bfd_vma addend;
261      struct bfd_link_info *info ATTRIBUTE_UNUSED;
262      asection *sym_sec ATTRIBUTE_UNUSED;
263      int is_local ATTRIBUTE_UNUSED;
264 {
265   bfd_byte *hit_data = contents + offset;
266
267   switch (r_type)
268     {
269
270     case R_H8_NONE:
271       return bfd_reloc_ok;
272
273     case R_H8_DIR32:
274     case R_H8_DIR32A16:
275       value += addend;
276       bfd_put_32 (input_bfd, value, hit_data);
277       return bfd_reloc_ok;
278
279     case R_H8_DIR16:
280     case R_H8_DIR16A8:
281     case R_H8_DIR16R8:
282       value += addend;
283       bfd_put_16 (input_bfd, value, hit_data);
284       return bfd_reloc_ok;
285
286     /* AKA R_RELBYTE */
287     case R_H8_DIR8:
288       value += addend;
289
290       if ((long) value > 0x7f || (long) value < -0x80)
291         return bfd_reloc_overflow;
292
293       bfd_put_8 (input_bfd, value, hit_data);
294       return bfd_reloc_ok;
295
296     case R_H8_DIR24A8:
297     case R_H8_DIR24R8:
298       value += addend;
299
300       if ((long) value > 0x7fffff || (long) value < -0x800000)
301         return bfd_reloc_overflow;
302
303       value &= 0xffffff;
304       value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
305       bfd_put_32 (input_bfd, value, hit_data);
306       return bfd_reloc_ok;
307
308     default:
309       return bfd_reloc_notsupported;
310     }
311 }
312 \f
313 /* Relocate an H8 ELF section.  */
314 static boolean
315 elf32_h8_relocate_section (output_bfd, info, input_bfd, input_section,
316                            contents, relocs, local_syms, local_sections)
317      bfd *output_bfd;
318      struct bfd_link_info *info;
319      bfd *input_bfd;
320      asection *input_section;
321      bfd_byte *contents;
322      Elf_Internal_Rela *relocs;
323      Elf_Internal_Sym *local_syms;
324      asection **local_sections;
325 {
326   Elf_Internal_Shdr *symtab_hdr;
327   struct elf_link_hash_entry **sym_hashes;
328   Elf_Internal_Rela *rel, *relend;
329
330   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
331   sym_hashes = elf_sym_hashes (input_bfd);
332
333   rel = relocs;
334   relend = relocs + input_section->reloc_count;
335   for (; rel < relend; rel++)
336     {
337       int r_type;
338       unsigned long r_symndx;
339       Elf_Internal_Sym *sym;
340       asection *sec;
341       struct elf_link_hash_entry *h;
342       bfd_vma relocation;
343       bfd_reloc_status_type r;
344
345       r_symndx = ELF32_R_SYM (rel->r_info);
346       r_type = ELF32_R_TYPE (rel->r_info);
347
348       if (info->relocateable)
349         {
350           /* This is a relocateable link.  We don't have to change
351              anything, unless the reloc is against a section symbol,
352              in which case we have to adjust according to where the
353              section symbol winds up in the output section.  */
354           if (r_symndx < symtab_hdr->sh_info)
355             {
356               sym = local_syms + r_symndx;
357               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
358                 {
359                   sec = local_sections[r_symndx];
360                   rel->r_addend += sec->output_offset + sym->st_value;
361                 }
362             }
363
364           continue;
365         }
366
367       /* This is a final link.  */
368       h = NULL;
369       sym = NULL;
370       sec = NULL;
371       if (r_symndx < symtab_hdr->sh_info)
372         {
373           sym = local_syms + r_symndx;
374           sec = local_sections[r_symndx];
375           relocation = (sec->output_section->vma
376                         + sec->output_offset
377                         + sym->st_value);
378         }
379       else
380         {
381           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
382           while (h->root.type == bfd_link_hash_indirect
383                  || h->root.type == bfd_link_hash_warning)
384             h = (struct elf_link_hash_entry *) h->root.u.i.link;
385           if (h->root.type == bfd_link_hash_defined
386               || h->root.type == bfd_link_hash_defweak)
387             {
388               sec = h->root.u.def.section;
389               relocation = (h->root.u.def.value
390                             + sec->output_section->vma
391                             + sec->output_offset);
392             }
393           else if (h->root.type == bfd_link_hash_undefweak)
394             relocation = 0;
395           else
396             {
397               if (! ((*info->callbacks->undefined_symbol)
398                      (info, h->root.root.string, input_bfd,
399                       input_section, rel->r_offset, true)))
400                 return false;
401               relocation = 0;
402             }
403         }
404
405       r = elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
406                                         input_section,
407                                         contents, rel->r_offset,
408                                         relocation, rel->r_addend,
409                                         info, sec, h == NULL);
410
411       if (r != bfd_reloc_ok)
412         {
413           const char *name;
414           const char *msg = (const char *) 0;
415           arelent bfd_reloc;
416           reloc_howto_type *howto;
417
418           elf32_h8_info_to_howto (input_bfd, &bfd_reloc, rel);
419           howto = bfd_reloc.howto;
420           
421           if (h != NULL)
422             name = h->root.root.string;
423           else
424             {
425               name = (bfd_elf_string_from_elf_section
426                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
427               if (name == NULL || *name == '\0')
428                 name = bfd_section_name (input_bfd, sec);
429             }
430
431           switch (r)
432             {
433             case bfd_reloc_overflow:
434               if (! ((*info->callbacks->reloc_overflow)
435                      (info, name, howto->name, (bfd_vma) 0,
436                       input_bfd, input_section, rel->r_offset)))
437                 return false;
438               break;
439
440             case bfd_reloc_undefined:
441               if (! ((*info->callbacks->undefined_symbol)
442                      (info, name, input_bfd, input_section,
443                       rel->r_offset, true)))
444                 return false;
445               break;
446
447             case bfd_reloc_outofrange:
448               msg = _("internal error: out of range error");
449               goto common_error;
450
451             case bfd_reloc_notsupported:
452               msg = _("internal error: unsupported relocation error");
453               goto common_error;
454
455             case bfd_reloc_dangerous:
456               msg = _("internal error: dangerous error");
457               goto common_error;
458
459             default:
460               msg = _("internal error: unknown error");
461               /* fall through */
462
463             common_error:
464               if (!((*info->callbacks->warning)
465                     (info, msg, name, input_bfd, input_section,
466                      rel->r_offset)))
467                 return false;
468               break;
469             }
470         }
471     }
472
473   return true;
474 }
475
476 /* Object files encode the specific H8 model they were compiled
477    for in the ELF flags field.
478
479    Examine that field and return the proper BFD machine type for
480    the object file.  */
481 static int
482 elf32_h8_mach (flags)
483      flagword flags;
484 {
485   switch (flags & EF_H8_MACH)
486     {
487     case E_H8_MACH_H8300:
488     default:
489       return bfd_mach_h8300;
490
491     case E_H8_MACH_H8300H:
492       return bfd_mach_h8300h;
493
494     case E_H8_MACH_H8300S:
495       return bfd_mach_h8300s;
496     }
497 }
498
499 /* The final processing done just before writing out a H8 ELF object
500    file.  We use this opportunity to encode the BFD machine type
501    into the flags field in the object file.  */
502
503 void
504 elf32_h8_final_write_processing (abfd, linker)
505      bfd *abfd;
506      boolean linker ATTRIBUTE_UNUSED;
507 {
508   unsigned long val;
509
510   switch (bfd_get_mach (abfd))
511     {
512     default:
513     case bfd_mach_h8300:
514       val = E_H8_MACH_H8300;
515       break;
516
517     case bfd_mach_h8300h:
518       val = E_H8_MACH_H8300H;
519       break;
520
521     case bfd_mach_h8300s:
522       val = E_H8_MACH_H8300S;
523       break;
524     }
525
526   elf_elfheader (abfd)->e_flags &= ~ (EF_H8_MACH);
527   elf_elfheader (abfd)->e_flags |= val;
528 }
529
530 /* Return nonzero if ABFD represents a valid H8 ELF object file; also
531    record the encoded machine type found in the ELF flags.  */
532
533 boolean
534 elf32_h8_object_p (abfd)
535      bfd *abfd;
536 {
537   bfd_default_set_arch_mach (abfd, bfd_arch_h8300,
538                              elf32_h8_mach (elf_elfheader (abfd)->e_flags));
539   return true;
540 }
541
542 /* Merge backend specific data from an object file to the output
543    object file when linking.  The only data we need to copy at this
544    time is the architecture/machine information.  */
545
546 boolean
547 elf32_h8_merge_private_bfd_data (ibfd, obfd)
548      bfd *ibfd;
549      bfd *obfd;
550 {
551   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
552       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
553     return true;
554
555   if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
556       && bfd_get_mach (obfd) < bfd_get_mach (ibfd))
557     {
558       if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
559                                bfd_get_mach (ibfd)))
560         return false;
561     }
562
563   return true;
564 }
565
566
567 #define TARGET_BIG_SYM                  bfd_elf32_h8300_vec
568 #define TARGET_BIG_NAME                 "elf32-h8300"
569 #define ELF_ARCH                        bfd_arch_h8300
570 #define ELF_MACHINE_CODE                EM_H8_300
571 #define ELF_MAXPAGESIZE                 0x1
572 #define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
573 #define elf_info_to_howto               elf32_h8_info_to_howto
574 #define elf_info_to_howto_rel           elf32_h8_info_to_howto_rel
575
576 /* So we can set/examine bits in e_flags to get the specific
577    H8 architecture in use.  */
578 #define elf_backend_final_write_processing \
579   elf32_h8_final_write_processing
580 #define elf_backend_object_p \
581   elf32_h8_object_p
582 #define bfd_elf32_bfd_merge_private_bfd_data \
583   elf32_h8_merge_private_bfd_data
584
585 /* ??? when elf_backend_relocate_section is not defined, elf32-target.h
586    defaults to using _bfd_generic_link_hash_table_create, but
587    elflink.h:bfd_elf32_size_dynamic_sections uses
588    dynobj = elf_hash_table (info)->dynobj;
589    and thus requires an elf hash table.  */
590 #define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
591
592 /* Use an H8 specific linker, not the ELF generic linker.  */
593 #define elf_backend_relocate_section elf32_h8_relocate_section
594
595 #include "elf32-target.h"