d6b40497633f0c5a7db25b9e1c942b278dd044a0
[deliverable/binutils-gdb.git] / bfd / elf32-openrisc.c
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
5
6 This file is part of BFD, the Binary File Descriptor library.
7
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.
12
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.
17
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. */
22
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"
29
30 static reloc_howto_type openrisc_elf_howto_table[] =
31 {
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 */
46
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 */
61
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 */
76
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 */
90
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 */
104
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 */
119
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 */
134
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 */
149
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 */
164
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 */
179 };
180
181 /* Map BFD reloc types to OpenRISC ELF reloc types. */
182
183 struct openrisc_reloc_map
184 {
185 bfd_reloc_code_real_type bfd_reloc_val;
186 unsigned int openrisc_reloc_val;
187 };
188
189 static const struct openrisc_reloc_map openrisc_reloc_map[] =
190 {
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 }
201 };
202
203 static reloc_howto_type *
204 openrisc_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
205 bfd_reloc_code_real_type code)
206 {
207 unsigned int i;
208
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];
213
214 return NULL;
215 }
216
217 /* Set the howto pointer for an OpenRISC ELF reloc. */
218
219 static void
220 openrisc_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
221 arelent * cache_ptr,
222 Elf_Internal_Rela * dst)
223 {
224 unsigned int r_type;
225
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];
229 }
230
231 /* Perform a single relocation. By default we use the standard BFD
232 routines, but a few relocs, we have to do them ourselves. */
233
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)
241 {
242 bfd_reloc_status_type r = bfd_reloc_ok;
243
244 switch (howto->type)
245 {
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;
252
253 default:
254 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
255 contents, rel->r_offset,
256 relocation, rel->r_addend);
257 }
258
259 return r;
260 }
261
262 /* Relocate an OpenRISC ELF section.
263
264 The RELOCATE_SECTION function is called by the new ELF backend linker
265 to handle the relocations for a section.
266
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.
270
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.
274
275 This function does not have to worry about setting the reloc
276 address or the reloc symbol index.
277
278 LOCAL_SYMS is a pointer to the swapped in local symbols.
279
280 LOCAL_SECTIONS is an array giving the section in the input file
281 corresponding to the st_shndx field of each local symbol.
282
283 The global hash table entry for the global symbols can be found
284 via elf_sym_hashes (input_bfd).
285
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. */
291
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)
301 {
302 Elf_Internal_Shdr *symtab_hdr;
303 struct elf_link_hash_entry **sym_hashes;
304 Elf_Internal_Rela *rel;
305 Elf_Internal_Rela *relend;
306
307 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
308 sym_hashes = elf_sym_hashes (input_bfd);
309 relend = relocs + input_section->reloc_count;
310
311 for (rel = relocs; rel < relend; rel++)
312 {
313 reloc_howto_type *howto;
314 unsigned long r_symndx;
315 Elf_Internal_Sym *sym;
316 asection *sec;
317 struct elf_link_hash_entry *h;
318 bfd_vma relocation;
319 bfd_reloc_status_type r;
320 const char *name = NULL;
321 int r_type;
322
323 r_type = ELF32_R_TYPE (rel->r_info);
324 r_symndx = ELF32_R_SYM (rel->r_info);
325
326 if (r_type == R_OPENRISC_GNU_VTINHERIT
327 || r_type == R_OPENRISC_GNU_VTENTRY)
328 continue;
329
330 if ((unsigned int) r_type >
331 (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
332 abort ();
333
334 howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
335 h = NULL;
336 sym = NULL;
337 sec = NULL;
338
339 if (r_symndx < symtab_hdr->sh_info)
340 {
341 sym = local_syms + r_symndx;
342 sec = local_sections[r_symndx];
343 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
344
345 name = bfd_elf_string_from_elf_section
346 (input_bfd, symtab_hdr->sh_link, sym->st_name);
347 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
348 }
349 else
350 {
351 bfd_boolean unresolved_reloc, warned;
352
353 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
354 r_symndx, symtab_hdr, sym_hashes,
355 h, sec, relocation,
356 unresolved_reloc, warned);
357 }
358
359 if (sec != NULL && elf_discarded_section (sec))
360 {
361 /* For relocs against symbols from removed linkonce sections,
362 or sections discarded by a linker script, we just want the
363 section contents zeroed. Avoid any special processing. */
364 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
365 rel->r_info = 0;
366 rel->r_addend = 0;
367 continue;
368 }
369
370 if (info->relocatable)
371 continue;
372
373 r = openrisc_final_link_relocate (howto, input_bfd, input_section,
374 contents, rel, relocation);
375
376 if (r != bfd_reloc_ok)
377 {
378 const char *msg = NULL;
379
380 switch (r)
381 {
382 case bfd_reloc_overflow:
383 r = info->callbacks->reloc_overflow
384 (info, (h ? &h->root : NULL), name, howto->name,
385 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
386 break;
387
388 case bfd_reloc_undefined:
389 r = info->callbacks->undefined_symbol
390 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
391 break;
392
393 case bfd_reloc_outofrange:
394 msg = _("internal error: out of range error");
395 break;
396
397 case bfd_reloc_notsupported:
398 msg = _("internal error: unsupported relocation error");
399 break;
400
401 case bfd_reloc_dangerous:
402 msg = _("internal error: dangerous relocation");
403 break;
404
405 default:
406 msg = _("internal error: unknown error");
407 break;
408 }
409
410 if (msg)
411 r = info->callbacks->warning
412 (info, msg, name, input_bfd, input_section, rel->r_offset);
413
414 if (!r)
415 return FALSE;
416 }
417 }
418
419 return TRUE;
420 }
421
422 /* Return the section that should be marked against GC for a given
423 relocation. */
424
425 static asection *
426 openrisc_elf_gc_mark_hook (asection *sec,
427 struct bfd_link_info *info,
428 Elf_Internal_Rela *rel,
429 struct elf_link_hash_entry *h,
430 Elf_Internal_Sym *sym)
431 {
432 if (h != NULL)
433 switch (ELF32_R_TYPE (rel->r_info))
434 {
435 case R_OPENRISC_GNU_VTINHERIT:
436 case R_OPENRISC_GNU_VTENTRY:
437 return NULL;
438 }
439
440 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
441 }
442
443 /* Look through the relocs for a section during the first phase.
444 Since we don't do .gots or .plts, we just need to consider the
445 virtual table relocs for gc. */
446
447 static bfd_boolean
448 openrisc_elf_check_relocs (bfd *abfd,
449 struct bfd_link_info *info,
450 asection *sec,
451 const Elf_Internal_Rela *relocs)
452 {
453 Elf_Internal_Shdr *symtab_hdr;
454 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
455 const Elf_Internal_Rela *rel;
456 const Elf_Internal_Rela *rel_end;
457
458 if (info->relocatable)
459 return TRUE;
460
461 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
462 sym_hashes = elf_sym_hashes (abfd);
463 sym_hashes_end =
464 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
465 if (!elf_bad_symtab (abfd))
466 sym_hashes_end -= symtab_hdr->sh_info;
467
468 rel_end = relocs + sec->reloc_count;
469 for (rel = relocs; rel < rel_end; rel++)
470 {
471 struct elf_link_hash_entry *h;
472 unsigned long r_symndx;
473
474 r_symndx = ELF32_R_SYM (rel->r_info);
475 if (r_symndx < symtab_hdr->sh_info)
476 h = NULL;
477 else
478 {
479 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
480 while (h->root.type == bfd_link_hash_indirect
481 || h->root.type == bfd_link_hash_warning)
482 h = (struct elf_link_hash_entry *) h->root.u.i.link;
483 }
484
485 switch (ELF32_R_TYPE (rel->r_info))
486 {
487 /* This relocation describes the C++ object vtable hierarchy.
488 Reconstruct it for later use during GC. */
489 case R_OPENRISC_GNU_VTINHERIT:
490 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
491 return FALSE;
492 break;
493
494 /* This relocation describes which C++ vtable entries are actually
495 used. Record for later use during GC. */
496 case R_OPENRISC_GNU_VTENTRY:
497 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
498 return FALSE;
499 break;
500 }
501 }
502
503 return TRUE;
504 }
505
506 /* Set the right machine number. */
507
508 static bfd_boolean
509 openrisc_elf_object_p (bfd *abfd)
510 {
511 bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
512 return TRUE;
513 }
514
515 /* Store the machine number in the flags field. */
516
517 static void
518 openrisc_elf_final_write_processing (bfd *abfd,
519 bfd_boolean linker ATTRIBUTE_UNUSED)
520 {
521 unsigned long val;
522
523 switch (bfd_get_mach (abfd))
524 {
525 default:
526 val = 0;
527 break;
528 }
529
530 elf_elfheader (abfd)->e_flags &= ~0xf;
531 elf_elfheader (abfd)->e_flags |= val;
532 }
533
534
535 #define ELF_ARCH bfd_arch_openrisc
536 #define ELF_MACHINE_CODE EM_OPENRISC
537 #define ELF_MACHINE_ALT1 EM_OPENRISC_OLD
538 #define ELF_MAXPAGESIZE 0x1000
539
540 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
541 #define TARGET_BIG_NAME "elf32-openrisc"
542
543 #define elf_info_to_howto_rel NULL
544 #define elf_info_to_howto openrisc_info_to_howto_rela
545 #define elf_backend_relocate_section openrisc_elf_relocate_section
546 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
547 #define elf_backend_check_relocs openrisc_elf_check_relocs
548
549 #define elf_backend_can_gc_sections 1
550 #define elf_backend_rela_normal 1
551
552 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
553
554 #define elf_backend_object_p openrisc_elf_object_p
555 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
556
557 #include "elf32-target.h"
This page took 0.041452 seconds and 4 git commands to generate.