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 */
176 /* This structure is used to map BFD reloc codes to H8 ELF relocs. */
180 bfd_reloc_code_real_type bfd_reloc_val
;
181 unsigned char howto_index
;
184 /* An array mapping BFD reloc codes to SH ELF relocs. */
186 static const struct elf_reloc_map h8_reloc_map
[] =
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
},
200 static reloc_howto_type
*
201 elf32_h8_reloc_type_lookup (abfd
, code
)
202 bfd
*abfd ATTRIBUTE_UNUSED
;
203 bfd_reloc_code_real_type code
;
207 for (i
= 0; i
< sizeof (h8_reloc_map
) / sizeof (struct elf_reloc_map
); i
++)
209 if (h8_reloc_map
[i
].bfd_reloc_val
== code
)
210 return &h8_elf_howto_table
[(int) h8_reloc_map
[i
].howto_index
];
216 elf32_h8_info_to_howto (abfd
, bfd_reloc
, elf_reloc
)
217 bfd
*abfd ATTRIBUTE_UNUSED
;
219 Elf32_Internal_Rela
*elf_reloc
;
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
)
228 bfd_reloc
->howto
= &h8_elf_howto_table
[i
];
235 elf32_h8_info_to_howto_rel (abfd
, bfd_reloc
, elf_reloc
)
236 bfd
*abfd ATTRIBUTE_UNUSED
;
238 Elf32_Internal_Rel
*elf_reloc ATTRIBUTE_UNUSED
;
243 r
= ELF32_R_TYPE (elf_reloc
->r_info
);
244 bfd_reloc
->howto
= &h8_elf_howto_table
[r
];
248 /* Perform a relocation as part of a final link. */
249 static bfd_reloc_status_type
250 elf32_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
;
255 bfd
*output_bfd ATTRIBUTE_UNUSED
;
256 asection
*input_section ATTRIBUTE_UNUSED
;
261 struct bfd_link_info
*info ATTRIBUTE_UNUSED
;
262 asection
*sym_sec ATTRIBUTE_UNUSED
;
263 int is_local ATTRIBUTE_UNUSED
;
265 bfd_byte
*hit_data
= contents
+ offset
;
276 bfd_put_32 (input_bfd
, value
, hit_data
);
283 bfd_put_16 (input_bfd
, value
, hit_data
);
290 if ((long) value
> 0x7f || (long) value
< -0x80)
291 return bfd_reloc_overflow
;
293 bfd_put_8 (input_bfd
, value
, hit_data
);
300 if ((long) value
> 0x7fffff || (long) value
< -0x800000)
301 return bfd_reloc_overflow
;
304 value
|= (bfd_get_32 (input_bfd
, hit_data
) & 0xff000000);
305 bfd_put_32 (input_bfd
, value
, hit_data
);
309 return bfd_reloc_notsupported
;
313 /* Relocate an H8 ELF section. */
315 elf32_h8_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
316 contents
, relocs
, local_syms
, local_sections
)
318 struct bfd_link_info
*info
;
320 asection
*input_section
;
322 Elf_Internal_Rela
*relocs
;
323 Elf_Internal_Sym
*local_syms
;
324 asection
**local_sections
;
326 Elf_Internal_Shdr
*symtab_hdr
;
327 struct elf_link_hash_entry
**sym_hashes
;
328 Elf_Internal_Rela
*rel
, *relend
;
330 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
331 sym_hashes
= elf_sym_hashes (input_bfd
);
334 relend
= relocs
+ input_section
->reloc_count
;
335 for (; rel
< relend
; rel
++)
338 unsigned long r_symndx
;
339 Elf_Internal_Sym
*sym
;
341 struct elf_link_hash_entry
*h
;
343 bfd_reloc_status_type r
;
345 r_symndx
= ELF32_R_SYM (rel
->r_info
);
346 r_type
= ELF32_R_TYPE (rel
->r_info
);
348 if (info
->relocateable
)
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
)
356 sym
= local_syms
+ r_symndx
;
357 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
359 sec
= local_sections
[r_symndx
];
360 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
367 /* This is a final link. */
371 if (r_symndx
< symtab_hdr
->sh_info
)
373 sym
= local_syms
+ r_symndx
;
374 sec
= local_sections
[r_symndx
];
375 relocation
= (sec
->output_section
->vma
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
)
388 sec
= h
->root
.u
.def
.section
;
389 relocation
= (h
->root
.u
.def
.value
390 + sec
->output_section
->vma
391 + sec
->output_offset
);
393 else if (h
->root
.type
== bfd_link_hash_undefweak
)
397 if (! ((*info
->callbacks
->undefined_symbol
)
398 (info
, h
->root
.root
.string
, input_bfd
,
399 input_section
, rel
->r_offset
, true)))
405 r
= elf32_h8_final_link_relocate (r_type
, input_bfd
, output_bfd
,
407 contents
, rel
->r_offset
,
408 relocation
, rel
->r_addend
,
409 info
, sec
, h
== NULL
);
411 if (r
!= bfd_reloc_ok
)
414 const char *msg
= (const char *) 0;
416 reloc_howto_type
*howto
;
418 elf32_h8_info_to_howto (input_bfd
, &bfd_reloc
, rel
);
419 howto
= bfd_reloc
.howto
;
422 name
= h
->root
.root
.string
;
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
);
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
)))
440 case bfd_reloc_undefined
:
441 if (! ((*info
->callbacks
->undefined_symbol
)
442 (info
, name
, input_bfd
, input_section
,
443 rel
->r_offset
, true)))
447 case bfd_reloc_outofrange
:
448 msg
= _("internal error: out of range error");
451 case bfd_reloc_notsupported
:
452 msg
= _("internal error: unsupported relocation error");
455 case bfd_reloc_dangerous
:
456 msg
= _("internal error: dangerous error");
460 msg
= _("internal error: unknown error");
464 if (!((*info
->callbacks
->warning
)
465 (info
, msg
, name
, input_bfd
, input_section
,
476 /* Object files encode the specific H8 model they were compiled
477 for in the ELF flags field.
479 Examine that field and return the proper BFD machine type for
482 elf32_h8_mach (flags
)
485 switch (flags
& EF_H8_MACH
)
487 case E_H8_MACH_H8300
:
489 return bfd_mach_h8300
;
491 case E_H8_MACH_H8300H
:
492 return bfd_mach_h8300h
;
494 case E_H8_MACH_H8300S
:
495 return bfd_mach_h8300s
;
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. */
504 elf32_h8_final_write_processing (abfd
, linker
)
506 boolean linker ATTRIBUTE_UNUSED
;
510 switch (bfd_get_mach (abfd
))
514 val
= E_H8_MACH_H8300
;
517 case bfd_mach_h8300h
:
518 val
= E_H8_MACH_H8300H
;
521 case bfd_mach_h8300s
:
522 val
= E_H8_MACH_H8300S
;
526 elf_elfheader (abfd
)->e_flags
&= ~ (EF_H8_MACH
);
527 elf_elfheader (abfd
)->e_flags
|= val
;
530 /* Return nonzero if ABFD represents a valid H8 ELF object file; also
531 record the encoded machine type found in the ELF flags. */
534 elf32_h8_object_p (abfd
)
537 bfd_default_set_arch_mach (abfd
, bfd_arch_h8300
,
538 elf32_h8_mach (elf_elfheader (abfd
)->e_flags
));
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. */
547 elf32_h8_merge_private_bfd_data (ibfd
, obfd
)
551 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
552 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
555 if (bfd_get_arch (obfd
) == bfd_get_arch (ibfd
)
556 && bfd_get_mach (obfd
) < bfd_get_mach (ibfd
))
558 if (! bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
),
559 bfd_get_mach (ibfd
)))
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
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 \
582 #define bfd_elf32_bfd_merge_private_bfd_data \
583 elf32_h8_merge_private_bfd_data
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
592 /* Use an H8 specific linker, not the ELF generic linker. */
593 #define elf_backend_relocate_section elf32_h8_relocate_section
595 #include "elf32-target.h"