Home | History | Annotate | Line # | Download | only in bfd
elf32-pru.c revision 1.1.1.1
      1 /* 32-bit ELF support for TI PRU.
      2    Copyright (C) 2014-2017 Free Software Foundation, Inc.
      3    Contributed by Dimitar Dimitrov <dimitar (at) 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 
    847 /* Perform a diff relocation.  Nothing to do, as the difference value is
    849    already written into the section's contents.  */
    850 
    851 static bfd_reloc_status_type
    852 bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
    853 			   arelent *reloc_entry ATTRIBUTE_UNUSED,
    854 			   asymbol *symbol ATTRIBUTE_UNUSED,
    855 			   void *data ATTRIBUTE_UNUSED,
    856 			   asection *input_section ATTRIBUTE_UNUSED,
    857 			   bfd *output_bfd ATTRIBUTE_UNUSED,
    858 			   char **error_message ATTRIBUTE_UNUSED)
    859 {
    860   return bfd_reloc_ok;
    861 }
    862 
    863 
    864 /* Returns whether the relocation type passed is a diff reloc.  */
    865 
    866 static bfd_boolean
    867 elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
    868 {
    869   return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
    870 	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
    871 	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
    872 	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
    873 	  || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
    874 }
    875 
    876 /* Reduce the diff value written in the section by count if the shrinked
    877    insn address happens to fall between the two symbols for which this
    878    diff reloc was emitted.  */
    879 
    880 static void
    881 elf32_pru_adjust_diff_reloc_value (bfd *abfd,
    882 				   struct bfd_section *isec,
    883 				   Elf_Internal_Rela *irel,
    884 				   bfd_vma symval,
    885 				   bfd_vma shrinked_insn_address,
    886 				   int count)
    887 {
    888   unsigned char *reloc_contents = NULL;
    889   unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
    890   if (isec_contents == NULL)
    891   {
    892     if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
    893       return;
    894 
    895     elf_section_data (isec)->this_hdr.contents = isec_contents;
    896   }
    897 
    898   reloc_contents = isec_contents + irel->r_offset;
    899 
    900   /* Read value written in object file.  */
    901   bfd_signed_vma x = 0;
    902   switch (ELF32_R_TYPE (irel->r_info))
    903   {
    904   case R_PRU_GNU_DIFF8:
    905     {
    906       x = bfd_get_signed_8 (abfd, reloc_contents);
    907       break;
    908     }
    909   case R_PRU_GNU_DIFF16:
    910     {
    911       x = bfd_get_signed_16 (abfd, reloc_contents);
    912       break;
    913     }
    914   case R_PRU_GNU_DIFF32:
    915     {
    916       x = bfd_get_signed_32 (abfd, reloc_contents);
    917       break;
    918     }
    919   case R_PRU_GNU_DIFF16_PMEM:
    920     {
    921       x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
    922       break;
    923     }
    924   case R_PRU_GNU_DIFF32_PMEM:
    925     {
    926       x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
    927       break;
    928     }
    929   default:
    930     {
    931       BFD_FAIL ();
    932     }
    933   }
    934 
    935   /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
    936      into the object file at the reloc offset.  sym2's logical value is
    937      symval (<start_of_section>) + reloc addend.  Compute the start and end
    938      addresses and check if the shrinked insn falls between sym1 and sym2.  */
    939 
    940   bfd_vma end_address = symval + irel->r_addend;
    941   bfd_vma start_address = end_address - x;
    942 
    943   /* Shrink the absolute DIFF value (get the to labels "closer"
    944      together), because we have removed data between labels.  */
    945   if (x < 0)
    946     {
    947       x += count;
    948       /* In case the signed x is negative, restore order.  */
    949       SWAP_VALS (end_address, start_address);
    950     }
    951   else
    952     {
    953       x -= count;
    954     }
    955 
    956   /* Reduce the diff value by count bytes and write it back into section
    957     contents.  */
    958 
    959   if (shrinked_insn_address >= start_address
    960       && shrinked_insn_address <= end_address)
    961   {
    962     switch (ELF32_R_TYPE (irel->r_info))
    963     {
    964     case R_PRU_GNU_DIFF8:
    965       {
    966 	bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
    967 	break;
    968       }
    969     case R_PRU_GNU_DIFF16:
    970       {
    971 	bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
    972 	break;
    973       }
    974     case R_PRU_GNU_DIFF32:
    975       {
    976 	bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
    977 	break;
    978       }
    979     case R_PRU_GNU_DIFF16_PMEM:
    980       {
    981 	bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
    982 	break;
    983       }
    984     case R_PRU_GNU_DIFF32_PMEM:
    985       {
    986 	bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
    987 	break;
    988       }
    989     default:
    990       {
    991 	BFD_FAIL ();
    992       }
    993     }
    994 
    995   }
    996 }
    997 
    998 /* Delete some bytes from a section while changing the size of an instruction.
    999    The parameter "addr" denotes the section-relative offset pointing just
   1000    behind the shrinked instruction. "addr+count" point at the first
   1001    byte just behind the original unshrinked instruction.
   1002 
   1003    Idea copied from the AVR port.  */
   1004 
   1005 static bfd_boolean
   1006 pru_elf_relax_delete_bytes (bfd *abfd,
   1007 			    asection *sec,
   1008 			    bfd_vma addr,
   1009 			    int count)
   1010 {
   1011   Elf_Internal_Shdr *symtab_hdr;
   1012   unsigned int sec_shndx;
   1013   bfd_byte *contents;
   1014   Elf_Internal_Rela *irel, *irelend;
   1015   Elf_Internal_Sym *isym;
   1016   Elf_Internal_Sym *isymbuf = NULL;
   1017   bfd_vma toaddr;
   1018   struct elf_link_hash_entry **sym_hashes;
   1019   struct elf_link_hash_entry **end_hashes;
   1020   unsigned int symcount;
   1021 
   1022   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   1023   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
   1024   contents = elf_section_data (sec)->this_hdr.contents;
   1025 
   1026   toaddr = sec->size;
   1027 
   1028   irel = elf_section_data (sec)->relocs;
   1029   irelend = irel + sec->reloc_count;
   1030 
   1031   /* Actually delete the bytes.  */
   1032   if (toaddr - addr - count > 0)
   1033     memmove (contents + addr, contents + addr + count,
   1034 	     (size_t) (toaddr - addr - count));
   1035   sec->size -= count;
   1036 
   1037   /* Adjust all the reloc addresses.  */
   1038   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
   1039     {
   1040       bfd_vma old_reloc_address;
   1041 
   1042       old_reloc_address = (sec->output_section->vma
   1043 			   + sec->output_offset + irel->r_offset);
   1044 
   1045       /* Get the new reloc address.  */
   1046       if ((irel->r_offset > addr
   1047 	   && irel->r_offset < toaddr))
   1048 	{
   1049 	  if (debug_relax)
   1050 	    printf ("Relocation at address 0x%x needs to be moved.\n"
   1051 		    "Old section offset: 0x%x, New section offset: 0x%x \n",
   1052 		    (unsigned int) old_reloc_address,
   1053 		    (unsigned int) irel->r_offset,
   1054 		    (unsigned int) ((irel->r_offset) - count));
   1055 
   1056 	  irel->r_offset -= count;
   1057 	}
   1058 
   1059     }
   1060 
   1061    /* The reloc's own addresses are now ok.  However, we need to readjust
   1062       the reloc's addend, i.e. the reloc's value if two conditions are met:
   1063       1.) the reloc is relative to a symbol in this section that
   1064 	  is located in front of the shrinked instruction
   1065       2.) symbol plus addend end up behind the shrinked instruction.
   1066 
   1067       The most common case where this happens are relocs relative to
   1068       the section-start symbol.
   1069 
   1070       This step needs to be done for all of the sections of the bfd.  */
   1071 
   1072   {
   1073     struct bfd_section *isec;
   1074 
   1075     for (isec = abfd->sections; isec; isec = isec->next)
   1076      {
   1077        bfd_vma symval;
   1078        bfd_vma shrinked_insn_address;
   1079 
   1080        if (isec->reloc_count == 0)
   1081 	 continue;
   1082 
   1083        shrinked_insn_address = (sec->output_section->vma
   1084 				+ sec->output_offset + addr - count);
   1085 
   1086        irel = elf_section_data (isec)->relocs;
   1087        /* PR 12161: Read in the relocs for this section if necessary.  */
   1088        if (irel == NULL)
   1089 	 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
   1090 
   1091        for (irelend = irel + isec->reloc_count;
   1092 	    irel < irelend;
   1093 	    irel++)
   1094 	 {
   1095 	   /* Read this BFD's local symbols if we haven't done
   1096 	      so already.  */
   1097 	   if (isymbuf == NULL && symtab_hdr->sh_info != 0)
   1098 	     {
   1099 	       isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   1100 	       if (isymbuf == NULL)
   1101 		 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
   1102 						 symtab_hdr->sh_info, 0,
   1103 						 NULL, NULL, NULL);
   1104 	       if (isymbuf == NULL)
   1105 		 return FALSE;
   1106 	     }
   1107 
   1108 	   /* Get the value of the symbol referred to by the reloc.  */
   1109 	   if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
   1110 	     {
   1111 	       /* A local symbol.  */
   1112 	       asection *sym_sec;
   1113 
   1114 	       isym = isymbuf + ELF32_R_SYM (irel->r_info);
   1115 	       sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
   1116 	       symval = isym->st_value;
   1117 	       /* If the reloc is absolute, it will not have
   1118 		  a symbol or section associated with it.  */
   1119 	       if (sym_sec == sec)
   1120 		 {
   1121 		   symval += sym_sec->output_section->vma
   1122 		     + sym_sec->output_offset;
   1123 
   1124 		   if (debug_relax)
   1125 		     printf ("Checking if the relocation's "
   1126 			     "addend needs corrections.\n"
   1127 			     "Address of anchor symbol: 0x%x \n"
   1128 			     "Address of relocation target: 0x%x \n"
   1129 			     "Address of relaxed insn: 0x%x \n",
   1130 			     (unsigned int) symval,
   1131 			     (unsigned int) (symval + irel->r_addend),
   1132 			     (unsigned int) shrinked_insn_address);
   1133 
   1134 		   /* Shrink the special DIFF relocations.  */
   1135 		   if (elf32_pru_is_diff_reloc (irel))
   1136 		     {
   1137 		       elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
   1138 							  symval,
   1139 							  shrinked_insn_address,
   1140 							  count);
   1141 		     }
   1142 
   1143 		   /* Fix the addend, if it is affected.  */
   1144 		   if (symval <= shrinked_insn_address
   1145 		       && (symval + irel->r_addend) > shrinked_insn_address)
   1146 		     {
   1147 
   1148 		       irel->r_addend -= count;
   1149 
   1150 		       if (debug_relax)
   1151 			 printf ("Relocation's addend needed to be fixed \n");
   1152 		     }
   1153 		 }
   1154 	       /* else...Reference symbol is absolute.
   1155 		  No adjustment needed.  */
   1156 	     }
   1157 	   /* else...Reference symbol is extern.  No need for adjusting
   1158 	      the addend.  */
   1159 	 }
   1160      }
   1161   }
   1162 
   1163   /* Adjust the local symbols defined in this section.  */
   1164   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
   1165   /* Fix PR 9841, there may be no local symbols.  */
   1166   if (isym != NULL)
   1167     {
   1168       Elf_Internal_Sym *isymend;
   1169 
   1170       isymend = isym + symtab_hdr->sh_info;
   1171       for (; isym < isymend; isym++)
   1172 	{
   1173 	  if (isym->st_shndx == sec_shndx)
   1174 	    {
   1175 	      if (isym->st_value > addr
   1176 		  && isym->st_value <= toaddr)
   1177 		isym->st_value -= count;
   1178 
   1179 	      if (isym->st_value <= addr
   1180 		  && isym->st_value + isym->st_size > addr)
   1181 		{
   1182 		  /* If this assert fires then we have a symbol that ends
   1183 		     part way through an instruction.  Does that make
   1184 		     sense?  */
   1185 		  BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
   1186 		  isym->st_size -= count;
   1187 		}
   1188 	    }
   1189 	}
   1190     }
   1191 
   1192   /* Now adjust the global symbols defined in this section.  */
   1193   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
   1194 	      - symtab_hdr->sh_info);
   1195   sym_hashes = elf_sym_hashes (abfd);
   1196   end_hashes = sym_hashes + symcount;
   1197   for (; sym_hashes < end_hashes; sym_hashes++)
   1198     {
   1199       struct elf_link_hash_entry *sym_hash = *sym_hashes;
   1200       if ((sym_hash->root.type == bfd_link_hash_defined
   1201 	   || sym_hash->root.type == bfd_link_hash_defweak)
   1202 	  && sym_hash->root.u.def.section == sec)
   1203 	{
   1204 	  if (sym_hash->root.u.def.value > addr
   1205 	      && sym_hash->root.u.def.value <= toaddr)
   1206 	    sym_hash->root.u.def.value -= count;
   1207 
   1208 	  if (sym_hash->root.u.def.value <= addr
   1209 	      && (sym_hash->root.u.def.value + sym_hash->size > addr))
   1210 	    {
   1211 	      /* If this assert fires then we have a symbol that ends
   1212 		 part way through an instruction.  Does that make
   1213 		 sense?  */
   1214 	      BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
   1215 			  >= addr + count);
   1216 	      sym_hash->size -= count;
   1217 	    }
   1218 	}
   1219     }
   1220 
   1221   return TRUE;
   1222 }
   1223 
   1224 static bfd_boolean
   1225 pru_elf32_relax_section (bfd * abfd, asection * sec,
   1226 			  struct bfd_link_info * link_info,
   1227 			  bfd_boolean * again)
   1228 {
   1229   Elf_Internal_Shdr * symtab_hdr;
   1230   Elf_Internal_Rela * internal_relocs;
   1231   Elf_Internal_Rela * irel;
   1232   Elf_Internal_Rela * irelend;
   1233   bfd_byte *	      contents = NULL;
   1234   Elf_Internal_Sym *  isymbuf = NULL;
   1235 
   1236   /* Assume nothing changes.  */
   1237   *again = FALSE;
   1238 
   1239   /* We don't have to do anything for a relocatable link, if
   1240      this section does not have relocs, or if this is not a
   1241      code section.  */
   1242   if (bfd_link_relocatable (link_info)
   1243     || (sec->flags & SEC_RELOC) == 0
   1244     || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
   1245     return TRUE;
   1246 
   1247   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
   1248 
   1249   /* Get a copy of the native relocations.  */
   1250   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
   1251 					       link_info->keep_memory);
   1252   if (internal_relocs == NULL)
   1253     goto error_return;
   1254 
   1255   /* Walk through them looking for relaxing opportunities.  */
   1256   irelend = internal_relocs + sec->reloc_count;
   1257 
   1258   for (irel = internal_relocs; irel < irelend; irel++)
   1259     {
   1260       bfd_vma symval;
   1261 
   1262       /* Get the section contents if we haven't done so already.  */
   1263       if (contents == NULL)
   1264 	{
   1265 	  /* Get cached copy if it exists.  */
   1266 	  if (elf_section_data (sec)->this_hdr.contents != NULL)
   1267 	    contents = elf_section_data (sec)->this_hdr.contents;
   1268 	  else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
   1269 	    goto error_return;
   1270 	}
   1271 
   1272       /* Read this BFD's local symbols if we haven't done so already.  */
   1273       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
   1274 	{
   1275 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   1276 	  if (isymbuf == NULL)
   1277 	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
   1278 					    symtab_hdr->sh_info, 0,
   1279 					    NULL, NULL, NULL);
   1280 	  if (isymbuf == NULL)
   1281 	    goto error_return;
   1282 	}
   1283 
   1284       /* Get the value of the symbol referred to by the reloc.  */
   1285       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
   1286 	{
   1287 	  /* A local symbol.  */
   1288 	  Elf_Internal_Sym *isym;
   1289 	  asection *sym_sec;
   1290 
   1291 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
   1292 	  if (isym->st_shndx == SHN_UNDEF)
   1293 	    sym_sec = bfd_und_section_ptr;
   1294 	  else if (isym->st_shndx == SHN_ABS)
   1295 	    sym_sec = bfd_abs_section_ptr;
   1296 	  else if (isym->st_shndx == SHN_COMMON)
   1297 	    sym_sec = bfd_com_section_ptr;
   1298 	  else
   1299 	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
   1300 	  symval = (isym->st_value
   1301 		    + sym_sec->output_section->vma + sym_sec->output_offset);
   1302 	}
   1303       else
   1304 	{
   1305 	  unsigned long indx;
   1306 	  struct elf_link_hash_entry *h;
   1307 
   1308 	  /* An external symbol.  */
   1309 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
   1310 	  h = elf_sym_hashes (abfd)[indx];
   1311 	  BFD_ASSERT (h != NULL);
   1312 
   1313 	  if (h->root.type != bfd_link_hash_defined
   1314 	      && h->root.type != bfd_link_hash_defweak)
   1315 	    /* This appears to be a reference to an undefined
   1316 	       symbol.  Just ignore it--it will be caught by the
   1317 	       regular reloc processing.  */
   1318 	    continue;
   1319 
   1320 	  symval = (h->root.u.def.value
   1321 		    + h->root.u.def.section->output_section->vma
   1322 		    + h->root.u.def.section->output_offset);
   1323 	}
   1324 
   1325       /* For simplicity of coding, we are going to modify the section
   1326 	 contents, the section relocs, and the BFD symbol table.  We
   1327 	 must tell the rest of the code not to free up this
   1328 	 information.  It would be possible to instead create a table
   1329 	 of changes which have to be made, as is done in coff-mips.c;
   1330 	 that would be more work, but would require less memory when
   1331 	 the linker is run.  */
   1332 
   1333       /* Check if we can remove an LDI instruction from the LDI32
   1334 	 pseudo instruction if the upper 16 operand bits are zero.  */
   1335       if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
   1336 	{
   1337 	  bfd_vma value = symval + irel->r_addend;
   1338 
   1339 	  if (debug_relax)
   1340 	    printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
   1341 
   1342 	  if ((long) value >> 16 == 0)
   1343 	    {
   1344 	      /* Note that we've changed the relocs, section contents.  */
   1345 	      elf_section_data (sec)->relocs = internal_relocs;
   1346 	      elf_section_data (sec)->this_hdr.contents = contents;
   1347 	      symtab_hdr->contents = (unsigned char *) isymbuf;
   1348 
   1349 	      /* Delete bytes.  */
   1350 	      if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 4, 4))
   1351 		goto error_return;
   1352 
   1353 	      /* We're done with deletion of the second instruction.
   1354 		 Set a regular LDI relocation for the first instruction
   1355 		 we left to load the 16-bit value into the 32-bit
   1356 		 register.  */
   1357 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1358 					   R_PRU_U16);
   1359 
   1360 	      /* That will change things, so, we should relax again.
   1361 		 Note that this is not required, and it may be slow.  */
   1362 	      *again = TRUE;
   1363 	    }
   1364 	}
   1365     }
   1366 
   1367   if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
   1368     {
   1369       if (!link_info->keep_memory)
   1370 	free (isymbuf);
   1371       else
   1372 	{
   1373 	  /* Cache the symbols for elf_link_input_bfd.  */
   1374 	  symtab_hdr->contents = (unsigned char *) isymbuf;
   1375 	}
   1376     }
   1377 
   1378   if (contents != NULL
   1379       && elf_section_data (sec)->this_hdr.contents != contents)
   1380     {
   1381       if (!link_info->keep_memory)
   1382 	free (contents);
   1383       else
   1384 	{
   1385 	  /* Cache the section contents for elf_link_input_bfd.  */
   1386 	  elf_section_data (sec)->this_hdr.contents = contents;
   1387 	}
   1388     }
   1389 
   1390   if (internal_relocs != NULL
   1391       && elf_section_data (sec)->relocs != internal_relocs)
   1392     free (internal_relocs);
   1393 
   1394   return TRUE;
   1395 
   1396 error_return:
   1397   if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
   1398     free (isymbuf);
   1399   if (contents != NULL
   1400       && elf_section_data (sec)->this_hdr.contents != contents)
   1401     free (contents);
   1402   if (internal_relocs != NULL
   1403       && elf_section_data (sec)->relocs != internal_relocs)
   1404     free (internal_relocs);
   1405 
   1406   return FALSE;
   1407 }
   1408 
   1409 /* Free the derived linker hash table.  */
   1410 static void
   1411 pru_elf32_link_hash_table_free (bfd *obfd)
   1412 {
   1413   _bfd_elf_link_hash_table_free (obfd);
   1414 }
   1415 
   1416 /* Implement bfd_elf32_bfd_link_hash_table_create.  */
   1417 static struct bfd_link_hash_table *
   1418 pru_elf32_link_hash_table_create (bfd *abfd)
   1419 {
   1420   struct elf_link_hash_table *ret;
   1421   bfd_size_type amt = sizeof (struct elf_link_hash_table);
   1422 
   1423   ret = bfd_zmalloc (amt);
   1424   if (ret == NULL)
   1425     return NULL;
   1426 
   1427   if (!_bfd_elf_link_hash_table_init (ret, abfd,
   1428 				      link_hash_newfunc,
   1429 				      sizeof (struct
   1430 					      elf_link_hash_entry),
   1431 				      PRU_ELF_DATA))
   1432     {
   1433       free (ret);
   1434       return NULL;
   1435     }
   1436 
   1437   ret->root.hash_table_free = pru_elf32_link_hash_table_free;
   1438 
   1439   return &ret->root;
   1440 }
   1441 
   1442 #define ELF_ARCH			bfd_arch_pru
   1443 #define ELF_TARGET_ID			PRU_ELF_DATA
   1444 #define ELF_MACHINE_CODE		EM_TI_PRU
   1445 
   1446 #define ELF_MAXPAGESIZE			1
   1447 
   1448 #define bfd_elf32_bfd_link_hash_table_create \
   1449 					  pru_elf32_link_hash_table_create
   1450 
   1451 /* Relocation table lookup macros.  */
   1452 
   1453 #define bfd_elf32_bfd_reloc_type_lookup	  pru_elf32_bfd_reloc_type_lookup
   1454 #define bfd_elf32_bfd_reloc_name_lookup	  pru_elf32_bfd_reloc_name_lookup
   1455 
   1456 /* elf_info_to_howto (using RELA relocations).  */
   1457 
   1458 #define elf_info_to_howto		pru_elf32_info_to_howto
   1459 
   1460 /* elf backend functions.  */
   1461 
   1462 #define elf_backend_rela_normal		1
   1463 
   1464 #define elf_backend_relocate_section	pru_elf32_relocate_section
   1465 #define bfd_elf32_bfd_relax_section	pru_elf32_relax_section
   1466 
   1467 #define TARGET_LITTLE_SYM		pru_elf32_vec
   1468 #define TARGET_LITTLE_NAME		"elf32-pru"
   1469 
   1470 #include "elf32-target.h"
   1471