2008-01-30 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
[binutils.git] / bfd / elf32-openrisc.c
blobaf7bc25b041ef3577219fc75de0f88ebcfa8a573
1 /* OpenRISC-specific support for 32-bit ELF.
2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4 Contributed by Johan Rydberg, jrydberg@opencores.org
6 This file is part of BFD, the Binary File Descriptor library.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf/openrisc.h"
28 #include "libiberty.h"
30 static reloc_howto_type openrisc_elf_howto_table[] =
32 /* This reloc does nothing. */
33 HOWTO (R_OPENRISC_NONE, /* type */
34 0, /* rightshift */
35 2, /* size (0 = byte, 1 = short, 2 = long) */
36 32, /* bitsize */
37 FALSE, /* pc_relative */
38 0, /* bitpos */
39 complain_overflow_bitfield, /* complain_on_overflow */
40 bfd_elf_generic_reloc, /* special_function */
41 "R_OPENRISC_NONE", /* name */
42 FALSE, /* partial_inplace */
43 0, /* src_mask */
44 0, /* dst_mask */
45 FALSE), /* pcrel_offset */
47 /* A PC relative 26 bit relocation, right shifted by 2. */
48 HOWTO (R_OPENRISC_INSN_REL_26, /* type */
49 2, /* rightshift */
50 2, /* size (0 = byte, 1 = short, 2 = long) */
51 26, /* bitsize */
52 TRUE, /* pc_relative */
53 0, /* bitpos */
54 complain_overflow_signed, /* complain_on_overflow */
55 bfd_elf_generic_reloc, /* special_function */
56 "R_OPENRISC_INSN_REL_26", /* name */
57 FALSE, /* partial_inplace */
58 0x00000000, /* src_mask */
59 0x03ffffff, /* dst_mask */
60 FALSE), /* pcrel_offset */
62 /* A absolute 26 bit relocation, right shifted by 2. */
63 HOWTO (R_OPENRISC_INSN_ABS_26, /* type */
64 2, /* rightshift */
65 2, /* size (0 = byte, 1 = short, 2 = long) */
66 26, /* bitsize */
67 FALSE, /* pc_relative */
68 0, /* bitpos */
69 complain_overflow_signed, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_OPENRISC_INSN_ABS_26", /* name */
72 FALSE, /* partial_inplace */
73 0x00000000, /* src_mask */
74 0x03ffffff, /* dst_mask */
75 FALSE), /* pcrel_offset */
77 HOWTO (R_OPENRISC_LO_16_IN_INSN, /* type */
78 0, /* rightshift */
79 1, /* size (0 = byte, 1 = short, 2 = long) */
80 16, /* bitsize */
81 FALSE, /* pc_relative */
82 0, /* bitpos */
83 complain_overflow_dont, /* complain_on_overflow */
84 bfd_elf_generic_reloc, /* special_function */
85 "R_OPENRISC_LO_16_IN_INSN", /* name */
86 FALSE, /* partial_inplace */
87 0, /* src_mask */
88 0x0000ffff, /* dst_mask */
89 FALSE), /* pcrel_offset */
91 HOWTO (R_OPENRISC_HI_16_IN_INSN, /* type */
92 16, /* rightshift */
93 1, /* size (0 = byte, 1 = short, 2 = long) */
94 16, /* bitsize */
95 FALSE, /* pc_relative */
96 0, /* bitpos */
97 complain_overflow_dont, /* complain_on_overflow */
98 bfd_elf_generic_reloc, /* special_function */
99 "R_OPENRISC_HI_16_IN_INSN", /* name */
100 FALSE, /* partial_inplace */
101 0, /* src_mask */
102 0x0000ffff, /* dst_mask */
103 FALSE), /* pcrel_offset */
105 /* An 8 bit absolute relocation. */
106 HOWTO (R_OPENRISC_8, /* type */
107 0, /* rightshift */
108 0, /* size (0 = byte, 1 = short, 2 = long) */
109 8, /* bitsize */
110 FALSE, /* pc_relative */
111 0, /* bitpos */
112 complain_overflow_bitfield, /* complain_on_overflow */
113 bfd_elf_generic_reloc, /* special_function */
114 "R_OPENRISC_8", /* name */
115 TRUE, /* partial_inplace */
116 0x0000, /* src_mask */
117 0x00ff, /* dst_mask */
118 FALSE), /* pcrel_offset */
120 /* A 16 bit absolute relocation. */
121 HOWTO (R_OPENRISC_16, /* type */
122 0, /* rightshift */
123 1, /* size (0 = byte, 1 = short, 2 = long) */
124 16, /* bitsize */
125 FALSE, /* pc_relative */
126 0, /* bitpos */
127 complain_overflow_bitfield, /* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_OPENRISC_16", /* name */
130 TRUE, /* partial_inplace */
131 0x00000000, /* src_mask */
132 0x0000ffff, /* dst_mask */
133 FALSE), /* pcrel_offset */
135 /* A 32 bit absolute relocation. */
136 HOWTO (R_OPENRISC_32, /* type */
137 0, /* rightshift */
138 2, /* size (0 = byte, 1 = short, 2 = long) */
139 32, /* bitsize */
140 FALSE, /* pc_relative */
141 0, /* bitpos */
142 complain_overflow_bitfield, /* complain_on_overflow */
143 bfd_elf_generic_reloc, /* special_function */
144 "R_OPENRISC_32", /* name */
145 TRUE, /* partial_inplace */
146 0x00000000, /* src_mask */
147 0xffffffff, /* dst_mask */
148 FALSE), /* pcrel_offset */
150 /* GNU extension to record C++ vtable hierarchy. */
151 HOWTO (R_OPENRISC_GNU_VTINHERIT, /* type */
152 0, /* rightshift */
153 2, /* size (0 = byte, 1 = short, 2 = long) */
154 0, /* bitsize */
155 FALSE, /* pc_relative */
156 0, /* bitpos */
157 complain_overflow_dont, /* complain_on_overflow */
158 NULL, /* special_function */
159 "R_OPENRISC_GNU_VTINHERIT", /* name */
160 FALSE, /* partial_inplace */
161 0, /* src_mask */
162 0, /* dst_mask */
163 FALSE), /* pcrel_offset */
165 /* GNU extension to record C++ vtable member usage. */
166 HOWTO (R_OPENRISC_GNU_VTENTRY, /* type */
167 0, /* rightshift */
168 2, /* size (0 = byte, 1 = short, 2 = long) */
169 0, /* bitsize */
170 FALSE, /* pc_relative */
171 0, /* bitpos */
172 complain_overflow_dont, /* complain_on_overflow */
173 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
174 "R_OPENRISC_GNU_VTENTRY", /* name */
175 FALSE, /* partial_inplace */
176 0, /* src_mask */
177 0, /* dst_mask */
178 FALSE), /* pcrel_offset */
181 /* Map BFD reloc types to OpenRISC ELF reloc types. */
183 struct openrisc_reloc_map
185 bfd_reloc_code_real_type bfd_reloc_val;
186 unsigned int openrisc_reloc_val;
189 static const struct openrisc_reloc_map openrisc_reloc_map[] =
191 { BFD_RELOC_NONE, R_OPENRISC_NONE },
192 { BFD_RELOC_32, R_OPENRISC_32 },
193 { BFD_RELOC_16, R_OPENRISC_16 },
194 { BFD_RELOC_8, R_OPENRISC_8 },
195 { BFD_RELOC_OPENRISC_REL_26, R_OPENRISC_INSN_REL_26 },
196 { BFD_RELOC_OPENRISC_ABS_26, R_OPENRISC_INSN_ABS_26 },
197 { BFD_RELOC_HI16, R_OPENRISC_HI_16_IN_INSN },
198 { BFD_RELOC_LO16, R_OPENRISC_LO_16_IN_INSN },
199 { BFD_RELOC_VTABLE_INHERIT, R_OPENRISC_GNU_VTINHERIT },
200 { BFD_RELOC_VTABLE_ENTRY, R_OPENRISC_GNU_VTENTRY }
203 static reloc_howto_type *
204 openrisc_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
205 bfd_reloc_code_real_type code)
207 unsigned int i;
209 for (i = ARRAY_SIZE (openrisc_reloc_map); --i;)
210 if (openrisc_reloc_map[i].bfd_reloc_val == code)
211 return & openrisc_elf_howto_table[openrisc_reloc_map[i].
212 openrisc_reloc_val];
214 return NULL;
217 static reloc_howto_type *
218 openrisc_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
219 const char *r_name)
221 unsigned int i;
223 for (i = 0;
224 i < (sizeof (openrisc_elf_howto_table)
225 / sizeof (openrisc_elf_howto_table[0]));
226 i++)
227 if (openrisc_elf_howto_table[i].name != NULL
228 && strcasecmp (openrisc_elf_howto_table[i].name, r_name) == 0)
229 return &openrisc_elf_howto_table[i];
231 return NULL;
234 /* Set the howto pointer for an OpenRISC ELF reloc. */
236 static void
237 openrisc_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
238 arelent * cache_ptr,
239 Elf_Internal_Rela * dst)
241 unsigned int r_type;
243 r_type = ELF32_R_TYPE (dst->r_info);
244 BFD_ASSERT (r_type < (unsigned int) R_OPENRISC_max);
245 cache_ptr->howto = & openrisc_elf_howto_table[r_type];
248 /* Perform a single relocation. By default we use the standard BFD
249 routines, but a few relocs, we have to do them ourselves. */
251 static bfd_reloc_status_type
252 openrisc_final_link_relocate (reloc_howto_type *howto,
253 bfd *input_bfd,
254 asection *input_section,
255 bfd_byte *contents,
256 Elf_Internal_Rela *rel,
257 bfd_vma relocation)
259 bfd_reloc_status_type r = bfd_reloc_ok;
261 switch (howto->type)
263 case R_OPENRISC_LO_16_IN_INSN:
264 relocation &= 0xffff;
265 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
266 contents, rel->r_offset,
267 relocation, rel->r_addend);
268 break;
270 default:
271 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
272 contents, rel->r_offset,
273 relocation, rel->r_addend);
276 return r;
279 /* Relocate an OpenRISC ELF section.
281 The RELOCATE_SECTION function is called by the new ELF backend linker
282 to handle the relocations for a section.
284 The relocs are always passed as Rela structures; if the section
285 actually uses Rel structures, the r_addend field will always be
286 zero.
288 This function is responsible for adjusting the section contents as
289 necessary, and (if using Rela relocs and generating a relocatable
290 output file) adjusting the reloc addend as necessary.
292 This function does not have to worry about setting the reloc
293 address or the reloc symbol index.
295 LOCAL_SYMS is a pointer to the swapped in local symbols.
297 LOCAL_SECTIONS is an array giving the section in the input file
298 corresponding to the st_shndx field of each local symbol.
300 The global hash table entry for the global symbols can be found
301 via elf_sym_hashes (input_bfd).
303 When generating relocatable output, this function must handle
304 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
305 going to be the section symbol corresponding to the output
306 section, which means that the addend must be adjusted
307 accordingly. */
309 static bfd_boolean
310 openrisc_elf_relocate_section (bfd *output_bfd,
311 struct bfd_link_info *info,
312 bfd *input_bfd,
313 asection *input_section,
314 bfd_byte *contents,
315 Elf_Internal_Rela *relocs,
316 Elf_Internal_Sym *local_syms,
317 asection **local_sections)
319 Elf_Internal_Shdr *symtab_hdr;
320 struct elf_link_hash_entry **sym_hashes;
321 Elf_Internal_Rela *rel;
322 Elf_Internal_Rela *relend;
324 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
325 sym_hashes = elf_sym_hashes (input_bfd);
326 relend = relocs + input_section->reloc_count;
328 for (rel = relocs; rel < relend; rel++)
330 reloc_howto_type *howto;
331 unsigned long r_symndx;
332 Elf_Internal_Sym *sym;
333 asection *sec;
334 struct elf_link_hash_entry *h;
335 bfd_vma relocation;
336 bfd_reloc_status_type r;
337 const char *name = NULL;
338 int r_type;
340 r_type = ELF32_R_TYPE (rel->r_info);
341 r_symndx = ELF32_R_SYM (rel->r_info);
343 if (r_type == R_OPENRISC_GNU_VTINHERIT
344 || r_type == R_OPENRISC_GNU_VTENTRY)
345 continue;
347 if ((unsigned int) r_type >
348 (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
349 abort ();
351 howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
352 h = NULL;
353 sym = NULL;
354 sec = NULL;
356 if (r_symndx < symtab_hdr->sh_info)
358 sym = local_syms + r_symndx;
359 sec = local_sections[r_symndx];
360 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
362 name = bfd_elf_string_from_elf_section
363 (input_bfd, symtab_hdr->sh_link, sym->st_name);
364 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
366 else
368 bfd_boolean unresolved_reloc, warned;
370 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
371 r_symndx, symtab_hdr, sym_hashes,
372 h, sec, relocation,
373 unresolved_reloc, warned);
376 if (sec != NULL && elf_discarded_section (sec))
378 /* For relocs against symbols from removed linkonce sections,
379 or sections discarded by a linker script, we just want the
380 section contents zeroed. Avoid any special processing. */
381 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
382 rel->r_info = 0;
383 rel->r_addend = 0;
384 continue;
387 if (info->relocatable)
388 continue;
390 r = openrisc_final_link_relocate (howto, input_bfd, input_section,
391 contents, rel, relocation);
393 if (r != bfd_reloc_ok)
395 const char *msg = NULL;
397 switch (r)
399 case bfd_reloc_overflow:
400 r = info->callbacks->reloc_overflow
401 (info, (h ? &h->root : NULL), name, howto->name,
402 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
403 break;
405 case bfd_reloc_undefined:
406 r = info->callbacks->undefined_symbol
407 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
408 break;
410 case bfd_reloc_outofrange:
411 msg = _("internal error: out of range error");
412 break;
414 case bfd_reloc_notsupported:
415 msg = _("internal error: unsupported relocation error");
416 break;
418 case bfd_reloc_dangerous:
419 msg = _("internal error: dangerous relocation");
420 break;
422 default:
423 msg = _("internal error: unknown error");
424 break;
427 if (msg)
428 r = info->callbacks->warning
429 (info, msg, name, input_bfd, input_section, rel->r_offset);
431 if (!r)
432 return FALSE;
436 return TRUE;
439 /* Return the section that should be marked against GC for a given
440 relocation. */
442 static asection *
443 openrisc_elf_gc_mark_hook (asection *sec,
444 struct bfd_link_info *info,
445 Elf_Internal_Rela *rel,
446 struct elf_link_hash_entry *h,
447 Elf_Internal_Sym *sym)
449 if (h != NULL)
450 switch (ELF32_R_TYPE (rel->r_info))
452 case R_OPENRISC_GNU_VTINHERIT:
453 case R_OPENRISC_GNU_VTENTRY:
454 return NULL;
457 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
460 /* Look through the relocs for a section during the first phase.
461 Since we don't do .gots or .plts, we just need to consider the
462 virtual table relocs for gc. */
464 static bfd_boolean
465 openrisc_elf_check_relocs (bfd *abfd,
466 struct bfd_link_info *info,
467 asection *sec,
468 const Elf_Internal_Rela *relocs)
470 Elf_Internal_Shdr *symtab_hdr;
471 struct elf_link_hash_entry **sym_hashes;
472 const Elf_Internal_Rela *rel;
473 const Elf_Internal_Rela *rel_end;
475 if (info->relocatable)
476 return TRUE;
478 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
479 sym_hashes = elf_sym_hashes (abfd);
481 rel_end = relocs + sec->reloc_count;
482 for (rel = relocs; rel < rel_end; rel++)
484 struct elf_link_hash_entry *h;
485 unsigned long r_symndx;
487 r_symndx = ELF32_R_SYM (rel->r_info);
488 if (r_symndx < symtab_hdr->sh_info)
489 h = NULL;
490 else
492 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
493 while (h->root.type == bfd_link_hash_indirect
494 || h->root.type == bfd_link_hash_warning)
495 h = (struct elf_link_hash_entry *) h->root.u.i.link;
498 switch (ELF32_R_TYPE (rel->r_info))
500 /* This relocation describes the C++ object vtable hierarchy.
501 Reconstruct it for later use during GC. */
502 case R_OPENRISC_GNU_VTINHERIT:
503 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
504 return FALSE;
505 break;
507 /* This relocation describes which C++ vtable entries are actually
508 used. Record for later use during GC. */
509 case R_OPENRISC_GNU_VTENTRY:
510 BFD_ASSERT (h != NULL);
511 if (h != NULL
512 && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
513 return FALSE;
514 break;
518 return TRUE;
521 /* Set the right machine number. */
523 static bfd_boolean
524 openrisc_elf_object_p (bfd *abfd)
526 bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
527 return TRUE;
530 /* Store the machine number in the flags field. */
532 static void
533 openrisc_elf_final_write_processing (bfd *abfd,
534 bfd_boolean linker ATTRIBUTE_UNUSED)
536 unsigned long val;
538 switch (bfd_get_mach (abfd))
540 default:
541 val = 0;
542 break;
545 elf_elfheader (abfd)->e_flags &= ~0xf;
546 elf_elfheader (abfd)->e_flags |= val;
550 #define ELF_ARCH bfd_arch_openrisc
551 #define ELF_MACHINE_CODE EM_OPENRISC
552 #define ELF_MACHINE_ALT1 EM_OPENRISC_OLD
553 #define ELF_MAXPAGESIZE 0x1000
555 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
556 #define TARGET_BIG_NAME "elf32-openrisc"
558 #define elf_info_to_howto_rel NULL
559 #define elf_info_to_howto openrisc_info_to_howto_rela
560 #define elf_backend_relocate_section openrisc_elf_relocate_section
561 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
562 #define elf_backend_check_relocs openrisc_elf_check_relocs
564 #define elf_backend_can_gc_sections 1
565 #define elf_backend_rela_normal 1
567 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
568 #define bfd_elf32_bfd_reloc_name_lookup openrisc_reloc_name_lookup
570 #define elf_backend_object_p openrisc_elf_object_p
571 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
573 #include "elf32-target.h"