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