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