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