1/* 32-bit ELF support for TI PRU.
2   Copyright (C) 2014-2022 Free Software Foundation, Inc.
3   Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
4   Based on elf32-nios2.c
5
6   This file is part of BFD, the Binary File Descriptor library.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21   MA 02110-1301, USA.  */
22
23/* This file handles TI PRU ELF targets.  */
24
25#include "sysdep.h"
26#include "bfd.h"
27#include "libbfd.h"
28#include "bfdlink.h"
29#include "genlink.h"
30#include "elf-bfd.h"
31#include "elf/pru.h"
32#include "opcode/pru.h"
33#include "libiberty.h"
34
35/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
36#define OCTETS_PER_BYTE(ABFD, SEC) 1
37
38#define SWAP_VALS(A,B)		      \
39  do {				      \
40      (A) ^= (B);		      \
41      (B) ^= (A);		      \
42      (A) ^= (B);		      \
43  } while (0)
44
45/* Enable debugging printout at stdout with this variable.  */
46static bool debug_relax = false;
47
48/* Forward declarations.  */
49static bfd_reloc_status_type pru_elf32_pmem_relocate
50  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
51static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate
52  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
53static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate
54  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
55static bfd_reloc_status_type pru_elf32_ldi32_relocate
56  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
57static bfd_reloc_status_type bfd_elf_pru_diff_relocate
58  (bfd *, arelent *, asymbol *, void *,	asection *, bfd *, char **);
59
60/* Target vector.  */
61extern const bfd_target pru_elf32_vec;
62
63/* The relocation table used for SHT_REL sections.  */
64static reloc_howto_type elf_pru_howto_table_rel[] = {
65  /* No relocation.  */
66  HOWTO (R_PRU_NONE,		/* type */
67	 0,			/* rightshift */
68	 0,			/* size */
69	 0,			/* bitsize */
70	 false,			/* pc_relative */
71	 0,			/* bitpos */
72	 complain_overflow_dont,/* complain_on_overflow */
73	 bfd_elf_generic_reloc,	/* special_function */
74	 "R_PRU_NONE",		/* name */
75	 false,			/* partial_inplace */
76	 0,			/* src_mask */
77	 0,			/* dst_mask */
78	 false),		/* pcrel_offset */
79
80  HOWTO (R_PRU_16_PMEM,
81	 2,
82	 2,			/* short */
83	 32,
84	 false,
85	 0,
86	 complain_overflow_dont,
87	 bfd_elf_generic_reloc,
88	 "R_PRU_16_PMEM",
89	 false,
90	 0,			/* src_mask */
91	 0xffff,
92	 false),
93
94  HOWTO (R_PRU_U16_PMEMIMM,
95	 2,
96	 4,
97	 32,
98	 false,
99	 8,
100	 complain_overflow_unsigned,
101	 pru_elf32_pmem_relocate,
102	 "R_PRU_U16_PMEMIMM",
103	 false,
104	 0,			/* src_mask */
105	 0x00ffff00,
106	 false),
107
108  HOWTO (R_PRU_BFD_RELOC_16,
109	 0,
110	 2,			/* short */
111	 16,
112	 false,
113	 0,
114	 complain_overflow_bitfield,
115	 bfd_elf_generic_reloc,
116	 "R_PRU_BFD_RELOC16",
117	 false,
118	 0,			/* src_mask */
119	 0x0000ffff,
120	 false),
121
122  /* 16-bit unsigned immediate relocation.  */
123  HOWTO (R_PRU_U16,		/* type */
124	 0,			/* rightshift */
125	 4,			/* size */
126	 16,			/* bitsize */
127	 false,			/* pc_relative */
128	 8,			/* bitpos */
129	 complain_overflow_unsigned,	/* complain on overflow */
130	 bfd_elf_generic_reloc,	/* special function */
131	 "R_PRU_U16",		/* name */
132	 false,			/* partial_inplace */
133	 0,			/* src_mask */
134	 0x00ffff00,		/* dest_mask */
135	 false),		/* pcrel_offset */
136
137  HOWTO (R_PRU_32_PMEM,
138	 2,
139	 4,			/* long */
140	 32,
141	 false,
142	 0,
143	 complain_overflow_dont,
144	 pru_elf32_pmem_relocate,
145	 "R_PRU_32_PMEM",
146	 false,
147	 0,			/* src_mask */
148	 0xffffffff,
149	 false),
150
151  HOWTO (R_PRU_BFD_RELOC_32,
152	 0,
153	 4,			/* long */
154	 32,
155	 false,
156	 0,
157	 complain_overflow_dont,
158	 bfd_elf_generic_reloc,
159	 "R_PRU_BFD_RELOC32",
160	 false,
161	 0,			/* src_mask */
162	 0xffffffff,
163	 false),
164
165  HOWTO (R_PRU_S10_PCREL,
166	 2,
167	 4,
168	 10,
169	 true,
170	 0,
171	 complain_overflow_bitfield,
172	 pru_elf32_s10_pcrel_relocate,
173	 "R_PRU_S10_PCREL",
174	 false,
175	 0,			/* src_mask */
176	 0x060000ff,
177	 true),
178
179  HOWTO (R_PRU_U8_PCREL,
180	 2,
181	 4,
182	 8,
183	 true,
184	 0,
185	 complain_overflow_unsigned,
186	 pru_elf32_u8_pcrel_relocate,
187	 "R_PRU_U8_PCREL",
188	 false,
189	 0,			/* src_mask */
190	 0x000000ff,
191	 true),
192
193  HOWTO (R_PRU_LDI32,
194	 0,			/* rightshift */
195	 8,			/* size */
196	 32,			/* bitsize */
197	 false,			/* pc_relative */
198	 0,			/* bitpos */
199	 complain_overflow_unsigned, /* complain on overflow */
200	 pru_elf32_ldi32_relocate, /* special function */
201	 "R_PRU_LDI32",		/* name */
202	 false,			/* partial_inplace */
203	 0,			/* src_mask */
204	 0xffffffff,		/* dest_mask */
205	 false),		/* pcrel_offset */
206
207  /* GNU-specific relocations.  */
208  HOWTO (R_PRU_GNU_BFD_RELOC_8,
209	 0,
210	 1,			/* byte */
211	 8,
212	 false,
213	 0,
214	 complain_overflow_bitfield,
215	 bfd_elf_generic_reloc,
216	 "R_PRU_BFD_RELOC8",
217	 false,
218	 0,			/* src_mask */
219	 0x000000ff,
220	 false),
221
222  HOWTO (R_PRU_GNU_DIFF8,	/* type */
223	 0,			/* rightshift */
224	 1,			/* size */
225	 8,			/* bitsize */
226	 false,			/* pc_relative */
227	 0,			/* bitpos */
228	 complain_overflow_bitfield, /* complain_on_overflow */
229	 bfd_elf_pru_diff_relocate, /* special_function */
230	 "R_PRU_DIFF8",		/* name */
231	 false,			/* partial_inplace */
232	 0,			/* src_mask */
233	 0xff,			/* dst_mask */
234	 false),		/* pcrel_offset */
235
236  HOWTO (R_PRU_GNU_DIFF16,	/* type */
237	 0,			/* rightshift */
238	 2,			/* size */
239	 16,			/* bitsize */
240	 false,			/* pc_relative */
241	 0,			/* bitpos */
242	 complain_overflow_bitfield, /* complain_on_overflow */
243	 bfd_elf_pru_diff_relocate,/* special_function */
244	 "R_PRU_DIFF16",	/* name */
245	 false,			/* partial_inplace */
246	 0,			/* src_mask */
247	 0xffff,		/* dst_mask */
248	 false),		/* pcrel_offset */
249
250  HOWTO (R_PRU_GNU_DIFF32,	/* type */
251	 0,			/* rightshift */
252	 4,			/* size */
253	 32,			/* bitsize */
254	 false,			/* pc_relative */
255	 0,			/* bitpos */
256	 complain_overflow_bitfield, /* complain_on_overflow */
257	 bfd_elf_pru_diff_relocate,/* special_function */
258	 "R_PRU_DIFF32",	/* name */
259	 false,			/* partial_inplace */
260	 0,			/* src_mask */
261	 0xffffffff,		/* dst_mask */
262	 false),		/* pcrel_offset */
263
264  HOWTO (R_PRU_GNU_DIFF16_PMEM,	/* type */
265	 0,			/* rightshift */
266	 2,			/* size */
267	 16,			/* bitsize */
268	 false,			/* pc_relative */
269	 0,			/* bitpos */
270	 complain_overflow_bitfield, /* complain_on_overflow */
271	 bfd_elf_pru_diff_relocate,/* special_function */
272	 "R_PRU_DIFF16_PMEM",	/* name */
273	 false,			/* partial_inplace */
274	 0,			/* src_mask */
275	 0xffff,		/* dst_mask */
276	 false),		/* pcrel_offset */
277
278  HOWTO (R_PRU_GNU_DIFF32_PMEM, /* type */
279	 0,			/* rightshift */
280	 4,			/* size */
281	 32,			/* bitsize */
282	 false,			/* pc_relative */
283	 0,			/* bitpos */
284	 complain_overflow_bitfield, /* complain_on_overflow */
285	 bfd_elf_pru_diff_relocate,/* special_function */
286	 "R_PRU_DIFF32_PMEM",	/* name */
287	 false,			/* partial_inplace */
288	 0,			/* src_mask */
289	 0xffffffff,		/* dst_mask */
290	 false),		/* pcrel_offset */
291
292/* Add other relocations here.  */
293};
294
295static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1];
296
297/* Return the howto for relocation RTYPE.  */
298
299static reloc_howto_type *
300lookup_howto (unsigned int rtype)
301{
302  static bool initialized = false;
303  int i;
304  int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel)
305			      / sizeof (elf_pru_howto_table_rel[0]));
306
307  if (! initialized)
308    {
309      initialized = true;
310      memset (elf_code_to_howto_index, 0xff,
311	      sizeof (elf_code_to_howto_index));
312      for (i = 0; i < howto_tbl_size; i++)
313	elf_code_to_howto_index[elf_pru_howto_table_rel[i].type] = i;
314    }
315
316  if (rtype > R_PRU_ILLEGAL)
317    return NULL;
318  i = elf_code_to_howto_index[rtype];
319  if (i >= howto_tbl_size)
320    return NULL;
321  return elf_pru_howto_table_rel + i;
322}
323
324/* Map for converting BFD reloc types to PRU reloc types.  */
325
326struct elf_reloc_map
327{
328  bfd_reloc_code_real_type bfd_val;
329  enum elf_pru_reloc_type elf_val;
330};
331
332static const struct elf_reloc_map pru_reloc_map[] =
333{
334  {BFD_RELOC_NONE, R_PRU_NONE},
335  {BFD_RELOC_PRU_16_PMEM, R_PRU_16_PMEM},
336  {BFD_RELOC_PRU_U16_PMEMIMM, R_PRU_U16_PMEMIMM},
337  {BFD_RELOC_16, R_PRU_BFD_RELOC_16},
338  {BFD_RELOC_PRU_U16, R_PRU_U16},
339  {BFD_RELOC_PRU_32_PMEM, R_PRU_32_PMEM},
340  {BFD_RELOC_32, R_PRU_BFD_RELOC_32},
341  {BFD_RELOC_PRU_S10_PCREL, R_PRU_S10_PCREL},
342  {BFD_RELOC_PRU_U8_PCREL, R_PRU_U8_PCREL},
343  {BFD_RELOC_PRU_LDI32, R_PRU_LDI32},
344
345  {BFD_RELOC_8, R_PRU_GNU_BFD_RELOC_8},
346  {BFD_RELOC_PRU_GNU_DIFF8, R_PRU_GNU_DIFF8},
347  {BFD_RELOC_PRU_GNU_DIFF16, R_PRU_GNU_DIFF16},
348  {BFD_RELOC_PRU_GNU_DIFF32, R_PRU_GNU_DIFF32},
349  {BFD_RELOC_PRU_GNU_DIFF16_PMEM, R_PRU_GNU_DIFF16_PMEM},
350  {BFD_RELOC_PRU_GNU_DIFF32_PMEM, R_PRU_GNU_DIFF32_PMEM},
351};
352
353
354/* Assorted hash table functions.  */
355
356/* Create an entry in a PRU ELF linker hash table.  */
357
358static struct bfd_hash_entry *
359link_hash_newfunc (struct bfd_hash_entry *entry,
360		   struct bfd_hash_table *table, const char *string)
361{
362  /* Allocate the structure if it has not already been allocated by a
363     subclass.  */
364  if (entry == NULL)
365    {
366      entry = bfd_hash_allocate (table,
367				 sizeof (struct elf_link_hash_entry));
368      if (entry == NULL)
369	return entry;
370    }
371
372  /* Call the allocation method of the superclass.  */
373  entry = _bfd_elf_link_hash_newfunc (entry, table, string);
374
375  return entry;
376}
377
378/* Implement bfd_elf32_bfd_reloc_type_lookup:
379   Given a BFD reloc type, return a howto structure.  */
380
381static reloc_howto_type *
382pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
383				   bfd_reloc_code_real_type code)
384{
385  unsigned int i;
386
387  for (i = 0; i < ARRAY_SIZE (pru_reloc_map); ++i)
388    if (pru_reloc_map[i].bfd_val == code)
389      return lookup_howto ((unsigned int) pru_reloc_map[i].elf_val);
390  return NULL;
391}
392
393/* Implement bfd_elf32_bfd_reloc_name_lookup:
394   Given a reloc name, return a howto structure.  */
395
396static reloc_howto_type *
397pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
398				   const char *r_name)
399{
400  unsigned int i;
401
402  for (i = 0; i < ARRAY_SIZE (elf_pru_howto_table_rel); i++)
403    if (elf_pru_howto_table_rel[i].name
404	&& strcasecmp (elf_pru_howto_table_rel[i].name, r_name) == 0)
405      return &elf_pru_howto_table_rel[i];
406
407  return NULL;
408}
409
410/* Implement elf_info_to_howto:
411   Given a ELF32 relocation, fill in a arelent structure.  */
412
413static bool
414pru_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr,
415			 Elf_Internal_Rela *dst)
416{
417  unsigned int r_type;
418
419  r_type = ELF32_R_TYPE (dst->r_info);
420  if (r_type >= R_PRU_ILLEGAL)
421    {
422      /* xgettext:c-format */
423      _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
424      bfd_set_error (bfd_error_bad_value);
425      return false;
426    }
427
428  cache_ptr->howto = lookup_howto (r_type);
429  return cache_ptr->howto != NULL;
430}
431
432/* Do the relocations that require special handling.  */
433/* Produce a word address for program memory.  Linker scripts will put .text
434   at a high offset in order to differentiate it from .data.  So here we also
435   mask the high bits of PMEM address.
436
437   But why 1MB when internal Program Memory much smaller? We want to catch
438   unintended overflows.
439
440   Why not use (1<<31) as an offset and a mask? Sitara DDRAM usually resides
441   there, and users might want to put some shared carveout memory region in
442   their linker scripts.  So 0x80000000 might be a valid .data address.
443
444   Note that we still keep and pass down the original howto.  This way we
445   can reuse this function for several different relocations.  */
446static bfd_reloc_status_type
447pru_elf32_do_pmem_relocate (bfd *abfd, reloc_howto_type *howto,
448			    asection *input_section,
449			    bfd_byte *data, bfd_vma offset,
450			    bfd_vma symbol_value, bfd_vma addend)
451{
452  symbol_value = symbol_value + addend;
453  addend = 0;
454  symbol_value &= 0x3fffff;
455  return _bfd_final_link_relocate (howto, abfd, input_section,
456				   data, offset, symbol_value, addend);
457}
458
459/* Direct copy of _bfd_final_link_relocate, but with special
460   "fill-in".  This copy-paste mumbo jumbo is only needed because BFD
461   cannot deal correctly with non-contiguous bit fields.  */
462static bfd_reloc_status_type
463pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto,
464				 asection *input_section,
465				 bfd_byte *contents, bfd_vma address,
466				 bfd_vma relocation, bfd_vma addend)
467{
468  bfd_byte *location;
469  bfd_vma x = 0;
470  bfd_vma qboff;
471  bfd_reloc_status_type flag = bfd_reloc_ok;
472
473  /* Sanity check the address.  */
474  if (address > bfd_get_section_limit (input_bfd, input_section))
475    return bfd_reloc_outofrange;
476
477  BFD_ASSERT (howto->pc_relative);
478  BFD_ASSERT (howto->pcrel_offset);
479
480  relocation = relocation + addend - (input_section->output_section->vma
481		+ input_section->output_offset) - address;
482
483  location = contents + address;
484
485  /* Get the value we are going to relocate.  */
486  BFD_ASSERT (bfd_get_reloc_size (howto) == 4);
487  x = bfd_get_32 (input_bfd, location);
488
489  qboff = GET_BROFF_SIGNED (x) << howto->rightshift;
490  relocation += qboff;
491
492  BFD_ASSERT (howto->complain_on_overflow == complain_overflow_bitfield);
493
494  if (relocation > 2047 && relocation < (bfd_vma)-2048l)
495    flag = bfd_reloc_overflow;
496
497  /* Check that target address is word-aligned.  */
498  if (relocation & ((1 << howto->rightshift) - 1))
499    flag = bfd_reloc_outofrange;
500
501  relocation >>= (bfd_vma) howto->rightshift;
502
503  /* Fill-in the RELOCATION to the right bits of X.  */
504  SET_BROFF_URAW (x, relocation);
505
506  bfd_put_32 (input_bfd, x, location);
507
508  return flag;
509}
510
511static bfd_reloc_status_type
512pru_elf32_do_u8_pcrel_relocate (bfd *abfd, reloc_howto_type *howto,
513				asection *input_section,
514				bfd_byte *data, bfd_vma offset,
515				bfd_vma symbol_value, bfd_vma addend)
516{
517  bfd_vma relocation;
518
519  BFD_ASSERT (howto->pc_relative);
520  BFD_ASSERT (howto->pcrel_offset);
521
522  relocation = symbol_value + addend - (input_section->output_section->vma
523		+ input_section->output_offset) - offset;
524  relocation >>= howto->rightshift;
525
526  /* 0 and 1 are invalid target labels for LOOP.  We cannot
527     encode this info in HOWTO, so catch such cases here.  */
528  if (relocation < 2)
529      return bfd_reloc_outofrange;
530
531  return _bfd_final_link_relocate (howto, abfd, input_section,
532				   data, offset, symbol_value, addend);
533}
534
535/* Idea and code taken from elf32-d30v.  */
536static bfd_reloc_status_type
537pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
538			     asection *input_section,
539			     bfd_byte *data, bfd_vma offset,
540			     bfd_vma symbol_value, bfd_vma addend)
541{
542  bfd_vma relocation;
543  bfd_size_type octets = offset * OCTETS_PER_BYTE (abfd, input_section);
544  bfd_byte *location;
545  unsigned long in1, in2;
546
547  /* A hacked-up version of _bfd_final_link_relocate() follows.  */
548
549  /* Sanity check the address.  */
550  if (octets + bfd_get_reloc_size (howto)
551      > bfd_get_section_limit_octets (abfd, input_section))
552    return bfd_reloc_outofrange;
553
554  /* This function assumes that we are dealing with a basic relocation
555     against a symbol.  We want to compute the value of the symbol to
556     relocate to.  This is just VALUE, the value of the symbol, plus
557     ADDEND, any addend associated with the reloc.  */
558  relocation = symbol_value + addend;
559
560  BFD_ASSERT (!howto->pc_relative);
561
562  /* A hacked-up version of _bfd_relocate_contents() follows.  */
563  location = data + octets;
564
565  BFD_ASSERT (!howto->pc_relative);
566
567  in1 = bfd_get_32 (abfd, location);
568  in2 = bfd_get_32 (abfd, location + 4);
569
570  SET_INSN_FIELD (IMM16, in1, relocation >> 16);
571  SET_INSN_FIELD (IMM16, in2, relocation & 0xffff);
572
573  bfd_put_32 (abfd, in1, location);
574  bfd_put_32 (abfd, in2, location + 4);
575
576  /* Old GAS and LD versions have a bug, where the two
577     LDI instructions are swapped.  Detect such object
578     files and bail.  */
579  if (GET_INSN_FIELD (RDSEL, in1) != RSEL_31_16)
580    {
581      /* xgettext:c-format */
582      _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
583			  abfd);
584      return bfd_reloc_notsupported;
585    }
586
587  return bfd_reloc_ok;
588}
589
590/* HOWTO handlers for relocations that require special handling.  */
591
592static bfd_reloc_status_type
593pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
594			 asymbol *symbol, void *data,
595			 asection *input_section, bfd *output_bfd,
596			 char **error_message)
597{
598  /* If this is a relocatable link (output_bfd test tells us), just
599     call the generic function.  Any adjustment will be done at final
600     link time.  */
601  if (output_bfd != NULL)
602    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
603				  input_section, output_bfd, error_message);
604
605  BFD_ASSERT (0);
606  return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
607				     input_section,
608				     data, reloc_entry->address,
609				     (symbol->value
610				      + symbol->section->output_section->vma
611				      + symbol->section->output_offset),
612				     reloc_entry->addend);
613}
614
615static bfd_reloc_status_type
616pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry,
617				 asymbol *symbol, void *data,
618				 asection *input_section, bfd *output_bfd,
619				 char **error_message)
620{
621  /* If this is a relocatable link (output_bfd test tells us), just
622     call the generic function.  Any adjustment will be done at final
623     link time.  */
624  if (output_bfd != NULL)
625    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
626				  input_section, output_bfd, error_message);
627
628  return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
629					  input_section, data,
630					  reloc_entry->address,
631					  (symbol->value
632					   + symbol->section->output_section->vma
633					   + symbol->section->output_offset),
634					  reloc_entry->addend);
635}
636
637static bfd_reloc_status_type
638pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
639			     void *data, asection *input_section,
640			     bfd *output_bfd,
641			     char **error_message)
642{
643  /* If this is a relocatable link (output_bfd test tells us), just
644     call the generic function.  Any adjustment will be done at final
645     link time.  */
646  if (output_bfd != NULL)
647    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
648				  input_section, output_bfd, error_message);
649
650  return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
651					 input_section,
652					 data, reloc_entry->address,
653					 (symbol->value
654					  + symbol->section->output_section->vma
655					  + symbol->section->output_offset),
656					 reloc_entry->addend);
657}
658
659static bfd_reloc_status_type
660pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
661			  void *data, asection *input_section,
662			  bfd *output_bfd,
663			  char **error_message)
664{
665  /* If this is a relocatable link (output_bfd test tells us), just
666     call the generic function.  Any adjustment will be done at final
667     link time.  */
668  if (output_bfd != NULL)
669    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
670				  input_section, output_bfd, error_message);
671
672  return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
673				      input_section,
674				      data, reloc_entry->address,
675				      (symbol->value
676				       + symbol->section->output_section->vma
677				       + symbol->section->output_offset),
678				      reloc_entry->addend);
679}
680
681
682/* Implement elf_backend_relocate_section.  */
683static int
684pru_elf32_relocate_section (bfd *output_bfd,
685			    struct bfd_link_info *info,
686			    bfd *input_bfd,
687			    asection *input_section,
688			    bfd_byte *contents,
689			    Elf_Internal_Rela *relocs,
690			    Elf_Internal_Sym *local_syms,
691			    asection **local_sections)
692{
693  struct bfd_elf_section_data * esd = elf_section_data (input_section);
694  Elf_Internal_Shdr *symtab_hdr;
695  struct elf_link_hash_entry **sym_hashes;
696  Elf_Internal_Rela *rel;
697  Elf_Internal_Rela *relend;
698  bool is_rel_reloc;
699
700  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
701  sym_hashes = elf_sym_hashes (input_bfd);
702  relend = relocs + input_section->reloc_count;
703
704  /* See if we have a REL type relocation.  */
705  is_rel_reloc = (esd->rel.hdr != NULL);
706  /* Sanity check - only one type of relocation per section.
707     FIXME: Theoretically it is possible to have both types,
708     but if that happens how can we distinguish between the two ?  */
709  BFD_ASSERT (! is_rel_reloc || ! esd->rela.hdr);
710
711  for (rel = relocs; rel < relend; rel++)
712    {
713      reloc_howto_type *howto;
714      unsigned long r_symndx;
715      Elf_Internal_Sym *sym;
716      asection *sec;
717      struct elf_link_hash_entry *h;
718      bfd_vma relocation;
719      bfd_reloc_status_type r = bfd_reloc_ok;
720      const char *name = NULL;
721      const char* msg = (const char*) NULL;
722      bool unresolved_reloc;
723      bfd_vma addend;
724
725      /* If we are using a REL relocation then the addend should be empty.  */
726      BFD_ASSERT (! is_rel_reloc || rel->r_addend == 0);
727
728      r_symndx = ELF32_R_SYM (rel->r_info);
729
730      howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
731      h = NULL;
732      sym = NULL;
733      sec = NULL;
734
735      if (r_symndx < symtab_hdr->sh_info)
736	{
737	  sym = local_syms + r_symndx;
738	  sec = local_sections[r_symndx];
739	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
740	}
741      else
742	{
743	  bool warned, ignored;
744
745	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
746				   r_symndx, symtab_hdr, sym_hashes,
747				   h, sec, relocation,
748				   unresolved_reloc, warned, ignored);
749	}
750
751      if (sec && discarded_section (sec))
752	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
753					 rel, 1, relend, howto, 0, contents);
754
755      /* Nothing more to do unless this is a final link.  */
756      if (bfd_link_relocatable (info))
757	continue;
758
759      if (howto)
760	{
761	  switch (howto->type)
762	    {
763	    case R_PRU_NONE:
764	      /* We don't need to find a value for this symbol.  It's just a
765		 marker.  */
766	      r = bfd_reloc_ok;
767	      break;
768
769	    case R_PRU_U16:
770	      if (is_rel_reloc)
771		{
772		  unsigned long insn;
773		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
774		  addend = GET_INSN_FIELD (IMM16, insn);
775		}
776	      else
777		addend = rel->r_addend;
778	      r = _bfd_final_link_relocate (howto, input_bfd,
779					    input_section, contents,
780					    rel->r_offset, relocation,
781					    addend);
782	      break;
783
784	    case R_PRU_U16_PMEMIMM:
785	    case R_PRU_32_PMEM:
786	    case R_PRU_16_PMEM:
787	      if (is_rel_reloc && howto->type == R_PRU_U16_PMEMIMM)
788		{
789		  unsigned long insn;
790		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
791		  addend = GET_INSN_FIELD (IMM16, insn) << 2;
792		}
793	      else if (is_rel_reloc && howto->type == R_PRU_32_PMEM)
794		{
795		  addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
796		  addend <<= 2;
797		}
798	      else if (is_rel_reloc && howto->type == R_PRU_16_PMEM)
799		{
800		  addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
801		  addend <<= 2;
802		}
803	      else
804		{
805		  BFD_ASSERT (!is_rel_reloc);
806		  addend = rel->r_addend;
807		}
808	      r = pru_elf32_do_pmem_relocate (input_bfd, howto,
809						input_section,
810						contents, rel->r_offset,
811						relocation, addend);
812	      break;
813	    case R_PRU_S10_PCREL:
814	      BFD_ASSERT (! is_rel_reloc);
815	      r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
816						      input_section,
817						      contents,
818						      rel->r_offset,
819						      relocation,
820						      rel->r_addend);
821	      break;
822	    case R_PRU_U8_PCREL:
823	      BFD_ASSERT (! is_rel_reloc);
824	      r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
825						      input_section,
826						      contents,
827						      rel->r_offset,
828						      relocation,
829						      rel->r_addend);
830	      break;
831	    case R_PRU_LDI32:
832	      if (is_rel_reloc)
833		{
834		  unsigned long in1, in2;
835		  in1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
836		  in2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
837		  addend = (GET_INSN_FIELD (IMM16, in1) << 16)
838			    | GET_INSN_FIELD (IMM16, in2);
839		}
840	      else
841		{
842		  addend = rel->r_addend;
843		}
844	      r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
845					       input_section,
846					       contents,
847					       rel->r_offset,
848					       relocation,
849					       addend);
850	      break;
851	    case R_PRU_GNU_DIFF8:
852	    case R_PRU_GNU_DIFF16:
853	    case R_PRU_GNU_DIFF32:
854	    case R_PRU_GNU_DIFF16_PMEM:
855	    case R_PRU_GNU_DIFF32_PMEM:
856	      /* GNU extensions support only rela.  */
857	      BFD_ASSERT (! is_rel_reloc);
858	      /* Nothing to do here, as contents already contain the
859		 diff value.  */
860	      r = bfd_reloc_ok;
861	      break;
862
863	    case R_PRU_BFD_RELOC_16:
864	      if (is_rel_reloc)
865		addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
866	      else
867		addend = rel->r_addend;
868	      r = _bfd_final_link_relocate (howto, input_bfd,
869					    input_section, contents,
870					    rel->r_offset, relocation,
871					    addend);
872	      break;
873
874	    case R_PRU_BFD_RELOC_32:
875	      if (is_rel_reloc)
876		addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
877	      else
878		addend = rel->r_addend;
879	      r = _bfd_final_link_relocate (howto, input_bfd,
880					    input_section, contents,
881					    rel->r_offset, relocation,
882					    addend);
883	      break;
884
885	    case R_PRU_GNU_BFD_RELOC_8:
886	      BFD_ASSERT (! is_rel_reloc);
887	      r = _bfd_final_link_relocate (howto, input_bfd,
888					    input_section, contents,
889					    rel->r_offset, relocation,
890					    rel->r_addend);
891	      break;
892
893	    default:
894	      BFD_ASSERT (0);
895	      break;
896	    }
897	}
898      else
899	r = bfd_reloc_notsupported;
900
901      if (r != bfd_reloc_ok)
902	{
903	  if (h != NULL)
904	    name = h->root.root.string;
905	  else
906	    {
907	      name = bfd_elf_string_from_elf_section (input_bfd,
908						      symtab_hdr->sh_link,
909						      sym->st_name);
910	      if (name == NULL || *name == '\0')
911		name = bfd_section_name (sec);
912	    }
913
914	  switch (r)
915	    {
916	    case bfd_reloc_overflow:
917	      (*info->callbacks->reloc_overflow) (info, NULL, name,
918						  howto->name, (bfd_vma) 0,
919						  input_bfd, input_section,
920						  rel->r_offset);
921	      break;
922
923	    case bfd_reloc_undefined:
924	      (*info->callbacks->undefined_symbol) (info, name, input_bfd,
925						    input_section,
926						    rel->r_offset, true);
927	      break;
928
929	    case bfd_reloc_outofrange:
930	      if (msg == NULL)
931		msg = _("relocation out of range");
932	      break;
933
934	    case bfd_reloc_notsupported:
935	      if (msg == NULL)
936		msg = _("unsupported relocation");
937	      break;
938
939	    case bfd_reloc_dangerous:
940	      if (msg == NULL)
941		msg = _("dangerous relocation");
942	      break;
943
944	    default:
945	      if (msg == NULL)
946		msg = _("unknown error");
947	      break;
948	    }
949
950	  if (msg)
951	    {
952	      (*info->callbacks->warning) (info, msg, name, input_bfd,
953					   input_section, rel->r_offset);
954	      return false;
955	    }
956	}
957    }
958  return true;
959}
960
961
962/* Perform a diff relocation.  Nothing to do, as the difference value is
963   already written into the section's contents.  */
964
965static bfd_reloc_status_type
966bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
967			   arelent *reloc_entry ATTRIBUTE_UNUSED,
968			   asymbol *symbol ATTRIBUTE_UNUSED,
969			   void *data ATTRIBUTE_UNUSED,
970			   asection *input_section ATTRIBUTE_UNUSED,
971			   bfd *output_bfd ATTRIBUTE_UNUSED,
972			   char **error_message ATTRIBUTE_UNUSED)
973{
974  return bfd_reloc_ok;
975}
976
977
978/* Returns whether the relocation type passed is a diff reloc.  */
979
980static bool
981elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
982{
983  return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
984	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
985	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
986	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
987	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
988}
989
990/* Reduce the diff value written in the section by count if the shrinked
991   insn address happens to fall between the two symbols for which this
992   diff reloc was emitted.  */
993
994static void
995elf32_pru_adjust_diff_reloc_value (bfd *abfd,
996				   struct bfd_section *isec,
997				   Elf_Internal_Rela *irel,
998				   bfd_vma symval,
999				   bfd_vma shrinked_insn_address,
1000				   int count)
1001{
1002  unsigned char *reloc_contents = NULL;
1003  unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
1004  if (isec_contents == NULL)
1005  {
1006    if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
1007      return;
1008
1009    elf_section_data (isec)->this_hdr.contents = isec_contents;
1010  }
1011
1012  reloc_contents = isec_contents + irel->r_offset;
1013
1014  /* Read value written in object file.  */
1015  bfd_signed_vma x = 0;
1016  switch (ELF32_R_TYPE (irel->r_info))
1017  {
1018  case R_PRU_GNU_DIFF8:
1019    {
1020      x = bfd_get_signed_8 (abfd, reloc_contents);
1021      break;
1022    }
1023  case R_PRU_GNU_DIFF16:
1024    {
1025      x = bfd_get_signed_16 (abfd, reloc_contents);
1026      break;
1027    }
1028  case R_PRU_GNU_DIFF32:
1029    {
1030      x = bfd_get_signed_32 (abfd, reloc_contents);
1031      break;
1032    }
1033  case R_PRU_GNU_DIFF16_PMEM:
1034    {
1035      x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
1036      break;
1037    }
1038  case R_PRU_GNU_DIFF32_PMEM:
1039    {
1040      x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
1041      break;
1042    }
1043  default:
1044    {
1045      BFD_FAIL ();
1046    }
1047  }
1048
1049  /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
1050     into the object file at the reloc offset.  sym2's logical value is
1051     symval (<start_of_section>) + reloc addend.  Compute the start and end
1052     addresses and check if the shrinked insn falls between sym1 and sym2.  */
1053
1054  bfd_vma end_address = symval + irel->r_addend;
1055  bfd_vma start_address = end_address - x;
1056
1057  /* Shrink the absolute DIFF value (get the to labels "closer"
1058     together), because we have removed data between labels.  */
1059  if (x < 0)
1060    {
1061      x += count;
1062      /* In case the signed x is negative, restore order.  */
1063      SWAP_VALS (end_address, start_address);
1064    }
1065  else
1066    {
1067      x -= count;
1068    }
1069
1070  /* Reduce the diff value by count bytes and write it back into section
1071    contents.  */
1072
1073  if (shrinked_insn_address >= start_address
1074      && shrinked_insn_address <= end_address)
1075  {
1076    switch (ELF32_R_TYPE (irel->r_info))
1077    {
1078    case R_PRU_GNU_DIFF8:
1079      {
1080	bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
1081	break;
1082      }
1083    case R_PRU_GNU_DIFF16:
1084      {
1085	bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
1086	break;
1087      }
1088    case R_PRU_GNU_DIFF32:
1089      {
1090	bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
1091	break;
1092      }
1093    case R_PRU_GNU_DIFF16_PMEM:
1094      {
1095	bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
1096	break;
1097      }
1098    case R_PRU_GNU_DIFF32_PMEM:
1099      {
1100	bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
1101	break;
1102      }
1103    default:
1104      {
1105	BFD_FAIL ();
1106      }
1107    }
1108
1109  }
1110}
1111
1112/* Delete some bytes from a section while changing the size of an instruction.
1113   The parameter "addr" denotes the section-relative offset pointing just
1114   behind the shrinked instruction. "addr+count" point at the first
1115   byte just behind the original unshrinked instruction.
1116
1117   Idea copied from the AVR port.  */
1118
1119static bool
1120pru_elf_relax_delete_bytes (bfd *abfd,
1121			    asection *sec,
1122			    bfd_vma addr,
1123			    int count)
1124{
1125  Elf_Internal_Shdr *symtab_hdr;
1126  unsigned int sec_shndx;
1127  bfd_byte *contents;
1128  Elf_Internal_Rela *irel, *irelend;
1129  Elf_Internal_Sym *isym;
1130  Elf_Internal_Sym *isymbuf = NULL;
1131  bfd_vma toaddr;
1132  struct elf_link_hash_entry **sym_hashes;
1133  struct elf_link_hash_entry **end_hashes;
1134  unsigned int symcount;
1135
1136  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1137  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1138  contents = elf_section_data (sec)->this_hdr.contents;
1139
1140  toaddr = sec->size;
1141
1142  irel = elf_section_data (sec)->relocs;
1143  irelend = irel + sec->reloc_count;
1144
1145  /* Actually delete the bytes.  */
1146  if (toaddr - addr - count > 0)
1147    memmove (contents + addr, contents + addr + count,
1148	     (size_t) (toaddr - addr - count));
1149  sec->size -= count;
1150
1151  /* Adjust all the reloc addresses.  */
1152  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1153    {
1154      bfd_vma old_reloc_address;
1155
1156      old_reloc_address = (sec->output_section->vma
1157			   + sec->output_offset + irel->r_offset);
1158
1159      /* Get the new reloc address.  */
1160      if ((irel->r_offset > addr
1161	   && irel->r_offset < toaddr))
1162	{
1163	  if (debug_relax)
1164	    printf ("Relocation at address 0x%x needs to be moved.\n"
1165		    "Old section offset: 0x%x, New section offset: 0x%x \n",
1166		    (unsigned int) old_reloc_address,
1167		    (unsigned int) irel->r_offset,
1168		    (unsigned int) ((irel->r_offset) - count));
1169
1170	  irel->r_offset -= count;
1171	}
1172
1173    }
1174
1175   /* The reloc's own addresses are now ok.  However, we need to readjust
1176      the reloc's addend, i.e. the reloc's value if two conditions are met:
1177      1.) the reloc is relative to a symbol in this section that
1178	  is located in front of the shrinked instruction
1179      2.) symbol plus addend end up behind the shrinked instruction.
1180
1181      The most common case where this happens are relocs relative to
1182      the section-start symbol.
1183
1184      This step needs to be done for all of the sections of the bfd.  */
1185
1186  {
1187    struct bfd_section *isec;
1188
1189    for (isec = abfd->sections; isec; isec = isec->next)
1190     {
1191       bfd_vma symval;
1192       bfd_vma shrinked_insn_address;
1193
1194       if (isec->reloc_count == 0)
1195	 continue;
1196
1197       shrinked_insn_address = (sec->output_section->vma
1198				+ sec->output_offset + addr);
1199
1200       irel = elf_section_data (isec)->relocs;
1201       /* PR 12161: Read in the relocs for this section if necessary.  */
1202       if (irel == NULL)
1203	 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true);
1204
1205       for (irelend = irel + isec->reloc_count;
1206	    irel < irelend;
1207	    irel++)
1208	 {
1209	   /* Read this BFD's local symbols if we haven't done
1210	      so already.  */
1211	   if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1212	     {
1213	       isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1214	       if (isymbuf == NULL)
1215		 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1216						 symtab_hdr->sh_info, 0,
1217						 NULL, NULL, NULL);
1218	       if (isymbuf == NULL)
1219		 return false;
1220	     }
1221
1222	   /* Get the value of the symbol referred to by the reloc.  */
1223	   if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1224	     {
1225	       /* A local symbol.  */
1226	       asection *sym_sec;
1227
1228	       isym = isymbuf + ELF32_R_SYM (irel->r_info);
1229	       sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1230	       symval = isym->st_value;
1231	       /* If the reloc is absolute, it will not have
1232		  a symbol or section associated with it.  */
1233	       if (sym_sec == sec)
1234		 {
1235		   symval += sym_sec->output_section->vma
1236		     + sym_sec->output_offset;
1237
1238		   if (debug_relax)
1239		     printf ("Checking if the relocation's "
1240			     "addend needs corrections.\n"
1241			     "Address of anchor symbol: 0x%x \n"
1242			     "Address of relocation target: 0x%x \n"
1243			     "Address of relaxed insn: 0x%x \n",
1244			     (unsigned int) symval,
1245			     (unsigned int) (symval + irel->r_addend),
1246			     (unsigned int) shrinked_insn_address);
1247
1248		   /* Shrink the special DIFF relocations.  */
1249		   if (elf32_pru_is_diff_reloc (irel))
1250		     {
1251		       elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1252							  symval,
1253							  shrinked_insn_address,
1254							  count);
1255		     }
1256
1257		   /* Fix the addend, if it is affected.  */
1258		   if (symval <= shrinked_insn_address
1259		       && (symval + irel->r_addend) > shrinked_insn_address)
1260		     {
1261
1262		       irel->r_addend -= count;
1263
1264		       if (debug_relax)
1265			 printf ("Relocation's addend needed to be fixed \n");
1266		     }
1267		 }
1268	       /* else...Reference symbol is absolute.
1269		  No adjustment needed.  */
1270	     }
1271	   /* else...Reference symbol is extern.  No need for adjusting
1272	      the addend.  */
1273	 }
1274     }
1275  }
1276
1277  /* Adjust the local symbols defined in this section.  */
1278  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1279  /* Fix PR 9841, there may be no local symbols.  */
1280  if (isym != NULL)
1281    {
1282      Elf_Internal_Sym *isymend;
1283
1284      isymend = isym + symtab_hdr->sh_info;
1285      for (; isym < isymend; isym++)
1286	{
1287	  if (isym->st_shndx == sec_shndx)
1288	    {
1289	      if (isym->st_value > addr
1290		  && isym->st_value <= toaddr)
1291		isym->st_value -= count;
1292
1293	      if (isym->st_value <= addr
1294		  && isym->st_value + isym->st_size > addr)
1295		{
1296		  /* If this assert fires then we have a symbol that ends
1297		     part way through an instruction.  Does that make
1298		     sense?  */
1299		  BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1300		  isym->st_size -= count;
1301		}
1302	    }
1303	}
1304    }
1305
1306  /* Now adjust the global symbols defined in this section.  */
1307  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1308	      - symtab_hdr->sh_info);
1309  sym_hashes = elf_sym_hashes (abfd);
1310  end_hashes = sym_hashes + symcount;
1311  for (; sym_hashes < end_hashes; sym_hashes++)
1312    {
1313      struct elf_link_hash_entry *sym_hash = *sym_hashes;
1314      if ((sym_hash->root.type == bfd_link_hash_defined
1315	   || sym_hash->root.type == bfd_link_hash_defweak)
1316	  && sym_hash->root.u.def.section == sec)
1317	{
1318	  if (sym_hash->root.u.def.value > addr
1319	      && sym_hash->root.u.def.value <= toaddr)
1320	    sym_hash->root.u.def.value -= count;
1321
1322	  if (sym_hash->root.u.def.value <= addr
1323	      && (sym_hash->root.u.def.value + sym_hash->size > addr))
1324	    {
1325	      /* If this assert fires then we have a symbol that ends
1326		 part way through an instruction.  Does that make
1327		 sense?  */
1328	      BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1329			  >= addr + count);
1330	      sym_hash->size -= count;
1331	    }
1332	}
1333    }
1334
1335  return true;
1336}
1337
1338static bool
1339pru_elf32_relax_section (bfd *abfd, asection *sec,
1340			 struct bfd_link_info *link_info,
1341			 bool *again)
1342{
1343  Elf_Internal_Shdr * symtab_hdr;
1344  Elf_Internal_Rela * internal_relocs;
1345  Elf_Internal_Rela * irel;
1346  Elf_Internal_Rela * irelend;
1347  bfd_byte *	      contents = NULL;
1348  Elf_Internal_Sym *  isymbuf = NULL;
1349
1350  /* Assume nothing changes.  */
1351  *again = false;
1352
1353  /* We don't have to do anything for a relocatable link, if
1354     this section does not have relocs, or if this is not a
1355     code section.  */
1356  if (bfd_link_relocatable (link_info)
1357    || (sec->flags & SEC_RELOC) == 0
1358    || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1359    return true;
1360
1361  symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1362
1363  /* Get a copy of the native relocations.  */
1364  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1365					       link_info->keep_memory);
1366  if (internal_relocs == NULL)
1367    goto error_return;
1368
1369  /* Walk through them looking for relaxing opportunities.  */
1370  irelend = internal_relocs + sec->reloc_count;
1371
1372  for (irel = internal_relocs; irel < irelend; irel++)
1373    {
1374      bfd_vma symval;
1375
1376      /* Get the section contents if we haven't done so already.  */
1377      if (contents == NULL)
1378	{
1379	  /* Get cached copy if it exists.  */
1380	  if (elf_section_data (sec)->this_hdr.contents != NULL)
1381	    contents = elf_section_data (sec)->this_hdr.contents;
1382	  else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1383	    goto error_return;
1384	}
1385
1386      /* Read this BFD's local symbols if we haven't done so already.  */
1387      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1388	{
1389	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1390	  if (isymbuf == NULL)
1391	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1392					    symtab_hdr->sh_info, 0,
1393					    NULL, NULL, NULL);
1394	  if (isymbuf == NULL)
1395	    goto error_return;
1396	}
1397
1398      /* Get the value of the symbol referred to by the reloc.  */
1399      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1400	{
1401	  /* A local symbol.  */
1402	  Elf_Internal_Sym *isym;
1403	  asection *sym_sec;
1404
1405	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
1406	  if (isym->st_shndx == SHN_UNDEF)
1407	    sym_sec = bfd_und_section_ptr;
1408	  else if (isym->st_shndx == SHN_ABS)
1409	    sym_sec = bfd_abs_section_ptr;
1410	  else if (isym->st_shndx == SHN_COMMON)
1411	    sym_sec = bfd_com_section_ptr;
1412	  else
1413	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1414	  symval = (isym->st_value
1415		    + sym_sec->output_section->vma + sym_sec->output_offset);
1416	}
1417      else
1418	{
1419	  unsigned long indx;
1420	  struct elf_link_hash_entry *h;
1421
1422	  /* An external symbol.  */
1423	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1424	  h = elf_sym_hashes (abfd)[indx];
1425	  BFD_ASSERT (h != NULL);
1426
1427	  if (h->root.type != bfd_link_hash_defined
1428	      && h->root.type != bfd_link_hash_defweak)
1429	    /* This appears to be a reference to an undefined
1430	       symbol.  Just ignore it--it will be caught by the
1431	       regular reloc processing.  */
1432	    continue;
1433
1434	  symval = (h->root.u.def.value
1435		    + h->root.u.def.section->output_section->vma
1436		    + h->root.u.def.section->output_offset);
1437	}
1438
1439      /* For simplicity of coding, we are going to modify the section
1440	 contents, the section relocs, and the BFD symbol table.  We
1441	 must tell the rest of the code not to free up this
1442	 information.  It would be possible to instead create a table
1443	 of changes which have to be made, as is done in coff-mips.c;
1444	 that would be more work, but would require less memory when
1445	 the linker is run.  */
1446
1447      /* Check if we can remove an LDI instruction from the LDI32
1448	 pseudo instruction if the upper 16 operand bits are zero.  */
1449      if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1450	{
1451	  bfd_vma value = symval + irel->r_addend;
1452
1453	  if (debug_relax)
1454	    printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1455
1456	  if ((long) value >> 16 == 0)
1457	    {
1458	      unsigned long insn;
1459
1460	      /* Note that we've changed the relocs, section contents.  */
1461	      elf_section_data (sec)->relocs = internal_relocs;
1462	      elf_section_data (sec)->this_hdr.contents = contents;
1463	      symtab_hdr->contents = (unsigned char *) isymbuf;
1464
1465	      /* Make the second instruction load the 16-bit constant
1466		 into the full 32-bit register.  */
1467	      insn = bfd_get_32 (abfd, contents + irel->r_offset + 4);
1468
1469	      /* Old GAS and LD versions have a bug, where the two
1470		 LDI instructions are swapped.  Detect such object
1471		 files and bail.  */
1472	      if (GET_INSN_FIELD (RDSEL, insn) != RSEL_15_0)
1473		{
1474		  /* xgettext:c-format */
1475		  _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
1476				      abfd);
1477		  goto error_return;
1478		}
1479
1480	      SET_INSN_FIELD (RDSEL, insn, RSEL_31_0);
1481	      bfd_put_32 (abfd, insn, contents + irel->r_offset + 4);
1482
1483	      /* Delete the first LDI instruction.  Note that there should
1484		 be no relocations or symbols pointing to the second LDI
1485		 instruction.  */
1486	      if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 4))
1487		goto error_return;
1488
1489	      /* We're done with deletion of the first instruction.
1490		 Set a regular LDI relocation for the second instruction
1491		 we left to load the 16-bit value into the 32-bit
1492		 register.  */
1493	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1494					   R_PRU_U16);
1495
1496	      /* That will change things, so, we should relax again.
1497		 Note that this is not required, and it may be slow.  */
1498	      *again = true;
1499	    }
1500	}
1501    }
1502
1503  if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1504    {
1505      if (!link_info->keep_memory)
1506	free (isymbuf);
1507      else
1508	{
1509	  /* Cache the symbols for elf_link_input_bfd.  */
1510	  symtab_hdr->contents = (unsigned char *) isymbuf;
1511	}
1512    }
1513
1514  if (contents != NULL
1515      && elf_section_data (sec)->this_hdr.contents != contents)
1516    {
1517      if (!link_info->keep_memory)
1518	free (contents);
1519      else
1520	{
1521	  /* Cache the section contents for elf_link_input_bfd.  */
1522	  elf_section_data (sec)->this_hdr.contents = contents;
1523	}
1524    }
1525
1526  if (elf_section_data (sec)->relocs != internal_relocs)
1527    free (internal_relocs);
1528
1529  return true;
1530
1531 error_return:
1532  if (symtab_hdr->contents != (unsigned char *) isymbuf)
1533    free (isymbuf);
1534  if (elf_section_data (sec)->this_hdr.contents != contents)
1535    free (contents);
1536  if (elf_section_data (sec)->relocs != internal_relocs)
1537    free (internal_relocs);
1538
1539  return false;
1540}
1541
1542/* Free the derived linker hash table.  */
1543static void
1544pru_elf32_link_hash_table_free (bfd *obfd)
1545{
1546  _bfd_elf_link_hash_table_free (obfd);
1547}
1548
1549/* Implement bfd_elf32_bfd_link_hash_table_create.  */
1550static struct bfd_link_hash_table *
1551pru_elf32_link_hash_table_create (bfd *abfd)
1552{
1553  struct elf_link_hash_table *ret;
1554  size_t amt = sizeof (struct elf_link_hash_table);
1555
1556  ret = bfd_zmalloc (amt);
1557  if (ret == NULL)
1558    return NULL;
1559
1560  if (!_bfd_elf_link_hash_table_init (ret, abfd,
1561				      link_hash_newfunc,
1562				      sizeof (struct
1563					      elf_link_hash_entry),
1564				      PRU_ELF_DATA))
1565    {
1566      free (ret);
1567      return NULL;
1568    }
1569
1570  ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1571
1572  return &ret->root;
1573}
1574
1575#define ELF_ARCH			bfd_arch_pru
1576#define ELF_TARGET_ID			PRU_ELF_DATA
1577#define ELF_MACHINE_CODE		EM_TI_PRU
1578
1579#define ELF_MAXPAGESIZE			1
1580
1581#define bfd_elf32_bfd_link_hash_table_create \
1582					  pru_elf32_link_hash_table_create
1583
1584/* Relocation table lookup macros.  */
1585
1586#define bfd_elf32_bfd_reloc_type_lookup	  pru_elf32_bfd_reloc_type_lookup
1587#define bfd_elf32_bfd_reloc_name_lookup	  pru_elf32_bfd_reloc_name_lookup
1588
1589#define elf_info_to_howto		pru_elf32_info_to_howto
1590#define elf_info_to_howto_rel		NULL
1591
1592/* elf backend functions.  */
1593
1594/* TI folks like to use a mix of REL and RELA relocations.  See also
1595   the MSP430 and TI C6X backends.  */
1596#define elf_backend_may_use_rel_p  1
1597#define elf_backend_may_use_rela_p 1
1598#define elf_backend_default_use_rela_p 1
1599
1600#define elf_backend_rela_normal		1
1601
1602#define elf_backend_relocate_section	pru_elf32_relocate_section
1603#define bfd_elf32_bfd_relax_section	pru_elf32_relax_section
1604#define elf_backend_can_gc_sections	1
1605
1606#define TARGET_LITTLE_SYM		pru_elf32_vec
1607#define TARGET_LITTLE_NAME		"elf32-pru"
1608
1609#include "elf32-target.h"
1610