]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf32-ft32.c
Add note about adding ChangeLog.git to src-release.sh
[thirdparty/binutils-gdb.git] / bfd / elf32-ft32.c
CommitLineData
3f8107ab 1/* ft32-specific support for 32-bit ELF.
d87bef3a 2 Copyright (C) 2013-2023 Free Software Foundation, Inc.
3f8107ab
AM
3
4 Copied from elf32-moxie.c which is..
d87bef3a 5 Copyright (C) 2009-2023 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 */
c94cb026 43 0, /* size */
ff50916f 44 0, /* bitsize */
0a1b45a2 45 false, /* pc_relative */
3f8107ab 46 0, /* bitpos */
ff50916f 47 complain_overflow_dont, /* complain_on_overflow */
3f8107ab
AM
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 */
c94cb026 59 4, /* size */
3f8107ab 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 */
c94cb026 73 2, /* size */
3f8107ab 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 */
c94cb026 87 1, /* size */
3f8107ab 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 */
c94cb026 101 2, /* size */
3f8107ab 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 */
c94cb026 115 4, /* size */
3f8107ab 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 */
c94cb026 129 4, /* size */
3f8107ab 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 */
c94cb026 143 4, /* size */
3f8107ab 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 */
c94cb026 157 2, /* size */
81b42bca 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 */
c94cb026 171 2, /* size */
81b42bca 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 */
c94cb026 184 4, /* size */
81b42bca 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 */
c94cb026 197 4, /* size */
3b4b0a62 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 */
c94cb026 210 4, /* size */
07d6d2b8 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
223/* Map BFD reloc types to FT32 ELF reloc types. */
224
225struct ft32_reloc_map
226{
227 bfd_reloc_code_real_type bfd_reloc_val;
228 unsigned int ft32_reloc_val;
229};
230
231static const struct ft32_reloc_map ft32_reloc_map [] =
232{
07d6d2b8
AM
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 },
3f8107ab
AM
246};
247
81b42bca
JB
248/* Perform a diff relocation. Nothing to do, as the difference value is
249 already written into the section's contents. */
250
251static bfd_reloc_status_type
252bfd_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
3f8107ab
AM
263static reloc_howto_type *
264ft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
265 bfd_reloc_code_real_type code)
266{
267 unsigned int i;
268
4287950e 269 for (i = 0; i < sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]); i++)
3f8107ab
AM
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
276static reloc_howto_type *
277ft32_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
0a1b45a2 293static bool
f3185997 294ft32_info_to_howto_rela (bfd *abfd,
3f8107ab
AM
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);
5224fa03 301 if (r_type >= (unsigned int) R_FT32_max)
f3185997
NC
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);
0a1b45a2 307 return false;
f3185997
NC
308 }
309
3f8107ab 310 cache_ptr->howto = & ft32_elf_howto_table [r_type];
f3185997 311 return cache_ptr->howto != NULL;
3f8107ab 312}
81b42bca 313
3f8107ab
AM
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
0f684201 344static int
3f8107ab
AM
345ft32_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);
fd361982 390 name = name == NULL ? bfd_section_name (sec) : name;
3f8107ab
AM
391 }
392 else
393 {
0a1b45a2 394 bool unresolved_reloc, warned, ignored;
3f8107ab
AM
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
0e1862bb 408 if (bfd_link_relocatable (info))
3f8107ab
AM
409 continue;
410
81b42bca
JB
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 }
3f8107ab
AM
473
474 if (r != bfd_reloc_ok)
475 {
476 const char * msg = NULL;
477
478 switch (r)
479 {
480 case bfd_reloc_overflow:
1a72702b 481 (*info->callbacks->reloc_overflow)
3f8107ab
AM
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:
1a72702b 487 (*info->callbacks->undefined_symbol)
0a1b45a2 488 (info, name, input_bfd, input_section, rel->r_offset, true);
3f8107ab
AM
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)
1a72702b
AM
509 (*info->callbacks->warning) (info, msg, name, input_bfd,
510 input_section, rel->r_offset);
3f8107ab
AM
511 }
512 }
513
0a1b45a2 514 return true;
3f8107ab
AM
515}
516\f
81b42bca
JB
517/* Relaxation. */
518
0a1b45a2 519static bool
81b42bca 520ft32_reloc_shortable
07d6d2b8
AM
521 (bfd * abfd,
522 asection * sec,
523 Elf_Internal_Sym * isymbuf ATTRIBUTE_UNUSED,
524 bfd_byte * contents,
525 bfd_vma pc ATTRIBUTE_UNUSED,
81b42bca 526 Elf_Internal_Rela * irel,
07d6d2b8 527 unsigned int * sc)
81b42bca
JB
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. */
0a1b45a2 573 return false;
81b42bca
JB
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)
0a1b45a2 588 return false;
81b42bca
JB
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 {
0a1b45a2
AM
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;
81b42bca
JB
622
623 default:
624 break;
625 }
626 }
627 break;
628
629 default:
630 break;
631 }
0a1b45a2 632 return false;
81b42bca
JB
633}
634
635/* Returns whether the relocation type passed is a diff reloc. */
636
0a1b45a2 637static bool
81b42bca
JB
638elf32_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
0a1b45a2 647static bool
81b42bca
JB
648elf32_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))
0a1b45a2 667 return false;
81b42bca
JB
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:
0a1b45a2 682 return false;
81b42bca
JB
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:
0a1b45a2 715 return false;
81b42bca
JB
716 }
717 }
718
0a1b45a2 719 return true;
81b42bca
JB
720}
721
0a1b45a2 722static bool
81b42bca
JB
723elf32_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,
07d6d2b8
AM
734 symval,
735 shrinked_insn_address,
736 count))
0a1b45a2 737 return false;
81b42bca
JB
738 }
739 else
740 {
741 bfd_vma reloc_value = symval + irel->r_addend;
0a1b45a2 742 bool addend_within_shrink_boundary =
81b42bca 743 (reloc_value <= shrink_boundary);
0a1b45a2 744 bool reloc_spans_insn =
81b42bca
JB
745 (symval <= shrinked_insn_address
746 && reloc_value > shrinked_insn_address
747 && addend_within_shrink_boundary);
748
749 if (! reloc_spans_insn)
0a1b45a2 750 return true;
81b42bca
JB
751
752 irel->r_addend -= count;
753
754 if (debug_relax)
755 printf ("Relocation's addend needed to be fixed \n");
756 }
0a1b45a2 757 return true;
81b42bca
JB
758}
759
760/* Delete some bytes from a section while relaxing. */
761
0a1b45a2 762static bool
81b42bca
JB
763elf32_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)
0a1b45a2 827 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true);
81b42bca
JB
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)
0a1b45a2 841 return false;
81b42bca
JB
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
07d6d2b8
AM
883 if (!elf32_ft32_adjust_reloc_if_spans_insn (abfd, isec,
884 irel, symval,
885 shrinked_insn_address,
886 shrink_boundary,
887 count))
0a1b45a2 888 return false;
81b42bca
JB
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,
07d6d2b8
AM
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. */
81b42bca
JB
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
0a1b45a2 954 return true;
81b42bca
JB
955}
956
957/* Return TRUE if LOC can be a target of a branch, jump or call. */
958
0a1b45a2 959static bool
81b42bca
JB
960elf32_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)
0a1b45a2 983 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true);
81b42bca
JB
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)
0a1b45a2 999 return false;
81b42bca
JB
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
07d6d2b8 1016 + sym_sec->output_offset;
81b42bca
JB
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)
0a1b45a2 1025 return true;
81b42bca
JB
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)
0a1b45a2 1068 return true;
81b42bca
JB
1069 }
1070
0a1b45a2 1071 return false;
81b42bca
JB
1072}
1073
0a1b45a2
AM
1074static bool
1075ft32_elf_relax_section (bfd *abfd,
1076 asection *sec,
1077 struct bfd_link_info *link_info,
1078 bool *again)
81b42bca
JB
1079{
1080 Elf_Internal_Rela * free_relocs = NULL;
1081 Elf_Internal_Rela * internal_relocs;
1082 Elf_Internal_Rela * irelend;
1083 Elf_Internal_Rela * irel;
07d6d2b8 1084 bfd_byte * contents = NULL;
81b42bca
JB
1085 Elf_Internal_Shdr * symtab_hdr;
1086 Elf_Internal_Sym * isymbuf = NULL;
1087
1088 /* Assume nothing changes. */
0a1b45a2 1089 *again = false;
81b42bca
JB
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)
81b42bca 1095 || sec->reloc_count == 0
3a574cce
AM
1096 || (sec->flags & SEC_RELOC) == 0
1097 || (sec->flags & SEC_HAS_CONTENTS) == 0
81b42bca 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"