* elf-bfd.h (struct elf_size_info): Add swap_symbol_in field.
[platform/upstream/binutils.git] / bfd / elf32-openrisc.c
1 /* OpenRISC-specific support for 32-bit ELF.
2    Copyright 2001, 2002 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., 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
30 static reloc_howto_type *openrisc_reloc_type_lookup
31   PARAMS ((bfd * , bfd_reloc_code_real_type));
32 static void openrisc_info_to_howto_rela
33   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
34 static boolean openrisc_elf_relocate_section
35   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
36            Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
37 static bfd_reloc_status_type openrisc_final_link_relocate
38   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
39            Elf_Internal_Rela *, bfd_vma));
40 static boolean openrisc_elf_gc_sweep_hook
41   PARAMS ((bfd *, struct bfd_link_info *, asection *,
42            const Elf_Internal_Rela *));
43 static asection * openrisc_elf_gc_mark_hook
44   PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
45            struct elf_link_hash_entry *, Elf_Internal_Sym *));
46 static boolean openrisc_elf_check_relocs
47   PARAMS ((bfd *, struct bfd_link_info *, asection *,
48            const Elf_Internal_Rela *));
49 static boolean openrisc_elf_object_p
50   PARAMS ((bfd *));
51 static void openrisc_elf_final_write_processing
52   PARAMS ((bfd *, boolean));
53
54
55 static 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
208 struct openrisc_reloc_map
209   {
210     bfd_reloc_code_real_type bfd_reloc_val;
211     unsigned int openrisc_reloc_val;
212   };
213
214 static 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
228 static reloc_howto_type *
229 openrisc_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
245 static void
246 openrisc_info_to_howto_rela (abfd, cache_ptr, dst)
247      bfd * abfd ATTRIBUTE_UNUSED;
248      arelent * cache_ptr;
249      Elf32_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
261 static bfd_reloc_status_type
262 openrisc_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    There is some attempt to make this function usable for many architectures,
293    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
294    if only to serve as a learning tool.
295
296    The RELOCATE_SECTION function is called by the new ELF backend linker
297    to handle the relocations for a section.
298
299    The relocs are always passed as Rela structures; if the section
300    actually uses Rel structures, the r_addend field will always be
301    zero.
302
303    This function is responsible for adjusting the section contents as
304    necessary, and (if using Rela relocs and generating a relocateable
305    output file) adjusting the reloc addend as necessary.
306
307    This function does not have to worry about setting the reloc
308    address or the reloc symbol index.
309
310    LOCAL_SYMS is a pointer to the swapped in local symbols.
311
312    LOCAL_SECTIONS is an array giving the section in the input file
313    corresponding to the st_shndx field of each local symbol.
314
315    The global hash table entry for the global symbols can be found
316    via elf_sym_hashes (input_bfd).
317
318    When generating relocateable output, this function must handle
319    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
320    going to be the section symbol corresponding to the output
321    section, which means that the addend must be adjusted
322    accordingly.  */
323
324 static boolean
325 openrisc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
326                                contents, relocs, local_syms, local_sections)
327      bfd *output_bfd;
328      struct bfd_link_info *info;
329      bfd *input_bfd;
330      asection *input_section;
331      bfd_byte *contents;
332      Elf_Internal_Rela *relocs;
333      Elf_Internal_Sym *local_syms;
334      asection **local_sections;
335 {
336   Elf_Internal_Shdr *symtab_hdr;
337   struct elf_link_hash_entry **sym_hashes;
338   Elf_Internal_Rela *rel;
339   Elf_Internal_Rela *relend;
340
341   if (info->relocateable)
342     return true;
343
344   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
345   sym_hashes = elf_sym_hashes (input_bfd);
346   relend = relocs + input_section->reloc_count;
347
348   for (rel = relocs; rel < relend; rel++)
349     {
350       reloc_howto_type *howto;
351       unsigned long r_symndx;
352       Elf_Internal_Sym *sym;
353       asection *sec;
354       struct elf_link_hash_entry *h;
355       bfd_vma relocation;
356       bfd_reloc_status_type r;
357       const char *name = NULL;
358       int r_type;
359
360       r_type = ELF32_R_TYPE (rel->r_info);
361       r_symndx = ELF32_R_SYM (rel->r_info);
362
363       if (r_type == R_OPENRISC_GNU_VTINHERIT
364           || r_type == R_OPENRISC_GNU_VTENTRY)
365         continue;
366
367       if ((unsigned int) r_type >
368           (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
369         abort ();
370
371       /* This is a final link.  */
372       howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
373       h = NULL;
374       sym = NULL;
375       sec = NULL;
376
377       if (r_symndx < symtab_hdr->sh_info)
378         {
379           sym = local_syms + r_symndx;
380           sec = local_sections[r_symndx];
381           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
382
383           name = bfd_elf_string_from_elf_section
384             (input_bfd, symtab_hdr->sh_link, sym->st_name);
385           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
386         }
387       else
388         {
389           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
390
391           while (h->root.type == bfd_link_hash_indirect
392                  || h->root.type == bfd_link_hash_warning)
393             h = (struct elf_link_hash_entry *) h->root.u.i.link;
394
395           name = h->root.root.string;
396
397           if (h->root.type == bfd_link_hash_defined
398               || h->root.type == bfd_link_hash_defweak)
399             {
400               sec = h->root.u.def.section;
401               relocation = (h->root.u.def.value
402                             + sec->output_section->vma + sec->output_offset);
403             }
404           else if (h->root.type == bfd_link_hash_undefweak)
405             {
406               relocation = 0;
407             }
408           else
409             {
410               if (!((*info->callbacks->undefined_symbol)
411                     (info, h->root.root.string, input_bfd,
412                      input_section, rel->r_offset, true)))
413                 return false;
414               relocation = 0;
415             }
416         }
417
418       r = openrisc_final_link_relocate (howto, input_bfd, input_section,
419                                         contents, rel, relocation);
420
421       if (r != bfd_reloc_ok)
422         {
423           const char *msg = (const char *) NULL;
424
425           switch (r)
426             {
427             case bfd_reloc_overflow:
428               r = info->callbacks->reloc_overflow
429                 (info, name, howto->name, (bfd_vma) 0,
430                  input_bfd, input_section, rel->r_offset);
431               break;
432
433             case bfd_reloc_undefined:
434               r = info->callbacks->undefined_symbol
435                 (info, name, input_bfd, input_section, rel->r_offset, true);
436               break;
437
438             case bfd_reloc_outofrange:
439               msg = _("internal error: out of range error");
440               break;
441
442             case bfd_reloc_notsupported:
443               msg = _("internal error: unsupported relocation error");
444               break;
445
446             case bfd_reloc_dangerous:
447               msg = _("internal error: dangerous relocation");
448               break;
449
450             default:
451               msg = _("internal error: unknown error");
452               break;
453             }
454
455           if (msg)
456             r = info->callbacks->warning
457               (info, msg, name, input_bfd, input_section, rel->r_offset);
458
459           if (!r)
460             return false;
461         }
462     }
463
464   return true;
465 }
466
467 /* Return the section that should be marked against GC for a given
468    relocation.  */
469
470 static asection *
471 openrisc_elf_gc_mark_hook (abfd, info, rel, h, sym)
472      bfd *abfd;
473      struct bfd_link_info *info ATTRIBUTE_UNUSED;
474      Elf_Internal_Rela *rel;
475      struct elf_link_hash_entry *h;
476      Elf_Internal_Sym *sym;
477 {
478   if (h != NULL)
479     {
480       switch (ELF32_R_TYPE (rel->r_info))
481         {
482         case R_OPENRISC_GNU_VTINHERIT:
483         case R_OPENRISC_GNU_VTENTRY:
484           break;
485
486         default:
487           switch (h->root.type)
488             {
489             case bfd_link_hash_defined:
490             case bfd_link_hash_defweak:
491               return h->root.u.def.section;
492
493             case bfd_link_hash_common:
494               return h->root.u.c.p->section;
495
496             default:
497               break;
498             }
499         }
500     }
501   else
502     {
503       return bfd_section_from_elf_index (abfd, sym->st_shndx);
504     }
505
506   return NULL;
507 }
508
509 /* Update the got entry reference counts for the section being removed.  */
510
511 static boolean
512 openrisc_elf_gc_sweep_hook (abfd, info, sec, relocs)
513      bfd *abfd ATTRIBUTE_UNUSED;
514      struct bfd_link_info *info ATTRIBUTE_UNUSED;
515      asection *sec ATTRIBUTE_UNUSED;
516      const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
517 {
518   return true;
519 }
520
521 /* Look through the relocs for a section during the first phase.
522    Since we don't do .gots or .plts, we just need to consider the
523    virtual table relocs for gc.  */
524
525 static boolean
526 openrisc_elf_check_relocs (abfd, info, sec, relocs)
527      bfd *abfd;
528      struct bfd_link_info *info;
529      asection *sec;
530      const Elf_Internal_Rela *relocs;
531 {
532   Elf_Internal_Shdr *symtab_hdr;
533   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
534   const Elf_Internal_Rela *rel;
535   const Elf_Internal_Rela *rel_end;
536
537   if (info->relocateable)
538     return true;
539
540   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
541   sym_hashes = elf_sym_hashes (abfd);
542   sym_hashes_end =
543     sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
544   if (!elf_bad_symtab (abfd))
545     sym_hashes_end -= symtab_hdr->sh_info;
546
547   rel_end = relocs + sec->reloc_count;
548   for (rel = relocs; rel < rel_end; rel++)
549     {
550       struct elf_link_hash_entry *h;
551       unsigned long r_symndx;
552
553       r_symndx = ELF32_R_SYM (rel->r_info);
554       if (r_symndx < symtab_hdr->sh_info)
555         h = NULL;
556       else
557         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
558
559       switch (ELF32_R_TYPE (rel->r_info))
560         {
561           /* This relocation describes the C++ object vtable hierarchy.
562              Reconstruct it for later use during GC.  */
563         case R_OPENRISC_GNU_VTINHERIT:
564           if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
565             return false;
566           break;
567
568           /* This relocation describes which C++ vtable entries are actually
569              used.  Record for later use during GC.  */
570         case R_OPENRISC_GNU_VTENTRY:
571           if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
572             return false;
573           break;
574         }
575     }
576
577   return true;
578 }
579
580 /* Set the right machine number.  */
581
582 static boolean
583 openrisc_elf_object_p (abfd)
584      bfd *abfd;
585 {
586   switch (elf_elfheader (abfd)->e_flags & 0xf)
587     {
588     default:
589       (void) bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
590       break;
591     }
592   return true;
593 }
594
595 /* Store the machine number in the flags field.  */
596
597 static void
598 openrisc_elf_final_write_processing (abfd, linker)
599      bfd *abfd;
600      boolean linker ATTRIBUTE_UNUSED;
601 {
602   unsigned long val;
603
604   switch (bfd_get_mach (abfd))
605     {
606     default:
607       val = 0;
608       break;
609     }
610
611   elf_elfheader (abfd)->e_flags &= ~0xf;
612   elf_elfheader (abfd)->e_flags |= val;
613 }
614
615
616 #define ELF_ARCH                        bfd_arch_openrisc
617 #define ELF_MACHINE_CODE                EM_OPENRISC
618 #define ELF_MACHINE_ALT1                EM_OPENRISC_OLD
619 #define ELF_MAXPAGESIZE                 0x1000
620
621 #define TARGET_BIG_SYM                  bfd_elf32_openrisc_vec
622 #define TARGET_BIG_NAME                 "elf32-openrisc"
623
624 #define elf_info_to_howto_rel           NULL
625 #define elf_info_to_howto               openrisc_info_to_howto_rela
626 #define elf_backend_relocate_section    openrisc_elf_relocate_section
627 #define elf_backend_gc_mark_hook        openrisc_elf_gc_mark_hook
628 #define elf_backend_gc_sweep_hook       openrisc_elf_gc_sweep_hook
629 #define elf_backend_check_relocs        openrisc_elf_check_relocs
630
631 #define elf_backend_can_gc_sections     1
632 #define elf_backend_rela_normal         1
633
634 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
635
636 #define elf_backend_object_p                openrisc_elf_object_p
637 #define elf_backend_final_write_processing  openrisc_elf_final_write_processing
638
639 #include "elf32-target.h"