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