OSDN Git Service

daily update
[pf3gnuchains/pf3gnuchains4x.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         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 *
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
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
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
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"