FT32B is a new FT32 family member. It has a code compression scheme, which requires...
[external/binutils.git] / bfd / elf32-ft32.c
1 /* ft32-specific support for 32-bit ELF.
2    Copyright (C) 2013-2017 Free Software Foundation, Inc.
3
4    Copied from elf32-moxie.c which is..
5    Copyright (C) 2009-2017 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 #include "opcode/ft32.h"
31
32 static bfd_boolean debug_relax = FALSE;
33
34 static bfd_reloc_status_type
35 bfd_elf_ft32_diff_reloc (bfd *, arelent *, asymbol *, void *,
36                         asection *, bfd *, char **);
37
38 static reloc_howto_type ft32_elf_howto_table [] =
39 {
40   /* This reloc does nothing.  */
41   HOWTO (R_FT32_NONE,           /* type */
42          0,                     /* rightshift */
43          2,                     /* size (0 = byte, 1 = short, 2 = long) */
44          32,                    /* bitsize */
45          FALSE,                 /* pc_relative */
46          0,                     /* bitpos */
47          complain_overflow_bitfield, /* complain_on_overflow */
48          bfd_elf_generic_reloc, /* special_function */
49          "R_FT32_NONE",         /* name */
50          FALSE,                 /* partial_inplace */
51          0,                     /* src_mask */
52          0,                     /* dst_mask */
53          FALSE),                /* pcrel_offset */
54
55   /* A 32 bit absolute relocation.  */
56
57   HOWTO (R_FT32_32,             /* type */
58          0,                     /* rightshift */
59          2,                     /* size (0 = byte, 1 = short, 2 = long) */
60          32,                    /* bitsize */
61          FALSE,                 /* pc_relative */
62          0,                     /* bitpos */
63          complain_overflow_bitfield, /* complain_on_overflow */
64          bfd_elf_generic_reloc, /* special_function */
65          "R_FT32_32",           /* name */
66          FALSE,                 /* partial_inplace */
67          0x00000000,            /* src_mask */
68          0xffffffff,            /* dst_mask */
69          FALSE),                /* pcrel_offset */
70
71   HOWTO (R_FT32_16,             /* type */
72          0,                     /* rightshift */
73          1,                     /* size (0 = byte, 1 = short, 2 = long) */
74          16,                    /* bitsize */
75          FALSE,                 /* pc_relative */
76          0,                     /* bitpos */
77          complain_overflow_dont, /* complain_on_overflow */
78          bfd_elf_generic_reloc, /* special_function */
79          "R_FT32_16",           /* name */
80          FALSE,                 /* partial_inplace */
81          0x00000000,            /* src_mask */
82          0x0000ffff,            /* dst_mask */
83          FALSE),                /* pcrel_offset */
84
85   HOWTO (R_FT32_8,              /* type */
86          0,                     /* rightshift */
87          0,                     /* size (0 = byte, 1 = short, 2 = long) */
88          8,                     /* bitsize */
89          FALSE,                 /* pc_relative */
90          0,                     /* bitpos */
91          complain_overflow_signed, /* complain_on_overflow */
92          bfd_elf_generic_reloc, /* special_function */
93          "R_FT32_8",            /* name */
94          FALSE,                 /* partial_inplace */
95          0x00000000,            /* src_mask */
96          0x000000ff,            /* dst_mask */
97          FALSE),                /* pcrel_offset */
98
99   HOWTO (R_FT32_10,             /* type */
100          0,                     /* rightshift */
101          1,                     /* size (0 = byte, 1 = short, 2 = long) */
102          10,                    /* bitsize */
103          FALSE,                 /* pc_relative */
104          4,                     /* bitpos */
105          complain_overflow_bitfield, /* complain_on_overflow */
106          bfd_elf_generic_reloc, /* special_function */
107          "R_FT32_10",           /* name */
108          FALSE,                 /* partial_inplace */
109          0x00000000,            /* src_mask */
110          0x00003ff0,            /* dst_mask */
111          FALSE),                /* pcrel_offset */
112
113   HOWTO (R_FT32_20,             /* type */
114          0,                     /* rightshift */
115          2,                     /* size (0 = byte, 1 = short, 2 = long) */
116          20,                    /* bitsize */
117          FALSE,                 /* pc_relative */
118          0,                     /* bitpos */
119          complain_overflow_dont, /* complain_on_overflow */
120          bfd_elf_generic_reloc, /* special_function */
121          "R_FT32_20",           /* name */
122          FALSE,                 /* partial_inplace */
123          0x00000000,            /* src_mask */
124          0x000fffff,            /* dst_mask */
125          FALSE),                /* pcrel_offset */
126
127   HOWTO (R_FT32_17,             /* type */
128          0,                     /* rightshift */
129          2,                     /* size (0 = byte, 1 = short, 2 = long) */
130          17,                    /* bitsize */
131          FALSE,                 /* pc_relative */
132          0,                     /* bitpos */
133          complain_overflow_dont, /* complain_on_overflow */
134          bfd_elf_generic_reloc, /* special_function */
135          "R_FT32_17",           /* name */
136          FALSE,                 /* partial_inplace */
137          0x00000000,            /* src_mask */
138          0x0001ffff,            /* dst_mask */
139          FALSE),                /* pcrel_offset */
140
141   HOWTO (R_FT32_18,             /* type */
142          2,                     /* rightshift */
143          2,                     /* size (0 = byte, 1 = short, 2 = long) */
144          18,                    /* bitsize */
145          FALSE,                 /* pc_relative */
146          0,                     /* bitpos */
147          complain_overflow_dont, /* complain_on_overflow */
148          bfd_elf_generic_reloc, /* special_function */
149          "R_FT32_18",           /* name */
150          FALSE,                 /* partial_inplace */
151          0x00000000,            /* src_mask */
152          0x0003ffff,            /* dst_mask */
153          FALSE),                /* pcrel_offset */
154
155   HOWTO (R_FT32_RELAX,          /* type */
156          0,                     /* rightshift */
157          1,                     /* size (0 = byte, 1 = short, 2 = long) */
158          10,                    /* bitsize */
159          FALSE,                 /* pc_relative */
160          4,                     /* bitpos */
161          complain_overflow_signed, /* complain_on_overflow */
162          bfd_elf_generic_reloc, /* special_function */
163          "R_FT32_RELAX",        /* name */
164          FALSE,                 /* partial_inplace */
165          0x00000000,            /* src_mask */
166          0x00000000,            /* dst_mask */
167          FALSE),                /* pcrel_offset */
168
169   HOWTO (R_FT32_SC0,            /* type */
170          0,                     /* rightshift */
171          1,                     /* size (0 = byte, 1 = short, 2 = long) */
172          10,                    /* bitsize */
173          FALSE,                 /* pc_relative */
174          4,                     /* bitpos */
175          complain_overflow_signed, /* complain_on_overflow */
176          bfd_elf_generic_reloc, /* special_function */
177          "R_FT32_SC0",          /* name */
178          FALSE,                 /* partial_inplace */
179          0x00000000,            /* src_mask */
180          0x00000000,            /* dst_mask */
181          FALSE),                /* pcrel_offset */
182   HOWTO (R_FT32_SC1,            /* type */
183          2,                     /* rightshift */
184          2,                     /* size (0 = byte, 1 = short, 2 = long) */
185          22,                    /* bitsize */
186          TRUE,                  /* pc_relative */
187          7,                     /* bitpos */
188          complain_overflow_dont, /* complain_on_overflow */
189          bfd_elf_generic_reloc, /* special_function */
190          "R_FT32_SC1",          /* name */
191          TRUE,                  /* partial_inplace */
192          0x07ffff80,            /* src_mask */
193          0x07ffff80,            /* dst_mask */
194          FALSE),                /* pcrel_offset */
195   HOWTO (R_FT32_15,             /* type */
196          0,                     /* rightshift */
197          2,                     /* size (0 = byte, 1 = short, 2 = long) */
198          15,                    /* bitsize */
199          FALSE,                 /* pc_relative */
200          0,                     /* bitpos */
201          complain_overflow_dont, /* complain_on_overflow */
202          bfd_elf_generic_reloc, /* special_function */
203          "R_FT32_15",           /* name */
204          FALSE,                 /* partial_inplace */
205          0x00000000,            /* src_mask */
206          0x00007fff,            /* dst_mask */
207          FALSE),                /* pcrel_offset */
208   HOWTO (R_FT32_DIFF32,         /* type */
209          0,                     /* rightshift */
210          2,                     /* size (0 = byte, 1 = short, 2 = long) */
211          32,                    /* bitsize */
212          FALSE,                 /* pc_relative */
213          0,                     /* bitpos */
214          complain_overflow_dont, /* complain_on_overflow */
215          bfd_elf_ft32_diff_reloc, /* special_function */
216          "R_FT32_DIFF32",       /* name */
217          FALSE,                 /* partial_inplace */
218          0,                     /* src_mask */
219          0xffffffff,            /* dst_mask */
220          FALSE),                /* pcrel_offset */
221 };
222 \f
223 \f
224 /* Map BFD reloc types to FT32 ELF reloc types.  */
225
226 struct ft32_reloc_map
227 {
228   bfd_reloc_code_real_type bfd_reloc_val;
229   unsigned int ft32_reloc_val;
230 };
231
232 static const struct ft32_reloc_map ft32_reloc_map [] =
233 {
234   { BFD_RELOC_NONE,             R_FT32_NONE },
235   { BFD_RELOC_32,               R_FT32_32 },
236   { BFD_RELOC_16,               R_FT32_16 },
237   { BFD_RELOC_8,                R_FT32_8 },
238   { BFD_RELOC_FT32_10,          R_FT32_10 },
239   { BFD_RELOC_FT32_20,          R_FT32_20 },
240   { BFD_RELOC_FT32_17,          R_FT32_17 },
241   { BFD_RELOC_FT32_18,          R_FT32_18 },
242   { BFD_RELOC_FT32_RELAX,       R_FT32_RELAX },
243   { BFD_RELOC_FT32_SC0,         R_FT32_SC0 },
244   { BFD_RELOC_FT32_SC1,         R_FT32_SC1 },
245   { BFD_RELOC_FT32_15,          R_FT32_15 },
246   { BFD_RELOC_FT32_DIFF32,      R_FT32_DIFF32 },
247 };
248
249 /* Perform a diff relocation. Nothing to do, as the difference value is
250    already written into the section's contents. */
251
252 static bfd_reloc_status_type
253 bfd_elf_ft32_diff_reloc (bfd *abfd ATTRIBUTE_UNUSED,
254                       arelent *reloc_entry ATTRIBUTE_UNUSED,
255               asymbol *symbol ATTRIBUTE_UNUSED,
256               void *data ATTRIBUTE_UNUSED,
257               asection *input_section ATTRIBUTE_UNUSED,
258               bfd *output_bfd ATTRIBUTE_UNUSED,
259               char **error_message ATTRIBUTE_UNUSED)
260 {
261   return bfd_reloc_ok;
262 }
263
264 static reloc_howto_type *
265 ft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
266                          bfd_reloc_code_real_type code)
267 {
268   unsigned int i;
269
270   for (i = sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]);
271        --i;)
272     if (ft32_reloc_map [i].bfd_reloc_val == code)
273       return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val];
274
275   return NULL;
276 }
277
278 static reloc_howto_type *
279 ft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
280 {
281   unsigned int i;
282
283   for (i = 0;
284        i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]);
285        i++)
286     if (ft32_elf_howto_table[i].name != NULL
287         && strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0)
288       return &ft32_elf_howto_table[i];
289
290   return NULL;
291 }
292
293 /* Set the howto pointer for an FT32 ELF reloc.  */
294
295 static void
296 ft32_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
297                           arelent *cache_ptr,
298                           Elf_Internal_Rela *dst)
299 {
300   unsigned int r_type;
301
302   r_type = ELF32_R_TYPE (dst->r_info);
303   BFD_ASSERT (r_type < (unsigned int) R_FT32_max);
304   cache_ptr->howto = & ft32_elf_howto_table [r_type];
305 }
306
307 /* Relocate an FT32 ELF section.
308
309    The RELOCATE_SECTION function is called by the new ELF backend linker
310    to handle the relocations for a section.
311
312    The relocs are always passed as Rela structures; if the section
313    actually uses Rel structures, the r_addend field will always be
314    zero.
315
316    This function is responsible for adjusting the section contents as
317    necessary, and (if using Rela relocs and generating a relocatable
318    output file) adjusting the reloc addend as necessary.
319
320    This function does not have to worry about setting the reloc
321    address or the reloc symbol index.
322
323    LOCAL_SYMS is a pointer to the swapped in local symbols.
324
325    LOCAL_SECTIONS is an array giving the section in the input file
326    corresponding to the st_shndx field of each local symbol.
327
328    The global hash table entry for the global symbols can be found
329    via elf_sym_hashes (input_bfd).
330
331    When generating relocatable output, this function must handle
332    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
333    going to be the section symbol corresponding to the output
334    section, which means that the addend must be adjusted
335    accordingly.  */
336
337 static bfd_boolean
338 ft32_elf_relocate_section (bfd *output_bfd,
339                             struct bfd_link_info *info,
340                             bfd *input_bfd,
341                             asection *input_section,
342                             bfd_byte *contents,
343                             Elf_Internal_Rela *relocs,
344                             Elf_Internal_Sym *local_syms,
345                             asection **local_sections)
346 {
347   Elf_Internal_Shdr *symtab_hdr;
348   struct elf_link_hash_entry **sym_hashes;
349   Elf_Internal_Rela *rel;
350   Elf_Internal_Rela *relend;
351
352   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
353   sym_hashes = elf_sym_hashes (input_bfd);
354   relend     = relocs + input_section->reloc_count;
355
356   for (rel = relocs; rel < relend; rel ++)
357     {
358       reloc_howto_type *howto;
359       unsigned long r_symndx;
360       Elf_Internal_Sym *sym;
361       asection *sec;
362       struct elf_link_hash_entry *h;
363       bfd_vma relocation;
364       bfd_reloc_status_type r;
365       const char *name;
366       int r_type;
367
368       r_type = ELF32_R_TYPE (rel->r_info);
369       r_symndx = ELF32_R_SYM (rel->r_info);
370       howto  = ft32_elf_howto_table + r_type;
371       h      = NULL;
372       sym    = NULL;
373       sec    = NULL;
374
375       if (r_symndx < symtab_hdr->sh_info)
376         {
377           sym = local_syms + r_symndx;
378           sec = local_sections [r_symndx];
379           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
380
381           name = bfd_elf_string_from_elf_section
382             (input_bfd, symtab_hdr->sh_link, sym->st_name);
383           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
384         }
385       else
386         {
387           bfd_boolean unresolved_reloc, warned, ignored;
388
389           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
390                                    r_symndx, symtab_hdr, sym_hashes,
391                                    h, sec, relocation,
392                                    unresolved_reloc, warned, ignored);
393
394           name = h->root.root.string;
395         }
396
397       if (sec != NULL && discarded_section (sec))
398         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
399                                          rel, 1, relend, howto, 0, contents);
400
401       if (bfd_link_relocatable (info))
402         continue;
403
404       switch (howto->type)
405         {
406           case R_FT32_SC0:
407             {
408               unsigned int insn;
409               int offset;
410               unsigned int code15[2];
411
412               insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
413               ft32_split_shortcode (insn, code15);
414
415               offset = (int)relocation;
416               offset += (int)(rel->r_addend - rel->r_offset);
417               offset -= (input_section->output_section->vma +
418                          input_section->output_offset);
419               if ((offset < -1024) || (offset >= 1024))
420                 {
421                   r = bfd_reloc_outofrange;
422                   break;
423                 }
424               code15[0] |= ((offset / 4) & 511);
425               insn = ft32_merge_shortcode (code15);
426               bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
427             }
428             r = bfd_reloc_ok;
429             break;
430
431           case R_FT32_SC1:
432             {
433               unsigned int insn;
434               int offset;
435               unsigned int code15[2];
436
437               insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
438               ft32_split_shortcode (insn, code15);
439
440               offset = (int)relocation;
441               offset += (int)(rel->r_addend - rel->r_offset);
442               offset -= (input_section->output_section->vma +
443                          input_section->output_offset);
444               if ((offset < -1024) || (offset >= 1024))
445                 {
446                   r = bfd_reloc_outofrange;
447                   break;
448                 }
449               code15[1] |= ((offset / 4) & 511);
450               insn = ft32_merge_shortcode (code15);
451               bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
452             }
453             r = bfd_reloc_ok;
454             break;
455
456           case R_FT32_DIFF32:
457             r = bfd_reloc_ok;
458             break;
459
460           default:
461             r = _bfd_final_link_relocate (howto, input_bfd, input_section,
462                                           contents, rel->r_offset,
463                                           relocation, rel->r_addend);
464             break;
465         }
466
467       if (r != bfd_reloc_ok)
468         {
469           const char * msg = NULL;
470
471           switch (r)
472             {
473             case bfd_reloc_overflow:
474               (*info->callbacks->reloc_overflow)
475                 (info, (h ? &h->root : NULL), name, howto->name,
476                  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
477               break;
478
479             case bfd_reloc_undefined:
480               (*info->callbacks->undefined_symbol)
481                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
482               break;
483
484             case bfd_reloc_outofrange:
485               msg = _("internal error: out of range error");
486               break;
487
488             case bfd_reloc_notsupported:
489               msg = _("internal error: unsupported relocation error");
490               break;
491
492             case bfd_reloc_dangerous:
493               msg = _("internal error: dangerous relocation");
494               break;
495
496             default:
497               msg = _("internal error: unknown error");
498               break;
499             }
500
501           if (msg)
502             (*info->callbacks->warning) (info, msg, name, input_bfd,
503                                          input_section, rel->r_offset);
504         }
505     }
506
507   return TRUE;
508 }
509 \f
510 /* Relaxation.  */
511
512 static bfd_boolean
513 ft32_reloc_shortable
514     (bfd *                  abfd,
515      asection *             sec,
516      Elf_Internal_Sym *     isymbuf ATTRIBUTE_UNUSED,
517      bfd_byte *             contents,
518      bfd_vma                pc ATTRIBUTE_UNUSED,
519      Elf_Internal_Rela *    irel,
520      unsigned int *         sc)
521 {
522   Elf_Internal_Shdr *symtab_hdr ATTRIBUTE_UNUSED;
523   bfd_vma symval;
524
525   enum elf_ft32_reloc_type r_type;
526   reloc_howto_type *howto = NULL;
527   unsigned int insn;
528   int offset;
529   bfd_vma dot, value;
530
531   r_type = ELF32_R_TYPE (irel->r_info);
532   howto = &ft32_elf_howto_table [r_type];
533
534   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
535
536   /* Get the value of the symbol referred to by the reloc.  */
537   if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
538     {
539       /* A local symbol.  */
540       Elf_Internal_Sym *isym;
541       asection *sym_sec;
542
543       isym = isymbuf + ELF32_R_SYM (irel->r_info);
544       sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
545       symval = isym->st_value;
546       /* If the reloc is absolute, it will not have
547          a symbol or section associated with it.  */
548       if (sym_sec)
549         symval += sym_sec->output_section->vma
550           + sym_sec->output_offset;
551     }
552   else
553     {
554       unsigned long indx;
555       struct elf_link_hash_entry *h;
556
557       /* An external symbol.  */
558       indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
559       h = elf_sym_hashes (abfd)[indx];
560       BFD_ASSERT (h != NULL);
561       if (h->root.type != bfd_link_hash_defined
562           && h->root.type != bfd_link_hash_defweak)
563         /* This appears to be a reference to an undefined
564            symbol.  Just ignore it--it will be caught by the
565            regular reloc processing.  */
566         return FALSE;
567
568       symval = (h->root.u.def.value
569                 + h->root.u.def.section->output_section->vma
570                 + h->root.u.def.section->output_offset);
571     }
572
573   switch (r_type)
574     {
575       case R_FT32_8:
576       case R_FT32_10:
577       case R_FT32_16:
578       case R_FT32_20:
579       case R_FT32_RELAX:
580         if (symval != 0)
581           return FALSE;
582         insn = bfd_get_32 (abfd, contents + irel->r_offset);
583         insn |= ((symval + irel->r_addend) << howto->bitpos) & howto->dst_mask;
584         return ft32_shortcode (insn, sc);
585
586       case R_FT32_18:
587         insn = bfd_get_32 (abfd, contents + irel->r_offset);
588         /* Get the address of this instruction.  */
589         dot = (sec->output_section->vma
590                + sec->output_offset + irel->r_offset);
591         value = symval + irel->r_addend;
592         offset = (value - dot) / 4;
593
594         if ((dot > 0x8c) && (-256 <= offset) && (offset < 256))
595           {
596             switch (insn)
597               {
598                 case 0x00200000: *sc = (3 << 13) | (0  << 9); return TRUE;
599                 case 0x00280000: *sc = (3 << 13) | (1  << 9); return TRUE;
600                 case 0x00600000: *sc = (3 << 13) | (2  << 9); return TRUE;
601                 case 0x00680000: *sc = (3 << 13) | (3  << 9); return TRUE;
602                 case 0x00a00000: *sc = (3 << 13) | (4  << 9); return TRUE;
603                 case 0x00a80000: *sc = (3 << 13) | (5  << 9); return TRUE;
604                 case 0x00e00000: *sc = (3 << 13) | (6  << 9); return TRUE;
605                 case 0x00e80000: *sc = (3 << 13) | (7  << 9); return TRUE;
606                 case 0x01200000: *sc = (3 << 13) | (8  << 9); return TRUE;
607                 case 0x01280000: *sc = (3 << 13) | (9  << 9); return TRUE;
608                 case 0x01600000: *sc = (3 << 13) | (10 << 9); return TRUE;
609                 case 0x01680000: *sc = (3 << 13) | (11 << 9); return TRUE;
610                 case 0x01a00000: *sc = (3 << 13) | (12 << 9); return TRUE;
611                 case 0x01a80000: *sc = (3 << 13) | (13 << 9); return TRUE;
612
613                 case 0x00300000: *sc = (3 << 13) | (14 << 9); return TRUE;
614                 case 0x00340000: *sc = (3 << 13) | (15 << 9); return TRUE;
615
616                 default:
617                   break;
618               }
619           }
620         break;
621
622       default:
623         break;
624     }
625   return FALSE;
626 }
627
628 /* Returns whether the relocation type passed is a diff reloc.  */
629
630 static bfd_boolean
631 elf32_ft32_is_diff_reloc (Elf_Internal_Rela *irel)
632 {
633   return (ELF32_R_TYPE (irel->r_info) == R_FT32_DIFF32);
634 }
635
636 /* Reduce the diff value written in the section by count if the shrinked
637    insn address happens to fall between the two symbols for which this
638    diff reloc was emitted.  */
639
640 static bfd_boolean
641 elf32_ft32_adjust_diff_reloc_value (bfd *abfd,
642                                    struct bfd_section *isec,
643                                    Elf_Internal_Rela *irel,
644                                    bfd_vma symval,
645                                    bfd_vma shrinked_insn_address,
646                                    int count)
647 {
648   unsigned char * reloc_contents = NULL;
649   unsigned char * isec_contents = elf_section_data (isec)->this_hdr.contents;
650   bfd_signed_vma x = 0;
651   bfd_vma sym2_address;
652   bfd_vma sym1_address;
653   bfd_vma start_address;
654   bfd_vma end_address;
655
656
657   if (isec_contents == NULL)
658     {
659       if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
660         return FALSE;
661
662       elf_section_data (isec)->this_hdr.contents = isec_contents;
663     }
664
665   reloc_contents = isec_contents + irel->r_offset;
666
667   /* Read value written in object file.  */
668   switch (ELF32_R_TYPE (irel->r_info))
669     {
670     case R_FT32_DIFF32:
671       x = bfd_get_signed_32 (abfd, reloc_contents);
672       break;
673
674     default:
675       return FALSE;
676     }
677
678   /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
679      into the object file at the reloc offset. sym2's logical value is
680      symval (<start_of_section>) + reloc addend. Compute the start and end
681      addresses and check if the shrinked insn falls between sym1 and sym2.  */
682   sym2_address = symval + irel->r_addend;
683   sym1_address = sym2_address - x;
684
685   /* Don't assume sym2 is bigger than sym1 - the difference
686      could be negative. Compute start and end addresses, and
687      use those to see if they span shrinked_insn_address.  */
688   start_address = sym1_address < sym2_address ? sym1_address : sym2_address;
689   end_address = sym1_address > sym2_address ? sym1_address : sym2_address;
690
691   if (shrinked_insn_address >= start_address
692       && shrinked_insn_address < end_address)
693     {
694       /* Reduce the diff value by count bytes and write it back into section
695          contents.  */
696       bfd_signed_vma new_diff = x < 0 ? x + count : x - count;
697
698       if (sym2_address > shrinked_insn_address)
699         irel->r_addend -= count;
700
701       switch (ELF32_R_TYPE (irel->r_info))
702         {
703         case R_FT32_DIFF32:
704           bfd_put_signed_32 (abfd, new_diff & 0xFFFFFFFF, reloc_contents);
705           break;
706
707         default:
708           return FALSE;
709         }
710     }
711
712   return TRUE;
713 }
714
715 static bfd_boolean
716 elf32_ft32_adjust_reloc_if_spans_insn (bfd *abfd,
717                                       asection *isec,
718                                       Elf_Internal_Rela *irel,  bfd_vma symval,
719                                       bfd_vma shrinked_insn_address,
720                                       bfd_vma shrink_boundary,
721                                       int count)
722 {
723
724   if (elf32_ft32_is_diff_reloc (irel))
725     {
726       if (!elf32_ft32_adjust_diff_reloc_value (abfd, isec, irel,
727                                                symval,
728                                                shrinked_insn_address,
729                                                count))
730         return FALSE;
731     }
732   else
733     {
734       bfd_vma reloc_value = symval + irel->r_addend;
735       bfd_boolean addend_within_shrink_boundary =
736         (reloc_value <= shrink_boundary);
737       bfd_boolean reloc_spans_insn =
738         (symval <= shrinked_insn_address
739          && reloc_value > shrinked_insn_address
740          && addend_within_shrink_boundary);
741
742       if (! reloc_spans_insn)
743         return TRUE;
744
745       irel->r_addend -= count;
746
747       if (debug_relax)
748         printf ("Relocation's addend needed to be fixed \n");
749     }
750   return TRUE;
751 }
752
753 /* Delete some bytes from a section while relaxing.  */
754
755 static bfd_boolean
756 elf32_ft32_relax_delete_bytes (struct bfd_link_info *link_info, bfd * abfd,
757                                asection * sec, bfd_vma addr, int count)
758 {
759   Elf_Internal_Shdr *symtab_hdr;
760   unsigned int sec_shndx;
761   bfd_byte *contents;
762   Elf_Internal_Rela *irel, *irelend;
763   bfd_vma toaddr;
764   Elf_Internal_Sym *isym;
765   Elf_Internal_Sym *isymend;
766   struct elf_link_hash_entry **sym_hashes;
767   struct elf_link_hash_entry **end_hashes;
768   struct elf_link_hash_entry **start_hashes;
769   unsigned int symcount;
770   Elf_Internal_Sym *isymbuf = NULL;
771
772   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
773   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
774
775   contents = elf_section_data (sec)->this_hdr.contents;
776
777   toaddr = sec->size;
778
779   irel = elf_section_data (sec)->relocs;
780   irelend = irel + sec->reloc_count;
781
782   /* Actually delete the bytes.  */
783   memmove (contents + addr, contents + addr + count,
784            (size_t) (toaddr - addr - count));
785   sec->size -= count;
786
787   /* Adjust all the relocs.  */
788   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
789     /* Get the new reloc address.  */
790     if ((irel->r_offset > addr && irel->r_offset < toaddr))
791       irel->r_offset -= count;
792
793   /* The reloc's own addresses are now ok. However, we need to readjust
794      the reloc's addend, i.e. the reloc's value if two conditions are met:
795      1.) the reloc is relative to a symbol in this section that
796      is located in front of the shrinked instruction
797      2.) symbol plus addend end up behind the shrinked instruction.
798
799      The most common case where this happens are relocs relative to
800      the section-start symbol.
801
802      This step needs to be done for all of the sections of the bfd.  */
803   {
804     struct bfd_section *isec;
805
806     for (isec = abfd->sections; isec; isec = isec->next)
807       {
808         bfd_vma symval;
809         bfd_vma shrinked_insn_address;
810
811         if (isec->reloc_count == 0)
812           continue;
813
814         shrinked_insn_address = (sec->output_section->vma
815                                  + sec->output_offset + addr - count);
816
817         irel = elf_section_data (isec)->relocs;
818         /* PR 12161: Read in the relocs for this section if necessary.  */
819         if (irel == NULL)
820           irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
821
822         for (irelend = irel + isec->reloc_count; irel < irelend; irel++)
823           {
824             /* Read this BFD's local symbols if we haven't done
825                so already.  */
826             if (isymbuf == NULL && symtab_hdr->sh_info != 0)
827               {
828                 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
829                 if (isymbuf == NULL)
830                   isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
831                                                   symtab_hdr->sh_info, 0,
832                                                   NULL, NULL, NULL);
833                 if (isymbuf == NULL)
834                   return FALSE;
835               }
836
837             /* Get the value of the symbol referred to by the reloc.  */
838             if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
839               {
840                 /* A local symbol.  */
841                 asection *sym_sec;
842
843                 isym = isymbuf + ELF32_R_SYM (irel->r_info);
844                 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
845                 symval = isym->st_value;
846                 /* If the reloc is absolute, it will not have
847                    a symbol or section associated with it.  */
848                 if (sym_sec == sec)
849                   {
850                     symval += sym_sec->output_section->vma
851                       + sym_sec->output_offset;
852
853                     if (debug_relax)
854                       printf ("Checking if the relocation's "
855                               "addend needs corrections.\n"
856                               "Address of anchor symbol: 0x%x \n"
857                               "Address of relocation target: 0x%x \n"
858                               "Address of relaxed insn: 0x%x \n",
859                               (unsigned int) symval,
860                               (unsigned int) (symval + irel->r_addend),
861                               (unsigned int) shrinked_insn_address);
862
863                     if (symval <= shrinked_insn_address
864                         && (symval + irel->r_addend) > shrinked_insn_address)
865                       {
866                         /* If there is an alignment boundary, we only need to
867                            adjust addends that end up below the boundary. */
868                         bfd_vma shrink_boundary = (toaddr
869                                                    + sec->output_section->vma
870                                                    + sec->output_offset);
871
872                         if (debug_relax)
873                           printf
874                             ("Relocation's addend needed to be fixed \n");
875
876                         if (!elf32_ft32_adjust_reloc_if_spans_insn (abfd, isec,
877                                                                     irel, symval,
878                                                                     shrinked_insn_address,
879                                                                     shrink_boundary,
880                                                                     count))
881                           return FALSE;
882                       }
883                   }
884                 /* else reference symbol is absolute. No adjustment needed. */
885               }
886             /* else...Reference symbol is extern.  No need for adjusting
887                the addend.  */
888           }
889       }
890   }
891
892   /* Adjust the local symbols defined in this section.  */
893   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
894   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
895   if (isym)
896     {
897       for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
898         {
899           if (isym->st_shndx == sec_shndx
900               && isym->st_value > addr && isym->st_value < toaddr)
901             isym->st_value -= count;
902         }
903     }
904
905   /* Now adjust the global symbols defined in this section.  */
906   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
907               - symtab_hdr->sh_info);
908   sym_hashes = start_hashes = elf_sym_hashes (abfd);
909   end_hashes = sym_hashes + symcount;
910
911   for (; sym_hashes < end_hashes; sym_hashes++)
912     {
913       struct elf_link_hash_entry *sym_hash = *sym_hashes;
914
915       /* The '--wrap SYMBOL' option is causing a pain when the object file,
916          containing the definition of __wrap_SYMBOL, includes a direct
917          call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
918          the same symbol (which is __wrap_SYMBOL), but still exist as two
919          different symbols in 'sym_hashes', we don't want to adjust
920          the global symbol __wrap_SYMBOL twice.
921          This check is only relevant when symbols are being wrapped.  */
922       if (link_info->wrap_hash != NULL)
923         {
924           struct elf_link_hash_entry **cur_sym_hashes;
925
926           /* Loop only over the symbols whom been already checked.  */
927           for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
928                cur_sym_hashes++)
929             /* If the current symbol is identical to 'sym_hash', that means
930                the symbol was already adjusted (or at least checked).  */
931             if (*cur_sym_hashes == sym_hash)
932               break;
933
934           /* Don't adjust the symbol again.  */
935           if (cur_sym_hashes < sym_hashes)
936             continue;
937         }
938
939       if ((sym_hash->root.type == bfd_link_hash_defined
940            || sym_hash->root.type == bfd_link_hash_defweak)
941           && sym_hash->root.u.def.section == sec
942           && sym_hash->root.u.def.value > addr
943           && sym_hash->root.u.def.value < toaddr)
944         sym_hash->root.u.def.value -= count;
945     }
946
947   return TRUE;
948 }
949
950 /* Return TRUE if LOC can be a target of a branch, jump or call.  */
951
952 static bfd_boolean
953 elf32_ft32_relax_is_branch_target (struct bfd_link_info *link_info,
954                                    bfd * abfd, asection * sec,
955                                    bfd_vma loc)
956 {
957   Elf_Internal_Shdr *symtab_hdr;
958   Elf_Internal_Rela *irel, *irelend;
959   Elf_Internal_Sym *isym;
960   Elf_Internal_Sym *isymbuf = NULL;
961   bfd_vma symval;
962   struct bfd_section *isec;
963
964   struct elf_link_hash_entry **sym_hashes;
965   struct elf_link_hash_entry **end_hashes;
966   struct elf_link_hash_entry **start_hashes;
967   unsigned int symcount;
968
969   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
970
971   /* Now we check for relocations pointing to ret.  */
972   for (isec = abfd->sections; isec; isec = isec->next)
973     {
974       irel = elf_section_data (isec)->relocs;
975       if (irel == NULL)
976         irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
977
978       irelend = irel + isec->reloc_count;
979
980       for (; irel < irelend; irel++)
981         {
982           /* Read this BFD's local symbols if we haven't done
983              so already.  */
984           if (isymbuf == NULL && symtab_hdr->sh_info != 0)
985             {
986               isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
987               if (isymbuf == NULL)
988                 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
989                                                 symtab_hdr->sh_info, 0,
990                                                 NULL, NULL, NULL);
991               if (isymbuf == NULL)
992                 return FALSE;
993             }
994
995           /* Get the value of the symbol referred to by the reloc.  */
996           if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
997             {
998               /* A local symbol.  */
999               asection *sym_sec;
1000
1001               isym = isymbuf + ELF32_R_SYM (irel->r_info);
1002               sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1003               symval = isym->st_value;
1004               /* If the reloc is absolute, it will not have
1005                  a symbol or section associated with it.  */
1006               if (sym_sec == sec)
1007                 {
1008                   symval += sym_sec->output_section->vma
1009                             + sym_sec->output_offset;
1010
1011                   if (debug_relax)
1012                     printf ("0x%x: Address of anchor symbol: 0x%x "
1013                             "Address of relocation target: 0x%x \n",
1014                             (unsigned int) irel->r_offset,
1015                             (unsigned int) symval,
1016                             (unsigned int) (symval + irel->r_addend));
1017                   if ((irel->r_addend) == loc)
1018                     return TRUE;
1019                 }
1020             }
1021         }
1022     }
1023
1024   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1025                - symtab_hdr->sh_info);
1026   sym_hashes = start_hashes = elf_sym_hashes (abfd);
1027   end_hashes = sym_hashes + symcount;
1028
1029   for (; sym_hashes < end_hashes; sym_hashes++)
1030     {
1031       struct elf_link_hash_entry *sym_hash = *sym_hashes;
1032
1033       /* The '--wrap SYMBOL' option is causing a pain when the object file,
1034          containing the definition of __wrap_SYMBOL, includes a direct
1035          call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
1036          the same symbol (which is __wrap_SYMBOL), but still exist as two
1037          different symbols in 'sym_hashes', we don't want to adjust
1038          the global symbol __wrap_SYMBOL twice.
1039          This check is only relevant when symbols are being wrapped.  */
1040       if (link_info->wrap_hash != NULL)
1041         {
1042           struct elf_link_hash_entry **cur_sym_hashes;
1043
1044           /* Loop only over the symbols whom been already checked.  */
1045           for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
1046                cur_sym_hashes++)
1047             /* If the current symbol is identical to 'sym_hash', that means
1048                the symbol was already adjusted (or at least checked).  */
1049             if (*cur_sym_hashes == sym_hash)
1050               break;
1051
1052           /* Don't adjust the symbol again.  */
1053           if (cur_sym_hashes < sym_hashes)
1054             continue;
1055         }
1056
1057       if ((sym_hash->root.type == bfd_link_hash_defined
1058           || sym_hash->root.type == bfd_link_hash_defweak)
1059           && sym_hash->root.u.def.section == sec
1060           && sym_hash->root.u.def.value == loc)
1061         return TRUE;
1062     }
1063
1064   return FALSE;
1065 }
1066
1067 static bfd_boolean
1068 ft32_elf_relax_section
1069     (bfd *                  abfd,
1070      asection *             sec,
1071      struct bfd_link_info * link_info,
1072      bfd_boolean *          again)
1073 {
1074   Elf_Internal_Rela * free_relocs = NULL;
1075   Elf_Internal_Rela * internal_relocs;
1076   Elf_Internal_Rela * irelend;
1077   Elf_Internal_Rela * irel;
1078   bfd_byte *          contents = NULL;
1079   Elf_Internal_Shdr * symtab_hdr;
1080   Elf_Internal_Sym *  isymbuf = NULL;
1081
1082   /* Assume nothing changes.  */
1083   *again = FALSE;
1084
1085   /* We don't have to do anything for a relocatable link, if
1086      this section does not have relocs, or if this is not a
1087      code section.  */
1088   if (bfd_link_relocatable (link_info)
1089       || (sec->flags & SEC_RELOC) == 0
1090       || sec->reloc_count == 0
1091       || (sec->flags & SEC_CODE) == 0)
1092     return TRUE;
1093
1094   /* Get the section contents.  */
1095   if (elf_section_data (sec)->this_hdr.contents != NULL)
1096     contents = elf_section_data (sec)->this_hdr.contents;
1097   /* Go get them off disk.  */
1098   else
1099     {
1100       if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1101         goto error_return;
1102       elf_section_data (sec)->this_hdr.contents = contents;
1103     }
1104
1105   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1106
1107   /* Read this BFD's local symbols if we haven't done so already.  */
1108   if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1109     {
1110       isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1111       if (isymbuf == NULL)
1112         isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1113                                         symtab_hdr->sh_info, 0,
1114                                         NULL, NULL, NULL);
1115       if (isymbuf == NULL)
1116         goto error_return;
1117       symtab_hdr->contents = (unsigned char *) isymbuf;
1118     }
1119
1120   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1121                                                link_info->keep_memory);
1122   if (internal_relocs == NULL)
1123     goto error_return;
1124   if (! link_info->keep_memory)
1125     free_relocs = internal_relocs;
1126
1127   /* Walk through them looking for relaxing opportunities.  */
1128   irelend = internal_relocs + sec->reloc_count;
1129
1130   /* Test every adjacent pair of relocs. If both have shortcodes,
1131      fuse them and delete the relocs.  */
1132   irel = internal_relocs;
1133   while (irel < irelend - 1)
1134     {
1135       Elf_Internal_Rela * irel_next = irel + 1;
1136       unsigned int sc0, sc1;
1137       bfd_vma pc;
1138
1139       pc = irel->r_offset;
1140
1141       if (((pc + 4) == (irel_next->r_offset))
1142           && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc, irel,
1143                                    &sc0)
1144           && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc,
1145                                    irel_next, &sc1)
1146           && !elf32_ft32_relax_is_branch_target (link_info, abfd, sec,
1147                                                  irel_next->r_offset))
1148         {
1149           unsigned int code30 = (sc1 << 15) | sc0;
1150           unsigned int code27 = code30 >> 3;
1151           unsigned int code3 = code30 & 7;
1152           static const unsigned char pat3[] = {2, 3, 4, 5, 6, 9, 10, 14};
1153           unsigned int pattern = pat3[code3];
1154           unsigned int fused = (pattern << 27) | code27;
1155
1156           /* Move second reloc to same place as first.  */
1157           irel_next->r_offset = irel->r_offset;
1158
1159           /* Change both relocs to R_FT32_NONE.  */
1160
1161           if (ELF32_R_TYPE (irel->r_info) == R_FT32_18)
1162             {
1163               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1164                                            R_FT32_SC0);
1165             }
1166           else
1167             {
1168               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1169                                            R_FT32_NONE);
1170             }
1171
1172           if (ELF32_R_TYPE (irel_next->r_info) == R_FT32_18)
1173             {
1174               irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel_next->r_info),
1175                                                 R_FT32_SC1);
1176             }
1177           else
1178             {
1179               irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1180                                                 R_FT32_NONE);
1181             }
1182
1183           /* Replace the first insn with the fused version.  */
1184           bfd_put_32 (abfd, fused, contents + irel->r_offset);
1185
1186           /* Delete the second insn.  */
1187           if (!elf32_ft32_relax_delete_bytes (link_info, abfd, sec,
1188                                                irel->r_offset + 4, 4))
1189             goto error_return;
1190
1191           /* That will change things, so, we should relax again.
1192              Note that this is not required, and it may be slow.  */
1193           *again = TRUE;
1194
1195           irel += 2;
1196         }
1197       else
1198         {
1199           irel += 1;
1200         }
1201     }
1202
1203   if (isymbuf != NULL
1204       && symtab_hdr->contents != (unsigned char *) isymbuf)
1205     {
1206       if (! link_info->keep_memory)
1207         free (isymbuf);
1208       else
1209        /* Cache the symbols for elf_link_input_bfd.  */
1210        symtab_hdr->contents = (unsigned char *) isymbuf;
1211     }
1212
1213   if (contents != NULL
1214       && elf_section_data (sec)->this_hdr.contents != contents)
1215     {
1216       if (! link_info->keep_memory)
1217         free (contents);
1218       else
1219        /* Cache the section contents for elf_link_input_bfd.  */
1220        elf_section_data (sec)->this_hdr.contents = contents;
1221
1222     }
1223
1224   if (internal_relocs != NULL
1225       && elf_section_data (sec)->relocs != internal_relocs)
1226     free (internal_relocs);
1227
1228   return TRUE;
1229
1230  error_return:
1231   if (free_relocs != NULL)
1232     free (free_relocs);
1233
1234   return TRUE;
1235 }
1236 \f
1237 #define ELF_ARCH                bfd_arch_ft32
1238 #define ELF_MACHINE_CODE        EM_FT32
1239 #define ELF_MAXPAGESIZE         0x1
1240
1241 #define TARGET_LITTLE_SYM       ft32_elf32_vec
1242 #define TARGET_LITTLE_NAME      "elf32-ft32"
1243
1244 #define elf_info_to_howto_rel                   NULL
1245 #define elf_info_to_howto                       ft32_info_to_howto_rela
1246 #define elf_backend_relocate_section            ft32_elf_relocate_section
1247
1248 #define elf_backend_can_gc_sections             1
1249 #define elf_backend_rela_normal                 1
1250
1251 #define bfd_elf32_bfd_reloc_type_lookup         ft32_reloc_type_lookup
1252 #define bfd_elf32_bfd_reloc_name_lookup         ft32_reloc_name_lookup
1253
1254 #define bfd_elf32_bfd_relax_section             ft32_elf_relax_section
1255
1256 #include "elf32-target.h"