* elf32-h8300.c (h8_elf_howto_table): Add new PC relative
[deliverable/binutils-gdb.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"
This page took 0.045306 seconds and 4 git commands to generate.