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