packaging: Enable testing infrastructure
[external/binutils.git] / bfd / elf32-pru.c
1 /* 32-bit ELF support for TI PRU.
2    Copyright (C) 2014-2019 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 \f
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"