1228753Smm/* ft32-specific support for 32-bit ELF.
2228753Smm   Copyright (C) 2013-2020 Free Software Foundation, Inc.
3228753Smm
4228753Smm   Copied from elf32-moxie.c which is..
5228753Smm   Copyright (C) 2009-2020 Free Software Foundation, Inc.
6228753Smm   Free Software Foundation, Inc.
7228753Smm
8228753Smm   This file is part of BFD, the Binary File Descriptor library.
9228753Smm
10228753Smm   This program is free software; you can redistribute it and/or modify
11228753Smm   it under the terms of the GNU General Public License as published by
12228753Smm   the Free Software Foundation; either version 3 of the License, or
13228753Smm   (at your option) any later version.
14228753Smm
15228753Smm   This program is distributed in the hope that it will be useful,
16228753Smm   but WITHOUT ANY WARRANTY; without even the implied warranty of
17228753Smm   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18228753Smm   GNU General Public License for more details.
19228753Smm
20228753Smm   You should have received a copy of the GNU General Public License
21228753Smm   along with this program; if not, write to the Free Software
22228753Smm   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23228753Smm   MA 02110-1301, USA.  */
24228753Smm
25228753Smm#include "sysdep.h"
26228753Smm#include "bfd.h"
27228763Smm#include "libbfd.h"
28228753Smm#include "elf-bfd.h"
29228753Smm#include "elf/ft32.h"
30228753Smm#include "opcode/ft32.h"
31228753Smm
32228753Smmstatic bfd_boolean debug_relax = FALSE;
33228753Smm
34228753Smmstatic bfd_reloc_status_type
35228753Smmbfd_elf_ft32_diff_reloc (bfd *, arelent *, asymbol *, void *,
36228753Smm			asection *, bfd *, char **);
37228753Smm
38228753Smmstatic reloc_howto_type ft32_elf_howto_table [] =
39228753Smm{
40228753Smm  /* This reloc does nothing.  */
41228753Smm  HOWTO (R_FT32_NONE,		/* type */
42228753Smm	 0,			/* rightshift */
43228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
44228753Smm	 32,			/* bitsize */
45228753Smm	 FALSE,			/* pc_relative */
46228753Smm	 0,			/* bitpos */
47228753Smm	 complain_overflow_bitfield, /* complain_on_overflow */
48228753Smm	 bfd_elf_generic_reloc,	/* special_function */
49228753Smm	 "R_FT32_NONE",		/* name */
50228753Smm	 FALSE,			/* partial_inplace */
51228753Smm	 0,			/* src_mask */
52228753Smm	 0,			/* dst_mask */
53228753Smm	 FALSE),		/* pcrel_offset */
54228753Smm
55228753Smm  /* A 32 bit absolute relocation.  */
56228753Smm
57228753Smm  HOWTO (R_FT32_32,		/* type */
58228753Smm	 0,			/* rightshift */
59228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
60228753Smm	 32,			/* bitsize */
61228753Smm	 FALSE,			/* pc_relative */
62228753Smm	 0,			/* bitpos */
63228753Smm	 complain_overflow_bitfield, /* complain_on_overflow */
64228753Smm	 bfd_elf_generic_reloc,	/* special_function */
65228753Smm	 "R_FT32_32",		/* name */
66228753Smm	 FALSE,			/* partial_inplace */
67228753Smm	 0x00000000,		/* src_mask */
68228753Smm	 0xffffffff,		/* dst_mask */
69228753Smm	 FALSE),		/* pcrel_offset */
70228753Smm
71228753Smm  HOWTO (R_FT32_16,		/* type */
72228753Smm	 0,			/* rightshift */
73228753Smm	 1,			/* size (0 = byte, 1 = short, 2 = long) */
74228753Smm	 16,			/* bitsize */
75228753Smm	 FALSE,			/* pc_relative */
76228753Smm	 0,			/* bitpos */
77228753Smm	 complain_overflow_dont, /* complain_on_overflow */
78228753Smm	 bfd_elf_generic_reloc,	/* special_function */
79228753Smm	 "R_FT32_16",		/* name */
80228753Smm	 FALSE,			/* partial_inplace */
81228753Smm	 0x00000000,		/* src_mask */
82228753Smm	 0x0000ffff,		/* dst_mask */
83228753Smm	 FALSE),		/* pcrel_offset */
84228753Smm
85228753Smm  HOWTO (R_FT32_8,		/* type */
86228753Smm	 0,			/* rightshift */
87228753Smm	 0,			/* size (0 = byte, 1 = short, 2 = long) */
88228753Smm	 8,			/* bitsize */
89228753Smm	 FALSE,			/* pc_relative */
90228753Smm	 0,			/* bitpos */
91228753Smm	 complain_overflow_signed, /* complain_on_overflow */
92228753Smm	 bfd_elf_generic_reloc,	/* special_function */
93228753Smm	 "R_FT32_8",		/* name */
94228753Smm	 FALSE,			/* partial_inplace */
95228753Smm	 0x00000000,		/* src_mask */
96228753Smm	 0x000000ff,		/* dst_mask */
97228753Smm	 FALSE),		/* pcrel_offset */
98228753Smm
99228753Smm  HOWTO (R_FT32_10,		/* type */
100228753Smm	 0,			/* rightshift */
101228753Smm	 1,			/* size (0 = byte, 1 = short, 2 = long) */
102228753Smm	 10,			/* bitsize */
103228753Smm	 FALSE,			/* pc_relative */
104228753Smm	 4,			/* bitpos */
105228753Smm	 complain_overflow_bitfield, /* complain_on_overflow */
106228753Smm	 bfd_elf_generic_reloc,	/* special_function */
107228753Smm	 "R_FT32_10",		/* name */
108228753Smm	 FALSE,			/* partial_inplace */
109228753Smm	 0x00000000,		/* src_mask */
110228753Smm	 0x00003ff0,		/* dst_mask */
111228753Smm	 FALSE),		/* pcrel_offset */
112228753Smm
113228753Smm  HOWTO (R_FT32_20,		/* type */
114228753Smm	 0,			/* rightshift */
115228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
116228753Smm	 20,			/* bitsize */
117228753Smm	 FALSE,			/* pc_relative */
118228753Smm	 0,			/* bitpos */
119228753Smm	 complain_overflow_dont, /* complain_on_overflow */
120228753Smm	 bfd_elf_generic_reloc,	/* special_function */
121228753Smm	 "R_FT32_20",		/* name */
122228753Smm	 FALSE,			/* partial_inplace */
123228753Smm	 0x00000000,		/* src_mask */
124228753Smm	 0x000fffff,		/* dst_mask */
125228753Smm	 FALSE),		/* pcrel_offset */
126228753Smm
127228753Smm  HOWTO (R_FT32_17,		/* type */
128228753Smm	 0,			/* rightshift */
129228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
130228753Smm	 17,			/* bitsize */
131228753Smm	 FALSE,			/* pc_relative */
132228753Smm	 0,			/* bitpos */
133228753Smm	 complain_overflow_dont, /* complain_on_overflow */
134228753Smm	 bfd_elf_generic_reloc,	/* special_function */
135228753Smm	 "R_FT32_17",		/* name */
136228753Smm	 FALSE,			/* partial_inplace */
137228753Smm	 0x00000000,		/* src_mask */
138228753Smm	 0x0001ffff,		/* dst_mask */
139228753Smm	 FALSE),		/* pcrel_offset */
140228753Smm
141228753Smm  HOWTO (R_FT32_18,		/* type */
142228753Smm	 2,			/* rightshift */
143228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
144228753Smm	 18,			/* bitsize */
145228753Smm	 FALSE,			/* pc_relative */
146228753Smm	 0,			/* bitpos */
147228753Smm	 complain_overflow_dont, /* complain_on_overflow */
148228753Smm	 bfd_elf_generic_reloc,	/* special_function */
149228753Smm	 "R_FT32_18",		/* name */
150228753Smm	 FALSE,			/* partial_inplace */
151228753Smm	 0x00000000,		/* src_mask */
152228753Smm	 0x0003ffff,		/* dst_mask */
153228753Smm	 FALSE),		/* pcrel_offset */
154228753Smm
155228753Smm  HOWTO (R_FT32_RELAX,		/* type */
156228753Smm	 0,			/* rightshift */
157228753Smm	 1,			/* size (0 = byte, 1 = short, 2 = long) */
158228753Smm	 10,			/* bitsize */
159228753Smm	 FALSE,			/* pc_relative */
160228753Smm	 4,			/* bitpos */
161228753Smm	 complain_overflow_signed, /* complain_on_overflow */
162228753Smm	 bfd_elf_generic_reloc,	/* special_function */
163228753Smm	 "R_FT32_RELAX",	/* name */
164228753Smm	 FALSE,			/* partial_inplace */
165228753Smm	 0x00000000,		/* src_mask */
166228753Smm	 0x00000000,		/* dst_mask */
167228753Smm	 FALSE),		/* pcrel_offset */
168228753Smm
169228753Smm  HOWTO (R_FT32_SC0,		/* type */
170228753Smm	 0,			/* rightshift */
171228753Smm	 1,			/* size (0 = byte, 1 = short, 2 = long) */
172228753Smm	 10,			/* bitsize */
173228753Smm	 FALSE,			/* pc_relative */
174228753Smm	 4,			/* bitpos */
175228753Smm	 complain_overflow_signed, /* complain_on_overflow */
176228753Smm	 bfd_elf_generic_reloc,	/* special_function */
177228753Smm	 "R_FT32_SC0",		/* name */
178228753Smm	 FALSE,			/* partial_inplace */
179228753Smm	 0x00000000,		/* src_mask */
180228753Smm	 0x00000000,		/* dst_mask */
181228753Smm	 FALSE),		/* pcrel_offset */
182228753Smm  HOWTO (R_FT32_SC1,		/* type */
183228753Smm	 2,			/* rightshift */
184228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
185228753Smm	 22,			/* bitsize */
186228753Smm	 TRUE,			/* pc_relative */
187228753Smm	 7,			/* bitpos */
188228753Smm	 complain_overflow_dont, /* complain_on_overflow */
189228753Smm	 bfd_elf_generic_reloc,	/* special_function */
190228753Smm	 "R_FT32_SC1",		/* name */
191228753Smm	 TRUE,			/* partial_inplace */
192228753Smm	 0x07ffff80,		/* src_mask */
193228753Smm	 0x07ffff80,		/* dst_mask */
194228753Smm	 FALSE),		/* pcrel_offset */
195228753Smm  HOWTO (R_FT32_15,		/* type */
196228753Smm	 0,			/* rightshift */
197228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
198228753Smm	 15,			/* bitsize */
199228753Smm	 FALSE,			/* pc_relative */
200228753Smm	 0,			/* bitpos */
201228753Smm	 complain_overflow_dont, /* complain_on_overflow */
202228753Smm	 bfd_elf_generic_reloc,	/* special_function */
203228753Smm	 "R_FT32_15",		/* name */
204228753Smm	 FALSE,			/* partial_inplace */
205228753Smm	 0x00000000,		/* src_mask */
206228753Smm	 0x00007fff,		/* dst_mask */
207228753Smm	 FALSE),		/* pcrel_offset */
208228753Smm  HOWTO (R_FT32_DIFF32,		/* type */
209228753Smm	 0,			/* rightshift */
210228753Smm	 2,			/* size (0 = byte, 1 = short, 2 = long) */
211228753Smm	 32,			/* bitsize */
212228753Smm	 FALSE,			/* pc_relative */
213228753Smm	 0,			/* bitpos */
214228753Smm	 complain_overflow_dont, /* complain_on_overflow */
215228753Smm	 bfd_elf_ft32_diff_reloc, /* special_function */
216228753Smm	 "R_FT32_DIFF32",	/* name */
217228753Smm	 FALSE,			/* partial_inplace */
218228753Smm	 0,			/* src_mask */
219228753Smm	 0xffffffff,		/* dst_mask */
220228753Smm	 FALSE),		/* pcrel_offset */
221228753Smm};
222228753Smm
223228753Smm
224228753Smm/* Map BFD reloc types to FT32 ELF reloc types.  */
225228753Smm
226228753Smmstruct ft32_reloc_map
227228753Smm{
228228753Smm  bfd_reloc_code_real_type bfd_reloc_val;
229228753Smm  unsigned int ft32_reloc_val;
230228753Smm};
231228753Smm
232228753Smmstatic const struct ft32_reloc_map ft32_reloc_map [] =
233228753Smm{
234228753Smm  { BFD_RELOC_NONE,		R_FT32_NONE },
235228753Smm  { BFD_RELOC_32,		R_FT32_32 },
236228753Smm  { BFD_RELOC_16,		R_FT32_16 },
237228753Smm  { BFD_RELOC_8,		R_FT32_8 },
238228753Smm  { BFD_RELOC_FT32_10,		R_FT32_10 },
239228753Smm  { BFD_RELOC_FT32_20,		R_FT32_20 },
240228753Smm  { BFD_RELOC_FT32_17,		R_FT32_17 },
241228753Smm  { BFD_RELOC_FT32_18,		R_FT32_18 },
242228753Smm  { BFD_RELOC_FT32_RELAX,	R_FT32_RELAX },
243228753Smm  { BFD_RELOC_FT32_SC0,		R_FT32_SC0 },
244228753Smm  { BFD_RELOC_FT32_SC1,		R_FT32_SC1 },
245228753Smm  { BFD_RELOC_FT32_15,		R_FT32_15 },
246228753Smm  { BFD_RELOC_FT32_DIFF32,	R_FT32_DIFF32 },
247228753Smm};
248228753Smm
249228753Smm/* Perform a diff relocation. Nothing to do, as the difference value is
250228753Smm   already written into the section's contents. */
251228753Smm
252228753Smmstatic bfd_reloc_status_type
253228753Smmbfd_elf_ft32_diff_reloc (bfd *abfd ATTRIBUTE_UNUSED,
254228753Smm		      arelent *reloc_entry ATTRIBUTE_UNUSED,
255228753Smm	      asymbol *symbol ATTRIBUTE_UNUSED,
256228753Smm	      void *data ATTRIBUTE_UNUSED,
257228753Smm	      asection *input_section ATTRIBUTE_UNUSED,
258228753Smm	      bfd *output_bfd ATTRIBUTE_UNUSED,
259228753Smm	      char **error_message ATTRIBUTE_UNUSED)
260228753Smm{
261228753Smm  return bfd_reloc_ok;
262228753Smm}
263228753Smm
264228753Smmstatic reloc_howto_type *
265228753Smmft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
266228753Smm			 bfd_reloc_code_real_type code)
267228753Smm{
268228753Smm  unsigned int i;
269228753Smm
270228753Smm  for (i = sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]);
271228753Smm       --i;)
272228753Smm    if (ft32_reloc_map [i].bfd_reloc_val == code)
273228753Smm      return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val];
274228753Smm
275228753Smm  return NULL;
276228753Smm}
277228753Smm
278228753Smmstatic reloc_howto_type *
279228753Smmft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
280228753Smm{
281228753Smm  unsigned int i;
282228753Smm
283228753Smm  for (i = 0;
284228753Smm       i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]);
285228753Smm       i++)
286228753Smm    if (ft32_elf_howto_table[i].name != NULL
287228753Smm	&& strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0)
288228753Smm      return &ft32_elf_howto_table[i];
289228753Smm
290228753Smm  return NULL;
291228753Smm}
292228753Smm
293228753Smm/* Set the howto pointer for an FT32 ELF reloc.  */
294228753Smm
295228753Smmstatic bfd_boolean
296228753Smmft32_info_to_howto_rela (bfd *abfd,
297228753Smm			  arelent *cache_ptr,
298228753Smm			  Elf_Internal_Rela *dst)
299228753Smm{
300228753Smm  unsigned int r_type;
301228753Smm
302228753Smm  r_type = ELF32_R_TYPE (dst->r_info);
303228753Smm  if (r_type >= (unsigned int) R_FT32_max)
304228753Smm    {
305228753Smm      /* xgettext:c-format */
306228753Smm      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
307228753Smm			  abfd, r_type);
308228753Smm      bfd_set_error (bfd_error_bad_value);
309228753Smm      return FALSE;
310228753Smm    }
311228753Smm
312228753Smm  cache_ptr->howto = & ft32_elf_howto_table [r_type];
313228753Smm  return cache_ptr->howto != NULL;
314228753Smm}
315228753Smm
316228753Smm/* Relocate an FT32 ELF section.
317228753Smm
318228753Smm   The RELOCATE_SECTION function is called by the new ELF backend linker
319228753Smm   to handle the relocations for a section.
320228753Smm
321228753Smm   The relocs are always passed as Rela structures; if the section
322228753Smm   actually uses Rel structures, the r_addend field will always be
323228753Smm   zero.
324228753Smm
325228753Smm   This function is responsible for adjusting the section contents as
326228753Smm   necessary, and (if using Rela relocs and generating a relocatable
327228753Smm   output file) adjusting the reloc addend as necessary.
328228753Smm
329228753Smm   This function does not have to worry about setting the reloc
330228753Smm   address or the reloc symbol index.
331228753Smm
332228753Smm   LOCAL_SYMS is a pointer to the swapped in local symbols.
333228753Smm
334228753Smm   LOCAL_SECTIONS is an array giving the section in the input file
335228753Smm   corresponding to the st_shndx field of each local symbol.
336228753Smm
337228753Smm   The global hash table entry for the global symbols can be found
338228753Smm   via elf_sym_hashes (input_bfd).
339228753Smm
340228753Smm   When generating relocatable output, this function must handle
341228753Smm   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
342228753Smm   going to be the section symbol corresponding to the output
343228753Smm   section, which means that the addend must be adjusted
344228753Smm   accordingly.  */
345228753Smm
346228753Smmstatic bfd_boolean
347228753Smmft32_elf_relocate_section (bfd *output_bfd,
348228753Smm			    struct bfd_link_info *info,
349228753Smm			    bfd *input_bfd,
350228753Smm			    asection *input_section,
351228753Smm			    bfd_byte *contents,
352228753Smm			    Elf_Internal_Rela *relocs,
353228753Smm			    Elf_Internal_Sym *local_syms,
354228753Smm			    asection **local_sections)
355228753Smm{
356228753Smm  Elf_Internal_Shdr *symtab_hdr;
357228753Smm  struct elf_link_hash_entry **sym_hashes;
358228753Smm  Elf_Internal_Rela *rel;
359228753Smm  Elf_Internal_Rela *relend;
360228753Smm
361228753Smm  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
362228753Smm  sym_hashes = elf_sym_hashes (input_bfd);
363228753Smm  relend     = relocs + input_section->reloc_count;
364228753Smm
365228753Smm  for (rel = relocs; rel < relend; rel ++)
366228753Smm    {
367228753Smm      reloc_howto_type *howto;
368228753Smm      unsigned long r_symndx;
369228753Smm      Elf_Internal_Sym *sym;
370228753Smm      asection *sec;
371228753Smm      struct elf_link_hash_entry *h;
372228753Smm      bfd_vma relocation;
373228753Smm      bfd_reloc_status_type r;
374228753Smm      const char *name;
375228753Smm      int r_type;
376228753Smm
377228753Smm      r_type = ELF32_R_TYPE (rel->r_info);
378228753Smm      r_symndx = ELF32_R_SYM (rel->r_info);
379228753Smm      howto  = ft32_elf_howto_table + r_type;
380228753Smm      h      = NULL;
381228753Smm      sym    = NULL;
382228753Smm      sec    = NULL;
383228753Smm
384228753Smm      if (r_symndx < symtab_hdr->sh_info)
385228753Smm	{
386228753Smm	  sym = local_syms + r_symndx;
387228753Smm	  sec = local_sections [r_symndx];
388228753Smm	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
389228753Smm
390228753Smm	  name = bfd_elf_string_from_elf_section
391228753Smm	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
392228753Smm	  name = name == NULL ? bfd_section_name (sec) : name;
393228753Smm	}
394228753Smm      else
395228753Smm	{
396228753Smm	  bfd_boolean unresolved_reloc, warned, ignored;
397228753Smm
398228753Smm	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
399228753Smm				   r_symndx, symtab_hdr, sym_hashes,
400228753Smm				   h, sec, relocation,
401228753Smm				   unresolved_reloc, warned, ignored);
402228753Smm
403228753Smm	  name = h->root.root.string;
404228753Smm	}
405228753Smm
406228753Smm      if (sec != NULL && discarded_section (sec))
407228753Smm	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
408228753Smm					 rel, 1, relend, howto, 0, contents);
409228753Smm
410228753Smm      if (bfd_link_relocatable (info))
411228753Smm	continue;
412228753Smm
413228753Smm      switch (howto->type)
414228753Smm	{
415228753Smm	  case R_FT32_SC0:
416228753Smm	    {
417228753Smm	      unsigned int insn;
418228753Smm	      int offset;
419228753Smm	      unsigned int code15[2];
420228753Smm
421228753Smm	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
422228753Smm	      ft32_split_shortcode (insn, code15);
423228753Smm
424228753Smm	      offset = (int)relocation;
425228753Smm	      offset += (int)(rel->r_addend - rel->r_offset);
426228753Smm	      offset -= (input_section->output_section->vma +
427228753Smm			 input_section->output_offset);
428228753Smm	      if ((offset < -1024) || (offset >= 1024))
429228753Smm		{
430228753Smm		  r = bfd_reloc_outofrange;
431228753Smm		  break;
432228753Smm		}
433228753Smm	      code15[0] |= ((offset / 4) & 511);
434228753Smm	      insn = ft32_merge_shortcode (code15);
435228753Smm	      bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
436228753Smm	    }
437228753Smm	    r = bfd_reloc_ok;
438228753Smm	    break;
439228753Smm
440228753Smm	  case R_FT32_SC1:
441228753Smm	    {
442228753Smm	      unsigned int insn;
443228753Smm	      int offset;
444228753Smm	      unsigned int code15[2];
445228753Smm
446228753Smm	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
447228753Smm	      ft32_split_shortcode (insn, code15);
448228753Smm
449228753Smm	      offset = (int)relocation;
450228753Smm	      offset += (int)(rel->r_addend - rel->r_offset);
451228753Smm	      offset -= (input_section->output_section->vma +
452228753Smm			 input_section->output_offset);
453228753Smm	      if ((offset < -1024) || (offset >= 1024))
454		{
455		  r = bfd_reloc_outofrange;
456		  break;
457		}
458	      code15[1] |= ((offset / 4) & 511);
459	      insn = ft32_merge_shortcode (code15);
460	      bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
461	    }
462	    r = bfd_reloc_ok;
463	    break;
464
465	  case R_FT32_DIFF32:
466	    r = bfd_reloc_ok;
467	    break;
468
469	  default:
470	    r = _bfd_final_link_relocate (howto, input_bfd, input_section,
471					  contents, rel->r_offset,
472					  relocation, rel->r_addend);
473	    break;
474	}
475
476      if (r != bfd_reloc_ok)
477	{
478	  const char * msg = NULL;
479
480	  switch (r)
481	    {
482	    case bfd_reloc_overflow:
483	      (*info->callbacks->reloc_overflow)
484		(info, (h ? &h->root : NULL), name, howto->name,
485		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
486	      break;
487
488	    case bfd_reloc_undefined:
489	      (*info->callbacks->undefined_symbol)
490		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
491	      break;
492
493	    case bfd_reloc_outofrange:
494	      msg = _("internal error: out of range error");
495	      break;
496
497	    case bfd_reloc_notsupported:
498	      msg = _("internal error: unsupported relocation error");
499	      break;
500
501	    case bfd_reloc_dangerous:
502	      msg = _("internal error: dangerous relocation");
503	      break;
504
505	    default:
506	      msg = _("internal error: unknown error");
507	      break;
508	    }
509
510	  if (msg)
511	    (*info->callbacks->warning) (info, msg, name, input_bfd,
512					 input_section, rel->r_offset);
513	}
514    }
515
516  return TRUE;
517}
518
519/* Relaxation.  */
520
521static bfd_boolean
522ft32_reloc_shortable
523    (bfd *		    abfd,
524     asection *		    sec,
525     Elf_Internal_Sym *	    isymbuf ATTRIBUTE_UNUSED,
526     bfd_byte *		    contents,
527     bfd_vma		    pc ATTRIBUTE_UNUSED,
528     Elf_Internal_Rela *    irel,
529     unsigned int *	    sc)
530{
531  Elf_Internal_Shdr *symtab_hdr ATTRIBUTE_UNUSED;
532  bfd_vma symval;
533
534  enum elf_ft32_reloc_type r_type;
535  reloc_howto_type *howto = NULL;
536  unsigned int insn;
537  int offset;
538  bfd_vma dot, value;
539
540  r_type = ELF32_R_TYPE (irel->r_info);
541  howto = &ft32_elf_howto_table [r_type];
542
543  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
544
545  /* Get the value of the symbol referred to by the reloc.  */
546  if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
547    {
548      /* A local symbol.  */
549      Elf_Internal_Sym *isym;
550      asection *sym_sec;
551
552      isym = isymbuf + ELF32_R_SYM (irel->r_info);
553      sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
554      symval = isym->st_value;
555      /* If the reloc is absolute, it will not have
556	 a symbol or section associated with it.  */
557      if (sym_sec)
558	symval += sym_sec->output_section->vma
559	  + sym_sec->output_offset;
560    }
561  else
562    {
563      unsigned long indx;
564      struct elf_link_hash_entry *h;
565
566      /* An external symbol.  */
567      indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
568      h = elf_sym_hashes (abfd)[indx];
569      BFD_ASSERT (h != NULL);
570      if (h->root.type != bfd_link_hash_defined
571	  && h->root.type != bfd_link_hash_defweak)
572	/* This appears to be a reference to an undefined
573	   symbol.  Just ignore it--it will be caught by the
574	   regular reloc processing.  */
575	return FALSE;
576
577      symval = (h->root.u.def.value
578		+ h->root.u.def.section->output_section->vma
579		+ h->root.u.def.section->output_offset);
580    }
581
582  switch (r_type)
583    {
584      case R_FT32_8:
585      case R_FT32_10:
586      case R_FT32_16:
587      case R_FT32_20:
588      case R_FT32_RELAX:
589	if (symval != 0)
590	  return FALSE;
591	insn = bfd_get_32 (abfd, contents + irel->r_offset);
592	insn |= ((symval + irel->r_addend) << howto->bitpos) & howto->dst_mask;
593	return ft32_shortcode (insn, sc);
594
595      case R_FT32_18:
596	insn = bfd_get_32 (abfd, contents + irel->r_offset);
597	/* Get the address of this instruction.  */
598	dot = (sec->output_section->vma
599	       + sec->output_offset + irel->r_offset);
600	value = symval + irel->r_addend;
601	offset = (value - dot) / 4;
602
603	if ((dot > 0x8c) && (-256 <= offset) && (offset < 256))
604	  {
605	    switch (insn)
606	      {
607		case 0x00200000: *sc = (3 << 13) | (0  << 9); return TRUE;
608		case 0x00280000: *sc = (3 << 13) | (1  << 9); return TRUE;
609		case 0x00600000: *sc = (3 << 13) | (2  << 9); return TRUE;
610		case 0x00680000: *sc = (3 << 13) | (3  << 9); return TRUE;
611		case 0x00a00000: *sc = (3 << 13) | (4  << 9); return TRUE;
612		case 0x00a80000: *sc = (3 << 13) | (5  << 9); return TRUE;
613		case 0x00e00000: *sc = (3 << 13) | (6  << 9); return TRUE;
614		case 0x00e80000: *sc = (3 << 13) | (7  << 9); return TRUE;
615		case 0x01200000: *sc = (3 << 13) | (8  << 9); return TRUE;
616		case 0x01280000: *sc = (3 << 13) | (9  << 9); return TRUE;
617		case 0x01600000: *sc = (3 << 13) | (10 << 9); return TRUE;
618		case 0x01680000: *sc = (3 << 13) | (11 << 9); return TRUE;
619		case 0x01a00000: *sc = (3 << 13) | (12 << 9); return TRUE;
620		case 0x01a80000: *sc = (3 << 13) | (13 << 9); return TRUE;
621
622		case 0x00300000: *sc = (3 << 13) | (14 << 9); return TRUE;
623		case 0x00340000: *sc = (3 << 13) | (15 << 9); return TRUE;
624
625		default:
626		  break;
627	      }
628	  }
629	break;
630
631      default:
632	break;
633    }
634  return FALSE;
635}
636
637/* Returns whether the relocation type passed is a diff reloc.  */
638
639static bfd_boolean
640elf32_ft32_is_diff_reloc (Elf_Internal_Rela *irel)
641{
642  return (ELF32_R_TYPE (irel->r_info) == R_FT32_DIFF32);
643}
644
645/* Reduce the diff value written in the section by count if the shrinked
646   insn address happens to fall between the two symbols for which this
647   diff reloc was emitted.  */
648
649static bfd_boolean
650elf32_ft32_adjust_diff_reloc_value (bfd *abfd,
651				   struct bfd_section *isec,
652				   Elf_Internal_Rela *irel,
653				   bfd_vma symval,
654				   bfd_vma shrinked_insn_address,
655				   int count)
656{
657  unsigned char * reloc_contents = NULL;
658  unsigned char * isec_contents = elf_section_data (isec)->this_hdr.contents;
659  bfd_signed_vma x = 0;
660  bfd_vma sym2_address;
661  bfd_vma sym1_address;
662  bfd_vma start_address;
663  bfd_vma end_address;
664
665
666  if (isec_contents == NULL)
667    {
668      if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
669	return FALSE;
670
671      elf_section_data (isec)->this_hdr.contents = isec_contents;
672    }
673
674  reloc_contents = isec_contents + irel->r_offset;
675
676  /* Read value written in object file.  */
677  switch (ELF32_R_TYPE (irel->r_info))
678    {
679    case R_FT32_DIFF32:
680      x = bfd_get_signed_32 (abfd, reloc_contents);
681      break;
682
683    default:
684      return FALSE;
685    }
686
687  /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
688     into the object file at the reloc offset. sym2's logical value is
689     symval (<start_of_section>) + reloc addend. Compute the start and end
690     addresses and check if the shrinked insn falls between sym1 and sym2.  */
691  sym2_address = symval + irel->r_addend;
692  sym1_address = sym2_address - x;
693
694  /* Don't assume sym2 is bigger than sym1 - the difference
695     could be negative. Compute start and end addresses, and
696     use those to see if they span shrinked_insn_address.  */
697  start_address = sym1_address < sym2_address ? sym1_address : sym2_address;
698  end_address = sym1_address > sym2_address ? sym1_address : sym2_address;
699
700  if (shrinked_insn_address >= start_address
701      && shrinked_insn_address < end_address)
702    {
703      /* Reduce the diff value by count bytes and write it back into section
704	 contents.  */
705      bfd_signed_vma new_diff = x < 0 ? x + count : x - count;
706
707      if (sym2_address > shrinked_insn_address)
708	irel->r_addend -= count;
709
710      switch (ELF32_R_TYPE (irel->r_info))
711	{
712	case R_FT32_DIFF32:
713	  bfd_put_signed_32 (abfd, new_diff & 0xFFFFFFFF, reloc_contents);
714	  break;
715
716	default:
717	  return FALSE;
718	}
719    }
720
721  return TRUE;
722}
723
724static bfd_boolean
725elf32_ft32_adjust_reloc_if_spans_insn (bfd *abfd,
726				      asection *isec,
727				      Elf_Internal_Rela *irel,  bfd_vma symval,
728				      bfd_vma shrinked_insn_address,
729				      bfd_vma shrink_boundary,
730				      int count)
731{
732
733  if (elf32_ft32_is_diff_reloc (irel))
734    {
735      if (!elf32_ft32_adjust_diff_reloc_value (abfd, isec, irel,
736					       symval,
737					       shrinked_insn_address,
738					       count))
739	return FALSE;
740    }
741  else
742    {
743      bfd_vma reloc_value = symval + irel->r_addend;
744      bfd_boolean addend_within_shrink_boundary =
745	(reloc_value <= shrink_boundary);
746      bfd_boolean reloc_spans_insn =
747	(symval <= shrinked_insn_address
748	 && reloc_value > shrinked_insn_address
749	 && addend_within_shrink_boundary);
750
751      if (! reloc_spans_insn)
752	return TRUE;
753
754      irel->r_addend -= count;
755
756      if (debug_relax)
757	printf ("Relocation's addend needed to be fixed \n");
758    }
759  return TRUE;
760}
761
762/* Delete some bytes from a section while relaxing.  */
763
764static bfd_boolean
765elf32_ft32_relax_delete_bytes (struct bfd_link_info *link_info, bfd * abfd,
766			       asection * sec, bfd_vma addr, int count)
767{
768  Elf_Internal_Shdr *symtab_hdr;
769  unsigned int sec_shndx;
770  bfd_byte *contents;
771  Elf_Internal_Rela *irel, *irelend;
772  bfd_vma toaddr;
773  Elf_Internal_Sym *isym;
774  Elf_Internal_Sym *isymend;
775  struct elf_link_hash_entry **sym_hashes;
776  struct elf_link_hash_entry **end_hashes;
777  struct elf_link_hash_entry **start_hashes;
778  unsigned int symcount;
779  Elf_Internal_Sym *isymbuf = NULL;
780
781  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
782  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
783
784  contents = elf_section_data (sec)->this_hdr.contents;
785
786  toaddr = sec->size;
787
788  irel = elf_section_data (sec)->relocs;
789  irelend = irel + sec->reloc_count;
790
791  /* Actually delete the bytes.  */
792  memmove (contents + addr, contents + addr + count,
793	   (size_t) (toaddr - addr - count));
794  sec->size -= count;
795
796  /* Adjust all the relocs.  */
797  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
798    /* Get the new reloc address.  */
799    if ((irel->r_offset > addr && irel->r_offset < toaddr))
800      irel->r_offset -= count;
801
802  /* The reloc's own addresses are now ok. However, we need to readjust
803     the reloc's addend, i.e. the reloc's value if two conditions are met:
804     1.) the reloc is relative to a symbol in this section that
805     is located in front of the shrinked instruction
806     2.) symbol plus addend end up behind the shrinked instruction.
807
808     The most common case where this happens are relocs relative to
809     the section-start symbol.
810
811     This step needs to be done for all of the sections of the bfd.  */
812  {
813    struct bfd_section *isec;
814
815    for (isec = abfd->sections; isec; isec = isec->next)
816      {
817	bfd_vma symval;
818	bfd_vma shrinked_insn_address;
819
820	if (isec->reloc_count == 0)
821	  continue;
822
823	shrinked_insn_address = (sec->output_section->vma
824				 + sec->output_offset + addr - count);
825
826	irel = elf_section_data (isec)->relocs;
827	/* PR 12161: Read in the relocs for this section if necessary.  */
828	if (irel == NULL)
829	  irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
830
831	for (irelend = irel + isec->reloc_count; irel < irelend; irel++)
832	  {
833	    /* Read this BFD's local symbols if we haven't done
834	       so already.  */
835	    if (isymbuf == NULL && symtab_hdr->sh_info != 0)
836	      {
837		isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
838		if (isymbuf == NULL)
839		  isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
840						  symtab_hdr->sh_info, 0,
841						  NULL, NULL, NULL);
842		if (isymbuf == NULL)
843		  return FALSE;
844	      }
845
846	    /* Get the value of the symbol referred to by the reloc.  */
847	    if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
848	      {
849		/* A local symbol.  */
850		asection *sym_sec;
851
852		isym = isymbuf + ELF32_R_SYM (irel->r_info);
853		sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
854		symval = isym->st_value;
855		/* If the reloc is absolute, it will not have
856		   a symbol or section associated with it.  */
857		if (sym_sec == sec)
858		  {
859		    symval += sym_sec->output_section->vma
860		      + sym_sec->output_offset;
861
862		    if (debug_relax)
863		      printf ("Checking if the relocation's "
864			      "addend needs corrections.\n"
865			      "Address of anchor symbol: 0x%x \n"
866			      "Address of relocation target: 0x%x \n"
867			      "Address of relaxed insn: 0x%x \n",
868			      (unsigned int) symval,
869			      (unsigned int) (symval + irel->r_addend),
870			      (unsigned int) shrinked_insn_address);
871
872		    if (symval <= shrinked_insn_address
873			&& (symval + irel->r_addend) > shrinked_insn_address)
874		      {
875			/* If there is an alignment boundary, we only need to
876			   adjust addends that end up below the boundary. */
877			bfd_vma shrink_boundary = (toaddr
878						   + sec->output_section->vma
879						   + sec->output_offset);
880
881			if (debug_relax)
882			  printf
883			    ("Relocation's addend needed to be fixed \n");
884
885			if (!elf32_ft32_adjust_reloc_if_spans_insn (abfd, isec,
886								    irel, symval,
887								    shrinked_insn_address,
888								    shrink_boundary,
889								    count))
890			  return FALSE;
891		      }
892		  }
893		/* else reference symbol is absolute. No adjustment needed. */
894	      }
895	    /* else...Reference symbol is extern.  No need for adjusting
896	       the addend.  */
897	  }
898      }
899  }
900
901  /* Adjust the local symbols defined in this section.  */
902  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
903  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
904  if (isym)
905    {
906      for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
907	{
908	  if (isym->st_shndx == sec_shndx
909	      && isym->st_value > addr && isym->st_value < toaddr)
910	    isym->st_value -= count;
911	}
912    }
913
914  /* Now adjust the global symbols defined in this section.  */
915  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
916	      - symtab_hdr->sh_info);
917  sym_hashes = start_hashes = elf_sym_hashes (abfd);
918  end_hashes = sym_hashes + symcount;
919
920  for (; sym_hashes < end_hashes; sym_hashes++)
921    {
922      struct elf_link_hash_entry *sym_hash = *sym_hashes;
923
924      /* The '--wrap SYMBOL' option is causing a pain when the object file,
925	 containing the definition of __wrap_SYMBOL, includes a direct
926	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
927	 the same symbol (which is __wrap_SYMBOL), but still exist as two
928	 different symbols in 'sym_hashes', we don't want to adjust
929	 the global symbol __wrap_SYMBOL twice.
930	 This check is only relevant when symbols are being wrapped.  */
931      if (link_info->wrap_hash != NULL)
932	{
933	  struct elf_link_hash_entry **cur_sym_hashes;
934
935	  /* Loop only over the symbols whom been already checked.  */
936	  for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
937	       cur_sym_hashes++)
938	    /* If the current symbol is identical to 'sym_hash', that means
939	       the symbol was already adjusted (or at least checked).  */
940	    if (*cur_sym_hashes == sym_hash)
941	      break;
942
943	  /* Don't adjust the symbol again.  */
944	  if (cur_sym_hashes < sym_hashes)
945	    continue;
946	}
947
948      if ((sym_hash->root.type == bfd_link_hash_defined
949	   || sym_hash->root.type == bfd_link_hash_defweak)
950	  && sym_hash->root.u.def.section == sec
951	  && sym_hash->root.u.def.value > addr
952	  && sym_hash->root.u.def.value < toaddr)
953	sym_hash->root.u.def.value -= count;
954    }
955
956  return TRUE;
957}
958
959/* Return TRUE if LOC can be a target of a branch, jump or call.  */
960
961static bfd_boolean
962elf32_ft32_relax_is_branch_target (struct bfd_link_info *link_info,
963				   bfd * abfd, asection * sec,
964				   bfd_vma loc)
965{
966  Elf_Internal_Shdr *symtab_hdr;
967  Elf_Internal_Rela *irel, *irelend;
968  Elf_Internal_Sym *isym;
969  Elf_Internal_Sym *isymbuf = NULL;
970  bfd_vma symval;
971  struct bfd_section *isec;
972
973  struct elf_link_hash_entry **sym_hashes;
974  struct elf_link_hash_entry **end_hashes;
975  struct elf_link_hash_entry **start_hashes;
976  unsigned int symcount;
977
978  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
979
980  /* Now we check for relocations pointing to ret.  */
981  for (isec = abfd->sections; isec; isec = isec->next)
982    {
983      irel = elf_section_data (isec)->relocs;
984      if (irel == NULL)
985	irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
986
987      irelend = irel + isec->reloc_count;
988
989      for (; irel < irelend; irel++)
990	{
991	  /* Read this BFD's local symbols if we haven't done
992	     so already.  */
993	  if (isymbuf == NULL && symtab_hdr->sh_info != 0)
994	    {
995	      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
996	      if (isymbuf == NULL)
997		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
998						symtab_hdr->sh_info, 0,
999						NULL, NULL, NULL);
1000	      if (isymbuf == NULL)
1001		return FALSE;
1002	    }
1003
1004	  /* Get the value of the symbol referred to by the reloc.  */
1005	  if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1006	    {
1007	      /* A local symbol.  */
1008	      asection *sym_sec;
1009
1010	      isym = isymbuf + ELF32_R_SYM (irel->r_info);
1011	      sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1012	      symval = isym->st_value;
1013	      /* If the reloc is absolute, it will not have
1014		 a symbol or section associated with it.  */
1015	      if (sym_sec == sec)
1016		{
1017		  symval += sym_sec->output_section->vma
1018			    + sym_sec->output_offset;
1019
1020		  if (debug_relax)
1021		    printf ("0x%x: Address of anchor symbol: 0x%x "
1022			    "Address of relocation target: 0x%x \n",
1023			    (unsigned int) irel->r_offset,
1024			    (unsigned int) symval,
1025			    (unsigned int) (symval + irel->r_addend));
1026		  if ((irel->r_addend) == loc)
1027		    return TRUE;
1028		}
1029	    }
1030	}
1031    }
1032
1033  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1034	       - symtab_hdr->sh_info);
1035  sym_hashes = start_hashes = elf_sym_hashes (abfd);
1036  end_hashes = sym_hashes + symcount;
1037
1038  for (; sym_hashes < end_hashes; sym_hashes++)
1039    {
1040      struct elf_link_hash_entry *sym_hash = *sym_hashes;
1041
1042      /* The '--wrap SYMBOL' option is causing a pain when the object file,
1043	 containing the definition of __wrap_SYMBOL, includes a direct
1044	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
1045	 the same symbol (which is __wrap_SYMBOL), but still exist as two
1046	 different symbols in 'sym_hashes', we don't want to adjust
1047	 the global symbol __wrap_SYMBOL twice.
1048	 This check is only relevant when symbols are being wrapped.  */
1049      if (link_info->wrap_hash != NULL)
1050	{
1051	  struct elf_link_hash_entry **cur_sym_hashes;
1052
1053	  /* Loop only over the symbols whom been already checked.  */
1054	  for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
1055	       cur_sym_hashes++)
1056	    /* If the current symbol is identical to 'sym_hash', that means
1057	       the symbol was already adjusted (or at least checked).  */
1058	    if (*cur_sym_hashes == sym_hash)
1059	      break;
1060
1061	  /* Don't adjust the symbol again.  */
1062	  if (cur_sym_hashes < sym_hashes)
1063	    continue;
1064	}
1065
1066      if ((sym_hash->root.type == bfd_link_hash_defined
1067	  || sym_hash->root.type == bfd_link_hash_defweak)
1068	  && sym_hash->root.u.def.section == sec
1069	  && sym_hash->root.u.def.value == loc)
1070	return TRUE;
1071    }
1072
1073  return FALSE;
1074}
1075
1076static bfd_boolean
1077ft32_elf_relax_section
1078    (bfd *		    abfd,
1079     asection *		    sec,
1080     struct bfd_link_info * link_info,
1081     bfd_boolean *	    again)
1082{
1083  Elf_Internal_Rela * free_relocs = NULL;
1084  Elf_Internal_Rela * internal_relocs;
1085  Elf_Internal_Rela * irelend;
1086  Elf_Internal_Rela * irel;
1087  bfd_byte *	      contents = NULL;
1088  Elf_Internal_Shdr * symtab_hdr;
1089  Elf_Internal_Sym *  isymbuf = NULL;
1090
1091  /* Assume nothing changes.  */
1092  *again = FALSE;
1093
1094  /* We don't have to do anything for a relocatable link, if
1095     this section does not have relocs, or if this is not a
1096     code section.  */
1097  if (bfd_link_relocatable (link_info)
1098      || (sec->flags & SEC_RELOC) == 0
1099      || sec->reloc_count == 0
1100      || (sec->flags & SEC_CODE) == 0)
1101    return TRUE;
1102
1103  /* Get the section contents.  */
1104  if (elf_section_data (sec)->this_hdr.contents != NULL)
1105    contents = elf_section_data (sec)->this_hdr.contents;
1106  /* Go get them off disk.  */
1107  else
1108    {
1109      if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1110	goto error_return;
1111      elf_section_data (sec)->this_hdr.contents = contents;
1112    }
1113
1114  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1115
1116  /* Read this BFD's local symbols if we haven't done so already.  */
1117  if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1118    {
1119      isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1120      if (isymbuf == NULL)
1121	isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1122					symtab_hdr->sh_info, 0,
1123					NULL, NULL, NULL);
1124      if (isymbuf == NULL)
1125	goto error_return;
1126      symtab_hdr->contents = (unsigned char *) isymbuf;
1127    }
1128
1129  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1130					       link_info->keep_memory);
1131  if (internal_relocs == NULL)
1132    goto error_return;
1133  if (! link_info->keep_memory)
1134    free_relocs = internal_relocs;
1135
1136  /* Walk through them looking for relaxing opportunities.  */
1137  irelend = internal_relocs + sec->reloc_count;
1138
1139  /* Test every adjacent pair of relocs. If both have shortcodes,
1140     fuse them and delete the relocs.  */
1141  irel = internal_relocs;
1142  while (irel < irelend - 1)
1143    {
1144      Elf_Internal_Rela * irel_next = irel + 1;
1145      unsigned int sc0, sc1;
1146      bfd_vma pc;
1147
1148      pc = irel->r_offset;
1149
1150      if (((pc + 4) == (irel_next->r_offset))
1151	  && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc, irel,
1152				   &sc0)
1153	  && ft32_reloc_shortable (abfd, sec, isymbuf, contents, pc,
1154				   irel_next, &sc1)
1155	  && !elf32_ft32_relax_is_branch_target (link_info, abfd, sec,
1156						 irel_next->r_offset))
1157	{
1158	  unsigned int code30 = (sc1 << 15) | sc0;
1159	  unsigned int code27 = code30 >> 3;
1160	  unsigned int code3 = code30 & 7;
1161	  static const unsigned char pat3[] = {2, 3, 4, 5, 6, 9, 10, 14};
1162	  unsigned int pattern = pat3[code3];
1163	  unsigned int fused = (pattern << 27) | code27;
1164
1165	  /* Move second reloc to same place as first.  */
1166	  irel_next->r_offset = irel->r_offset;
1167
1168	  /* Change both relocs to R_FT32_NONE.  */
1169
1170	  if (ELF32_R_TYPE (irel->r_info) == R_FT32_18)
1171	    {
1172	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1173					   R_FT32_SC0);
1174	    }
1175	  else
1176	    {
1177	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1178					   R_FT32_NONE);
1179	    }
1180
1181	  if (ELF32_R_TYPE (irel_next->r_info) == R_FT32_18)
1182	    {
1183	      irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel_next->r_info),
1184						R_FT32_SC1);
1185	    }
1186	  else
1187	    {
1188	      irel_next->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1189						R_FT32_NONE);
1190	    }
1191
1192	  /* Replace the first insn with the fused version.  */
1193	  bfd_put_32 (abfd, fused, contents + irel->r_offset);
1194
1195	  /* Delete the second insn.  */
1196	  if (!elf32_ft32_relax_delete_bytes (link_info, abfd, sec,
1197					       irel->r_offset + 4, 4))
1198	    goto error_return;
1199
1200	  /* That will change things, so, we should relax again.
1201	     Note that this is not required, and it may be slow.  */
1202	  *again = TRUE;
1203
1204	  irel += 2;
1205	}
1206      else
1207	{
1208	  irel += 1;
1209	}
1210    }
1211
1212  if (isymbuf != NULL
1213      && symtab_hdr->contents != (unsigned char *) isymbuf)
1214    {
1215      if (! link_info->keep_memory)
1216	free (isymbuf);
1217      else
1218       /* Cache the symbols for elf_link_input_bfd.  */
1219       symtab_hdr->contents = (unsigned char *) isymbuf;
1220    }
1221
1222  if (contents != NULL
1223      && elf_section_data (sec)->this_hdr.contents != contents)
1224    {
1225      if (! link_info->keep_memory)
1226	free (contents);
1227      else
1228       /* Cache the section contents for elf_link_input_bfd.  */
1229       elf_section_data (sec)->this_hdr.contents = contents;
1230
1231    }
1232
1233  if (elf_section_data (sec)->relocs != internal_relocs)
1234    free (internal_relocs);
1235
1236  return TRUE;
1237
1238 error_return:
1239  free (free_relocs);
1240
1241  return TRUE;
1242}
1243
1244#define ELF_ARCH		bfd_arch_ft32
1245#define ELF_MACHINE_CODE	EM_FT32
1246#define ELF_MAXPAGESIZE		0x1
1247
1248#define TARGET_LITTLE_SYM       ft32_elf32_vec
1249#define TARGET_LITTLE_NAME	"elf32-ft32"
1250
1251#define elf_info_to_howto_rel			NULL
1252#define elf_info_to_howto			ft32_info_to_howto_rela
1253#define elf_backend_relocate_section		ft32_elf_relocate_section
1254
1255#define elf_backend_can_gc_sections		1
1256#define elf_backend_rela_normal			1
1257
1258#define bfd_elf32_bfd_reloc_type_lookup		ft32_reloc_type_lookup
1259#define bfd_elf32_bfd_reloc_name_lookup		ft32_reloc_name_lookup
1260
1261#define bfd_elf32_bfd_relax_section		ft32_elf_relax_section
1262
1263#include "elf32-target.h"
1264