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
**));
43 /* This does not include any relocation information, but should be
44 good enough for GDB or objdump to read the file. */
46 static reloc_howto_type h8_elf_howto_table
[] =
49 HOWTO (R_H8_NONE
, /* type */
51 0, /* size (0 = byte, 1 = short, 2 = long) */
53 false, /* pc_relative */
55 complain_overflow_dont
, /* complain_on_overflow */
56 NULL
, /* special_function */
57 "R_H8_NONE", /* name */
58 false, /* partial_inplace */
61 false), /* pcrel_offset */
62 #define R_H8_DIR32_X (R_H8_NONE_X + 1)
63 HOWTO (R_H8_DIR32
, /* type */
65 2, /* size (0 = byte, 1 = short, 2 = long) */
67 false, /* pc_relative */
69 complain_overflow_dont
, /* complain_on_overflow */
70 NULL
, /* special_function */
71 "R_H8_DIR32", /* name */
72 false, /* partial_inplace */
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 */
79 1, /* size (0 = byte, 1 = short, 2 = long) */
81 false, /* pc_relative */
83 complain_overflow_dont
, /* complain_on_overflow */
84 NULL
, /* special_function */
85 "R_H8_DIR16", /* name */
86 false, /* partial_inplace */
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 */
93 0, /* size (0 = byte, 1 = short, 2 = long) */
95 false, /* pc_relative */
97 complain_overflow_dont
, /* complain_on_overflow */
98 NULL
, /* special_function */
99 "R_H8_DIR16", /* name */
100 false, /* partial_inplace */
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 */
107 1, /* size (0 = byte, 1 = short, 2 = long) */
109 false, /* pc_relative */
111 complain_overflow_bitfield
, /* complain_on_overflow */
112 NULL
, /* special_function */
113 "R_H8_DIR16A8", /* name */
114 false, /* partial_inplace */
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 */
121 1, /* size (0 = byte, 1 = short, 2 = long) */
123 false, /* pc_relative */
125 complain_overflow_bitfield
, /* complain_on_overflow */
126 NULL
, /* special_function */
127 "R_H8_DIR16R8", /* name */
128 false, /* partial_inplace */
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 */
135 2, /* size (0 = byte, 1 = short, 2 = long) */
137 false, /* pc_relative */
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 */
149 2, /* size (0 = byte, 1 = short, 2 = long) */
151 false, /* pc_relative */
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 */
163 2, /* size (0 = byte, 1 = short, 2 = long) */
165 false, /* pc_relative */
167 complain_overflow_dont
, /* complain_on_overflow */
168 NULL
, /* special_function */
169 "R_H8_DIR32", /* name */
170 false, /* partial_inplace */
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 */
177 1, /* size (0 = byte, 1 = short, 2 = long) */
179 true, /* pc_relative */
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 */
191 0, /* size (0 = byte, 1 = short, 2 = long) */
193 true, /* pc_relative */
195 complain_overflow_signed
, /* complain_on_overflow */
196 NULL
, /* special_function */
197 "R_H8_PCREL8", /* name */
198 false, /* partial_inplace */
201 true), /* pcrel_offset */
204 /* This structure is used to map BFD reloc codes to H8 ELF relocs. */
208 bfd_reloc_code_real_type bfd_reloc_val
;
209 unsigned char howto_index
;
212 /* An array mapping BFD reloc codes to SH ELF relocs. */
214 static const struct elf_reloc_map h8_reloc_map
[] =
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
},
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
;
237 for (i
= 0; i
< sizeof (h8_reloc_map
) / sizeof (struct elf_reloc_map
); i
++)
239 if (h8_reloc_map
[i
].bfd_reloc_val
== code
)
240 return &h8_elf_howto_table
[(int) h8_reloc_map
[i
].howto_index
];
246 elf32_h8_info_to_howto (abfd
, bfd_reloc
, elf_reloc
)
247 bfd
*abfd ATTRIBUTE_UNUSED
;
249 Elf32_Internal_Rela
*elf_reloc
;
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
)
258 bfd_reloc
->howto
= &h8_elf_howto_table
[i
];
265 elf32_h8_info_to_howto_rel (abfd
, bfd_reloc
, elf_reloc
)
266 bfd
*abfd ATTRIBUTE_UNUSED
;
268 Elf32_Internal_Rel
*elf_reloc ATTRIBUTE_UNUSED
;
273 r
= ELF32_R_TYPE (elf_reloc
->r_info
);
274 bfd_reloc
->howto
= &h8_elf_howto_table
[r
];
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
;
285 bfd
*output_bfd ATTRIBUTE_UNUSED
;
286 asection
*input_section ATTRIBUTE_UNUSED
;
291 struct bfd_link_info
*info ATTRIBUTE_UNUSED
;
292 asection
*sym_sec ATTRIBUTE_UNUSED
;
293 int is_local ATTRIBUTE_UNUSED
;
295 bfd_byte
*hit_data
= contents
+ offset
;
306 bfd_put_32 (input_bfd
, value
, hit_data
);
313 bfd_put_16 (input_bfd
, value
, hit_data
);
320 bfd_put_8 (input_bfd
, value
, hit_data
);
328 value
|= (bfd_get_32 (input_bfd
, hit_data
) & 0xff000000);
329 bfd_put_32 (input_bfd
, value
, hit_data
);
333 value
-= (input_section
->output_section
->vma
334 + input_section
->output_offset
);
338 bfd_put_16 (input_bfd
, value
, hit_data
);
342 value
-= (input_section
->output_section
->vma
343 + input_section
->output_offset
);
347 bfd_put_8 (input_bfd
, value
, hit_data
);
351 return bfd_reloc_notsupported
;
355 /* Relocate an H8 ELF section. */
357 elf32_h8_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
358 contents
, relocs
, local_syms
, local_sections
)
360 struct bfd_link_info
*info
;
362 asection
*input_section
;
364 Elf_Internal_Rela
*relocs
;
365 Elf_Internal_Sym
*local_syms
;
366 asection
**local_sections
;
368 Elf_Internal_Shdr
*symtab_hdr
;
369 struct elf_link_hash_entry
**sym_hashes
;
370 Elf_Internal_Rela
*rel
, *relend
;
372 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
373 sym_hashes
= elf_sym_hashes (input_bfd
);
376 relend
= relocs
+ input_section
->reloc_count
;
377 for (; rel
< relend
; rel
++)
380 unsigned long r_symndx
;
381 Elf_Internal_Sym
*sym
;
383 struct elf_link_hash_entry
*h
;
385 bfd_reloc_status_type r
;
387 r_symndx
= ELF32_R_SYM (rel
->r_info
);
388 r_type
= ELF32_R_TYPE (rel
->r_info
);
390 if (info
->relocateable
)
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
)
398 sym
= local_syms
+ r_symndx
;
399 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
401 sec
= local_sections
[r_symndx
];
402 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
409 /* This is a final link. */
413 if (r_symndx
< symtab_hdr
->sh_info
)
415 sym
= local_syms
+ r_symndx
;
416 sec
= local_sections
[r_symndx
];
417 relocation
= (sec
->output_section
->vma
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
)
430 sec
= h
->root
.u
.def
.section
;
431 relocation
= (h
->root
.u
.def
.value
432 + sec
->output_section
->vma
433 + sec
->output_offset
);
435 else if (h
->root
.type
== bfd_link_hash_undefweak
)
439 if (! ((*info
->callbacks
->undefined_symbol
)
440 (info
, h
->root
.root
.string
, input_bfd
,
441 input_section
, rel
->r_offset
, true)))
447 r
= elf32_h8_final_link_relocate (r_type
, input_bfd
, output_bfd
,
449 contents
, rel
->r_offset
,
450 relocation
, rel
->r_addend
,
451 info
, sec
, h
== NULL
);
453 if (r
!= bfd_reloc_ok
)
456 const char *msg
= (const char *) 0;
458 reloc_howto_type
*howto
;
460 elf32_h8_info_to_howto (input_bfd
, &bfd_reloc
, rel
);
461 howto
= bfd_reloc
.howto
;
464 name
= h
->root
.root
.string
;
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
);
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
)))
482 case bfd_reloc_undefined
:
483 if (! ((*info
->callbacks
->undefined_symbol
)
484 (info
, name
, input_bfd
, input_section
,
485 rel
->r_offset
, true)))
489 case bfd_reloc_outofrange
:
490 msg
= _("internal error: out of range error");
493 case bfd_reloc_notsupported
:
494 msg
= _("internal error: unsupported relocation error");
497 case bfd_reloc_dangerous
:
498 msg
= _("internal error: dangerous error");
502 msg
= _("internal error: unknown error");
506 if (!((*info
->callbacks
->warning
)
507 (info
, msg
, name
, input_bfd
, input_section
,
518 /* Object files encode the specific H8 model they were compiled
519 for in the ELF flags field.
521 Examine that field and return the proper BFD machine type for
524 elf32_h8_mach (flags
)
527 switch (flags
& EF_H8_MACH
)
529 case E_H8_MACH_H8300
:
531 return bfd_mach_h8300
;
533 case E_H8_MACH_H8300H
:
534 return bfd_mach_h8300h
;
536 case E_H8_MACH_H8300S
:
537 return bfd_mach_h8300s
;
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. */
546 elf32_h8_final_write_processing (abfd
, linker
)
548 boolean linker ATTRIBUTE_UNUSED
;
552 switch (bfd_get_mach (abfd
))
556 val
= E_H8_MACH_H8300
;
559 case bfd_mach_h8300h
:
560 val
= E_H8_MACH_H8300H
;
563 case bfd_mach_h8300s
:
564 val
= E_H8_MACH_H8300S
;
568 elf_elfheader (abfd
)->e_flags
&= ~ (EF_H8_MACH
);
569 elf_elfheader (abfd
)->e_flags
|= val
;
572 /* Return nonzero if ABFD represents a valid H8 ELF object file; also
573 record the encoded machine type found in the ELF flags. */
576 elf32_h8_object_p (abfd
)
579 bfd_default_set_arch_mach (abfd
, bfd_arch_h8300
,
580 elf32_h8_mach (elf_elfheader (abfd
)->e_flags
));
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. */
589 elf32_h8_merge_private_bfd_data (ibfd
, obfd
)
593 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
594 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
597 if (bfd_get_arch (obfd
) == bfd_get_arch (ibfd
)
598 && bfd_get_mach (obfd
) < bfd_get_mach (ibfd
))
600 if (! bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
),
601 bfd_get_mach (ibfd
)))
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
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 \
624 #define bfd_elf32_bfd_merge_private_bfd_data \
625 elf32_h8_merge_private_bfd_data
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
634 /* Use an H8 specific linker, not the ELF generic linker. */
635 #define elf_backend_relocate_section elf32_h8_relocate_section
637 #include "elf32-target.h"