1 /* Generic support for 32-bit ELF
2 Copyright 1993, 1995, 1998, 1999 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
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
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 static bfd_reloc_status_type special
43 PARAMS ((bfd
*, arelent
*, asymbol
*, PTR
, asection
*, bfd
*, char **));
45 /* This does not include any relocation information, but should be
46 good enough for GDB or objdump to read the file. */
48 static reloc_howto_type h8_elf_howto_table
[] =
51 HOWTO (R_H8_NONE
, /* type */
53 0, /* size (0 = byte, 1 = short, 2 = long) */
55 false, /* pc_relative */
57 complain_overflow_dont
, /* complain_on_overflow */
58 special
, /* special_function */
59 "R_H8_NONE", /* name */
60 false, /* partial_inplace */
63 false), /* pcrel_offset */
64 #define R_H8_DIR32_X (R_H8_NONE_X + 1)
65 HOWTO (R_H8_DIR32
, /* type */
67 2, /* size (0 = byte, 1 = short, 2 = long) */
69 false, /* pc_relative */
71 complain_overflow_dont
, /* complain_on_overflow */
72 special
, /* special_function */
73 "R_H8_DIR32", /* name */
74 false, /* partial_inplace */
76 0xffffffff, /* dst_mask */
77 false), /* pcrel_offset */
78 #define R_H8_DIR16_X (R_H8_DIR32_X + 1)
79 HOWTO (R_H8_DIR16
, /* type */
81 1, /* size (0 = byte, 1 = short, 2 = long) */
83 false, /* pc_relative */
85 complain_overflow_dont
, /* complain_on_overflow */
86 special
, /* special_function */
87 "R_H8_DIR16", /* name */
88 false, /* partial_inplace */
90 0x0000ffff, /* dst_mask */
91 false), /* pcrel_offset */
92 #define R_H8_DIR8_X (R_H8_DIR16_X + 1)
93 HOWTO (R_H8_DIR8
, /* type */
95 0, /* size (0 = byte, 1 = short, 2 = long) */
97 false, /* pc_relative */
99 complain_overflow_dont
, /* complain_on_overflow */
100 special
, /* special_function */
101 "R_H8_DIR16", /* name */
102 false, /* partial_inplace */
104 0x000000ff, /* dst_mask */
105 false), /* pcrel_offset */
106 #define R_H8_DIR16A8_X (R_H8_DIR8_X + 1)
107 HOWTO (R_H8_DIR16A8
, /* type */
109 1, /* size (0 = byte, 1 = short, 2 = long) */
111 false, /* pc_relative */
113 complain_overflow_bitfield
, /* complain_on_overflow */
114 special
, /* special_function */
115 "R_H8_DIR16A8", /* name */
116 false, /* partial_inplace */
118 0x0000ffff, /* dst_mask */
119 false), /* pcrel_offset */
120 #define R_H8_DIR16R8_X (R_H8_DIR16A8_X + 1)
121 HOWTO (R_H8_DIR16R8
, /* type */
123 1, /* size (0 = byte, 1 = short, 2 = long) */
125 false, /* pc_relative */
127 complain_overflow_bitfield
, /* complain_on_overflow */
128 special
, /* special_function */
129 "R_H8_DIR16R8", /* name */
130 false, /* partial_inplace */
132 0x0000ffff, /* dst_mask */
133 false), /* pcrel_offset */
134 #define R_H8_DIR24A8_X (R_H8_DIR16R8_X + 1)
135 HOWTO (R_H8_DIR24A8
, /* type */
137 2, /* size (0 = byte, 1 = short, 2 = long) */
139 false, /* pc_relative */
141 complain_overflow_bitfield
, /* complain_on_overflow */
142 special
, /* special_function */
143 "R_H8_DIR24A8", /* name */
144 true, /* partial_inplace */
145 0xff000000, /* src_mask */
146 0x00ffffff, /* dst_mask */
147 false), /* pcrel_offset */
148 #define R_H8_DIR24R8_X (R_H8_DIR24A8_X + 1)
149 HOWTO (R_H8_DIR24R8
, /* type */
151 2, /* size (0 = byte, 1 = short, 2 = long) */
153 false, /* pc_relative */
155 complain_overflow_bitfield
, /* complain_on_overflow */
156 special
, /* special_function */
157 "R_H8_DIR24R8", /* name */
158 true, /* partial_inplace */
159 0xff000000, /* src_mask */
160 0x00ffffff, /* dst_mask */
161 false), /* pcrel_offset */
162 #define R_H8_DIR32A16_X (R_H8_DIR24R8_X + 1)
163 HOWTO (R_H8_DIR32A16
, /* type */
165 2, /* size (0 = byte, 1 = short, 2 = long) */
167 false, /* pc_relative */
169 complain_overflow_dont
, /* complain_on_overflow */
170 special
, /* special_function */
171 "R_H8_DIR32", /* name */
172 false, /* partial_inplace */
174 0xffffffff, /* dst_mask */
175 false), /* pcrel_offset */
176 #define R_H8_PCREL16_X (R_H8_DIR32A16_X + 1)
177 HOWTO (R_H8_PCREL16
, /* type */
179 1, /* size (0 = byte, 1 = short, 2 = long) */
181 true, /* pc_relative */
183 complain_overflow_signed
, /* complain_on_overflow */
184 special
, /* special_function */
185 "R_H8_PCREL16", /* name */
186 false, /* partial_inplace */
187 0xffff, /* src_mask */
188 0xffff, /* dst_mask */
189 true), /* pcrel_offset */
190 #define R_H8_PCREL8_X (R_H8_PCREL16_X + 1)
191 HOWTO (R_H8_PCREL8
, /* type */
193 0, /* size (0 = byte, 1 = short, 2 = long) */
195 true, /* pc_relative */
197 complain_overflow_signed
, /* complain_on_overflow */
198 special
, /* special_function */
199 "R_H8_PCREL8", /* name */
200 false, /* partial_inplace */
203 true), /* pcrel_offset */
206 /* This structure is used to map BFD reloc codes to H8 ELF relocs. */
210 bfd_reloc_code_real_type bfd_reloc_val
;
211 unsigned char howto_index
;
214 /* An array mapping BFD reloc codes to SH ELF relocs. */
216 static const struct elf_reloc_map h8_reloc_map
[] =
218 { BFD_RELOC_NONE
, R_H8_NONE_X
},
219 { BFD_RELOC_32
, R_H8_DIR32_X
},
220 { BFD_RELOC_16
, R_H8_DIR16_X
},
221 { BFD_RELOC_8
, R_H8_DIR8_X
},
222 { BFD_RELOC_H8_DIR16A8
, R_H8_DIR16A8_X
},
223 { BFD_RELOC_H8_DIR16R8
, R_H8_DIR16R8_X
},
224 { BFD_RELOC_H8_DIR24A8
, R_H8_DIR24A8_X
},
225 { BFD_RELOC_H8_DIR24R8
, R_H8_DIR24R8_X
},
226 { BFD_RELOC_H8_DIR32A16
, R_H8_DIR32A16_X
},
227 { BFD_RELOC_16_PCREL
, R_H8_PCREL16_X
},
228 { BFD_RELOC_8_PCREL
, R_H8_PCREL8_X
},
232 static reloc_howto_type
*
233 elf32_h8_reloc_type_lookup (abfd
, code
)
234 bfd
*abfd ATTRIBUTE_UNUSED
;
235 bfd_reloc_code_real_type code
;
239 for (i
= 0; i
< sizeof (h8_reloc_map
) / sizeof (struct elf_reloc_map
); i
++)
241 if (h8_reloc_map
[i
].bfd_reloc_val
== code
)
242 return &h8_elf_howto_table
[(int) h8_reloc_map
[i
].howto_index
];
248 elf32_h8_info_to_howto (abfd
, bfd_reloc
, elf_reloc
)
249 bfd
*abfd ATTRIBUTE_UNUSED
;
251 Elf32_Internal_Rela
*elf_reloc
;
256 r
= ELF32_R_TYPE (elf_reloc
->r_info
);
257 for (i
= 0; i
< sizeof (h8_elf_howto_table
) / sizeof (reloc_howto_type
); i
++)
258 if (h8_elf_howto_table
[i
].type
== r
)
260 bfd_reloc
->howto
= &h8_elf_howto_table
[i
];
267 elf32_h8_info_to_howto_rel (abfd
, bfd_reloc
, elf_reloc
)
268 bfd
*abfd ATTRIBUTE_UNUSED
;
270 Elf32_Internal_Rel
*elf_reloc ATTRIBUTE_UNUSED
;
275 r
= ELF32_R_TYPE (elf_reloc
->r_info
);
276 bfd_reloc
->howto
= &h8_elf_howto_table
[r
];
279 /* Special handling for H8/300 relocs.
280 We only come here for pcrel stuff and return normally if not an -r link.
281 When doing -r, we can't do any arithmetic for the pcrel stuff, because
282 we support relaxing on the H8/300 series chips. */
283 static bfd_reloc_status_type
284 special (abfd
, reloc_entry
, symbol
, data
, input_section
, output_bfd
,
286 bfd
*abfd ATTRIBUTE_UNUSED
;
287 arelent
*reloc_entry ATTRIBUTE_UNUSED
;
288 asymbol
*symbol ATTRIBUTE_UNUSED
;
289 PTR data ATTRIBUTE_UNUSED
;
290 asection
*input_section ATTRIBUTE_UNUSED
;
292 char **error_message ATTRIBUTE_UNUSED
;
294 if (output_bfd
== (bfd
*) NULL
)
295 return bfd_reloc_continue
;
297 /* Adjust the reloc address to that in the output section. */
298 reloc_entry
->address
+= input_section
->output_offset
;
302 /* Perform a relocation as part of a final link. */
303 static bfd_reloc_status_type
304 elf32_h8_final_link_relocate (r_type
, input_bfd
, output_bfd
,
305 input_section
, contents
, offset
, value
,
306 addend
, info
, sym_sec
, is_local
)
307 unsigned long r_type
;
309 bfd
*output_bfd ATTRIBUTE_UNUSED
;
310 asection
*input_section ATTRIBUTE_UNUSED
;
315 struct bfd_link_info
*info ATTRIBUTE_UNUSED
;
316 asection
*sym_sec ATTRIBUTE_UNUSED
;
317 int is_local ATTRIBUTE_UNUSED
;
319 bfd_byte
*hit_data
= contents
+ offset
;
331 bfd_put_32 (input_bfd
, value
, hit_data
);
338 bfd_put_16 (input_bfd
, value
, hit_data
);
345 bfd_put_8 (input_bfd
, value
, hit_data
);
351 /* HIT_DATA is the address for the first byte for the relocated
352 value. Subtract 1 so that we can manipulate the data in 32bit
356 /* Clear out the top byte in value. */
359 /* Retrieve the type byte for value from the section contents. */
360 value
|= (bfd_get_32 (input_bfd
, hit_data
) & 0xff000000);
362 /* Now scribble it out in one 32bit hunk. */
363 bfd_put_32 (input_bfd
, value
, hit_data
);
367 value
-= (input_section
->output_section
->vma
368 + input_section
->output_offset
);
372 /* The value is relative to the start of the instruction,
373 not the relocation offset. Subtract 2 to account for
377 bfd_put_16 (input_bfd
, value
, hit_data
);
381 value
-= (input_section
->output_section
->vma
382 + input_section
->output_offset
);
386 /* The value is relative to the start of the instruction,
387 not the relocation offset. Subtract 1 to account for
391 bfd_put_8 (input_bfd
, value
, hit_data
);
395 return bfd_reloc_notsupported
;
399 /* Relocate an H8 ELF section. */
401 elf32_h8_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
402 contents
, relocs
, local_syms
, local_sections
)
404 struct bfd_link_info
*info
;
406 asection
*input_section
;
408 Elf_Internal_Rela
*relocs
;
409 Elf_Internal_Sym
*local_syms
;
410 asection
**local_sections
;
412 Elf_Internal_Shdr
*symtab_hdr
;
413 struct elf_link_hash_entry
**sym_hashes
;
414 Elf_Internal_Rela
*rel
, *relend
;
416 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
417 sym_hashes
= elf_sym_hashes (input_bfd
);
420 relend
= relocs
+ input_section
->reloc_count
;
421 for (; rel
< relend
; rel
++)
424 unsigned long r_symndx
;
425 Elf_Internal_Sym
*sym
;
427 struct elf_link_hash_entry
*h
;
429 bfd_reloc_status_type r
;
431 r_symndx
= ELF32_R_SYM (rel
->r_info
);
432 r_type
= ELF32_R_TYPE (rel
->r_info
);
434 if (info
->relocateable
)
436 /* This is a relocateable link. We don't have to change
437 anything, unless the reloc is against a section symbol,
438 in which case we have to adjust according to where the
439 section symbol winds up in the output section. */
440 if (r_symndx
< symtab_hdr
->sh_info
)
442 sym
= local_syms
+ r_symndx
;
443 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
445 sec
= local_sections
[r_symndx
];
446 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
453 /* This is a final link. */
457 if (r_symndx
< symtab_hdr
->sh_info
)
459 sym
= local_syms
+ r_symndx
;
460 sec
= local_sections
[r_symndx
];
461 relocation
= (sec
->output_section
->vma
467 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
468 while (h
->root
.type
== bfd_link_hash_indirect
469 || h
->root
.type
== bfd_link_hash_warning
)
470 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
471 if (h
->root
.type
== bfd_link_hash_defined
472 || h
->root
.type
== bfd_link_hash_defweak
)
474 sec
= h
->root
.u
.def
.section
;
475 relocation
= (h
->root
.u
.def
.value
476 + sec
->output_section
->vma
477 + sec
->output_offset
);
479 else if (h
->root
.type
== bfd_link_hash_undefweak
)
483 if (! ((*info
->callbacks
->undefined_symbol
)
484 (info
, h
->root
.root
.string
, input_bfd
,
485 input_section
, rel
->r_offset
, true)))
491 r
= elf32_h8_final_link_relocate (r_type
, input_bfd
, output_bfd
,
493 contents
, rel
->r_offset
,
494 relocation
, rel
->r_addend
,
495 info
, sec
, h
== NULL
);
497 if (r
!= bfd_reloc_ok
)
500 const char *msg
= (const char *) 0;
502 reloc_howto_type
*howto
;
504 elf32_h8_info_to_howto (input_bfd
, &bfd_reloc
, rel
);
505 howto
= bfd_reloc
.howto
;
508 name
= h
->root
.root
.string
;
511 name
= (bfd_elf_string_from_elf_section
512 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
513 if (name
== NULL
|| *name
== '\0')
514 name
= bfd_section_name (input_bfd
, sec
);
519 case bfd_reloc_overflow
:
520 if (! ((*info
->callbacks
->reloc_overflow
)
521 (info
, name
, howto
->name
, (bfd_vma
) 0,
522 input_bfd
, input_section
, rel
->r_offset
)))
526 case bfd_reloc_undefined
:
527 if (! ((*info
->callbacks
->undefined_symbol
)
528 (info
, name
, input_bfd
, input_section
,
529 rel
->r_offset
, true)))
533 case bfd_reloc_outofrange
:
534 msg
= _("internal error: out of range error");
537 case bfd_reloc_notsupported
:
538 msg
= _("internal error: unsupported relocation error");
541 case bfd_reloc_dangerous
:
542 msg
= _("internal error: dangerous error");
546 msg
= _("internal error: unknown error");
550 if (!((*info
->callbacks
->warning
)
551 (info
, msg
, name
, input_bfd
, input_section
,
562 /* Object files encode the specific H8 model they were compiled
563 for in the ELF flags field.
565 Examine that field and return the proper BFD machine type for
568 elf32_h8_mach (flags
)
571 switch (flags
& EF_H8_MACH
)
573 case E_H8_MACH_H8300
:
575 return bfd_mach_h8300
;
577 case E_H8_MACH_H8300H
:
578 return bfd_mach_h8300h
;
580 case E_H8_MACH_H8300S
:
581 return bfd_mach_h8300s
;
585 /* The final processing done just before writing out a H8 ELF object
586 file. We use this opportunity to encode the BFD machine type
587 into the flags field in the object file. */
590 elf32_h8_final_write_processing (abfd
, linker
)
592 boolean linker ATTRIBUTE_UNUSED
;
596 switch (bfd_get_mach (abfd
))
600 val
= E_H8_MACH_H8300
;
603 case bfd_mach_h8300h
:
604 val
= E_H8_MACH_H8300H
;
607 case bfd_mach_h8300s
:
608 val
= E_H8_MACH_H8300S
;
612 elf_elfheader (abfd
)->e_flags
&= ~ (EF_H8_MACH
);
613 elf_elfheader (abfd
)->e_flags
|= val
;
616 /* Return nonzero if ABFD represents a valid H8 ELF object file; also
617 record the encoded machine type found in the ELF flags. */
620 elf32_h8_object_p (abfd
)
623 bfd_default_set_arch_mach (abfd
, bfd_arch_h8300
,
624 elf32_h8_mach (elf_elfheader (abfd
)->e_flags
));
628 /* Merge backend specific data from an object file to the output
629 object file when linking. The only data we need to copy at this
630 time is the architecture/machine information. */
633 elf32_h8_merge_private_bfd_data (ibfd
, obfd
)
637 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
638 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
641 if (bfd_get_arch (obfd
) == bfd_get_arch (ibfd
)
642 && bfd_get_mach (obfd
) < bfd_get_mach (ibfd
))
644 if (! bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
),
645 bfd_get_mach (ibfd
)))
653 #define TARGET_BIG_SYM bfd_elf32_h8300_vec
654 #define TARGET_BIG_NAME "elf32-h8300"
655 #define ELF_ARCH bfd_arch_h8300
656 #define ELF_MACHINE_CODE EM_H8_300
657 #define ELF_MAXPAGESIZE 0x1
658 #define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
659 #define elf_info_to_howto elf32_h8_info_to_howto
660 #define elf_info_to_howto_rel elf32_h8_info_to_howto_rel
662 /* So we can set/examine bits in e_flags to get the specific
663 H8 architecture in use. */
664 #define elf_backend_final_write_processing \
665 elf32_h8_final_write_processing
666 #define elf_backend_object_p \
668 #define bfd_elf32_bfd_merge_private_bfd_data \
669 elf32_h8_merge_private_bfd_data
671 /* ??? when elf_backend_relocate_section is not defined, elf32-target.h
672 defaults to using _bfd_generic_link_hash_table_create, but
673 elflink.h:bfd_elf32_size_dynamic_sections uses
674 dynobj = elf_hash_table (info)->dynobj;
675 and thus requires an elf hash table. */
676 #define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
678 /* Use an H8 specific linker, not the ELF generic linker. */
679 #define elf_backend_relocate_section elf32_h8_relocate_section
681 #include "elf32-target.h"