1 /* Matsushita 10200 specific support for 32-bit ELF
2 Copyright (C) 1996, 1997 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. */
25 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
26 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
27 static void mn10200_info_to_howto
28 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
31 /* We have to use RELA instructions since md_apply_fix3 in the assembler
32 does absolutely nothing. */
48 static reloc_howto_type elf_mn10200_howto_table[] =
50 /* Dummy relocation. Does nothing. */
51 HOWTO (R_MN10200_NONE,
57 complain_overflow_bitfield,
58 bfd_elf_generic_reloc,
64 /* Standard 32 bit reloc. */
71 complain_overflow_bitfield,
72 bfd_elf_generic_reloc,
78 /* Standard 16 bit reloc. */
85 complain_overflow_bitfield,
86 bfd_elf_generic_reloc,
92 /* Standard 8 bit reloc. */
99 complain_overflow_bitfield,
100 bfd_elf_generic_reloc,
106 /* Standard 24 bit reloc. */
113 complain_overflow_bitfield,
114 bfd_elf_generic_reloc,
120 /* Simple 8 pc-relative reloc. */
121 HOWTO (R_MN10200_PCREL8,
127 complain_overflow_bitfield,
128 bfd_elf_generic_reloc,
134 /* Simple 16 pc-relative reloc. */
135 HOWTO (R_MN10200_PCREL16,
141 complain_overflow_bitfield,
142 bfd_elf_generic_reloc,
148 /* Simple 32bit pc-relative reloc with a 1 byte adjustment
149 to get the pc-relative offset correct. */
150 HOWTO (R_MN10200_PCREL24,
156 complain_overflow_bitfield,
157 bfd_elf_generic_reloc,
165 struct mn10200_reloc_map
167 unsigned char bfd_reloc_val;
168 unsigned char elf_reloc_val;
171 static const struct mn10200_reloc_map mn10200_reloc_map[] =
173 { BFD_RELOC_NONE, R_MN10200_NONE, },
174 { BFD_RELOC_32, R_MN10200_32, },
175 { BFD_RELOC_16, R_MN10200_16, },
176 { BFD_RELOC_8, R_MN10200_8, },
177 { BFD_RELOC_24, R_MN10200_24, },
178 { BFD_RELOC_8_PCREL, R_MN10200_PCREL8, },
179 { BFD_RELOC_16_PCREL, R_MN10200_PCREL16, },
180 { BFD_RELOC_24_PCREL, R_MN10200_PCREL24, },
183 static reloc_howto_type *
184 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
186 bfd_reloc_code_real_type code;
191 i < sizeof (mn10200_reloc_map) / sizeof (struct mn10200_reloc_map);
194 if (mn10200_reloc_map[i].bfd_reloc_val == code)
195 return &elf_mn10200_howto_table[mn10200_reloc_map[i].elf_reloc_val];
201 /* Set the howto pointer for an MN10200 ELF reloc. */
204 mn10200_info_to_howto (abfd, cache_ptr, dst)
207 Elf32_Internal_Rela *dst;
211 r_type = ELF32_R_TYPE (dst->r_info);
212 BFD_ASSERT (r_type < (unsigned int) R_MN10200_MAX);
213 cache_ptr->howto = &elf_mn10200_howto_table[r_type];
216 /* Perform a relocation as part of a final link. */
217 static bfd_reloc_status_type
218 mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd,
219 input_section, contents, offset, value,
220 addend, info, sym_sec, is_local)
221 reloc_howto_type *howto;
224 asection *input_section;
229 struct bfd_link_info *info;
234 unsigned long r_type = howto->type;
235 bfd_byte *hit_data = contents + offset;
244 value += bfd_get_32 (input_bfd, hit_data);
246 bfd_put_32 (input_bfd, value, hit_data);
250 value += (short)bfd_get_16 (input_bfd, hit_data);
253 if ((long)value > 0x7fff || (long)value < -0x8000)
254 return bfd_reloc_overflow;
256 bfd_put_16 (input_bfd, value, hit_data);
260 value += (char)bfd_get_8 (input_bfd, hit_data);
263 if ((long)value > 0x7fff || (long)value < -0x8000)
264 return bfd_reloc_overflow;
266 bfd_put_8 (input_bfd, value, hit_data);
270 value += (bfd_get_32 (input_bfd, hit_data) & 0xffffff);
273 if ((long)value > 0x7fffff || (long)value < -0x800000)
274 return bfd_reloc_overflow;
277 value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
278 bfd_put_32 (input_bfd, value, hit_data);
281 case R_MN10200_PCREL8:
282 value -= (input_section->output_section->vma
283 + input_section->output_offset);
287 if ((long)value > 0xff || (long)value < -0x100)
288 return bfd_reloc_overflow;
290 bfd_put_8 (input_bfd, value, hit_data);
293 case R_MN10200_PCREL16:
294 value -= (input_section->output_section->vma
295 + input_section->output_offset);
299 if ((long)value > 0xffff || (long)value < -0x10000)
300 return bfd_reloc_overflow;
302 bfd_put_16 (input_bfd, value, hit_data);
305 case R_MN10200_PCREL24:
306 value -= (input_section->output_section->vma
307 + input_section->output_offset);
311 if ((long)value > 0xffffff || (long)value < -0x1000000)
312 return bfd_reloc_overflow;
315 value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
316 bfd_put_32 (input_bfd, value, hit_data);
320 return bfd_reloc_notsupported;
325 /* Relocate an MN10200 ELF section. */
327 mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section,
328 contents, relocs, local_syms, local_sections)
330 struct bfd_link_info *info;
332 asection *input_section;
334 Elf_Internal_Rela *relocs;
335 Elf_Internal_Sym *local_syms;
336 asection **local_sections;
338 Elf_Internal_Shdr *symtab_hdr;
339 struct elf_link_hash_entry **sym_hashes;
340 Elf_Internal_Rela *rel, *relend;
342 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
343 sym_hashes = elf_sym_hashes (input_bfd);
346 relend = relocs + input_section->reloc_count;
347 for (; rel < relend; rel++)
350 reloc_howto_type *howto;
351 unsigned long r_symndx;
352 Elf_Internal_Sym *sym;
354 struct elf_link_hash_entry *h;
356 bfd_reloc_status_type r;
358 r_symndx = ELF32_R_SYM (rel->r_info);
359 r_type = ELF32_R_TYPE (rel->r_info);
360 howto = elf_mn10200_howto_table + r_type;
362 if (info->relocateable)
364 /* This is a relocateable link. We don't have to change
365 anything, unless the reloc is against a section symbol,
366 in which case we have to adjust according to where the
367 section symbol winds up in the output section. */
368 if (r_symndx < symtab_hdr->sh_info)
370 sym = local_syms + r_symndx;
371 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
373 sec = local_sections[r_symndx];
374 rel->r_addend += sec->output_offset + sym->st_value;
381 /* This is a final link. */
385 if (r_symndx < symtab_hdr->sh_info)
387 sym = local_syms + r_symndx;
388 sec = local_sections[r_symndx];
389 relocation = (sec->output_section->vma
395 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
396 while (h->root.type == bfd_link_hash_indirect
397 || h->root.type == bfd_link_hash_warning)
398 h = (struct elf_link_hash_entry *) h->root.u.i.link;
399 if (h->root.type == bfd_link_hash_defined
400 || h->root.type == bfd_link_hash_defweak)
402 sec = h->root.u.def.section;
403 relocation = (h->root.u.def.value
404 + sec->output_section->vma
405 + sec->output_offset);
407 else if (h->root.type == bfd_link_hash_undefweak)
411 if (! ((*info->callbacks->undefined_symbol)
412 (info, h->root.root.string, input_bfd,
413 input_section, rel->r_offset)))
419 r = mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd,
421 contents, rel->r_offset,
422 relocation, rel->r_addend,
423 info, sec, h == NULL);
425 if (r != bfd_reloc_ok)
428 const char *msg = (const char *)0;
431 name = h->root.root.string;
434 name = (bfd_elf_string_from_elf_section
435 (input_bfd, symtab_hdr->sh_link, sym->st_name));
436 if (name == NULL || *name == '\0')
437 name = bfd_section_name (input_bfd, sec);
442 case bfd_reloc_overflow:
443 if (! ((*info->callbacks->reloc_overflow)
444 (info, name, howto->name, (bfd_vma) 0,
445 input_bfd, input_section, rel->r_offset)))
449 case bfd_reloc_undefined:
450 if (! ((*info->callbacks->undefined_symbol)
451 (info, name, input_bfd, input_section,
456 case bfd_reloc_outofrange:
457 msg = "internal error: out of range error";
460 case bfd_reloc_notsupported:
461 msg = "internal error: unsupported relocation error";
464 case bfd_reloc_dangerous:
465 msg = "internal error: dangerous error";
469 msg = "internal error: unknown error";
473 if (!((*info->callbacks->warning)
474 (info, msg, name, input_bfd, input_section,
485 #define TARGET_LITTLE_SYM bfd_elf32_mn10200_vec
486 #define TARGET_LITTLE_NAME "elf32-mn10200"
487 #define ELF_ARCH bfd_arch_mn10200
488 #define ELF_MACHINE_CODE EM_CYGNUS_MN10200
489 #define ELF_MAXPAGESIZE 0x1000
491 #define elf_info_to_howto mn10200_info_to_howto
492 #define elf_info_to_howto_rel 0
493 #define elf_backend_relocate_section mn10200_elf_relocate_section
495 #define elf_symbol_leading_char '_'
497 #include "elf32-target.h"