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