Automatic date update in version.in
[external/binutils.git] / bfd / elf32-pru.c
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, num;
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   /* Extract the addend - should be zero per my understanding.  */
568   num = GET_INSN_FIELD (IMM16, in1) | (GET_INSN_FIELD (IMM16, in2) << 16);
569   BFD_ASSERT (!num);
570
571   relocation += num;
572
573   SET_INSN_FIELD (IMM16, in1, relocation & 0xffff);
574   SET_INSN_FIELD (IMM16, in2, relocation >> 16);
575
576   bfd_put_32 (abfd, in1, location);
577   bfd_put_32 (abfd, in2, location + 4);
578
579   return bfd_reloc_ok;
580 }
581
582 /* HOWTO handlers for relocations that require special handling.  */
583
584 static bfd_reloc_status_type
585 pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
586                          asymbol *symbol, void *data,
587                          asection *input_section, bfd *output_bfd,
588                          char **error_message)
589 {
590   /* If this is a relocatable link (output_bfd test tells us), just
591      call the generic function.  Any adjustment will be done at final
592      link time.  */
593   if (output_bfd != NULL)
594     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
595                                   input_section, output_bfd, error_message);
596
597   return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
598                                      input_section,
599                                      data, reloc_entry->address,
600                                      (symbol->value
601                                       + symbol->section->output_section->vma
602                                       + symbol->section->output_offset),
603                                      reloc_entry->addend);
604 }
605
606 static bfd_reloc_status_type
607 pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry,
608                                  asymbol *symbol, void *data,
609                                  asection *input_section, bfd *output_bfd,
610                                  char **error_message)
611 {
612   /* If this is a relocatable link (output_bfd test tells us), just
613      call the generic function.  Any adjustment will be done at final
614      link time.  */
615   if (output_bfd != NULL)
616     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
617                                   input_section, output_bfd, error_message);
618
619   return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
620                                           input_section, data,
621                                           reloc_entry->address,
622                                           (symbol->value
623                                            + symbol->section->output_section->vma
624                                            + symbol->section->output_offset),
625                                           reloc_entry->addend);
626 }
627
628 static bfd_reloc_status_type
629 pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
630                              void *data, asection *input_section,
631                              bfd *output_bfd,
632                              char **error_message)
633 {
634   /* If this is a relocatable link (output_bfd test tells us), just
635      call the generic function.  Any adjustment will be done at final
636      link time.  */
637   if (output_bfd != NULL)
638     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
639                                   input_section, output_bfd, error_message);
640
641   return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
642                                          input_section,
643                                          data, reloc_entry->address,
644                                          (symbol->value
645                                           + symbol->section->output_section->vma
646                                           + symbol->section->output_offset),
647                                          reloc_entry->addend);
648 }
649
650 static bfd_reloc_status_type
651 pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
652                           void *data, asection *input_section,
653                           bfd *output_bfd,
654                           char **error_message)
655 {
656   /* If this is a relocatable link (output_bfd test tells us), just
657      call the generic function.  Any adjustment will be done at final
658      link time.  */
659   if (output_bfd != NULL)
660     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
661                                   input_section, output_bfd, error_message);
662
663   return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
664                                       input_section,
665                                       data, reloc_entry->address,
666                                       (symbol->value
667                                        + symbol->section->output_section->vma
668                                        + symbol->section->output_offset),
669                                       reloc_entry->addend);
670 }
671
672
673 /* Implement elf_backend_relocate_section.  */
674 static bfd_boolean
675 pru_elf32_relocate_section (bfd *output_bfd,
676                             struct bfd_link_info *info,
677                             bfd *input_bfd,
678                             asection *input_section,
679                             bfd_byte *contents,
680                             Elf_Internal_Rela *relocs,
681                             Elf_Internal_Sym *local_syms,
682                             asection **local_sections)
683 {
684   Elf_Internal_Shdr *symtab_hdr;
685   struct elf_link_hash_entry **sym_hashes;
686   Elf_Internal_Rela *rel;
687   Elf_Internal_Rela *relend;
688
689   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
690   sym_hashes = elf_sym_hashes (input_bfd);
691   relend = relocs + input_section->reloc_count;
692
693   for (rel = relocs; rel < relend; rel++)
694     {
695       reloc_howto_type *howto;
696       unsigned long r_symndx;
697       Elf_Internal_Sym *sym;
698       asection *sec;
699       struct elf_link_hash_entry *h;
700       bfd_vma relocation;
701       bfd_reloc_status_type r = bfd_reloc_ok;
702       const char *name = NULL;
703       const char* msg = (const char*) NULL;
704       bfd_boolean unresolved_reloc;
705
706       r_symndx = ELF32_R_SYM (rel->r_info);
707
708       howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
709       h = NULL;
710       sym = NULL;
711       sec = NULL;
712
713       if (r_symndx < symtab_hdr->sh_info)
714         {
715           sym = local_syms + r_symndx;
716           sec = local_sections[r_symndx];
717           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
718         }
719       else
720         {
721           bfd_boolean warned, ignored;
722
723           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
724                                    r_symndx, symtab_hdr, sym_hashes,
725                                    h, sec, relocation,
726                                    unresolved_reloc, warned, ignored);
727         }
728
729       if (sec && discarded_section (sec))
730         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
731                                          rel, 1, relend, howto, 0, contents);
732
733       /* Nothing more to do unless this is a final link.  */
734       if (bfd_link_relocatable (info))
735         continue;
736
737       if (howto)
738         {
739           switch (howto->type)
740             {
741             case R_PRU_NONE:
742               /* We don't need to find a value for this symbol.  It's just a
743                  marker.  */
744               r = bfd_reloc_ok;
745               break;
746
747             case R_PRU_U16_PMEMIMM:
748             case R_PRU_32_PMEM:
749             case R_PRU_16_PMEM:
750               r = pru_elf32_do_pmem_relocate (input_bfd, howto,
751                                                 input_section,
752                                                 contents, rel->r_offset,
753                                                 relocation, rel->r_addend);
754               break;
755             case R_PRU_S10_PCREL:
756               r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
757                                                       input_section,
758                                                       contents,
759                                                       rel->r_offset,
760                                                       relocation,
761                                                       rel->r_addend);
762               break;
763             case R_PRU_U8_PCREL:
764               r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
765                                                       input_section,
766                                                       contents,
767                                                       rel->r_offset,
768                                                       relocation,
769                                                       rel->r_addend);
770               break;
771             case R_PRU_LDI32:
772               r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
773                                                input_section,
774                                                contents,
775                                                rel->r_offset,
776                                                relocation,
777                                                rel->r_addend);
778               break;
779             case R_PRU_GNU_DIFF8:
780             case R_PRU_GNU_DIFF16:
781             case R_PRU_GNU_DIFF32:
782             case R_PRU_GNU_DIFF16_PMEM:
783             case R_PRU_GNU_DIFF32_PMEM:
784               /* Nothing to do here, as contents already contain the
785                  diff value.  */
786               r = bfd_reloc_ok;
787               break;
788
789             default:
790               r = _bfd_final_link_relocate (howto, input_bfd,
791                                             input_section, contents,
792                                             rel->r_offset, relocation,
793                                             rel->r_addend);
794               break;
795             }
796         }
797       else
798         r = bfd_reloc_notsupported;
799
800       if (r != bfd_reloc_ok)
801         {
802           if (h != NULL)
803             name = h->root.root.string;
804           else
805             {
806               name = bfd_elf_string_from_elf_section (input_bfd,
807                                                       symtab_hdr->sh_link,
808                                                       sym->st_name);
809               if (name == NULL || *name == '\0')
810                 name = bfd_section_name (input_bfd, sec);
811             }
812
813           switch (r)
814             {
815             case bfd_reloc_overflow:
816               (*info->callbacks->reloc_overflow) (info, NULL, name,
817                                                   howto->name, (bfd_vma) 0,
818                                                   input_bfd, input_section,
819                                                   rel->r_offset);
820               break;
821
822             case bfd_reloc_undefined:
823               (*info->callbacks->undefined_symbol) (info, name, input_bfd,
824                                                     input_section,
825                                                     rel->r_offset, TRUE);
826               break;
827
828             case bfd_reloc_outofrange:
829               if (msg == NULL)
830                 msg = _("relocation out of range");
831               break;
832
833             case bfd_reloc_notsupported:
834               if (msg == NULL)
835                 msg = _("unsupported relocation");
836               break;
837
838             case bfd_reloc_dangerous:
839               if (msg == NULL)
840                 msg = _("dangerous relocation");
841               break;
842
843             default:
844               if (msg == NULL)
845                 msg = _("unknown error");
846               break;
847             }
848
849           if (msg)
850             {
851               (*info->callbacks->warning) (info, msg, name, input_bfd,
852                                            input_section, rel->r_offset);
853               return FALSE;
854             }
855         }
856     }
857   return TRUE;
858 }
859
860 \f
861 /* Perform a diff relocation.  Nothing to do, as the difference value is
862    already written into the section's contents.  */
863
864 static bfd_reloc_status_type
865 bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
866                            arelent *reloc_entry ATTRIBUTE_UNUSED,
867                            asymbol *symbol ATTRIBUTE_UNUSED,
868                            void *data ATTRIBUTE_UNUSED,
869                            asection *input_section ATTRIBUTE_UNUSED,
870                            bfd *output_bfd ATTRIBUTE_UNUSED,
871                            char **error_message ATTRIBUTE_UNUSED)
872 {
873   return bfd_reloc_ok;
874 }
875
876
877 /* Returns whether the relocation type passed is a diff reloc.  */
878
879 static bfd_boolean
880 elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
881 {
882   return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
883           || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
884           || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
885           || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
886           || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
887 }
888
889 /* Reduce the diff value written in the section by count if the shrinked
890    insn address happens to fall between the two symbols for which this
891    diff reloc was emitted.  */
892
893 static void
894 elf32_pru_adjust_diff_reloc_value (bfd *abfd,
895                                    struct bfd_section *isec,
896                                    Elf_Internal_Rela *irel,
897                                    bfd_vma symval,
898                                    bfd_vma shrinked_insn_address,
899                                    int count)
900 {
901   unsigned char *reloc_contents = NULL;
902   unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
903   if (isec_contents == NULL)
904   {
905     if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
906       return;
907
908     elf_section_data (isec)->this_hdr.contents = isec_contents;
909   }
910
911   reloc_contents = isec_contents + irel->r_offset;
912
913   /* Read value written in object file.  */
914   bfd_signed_vma x = 0;
915   switch (ELF32_R_TYPE (irel->r_info))
916   {
917   case R_PRU_GNU_DIFF8:
918     {
919       x = bfd_get_signed_8 (abfd, reloc_contents);
920       break;
921     }
922   case R_PRU_GNU_DIFF16:
923     {
924       x = bfd_get_signed_16 (abfd, reloc_contents);
925       break;
926     }
927   case R_PRU_GNU_DIFF32:
928     {
929       x = bfd_get_signed_32 (abfd, reloc_contents);
930       break;
931     }
932   case R_PRU_GNU_DIFF16_PMEM:
933     {
934       x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
935       break;
936     }
937   case R_PRU_GNU_DIFF32_PMEM:
938     {
939       x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
940       break;
941     }
942   default:
943     {
944       BFD_FAIL ();
945     }
946   }
947
948   /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
949      into the object file at the reloc offset.  sym2's logical value is
950      symval (<start_of_section>) + reloc addend.  Compute the start and end
951      addresses and check if the shrinked insn falls between sym1 and sym2.  */
952
953   bfd_vma end_address = symval + irel->r_addend;
954   bfd_vma start_address = end_address - x;
955
956   /* Shrink the absolute DIFF value (get the to labels "closer"
957      together), because we have removed data between labels.  */
958   if (x < 0)
959     {
960       x += count;
961       /* In case the signed x is negative, restore order.  */
962       SWAP_VALS (end_address, start_address);
963     }
964   else
965     {
966       x -= count;
967     }
968
969   /* Reduce the diff value by count bytes and write it back into section
970     contents.  */
971
972   if (shrinked_insn_address >= start_address
973       && shrinked_insn_address <= end_address)
974   {
975     switch (ELF32_R_TYPE (irel->r_info))
976     {
977     case R_PRU_GNU_DIFF8:
978       {
979         bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
980         break;
981       }
982     case R_PRU_GNU_DIFF16:
983       {
984         bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
985         break;
986       }
987     case R_PRU_GNU_DIFF32:
988       {
989         bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
990         break;
991       }
992     case R_PRU_GNU_DIFF16_PMEM:
993       {
994         bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
995         break;
996       }
997     case R_PRU_GNU_DIFF32_PMEM:
998       {
999         bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
1000         break;
1001       }
1002     default:
1003       {
1004         BFD_FAIL ();
1005       }
1006     }
1007
1008   }
1009 }
1010
1011 /* Delete some bytes from a section while changing the size of an instruction.
1012    The parameter "addr" denotes the section-relative offset pointing just
1013    behind the shrinked instruction. "addr+count" point at the first
1014    byte just behind the original unshrinked instruction.
1015
1016    Idea copied from the AVR port.  */
1017
1018 static bfd_boolean
1019 pru_elf_relax_delete_bytes (bfd *abfd,
1020                             asection *sec,
1021                             bfd_vma addr,
1022                             int count)
1023 {
1024   Elf_Internal_Shdr *symtab_hdr;
1025   unsigned int sec_shndx;
1026   bfd_byte *contents;
1027   Elf_Internal_Rela *irel, *irelend;
1028   Elf_Internal_Sym *isym;
1029   Elf_Internal_Sym *isymbuf = NULL;
1030   bfd_vma toaddr;
1031   struct elf_link_hash_entry **sym_hashes;
1032   struct elf_link_hash_entry **end_hashes;
1033   unsigned int symcount;
1034
1035   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1036   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1037   contents = elf_section_data (sec)->this_hdr.contents;
1038
1039   toaddr = sec->size;
1040
1041   irel = elf_section_data (sec)->relocs;
1042   irelend = irel + sec->reloc_count;
1043
1044   /* Actually delete the bytes.  */
1045   if (toaddr - addr - count > 0)
1046     memmove (contents + addr, contents + addr + count,
1047              (size_t) (toaddr - addr - count));
1048   sec->size -= count;
1049
1050   /* Adjust all the reloc addresses.  */
1051   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1052     {
1053       bfd_vma old_reloc_address;
1054
1055       old_reloc_address = (sec->output_section->vma
1056                            + sec->output_offset + irel->r_offset);
1057
1058       /* Get the new reloc address.  */
1059       if ((irel->r_offset > addr
1060            && irel->r_offset < toaddr))
1061         {
1062           if (debug_relax)
1063             printf ("Relocation at address 0x%x needs to be moved.\n"
1064                     "Old section offset: 0x%x, New section offset: 0x%x \n",
1065                     (unsigned int) old_reloc_address,
1066                     (unsigned int) irel->r_offset,
1067                     (unsigned int) ((irel->r_offset) - count));
1068
1069           irel->r_offset -= count;
1070         }
1071
1072     }
1073
1074    /* The reloc's own addresses are now ok.  However, we need to readjust
1075       the reloc's addend, i.e. the reloc's value if two conditions are met:
1076       1.) the reloc is relative to a symbol in this section that
1077           is located in front of the shrinked instruction
1078       2.) symbol plus addend end up behind the shrinked instruction.
1079
1080       The most common case where this happens are relocs relative to
1081       the section-start symbol.
1082
1083       This step needs to be done for all of the sections of the bfd.  */
1084
1085   {
1086     struct bfd_section *isec;
1087
1088     for (isec = abfd->sections; isec; isec = isec->next)
1089      {
1090        bfd_vma symval;
1091        bfd_vma shrinked_insn_address;
1092
1093        if (isec->reloc_count == 0)
1094          continue;
1095
1096        shrinked_insn_address = (sec->output_section->vma
1097                                 + sec->output_offset + addr - count);
1098
1099        irel = elf_section_data (isec)->relocs;
1100        /* PR 12161: Read in the relocs for this section if necessary.  */
1101        if (irel == NULL)
1102          irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
1103
1104        for (irelend = irel + isec->reloc_count;
1105             irel < irelend;
1106             irel++)
1107          {
1108            /* Read this BFD's local symbols if we haven't done
1109               so already.  */
1110            if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1111              {
1112                isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1113                if (isymbuf == NULL)
1114                  isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1115                                                  symtab_hdr->sh_info, 0,
1116                                                  NULL, NULL, NULL);
1117                if (isymbuf == NULL)
1118                  return FALSE;
1119              }
1120
1121            /* Get the value of the symbol referred to by the reloc.  */
1122            if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1123              {
1124                /* A local symbol.  */
1125                asection *sym_sec;
1126
1127                isym = isymbuf + ELF32_R_SYM (irel->r_info);
1128                sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1129                symval = isym->st_value;
1130                /* If the reloc is absolute, it will not have
1131                   a symbol or section associated with it.  */
1132                if (sym_sec == sec)
1133                  {
1134                    symval += sym_sec->output_section->vma
1135                      + sym_sec->output_offset;
1136
1137                    if (debug_relax)
1138                      printf ("Checking if the relocation's "
1139                              "addend needs corrections.\n"
1140                              "Address of anchor symbol: 0x%x \n"
1141                              "Address of relocation target: 0x%x \n"
1142                              "Address of relaxed insn: 0x%x \n",
1143                              (unsigned int) symval,
1144                              (unsigned int) (symval + irel->r_addend),
1145                              (unsigned int) shrinked_insn_address);
1146
1147                    /* Shrink the special DIFF relocations.  */
1148                    if (elf32_pru_is_diff_reloc (irel))
1149                      {
1150                        elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1151                                                           symval,
1152                                                           shrinked_insn_address,
1153                                                           count);
1154                      }
1155
1156                    /* Fix the addend, if it is affected.  */
1157                    if (symval <= shrinked_insn_address
1158                        && (symval + irel->r_addend) > shrinked_insn_address)
1159                      {
1160
1161                        irel->r_addend -= count;
1162
1163                        if (debug_relax)
1164                          printf ("Relocation's addend needed to be fixed \n");
1165                      }
1166                  }
1167                /* else...Reference symbol is absolute.
1168                   No adjustment needed.  */
1169              }
1170            /* else...Reference symbol is extern.  No need for adjusting
1171               the addend.  */
1172          }
1173      }
1174   }
1175
1176   /* Adjust the local symbols defined in this section.  */
1177   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1178   /* Fix PR 9841, there may be no local symbols.  */
1179   if (isym != NULL)
1180     {
1181       Elf_Internal_Sym *isymend;
1182
1183       isymend = isym + symtab_hdr->sh_info;
1184       for (; isym < isymend; isym++)
1185         {
1186           if (isym->st_shndx == sec_shndx)
1187             {
1188               if (isym->st_value > addr
1189                   && isym->st_value <= toaddr)
1190                 isym->st_value -= count;
1191
1192               if (isym->st_value <= addr
1193                   && isym->st_value + isym->st_size > addr)
1194                 {
1195                   /* If this assert fires then we have a symbol that ends
1196                      part way through an instruction.  Does that make
1197                      sense?  */
1198                   BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1199                   isym->st_size -= count;
1200                 }
1201             }
1202         }
1203     }
1204
1205   /* Now adjust the global symbols defined in this section.  */
1206   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1207               - symtab_hdr->sh_info);
1208   sym_hashes = elf_sym_hashes (abfd);
1209   end_hashes = sym_hashes + symcount;
1210   for (; sym_hashes < end_hashes; sym_hashes++)
1211     {
1212       struct elf_link_hash_entry *sym_hash = *sym_hashes;
1213       if ((sym_hash->root.type == bfd_link_hash_defined
1214            || sym_hash->root.type == bfd_link_hash_defweak)
1215           && sym_hash->root.u.def.section == sec)
1216         {
1217           if (sym_hash->root.u.def.value > addr
1218               && sym_hash->root.u.def.value <= toaddr)
1219             sym_hash->root.u.def.value -= count;
1220
1221           if (sym_hash->root.u.def.value <= addr
1222               && (sym_hash->root.u.def.value + sym_hash->size > addr))
1223             {
1224               /* If this assert fires then we have a symbol that ends
1225                  part way through an instruction.  Does that make
1226                  sense?  */
1227               BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1228                           >= addr + count);
1229               sym_hash->size -= count;
1230             }
1231         }
1232     }
1233
1234   return TRUE;
1235 }
1236
1237 static bfd_boolean
1238 pru_elf32_relax_section (bfd * abfd, asection * sec,
1239                           struct bfd_link_info * link_info,
1240                           bfd_boolean * again)
1241 {
1242   Elf_Internal_Shdr * symtab_hdr;
1243   Elf_Internal_Rela * internal_relocs;
1244   Elf_Internal_Rela * irel;
1245   Elf_Internal_Rela * irelend;
1246   bfd_byte *          contents = NULL;
1247   Elf_Internal_Sym *  isymbuf = NULL;
1248
1249   /* Assume nothing changes.  */
1250   *again = FALSE;
1251
1252   /* We don't have to do anything for a relocatable link, if
1253      this section does not have relocs, or if this is not a
1254      code section.  */
1255   if (bfd_link_relocatable (link_info)
1256     || (sec->flags & SEC_RELOC) == 0
1257     || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1258     return TRUE;
1259
1260   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1261
1262   /* Get a copy of the native relocations.  */
1263   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1264                                                link_info->keep_memory);
1265   if (internal_relocs == NULL)
1266     goto error_return;
1267
1268   /* Walk through them looking for relaxing opportunities.  */
1269   irelend = internal_relocs + sec->reloc_count;
1270
1271   for (irel = internal_relocs; irel < irelend; irel++)
1272     {
1273       bfd_vma symval;
1274
1275       /* Get the section contents if we haven't done so already.  */
1276       if (contents == NULL)
1277         {
1278           /* Get cached copy if it exists.  */
1279           if (elf_section_data (sec)->this_hdr.contents != NULL)
1280             contents = elf_section_data (sec)->this_hdr.contents;
1281           else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1282             goto error_return;
1283         }
1284
1285       /* Read this BFD's local symbols if we haven't done so already.  */
1286       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1287         {
1288           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1289           if (isymbuf == NULL)
1290             isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1291                                             symtab_hdr->sh_info, 0,
1292                                             NULL, NULL, NULL);
1293           if (isymbuf == NULL)
1294             goto error_return;
1295         }
1296
1297       /* Get the value of the symbol referred to by the reloc.  */
1298       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1299         {
1300           /* A local symbol.  */
1301           Elf_Internal_Sym *isym;
1302           asection *sym_sec;
1303
1304           isym = isymbuf + ELF32_R_SYM (irel->r_info);
1305           if (isym->st_shndx == SHN_UNDEF)
1306             sym_sec = bfd_und_section_ptr;
1307           else if (isym->st_shndx == SHN_ABS)
1308             sym_sec = bfd_abs_section_ptr;
1309           else if (isym->st_shndx == SHN_COMMON)
1310             sym_sec = bfd_com_section_ptr;
1311           else
1312             sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1313           symval = (isym->st_value
1314                     + sym_sec->output_section->vma + sym_sec->output_offset);
1315         }
1316       else
1317         {
1318           unsigned long indx;
1319           struct elf_link_hash_entry *h;
1320
1321           /* An external symbol.  */
1322           indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1323           h = elf_sym_hashes (abfd)[indx];
1324           BFD_ASSERT (h != NULL);
1325
1326           if (h->root.type != bfd_link_hash_defined
1327               && h->root.type != bfd_link_hash_defweak)
1328             /* This appears to be a reference to an undefined
1329                symbol.  Just ignore it--it will be caught by the
1330                regular reloc processing.  */
1331             continue;
1332
1333           symval = (h->root.u.def.value
1334                     + h->root.u.def.section->output_section->vma
1335                     + h->root.u.def.section->output_offset);
1336         }
1337
1338       /* For simplicity of coding, we are going to modify the section
1339          contents, the section relocs, and the BFD symbol table.  We
1340          must tell the rest of the code not to free up this
1341          information.  It would be possible to instead create a table
1342          of changes which have to be made, as is done in coff-mips.c;
1343          that would be more work, but would require less memory when
1344          the linker is run.  */
1345
1346       /* Check if we can remove an LDI instruction from the LDI32
1347          pseudo instruction if the upper 16 operand bits are zero.  */
1348       if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1349         {
1350           bfd_vma value = symval + irel->r_addend;
1351
1352           if (debug_relax)
1353             printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1354
1355           if ((long) value >> 16 == 0)
1356             {
1357               /* Note that we've changed the relocs, section contents.  */
1358               elf_section_data (sec)->relocs = internal_relocs;
1359               elf_section_data (sec)->this_hdr.contents = contents;
1360               symtab_hdr->contents = (unsigned char *) isymbuf;
1361
1362               /* Delete bytes.  */
1363               if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 4, 4))
1364                 goto error_return;
1365
1366               /* We're done with deletion of the second instruction.
1367                  Set a regular LDI relocation for the first instruction
1368                  we left to load the 16-bit value into the 32-bit
1369                  register.  */
1370               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1371                                            R_PRU_U16);
1372
1373               /* That will change things, so, we should relax again.
1374                  Note that this is not required, and it may be slow.  */
1375               *again = TRUE;
1376             }
1377         }
1378     }
1379
1380   if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1381     {
1382       if (!link_info->keep_memory)
1383         free (isymbuf);
1384       else
1385         {
1386           /* Cache the symbols for elf_link_input_bfd.  */
1387           symtab_hdr->contents = (unsigned char *) isymbuf;
1388         }
1389     }
1390
1391   if (contents != NULL
1392       && elf_section_data (sec)->this_hdr.contents != contents)
1393     {
1394       if (!link_info->keep_memory)
1395         free (contents);
1396       else
1397         {
1398           /* Cache the section contents for elf_link_input_bfd.  */
1399           elf_section_data (sec)->this_hdr.contents = contents;
1400         }
1401     }
1402
1403   if (internal_relocs != NULL
1404       && elf_section_data (sec)->relocs != internal_relocs)
1405     free (internal_relocs);
1406
1407   return TRUE;
1408
1409 error_return:
1410   if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1411     free (isymbuf);
1412   if (contents != NULL
1413       && elf_section_data (sec)->this_hdr.contents != contents)
1414     free (contents);
1415   if (internal_relocs != NULL
1416       && elf_section_data (sec)->relocs != internal_relocs)
1417     free (internal_relocs);
1418
1419   return FALSE;
1420 }
1421
1422 /* Free the derived linker hash table.  */
1423 static void
1424 pru_elf32_link_hash_table_free (bfd *obfd)
1425 {
1426   _bfd_elf_link_hash_table_free (obfd);
1427 }
1428
1429 /* Implement bfd_elf32_bfd_link_hash_table_create.  */
1430 static struct bfd_link_hash_table *
1431 pru_elf32_link_hash_table_create (bfd *abfd)
1432 {
1433   struct elf_link_hash_table *ret;
1434   bfd_size_type amt = sizeof (struct elf_link_hash_table);
1435
1436   ret = bfd_zmalloc (amt);
1437   if (ret == NULL)
1438     return NULL;
1439
1440   if (!_bfd_elf_link_hash_table_init (ret, abfd,
1441                                       link_hash_newfunc,
1442                                       sizeof (struct
1443                                               elf_link_hash_entry),
1444                                       PRU_ELF_DATA))
1445     {
1446       free (ret);
1447       return NULL;
1448     }
1449
1450   ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1451
1452   return &ret->root;
1453 }
1454
1455 #define ELF_ARCH                        bfd_arch_pru
1456 #define ELF_TARGET_ID                   PRU_ELF_DATA
1457 #define ELF_MACHINE_CODE                EM_TI_PRU
1458
1459 #define ELF_MAXPAGESIZE                 1
1460
1461 #define bfd_elf32_bfd_link_hash_table_create \
1462                                           pru_elf32_link_hash_table_create
1463
1464 /* Relocation table lookup macros.  */
1465
1466 #define bfd_elf32_bfd_reloc_type_lookup   pru_elf32_bfd_reloc_type_lookup
1467 #define bfd_elf32_bfd_reloc_name_lookup   pru_elf32_bfd_reloc_name_lookup
1468
1469 /* elf_info_to_howto (using RELA relocations).  */
1470
1471 #define elf_info_to_howto               pru_elf32_info_to_howto
1472
1473 /* elf backend functions.  */
1474
1475 #define elf_backend_rela_normal         1
1476
1477 #define elf_backend_relocate_section    pru_elf32_relocate_section
1478 #define bfd_elf32_bfd_relax_section     pru_elf32_relax_section
1479
1480 #define TARGET_LITTLE_SYM               pru_elf32_vec
1481 #define TARGET_LITTLE_NAME              "elf32-pru"
1482
1483 #include "elf32-target.h"