* elf32-h8300.c (h8_elf_howto_table): Add new PC relative
[platform/upstream/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 #define R_H8_PCREL16_X (R_H8_DIR32A16_X + 1)
175   HOWTO (R_H8_PCREL16,          /* type */
176          0,                     /* rightshift */
177          1,                     /* size (0 = byte, 1 = short, 2 = long) */
178          16,                    /* bitsize */
179          true,                  /* pc_relative */
180          0,                     /* bitpos */
181          complain_overflow_signed, /* complain_on_overflow */
182          NULL,                  /* special_function */
183          "R_H8_PCREL16",        /* name */
184          false,                 /* partial_inplace */
185          0xffff,                /* src_mask */
186          0xffff,                /* dst_mask */
187          true),                 /* pcrel_offset */
188 #define R_H8_PCREL8_X (R_H8_PCREL16_X + 1)
189   HOWTO (R_H8_PCREL8,           /* type */
190          0,                     /* rightshift */
191          0,                     /* size (0 = byte, 1 = short, 2 = long) */
192          8,                     /* bitsize */
193          true,                  /* pc_relative */
194          0,                     /* bitpos */
195          complain_overflow_signed, /* complain_on_overflow */
196          NULL,                  /* special_function */
197          "R_H8_PCREL8",         /* name */
198          false,                 /* partial_inplace */
199          0xff,                  /* src_mask */
200          0xff,                  /* dst_mask */
201          true),                 /* pcrel_offset */
202 };
203
204 /* This structure is used to map BFD reloc codes to H8 ELF relocs.  */
205
206 struct elf_reloc_map
207 {
208   bfd_reloc_code_real_type bfd_reloc_val;
209   unsigned char howto_index;
210 };
211
212 /* An array mapping BFD reloc codes to SH ELF relocs.  */
213
214 static const struct elf_reloc_map h8_reloc_map[] =
215 {
216   { BFD_RELOC_NONE, R_H8_NONE_X },
217   { BFD_RELOC_32, R_H8_DIR32_X },
218   { BFD_RELOC_16, R_H8_DIR16_X },
219   { BFD_RELOC_8, R_H8_DIR8_X },
220   { BFD_RELOC_H8_DIR16A8, R_H8_DIR16A8_X },
221   { BFD_RELOC_H8_DIR16R8, R_H8_DIR16R8_X },
222   { BFD_RELOC_H8_DIR24A8, R_H8_DIR24A8_X },
223   { BFD_RELOC_H8_DIR24R8, R_H8_DIR24R8_X },
224   { BFD_RELOC_H8_DIR32A16, R_H8_DIR32A16_X },
225   { BFD_RELOC_16_PCREL, R_H8_PCREL16_X },
226   { BFD_RELOC_8_PCREL, R_H8_PCREL8_X },
227 };
228
229
230 static reloc_howto_type *
231 elf32_h8_reloc_type_lookup (abfd, code)
232      bfd *abfd ATTRIBUTE_UNUSED;
233      bfd_reloc_code_real_type code;
234 {
235   unsigned int i;
236
237   for (i = 0; i < sizeof (h8_reloc_map) / sizeof (struct elf_reloc_map); i++)
238     {
239       if (h8_reloc_map[i].bfd_reloc_val == code)
240         return &h8_elf_howto_table[(int) h8_reloc_map[i].howto_index];
241     }
242   return NULL;
243 }
244
245 static void
246 elf32_h8_info_to_howto (abfd, bfd_reloc, elf_reloc)
247      bfd *abfd ATTRIBUTE_UNUSED;
248      arelent *bfd_reloc;
249      Elf32_Internal_Rela *elf_reloc;
250 {
251   unsigned int r;
252   unsigned int i;
253
254   r = ELF32_R_TYPE (elf_reloc->r_info);
255   for (i = 0; i < sizeof (h8_elf_howto_table) / sizeof (reloc_howto_type); i++)
256     if (h8_elf_howto_table[i].type== r)
257       {
258         bfd_reloc->howto = &h8_elf_howto_table[i];
259         return;
260       }
261   abort ();
262 }
263
264 static void
265 elf32_h8_info_to_howto_rel (abfd, bfd_reloc, elf_reloc)
266      bfd *abfd ATTRIBUTE_UNUSED;
267      arelent *bfd_reloc;
268      Elf32_Internal_Rel *elf_reloc ATTRIBUTE_UNUSED;
269 {
270   unsigned int r;
271
272   abort ();
273   r = ELF32_R_TYPE (elf_reloc->r_info);
274   bfd_reloc->howto = &h8_elf_howto_table[r];
275 }
276
277
278 /* Perform a relocation as part of a final link.  */
279 static bfd_reloc_status_type
280 elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
281                               input_section, contents, offset, value,
282                               addend, info, sym_sec, is_local)
283      unsigned long r_type;
284      bfd *input_bfd;
285      bfd *output_bfd ATTRIBUTE_UNUSED;
286      asection *input_section ATTRIBUTE_UNUSED;
287      bfd_byte *contents;
288      bfd_vma offset;
289      bfd_vma value;
290      bfd_vma addend;
291      struct bfd_link_info *info ATTRIBUTE_UNUSED;
292      asection *sym_sec ATTRIBUTE_UNUSED;
293      int is_local ATTRIBUTE_UNUSED;
294 {
295   bfd_byte *hit_data = contents + offset;
296
297   switch (r_type)
298     {
299
300     case R_H8_NONE:
301       return bfd_reloc_ok;
302
303     case R_H8_DIR32:
304     case R_H8_DIR32A16:
305       value += addend;
306       bfd_put_32 (input_bfd, value, hit_data);
307       return bfd_reloc_ok;
308
309     case R_H8_DIR16:
310     case R_H8_DIR16A8:
311     case R_H8_DIR16R8:
312       value += addend;
313       bfd_put_16 (input_bfd, value, hit_data);
314       return bfd_reloc_ok;
315
316     /* AKA R_RELBYTE */
317     case R_H8_DIR8:
318       value += addend;
319
320       bfd_put_8 (input_bfd, value, hit_data);
321       return bfd_reloc_ok;
322
323     case R_H8_DIR24A8:
324     case R_H8_DIR24R8:
325       value += addend;
326
327       value &= 0xffffff;
328       value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
329       bfd_put_32 (input_bfd, value, hit_data);
330       return bfd_reloc_ok;
331
332     case R_H8_PCREL16:
333       value -= (input_section->output_section->vma
334                 + input_section->output_offset);
335       value -= offset;
336       value += addend;
337
338       bfd_put_16 (input_bfd, value, hit_data);
339       return bfd_reloc_ok;
340
341     case R_H8_PCREL8:
342       value -= (input_section->output_section->vma
343                 + input_section->output_offset);
344       value -= offset;
345       value += addend;
346
347       bfd_put_8 (input_bfd, value, hit_data);
348       return bfd_reloc_ok;
349
350     default:
351       return bfd_reloc_notsupported;
352     }
353 }
354 \f
355 /* Relocate an H8 ELF section.  */
356 static boolean
357 elf32_h8_relocate_section (output_bfd, info, input_bfd, input_section,
358                            contents, relocs, local_syms, local_sections)
359      bfd *output_bfd;
360      struct bfd_link_info *info;
361      bfd *input_bfd;
362      asection *input_section;
363      bfd_byte *contents;
364      Elf_Internal_Rela *relocs;
365      Elf_Internal_Sym *local_syms;
366      asection **local_sections;
367 {
368   Elf_Internal_Shdr *symtab_hdr;
369   struct elf_link_hash_entry **sym_hashes;
370   Elf_Internal_Rela *rel, *relend;
371
372   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
373   sym_hashes = elf_sym_hashes (input_bfd);
374
375   rel = relocs;
376   relend = relocs + input_section->reloc_count;
377   for (; rel < relend; rel++)
378     {
379       int r_type;
380       unsigned long r_symndx;
381       Elf_Internal_Sym *sym;
382       asection *sec;
383       struct elf_link_hash_entry *h;
384       bfd_vma relocation;
385       bfd_reloc_status_type r;
386
387       r_symndx = ELF32_R_SYM (rel->r_info);
388       r_type = ELF32_R_TYPE (rel->r_info);
389
390       if (info->relocateable)
391         {
392           /* This is a relocateable link.  We don't have to change
393              anything, unless the reloc is against a section symbol,
394              in which case we have to adjust according to where the
395              section symbol winds up in the output section.  */
396           if (r_symndx < symtab_hdr->sh_info)
397             {
398               sym = local_syms + r_symndx;
399               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
400                 {
401                   sec = local_sections[r_symndx];
402                   rel->r_addend += sec->output_offset + sym->st_value;
403                 }
404             }
405
406           continue;
407         }
408
409       /* This is a final link.  */
410       h = NULL;
411       sym = NULL;
412       sec = NULL;
413       if (r_symndx < symtab_hdr->sh_info)
414         {
415           sym = local_syms + r_symndx;
416           sec = local_sections[r_symndx];
417           relocation = (sec->output_section->vma
418                         + sec->output_offset
419                         + sym->st_value);
420         }
421       else
422         {
423           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
424           while (h->root.type == bfd_link_hash_indirect
425                  || h->root.type == bfd_link_hash_warning)
426             h = (struct elf_link_hash_entry *) h->root.u.i.link;
427           if (h->root.type == bfd_link_hash_defined
428               || h->root.type == bfd_link_hash_defweak)
429             {
430               sec = h->root.u.def.section;
431               relocation = (h->root.u.def.value
432                             + sec->output_section->vma
433                             + sec->output_offset);
434             }
435           else if (h->root.type == bfd_link_hash_undefweak)
436             relocation = 0;
437           else
438             {
439               if (! ((*info->callbacks->undefined_symbol)
440                      (info, h->root.root.string, input_bfd,
441                       input_section, rel->r_offset, true)))
442                 return false;
443               relocation = 0;
444             }
445         }
446
447       r = elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
448                                         input_section,
449                                         contents, rel->r_offset,
450                                         relocation, rel->r_addend,
451                                         info, sec, h == NULL);
452
453       if (r != bfd_reloc_ok)
454         {
455           const char *name;
456           const char *msg = (const char *) 0;
457           arelent bfd_reloc;
458           reloc_howto_type *howto;
459
460           elf32_h8_info_to_howto (input_bfd, &bfd_reloc, rel);
461           howto = bfd_reloc.howto;
462           
463           if (h != NULL)
464             name = h->root.root.string;
465           else
466             {
467               name = (bfd_elf_string_from_elf_section
468                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
469               if (name == NULL || *name == '\0')
470                 name = bfd_section_name (input_bfd, sec);
471             }
472
473           switch (r)
474             {
475             case bfd_reloc_overflow:
476               if (! ((*info->callbacks->reloc_overflow)
477                      (info, name, howto->name, (bfd_vma) 0,
478                       input_bfd, input_section, rel->r_offset)))
479                 return false;
480               break;
481
482             case bfd_reloc_undefined:
483               if (! ((*info->callbacks->undefined_symbol)
484                      (info, name, input_bfd, input_section,
485                       rel->r_offset, true)))
486                 return false;
487               break;
488
489             case bfd_reloc_outofrange:
490               msg = _("internal error: out of range error");
491               goto common_error;
492
493             case bfd_reloc_notsupported:
494               msg = _("internal error: unsupported relocation error");
495               goto common_error;
496
497             case bfd_reloc_dangerous:
498               msg = _("internal error: dangerous error");
499               goto common_error;
500
501             default:
502               msg = _("internal error: unknown error");
503               /* fall through */
504
505             common_error:
506               if (!((*info->callbacks->warning)
507                     (info, msg, name, input_bfd, input_section,
508                      rel->r_offset)))
509                 return false;
510               break;
511             }
512         }
513     }
514
515   return true;
516 }
517
518 /* Object files encode the specific H8 model they were compiled
519    for in the ELF flags field.
520
521    Examine that field and return the proper BFD machine type for
522    the object file.  */
523 static int
524 elf32_h8_mach (flags)
525      flagword flags;
526 {
527   switch (flags & EF_H8_MACH)
528     {
529     case E_H8_MACH_H8300:
530     default:
531       return bfd_mach_h8300;
532
533     case E_H8_MACH_H8300H:
534       return bfd_mach_h8300h;
535
536     case E_H8_MACH_H8300S:
537       return bfd_mach_h8300s;
538     }
539 }
540
541 /* The final processing done just before writing out a H8 ELF object
542    file.  We use this opportunity to encode the BFD machine type
543    into the flags field in the object file.  */
544
545 void
546 elf32_h8_final_write_processing (abfd, linker)
547      bfd *abfd;
548      boolean linker ATTRIBUTE_UNUSED;
549 {
550   unsigned long val;
551
552   switch (bfd_get_mach (abfd))
553     {
554     default:
555     case bfd_mach_h8300:
556       val = E_H8_MACH_H8300;
557       break;
558
559     case bfd_mach_h8300h:
560       val = E_H8_MACH_H8300H;
561       break;
562
563     case bfd_mach_h8300s:
564       val = E_H8_MACH_H8300S;
565       break;
566     }
567
568   elf_elfheader (abfd)->e_flags &= ~ (EF_H8_MACH);
569   elf_elfheader (abfd)->e_flags |= val;
570 }
571
572 /* Return nonzero if ABFD represents a valid H8 ELF object file; also
573    record the encoded machine type found in the ELF flags.  */
574
575 boolean
576 elf32_h8_object_p (abfd)
577      bfd *abfd;
578 {
579   bfd_default_set_arch_mach (abfd, bfd_arch_h8300,
580                              elf32_h8_mach (elf_elfheader (abfd)->e_flags));
581   return true;
582 }
583
584 /* Merge backend specific data from an object file to the output
585    object file when linking.  The only data we need to copy at this
586    time is the architecture/machine information.  */
587
588 boolean
589 elf32_h8_merge_private_bfd_data (ibfd, obfd)
590      bfd *ibfd;
591      bfd *obfd;
592 {
593   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
594       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
595     return true;
596
597   if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
598       && bfd_get_mach (obfd) < bfd_get_mach (ibfd))
599     {
600       if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
601                                bfd_get_mach (ibfd)))
602         return false;
603     }
604
605   return true;
606 }
607
608
609 #define TARGET_BIG_SYM                  bfd_elf32_h8300_vec
610 #define TARGET_BIG_NAME                 "elf32-h8300"
611 #define ELF_ARCH                        bfd_arch_h8300
612 #define ELF_MACHINE_CODE                EM_H8_300
613 #define ELF_MAXPAGESIZE                 0x1
614 #define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
615 #define elf_info_to_howto               elf32_h8_info_to_howto
616 #define elf_info_to_howto_rel           elf32_h8_info_to_howto_rel
617
618 /* So we can set/examine bits in e_flags to get the specific
619    H8 architecture in use.  */
620 #define elf_backend_final_write_processing \
621   elf32_h8_final_write_processing
622 #define elf_backend_object_p \
623   elf32_h8_object_p
624 #define bfd_elf32_bfd_merge_private_bfd_data \
625   elf32_h8_merge_private_bfd_data
626
627 /* ??? when elf_backend_relocate_section is not defined, elf32-target.h
628    defaults to using _bfd_generic_link_hash_table_create, but
629    elflink.h:bfd_elf32_size_dynamic_sections uses
630    dynobj = elf_hash_table (info)->dynobj;
631    and thus requires an elf hash table.  */
632 #define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
633
634 /* Use an H8 specific linker, not the ELF generic linker.  */
635 #define elf_backend_relocate_section elf32_h8_relocate_section
636
637 #include "elf32-target.h"