1/* OpenRISC-specific support for 32-bit ELF.
2   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3   Contributed by Johan Rydberg, jrydberg@opencores.org
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, 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
30static reloc_howto_type *openrisc_reloc_type_lookup
31  PARAMS ((bfd * , bfd_reloc_code_real_type));
32static void openrisc_info_to_howto_rela
33  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
34static bfd_boolean openrisc_elf_relocate_section
35  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
36	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
37static bfd_reloc_status_type openrisc_final_link_relocate
38  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
39           Elf_Internal_Rela *, bfd_vma));
40static bfd_boolean openrisc_elf_gc_sweep_hook
41  PARAMS ((bfd *, struct bfd_link_info *, asection *,
42           const Elf_Internal_Rela *));
43static 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 *));
46static bfd_boolean openrisc_elf_check_relocs
47  PARAMS ((bfd *, struct bfd_link_info *, asection *,
48	   const Elf_Internal_Rela *));
49static bfd_boolean openrisc_elf_object_p
50  PARAMS ((bfd *));
51static void openrisc_elf_final_write_processing
52  PARAMS ((bfd *, bfd_boolean));
53
54
55static 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
208struct openrisc_reloc_map
209  {
210    bfd_reloc_code_real_type bfd_reloc_val;
211    unsigned int openrisc_reloc_val;
212  };
213
214static 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
228static reloc_howto_type *
229openrisc_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
245static void
246openrisc_info_to_howto_rela (abfd, cache_ptr, dst)
247     bfd * abfd ATTRIBUTE_UNUSED;
248     arelent * cache_ptr;
249     Elf_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
261static bfd_reloc_status_type
262openrisc_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 relocatable
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 relocatable 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
321static bfd_boolean
322openrisc_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->relocatable)
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	  bfd_boolean unresolved_reloc, warned;
387
388	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
389				   r_symndx, symtab_hdr, sym_hashes,
390				   h, sec, relocation,
391				   unresolved_reloc, warned);
392	}
393
394      r = openrisc_final_link_relocate (howto, input_bfd, input_section,
395					contents, rel, relocation);
396
397      if (r != bfd_reloc_ok)
398	{
399	  const char *msg = (const char *) NULL;
400
401	  switch (r)
402	    {
403	    case bfd_reloc_overflow:
404	      r = info->callbacks->reloc_overflow
405		(info, name, howto->name, (bfd_vma) 0,
406		 input_bfd, input_section, rel->r_offset);
407	      break;
408
409	    case bfd_reloc_undefined:
410	      r = info->callbacks->undefined_symbol
411		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
412	      break;
413
414	    case bfd_reloc_outofrange:
415	      msg = _("internal error: out of range error");
416	      break;
417
418	    case bfd_reloc_notsupported:
419	      msg = _("internal error: unsupported relocation error");
420	      break;
421
422	    case bfd_reloc_dangerous:
423	      msg = _("internal error: dangerous relocation");
424	      break;
425
426	    default:
427	      msg = _("internal error: unknown error");
428	      break;
429	    }
430
431	  if (msg)
432	    r = info->callbacks->warning
433	      (info, msg, name, input_bfd, input_section, rel->r_offset);
434
435	  if (!r)
436	    return FALSE;
437	}
438    }
439
440  return TRUE;
441}
442
443/* Return the section that should be marked against GC for a given
444   relocation.  */
445
446static asection *
447openrisc_elf_gc_mark_hook (sec, info, rel, h, sym)
448     asection *sec;
449     struct bfd_link_info *info ATTRIBUTE_UNUSED;
450     Elf_Internal_Rela *rel;
451     struct elf_link_hash_entry *h;
452     Elf_Internal_Sym *sym;
453{
454  if (h != NULL)
455    {
456      switch (ELF32_R_TYPE (rel->r_info))
457	{
458	case R_OPENRISC_GNU_VTINHERIT:
459	case R_OPENRISC_GNU_VTENTRY:
460	  break;
461
462	default:
463	  switch (h->root.type)
464	    {
465	    case bfd_link_hash_defined:
466	    case bfd_link_hash_defweak:
467	      return h->root.u.def.section;
468
469	    case bfd_link_hash_common:
470	      return h->root.u.c.p->section;
471
472	    default:
473	      break;
474	    }
475	}
476    }
477  else
478    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
479
480  return NULL;
481}
482
483/* Update the got entry reference counts for the section being removed.  */
484
485static bfd_boolean
486openrisc_elf_gc_sweep_hook (abfd, info, sec, relocs)
487     bfd *abfd ATTRIBUTE_UNUSED;
488     struct bfd_link_info *info ATTRIBUTE_UNUSED;
489     asection *sec ATTRIBUTE_UNUSED;
490     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
491{
492  return TRUE;
493}
494
495/* Look through the relocs for a section during the first phase.
496   Since we don't do .gots or .plts, we just need to consider the
497   virtual table relocs for gc.  */
498
499static bfd_boolean
500openrisc_elf_check_relocs (abfd, info, sec, relocs)
501     bfd *abfd;
502     struct bfd_link_info *info;
503     asection *sec;
504     const Elf_Internal_Rela *relocs;
505{
506  Elf_Internal_Shdr *symtab_hdr;
507  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
508  const Elf_Internal_Rela *rel;
509  const Elf_Internal_Rela *rel_end;
510
511  if (info->relocatable)
512    return TRUE;
513
514  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
515  sym_hashes = elf_sym_hashes (abfd);
516  sym_hashes_end =
517    sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
518  if (!elf_bad_symtab (abfd))
519    sym_hashes_end -= symtab_hdr->sh_info;
520
521  rel_end = relocs + sec->reloc_count;
522  for (rel = relocs; rel < rel_end; rel++)
523    {
524      struct elf_link_hash_entry *h;
525      unsigned long r_symndx;
526
527      r_symndx = ELF32_R_SYM (rel->r_info);
528      if (r_symndx < symtab_hdr->sh_info)
529	h = NULL;
530      else
531	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
532
533      switch (ELF32_R_TYPE (rel->r_info))
534	{
535	  /* This relocation describes the C++ object vtable hierarchy.
536	     Reconstruct it for later use during GC.  */
537	case R_OPENRISC_GNU_VTINHERIT:
538	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
539	    return FALSE;
540	  break;
541
542	  /* This relocation describes which C++ vtable entries are actually
543	     used.  Record for later use during GC.  */
544	case R_OPENRISC_GNU_VTENTRY:
545	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
546	    return FALSE;
547	  break;
548	}
549    }
550
551  return TRUE;
552}
553
554/* Set the right machine number.  */
555
556static bfd_boolean
557openrisc_elf_object_p (abfd)
558     bfd *abfd;
559{
560  switch (elf_elfheader (abfd)->e_flags & 0xf)
561    {
562    default:
563      (void) bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
564      break;
565    }
566  return TRUE;
567}
568
569/* Store the machine number in the flags field.  */
570
571static void
572openrisc_elf_final_write_processing (abfd, linker)
573     bfd *abfd;
574     bfd_boolean linker ATTRIBUTE_UNUSED;
575{
576  unsigned long val;
577
578  switch (bfd_get_mach (abfd))
579    {
580    default:
581      val = 0;
582      break;
583    }
584
585  elf_elfheader (abfd)->e_flags &= ~0xf;
586  elf_elfheader (abfd)->e_flags |= val;
587}
588
589
590#define ELF_ARCH			bfd_arch_openrisc
591#define ELF_MACHINE_CODE		EM_OPENRISC
592#define ELF_MACHINE_ALT1		EM_OPENRISC_OLD
593#define ELF_MAXPAGESIZE			0x1000
594
595#define TARGET_BIG_SYM			bfd_elf32_openrisc_vec
596#define TARGET_BIG_NAME			"elf32-openrisc"
597
598#define elf_info_to_howto_rel		NULL
599#define elf_info_to_howto		openrisc_info_to_howto_rela
600#define elf_backend_relocate_section	openrisc_elf_relocate_section
601#define elf_backend_gc_mark_hook	openrisc_elf_gc_mark_hook
602#define elf_backend_gc_sweep_hook	openrisc_elf_gc_sweep_hook
603#define elf_backend_check_relocs	openrisc_elf_check_relocs
604
605#define elf_backend_can_gc_sections	1
606#define elf_backend_rela_normal		1
607
608#define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
609
610#define elf_backend_object_p                openrisc_elf_object_p
611#define elf_backend_final_write_processing  openrisc_elf_final_write_processing
612
613#include "elf32-target.h"
614