1 /* OpenRISC-specific support for 32-bit ELF.
2    Copyright 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
20    USA.  */
21 
22 #include "bfd.h"
23 #include "sysdep.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 /* Set the howto pointer for an OpenRISC ELF reloc.  */
217 
218 static void
219 openrisc_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
220 			     arelent * cache_ptr,
221 			     Elf_Internal_Rela * dst)
222 {
223   unsigned int r_type;
224 
225   r_type = ELF32_R_TYPE (dst->r_info);
226   BFD_ASSERT (r_type < (unsigned int) R_OPENRISC_max);
227   cache_ptr->howto = & openrisc_elf_howto_table[r_type];
228 }
229 
230 /* Perform a single relocation.  By default we use the standard BFD
231    routines, but a few relocs, we have to do them ourselves.  */
232 
233 static bfd_reloc_status_type
234 openrisc_final_link_relocate (reloc_howto_type *howto,
235 			      bfd *input_bfd,
236 			      asection *input_section,
237 			      bfd_byte *contents,
238 			      Elf_Internal_Rela *rel,
239 			      bfd_vma relocation)
240 {
241   bfd_reloc_status_type r = bfd_reloc_ok;
242 
243   switch (howto->type)
244     {
245     case R_OPENRISC_LO_16_IN_INSN:
246       relocation &= 0xffff;
247       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
248 				    contents, rel->r_offset,
249 				    relocation, rel->r_addend);
250       break;
251 
252     default:
253       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
254 				    contents, rel->r_offset,
255 				    relocation, rel->r_addend);
256     }
257 
258   return r;
259 }
260 
261 /* Relocate an OpenRISC ELF section.
262 
263    The RELOCATE_SECTION function is called by the new ELF backend linker
264    to handle the relocations for a section.
265 
266    The relocs are always passed as Rela structures; if the section
267    actually uses Rel structures, the r_addend field will always be
268    zero.
269 
270    This function is responsible for adjusting the section contents as
271    necessary, and (if using Rela relocs and generating a relocatable
272    output file) adjusting the reloc addend as necessary.
273 
274    This function does not have to worry about setting the reloc
275    address or the reloc symbol index.
276 
277    LOCAL_SYMS is a pointer to the swapped in local symbols.
278 
279    LOCAL_SECTIONS is an array giving the section in the input file
280    corresponding to the st_shndx field of each local symbol.
281 
282    The global hash table entry for the global symbols can be found
283    via elf_sym_hashes (input_bfd).
284 
285    When generating relocatable output, this function must handle
286    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
287    going to be the section symbol corresponding to the output
288    section, which means that the addend must be adjusted
289    accordingly.  */
290 
291 static bfd_boolean
292 openrisc_elf_relocate_section (bfd *output_bfd,
293 			       struct bfd_link_info *info,
294 			       bfd *input_bfd,
295 			       asection *input_section,
296 			       bfd_byte *contents,
297 			       Elf_Internal_Rela *relocs,
298 			       Elf_Internal_Sym *local_syms,
299 			       asection **local_sections)
300 {
301   Elf_Internal_Shdr *symtab_hdr;
302   struct elf_link_hash_entry **sym_hashes;
303   Elf_Internal_Rela *rel;
304   Elf_Internal_Rela *relend;
305 
306   if (info->relocatable)
307     return TRUE;
308 
309   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
310   sym_hashes = elf_sym_hashes (input_bfd);
311   relend = relocs + input_section->reloc_count;
312 
313   for (rel = relocs; rel < relend; rel++)
314     {
315       reloc_howto_type *howto;
316       unsigned long r_symndx;
317       Elf_Internal_Sym *sym;
318       asection *sec;
319       struct elf_link_hash_entry *h;
320       bfd_vma relocation;
321       bfd_reloc_status_type r;
322       const char *name = NULL;
323       int r_type;
324 
325       r_type = ELF32_R_TYPE (rel->r_info);
326       r_symndx = ELF32_R_SYM (rel->r_info);
327 
328       if (r_type == R_OPENRISC_GNU_VTINHERIT
329 	  || r_type == R_OPENRISC_GNU_VTENTRY)
330 	continue;
331 
332       if ((unsigned int) r_type >
333 	  (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
334 	abort ();
335 
336       /* This is a final link.  */
337       howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
338       h = NULL;
339       sym = NULL;
340       sec = NULL;
341 
342       if (r_symndx < symtab_hdr->sh_info)
343 	{
344 	  sym = local_syms + r_symndx;
345 	  sec = local_sections[r_symndx];
346 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
347 
348 	  name = bfd_elf_string_from_elf_section
349 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
350 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
351 	}
352       else
353 	{
354 	  bfd_boolean unresolved_reloc, warned;
355 
356 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
357 				   r_symndx, symtab_hdr, sym_hashes,
358 				   h, sec, relocation,
359 				   unresolved_reloc, warned);
360 	}
361 
362       r = openrisc_final_link_relocate (howto, input_bfd, input_section,
363 					contents, rel, relocation);
364 
365       if (r != bfd_reloc_ok)
366 	{
367 	  const char *msg = NULL;
368 
369 	  switch (r)
370 	    {
371 	    case bfd_reloc_overflow:
372 	      r = info->callbacks->reloc_overflow
373 		(info, (h ? &h->root : NULL), name, howto->name,
374 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
375 	      break;
376 
377 	    case bfd_reloc_undefined:
378 	      r = info->callbacks->undefined_symbol
379 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
380 	      break;
381 
382 	    case bfd_reloc_outofrange:
383 	      msg = _("internal error: out of range error");
384 	      break;
385 
386 	    case bfd_reloc_notsupported:
387 	      msg = _("internal error: unsupported relocation error");
388 	      break;
389 
390 	    case bfd_reloc_dangerous:
391 	      msg = _("internal error: dangerous relocation");
392 	      break;
393 
394 	    default:
395 	      msg = _("internal error: unknown error");
396 	      break;
397 	    }
398 
399 	  if (msg)
400 	    r = info->callbacks->warning
401 	      (info, msg, name, input_bfd, input_section, rel->r_offset);
402 
403 	  if (!r)
404 	    return FALSE;
405 	}
406     }
407 
408   return TRUE;
409 }
410 
411 /* Return the section that should be marked against GC for a given
412    relocation.  */
413 
414 static asection *
415 openrisc_elf_gc_mark_hook (asection *sec,
416 			   struct bfd_link_info *info ATTRIBUTE_UNUSED,
417 			   Elf_Internal_Rela *rel,
418 			   struct elf_link_hash_entry *h,
419 			   Elf_Internal_Sym *sym)
420 {
421   if (h == NULL)
422     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
423 
424   switch (ELF32_R_TYPE (rel->r_info))
425     {
426     case R_OPENRISC_GNU_VTINHERIT:
427     case R_OPENRISC_GNU_VTENTRY:
428       break;
429 
430     default:
431       switch (h->root.type)
432 	{
433 	case bfd_link_hash_defined:
434 	case bfd_link_hash_defweak:
435 	  return h->root.u.def.section;
436 
437 	case bfd_link_hash_common:
438 	  return h->root.u.c.p->section;
439 
440 	default:
441 	  break;
442 	}
443     }
444 
445   return NULL;
446 }
447 
448 /* Update the got entry reference counts for the section being removed.  */
449 
450 static bfd_boolean
451 openrisc_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
452 			    struct bfd_link_info *info ATTRIBUTE_UNUSED,
453 			    asection *sec ATTRIBUTE_UNUSED,
454 			    const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
455 {
456   return TRUE;
457 }
458 
459 /* Look through the relocs for a section during the first phase.
460    Since we don't do .gots or .plts, we just need to consider the
461    virtual table relocs for gc.  */
462 
463 static bfd_boolean
464 openrisc_elf_check_relocs (bfd *abfd,
465 			   struct bfd_link_info *info,
466 			   asection *sec,
467 			   const Elf_Internal_Rela *relocs)
468 {
469   Elf_Internal_Shdr *symtab_hdr;
470   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
471   const Elf_Internal_Rela *rel;
472   const Elf_Internal_Rela *rel_end;
473 
474   if (info->relocatable)
475     return TRUE;
476 
477   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
478   sym_hashes = elf_sym_hashes (abfd);
479   sym_hashes_end =
480     sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
481   if (!elf_bad_symtab (abfd))
482     sym_hashes_end -= symtab_hdr->sh_info;
483 
484   rel_end = relocs + sec->reloc_count;
485   for (rel = relocs; rel < rel_end; rel++)
486     {
487       struct elf_link_hash_entry *h;
488       unsigned long r_symndx;
489 
490       r_symndx = ELF32_R_SYM (rel->r_info);
491       if (r_symndx < symtab_hdr->sh_info)
492 	h = NULL;
493       else
494 	{
495 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
496 	  while (h->root.type == bfd_link_hash_indirect
497 		 || h->root.type == bfd_link_hash_warning)
498 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
499 	}
500 
501       switch (ELF32_R_TYPE (rel->r_info))
502 	{
503 	  /* This relocation describes the C++ object vtable hierarchy.
504 	     Reconstruct it for later use during GC.  */
505 	case R_OPENRISC_GNU_VTINHERIT:
506 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
507 	    return FALSE;
508 	  break;
509 
510 	  /* This relocation describes which C++ vtable entries are actually
511 	     used.  Record for later use during GC.  */
512 	case R_OPENRISC_GNU_VTENTRY:
513 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
514 	    return FALSE;
515 	  break;
516 	}
517     }
518 
519   return TRUE;
520 }
521 
522 /* Set the right machine number.  */
523 
524 static bfd_boolean
525 openrisc_elf_object_p (bfd *abfd)
526 {
527   bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
528   return TRUE;
529 }
530 
531 /* Store the machine number in the flags field.  */
532 
533 static void
534 openrisc_elf_final_write_processing (bfd *abfd,
535 				     bfd_boolean linker ATTRIBUTE_UNUSED)
536 {
537   unsigned long val;
538 
539   switch (bfd_get_mach (abfd))
540     {
541     default:
542       val = 0;
543       break;
544     }
545 
546   elf_elfheader (abfd)->e_flags &= ~0xf;
547   elf_elfheader (abfd)->e_flags |= val;
548 }
549 
550 
551 #define ELF_ARCH			bfd_arch_openrisc
552 #define ELF_MACHINE_CODE		EM_OPENRISC
553 #define ELF_MACHINE_ALT1		EM_OPENRISC_OLD
554 #define ELF_MAXPAGESIZE			0x1000
555 
556 #define TARGET_BIG_SYM			bfd_elf32_openrisc_vec
557 #define TARGET_BIG_NAME			"elf32-openrisc"
558 
559 #define elf_info_to_howto_rel		NULL
560 #define elf_info_to_howto		openrisc_info_to_howto_rela
561 #define elf_backend_relocate_section	openrisc_elf_relocate_section
562 #define elf_backend_gc_mark_hook	openrisc_elf_gc_mark_hook
563 #define elf_backend_gc_sweep_hook	openrisc_elf_gc_sweep_hook
564 #define elf_backend_check_relocs	openrisc_elf_check_relocs
565 
566 #define elf_backend_can_gc_sections	1
567 #define elf_backend_rela_normal		1
568 
569 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
570 
571 #define elf_backend_object_p                openrisc_elf_object_p
572 #define elf_backend_final_write_processing  openrisc_elf_final_write_processing
573 
574 #include "elf32-target.h"
575