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