OSDN Git Service

daily update
[pf3gnuchains/pf3gnuchains4x.git] / bfd / elf32-moxie.c
1 /* moxie-specific support for 32-bit ELF.
2    Copyright 2009, 2010 Free Software Foundation, Inc.
3
4    Copied from elf32-fr30.c which is..
5    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
6    Free Software Foundation, Inc.
7
8    This file is part of BFD, the Binary File Descriptor library.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23    MA 02110-1301, USA.  */
24
25 #include "sysdep.h"
26 #include "bfd.h"
27 #include "libbfd.h"
28 #include "elf-bfd.h"
29 #include "elf/moxie.h"
30
31 /* Forward declarations.  */
32
33 static reloc_howto_type moxie_elf_howto_table [] =
34 {
35   /* This reloc does nothing.  */
36   HOWTO (R_MOXIE_NONE,          /* type */
37          0,                     /* rightshift */
38          2,                     /* size (0 = byte, 1 = short, 2 = long) */
39          32,                    /* bitsize */
40          FALSE,                 /* pc_relative */
41          0,                     /* bitpos */
42          complain_overflow_bitfield, /* complain_on_overflow */
43          bfd_elf_generic_reloc, /* special_function */
44          "R_MOXIE_NONE",                /* name */
45          FALSE,                 /* partial_inplace */
46          0,                     /* src_mask */
47          0,                     /* dst_mask */
48          FALSE),                /* pcrel_offset */
49
50   /* A 32 bit absolute relocation.  */
51   HOWTO (R_MOXIE_32,            /* type */
52          0,                     /* rightshift */
53          2,                     /* size (0 = byte, 1 = short, 2 = long) */
54          32,                    /* bitsize */
55          FALSE,                 /* pc_relative */
56          0,                     /* bitpos */
57          complain_overflow_bitfield, /* complain_on_overflow */
58          bfd_elf_generic_reloc, /* special_function */
59          "R_MOXIE_32",          /* name */
60          FALSE,                 /* partial_inplace */
61          0x00000000,            /* src_mask */
62          0xffffffff,            /* dst_mask */
63          FALSE),                /* pcrel_offset */
64
65   /* A 10 bit PC-relative relocation.  */
66   HOWTO (R_MOXIE_PCREL10,       /* type.  */
67          1,                     /* rightshift.  */
68          1,                     /* size (0 = byte, 1 = short, 2 = long).  */
69          10,                    /* bitsize.  */
70          TRUE,                  /* pc_relative.  */
71          0,                     /* bitpos.  */
72          complain_overflow_signed, /* complain_on_overflow.  */
73          bfd_elf_generic_reloc, /* special_function.  */
74          "R_MOXIE_PCREL10",             /* name.  */
75          FALSE,                 /* partial_inplace.  */
76          0,                     /* src_mask.  */
77          0x000003FF,            /* dst_mask.  */
78          TRUE),                 /* pcrel_offset.  */
79 };
80 \f
81 /* Map BFD reloc types to MOXIE ELF reloc types.  */
82
83 struct moxie_reloc_map
84 {
85   bfd_reloc_code_real_type bfd_reloc_val;
86   unsigned int moxie_reloc_val;
87 };
88
89 static const struct moxie_reloc_map moxie_reloc_map [] =
90 {
91   { BFD_RELOC_NONE,            R_MOXIE_NONE },
92   { BFD_RELOC_32,              R_MOXIE_32 },
93   { BFD_RELOC_MOXIE_10_PCREL,  R_MOXIE_PCREL10 },
94 };
95
96 static reloc_howto_type *
97 moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
98                          bfd_reloc_code_real_type code)
99 {
100   unsigned int i;
101
102   for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
103        --i;)
104     if (moxie_reloc_map [i].bfd_reloc_val == code)
105       return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
106
107   return NULL;
108 }
109
110 static reloc_howto_type *
111 moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
112 {
113   unsigned int i;
114
115   for (i = 0;
116        i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]);
117        i++)
118     if (moxie_elf_howto_table[i].name != NULL
119         && strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0)
120       return &moxie_elf_howto_table[i];
121
122   return NULL;
123 }
124
125 /* Set the howto pointer for an MOXIE ELF reloc.  */
126
127 static void
128 moxie_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
129                           arelent *cache_ptr,
130                           Elf_Internal_Rela *dst)
131 {
132   unsigned int r_type;
133
134   r_type = ELF32_R_TYPE (dst->r_info);
135   BFD_ASSERT (r_type < (unsigned int) R_MOXIE_max);
136   cache_ptr->howto = & moxie_elf_howto_table [r_type];
137 }
138 \f
139 /* Perform a single relocation.  By default we use the standard BFD
140    routines, but a few relocs, we have to do them ourselves.  */
141
142 static bfd_reloc_status_type
143 moxie_final_link_relocate (reloc_howto_type *howto,
144                            bfd *input_bfd,
145                            asection *input_section,
146                            bfd_byte *contents,
147                            Elf_Internal_Rela *rel,
148                            bfd_vma relocation)
149 {
150   bfd_reloc_status_type r = bfd_reloc_ok;
151
152   switch (howto->type)
153     {
154     default:
155       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
156                                     contents, rel->r_offset,
157                                     relocation, rel->r_addend);
158     }
159
160   return r;
161 }
162 \f
163 /* Relocate an MOXIE ELF section.
164
165    The RELOCATE_SECTION function is called by the new ELF backend linker
166    to handle the relocations for a section.
167
168    The relocs are always passed as Rela structures; if the section
169    actually uses Rel structures, the r_addend field will always be
170    zero.
171
172    This function is responsible for adjusting the section contents as
173    necessary, and (if using Rela relocs and generating a relocatable
174    output file) adjusting the reloc addend as necessary.
175
176    This function does not have to worry about setting the reloc
177    address or the reloc symbol index.
178
179    LOCAL_SYMS is a pointer to the swapped in local symbols.
180
181    LOCAL_SECTIONS is an array giving the section in the input file
182    corresponding to the st_shndx field of each local symbol.
183
184    The global hash table entry for the global symbols can be found
185    via elf_sym_hashes (input_bfd).
186
187    When generating relocatable output, this function must handle
188    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
189    going to be the section symbol corresponding to the output
190    section, which means that the addend must be adjusted
191    accordingly.  */
192
193 static bfd_boolean
194 moxie_elf_relocate_section (bfd *output_bfd,
195                             struct bfd_link_info *info,
196                             bfd *input_bfd,
197                             asection *input_section,
198                             bfd_byte *contents,
199                             Elf_Internal_Rela *relocs,
200                             Elf_Internal_Sym *local_syms,
201                             asection **local_sections)
202 {
203   Elf_Internal_Shdr *symtab_hdr;
204   struct elf_link_hash_entry **sym_hashes;
205   Elf_Internal_Rela *rel;
206   Elf_Internal_Rela *relend;
207
208   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
209   sym_hashes = elf_sym_hashes (input_bfd);
210   relend     = relocs + input_section->reloc_count;
211
212   for (rel = relocs; rel < relend; rel ++)
213     {
214       reloc_howto_type *howto;
215       unsigned long r_symndx;
216       Elf_Internal_Sym *sym;
217       asection *sec;
218       struct elf_link_hash_entry *h;
219       bfd_vma relocation;
220       bfd_reloc_status_type r;
221       const char *name;
222       int r_type;
223
224       r_type = ELF32_R_TYPE (rel->r_info);
225       r_symndx = ELF32_R_SYM (rel->r_info);
226       howto  = moxie_elf_howto_table + r_type;
227       h      = NULL;
228       sym    = NULL;
229       sec    = NULL;
230
231       if (r_symndx < symtab_hdr->sh_info)
232         {
233           sym = local_syms + r_symndx;
234           sec = local_sections [r_symndx];
235           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
236
237           name = bfd_elf_string_from_elf_section
238             (input_bfd, symtab_hdr->sh_link, sym->st_name);
239           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
240         }
241       else
242         {
243           bfd_boolean unresolved_reloc, warned;
244
245           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
246                                    r_symndx, symtab_hdr, sym_hashes,
247                                    h, sec, relocation,
248                                    unresolved_reloc, warned);
249
250           name = h->root.root.string;
251         }
252
253       if (sec != NULL && elf_discarded_section (sec))
254         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
255                                          rel, relend, howto, contents);
256
257       if (info->relocatable)
258         continue;
259
260       r = moxie_final_link_relocate (howto, input_bfd, input_section,
261                                      contents, rel, relocation);
262
263       if (r != bfd_reloc_ok)
264         {
265           const char * msg = NULL;
266
267           switch (r)
268             {
269             case bfd_reloc_overflow:
270               r = info->callbacks->reloc_overflow
271                 (info, (h ? &h->root : NULL), name, howto->name,
272                  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
273               break;
274
275             case bfd_reloc_undefined:
276               r = info->callbacks->undefined_symbol
277                 (info, name, input_bfd, input_section, rel->r_offset,
278                  TRUE);
279               break;
280
281             case bfd_reloc_outofrange:
282               msg = _("internal error: out of range error");
283               break;
284
285             case bfd_reloc_notsupported:
286               msg = _("internal error: unsupported relocation error");
287               break;
288
289             case bfd_reloc_dangerous:
290               msg = _("internal error: dangerous relocation");
291               break;
292
293             default:
294               msg = _("internal error: unknown error");
295               break;
296             }
297
298           if (msg)
299             r = info->callbacks->warning
300               (info, msg, name, input_bfd, input_section, rel->r_offset);
301
302           if (! r)
303             return FALSE;
304         }
305     }
306
307   return TRUE;
308 }
309 \f
310 /* Return the section that should be marked against GC for a given
311    relocation.  */
312
313 static asection *
314 moxie_elf_gc_mark_hook (asection *sec,
315                         struct bfd_link_info *info,
316                         Elf_Internal_Rela *rel,
317                         struct elf_link_hash_entry *h,
318                         Elf_Internal_Sym *sym)
319 {
320   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
321 }
322
323 /* Look through the relocs for a section during the first phase.
324    Since we don't do .gots or .plts, we just need to consider the
325    virtual table relocs for gc.  */
326
327 static bfd_boolean
328 moxie_elf_check_relocs (bfd *abfd,
329                         struct bfd_link_info *info,
330                         asection *sec,
331                         const Elf_Internal_Rela *relocs)
332 {
333   Elf_Internal_Shdr *symtab_hdr;
334   struct elf_link_hash_entry **sym_hashes;
335   const Elf_Internal_Rela *rel;
336   const Elf_Internal_Rela *rel_end;
337
338   if (info->relocatable)
339     return TRUE;
340
341   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
342   sym_hashes = elf_sym_hashes (abfd);
343
344   rel_end = relocs + sec->reloc_count;
345   for (rel = relocs; rel < rel_end; rel++)
346     {
347       struct elf_link_hash_entry *h;
348       unsigned long r_symndx;
349
350       r_symndx = ELF32_R_SYM (rel->r_info);
351       if (r_symndx < symtab_hdr->sh_info)
352         h = NULL;
353       else
354         {
355           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
356           while (h->root.type == bfd_link_hash_indirect
357                  || h->root.type == bfd_link_hash_warning)
358             h = (struct elf_link_hash_entry *) h->root.u.i.link;
359         }
360     }
361
362   return TRUE;
363 }
364 \f
365 #define ELF_ARCH                bfd_arch_moxie
366 #define ELF_MACHINE_CODE        EM_MOXIE
367 #define ELF_MAXPAGESIZE         0x1
368
369 #define TARGET_BIG_SYM          bfd_elf32_moxie_vec
370 #define TARGET_BIG_NAME         "elf32-moxie"
371
372 #define elf_info_to_howto_rel                   NULL
373 #define elf_info_to_howto                       moxie_info_to_howto_rela
374 #define elf_backend_relocate_section            moxie_elf_relocate_section
375 #define elf_backend_gc_mark_hook                moxie_elf_gc_mark_hook
376 #define elf_backend_check_relocs                moxie_elf_check_relocs
377
378 #define elf_backend_can_gc_sections             1
379 #define elf_backend_rela_normal                 1
380
381 #define bfd_elf32_bfd_reloc_type_lookup         moxie_reloc_type_lookup
382 #define bfd_elf32_bfd_reloc_name_lookup         moxie_reloc_name_lookup
383
384 #include "elf32-target.h"