merge from gcc
[external/binutils.git] / bfd / elf32-moxie.c
1 /* moxie-specific support for 32-bit ELF.
2    Copyright 2009 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
226       r_symndx = ELF32_R_SYM (rel->r_info);
227
228       howto  = moxie_elf_howto_table + ELF32_R_TYPE (rel->r_info);
229       h      = NULL;
230       sym    = NULL;
231       sec    = NULL;
232
233       if (r_symndx < symtab_hdr->sh_info)
234         {
235           sym = local_syms + r_symndx;
236           sec = local_sections [r_symndx];
237           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
238
239           name = bfd_elf_string_from_elf_section
240             (input_bfd, symtab_hdr->sh_link, sym->st_name);
241           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
242         }
243       else
244         {
245           bfd_boolean unresolved_reloc, warned;
246
247           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
248                                    r_symndx, symtab_hdr, sym_hashes,
249                                    h, sec, relocation,
250                                    unresolved_reloc, warned);
251
252           name = h->root.root.string;
253         }
254
255       if (sec != NULL && elf_discarded_section (sec))
256         {
257           /* For relocs against symbols from removed linkonce sections,
258              or sections discarded by a linker script, we just want the
259              section contents zeroed.  Avoid any special processing.  */
260           _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
261           rel->r_info = 0;
262           rel->r_addend = 0;
263           continue;
264         }
265
266       if (info->relocatable)
267         continue;
268
269       r = moxie_final_link_relocate (howto, input_bfd, input_section,
270                                      contents, rel, relocation);
271
272       if (r != bfd_reloc_ok)
273         {
274           const char * msg = NULL;
275
276           switch (r)
277             {
278             case bfd_reloc_overflow:
279               r = info->callbacks->reloc_overflow
280                 (info, (h ? &h->root : NULL), name, howto->name,
281                  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
282               break;
283
284             case bfd_reloc_undefined:
285               r = info->callbacks->undefined_symbol
286                 (info, name, input_bfd, input_section, rel->r_offset,
287                  TRUE);
288               break;
289
290             case bfd_reloc_outofrange:
291               msg = _("internal error: out of range error");
292               break;
293
294             case bfd_reloc_notsupported:
295               msg = _("internal error: unsupported relocation error");
296               break;
297
298             case bfd_reloc_dangerous:
299               msg = _("internal error: dangerous relocation");
300               break;
301
302             default:
303               msg = _("internal error: unknown error");
304               break;
305             }
306
307           if (msg)
308             r = info->callbacks->warning
309               (info, msg, name, input_bfd, input_section, rel->r_offset);
310
311           if (! r)
312             return FALSE;
313         }
314     }
315
316   return TRUE;
317 }
318 \f
319 /* Return the section that should be marked against GC for a given
320    relocation.  */
321
322 static asection *
323 moxie_elf_gc_mark_hook (asection *sec,
324                         struct bfd_link_info *info,
325                         Elf_Internal_Rela *rel,
326                         struct elf_link_hash_entry *h,
327                         Elf_Internal_Sym *sym)
328 {
329   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
330 }
331
332 /* Look through the relocs for a section during the first phase.
333    Since we don't do .gots or .plts, we just need to consider the
334    virtual table relocs for gc.  */
335
336 static bfd_boolean
337 moxie_elf_check_relocs (bfd *abfd,
338                         struct bfd_link_info *info,
339                         asection *sec,
340                         const Elf_Internal_Rela *relocs)
341 {
342   Elf_Internal_Shdr *symtab_hdr;
343   struct elf_link_hash_entry **sym_hashes;
344   const Elf_Internal_Rela *rel;
345   const Elf_Internal_Rela *rel_end;
346
347   if (info->relocatable)
348     return TRUE;
349
350   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
351   sym_hashes = elf_sym_hashes (abfd);
352
353   rel_end = relocs + sec->reloc_count;
354   for (rel = relocs; rel < rel_end; rel++)
355     {
356       struct elf_link_hash_entry *h;
357       unsigned long r_symndx;
358
359       r_symndx = ELF32_R_SYM (rel->r_info);
360       if (r_symndx < symtab_hdr->sh_info)
361         h = NULL;
362       else
363         {
364           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
365           while (h->root.type == bfd_link_hash_indirect
366                  || h->root.type == bfd_link_hash_warning)
367             h = (struct elf_link_hash_entry *) h->root.u.i.link;
368         }
369     }
370
371   return TRUE;
372 }
373 \f
374 #define ELF_ARCH                bfd_arch_moxie
375 #define ELF_MACHINE_CODE        EM_MOXIE
376 #define ELF_MAXPAGESIZE         0x1
377
378 #define TARGET_BIG_SYM          bfd_elf32_moxie_vec
379 #define TARGET_BIG_NAME         "elf32-moxie"
380
381 #define elf_info_to_howto_rel                   NULL
382 #define elf_info_to_howto                       moxie_info_to_howto_rela
383 #define elf_backend_relocate_section            moxie_elf_relocate_section
384 #define elf_backend_gc_mark_hook                moxie_elf_gc_mark_hook
385 #define elf_backend_check_relocs                moxie_elf_check_relocs
386
387 #define elf_backend_can_gc_sections             1
388 #define elf_backend_rela_normal                 1
389
390 #define bfd_elf32_bfd_reloc_type_lookup         moxie_reloc_type_lookup
391 #define bfd_elf32_bfd_reloc_name_lookup         moxie_reloc_name_lookup
392
393 #include "elf32-target.h"