* elf-hppa.h (elf_hppa_relocate_section): If relocatable, return
[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 ((asection *, 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
293 The RELOCATE_SECTION function is called by the new ELF backend linker
294 to handle the relocations for a section.
295
296 The relocs are always passed as Rela structures; if the section
297 actually uses Rel structures, the r_addend field will always be
298 zero.
299
300 This function is responsible for adjusting the section contents as
301 necessary, and (if using Rela relocs and generating a relocateable
302 output file) adjusting the reloc addend as necessary.
303
304 This function does not have to worry about setting the reloc
305 address or the reloc symbol index.
306
307 LOCAL_SYMS is a pointer to the swapped in local symbols.
308
309 LOCAL_SECTIONS is an array giving the section in the input file
310 corresponding to the st_shndx field of each local symbol.
311
312 The global hash table entry for the global symbols can be found
313 via elf_sym_hashes (input_bfd).
314
315 When generating relocateable output, this function must handle
316 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
317 going to be the section symbol corresponding to the output
318 section, which means that the addend must be adjusted
319 accordingly. */
320
321 static boolean
322 openrisc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
323 contents, relocs, local_syms, local_sections)
324 bfd *output_bfd;
325 struct bfd_link_info *info;
326 bfd *input_bfd;
327 asection *input_section;
328 bfd_byte *contents;
329 Elf_Internal_Rela *relocs;
330 Elf_Internal_Sym *local_syms;
331 asection **local_sections;
332 {
333 Elf_Internal_Shdr *symtab_hdr;
334 struct elf_link_hash_entry **sym_hashes;
335 Elf_Internal_Rela *rel;
336 Elf_Internal_Rela *relend;
337
338 if (info->relocateable)
339 return true;
340
341 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
342 sym_hashes = elf_sym_hashes (input_bfd);
343 relend = relocs + input_section->reloc_count;
344
345 for (rel = relocs; rel < relend; rel++)
346 {
347 reloc_howto_type *howto;
348 unsigned long r_symndx;
349 Elf_Internal_Sym *sym;
350 asection *sec;
351 struct elf_link_hash_entry *h;
352 bfd_vma relocation;
353 bfd_reloc_status_type r;
354 const char *name = NULL;
355 int r_type;
356
357 r_type = ELF32_R_TYPE (rel->r_info);
358 r_symndx = ELF32_R_SYM (rel->r_info);
359
360 if (r_type == R_OPENRISC_GNU_VTINHERIT
361 || r_type == R_OPENRISC_GNU_VTENTRY)
362 continue;
363
364 if ((unsigned int) r_type >
365 (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
366 abort ();
367
368 /* This is a final link. */
369 howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
370 h = NULL;
371 sym = NULL;
372 sec = NULL;
373
374 if (r_symndx < symtab_hdr->sh_info)
375 {
376 sym = local_syms + r_symndx;
377 sec = local_sections[r_symndx];
378 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
379
380 name = bfd_elf_string_from_elf_section
381 (input_bfd, symtab_hdr->sh_link, sym->st_name);
382 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
383 }
384 else
385 {
386 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
387
388 while (h->root.type == bfd_link_hash_indirect
389 || h->root.type == bfd_link_hash_warning)
390 h = (struct elf_link_hash_entry *) h->root.u.i.link;
391
392 name = h->root.root.string;
393
394 if (h->root.type == bfd_link_hash_defined
395 || h->root.type == bfd_link_hash_defweak)
396 {
397 sec = h->root.u.def.section;
398 relocation = (h->root.u.def.value
399 + sec->output_section->vma + sec->output_offset);
400 }
401 else if (h->root.type == bfd_link_hash_undefweak)
402 {
403 relocation = 0;
404 }
405 else
406 {
407 if (!((*info->callbacks->undefined_symbol)
408 (info, h->root.root.string, input_bfd,
409 input_section, rel->r_offset, true)))
410 return false;
411 relocation = 0;
412 }
413 }
414
415 r = openrisc_final_link_relocate (howto, input_bfd, input_section,
416 contents, rel, relocation);
417
418 if (r != bfd_reloc_ok)
419 {
420 const char *msg = (const char *) NULL;
421
422 switch (r)
423 {
424 case bfd_reloc_overflow:
425 r = info->callbacks->reloc_overflow
426 (info, name, howto->name, (bfd_vma) 0,
427 input_bfd, input_section, rel->r_offset);
428 break;
429
430 case bfd_reloc_undefined:
431 r = info->callbacks->undefined_symbol
432 (info, name, input_bfd, input_section, rel->r_offset, true);
433 break;
434
435 case bfd_reloc_outofrange:
436 msg = _("internal error: out of range error");
437 break;
438
439 case bfd_reloc_notsupported:
440 msg = _("internal error: unsupported relocation error");
441 break;
442
443 case bfd_reloc_dangerous:
444 msg = _("internal error: dangerous relocation");
445 break;
446
447 default:
448 msg = _("internal error: unknown error");
449 break;
450 }
451
452 if (msg)
453 r = info->callbacks->warning
454 (info, msg, name, input_bfd, input_section, rel->r_offset);
455
456 if (!r)
457 return false;
458 }
459 }
460
461 return true;
462 }
463
464 /* Return the section that should be marked against GC for a given
465 relocation. */
466
467 static asection *
468 openrisc_elf_gc_mark_hook (sec, info, rel, h, sym)
469 asection *sec;
470 struct bfd_link_info *info ATTRIBUTE_UNUSED;
471 Elf_Internal_Rela *rel;
472 struct elf_link_hash_entry *h;
473 Elf_Internal_Sym *sym;
474 {
475 if (h != NULL)
476 {
477 switch (ELF32_R_TYPE (rel->r_info))
478 {
479 case R_OPENRISC_GNU_VTINHERIT:
480 case R_OPENRISC_GNU_VTENTRY:
481 break;
482
483 default:
484 switch (h->root.type)
485 {
486 case bfd_link_hash_defined:
487 case bfd_link_hash_defweak:
488 return h->root.u.def.section;
489
490 case bfd_link_hash_common:
491 return h->root.u.c.p->section;
492
493 default:
494 break;
495 }
496 }
497 }
498 else
499 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
500
501 return NULL;
502 }
503
504 /* Update the got entry reference counts for the section being removed. */
505
506 static boolean
507 openrisc_elf_gc_sweep_hook (abfd, info, sec, relocs)
508 bfd *abfd ATTRIBUTE_UNUSED;
509 struct bfd_link_info *info ATTRIBUTE_UNUSED;
510 asection *sec ATTRIBUTE_UNUSED;
511 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
512 {
513 return true;
514 }
515
516 /* Look through the relocs for a section during the first phase.
517 Since we don't do .gots or .plts, we just need to consider the
518 virtual table relocs for gc. */
519
520 static boolean
521 openrisc_elf_check_relocs (abfd, info, sec, relocs)
522 bfd *abfd;
523 struct bfd_link_info *info;
524 asection *sec;
525 const Elf_Internal_Rela *relocs;
526 {
527 Elf_Internal_Shdr *symtab_hdr;
528 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
529 const Elf_Internal_Rela *rel;
530 const Elf_Internal_Rela *rel_end;
531
532 if (info->relocateable)
533 return true;
534
535 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
536 sym_hashes = elf_sym_hashes (abfd);
537 sym_hashes_end =
538 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
539 if (!elf_bad_symtab (abfd))
540 sym_hashes_end -= symtab_hdr->sh_info;
541
542 rel_end = relocs + sec->reloc_count;
543 for (rel = relocs; rel < rel_end; rel++)
544 {
545 struct elf_link_hash_entry *h;
546 unsigned long r_symndx;
547
548 r_symndx = ELF32_R_SYM (rel->r_info);
549 if (r_symndx < symtab_hdr->sh_info)
550 h = NULL;
551 else
552 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
553
554 switch (ELF32_R_TYPE (rel->r_info))
555 {
556 /* This relocation describes the C++ object vtable hierarchy.
557 Reconstruct it for later use during GC. */
558 case R_OPENRISC_GNU_VTINHERIT:
559 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
560 return false;
561 break;
562
563 /* This relocation describes which C++ vtable entries are actually
564 used. Record for later use during GC. */
565 case R_OPENRISC_GNU_VTENTRY:
566 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
567 return false;
568 break;
569 }
570 }
571
572 return true;
573 }
574
575 /* Set the right machine number. */
576
577 static boolean
578 openrisc_elf_object_p (abfd)
579 bfd *abfd;
580 {
581 switch (elf_elfheader (abfd)->e_flags & 0xf)
582 {
583 default:
584 (void) bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
585 break;
586 }
587 return true;
588 }
589
590 /* Store the machine number in the flags field. */
591
592 static void
593 openrisc_elf_final_write_processing (abfd, linker)
594 bfd *abfd;
595 boolean linker ATTRIBUTE_UNUSED;
596 {
597 unsigned long val;
598
599 switch (bfd_get_mach (abfd))
600 {
601 default:
602 val = 0;
603 break;
604 }
605
606 elf_elfheader (abfd)->e_flags &= ~0xf;
607 elf_elfheader (abfd)->e_flags |= val;
608 }
609
610
611 #define ELF_ARCH bfd_arch_openrisc
612 #define ELF_MACHINE_CODE EM_OPENRISC
613 #define ELF_MACHINE_ALT1 EM_OPENRISC_OLD
614 #define ELF_MAXPAGESIZE 0x1000
615
616 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
617 #define TARGET_BIG_NAME "elf32-openrisc"
618
619 #define elf_info_to_howto_rel NULL
620 #define elf_info_to_howto openrisc_info_to_howto_rela
621 #define elf_backend_relocate_section openrisc_elf_relocate_section
622 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
623 #define elf_backend_gc_sweep_hook openrisc_elf_gc_sweep_hook
624 #define elf_backend_check_relocs openrisc_elf_check_relocs
625
626 #define elf_backend_can_gc_sections 1
627 #define elf_backend_rela_normal 1
628
629 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
630
631 #define elf_backend_object_p openrisc_elf_object_p
632 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
633
634 #include "elf32-target.h"
This page took 0.049269 seconds and 4 git commands to generate.