Automatic date update in version.in
[external/binutils.git] / bfd / elf32-ft32.c
1 /* ft32-specific support for 32-bit ELF.
2    Copyright (C) 2013-2016 Free Software Foundation, Inc.
3
4    Copied from elf32-moxie.c which is..
5    Copyright (C) 2009-2016 Free Software Foundation, Inc.
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/ft32.h"
30
31 /* Forward declarations.  */
32
33 static reloc_howto_type ft32_elf_howto_table [] =
34 {
35   /* This reloc does nothing.  */
36   HOWTO (R_FT32_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_FT32_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
52   HOWTO (R_FT32_32,             /* type */
53          0,                     /* rightshift */
54          2,                     /* size (0 = byte, 1 = short, 2 = long) */
55          32,                    /* bitsize */
56          FALSE,                 /* pc_relative */
57          0,                     /* bitpos */
58          complain_overflow_bitfield, /* complain_on_overflow */
59          bfd_elf_generic_reloc, /* special_function */
60          "R_FT32_32",           /* name */
61          FALSE,                 /* partial_inplace */
62          0x00000000,            /* src_mask */
63          0xffffffff,            /* dst_mask */
64          FALSE),                /* pcrel_offset */
65
66   HOWTO (R_FT32_16,             /* type */
67          0,                     /* rightshift */
68          1,                     /* size (0 = byte, 1 = short, 2 = long) */
69          16,                    /* bitsize */
70          FALSE,                 /* pc_relative */
71          0,                     /* bitpos */
72          complain_overflow_bitfield, /* complain_on_overflow */
73          bfd_elf_generic_reloc, /* special_function */
74          "R_FT32_16",           /* name */
75          FALSE,                 /* partial_inplace */
76          0x00000000,            /* src_mask */
77          0x0000ffff,            /* dst_mask */
78          FALSE),                /* pcrel_offset */
79
80   HOWTO (R_FT32_8,              /* type */
81          0,                     /* rightshift */
82          0,                     /* size (0 = byte, 1 = short, 2 = long) */
83          8,                     /* bitsize */
84          FALSE,                 /* pc_relative */
85          0,                     /* bitpos */
86          complain_overflow_signed, /* complain_on_overflow */
87          bfd_elf_generic_reloc, /* special_function */
88          "R_FT32_8",            /* name */
89          FALSE,                 /* partial_inplace */
90          0x00000000,            /* src_mask */
91          0x000000ff,            /* dst_mask */
92          FALSE),                /* pcrel_offset */
93
94   HOWTO (R_FT32_10,             /* type */
95          0,                     /* rightshift */
96          1,                     /* size (0 = byte, 1 = short, 2 = long) */
97          10,                    /* bitsize */
98          FALSE,                 /* pc_relative */
99          4,                     /* bitpos */
100          complain_overflow_signed, /* complain_on_overflow */
101          bfd_elf_generic_reloc, /* special_function */
102          "R_FT32_10",           /* name */
103          FALSE,                 /* partial_inplace */
104          0x00000000,            /* src_mask */
105          0x00003ff0,            /* dst_mask */
106          FALSE),                /* pcrel_offset */
107
108   HOWTO (R_FT32_20,             /* type */
109          0,                     /* rightshift */
110          2,                     /* size (0 = byte, 1 = short, 2 = long) */
111          20,                    /* bitsize */
112          FALSE,                 /* pc_relative */
113          0,                     /* bitpos */
114          complain_overflow_dont, /* complain_on_overflow */
115          bfd_elf_generic_reloc, /* special_function */
116          "R_FT32_20",           /* name */
117          FALSE,                 /* partial_inplace */
118          0x00000000,            /* src_mask */
119          0x000fffff,            /* dst_mask */
120          FALSE),                /* pcrel_offset */
121
122   HOWTO (R_FT32_17,             /* type */
123          0,                     /* rightshift */
124          2,                     /* size (0 = byte, 1 = short, 2 = long) */
125          17,                    /* bitsize */
126          FALSE,                 /* pc_relative */
127          0,                     /* bitpos */
128          complain_overflow_dont, /* complain_on_overflow */
129          bfd_elf_generic_reloc, /* special_function */
130          "R_FT32_17",           /* name */
131          FALSE,                 /* partial_inplace */
132          0x00000000,            /* src_mask */
133          0x0001ffff,            /* dst_mask */
134          FALSE),                /* pcrel_offset */
135
136   HOWTO (R_FT32_18,             /* type */
137          2,                     /* rightshift */
138          2,                     /* size (0 = byte, 1 = short, 2 = long) */
139          18,                    /* bitsize */
140          FALSE,                 /* pc_relative */
141          0,                     /* bitpos */
142          complain_overflow_signed, /* complain_on_overflow */
143          bfd_elf_generic_reloc, /* special_function */
144          "R_FT32_18",           /* name */
145          FALSE,         /* partial_inplace */
146          0x00000000,            /* src_mask */
147          0x0003ffff,            /* dst_mask */
148          FALSE),                /* pcrel_offset */
149
150 };
151 \f
152 /* Map BFD reloc types to FT32 ELF reloc types.  */
153
154 struct ft32_reloc_map
155 {
156   bfd_reloc_code_real_type bfd_reloc_val;
157   unsigned int ft32_reloc_val;
158 };
159
160 static const struct ft32_reloc_map ft32_reloc_map [] =
161 {
162   { BFD_RELOC_NONE,            R_FT32_NONE },
163   { BFD_RELOC_32,              R_FT32_20 },
164   { BFD_RELOC_16,              R_FT32_16 },
165   { BFD_RELOC_8,               R_FT32_8 },
166   { BFD_RELOC_FT32_10,           R_FT32_10 },
167   { BFD_RELOC_FT32_20,           R_FT32_20 },
168   { BFD_RELOC_FT32_17,           R_FT32_17 },
169   { BFD_RELOC_FT32_18,           R_FT32_18 },
170 };
171
172 static reloc_howto_type *
173 ft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
174                          bfd_reloc_code_real_type code)
175 {
176   unsigned int i;
177
178   for (i = sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]);
179        --i;)
180     if (ft32_reloc_map [i].bfd_reloc_val == code)
181       return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val];
182
183   return NULL;
184 }
185
186 static reloc_howto_type *
187 ft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
188 {
189   unsigned int i;
190
191   for (i = 0;
192        i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]);
193        i++)
194     if (ft32_elf_howto_table[i].name != NULL
195         && strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0)
196       return &ft32_elf_howto_table[i];
197
198   return NULL;
199 }
200
201 /* Set the howto pointer for an FT32 ELF reloc.  */
202
203 static void
204 ft32_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
205                           arelent *cache_ptr,
206                           Elf_Internal_Rela *dst)
207 {
208   unsigned int r_type;
209
210   r_type = ELF32_R_TYPE (dst->r_info);
211   BFD_ASSERT (r_type < (unsigned int) R_FT32_max);
212   cache_ptr->howto = & ft32_elf_howto_table [r_type];
213 }
214 \f
215 /* Relocate an FT32 ELF section.
216
217    The RELOCATE_SECTION function is called by the new ELF backend linker
218    to handle the relocations for a section.
219
220    The relocs are always passed as Rela structures; if the section
221    actually uses Rel structures, the r_addend field will always be
222    zero.
223
224    This function is responsible for adjusting the section contents as
225    necessary, and (if using Rela relocs and generating a relocatable
226    output file) adjusting the reloc addend as necessary.
227
228    This function does not have to worry about setting the reloc
229    address or the reloc symbol index.
230
231    LOCAL_SYMS is a pointer to the swapped in local symbols.
232
233    LOCAL_SECTIONS is an array giving the section in the input file
234    corresponding to the st_shndx field of each local symbol.
235
236    The global hash table entry for the global symbols can be found
237    via elf_sym_hashes (input_bfd).
238
239    When generating relocatable output, this function must handle
240    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
241    going to be the section symbol corresponding to the output
242    section, which means that the addend must be adjusted
243    accordingly.  */
244
245 static bfd_boolean
246 ft32_elf_relocate_section (bfd *output_bfd,
247                             struct bfd_link_info *info,
248                             bfd *input_bfd,
249                             asection *input_section,
250                             bfd_byte *contents,
251                             Elf_Internal_Rela *relocs,
252                             Elf_Internal_Sym *local_syms,
253                             asection **local_sections)
254 {
255   Elf_Internal_Shdr *symtab_hdr;
256   struct elf_link_hash_entry **sym_hashes;
257   Elf_Internal_Rela *rel;
258   Elf_Internal_Rela *relend;
259
260   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
261   sym_hashes = elf_sym_hashes (input_bfd);
262   relend     = relocs + input_section->reloc_count;
263
264   for (rel = relocs; rel < relend; rel ++)
265     {
266       reloc_howto_type *howto;
267       unsigned long r_symndx;
268       Elf_Internal_Sym *sym;
269       asection *sec;
270       struct elf_link_hash_entry *h;
271       bfd_vma relocation;
272       bfd_reloc_status_type r;
273       const char *name;
274       int r_type;
275
276       r_type = ELF32_R_TYPE (rel->r_info);
277       r_symndx = ELF32_R_SYM (rel->r_info);
278       howto  = ft32_elf_howto_table + r_type;
279       h      = NULL;
280       sym    = NULL;
281       sec    = NULL;
282
283       if (r_symndx < symtab_hdr->sh_info)
284         {
285           sym = local_syms + r_symndx;
286           sec = local_sections [r_symndx];
287           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
288
289           name = bfd_elf_string_from_elf_section
290             (input_bfd, symtab_hdr->sh_link, sym->st_name);
291           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
292         }
293       else
294         {
295           bfd_boolean unresolved_reloc, warned, ignored;
296
297           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
298                                    r_symndx, symtab_hdr, sym_hashes,
299                                    h, sec, relocation,
300                                    unresolved_reloc, warned, ignored);
301
302           name = h->root.root.string;
303         }
304
305       if (sec != NULL && discarded_section (sec))
306         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
307                                          rel, 1, relend, howto, 0, contents);
308
309       if (bfd_link_relocatable (info))
310         continue;
311
312       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
313                                     contents, rel->r_offset,
314                                     relocation, rel->r_addend);
315
316       if (r != bfd_reloc_ok)
317         {
318           const char * msg = NULL;
319
320           switch (r)
321             {
322             case bfd_reloc_overflow:
323               (*info->callbacks->reloc_overflow)
324                 (info, (h ? &h->root : NULL), name, howto->name,
325                  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
326               break;
327
328             case bfd_reloc_undefined:
329               (*info->callbacks->undefined_symbol)
330                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
331               break;
332
333             case bfd_reloc_outofrange:
334               msg = _("internal error: out of range error");
335               break;
336
337             case bfd_reloc_notsupported:
338               msg = _("internal error: unsupported relocation error");
339               break;
340
341             case bfd_reloc_dangerous:
342               msg = _("internal error: dangerous relocation");
343               break;
344
345             default:
346               msg = _("internal error: unknown error");
347               break;
348             }
349
350           if (msg)
351             (*info->callbacks->warning) (info, msg, name, input_bfd,
352                                          input_section, rel->r_offset);
353         }
354     }
355
356   return TRUE;
357 }
358 \f
359 #define ELF_ARCH                bfd_arch_ft32
360 #define ELF_MACHINE_CODE        EM_FT32
361 #define ELF_MAXPAGESIZE         0x1
362
363 #define TARGET_LITTLE_SYM       ft32_elf32_vec
364 #define TARGET_LITTLE_NAME      "elf32-ft32"
365
366 #define elf_info_to_howto_rel                   NULL
367 #define elf_info_to_howto                       ft32_info_to_howto_rela
368 #define elf_backend_relocate_section            ft32_elf_relocate_section
369
370 #define elf_backend_can_gc_sections             1
371 #define elf_backend_rela_normal                 1
372
373 #define bfd_elf32_bfd_reloc_type_lookup         ft32_reloc_type_lookup
374 #define bfd_elf32_bfd_reloc_name_lookup         ft32_reloc_name_lookup
375
376 #include "elf32-target.h"