Add OpenRISC support
[binutils.git] / bfd / elf32-openrisc.c
bloba6c1a0027b46ae6738693fb5a2876f3db037625c
1 /* OpenRISC-specific support for 32-bit ELF.
2 Copyright (C) 2001 Free Software Foundation, Inc.
3 Contributed by Johan Rydberg, jrydberg@opencores.org
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 2 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, MA 02111-1307, USA. */
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25 #include "elf/openrisc.h"
26 #include "libiberty.h"
28 /* Forward declarations. */
30 static reloc_howto_type *openrisc_reloc_type_lookup
31 PARAMS ((bfd * , bfd_reloc_code_real_type));
32 static void openrisc_info_to_howto_rela
33 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
34 static boolean openrisc_elf_relocate_section
35 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
36 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
37 static bfd_reloc_status_type openrisc_final_link_relocate
38 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
39 Elf_Internal_Rela *, bfd_vma));
40 static boolean openrisc_elf_gc_sweep_hook
41 PARAMS ((bfd *, struct bfd_link_info *, asection *,
42 const Elf_Internal_Rela *));
43 static asection *openrisc_elf_gc_mark_hook
44 PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
45 struct elf_link_hash_entry *, Elf_Internal_Sym *));
48 static reloc_howto_type openrisc_elf_howto_table[] =
50 /* This reloc does nothing. */
51 HOWTO (R_OPENRISC_NONE, /* type */
52 0, /* rightshift */
53 2, /* size (0 = byte, 1 = short, 2 = long) */
54 32, /* bitsize */
55 false, /* pc_relative */
56 0, /* bitpos */
57 complain_overflow_bitfield, /* complain_on_overflow */
58 bfd_elf_generic_reloc, /* special_function */
59 "R_OPENRISC_NONE", /* name */
60 false, /* partial_inplace */
61 0, /* src_mask */
62 0, /* dst_mask */
63 false), /* pcrel_offset */
65 /* A PC relative 26 bit relocation, right shifted by 2. */
66 HOWTO (R_OPENRISC_INSN_REL_26, /* type */
67 2, /* rightshift */
68 2, /* size (0 = byte, 1 = short, 2 = long) */
69 26, /* bitsize */
70 true, /* pc_relative */
71 0, /* bitpos */
72 complain_overflow_signed, /* complain_on_overflow */
73 bfd_elf_generic_reloc, /* special_function */
74 "R_OPENRISC_INSN_REL_26", /* name */
75 false, /* partial_inplace */
76 0x00000000, /* src_mask */
77 0x03ffffff, /* dst_mask */
78 false), /* pcrel_offset */
80 /* A absolute 26 bit relocation, right shifted by 2. */
81 HOWTO (R_OPENRISC_INSN_ABS_26, /* type */
82 2, /* rightshift */
83 2, /* size (0 = byte, 1 = short, 2 = long) */
84 26, /* bitsize */
85 false, /* pc_relative */
86 0, /* bitpos */
87 complain_overflow_signed, /* complain_on_overflow */
88 bfd_elf_generic_reloc, /* special_function */
89 "R_OPENRISC_INSN_ABS_26", /* name */
90 false, /* partial_inplace */
91 0x00000000, /* src_mask */
92 0x03ffffff, /* dst_mask */
93 false), /* pcrel_offset */
95 HOWTO (R_OPENRISC_LO_16_IN_INSN, /* type */
96 0, /* rightshift */
97 2, /* size (0 = byte, 1 = short, 2 = long) */
98 16, /* bitsize */
99 false, /* pc_relative */
100 0, /* bitpos */
101 complain_overflow_bitfield, /* complain_on_overflow */
102 bfd_elf_generic_reloc, /* special_function */
103 "R_OPENRISC_LO_16_IN_INSN", /* name */
104 false, /* partial_inplace */
105 0x0000ffff, /* src_mask */
106 0x0000ffff, /* dst_mask */
107 false), /* pcrel_offset */
109 HOWTO (R_OPENRISC_HI_16_IN_INSN, /* type */
110 16, /* rightshift */
111 2, /* size (0 = byte, 1 = short, 2 = long) */
112 16, /* bitsize */
113 false, /* pc_relative */
114 0, /* bitpos */
115 complain_overflow_bitfield, /* complain_on_overflow */
116 bfd_elf_generic_reloc, /* special_function */
117 "R_OPENRISC_HI_16_IN_INSN", /* name */
118 false, /* partial_inplace */
119 0x0000ffff, /* src_mask */
120 0x0000ffff, /* dst_mask */
121 false), /* pcrel_offset */
123 /* An 8 bit absolute relocation. */
124 HOWTO (R_OPENRISC_8, /* type */
125 0, /* rightshift */
126 0, /* size (0 = byte, 1 = short, 2 = long) */
127 8, /* bitsize */
128 false, /* pc_relative */
129 0, /* bitpos */
130 complain_overflow_bitfield, /* complain_on_overflow */
131 bfd_elf_generic_reloc, /* special_function */
132 "R_OPENRISC_8", /* name */
133 true, /* partial_inplace */
134 0x0000, /* src_mask */
135 0x00ff, /* dst_mask */
136 false), /* pcrel_offset */
138 /* A 16 bit absolute relocation. */
139 HOWTO (R_OPENRISC_16, /* type */
140 0, /* rightshift */
141 1, /* size (0 = byte, 1 = short, 2 = long) */
142 16, /* bitsize */
143 false, /* pc_relative */
144 0, /* bitpos */
145 complain_overflow_bitfield, /* complain_on_overflow */
146 bfd_elf_generic_reloc, /* special_function */
147 "R_OPENRISC_16", /* name */
148 true, /* partial_inplace */
149 0x00000000, /* src_mask */
150 0x0000ffff, /* dst_mask */
151 false), /* pcrel_offset */
153 /* A 32 bit absolute relocation. */
154 HOWTO (R_OPENRISC_32, /* type */
155 0, /* rightshift */
156 2, /* size (0 = byte, 1 = short, 2 = long) */
157 32, /* bitsize */
158 false, /* pc_relative */
159 0, /* bitpos */
160 complain_overflow_bitfield, /* complain_on_overflow */
161 bfd_elf_generic_reloc, /* special_function */
162 "R_OPENRISC_32", /* name */
163 true, /* partial_inplace */
164 0x00000000, /* src_mask */
165 0xffffffff, /* dst_mask */
166 false), /* pcrel_offset */
168 /* GNU extension to record C++ vtable hierarchy */
169 HOWTO (R_OPENRISC_GNU_VTINHERIT, /* type */
170 0, /* rightshift */
171 2, /* size (0 = byte, 1 = short, 2 = long) */
172 0, /* bitsize */
173 false, /* pc_relative */
174 0, /* bitpos */
175 complain_overflow_dont, /* complain_on_overflow */
176 NULL, /* special_function */
177 "R_OPENRISC_GNU_VTINHERIT", /* name */
178 false, /* partial_inplace */
179 0, /* src_mask */
180 0, /* dst_mask */
181 false), /* pcrel_offset */
183 /* GNU extension to record C++ vtable member usage */
184 HOWTO (R_OPENRISC_GNU_VTENTRY, /* type */
185 0, /* rightshift */
186 2, /* size (0 = byte, 1 = short, 2 = long) */
187 0, /* bitsize */
188 false, /* pc_relative */
189 0, /* bitpos */
190 complain_overflow_dont, /* complain_on_overflow */
191 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
192 "R_OPENRISC_GNU_VTENTRY", /* name */
193 false, /* partial_inplace */
194 0, /* src_mask */
195 0, /* dst_mask */
196 false), /* pcrel_offset */
199 /* Map BFD reloc types to OpenRISC ELF reloc types. */
201 struct openrisc_reloc_map
203 bfd_reloc_code_real_type bfd_reloc_val;
204 unsigned int openrisc_reloc_val;
207 static const struct openrisc_reloc_map openrisc_reloc_map[] =
209 { BFD_RELOC_NONE, R_OPENRISC_NONE },
210 { BFD_RELOC_32, R_OPENRISC_32 },
211 { BFD_RELOC_16, R_OPENRISC_16 },
212 { BFD_RELOC_8, R_OPENRISC_8 },
213 { BFD_RELOC_OPENRISC_REL_26,R_OPENRISC_INSN_REL_26 },
214 { BFD_RELOC_OPENRISC_ABS_26,R_OPENRISC_INSN_ABS_26 },
215 { BFD_RELOC_HI16, R_OPENRISC_HI_16_IN_INSN },
216 { BFD_RELOC_LO16, R_OPENRISC_LO_16_IN_INSN },
217 { BFD_RELOC_VTABLE_INHERIT, R_OPENRISC_GNU_VTINHERIT },
218 { BFD_RELOC_VTABLE_ENTRY, R_OPENRISC_GNU_VTENTRY }
221 static reloc_howto_type *
222 openrisc_reloc_type_lookup (abfd, code)
223 bfd * abfd ATTRIBUTE_UNUSED;
224 bfd_reloc_code_real_type code;
226 unsigned int i;
228 for (i = ARRAY_SIZE (openrisc_reloc_map); --i;)
229 if (openrisc_reloc_map[i].bfd_reloc_val == code)
230 return & openrisc_elf_howto_table[openrisc_reloc_map[i].
231 openrisc_reloc_val];
233 return NULL;
236 /* Set the howto pointer for an OpenRISC ELF reloc. */
238 static void
239 openrisc_info_to_howto_rela (abfd, cache_ptr, dst)
240 bfd * abfd ATTRIBUTE_UNUSED;
241 arelent * cache_ptr;
242 Elf32_Internal_Rela * dst;
244 unsigned int r_type;
246 r_type = ELF32_R_TYPE (dst->r_info);
247 BFD_ASSERT (r_type < (unsigned int) R_OPENRISC_max);
248 cache_ptr->howto = & openrisc_elf_howto_table[r_type];
251 /* Perform a single relocation. By default we use the standard BFD
252 routines, but a few relocs, we have to do them ourselves. */
254 static bfd_reloc_status_type
255 openrisc_final_link_relocate (howto, input_bfd, input_section, contents, rel,
256 relocation)
257 reloc_howto_type *howto;
258 bfd *input_bfd;
259 asection *input_section;
260 bfd_byte *contents;
261 Elf_Internal_Rela *rel;
262 bfd_vma relocation;
264 bfd_reloc_status_type r = bfd_reloc_ok;
266 switch (howto->type)
268 case R_OPENRISC_LO_16_IN_INSN:
269 relocation &= 0xffff;
270 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
271 contents, rel->r_offset,
272 relocation, rel->r_addend);
273 break;
275 default:
276 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
277 contents, rel->r_offset,
278 relocation, rel->r_addend);
281 return r;
284 /* Relocate an OpenRISC ELF section.
285 There is some attempt to make this function usable for many architectures,
286 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
287 if only to serve as a learning tool.
289 The RELOCATE_SECTION function is called by the new ELF backend linker
290 to handle the relocations for a section.
292 The relocs are always passed as Rela structures; if the section
293 actually uses Rel structures, the r_addend field will always be
294 zero.
296 This function is responsible for adjusting the section contents as
297 necessary, and (if using Rela relocs and generating a relocateable
298 output file) adjusting the reloc addend as necessary.
300 This function does not have to worry about setting the reloc
301 address or the reloc symbol index.
303 LOCAL_SYMS is a pointer to the swapped in local symbols.
305 LOCAL_SECTIONS is an array giving the section in the input file
306 corresponding to the st_shndx field of each local symbol.
308 The global hash table entry for the global symbols can be found
309 via elf_sym_hashes (input_bfd).
311 When generating relocateable output, this function must handle
312 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
313 going to be the section symbol corresponding to the output
314 section, which means that the addend must be adjusted
315 accordingly. */
317 static boolean
318 openrisc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
319 contents, relocs, local_syms, local_sections)
320 bfd *output_bfd ATTRIBUTE_UNUSED;
321 struct bfd_link_info *info;
322 bfd *input_bfd;
323 asection *input_section;
324 bfd_byte *contents;
325 Elf_Internal_Rela *relocs;
326 Elf_Internal_Sym *local_syms;
327 asection **local_sections;
329 Elf_Internal_Shdr *symtab_hdr;
330 struct elf_link_hash_entry **sym_hashes;
331 Elf_Internal_Rela *rel;
332 Elf_Internal_Rela *relend;
334 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
335 sym_hashes = elf_sym_hashes (input_bfd);
336 relend = relocs + input_section->reloc_count;
338 for (rel = relocs; rel < relend; rel++)
340 reloc_howto_type *howto;
341 unsigned long r_symndx;
342 Elf_Internal_Sym *sym;
343 asection *sec;
344 struct elf_link_hash_entry *h;
345 bfd_vma relocation;
346 bfd_reloc_status_type r;
347 const char *name = NULL;
348 int r_type;
350 r_type = ELF32_R_TYPE (rel->r_info);
351 r_symndx = ELF32_R_SYM (rel->r_info);
353 if (r_type == R_OPENRISC_GNU_VTINHERIT
354 || r_type == R_OPENRISC_GNU_VTENTRY)
355 continue;
357 if (info->relocateable)
359 /* This is a relocateable link. We don't have to change
360 anything, unless the reloc is against a section symbol,
361 in which case we have to adjust according to where the
362 section symbol winds up in the output section. */
363 if (r_symndx < symtab_hdr->sh_info)
365 sym = local_syms + r_symndx;
367 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
369 sec = local_sections[r_symndx];
370 rel->r_addend += sec->output_offset + sym->st_value;
373 continue;
376 if ((unsigned int) r_type >
377 (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
378 abort ();
380 /* This is a final link. */
381 howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
382 h = NULL;
383 sym = NULL;
384 sec = NULL;
386 if (r_symndx < symtab_hdr->sh_info)
388 sym = local_syms + r_symndx;
389 sec = local_sections[r_symndx];
390 relocation = (sec->output_section->vma
391 + sec->output_offset + sym->st_value);
393 name = bfd_elf_string_from_elf_section
394 (input_bfd, symtab_hdr->sh_link, sym->st_name);
395 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
397 else
399 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
401 while (h->root.type == bfd_link_hash_indirect
402 || h->root.type == bfd_link_hash_warning)
403 h = (struct elf_link_hash_entry *) h->root.u.i.link;
405 name = h->root.root.string;
407 if (h->root.type == bfd_link_hash_defined
408 || h->root.type == bfd_link_hash_defweak)
410 sec = h->root.u.def.section;
411 relocation = (h->root.u.def.value
412 + sec->output_section->vma + sec->output_offset);
414 else if (h->root.type == bfd_link_hash_undefweak)
416 relocation = 0;
418 else
420 if (!((*info->callbacks->undefined_symbol)
421 (info, h->root.root.string, input_bfd,
422 input_section, rel->r_offset, true)))
423 return false;
424 relocation = 0;
428 r = openrisc_final_link_relocate (howto, input_bfd, input_section,
429 contents, rel, relocation);
431 if (r != bfd_reloc_ok)
433 const char *msg = (const char *) NULL;
435 switch (r)
437 case bfd_reloc_overflow:
438 r = info->callbacks->reloc_overflow
439 (info, name, howto->name, (bfd_vma) 0,
440 input_bfd, input_section, rel->r_offset);
441 break;
443 case bfd_reloc_undefined:
444 r = info->callbacks->undefined_symbol
445 (info, name, input_bfd, input_section, rel->r_offset, true);
446 break;
448 case bfd_reloc_outofrange:
449 msg = _("internal error: out of range error");
450 break;
452 case bfd_reloc_notsupported:
453 msg = _("internal error: unsupported relocation error");
454 break;
456 case bfd_reloc_dangerous:
457 msg = _("internal error: dangerous relocation");
458 break;
460 default:
461 msg = _("internal error: unknown error");
462 break;
465 if (msg)
466 r = info->callbacks->warning
467 (info, msg, name, input_bfd, input_section, rel->r_offset);
469 if (!r)
470 return false;
474 return true;
477 /* Return the section that should be marked against GC for a given
478 relocation. */
480 static asection *
481 openrisc_elf_gc_mark_hook (abfd, info, rel, h, sym)
482 bfd *abfd ATTRIBUTE_UNUSED;
483 struct bfd_link_info *info ATTRIBUTE_UNUSED;
484 Elf_Internal_Rela *rel ATTRIBUTE_UNUSED;
485 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED;
486 Elf_Internal_Sym *sym ATTRIBUTE_UNUSED;
488 if (h != NULL)
490 switch (ELF32_R_TYPE (rel->r_info))
492 case R_OPENRISC_GNU_VTINHERIT:
493 case R_OPENRISC_GNU_VTENTRY:
494 break;
496 default:
497 switch (h->root.type)
499 case bfd_link_hash_defined:
500 case bfd_link_hash_defweak:
501 return h->root.u.def.section;
503 case bfd_link_hash_common:
504 return h->root.u.c.p->section;
506 default:
507 break;
511 else
513 if (!(elf_bad_symtab (abfd)
514 && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
515 && !((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
516 && sym->st_shndx != SHN_COMMON))
518 return bfd_section_from_elf_index (abfd, sym->st_shndx);
522 return NULL;
525 /* Update the got entry reference counts for the section being removed. */
527 static boolean
528 openrisc_elf_gc_sweep_hook (abfd, info, sec, relocs)
529 bfd *abfd ATTRIBUTE_UNUSED;
530 struct bfd_link_info *info ATTRIBUTE_UNUSED;
531 asection *sec ATTRIBUTE_UNUSED;
532 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
534 return true;
537 /* Look through the relocs for a section during the first phase.
538 Since we don't do .gots or .plts, we just need to consider the
539 virtual table relocs for gc. */
541 static boolean
542 openrisc_elf_check_relocs (abfd, info, sec, relocs)
543 bfd *abfd;
544 struct bfd_link_info *info;
545 asection *sec;
546 const Elf_Internal_Rela *relocs;
548 Elf_Internal_Shdr *symtab_hdr;
549 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
550 const Elf_Internal_Rela *rel;
551 const Elf_Internal_Rela *rel_end;
553 if (info->relocateable)
554 return true;
556 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
557 sym_hashes = elf_sym_hashes (abfd);
558 sym_hashes_end =
559 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
560 if (!elf_bad_symtab (abfd))
561 sym_hashes_end -= symtab_hdr->sh_info;
563 rel_end = relocs + sec->reloc_count;
564 for (rel = relocs; rel < rel_end; rel++)
566 struct elf_link_hash_entry *h;
567 unsigned long r_symndx;
569 r_symndx = ELF32_R_SYM (rel->r_info);
570 if (r_symndx < symtab_hdr->sh_info)
571 h = NULL;
572 else
573 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
575 switch (ELF32_R_TYPE (rel->r_info))
577 /* This relocation describes the C++ object vtable hierarchy.
578 Reconstruct it for later use during GC. */
579 case R_OPENRISC_GNU_VTINHERIT:
580 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
581 return false;
582 break;
584 /* This relocation describes which C++ vtable entries are actually
585 used. Record for later use during GC. */
586 case R_OPENRISC_GNU_VTENTRY:
587 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
588 return false;
589 break;
593 return true;
596 /* Set the right machine number. */
598 static boolean
599 openrisc_elf_object_p (abfd)
600 bfd *abfd;
602 switch (elf_elfheader (abfd)->e_flags & 0xf)
604 default:
605 (void) bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
606 break;
608 return true;
611 /* Store the machine number in the flags field. */
613 static void
614 openrisc_elf_final_write_processing (abfd, linker)
615 bfd *abfd;
616 boolean linker ATTRIBUTE_UNUSED;
618 unsigned long val;
620 switch (bfd_get_mach (abfd))
622 default:
623 val = 0;
624 break;
627 elf_elfheader (abfd)->e_flags &= ~0xf;
628 elf_elfheader (abfd)->e_flags |= val;
632 #define ELF_ARCH bfd_arch_openrisc
633 #define ELF_MACHINE_CODE EM_OPENRISC
634 #define ELF_MAXPAGESIZE 0x1000
636 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
637 #define TARGET_BIG_NAME "elf32-openrisc"
639 #define elf_info_to_howto_rel NULL
640 #define elf_info_to_howto openrisc_info_to_howto_rela
641 #define elf_backend_relocate_section openrisc_elf_relocate_section
642 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
643 #define elf_backend_gc_sweep_hook openrisc_elf_gc_sweep_hook
644 #define elf_backend_check_relocs openrisc_elf_check_relocs
646 #define elf_backend_can_gc_sections 1
648 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
650 #define elf_backend_object_p openrisc_elf_object_p
651 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
653 #include "elf32-target.h"