1 /* Morpho Technologies MT specific support for 32-bit ELF
2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
3 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 MA 02111-1307, USA. */
29 static reloc_howto_type * mt_reloc_type_lookup
30 (bfd *, bfd_reloc_code_real_type);
32 static void mt_info_to_howto_rela
33 (bfd *, arelent *, Elf_Internal_Rela *);
35 static bfd_reloc_status_type mt_elf_relocate_hi16
36 (bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma);
38 static bfd_reloc_status_type mt_final_link_relocate
39 (reloc_howto_type *, bfd *, asection *, bfd_byte *,
40 Elf_Internal_Rela *, bfd_vma);
42 static bfd_boolean mt_elf_relocate_section
43 (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
44 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
46 /* Relocation tables. */
47 static reloc_howto_type mt_elf_howto_table [] =
49 /* This reloc does nothing. */
50 HOWTO (R_MT_NONE, /* type */
52 2, /* size (0 = byte, 1 = short, 2 = long) */
54 FALSE, /* pc_relative */
56 complain_overflow_dont, /* complain_on_overflow */
57 bfd_elf_generic_reloc, /* special_function */
58 "R_MT_NONE", /* name */
59 FALSE, /* partial_inplace */
62 FALSE), /* pcrel_offset */
64 /* A 16 bit absolute relocation. */
65 HOWTO (R_MT_16, /* type */
67 2, /* size (0 = byte, 1 = short, 2 = long) */
69 FALSE, /* pc_relative */
71 complain_overflow_dont, /* complain_on_overflow */
72 bfd_elf_generic_reloc, /* special_function */
74 FALSE, /* partial_inplace */
76 0xffff, /* dst_mask */
77 FALSE), /* pcrel_offset */
79 /* A 32 bit absolute relocation. */
80 HOWTO (R_MT_32, /* type */
82 2, /* size (0 = byte, 1 = short, 2 = long) */
84 FALSE, /* pc_relative */
86 complain_overflow_dont, /* complain_on_overflow */
87 bfd_elf_generic_reloc, /* special_function */
89 FALSE, /* partial_inplace */
91 0xffffffff, /* dst_mask */
92 FALSE), /* pcrel_offset */
94 /* A 32 bit pc-relative relocation. */
95 HOWTO (R_MT_32_PCREL, /* type */
97 2, /* size (0 = byte, 1 = short, 2 = long) */
99 TRUE, /* pc_relative */
101 complain_overflow_dont, /* complain_on_overflow */
102 bfd_elf_generic_reloc, /* special_function */
103 "R_MT_32_PCREL", /* name */
104 FALSE, /* partial_inplace */
106 0xffffffff, /* dst_mask */
107 TRUE), /* pcrel_offset */
109 /* A 16 bit pc-relative relocation. */
110 HOWTO (R_MT_PC16, /* type */
112 2, /* size (0 = byte, 1 = short, 2 = long) */
114 TRUE, /* pc_relative */
116 complain_overflow_signed, /* complain_on_overflow */
117 bfd_elf_generic_reloc, /* special_function */
118 "R_MT_PC16", /* name */
119 FALSE, /* partial_inplace */
121 0xffff, /* dst_mask */
122 TRUE), /* pcrel_offset */
124 /* high 16 bits of symbol value. */
125 HOWTO (R_MT_HI16, /* type */
127 2, /* size (0 = byte, 1 = short, 2 = long) */
129 FALSE, /* pc_relative */
131 complain_overflow_dont, /* complain_on_overflow */
132 bfd_elf_generic_reloc, /* special_function */
133 "R_MT_HI16", /* name */
134 FALSE, /* partial_inplace */
135 0xffff0000, /* src_mask */
136 0xffff0000, /* dst_mask */
137 FALSE), /* pcrel_offset */
139 /* Low 16 bits of symbol value. */
140 HOWTO (R_MT_LO16, /* type */
142 2, /* size (0 = byte, 1 = short, 2 = long) */
144 FALSE, /* pc_relative */
146 complain_overflow_dont, /* complain_on_overflow */
147 bfd_elf_generic_reloc, /* special_function */
148 "R_MT_LO16", /* name */
149 FALSE, /* partial_inplace */
150 0xffff, /* src_mask */
151 0xffff, /* dst_mask */
152 FALSE), /* pcrel_offset */
155 /* Map BFD reloc types to MT ELF reloc types. */
157 static reloc_howto_type *
159 (bfd * abfd ATTRIBUTE_UNUSED,
160 bfd_reloc_code_real_type code)
162 /* Note that the mt_elf_howto_table is indxed by the R_
163 constants. Thus, the order that the howto records appear in the
164 table *must* match the order of the relocation types defined in
170 return &mt_elf_howto_table[ (int) R_MT_NONE];
172 return &mt_elf_howto_table[ (int) R_MT_16];
174 return &mt_elf_howto_table[ (int) R_MT_32];
175 case BFD_RELOC_32_PCREL:
176 return &mt_elf_howto_table[ (int) R_MT_32_PCREL];
177 case BFD_RELOC_16_PCREL:
178 return &mt_elf_howto_table[ (int) R_MT_PC16];
180 return &mt_elf_howto_table[ (int) R_MT_HI16];
182 return &mt_elf_howto_table[ (int) R_MT_LO16];
185 /* Pacify gcc -Wall. */
191 static reloc_howto_type *
192 mt_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
198 i < sizeof (mt_elf_howto_table) / sizeof (mt_elf_howto_table[0]);
200 if (mt_elf_howto_table[i].name != NULL
201 && strcasecmp (mt_elf_howto_table[i].name, r_name) == 0)
202 return &mt_elf_howto_table[i];
207 bfd_reloc_status_type
210 Elf_Internal_Rela * relhi,
216 insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
218 value += relhi->r_addend;
220 insn = ((insn & ~0xFFFF) | value);
222 bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
226 /* XXX: The following code is the result of a cut&paste. This unfortunate
227 practice is very widespread in the various target back-end files. */
229 /* Set the howto pointer for a MT ELF reloc. */
232 mt_info_to_howto_rela
233 (bfd * abfd ATTRIBUTE_UNUSED,
235 Elf_Internal_Rela * dst)
239 r_type = ELF32_R_TYPE (dst->r_info);
240 cache_ptr->howto = & mt_elf_howto_table [r_type];
243 /* Perform a single relocation. By default we use the standard BFD
246 static bfd_reloc_status_type
247 mt_final_link_relocate
248 (reloc_howto_type * howto,
250 asection * input_section,
252 Elf_Internal_Rela * rel,
255 return _bfd_final_link_relocate (howto, input_bfd, input_section,
256 contents, rel->r_offset,
257 relocation, rel->r_addend);
260 /* Relocate a MT ELF section.
261 There is some attempt to make this function usable for many architectures,
262 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
263 if only to serve as a learning tool.
265 The RELOCATE_SECTION function is called by the new ELF backend linker
266 to handle the relocations for a section.
268 The relocs are always passed as Rela structures; if the section
269 actually uses Rel structures, the r_addend field will always be
272 This function is responsible for adjusting the section contents as
273 necessary, and (if using Rela relocs and generating a relocatable
274 output file) adjusting the reloc addend as necessary.
276 This function does not have to worry about setting the reloc
277 address or the reloc symbol index.
279 LOCAL_SYMS is a pointer to the swapped in local symbols.
281 LOCAL_SECTIONS is an array giving the section in the input file
282 corresponding to the st_shndx field of each local symbol.
284 The global hash table entry for the global symbols can be found
285 via elf_sym_hashes (input_bfd).
287 When generating relocatable output, this function must handle
288 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
289 going to be the section symbol corresponding to the output
290 section, which means that the addend must be adjusted
294 mt_elf_relocate_section
295 (bfd * output_bfd ATTRIBUTE_UNUSED,
296 struct bfd_link_info * info,
298 asection * input_section,
300 Elf_Internal_Rela * relocs,
301 Elf_Internal_Sym * local_syms,
302 asection ** local_sections)
304 Elf_Internal_Shdr * symtab_hdr;
305 struct elf_link_hash_entry ** sym_hashes;
306 Elf_Internal_Rela * rel;
307 Elf_Internal_Rela * relend;
309 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
310 sym_hashes = elf_sym_hashes (input_bfd);
311 relend = relocs + input_section->reloc_count;
313 for (rel = relocs; rel < relend; rel ++)
315 reloc_howto_type * howto;
316 unsigned long r_symndx;
317 Elf_Internal_Sym * sym;
319 struct elf_link_hash_entry * h;
321 bfd_reloc_status_type r;
322 const char * name = NULL;
325 r_type = ELF32_R_TYPE (rel->r_info);
327 r_symndx = ELF32_R_SYM (rel->r_info);
329 howto = mt_elf_howto_table + ELF32_R_TYPE (rel->r_info);
334 if (r_symndx < symtab_hdr->sh_info)
336 sym = local_syms + r_symndx;
337 sec = local_sections [r_symndx];
338 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
340 name = bfd_elf_string_from_elf_section
341 (input_bfd, symtab_hdr->sh_link, sym->st_name);
342 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
346 bfd_boolean unresolved_reloc;
349 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
350 r_symndx, symtab_hdr, sym_hashes,
352 unresolved_reloc, warned);
354 name = h->root.root.string;
357 if (sec != NULL && elf_discarded_section (sec))
358 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
359 rel, relend, howto, contents);
361 if (info->relocatable)
364 /* Finally, the sole MT-specific part. */
368 r = mt_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
371 r = mt_final_link_relocate (howto, input_bfd, input_section,
372 contents, rel, relocation);
377 if (r != bfd_reloc_ok)
379 const char * msg = (const char *) NULL;
383 case bfd_reloc_overflow:
384 r = info->callbacks->reloc_overflow
385 (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
386 input_bfd, input_section, rel->r_offset);
389 case bfd_reloc_undefined:
390 r = info->callbacks->undefined_symbol
391 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
394 case bfd_reloc_outofrange:
395 msg = _("internal error: out of range error");
398 case bfd_reloc_dangerous:
399 msg = _("internal error: dangerous relocation");
403 msg = _("internal error: unknown error");
408 r = info->callbacks->warning
409 (info, msg, name, input_bfd, input_section, rel->r_offset);
419 /* Look through the relocs for a section during the first phase.
420 Since we don't do .gots or .plts, we just need to consider the
421 virtual table relocs for gc. */
426 struct bfd_link_info * info,
428 const Elf_Internal_Rela * relocs)
430 Elf_Internal_Shdr * symtab_hdr;
431 struct elf_link_hash_entry ** sym_hashes;
432 const Elf_Internal_Rela * rel;
433 const Elf_Internal_Rela * rel_end;
435 if (info->relocatable)
438 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
439 sym_hashes = elf_sym_hashes (abfd);
441 rel_end = relocs + sec->reloc_count;
442 for (rel = relocs; rel < rel_end; rel++)
444 struct elf_link_hash_entry *h;
445 unsigned long r_symndx;
447 r_symndx = ELF32_R_SYM (rel->r_info);
448 if (r_symndx < symtab_hdr->sh_info)
452 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
453 while (h->root.type == bfd_link_hash_indirect
454 || h->root.type == bfd_link_hash_warning)
455 h = (struct elf_link_hash_entry *) h->root.u.i.link;
462 /* Return the MACH for an e_flags value. */
465 elf32_mt_machine (bfd *abfd)
467 switch (elf_elfheader (abfd)->e_flags & EF_MT_CPU_MASK)
469 case EF_MT_CPU_MRISC: return bfd_mach_ms1;
470 case EF_MT_CPU_MRISC2: return bfd_mach_mrisc2;
471 case EF_MT_CPU_MS2: return bfd_mach_ms2;
478 mt_elf_object_p (bfd * abfd)
480 bfd_default_set_arch_mach (abfd, bfd_arch_mt, elf32_mt_machine (abfd));
485 /* Function to set the ELF flag bits. */
488 mt_elf_set_private_flags (bfd * abfd,
491 elf_elfheader (abfd)->e_flags = flags;
492 elf_flags_init (abfd) = TRUE;
497 mt_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
499 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
500 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
503 BFD_ASSERT (!elf_flags_init (obfd)
504 || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
506 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
507 elf_flags_init (obfd) = TRUE;
509 /* Copy object attributes. */
510 _bfd_elf_copy_obj_attributes (ibfd, obfd);
515 /* Merge backend specific data from an object file to the output
516 object file when linking. */
519 mt_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
521 flagword old_flags, new_flags;
522 bfd_boolean ok = TRUE;
524 /* Check if we have the same endianess. */
525 if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
528 /* If they're not both mt, then merging is meaningless, so just
530 if (strcmp (ibfd->arch_info->arch_name, "mt") != 0)
532 if (strcmp (obfd->arch_info->arch_name, "mt") != 0)
535 new_flags = elf_elfheader (ibfd)->e_flags;
536 old_flags = elf_elfheader (obfd)->e_flags;
539 _bfd_error_handler ("%B: old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s",
540 ibfd, old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no");
543 if (!elf_flags_init (obfd))
545 old_flags = new_flags;
546 elf_flags_init (obfd) = TRUE;
548 else if ((new_flags & EF_MT_CPU_MASK) != (old_flags & EF_MT_CPU_MASK))
550 /* CPU has changed. This is invalid, because MRISC, MRISC2 and
551 MS2 are not subsets of each other. */
557 obfd->arch_info = ibfd->arch_info;
558 elf_elfheader (obfd)->e_flags = old_flags;
565 mt_elf_print_private_bfd_data (bfd * abfd, void * ptr)
567 FILE * file = (FILE *) ptr;
570 BFD_ASSERT (abfd != NULL && ptr != NULL);
572 /* Print normal ELF private data. */
573 _bfd_elf_print_private_bfd_data (abfd, ptr);
575 flags = elf_elfheader (abfd)->e_flags;
576 fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
578 switch (flags & EF_MT_CPU_MASK)
581 case EF_MT_CPU_MRISC: fprintf (file, " ms1-16-002"); break;
582 case EF_MT_CPU_MRISC2: fprintf (file, " ms1-16-003"); break;
583 case EF_MT_CPU_MS2: fprintf (file, " ms2"); break;
592 #define TARGET_BIG_SYM bfd_elf32_mt_vec
593 #define TARGET_BIG_NAME "elf32-mt"
595 #define ELF_ARCH bfd_arch_mt
596 #define ELF_MACHINE_CODE EM_MT
597 #define ELF_MAXPAGESIZE 1 /* No pages on the MT. */
599 #define elf_info_to_howto_rel NULL
600 #define elf_info_to_howto mt_info_to_howto_rela
602 #define elf_backend_relocate_section mt_elf_relocate_section
604 #define bfd_elf32_bfd_reloc_type_lookup mt_reloc_type_lookup
605 #define bfd_elf32_bfd_reloc_name_lookup mt_reloc_name_lookup
607 #define elf_backend_check_relocs mt_elf_check_relocs
608 #define elf_backend_object_p mt_elf_object_p
609 #define elf_backend_rela_normal 1
611 #define elf_backend_can_gc_sections 1
613 #define bfd_elf32_bfd_set_private_flags mt_elf_set_private_flags
614 #define bfd_elf32_bfd_copy_private_bfd_data mt_elf_copy_private_bfd_data
615 #define bfd_elf32_bfd_merge_private_bfd_data mt_elf_merge_private_bfd_data
616 #define bfd_elf32_bfd_print_private_bfd_data mt_elf_print_private_bfd_data
618 #include "elf32-target.h"