* elf32-xtensa.c (analyze_relocations): Zero src_count if not relaxing.
[binutils.git] / bfd / elf32-openrisc.c
blobfbda8fb3d1d3601906885dd19cdc511096cf83f9
1 /* OpenRISC-specific support for 32-bit ELF.
2 Copyright 2001, 2002, 2003, 2004, 2005, 2006
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 2 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, MA 02110-1301,
21 USA. */
23 #include "bfd.h"
24 #include "sysdep.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 /* Set the howto pointer for an OpenRISC ELF reloc. */
219 static void
220 openrisc_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
221 arelent * cache_ptr,
222 Elf_Internal_Rela * dst)
224 unsigned int r_type;
226 r_type = ELF32_R_TYPE (dst->r_info);
227 BFD_ASSERT (r_type < (unsigned int) R_OPENRISC_max);
228 cache_ptr->howto = & openrisc_elf_howto_table[r_type];
231 /* Perform a single relocation. By default we use the standard BFD
232 routines, but a few relocs, we have to do them ourselves. */
234 static bfd_reloc_status_type
235 openrisc_final_link_relocate (reloc_howto_type *howto,
236 bfd *input_bfd,
237 asection *input_section,
238 bfd_byte *contents,
239 Elf_Internal_Rela *rel,
240 bfd_vma relocation)
242 bfd_reloc_status_type r = bfd_reloc_ok;
244 switch (howto->type)
246 case R_OPENRISC_LO_16_IN_INSN:
247 relocation &= 0xffff;
248 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
249 contents, rel->r_offset,
250 relocation, rel->r_addend);
251 break;
253 default:
254 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
255 contents, rel->r_offset,
256 relocation, rel->r_addend);
259 return r;
262 /* Relocate an OpenRISC ELF section.
264 The RELOCATE_SECTION function is called by the new ELF backend linker
265 to handle the relocations for a section.
267 The relocs are always passed as Rela structures; if the section
268 actually uses Rel structures, the r_addend field will always be
269 zero.
271 This function is responsible for adjusting the section contents as
272 necessary, and (if using Rela relocs and generating a relocatable
273 output file) adjusting the reloc addend as necessary.
275 This function does not have to worry about setting the reloc
276 address or the reloc symbol index.
278 LOCAL_SYMS is a pointer to the swapped in local symbols.
280 LOCAL_SECTIONS is an array giving the section in the input file
281 corresponding to the st_shndx field of each local symbol.
283 The global hash table entry for the global symbols can be found
284 via elf_sym_hashes (input_bfd).
286 When generating relocatable output, this function must handle
287 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
288 going to be the section symbol corresponding to the output
289 section, which means that the addend must be adjusted
290 accordingly. */
292 static bfd_boolean
293 openrisc_elf_relocate_section (bfd *output_bfd,
294 struct bfd_link_info *info,
295 bfd *input_bfd,
296 asection *input_section,
297 bfd_byte *contents,
298 Elf_Internal_Rela *relocs,
299 Elf_Internal_Sym *local_syms,
300 asection **local_sections)
302 Elf_Internal_Shdr *symtab_hdr;
303 struct elf_link_hash_entry **sym_hashes;
304 Elf_Internal_Rela *rel;
305 Elf_Internal_Rela *relend;
307 if (info->relocatable)
308 return TRUE;
310 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
311 sym_hashes = elf_sym_hashes (input_bfd);
312 relend = relocs + input_section->reloc_count;
314 for (rel = relocs; rel < relend; rel++)
316 reloc_howto_type *howto;
317 unsigned long r_symndx;
318 Elf_Internal_Sym *sym;
319 asection *sec;
320 struct elf_link_hash_entry *h;
321 bfd_vma relocation;
322 bfd_reloc_status_type r;
323 const char *name = NULL;
324 int r_type;
326 r_type = ELF32_R_TYPE (rel->r_info);
327 r_symndx = ELF32_R_SYM (rel->r_info);
329 if (r_type == R_OPENRISC_GNU_VTINHERIT
330 || r_type == R_OPENRISC_GNU_VTENTRY)
331 continue;
333 if ((unsigned int) r_type >
334 (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
335 abort ();
337 /* This is a final link. */
338 howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
339 h = NULL;
340 sym = NULL;
341 sec = NULL;
343 if (r_symndx < symtab_hdr->sh_info)
345 sym = local_syms + r_symndx;
346 sec = local_sections[r_symndx];
347 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
349 name = bfd_elf_string_from_elf_section
350 (input_bfd, symtab_hdr->sh_link, sym->st_name);
351 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
353 else
355 bfd_boolean unresolved_reloc, warned;
357 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
358 r_symndx, symtab_hdr, sym_hashes,
359 h, sec, relocation,
360 unresolved_reloc, warned);
363 r = openrisc_final_link_relocate (howto, input_bfd, input_section,
364 contents, rel, relocation);
366 if (r != bfd_reloc_ok)
368 const char *msg = NULL;
370 switch (r)
372 case bfd_reloc_overflow:
373 r = info->callbacks->reloc_overflow
374 (info, (h ? &h->root : NULL), name, howto->name,
375 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
376 break;
378 case bfd_reloc_undefined:
379 r = info->callbacks->undefined_symbol
380 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
381 break;
383 case bfd_reloc_outofrange:
384 msg = _("internal error: out of range error");
385 break;
387 case bfd_reloc_notsupported:
388 msg = _("internal error: unsupported relocation error");
389 break;
391 case bfd_reloc_dangerous:
392 msg = _("internal error: dangerous relocation");
393 break;
395 default:
396 msg = _("internal error: unknown error");
397 break;
400 if (msg)
401 r = info->callbacks->warning
402 (info, msg, name, input_bfd, input_section, rel->r_offset);
404 if (!r)
405 return FALSE;
409 return TRUE;
412 /* Return the section that should be marked against GC for a given
413 relocation. */
415 static asection *
416 openrisc_elf_gc_mark_hook (asection *sec,
417 struct bfd_link_info *info,
418 Elf_Internal_Rela *rel,
419 struct elf_link_hash_entry *h,
420 Elf_Internal_Sym *sym)
422 if (h != NULL)
423 switch (ELF32_R_TYPE (rel->r_info))
425 case R_OPENRISC_GNU_VTINHERIT:
426 case R_OPENRISC_GNU_VTENTRY:
427 return NULL;
430 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
433 /* Look through the relocs for a section during the first phase.
434 Since we don't do .gots or .plts, we just need to consider the
435 virtual table relocs for gc. */
437 static bfd_boolean
438 openrisc_elf_check_relocs (bfd *abfd,
439 struct bfd_link_info *info,
440 asection *sec,
441 const Elf_Internal_Rela *relocs)
443 Elf_Internal_Shdr *symtab_hdr;
444 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
445 const Elf_Internal_Rela *rel;
446 const Elf_Internal_Rela *rel_end;
448 if (info->relocatable)
449 return TRUE;
451 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
452 sym_hashes = elf_sym_hashes (abfd);
453 sym_hashes_end =
454 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
455 if (!elf_bad_symtab (abfd))
456 sym_hashes_end -= symtab_hdr->sh_info;
458 rel_end = relocs + sec->reloc_count;
459 for (rel = relocs; rel < rel_end; rel++)
461 struct elf_link_hash_entry *h;
462 unsigned long r_symndx;
464 r_symndx = ELF32_R_SYM (rel->r_info);
465 if (r_symndx < symtab_hdr->sh_info)
466 h = NULL;
467 else
469 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
470 while (h->root.type == bfd_link_hash_indirect
471 || h->root.type == bfd_link_hash_warning)
472 h = (struct elf_link_hash_entry *) h->root.u.i.link;
475 switch (ELF32_R_TYPE (rel->r_info))
477 /* This relocation describes the C++ object vtable hierarchy.
478 Reconstruct it for later use during GC. */
479 case R_OPENRISC_GNU_VTINHERIT:
480 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
481 return FALSE;
482 break;
484 /* This relocation describes which C++ vtable entries are actually
485 used. Record for later use during GC. */
486 case R_OPENRISC_GNU_VTENTRY:
487 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
488 return FALSE;
489 break;
493 return TRUE;
496 /* Set the right machine number. */
498 static bfd_boolean
499 openrisc_elf_object_p (bfd *abfd)
501 bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
502 return TRUE;
505 /* Store the machine number in the flags field. */
507 static void
508 openrisc_elf_final_write_processing (bfd *abfd,
509 bfd_boolean linker ATTRIBUTE_UNUSED)
511 unsigned long val;
513 switch (bfd_get_mach (abfd))
515 default:
516 val = 0;
517 break;
520 elf_elfheader (abfd)->e_flags &= ~0xf;
521 elf_elfheader (abfd)->e_flags |= val;
525 #define ELF_ARCH bfd_arch_openrisc
526 #define ELF_MACHINE_CODE EM_OPENRISC
527 #define ELF_MACHINE_ALT1 EM_OPENRISC_OLD
528 #define ELF_MAXPAGESIZE 0x1000
530 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
531 #define TARGET_BIG_NAME "elf32-openrisc"
533 #define elf_info_to_howto_rel NULL
534 #define elf_info_to_howto openrisc_info_to_howto_rela
535 #define elf_backend_relocate_section openrisc_elf_relocate_section
536 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
537 #define elf_backend_check_relocs openrisc_elf_check_relocs
539 #define elf_backend_can_gc_sections 1
540 #define elf_backend_rela_normal 1
542 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
544 #define elf_backend_object_p openrisc_elf_object_p
545 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
547 #include "elf32-target.h"