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