]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf32-h8300.c
Cleanups. Now passes!
[thirdparty/binutils-gdb.git] / bfd / elf32-h8300.c
CommitLineData
e01b0e69
JR
1/* Generic support for 32-bit ELF
2 Copyright 1993, 1995, 1998, 1999 Free Software Foundation, Inc.
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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
26static reloc_howto_type *elf32_h8_reloc_type_lookup
27 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28static void elf32_h8_info_to_howto
29 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
5e47149d
JL
30static void elf32_h8_info_to_howto_rel
31 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
32static int elf32_h8_mach
33 PARAMS ((flagword));
34static 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));
38static 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 **));
e01b0e69
JR
42
43/* This does not include any relocation information, but should be
44 good enough for GDB or objdump to read the file. */
45
46static 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
178struct 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
186static 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
0a83638b 199
e01b0e69
JR
200static reloc_howto_type *
201elf32_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
215static void
216elf32_h8_info_to_howto (abfd, bfd_reloc, elf_reloc)
217 bfd *abfd ATTRIBUTE_UNUSED;
218 arelent *bfd_reloc;
5e47149d 219 Elf32_Internal_Rela *elf_reloc;
e01b0e69
JR
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
234static void
235elf32_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
5e47149d
JL
247
248/* Perform a relocation as part of a final link. */
249static bfd_reloc_status_type
250elf32_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. */
314static boolean
315elf32_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
0a83638b
JL
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. */
481static int
482elf32_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
503void
504elf32_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
533boolean
534elf32_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
546boolean
547elf32_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
e01b0e69
JR
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
0a83638b
JL
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
e01b0e69
JR
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
5e47149d
JL
592/* Use an H8 specific linker, not the ELF generic linker. */
593#define elf_backend_relocate_section elf32_h8_relocate_section
594
e01b0e69 595#include "elf32-target.h"