daily update
[deliverable/binutils-gdb.git] / bfd / elf32-openrisc.c
1 /* OpenRISC-specific support for 32-bit ELF.
2 Copyright 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Johan Rydberg, jrydberg@opencores.org
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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.
11
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.
16
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. */
20
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"
27
28 /* Forward declarations. */
29
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 *));
46 static boolean openrisc_elf_check_relocs
47 PARAMS ((bfd *, struct bfd_link_info *, asection *,
48 const Elf_Internal_Rela *));
49 static boolean openrisc_elf_object_p
50 PARAMS ((bfd *));
51 static void openrisc_elf_final_write_processing
52 PARAMS ((bfd *, boolean));
53
54
55 static reloc_howto_type openrisc_elf_howto_table[] =
56 {
57 /* This reloc does nothing. */
58 HOWTO (R_OPENRISC_NONE, /* type */
59 0, /* rightshift */
60 2, /* size (0 = byte, 1 = short, 2 = long) */
61 32, /* bitsize */
62 false, /* pc_relative */
63 0, /* bitpos */
64 complain_overflow_bitfield, /* complain_on_overflow */
65 bfd_elf_generic_reloc, /* special_function */
66 "R_OPENRISC_NONE", /* name */
67 false, /* partial_inplace */
68 0, /* src_mask */
69 0, /* dst_mask */
70 false), /* pcrel_offset */
71
72 /* A PC relative 26 bit relocation, right shifted by 2. */
73 HOWTO (R_OPENRISC_INSN_REL_26, /* type */
74 2, /* rightshift */
75 2, /* size (0 = byte, 1 = short, 2 = long) */
76 26, /* bitsize */
77 true, /* pc_relative */
78 0, /* bitpos */
79 complain_overflow_signed, /* complain_on_overflow */
80 bfd_elf_generic_reloc, /* special_function */
81 "R_OPENRISC_INSN_REL_26", /* name */
82 false, /* partial_inplace */
83 0x00000000, /* src_mask */
84 0x03ffffff, /* dst_mask */
85 false), /* pcrel_offset */
86
87 /* A absolute 26 bit relocation, right shifted by 2. */
88 HOWTO (R_OPENRISC_INSN_ABS_26, /* type */
89 2, /* rightshift */
90 2, /* size (0 = byte, 1 = short, 2 = long) */
91 26, /* bitsize */
92 false, /* pc_relative */
93 0, /* bitpos */
94 complain_overflow_signed, /* complain_on_overflow */
95 bfd_elf_generic_reloc, /* special_function */
96 "R_OPENRISC_INSN_ABS_26", /* name */
97 false, /* partial_inplace */
98 0x00000000, /* src_mask */
99 0x03ffffff, /* dst_mask */
100 false), /* pcrel_offset */
101
102 HOWTO (R_OPENRISC_LO_16_IN_INSN, /* type */
103 0, /* rightshift */
104 1, /* size (0 = byte, 1 = short, 2 = long) */
105 16, /* bitsize */
106 false, /* pc_relative */
107 0, /* bitpos */
108 complain_overflow_dont, /* complain_on_overflow */
109 bfd_elf_generic_reloc, /* special_function */
110 "R_OPENRISC_LO_16_IN_INSN", /* name */
111 false, /* partial_inplace */
112 0, /* src_mask */
113 0x0000ffff, /* dst_mask */
114 false), /* pcrel_offset */
115
116 HOWTO (R_OPENRISC_HI_16_IN_INSN, /* type */
117 16, /* rightshift */
118 1, /* size (0 = byte, 1 = short, 2 = long) */
119 16, /* bitsize */
120 false, /* pc_relative */
121 0, /* bitpos */
122 complain_overflow_dont, /* complain_on_overflow */
123 bfd_elf_generic_reloc, /* special_function */
124 "R_OPENRISC_HI_16_IN_INSN", /* name */
125 false, /* partial_inplace */
126 0, /* src_mask */
127 0x0000ffff, /* dst_mask */
128 false), /* pcrel_offset */
129
130 /* An 8 bit absolute relocation. */
131 HOWTO (R_OPENRISC_8, /* type */
132 0, /* rightshift */
133 0, /* size (0 = byte, 1 = short, 2 = long) */
134 8, /* bitsize */
135 false, /* pc_relative */
136 0, /* bitpos */
137 complain_overflow_bitfield, /* complain_on_overflow */
138 bfd_elf_generic_reloc, /* special_function */
139 "R_OPENRISC_8", /* name */
140 true, /* partial_inplace */
141 0x0000, /* src_mask */
142 0x00ff, /* dst_mask */
143 false), /* pcrel_offset */
144
145 /* A 16 bit absolute relocation. */
146 HOWTO (R_OPENRISC_16, /* type */
147 0, /* rightshift */
148 1, /* size (0 = byte, 1 = short, 2 = long) */
149 16, /* bitsize */
150 false, /* pc_relative */
151 0, /* bitpos */
152 complain_overflow_bitfield, /* complain_on_overflow */
153 bfd_elf_generic_reloc, /* special_function */
154 "R_OPENRISC_16", /* name */
155 true, /* partial_inplace */
156 0x00000000, /* src_mask */
157 0x0000ffff, /* dst_mask */
158 false), /* pcrel_offset */
159
160 /* A 32 bit absolute relocation. */
161 HOWTO (R_OPENRISC_32, /* type */
162 0, /* rightshift */
163 2, /* size (0 = byte, 1 = short, 2 = long) */
164 32, /* bitsize */
165 false, /* pc_relative */
166 0, /* bitpos */
167 complain_overflow_bitfield, /* complain_on_overflow */
168 bfd_elf_generic_reloc, /* special_function */
169 "R_OPENRISC_32", /* name */
170 true, /* partial_inplace */
171 0x00000000, /* src_mask */
172 0xffffffff, /* dst_mask */
173 false), /* pcrel_offset */
174
175 /* GNU extension to record C++ vtable hierarchy */
176 HOWTO (R_OPENRISC_GNU_VTINHERIT, /* type */
177 0, /* rightshift */
178 2, /* size (0 = byte, 1 = short, 2 = long) */
179 0, /* bitsize */
180 false, /* pc_relative */
181 0, /* bitpos */
182 complain_overflow_dont, /* complain_on_overflow */
183 NULL, /* special_function */
184 "R_OPENRISC_GNU_VTINHERIT", /* name */
185 false, /* partial_inplace */
186 0, /* src_mask */
187 0, /* dst_mask */
188 false), /* pcrel_offset */
189
190 /* GNU extension to record C++ vtable member usage */
191 HOWTO (R_OPENRISC_GNU_VTENTRY, /* type */
192 0, /* rightshift */
193 2, /* size (0 = byte, 1 = short, 2 = long) */
194 0, /* bitsize */
195 false, /* pc_relative */
196 0, /* bitpos */
197 complain_overflow_dont, /* complain_on_overflow */
198 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
199 "R_OPENRISC_GNU_VTENTRY", /* name */
200 false, /* partial_inplace */
201 0, /* src_mask */
202 0, /* dst_mask */
203 false), /* pcrel_offset */
204 };
205
206 /* Map BFD reloc types to OpenRISC ELF reloc types. */
207
208 struct openrisc_reloc_map
209 {
210 bfd_reloc_code_real_type bfd_reloc_val;
211 unsigned int openrisc_reloc_val;
212 };
213
214 static const struct openrisc_reloc_map openrisc_reloc_map[] =
215 {
216 { BFD_RELOC_NONE, R_OPENRISC_NONE },
217 { BFD_RELOC_32, R_OPENRISC_32 },
218 { BFD_RELOC_16, R_OPENRISC_16 },
219 { BFD_RELOC_8, R_OPENRISC_8 },
220 { BFD_RELOC_OPENRISC_REL_26,R_OPENRISC_INSN_REL_26 },
221 { BFD_RELOC_OPENRISC_ABS_26,R_OPENRISC_INSN_ABS_26 },
222 { BFD_RELOC_HI16, R_OPENRISC_HI_16_IN_INSN },
223 { BFD_RELOC_LO16, R_OPENRISC_LO_16_IN_INSN },
224 { BFD_RELOC_VTABLE_INHERIT, R_OPENRISC_GNU_VTINHERIT },
225 { BFD_RELOC_VTABLE_ENTRY, R_OPENRISC_GNU_VTENTRY }
226 };
227
228 static reloc_howto_type *
229 openrisc_reloc_type_lookup (abfd, code)
230 bfd * abfd ATTRIBUTE_UNUSED;
231 bfd_reloc_code_real_type code;
232 {
233 unsigned int i;
234
235 for (i = ARRAY_SIZE (openrisc_reloc_map); --i;)
236 if (openrisc_reloc_map[i].bfd_reloc_val == code)
237 return & openrisc_elf_howto_table[openrisc_reloc_map[i].
238 openrisc_reloc_val];
239
240 return NULL;
241 }
242
243 /* Set the howto pointer for an OpenRISC ELF reloc. */
244
245 static void
246 openrisc_info_to_howto_rela (abfd, cache_ptr, dst)
247 bfd * abfd ATTRIBUTE_UNUSED;
248 arelent * cache_ptr;
249 Elf32_Internal_Rela * dst;
250 {
251 unsigned int r_type;
252
253 r_type = ELF32_R_TYPE (dst->r_info);
254 BFD_ASSERT (r_type < (unsigned int) R_OPENRISC_max);
255 cache_ptr->howto = & openrisc_elf_howto_table[r_type];
256 }
257
258 /* Perform a single relocation. By default we use the standard BFD
259 routines, but a few relocs, we have to do them ourselves. */
260
261 static bfd_reloc_status_type
262 openrisc_final_link_relocate (howto, input_bfd, input_section, contents, rel,
263 relocation)
264 reloc_howto_type *howto;
265 bfd *input_bfd;
266 asection *input_section;
267 bfd_byte *contents;
268 Elf_Internal_Rela *rel;
269 bfd_vma relocation;
270 {
271 bfd_reloc_status_type r = bfd_reloc_ok;
272
273 switch (howto->type)
274 {
275 case R_OPENRISC_LO_16_IN_INSN:
276 relocation &= 0xffff;
277 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
278 contents, rel->r_offset,
279 relocation, rel->r_addend);
280 break;
281
282 default:
283 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
284 contents, rel->r_offset,
285 relocation, rel->r_addend);
286 }
287
288 return r;
289 }
290
291 /* Relocate an OpenRISC ELF section.
292 There is some attempt to make this function usable for many architectures,
293 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
294 if only to serve as a learning tool.
295
296 The RELOCATE_SECTION function is called by the new ELF backend linker
297 to handle the relocations for a section.
298
299 The relocs are always passed as Rela structures; if the section
300 actually uses Rel structures, the r_addend field will always be
301 zero.
302
303 This function is responsible for adjusting the section contents as
304 necessary, and (if using Rela relocs and generating a relocateable
305 output file) adjusting the reloc addend as necessary.
306
307 This function does not have to worry about setting the reloc
308 address or the reloc symbol index.
309
310 LOCAL_SYMS is a pointer to the swapped in local symbols.
311
312 LOCAL_SECTIONS is an array giving the section in the input file
313 corresponding to the st_shndx field of each local symbol.
314
315 The global hash table entry for the global symbols can be found
316 via elf_sym_hashes (input_bfd).
317
318 When generating relocateable output, this function must handle
319 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
320 going to be the section symbol corresponding to the output
321 section, which means that the addend must be adjusted
322 accordingly. */
323
324 static boolean
325 openrisc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
326 contents, relocs, local_syms, local_sections)
327 bfd *output_bfd;
328 struct bfd_link_info *info;
329 bfd *input_bfd;
330 asection *input_section;
331 bfd_byte *contents;
332 Elf_Internal_Rela *relocs;
333 Elf_Internal_Sym *local_syms;
334 asection **local_sections;
335 {
336 Elf_Internal_Shdr *symtab_hdr;
337 struct elf_link_hash_entry **sym_hashes;
338 Elf_Internal_Rela *rel;
339 Elf_Internal_Rela *relend;
340
341 if (info->relocateable)
342 return true;
343
344 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
345 sym_hashes = elf_sym_hashes (input_bfd);
346 relend = relocs + input_section->reloc_count;
347
348 for (rel = relocs; rel < relend; rel++)
349 {
350 reloc_howto_type *howto;
351 unsigned long r_symndx;
352 Elf_Internal_Sym *sym;
353 asection *sec;
354 struct elf_link_hash_entry *h;
355 bfd_vma relocation;
356 bfd_reloc_status_type r;
357 const char *name = NULL;
358 int r_type;
359
360 r_type = ELF32_R_TYPE (rel->r_info);
361 r_symndx = ELF32_R_SYM (rel->r_info);
362
363 if (r_type == R_OPENRISC_GNU_VTINHERIT
364 || r_type == R_OPENRISC_GNU_VTENTRY)
365 continue;
366
367 if ((unsigned int) r_type >
368 (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
369 abort ();
370
371 /* This is a final link. */
372 howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
373 h = NULL;
374 sym = NULL;
375 sec = NULL;
376
377 if (r_symndx < symtab_hdr->sh_info)
378 {
379 sym = local_syms + r_symndx;
380 sec = local_sections[r_symndx];
381 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
382
383 name = bfd_elf_string_from_elf_section
384 (input_bfd, symtab_hdr->sh_link, sym->st_name);
385 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
386 }
387 else
388 {
389 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
390
391 while (h->root.type == bfd_link_hash_indirect
392 || h->root.type == bfd_link_hash_warning)
393 h = (struct elf_link_hash_entry *) h->root.u.i.link;
394
395 name = h->root.root.string;
396
397 if (h->root.type == bfd_link_hash_defined
398 || h->root.type == bfd_link_hash_defweak)
399 {
400 sec = h->root.u.def.section;
401 relocation = (h->root.u.def.value
402 + sec->output_section->vma + sec->output_offset);
403 }
404 else if (h->root.type == bfd_link_hash_undefweak)
405 {
406 relocation = 0;
407 }
408 else
409 {
410 if (!((*info->callbacks->undefined_symbol)
411 (info, h->root.root.string, input_bfd,
412 input_section, rel->r_offset, true)))
413 return false;
414 relocation = 0;
415 }
416 }
417
418 r = openrisc_final_link_relocate (howto, input_bfd, input_section,
419 contents, rel, relocation);
420
421 if (r != bfd_reloc_ok)
422 {
423 const char *msg = (const char *) NULL;
424
425 switch (r)
426 {
427 case bfd_reloc_overflow:
428 r = info->callbacks->reloc_overflow
429 (info, name, howto->name, (bfd_vma) 0,
430 input_bfd, input_section, rel->r_offset);
431 break;
432
433 case bfd_reloc_undefined:
434 r = info->callbacks->undefined_symbol
435 (info, name, input_bfd, input_section, rel->r_offset, true);
436 break;
437
438 case bfd_reloc_outofrange:
439 msg = _("internal error: out of range error");
440 break;
441
442 case bfd_reloc_notsupported:
443 msg = _("internal error: unsupported relocation error");
444 break;
445
446 case bfd_reloc_dangerous:
447 msg = _("internal error: dangerous relocation");
448 break;
449
450 default:
451 msg = _("internal error: unknown error");
452 break;
453 }
454
455 if (msg)
456 r = info->callbacks->warning
457 (info, msg, name, input_bfd, input_section, rel->r_offset);
458
459 if (!r)
460 return false;
461 }
462 }
463
464 return true;
465 }
466
467 /* Return the section that should be marked against GC for a given
468 relocation. */
469
470 static asection *
471 openrisc_elf_gc_mark_hook (abfd, info, rel, h, sym)
472 bfd *abfd;
473 struct bfd_link_info *info ATTRIBUTE_UNUSED;
474 Elf_Internal_Rela *rel;
475 struct elf_link_hash_entry *h;
476 Elf_Internal_Sym *sym;
477 {
478 if (h != NULL)
479 {
480 switch (ELF32_R_TYPE (rel->r_info))
481 {
482 case R_OPENRISC_GNU_VTINHERIT:
483 case R_OPENRISC_GNU_VTENTRY:
484 break;
485
486 default:
487 switch (h->root.type)
488 {
489 case bfd_link_hash_defined:
490 case bfd_link_hash_defweak:
491 return h->root.u.def.section;
492
493 case bfd_link_hash_common:
494 return h->root.u.c.p->section;
495
496 default:
497 break;
498 }
499 }
500 }
501 else
502 {
503 return bfd_section_from_elf_index (abfd, sym->st_shndx);
504 }
505
506 return NULL;
507 }
508
509 /* Update the got entry reference counts for the section being removed. */
510
511 static boolean
512 openrisc_elf_gc_sweep_hook (abfd, info, sec, relocs)
513 bfd *abfd ATTRIBUTE_UNUSED;
514 struct bfd_link_info *info ATTRIBUTE_UNUSED;
515 asection *sec ATTRIBUTE_UNUSED;
516 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
517 {
518 return true;
519 }
520
521 /* Look through the relocs for a section during the first phase.
522 Since we don't do .gots or .plts, we just need to consider the
523 virtual table relocs for gc. */
524
525 static boolean
526 openrisc_elf_check_relocs (abfd, info, sec, relocs)
527 bfd *abfd;
528 struct bfd_link_info *info;
529 asection *sec;
530 const Elf_Internal_Rela *relocs;
531 {
532 Elf_Internal_Shdr *symtab_hdr;
533 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
534 const Elf_Internal_Rela *rel;
535 const Elf_Internal_Rela *rel_end;
536
537 if (info->relocateable)
538 return true;
539
540 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
541 sym_hashes = elf_sym_hashes (abfd);
542 sym_hashes_end =
543 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
544 if (!elf_bad_symtab (abfd))
545 sym_hashes_end -= symtab_hdr->sh_info;
546
547 rel_end = relocs + sec->reloc_count;
548 for (rel = relocs; rel < rel_end; rel++)
549 {
550 struct elf_link_hash_entry *h;
551 unsigned long r_symndx;
552
553 r_symndx = ELF32_R_SYM (rel->r_info);
554 if (r_symndx < symtab_hdr->sh_info)
555 h = NULL;
556 else
557 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
558
559 switch (ELF32_R_TYPE (rel->r_info))
560 {
561 /* This relocation describes the C++ object vtable hierarchy.
562 Reconstruct it for later use during GC. */
563 case R_OPENRISC_GNU_VTINHERIT:
564 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
565 return false;
566 break;
567
568 /* This relocation describes which C++ vtable entries are actually
569 used. Record for later use during GC. */
570 case R_OPENRISC_GNU_VTENTRY:
571 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
572 return false;
573 break;
574 }
575 }
576
577 return true;
578 }
579
580 /* Set the right machine number. */
581
582 static boolean
583 openrisc_elf_object_p (abfd)
584 bfd *abfd;
585 {
586 switch (elf_elfheader (abfd)->e_flags & 0xf)
587 {
588 default:
589 (void) bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
590 break;
591 }
592 return true;
593 }
594
595 /* Store the machine number in the flags field. */
596
597 static void
598 openrisc_elf_final_write_processing (abfd, linker)
599 bfd *abfd;
600 boolean linker ATTRIBUTE_UNUSED;
601 {
602 unsigned long val;
603
604 switch (bfd_get_mach (abfd))
605 {
606 default:
607 val = 0;
608 break;
609 }
610
611 elf_elfheader (abfd)->e_flags &= ~0xf;
612 elf_elfheader (abfd)->e_flags |= val;
613 }
614
615
616 #define ELF_ARCH bfd_arch_openrisc
617 #define ELF_MACHINE_CODE EM_OPENRISC
618 #define ELF_MACHINE_ALT1 EM_OPENRISC_OLD
619 #define ELF_MAXPAGESIZE 0x1000
620
621 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
622 #define TARGET_BIG_NAME "elf32-openrisc"
623
624 #define elf_info_to_howto_rel NULL
625 #define elf_info_to_howto openrisc_info_to_howto_rela
626 #define elf_backend_relocate_section openrisc_elf_relocate_section
627 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
628 #define elf_backend_gc_sweep_hook openrisc_elf_gc_sweep_hook
629 #define elf_backend_check_relocs openrisc_elf_check_relocs
630
631 #define elf_backend_can_gc_sections 1
632 #define elf_backend_rela_normal 1
633
634 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
635
636 #define elf_backend_object_p openrisc_elf_object_p
637 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
638
639 #include "elf32-target.h"
This page took 0.045241 seconds and 4 git commands to generate.