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