OSDN Git Service

Regenerate cgen files, update copyright year.
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf32-openrisc.c
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 *
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 *
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
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
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
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         {
378           /* For relocs against symbols from removed linkonce sections,
379              or sections discarded by a linker script, we just want the
380              section contents zeroed.  Avoid any special processing.  */
381           _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
382           rel->r_info = 0;
383           rel->r_addend = 0;
384           continue;
385         }
386
387       if (info->relocatable)
388         continue;
389
390       r = openrisc_final_link_relocate (howto, input_bfd, input_section,
391                                         contents, rel, relocation);
392
393       if (r != bfd_reloc_ok)
394         {
395           const char *msg = NULL;
396
397           switch (r)
398             {
399             case bfd_reloc_overflow:
400               r = info->callbacks->reloc_overflow
401                 (info, (h ? &h->root : NULL), name, howto->name,
402                  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
403               break;
404
405             case bfd_reloc_undefined:
406               r = info->callbacks->undefined_symbol
407                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
408               break;
409
410             case bfd_reloc_outofrange:
411               msg = _("internal error: out of range error");
412               break;
413
414             case bfd_reloc_notsupported:
415               msg = _("internal error: unsupported relocation error");
416               break;
417
418             case bfd_reloc_dangerous:
419               msg = _("internal error: dangerous relocation");
420               break;
421
422             default:
423               msg = _("internal error: unknown error");
424               break;
425             }
426
427           if (msg)
428             r = info->callbacks->warning
429               (info, msg, name, input_bfd, input_section, rel->r_offset);
430
431           if (!r)
432             return FALSE;
433         }
434     }
435
436   return TRUE;
437 }
438
439 /* Return the section that should be marked against GC for a given
440    relocation.  */
441
442 static asection *
443 openrisc_elf_gc_mark_hook (asection *sec,
444                            struct bfd_link_info *info,
445                            Elf_Internal_Rela *rel,
446                            struct elf_link_hash_entry *h,
447                            Elf_Internal_Sym *sym)
448 {
449   if (h != NULL)
450     switch (ELF32_R_TYPE (rel->r_info))
451       {
452       case R_OPENRISC_GNU_VTINHERIT:
453       case R_OPENRISC_GNU_VTENTRY:
454         return NULL;
455       }
456
457   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
458 }
459
460 /* Look through the relocs for a section during the first phase.
461    Since we don't do .gots or .plts, we just need to consider the
462    virtual table relocs for gc.  */
463
464 static bfd_boolean
465 openrisc_elf_check_relocs (bfd *abfd,
466                            struct bfd_link_info *info,
467                            asection *sec,
468                            const Elf_Internal_Rela *relocs)
469 {
470   Elf_Internal_Shdr *symtab_hdr;
471   struct elf_link_hash_entry **sym_hashes;
472   const Elf_Internal_Rela *rel;
473   const Elf_Internal_Rela *rel_end;
474
475   if (info->relocatable)
476     return TRUE;
477
478   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
479   sym_hashes = elf_sym_hashes (abfd);
480
481   rel_end = relocs + sec->reloc_count;
482   for (rel = relocs; rel < rel_end; rel++)
483     {
484       struct elf_link_hash_entry *h;
485       unsigned long r_symndx;
486
487       r_symndx = ELF32_R_SYM (rel->r_info);
488       if (r_symndx < symtab_hdr->sh_info)
489         h = NULL;
490       else
491         {
492           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
493           while (h->root.type == bfd_link_hash_indirect
494                  || h->root.type == bfd_link_hash_warning)
495             h = (struct elf_link_hash_entry *) h->root.u.i.link;
496         }
497
498       switch (ELF32_R_TYPE (rel->r_info))
499         {
500           /* This relocation describes the C++ object vtable hierarchy.
501              Reconstruct it for later use during GC.  */
502         case R_OPENRISC_GNU_VTINHERIT:
503           if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
504             return FALSE;
505           break;
506
507           /* This relocation describes which C++ vtable entries are actually
508              used.  Record for later use during GC.  */
509         case R_OPENRISC_GNU_VTENTRY:
510           BFD_ASSERT (h != NULL);
511           if (h != NULL
512               && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
513             return FALSE;
514           break;
515         }
516     }
517
518   return TRUE;
519 }
520
521 /* Set the right machine number.  */
522
523 static bfd_boolean
524 openrisc_elf_object_p (bfd *abfd)
525 {
526   bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
527   return TRUE;
528 }
529
530 /* Store the machine number in the flags field.  */
531
532 static void
533 openrisc_elf_final_write_processing (bfd *abfd,
534                                      bfd_boolean linker ATTRIBUTE_UNUSED)
535 {
536   unsigned long val;
537
538   switch (bfd_get_mach (abfd))
539     {
540     default:
541       val = 0;
542       break;
543     }
544
545   elf_elfheader (abfd)->e_flags &= ~0xf;
546   elf_elfheader (abfd)->e_flags |= val;
547 }
548
549
550 #define ELF_ARCH                        bfd_arch_openrisc
551 #define ELF_MACHINE_CODE                EM_OPENRISC
552 #define ELF_MACHINE_ALT1                EM_OPENRISC_OLD
553 #define ELF_MAXPAGESIZE                 0x1000
554
555 #define TARGET_BIG_SYM                  bfd_elf32_openrisc_vec
556 #define TARGET_BIG_NAME                 "elf32-openrisc"
557
558 #define elf_info_to_howto_rel           NULL
559 #define elf_info_to_howto               openrisc_info_to_howto_rela
560 #define elf_backend_relocate_section    openrisc_elf_relocate_section
561 #define elf_backend_gc_mark_hook        openrisc_elf_gc_mark_hook
562 #define elf_backend_check_relocs        openrisc_elf_check_relocs
563
564 #define elf_backend_can_gc_sections     1
565 #define elf_backend_rela_normal         1
566
567 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
568 #define bfd_elf32_bfd_reloc_name_lookup openrisc_reloc_name_lookup
569
570 #define elf_backend_object_p                openrisc_elf_object_p
571 #define elf_backend_final_write_processing  openrisc_elf_final_write_processing
572
573 #include "elf32-target.h"