Home | History | Annotate | Line # | Download | only in bfd
elf32-microblaze.c revision 1.1.1.7.4.1
      1          1.1  christos /* Xilinx MicroBlaze-specific support for 32-bit ELF
      2          1.1  christos 
      3  1.1.1.7.4.1  christos    Copyright (C) 2009-2019 Free Software Foundation, Inc.
      4          1.1  christos 
      5          1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      6          1.1  christos 
      7          1.1  christos    This program is free software; you can redistribute it and/or modify
      8          1.1  christos    it under the terms of the GNU General Public License as published by
      9          1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10          1.1  christos    (at your option) any later version.
     11          1.1  christos 
     12          1.1  christos    This program is distributed in the hope that it will be useful,
     13          1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14          1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15          1.1  christos    GNU General Public License for more details.
     16          1.1  christos 
     17          1.1  christos    You should have received a copy of the GNU General Public License
     18          1.1  christos    along with this program; if not, write to the
     19          1.1  christos    Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
     20          1.1  christos    Boston, MA 02110-1301, USA.  */
     21          1.1  christos 
     22          1.1  christos 
     23          1.1  christos int dbg = 0;
     24          1.1  christos 
     25          1.1  christos #include "sysdep.h"
     26      1.1.1.2  christos #include "bfd.h"
     27          1.1  christos #include "bfdlink.h"
     28          1.1  christos #include "libbfd.h"
     29          1.1  christos #include "elf-bfd.h"
     30          1.1  christos #include "elf/microblaze.h"
     31          1.1  christos #include <assert.h>
     32          1.1  christos 
     33          1.1  christos #define	USE_RELA	/* Only USE_REL is actually significant, but this is
     34          1.1  christos 			   here are a reminder...  */
     35          1.1  christos #define INST_WORD_SIZE 4
     36          1.1  christos 
     37          1.1  christos static int ro_small_data_pointer = 0;
     38          1.1  christos static int rw_small_data_pointer = 0;
     39          1.1  christos 
     40          1.1  christos static reloc_howto_type * microblaze_elf_howto_table [(int) R_MICROBLAZE_max];
     41          1.1  christos 
     42          1.1  christos static reloc_howto_type microblaze_elf_howto_raw[] =
     43          1.1  christos {
     44          1.1  christos    /* This reloc does nothing.  */
     45          1.1  christos    HOWTO (R_MICROBLAZE_NONE,	/* Type.  */
     46  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
     47  1.1.1.7.4.1  christos 	  3,			/* Size (0 = byte, 1 = short, 2 = long).  */
     48  1.1.1.7.4.1  christos 	  0,			/* Bitsize.  */
     49  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
     50  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
     51  1.1.1.7.4.1  christos 	  complain_overflow_dont,  /* Complain on overflow.  */
     52  1.1.1.7.4.1  christos 	  NULL,			 /* Special Function.  */
     53  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_NONE",	/* Name.  */
     54  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
     55  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
     56  1.1.1.7.4.1  christos 	  0,			/* Dest Mask.  */
     57  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
     58          1.1  christos 
     59          1.1  christos    /* A standard 32 bit relocation.  */
     60  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_32,	/* Type.  */
     61  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
     62  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
     63  1.1.1.7.4.1  christos 	  32,			/* Bitsize.  */
     64  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
     65  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
     66  1.1.1.7.4.1  christos 	  complain_overflow_bitfield, /* Complain on overflow.  */
     67  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
     68  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_32",	/* Name.  */
     69  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
     70  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
     71  1.1.1.7.4.1  christos 	  0xffffffff,		/* Dest Mask.  */
     72  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
     73          1.1  christos 
     74          1.1  christos    /* A standard PCREL 32 bit relocation.  */
     75          1.1  christos    HOWTO (R_MICROBLAZE_32_PCREL,/* Type.  */
     76  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
     77  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
     78  1.1.1.7.4.1  christos 	  32,			/* Bitsize.  */
     79  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
     80  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
     81  1.1.1.7.4.1  christos 	  complain_overflow_bitfield, /* Complain on overflow.  */
     82  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
     83  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_32_PCREL",	/* Name.  */
     84  1.1.1.7.4.1  christos 	  TRUE,			/* Partial Inplace.  */
     85  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
     86  1.1.1.7.4.1  christos 	  0xffffffff,		/* Dest Mask.  */
     87  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
     88          1.1  christos 
     89          1.1  christos    /* A 64 bit PCREL relocation.  Table-entry not really used.  */
     90          1.1  christos    HOWTO (R_MICROBLAZE_64_PCREL,/* Type.  */
     91  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
     92  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
     93  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
     94  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
     95  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
     96  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
     97  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
     98  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_64_PCREL",	/* Name.  */
     99  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    100  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    101  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    102  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
    103          1.1  christos 
    104          1.1  christos    /* The low half of a PCREL 32 bit relocation.  */
    105  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_32_PCREL_LO,	/* Type.  */
    106  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    107  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    108  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    109  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    110  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    111  1.1.1.7.4.1  christos 	  complain_overflow_signed, /* Complain on overflow.  */
    112  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,	/* Special Function.  */
    113  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_32_PCREL_LO",	/* Name.  */
    114  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    115  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    116  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    117  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
    118          1.1  christos 
    119          1.1  christos    /* A 64 bit relocation.  Table entry not really used.  */
    120  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_64,	/* Type.  */
    121  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    122  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    123  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    124  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    125  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    126  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    127  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    128  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_64",	/* Name.  */
    129  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    130  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    131  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    132  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    133          1.1  christos 
    134          1.1  christos    /* The low half of a 32 bit relocation.  */
    135  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_32_LO,	/* Type.  */
    136  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    137  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    138  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    139  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    140  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    141  1.1.1.7.4.1  christos 	  complain_overflow_signed, /* Complain on overflow.  */
    142  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    143  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_32_LO", /* Name.  */
    144  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    145  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    146  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    147  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    148          1.1  christos 
    149          1.1  christos    /* Read-only small data section relocation.  */
    150  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_SRO32,	/* Type.  */
    151  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    152  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    153  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    154  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    155  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    156  1.1.1.7.4.1  christos 	  complain_overflow_bitfield, /* Complain on overflow.  */
    157  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    158  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_SRO32", /* Name.  */
    159  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    160  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    161  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    162  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    163          1.1  christos 
    164          1.1  christos    /* Read-write small data area relocation.  */
    165  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_SRW32,	/* Type.  */
    166  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    167  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    168  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    169  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    170  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    171  1.1.1.7.4.1  christos 	  complain_overflow_bitfield, /* Complain on overflow.  */
    172  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    173  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_SRW32", /* Name.  */
    174  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    175  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    176  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    177  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    178          1.1  christos 
    179  1.1.1.7.4.1  christos    /* This reloc does nothing.	Used for relaxation.  */
    180          1.1  christos    HOWTO (R_MICROBLAZE_64_NONE,	/* Type.  */
    181  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    182  1.1.1.7.4.1  christos 	  3,			/* Size (0 = byte, 1 = short, 2 = long).  */
    183  1.1.1.7.4.1  christos 	  0,			/* Bitsize.  */
    184  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    185  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    186  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    187  1.1.1.7.4.1  christos 	  NULL,			 /* Special Function.  */
    188  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_64_NONE",/* Name.  */
    189  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    190  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    191  1.1.1.7.4.1  christos 	  0,			/* Dest Mask.  */
    192  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    193          1.1  christos 
    194          1.1  christos    /* Symbol Op Symbol relocation.  */
    195  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_32_SYM_OP_SYM,		/* Type.  */
    196  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    197  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    198  1.1.1.7.4.1  christos 	  32,			/* Bitsize.  */
    199  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    200  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    201  1.1.1.7.4.1  christos 	  complain_overflow_bitfield, /* Complain on overflow.  */
    202  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    203  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_32_SYM_OP_SYM",		/* Name.  */
    204  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    205  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    206  1.1.1.7.4.1  christos 	  0xffffffff,		/* Dest Mask.  */
    207  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    208          1.1  christos 
    209          1.1  christos    /* GNU extension to record C++ vtable hierarchy.  */
    210          1.1  christos    HOWTO (R_MICROBLAZE_GNU_VTINHERIT, /* Type.  */
    211  1.1.1.7.4.1  christos 	  0,			 /* Rightshift.  */
    212  1.1.1.7.4.1  christos 	  2,			 /* Size (0 = byte, 1 = short, 2 = long).  */
    213  1.1.1.7.4.1  christos 	  0,			 /* Bitsize.  */
    214  1.1.1.7.4.1  christos 	  FALSE,		 /* PC_relative.  */
    215  1.1.1.7.4.1  christos 	  0,			 /* Bitpos.  */
    216  1.1.1.7.4.1  christos 	  complain_overflow_dont,/* Complain on overflow.  */
    217  1.1.1.7.4.1  christos 	  NULL,			 /* Special Function.  */
    218  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_GNU_VTINHERIT", /* Name.  */
    219  1.1.1.7.4.1  christos 	  FALSE,		 /* Partial Inplace.  */
    220  1.1.1.7.4.1  christos 	  0,			 /* Source Mask.  */
    221  1.1.1.7.4.1  christos 	  0,			 /* Dest Mask.  */
    222  1.1.1.7.4.1  christos 	  FALSE),		 /* PC relative offset?  */
    223          1.1  christos 
    224          1.1  christos    /* GNU extension to record C++ vtable member usage.  */
    225          1.1  christos    HOWTO (R_MICROBLAZE_GNU_VTENTRY,   /* Type.  */
    226  1.1.1.7.4.1  christos 	  0,			 /* Rightshift.  */
    227  1.1.1.7.4.1  christos 	  2,			 /* Size (0 = byte, 1 = short, 2 = long).  */
    228  1.1.1.7.4.1  christos 	  0,			 /* Bitsize.  */
    229  1.1.1.7.4.1  christos 	  FALSE,		 /* PC_relative.  */
    230  1.1.1.7.4.1  christos 	  0,			 /* Bitpos.  */
    231  1.1.1.7.4.1  christos 	  complain_overflow_dont,/* Complain on overflow.  */
    232  1.1.1.7.4.1  christos 	  _bfd_elf_rel_vtable_reloc_fn,	 /* Special Function.  */
    233  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_GNU_VTENTRY", /* Name.  */
    234  1.1.1.7.4.1  christos 	  FALSE,		 /* Partial Inplace.  */
    235  1.1.1.7.4.1  christos 	  0,			 /* Source Mask.  */
    236  1.1.1.7.4.1  christos 	  0,			 /* Dest Mask.  */
    237  1.1.1.7.4.1  christos 	  FALSE),		 /* PC relative offset?  */
    238          1.1  christos 
    239          1.1  christos    /* A 64 bit GOTPC relocation.  Table-entry not really used.  */
    240  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_GOTPC_64,	/* Type.  */
    241  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    242  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    243  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    244  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    245  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    246  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    247  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,	/* Special Function.  */
    248  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_GOTPC_64",	/* Name.  */
    249  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    250  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    251  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    252  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
    253  1.1.1.7.4.1  christos 
    254  1.1.1.7.4.1  christos      /* A 64 bit TEXTPCREL relocation.  Table-entry not really used.  */
    255  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_TEXTPCREL_64,   	/* Type.  */
    256  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    257  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    258  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    259  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    260  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    261  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    262  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,	/* Special Function.  */
    263  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_TEXTPCREL_64", 	/* Name.  */
    264  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    265  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    266  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    267  1.1.1.7.4.1  christos 	  TRUE), 		/* PC relative offset?  */
    268          1.1  christos 
    269          1.1  christos    /* A 64 bit GOT relocation.  Table-entry not really used.  */
    270          1.1  christos    HOWTO (R_MICROBLAZE_GOT_64,  /* Type.  */
    271  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    272  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    273  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    274  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    275  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    276  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    277  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    278  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_GOT_64",/* Name.  */
    279  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    280  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    281  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    282  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    283  1.1.1.7.4.1  christos 
    284  1.1.1.7.4.1  christos     /* A 64 bit TEXTREL relocation.  Table-entry not really used.  */
    285  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_TEXTREL_64,  /* Type.  */
    286  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    287  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    288  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    289  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    290  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    291  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    292  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    293  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_TEXTREL_64",/* Name.  */
    294  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    295  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    296  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    297  1.1.1.7.4.1  christos 	  FALSE), 		/* PC relative offset?  */
    298          1.1  christos 
    299          1.1  christos    /* A 64 bit PLT relocation.  Table-entry not really used.  */
    300          1.1  christos    HOWTO (R_MICROBLAZE_PLT_64,  /* Type.  */
    301  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    302  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    303  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    304  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    305  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    306  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    307  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    308  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_PLT_64",/* Name.  */
    309  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    310  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    311  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    312  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
    313          1.1  christos 
    314          1.1  christos    /*  Table-entry not really used.  */
    315  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_REL,	/* Type.  */
    316  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    317  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    318  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    319  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    320  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    321  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    322  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    323  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_REL",	/* Name.  */
    324  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    325  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    326  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    327  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
    328          1.1  christos 
    329          1.1  christos    /*  Table-entry not really used.  */
    330          1.1  christos    HOWTO (R_MICROBLAZE_JUMP_SLOT,/* Type.  */
    331  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    332  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    333  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    334  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    335  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    336  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    337  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    338  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_JUMP_SLOT",	/* Name.  */
    339  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    340  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    341  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    342  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
    343          1.1  christos 
    344          1.1  christos    /*  Table-entry not really used.  */
    345          1.1  christos    HOWTO (R_MICROBLAZE_GLOB_DAT,/* Type.  */
    346  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    347  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    348  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    349  1.1.1.7.4.1  christos 	  TRUE,			/* PC_relative.  */
    350  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    351  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    352  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    353  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_GLOB_DAT",	/* Name.  */
    354  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    355  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    356  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    357  1.1.1.7.4.1  christos 	  TRUE),		/* PC relative offset?  */
    358          1.1  christos 
    359          1.1  christos    /* A 64 bit GOT relative relocation.  Table-entry not really used.  */
    360  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_GOTOFF_64,	/* Type.  */
    361  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    362  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    363  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    364  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    365  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    366  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    367  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    368  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_GOTOFF_64",	/* Name.  */
    369  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    370  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    371  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    372  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    373          1.1  christos 
    374          1.1  christos    /* A 32 bit GOT relative relocation.  Table-entry not really used.  */
    375  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_GOTOFF_32,	/* Type.  */
    376  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    377  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    378  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    379  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    380  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    381  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    382  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,	/* Special Function.  */
    383  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_GOTOFF_32",	/* Name.  */
    384  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    385  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    386  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    387  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    388          1.1  christos 
    389          1.1  christos    /* COPY relocation.  Table-entry not really used.  */
    390  1.1.1.7.4.1  christos    HOWTO (R_MICROBLAZE_COPY,	/* Type.  */
    391  1.1.1.7.4.1  christos 	  0,			/* Rightshift.  */
    392  1.1.1.7.4.1  christos 	  2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    393  1.1.1.7.4.1  christos 	  16,			/* Bitsize.  */
    394  1.1.1.7.4.1  christos 	  FALSE,		/* PC_relative.  */
    395  1.1.1.7.4.1  christos 	  0,			/* Bitpos.  */
    396  1.1.1.7.4.1  christos 	  complain_overflow_dont, /* Complain on overflow.  */
    397  1.1.1.7.4.1  christos 	  bfd_elf_generic_reloc,/* Special Function.  */
    398  1.1.1.7.4.1  christos 	  "R_MICROBLAZE_COPY",	/* Name.  */
    399  1.1.1.7.4.1  christos 	  FALSE,		/* Partial Inplace.  */
    400  1.1.1.7.4.1  christos 	  0,			/* Source Mask.  */
    401  1.1.1.7.4.1  christos 	  0x0000ffff,		/* Dest Mask.  */
    402  1.1.1.7.4.1  christos 	  FALSE),		/* PC relative offset?  */
    403      1.1.1.2  christos 
    404      1.1.1.2  christos    /* Marker relocs for TLS.  */
    405      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLS,
    406      1.1.1.2  christos 	 0,			/* rightshift */
    407      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    408      1.1.1.2  christos 	 32,			/* bitsize */
    409      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    410      1.1.1.2  christos 	 0,			/* bitpos */
    411      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    412      1.1.1.2  christos 	 bfd_elf_generic_reloc,	/* special_function */
    413      1.1.1.2  christos 	 "R_MICROBLAZE_TLS",		/* name */
    414      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    415      1.1.1.2  christos 	 0,			/* src_mask */
    416      1.1.1.2  christos 	 0x0000ffff,			/* dst_mask */
    417      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    418      1.1.1.2  christos 
    419      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLSGD,
    420      1.1.1.2  christos 	 0,			/* rightshift */
    421      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    422      1.1.1.2  christos 	 32,			/* bitsize */
    423      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    424      1.1.1.2  christos 	 0,			/* bitpos */
    425      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    426      1.1.1.2  christos 	 bfd_elf_generic_reloc, /* special_function */
    427      1.1.1.2  christos 	 "R_MICROBLAZE_TLSGD",		/* name */
    428      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    429      1.1.1.2  christos 	 0,			/* src_mask */
    430      1.1.1.2  christos 	 0x0000ffff,			/* dst_mask */
    431      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    432      1.1.1.2  christos 
    433      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLSLD,
    434      1.1.1.2  christos 	 0,			/* rightshift */
    435      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    436      1.1.1.2  christos 	 32,			/* bitsize */
    437      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    438      1.1.1.2  christos 	 0,			/* bitpos */
    439      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    440      1.1.1.2  christos 	 bfd_elf_generic_reloc, /* special_function */
    441      1.1.1.2  christos 	 "R_MICROBLAZE_TLSLD",		/* name */
    442      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    443      1.1.1.2  christos 	 0,			/* src_mask */
    444      1.1.1.2  christos 	 0x0000ffff,		/* dst_mask */
    445      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    446      1.1.1.2  christos 
    447      1.1.1.2  christos    /* Computes the load module index of the load module that contains the
    448      1.1.1.2  christos       definition of its TLS sym.  */
    449      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLSDTPMOD32,
    450      1.1.1.2  christos 	 0,			/* rightshift */
    451      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    452      1.1.1.2  christos 	 32,			/* bitsize */
    453      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    454      1.1.1.2  christos 	 0,			/* bitpos */
    455      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    456      1.1.1.2  christos 	 bfd_elf_generic_reloc, /* special_function */
    457      1.1.1.2  christos 	 "R_MICROBLAZE_TLSDTPMOD32",	/* name */
    458      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    459      1.1.1.2  christos 	 0,			/* src_mask */
    460      1.1.1.2  christos 	 0x0000ffff,		/* dst_mask */
    461      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    462      1.1.1.2  christos 
    463      1.1.1.2  christos    /* Computes a dtv-relative displacement, the difference between the value
    464      1.1.1.2  christos       of sym+add and the base address of the thread-local storage block that
    465      1.1.1.2  christos       contains the definition of sym, minus 0x8000.  Used for initializing GOT */
    466      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLSDTPREL32,
    467      1.1.1.2  christos 	 0,			/* rightshift */
    468      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    469      1.1.1.2  christos 	 32,			/* bitsize */
    470      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    471      1.1.1.2  christos 	 0,			/* bitpos */
    472      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    473      1.1.1.2  christos 	 bfd_elf_generic_reloc, /* special_function */
    474      1.1.1.2  christos 	 "R_MICROBLAZE_TLSDTPREL32",	/* name */
    475      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    476      1.1.1.2  christos 	 0,			/* src_mask */
    477      1.1.1.2  christos 	 0x0000ffff,		/* dst_mask */
    478      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    479      1.1.1.2  christos 
    480      1.1.1.2  christos    /* Computes a dtv-relative displacement, the difference between the value
    481      1.1.1.2  christos       of sym+add and the base address of the thread-local storage block that
    482      1.1.1.2  christos       contains the definition of sym, minus 0x8000.  */
    483      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLSDTPREL64,
    484      1.1.1.2  christos 	 0,			/* rightshift */
    485      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    486      1.1.1.2  christos 	 32,			/* bitsize */
    487      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    488      1.1.1.2  christos 	 0,			/* bitpos */
    489      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    490      1.1.1.2  christos 	 bfd_elf_generic_reloc, /* special_function */
    491      1.1.1.2  christos 	 "R_MICROBLAZE_TLSDTPREL64",	/* name */
    492      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    493      1.1.1.2  christos 	 0,			/* src_mask */
    494      1.1.1.2  christos 	 0x0000ffff,		/* dst_mask */
    495      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    496      1.1.1.2  christos 
    497      1.1.1.2  christos    /* Computes a tp-relative displacement, the difference between the value of
    498      1.1.1.2  christos       sym+add and the value of the thread pointer (r13).  */
    499      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
    500      1.1.1.2  christos 	 0,			/* rightshift */
    501      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    502      1.1.1.2  christos 	 32,			/* bitsize */
    503      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    504      1.1.1.2  christos 	 0,			/* bitpos */
    505      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    506      1.1.1.2  christos 	 bfd_elf_generic_reloc, /* special_function */
    507      1.1.1.2  christos 	 "R_MICROBLAZE_TLSGOTTPREL32",	/* name */
    508      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    509      1.1.1.2  christos 	 0,			/* src_mask */
    510      1.1.1.2  christos 	 0x0000ffff,		/* dst_mask */
    511      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    512      1.1.1.2  christos 
    513      1.1.1.2  christos    /* Computes a tp-relative displacement, the difference between the value of
    514      1.1.1.2  christos       sym+add and the value of the thread pointer (r13).  */
    515      1.1.1.2  christos    HOWTO (R_MICROBLAZE_TLSTPREL32,
    516      1.1.1.2  christos 	 0,			/* rightshift */
    517      1.1.1.2  christos 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    518      1.1.1.2  christos 	 32,			/* bitsize */
    519      1.1.1.2  christos 	 FALSE,			/* pc_relative */
    520      1.1.1.2  christos 	 0,			/* bitpos */
    521      1.1.1.2  christos 	 complain_overflow_dont, /* complain_on_overflow */
    522      1.1.1.2  christos 	 bfd_elf_generic_reloc, /* special_function */
    523      1.1.1.2  christos 	 "R_MICROBLAZE_TLSTPREL32",	/* name */
    524      1.1.1.2  christos 	 FALSE,			/* partial_inplace */
    525      1.1.1.2  christos 	 0,			/* src_mask */
    526      1.1.1.2  christos 	 0x0000ffff,		/* dst_mask */
    527      1.1.1.2  christos 	 FALSE),		/* pcrel_offset */
    528      1.1.1.2  christos 
    529          1.1  christos };
    530          1.1  christos 
    531          1.1  christos #ifndef NUM_ELEM
    532          1.1  christos #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
    533          1.1  christos #endif
    534          1.1  christos 
    535          1.1  christos /* Initialize the microblaze_elf_howto_table, so that linear accesses can be done.  */
    537          1.1  christos 
    538          1.1  christos static void
    539          1.1  christos microblaze_elf_howto_init (void)
    540          1.1  christos {
    541          1.1  christos   unsigned int i;
    542          1.1  christos 
    543          1.1  christos   for (i = NUM_ELEM (microblaze_elf_howto_raw); i--;)
    544          1.1  christos     {
    545          1.1  christos       unsigned int type;
    546          1.1  christos 
    547          1.1  christos       type = microblaze_elf_howto_raw[i].type;
    548          1.1  christos 
    549          1.1  christos       BFD_ASSERT (type < NUM_ELEM (microblaze_elf_howto_table));
    550          1.1  christos 
    551          1.1  christos       microblaze_elf_howto_table [type] = & microblaze_elf_howto_raw [i];
    552          1.1  christos     }
    553          1.1  christos }
    554          1.1  christos 
    555          1.1  christos static reloc_howto_type *
    557          1.1  christos microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
    558          1.1  christos 				  bfd_reloc_code_real_type code)
    559          1.1  christos {
    560          1.1  christos   enum elf_microblaze_reloc_type microblaze_reloc = R_MICROBLAZE_NONE;
    561          1.1  christos 
    562          1.1  christos   switch (code)
    563          1.1  christos     {
    564          1.1  christos     case BFD_RELOC_NONE:
    565          1.1  christos       microblaze_reloc = R_MICROBLAZE_NONE;
    566          1.1  christos       break;
    567          1.1  christos     case BFD_RELOC_MICROBLAZE_64_NONE:
    568          1.1  christos       microblaze_reloc = R_MICROBLAZE_64_NONE;
    569          1.1  christos       break;
    570          1.1  christos     case BFD_RELOC_32:
    571          1.1  christos       microblaze_reloc = R_MICROBLAZE_32;
    572          1.1  christos       break;
    573          1.1  christos       /* RVA is treated the same as 32 */
    574          1.1  christos     case BFD_RELOC_RVA:
    575          1.1  christos       microblaze_reloc = R_MICROBLAZE_32;
    576          1.1  christos       break;
    577          1.1  christos     case BFD_RELOC_32_PCREL:
    578          1.1  christos       microblaze_reloc = R_MICROBLAZE_32_PCREL;
    579          1.1  christos       break;
    580          1.1  christos     case BFD_RELOC_64_PCREL:
    581          1.1  christos       microblaze_reloc = R_MICROBLAZE_64_PCREL;
    582          1.1  christos       break;
    583          1.1  christos     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
    584          1.1  christos       microblaze_reloc = R_MICROBLAZE_32_PCREL_LO;
    585          1.1  christos       break;
    586          1.1  christos     case BFD_RELOC_64:
    587          1.1  christos       microblaze_reloc = R_MICROBLAZE_64;
    588          1.1  christos       break;
    589          1.1  christos     case BFD_RELOC_MICROBLAZE_32_LO:
    590          1.1  christos       microblaze_reloc = R_MICROBLAZE_32_LO;
    591          1.1  christos       break;
    592          1.1  christos     case BFD_RELOC_MICROBLAZE_32_ROSDA:
    593          1.1  christos       microblaze_reloc = R_MICROBLAZE_SRO32;
    594          1.1  christos       break;
    595          1.1  christos     case BFD_RELOC_MICROBLAZE_32_RWSDA:
    596          1.1  christos       microblaze_reloc = R_MICROBLAZE_SRW32;
    597          1.1  christos       break;
    598          1.1  christos     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
    599          1.1  christos       microblaze_reloc = R_MICROBLAZE_32_SYM_OP_SYM;
    600          1.1  christos       break;
    601          1.1  christos     case BFD_RELOC_VTABLE_INHERIT:
    602          1.1  christos       microblaze_reloc = R_MICROBLAZE_GNU_VTINHERIT;
    603          1.1  christos       break;
    604          1.1  christos     case BFD_RELOC_VTABLE_ENTRY:
    605          1.1  christos       microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
    606          1.1  christos       break;
    607          1.1  christos     case BFD_RELOC_MICROBLAZE_64_GOTPC:
    608          1.1  christos       microblaze_reloc = R_MICROBLAZE_GOTPC_64;
    609          1.1  christos       break;
    610          1.1  christos     case BFD_RELOC_MICROBLAZE_64_GOT:
    611  1.1.1.7.4.1  christos       microblaze_reloc = R_MICROBLAZE_GOT_64;
    612  1.1.1.7.4.1  christos       break;
    613  1.1.1.7.4.1  christos     case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
    614  1.1.1.7.4.1  christos       microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
    615  1.1.1.7.4.1  christos       break;
    616  1.1.1.7.4.1  christos     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
    617          1.1  christos       microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
    618          1.1  christos       break;
    619          1.1  christos     case BFD_RELOC_MICROBLAZE_64_PLT:
    620          1.1  christos       microblaze_reloc = R_MICROBLAZE_PLT_64;
    621          1.1  christos       break;
    622          1.1  christos     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
    623          1.1  christos       microblaze_reloc = R_MICROBLAZE_GOTOFF_64;
    624          1.1  christos       break;
    625          1.1  christos     case BFD_RELOC_MICROBLAZE_32_GOTOFF:
    626      1.1.1.2  christos       microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
    627      1.1.1.2  christos       break;
    628      1.1.1.2  christos     case BFD_RELOC_MICROBLAZE_64_TLSGD:
    629      1.1.1.2  christos       microblaze_reloc = R_MICROBLAZE_TLSGD;
    630      1.1.1.2  christos       break;
    631      1.1.1.2  christos     case BFD_RELOC_MICROBLAZE_64_TLSLD:
    632      1.1.1.2  christos       microblaze_reloc = R_MICROBLAZE_TLSLD;
    633      1.1.1.2  christos       break;
    634      1.1.1.2  christos     case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
    635      1.1.1.2  christos       microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
    636      1.1.1.2  christos       break;
    637      1.1.1.2  christos     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
    638      1.1.1.2  christos       microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
    639      1.1.1.2  christos       break;
    640      1.1.1.2  christos     case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
    641      1.1.1.2  christos       microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
    642      1.1.1.2  christos       break;
    643      1.1.1.2  christos     case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
    644      1.1.1.2  christos       microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
    645      1.1.1.2  christos       break;
    646      1.1.1.2  christos     case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
    647          1.1  christos       microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
    648          1.1  christos       break;
    649          1.1  christos     case BFD_RELOC_MICROBLAZE_COPY:
    650          1.1  christos       microblaze_reloc = R_MICROBLAZE_COPY;
    651          1.1  christos       break;
    652          1.1  christos     default:
    653          1.1  christos       return (reloc_howto_type *) NULL;
    654          1.1  christos     }
    655          1.1  christos 
    656          1.1  christos   if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
    657          1.1  christos     /* Initialize howto table if needed.  */
    658          1.1  christos     microblaze_elf_howto_init ();
    659          1.1  christos 
    660          1.1  christos   return microblaze_elf_howto_table [(int) microblaze_reloc];
    661          1.1  christos };
    662          1.1  christos 
    663          1.1  christos static reloc_howto_type *
    664          1.1  christos microblaze_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    665          1.1  christos 				  const char *r_name)
    666          1.1  christos {
    667          1.1  christos   unsigned int i;
    668          1.1  christos 
    669          1.1  christos   for (i = 0; i < NUM_ELEM (microblaze_elf_howto_raw); i++)
    670          1.1  christos     if (microblaze_elf_howto_raw[i].name != NULL
    671          1.1  christos 	&& strcasecmp (microblaze_elf_howto_raw[i].name, r_name) == 0)
    672          1.1  christos       return &microblaze_elf_howto_raw[i];
    673          1.1  christos 
    674          1.1  christos   return NULL;
    675          1.1  christos }
    676          1.1  christos 
    677  1.1.1.7.4.1  christos /* Set the howto pointer for a RCE ELF reloc.  */
    678  1.1.1.7.4.1  christos 
    679          1.1  christos static bfd_boolean
    680          1.1  christos microblaze_elf_info_to_howto (bfd * abfd,
    681          1.1  christos 			      arelent * cache_ptr,
    682      1.1.1.5  christos 			      Elf_Internal_Rela * dst)
    683      1.1.1.5  christos {
    684          1.1  christos   unsigned int r_type;
    685          1.1  christos 
    686          1.1  christos   if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
    687          1.1  christos     /* Initialize howto table if needed.  */
    688      1.1.1.5  christos     microblaze_elf_howto_init ();
    689      1.1.1.5  christos 
    690      1.1.1.5  christos   r_type = ELF32_R_TYPE (dst->r_info);
    691      1.1.1.7  christos   if (r_type >= R_MICROBLAZE_max)
    692  1.1.1.7.4.1  christos     {
    693      1.1.1.7  christos       /* xgettext:c-format */
    694      1.1.1.5  christos       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    695  1.1.1.7.4.1  christos 			  abfd, r_type);
    696      1.1.1.5  christos       bfd_set_error (bfd_error_bad_value);
    697          1.1  christos       return FALSE;
    698      1.1.1.5  christos     }
    699  1.1.1.7.4.1  christos 
    700          1.1  christos   cache_ptr->howto = microblaze_elf_howto_table [r_type];
    701          1.1  christos   return TRUE;
    702          1.1  christos }
    703          1.1  christos 
    704          1.1  christos /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'.  */
    705          1.1  christos 
    706          1.1  christos static bfd_boolean
    707          1.1  christos microblaze_elf_is_local_label_name (bfd *abfd, const char *name)
    708          1.1  christos {
    709          1.1  christos   if (name[0] == 'L' && name[1] == '.')
    710          1.1  christos     return TRUE;
    711          1.1  christos 
    712          1.1  christos   if (name[0] == '$' && name[1] == 'L')
    713          1.1  christos     return TRUE;
    714          1.1  christos 
    715          1.1  christos   /* With gcc, the labels go back to starting with '.', so we accept
    716          1.1  christos      the generic ELF local label syntax as well.  */
    717          1.1  christos   return _bfd_elf_is_local_label_name (abfd, name);
    718          1.1  christos }
    719          1.1  christos 
    720          1.1  christos /* ELF linker hash entry.  */
    721          1.1  christos 
    722          1.1  christos struct elf32_mb_link_hash_entry
    723          1.1  christos {
    724          1.1  christos   struct elf_link_hash_entry elf;
    725  1.1.1.7.4.1  christos 
    726          1.1  christos   /* Track dynamic relocs copied for this symbol.  */
    727      1.1.1.2  christos   struct elf_dyn_relocs *dyn_relocs;
    728      1.1.1.2  christos 
    729      1.1.1.2  christos   /* TLS Reference Types for the symbol; Updated by check_relocs */
    730      1.1.1.2  christos #define TLS_GD     1  /* GD reloc. */
    731      1.1.1.2  christos #define TLS_LD     2  /* LD reloc. */
    732      1.1.1.2  christos #define TLS_TPREL  4  /* TPREL reloc, => IE. */
    733      1.1.1.2  christos #define TLS_DTPREL 8  /* DTPREL reloc, => LD. */
    734      1.1.1.2  christos #define TLS_TLS    16 /* Any TLS reloc.  */
    735          1.1  christos   unsigned char tls_mask;
    736          1.1  christos 
    737      1.1.1.2  christos };
    738      1.1.1.2  christos 
    739      1.1.1.2  christos #define IS_TLS_GD(x)     (x == (TLS_TLS | TLS_GD))
    740      1.1.1.2  christos #define IS_TLS_LD(x)     (x == (TLS_TLS | TLS_LD))
    741      1.1.1.2  christos #define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
    742          1.1  christos #define IS_TLS_NONE(x)   (x == 0)
    743          1.1  christos 
    744          1.1  christos #define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
    745          1.1  christos 
    746          1.1  christos /* ELF linker hash table.  */
    747          1.1  christos 
    748          1.1  christos struct elf32_mb_link_hash_table
    749          1.1  christos {
    750          1.1  christos   struct elf_link_hash_table elf;
    751          1.1  christos 
    752      1.1.1.2  christos   /* Small local sym to section mapping cache.  */
    753      1.1.1.2  christos   struct sym_cache sym_sec;
    754      1.1.1.2  christos 
    755      1.1.1.2  christos   /* TLS Local Dynamic GOT Entry */
    756      1.1.1.2  christos   union {
    757      1.1.1.2  christos     bfd_signed_vma refcount;
    758          1.1  christos     bfd_vma offset;
    759          1.1  christos   } tlsld_got;
    760      1.1.1.2  christos };
    761      1.1.1.2  christos 
    762      1.1.1.2  christos /* Nonzero if this section has TLS related relocations.  */
    763          1.1  christos #define has_tls_reloc sec_flg0
    764          1.1  christos 
    765          1.1  christos /* Get the ELF linker hash table from a link_info structure.  */
    766          1.1  christos 
    767          1.1  christos #define elf32_mb_hash_table(p)				\
    768          1.1  christos   (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
    769          1.1  christos   == MICROBLAZE_ELF_DATA ? ((struct elf32_mb_link_hash_table *) ((p)->hash)) : NULL)
    770          1.1  christos 
    771          1.1  christos /* Create an entry in a microblaze ELF linker hash table.  */
    772          1.1  christos 
    773          1.1  christos static struct bfd_hash_entry *
    774          1.1  christos link_hash_newfunc (struct bfd_hash_entry *entry,
    775          1.1  christos 		   struct bfd_hash_table *table,
    776          1.1  christos 		   const char *string)
    777          1.1  christos {
    778          1.1  christos   /* Allocate the structure if it has not already been allocated by a
    779          1.1  christos      subclass.  */
    780          1.1  christos   if (entry == NULL)
    781          1.1  christos     {
    782          1.1  christos       entry = bfd_hash_allocate (table,
    783          1.1  christos 				 sizeof (struct elf32_mb_link_hash_entry));
    784          1.1  christos       if (entry == NULL)
    785          1.1  christos 	return entry;
    786          1.1  christos     }
    787          1.1  christos 
    788          1.1  christos   /* Call the allocation method of the superclass.  */
    789          1.1  christos   entry = _bfd_elf_link_hash_newfunc (entry, table, string);
    790          1.1  christos   if (entry != NULL)
    791          1.1  christos     {
    792          1.1  christos       struct elf32_mb_link_hash_entry *eh;
    793          1.1  christos 
    794      1.1.1.2  christos       eh = (struct elf32_mb_link_hash_entry *) entry;
    795          1.1  christos       eh->dyn_relocs = NULL;
    796          1.1  christos       eh->tls_mask = 0;
    797          1.1  christos     }
    798          1.1  christos 
    799          1.1  christos   return entry;
    800          1.1  christos }
    801          1.1  christos 
    802          1.1  christos /* Create a mb ELF linker hash table.  */
    803          1.1  christos 
    804          1.1  christos static struct bfd_link_hash_table *
    805          1.1  christos microblaze_elf_link_hash_table_create (bfd *abfd)
    806          1.1  christos {
    807          1.1  christos   struct elf32_mb_link_hash_table *ret;
    808          1.1  christos   bfd_size_type amt = sizeof (struct elf32_mb_link_hash_table);
    809          1.1  christos 
    810          1.1  christos   ret = (struct elf32_mb_link_hash_table *) bfd_zmalloc (amt);
    811          1.1  christos   if (ret == NULL)
    812          1.1  christos     return NULL;
    813          1.1  christos 
    814          1.1  christos   if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
    815          1.1  christos 				      sizeof (struct elf32_mb_link_hash_entry),
    816          1.1  christos 				      MICROBLAZE_ELF_DATA))
    817          1.1  christos     {
    818          1.1  christos       free (ret);
    819          1.1  christos       return NULL;
    820          1.1  christos     }
    821          1.1  christos 
    822          1.1  christos   return &ret->elf.root;
    823          1.1  christos }
    824          1.1  christos 
    825          1.1  christos /* Set the values of the small data pointers.  */
    827          1.1  christos 
    828          1.1  christos static void
    829          1.1  christos microblaze_elf_final_sdp (struct bfd_link_info *info)
    830          1.1  christos {
    831          1.1  christos   struct bfd_link_hash_entry *h;
    832          1.1  christos 
    833          1.1  christos   h = bfd_link_hash_lookup (info->hash, RO_SDA_ANCHOR_NAME, FALSE, FALSE, TRUE);
    834  1.1.1.7.4.1  christos   if (h != (struct bfd_link_hash_entry *) NULL
    835  1.1.1.7.4.1  christos       && h->type == bfd_link_hash_defined)
    836          1.1  christos     ro_small_data_pointer = (h->u.def.value
    837          1.1  christos 			     + h->u.def.section->output_section->vma
    838          1.1  christos 			     + h->u.def.section->output_offset);
    839          1.1  christos 
    840          1.1  christos   h = bfd_link_hash_lookup (info->hash, RW_SDA_ANCHOR_NAME, FALSE, FALSE, TRUE);
    841  1.1.1.7.4.1  christos   if (h != (struct bfd_link_hash_entry *) NULL
    842  1.1.1.7.4.1  christos       && h->type == bfd_link_hash_defined)
    843          1.1  christos     rw_small_data_pointer = (h->u.def.value
    844          1.1  christos 			     + h->u.def.section->output_section->vma
    845      1.1.1.2  christos 			     + h->u.def.section->output_offset);
    846      1.1.1.2  christos }
    847      1.1.1.2  christos 
    848      1.1.1.2  christos static bfd_vma
    849      1.1.1.2  christos dtprel_base (struct bfd_link_info *info)
    850      1.1.1.2  christos {
    851      1.1.1.2  christos   /* If tls_sec is NULL, we should have signalled an error already.  */
    852      1.1.1.2  christos   if (elf_hash_table (info)->tls_sec == NULL)
    853      1.1.1.2  christos     return 0;
    854      1.1.1.2  christos   return elf_hash_table (info)->tls_sec->vma;
    855      1.1.1.2  christos }
    856      1.1.1.2  christos 
    857      1.1.1.2  christos /* The size of the thread control block.  */
    858      1.1.1.2  christos #define TCB_SIZE	8
    859      1.1.1.2  christos 
    860      1.1.1.2  christos /* Output a simple dynamic relocation into SRELOC.  */
    861      1.1.1.2  christos 
    862      1.1.1.2  christos static void
    863      1.1.1.2  christos microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
    864      1.1.1.2  christos 					  asection *sreloc,
    865      1.1.1.2  christos 					  unsigned long reloc_index,
    866      1.1.1.2  christos 					  unsigned long indx,
    867      1.1.1.2  christos 					  int r_type,
    868      1.1.1.2  christos 					  bfd_vma offset,
    869      1.1.1.2  christos 					  bfd_vma addend)
    870      1.1.1.2  christos {
    871      1.1.1.2  christos 
    872      1.1.1.2  christos   Elf_Internal_Rela rel;
    873      1.1.1.2  christos 
    874      1.1.1.2  christos   rel.r_info = ELF32_R_INFO (indx, r_type);
    875      1.1.1.2  christos   rel.r_offset = offset;
    876  1.1.1.7.4.1  christos   rel.r_addend = addend;
    877      1.1.1.2  christos 
    878      1.1.1.2  christos   bfd_elf32_swap_reloca_out (output_bfd, &rel,
    879          1.1  christos 	      (sreloc->contents + reloc_index * sizeof (Elf32_External_Rela)));
    880          1.1  christos }
    881          1.1  christos 
    882          1.1  christos /* This code is taken from elf32-m32r.c
    883          1.1  christos    There is some attempt to make this function usable for many architectures,
    884          1.1  christos    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
    885          1.1  christos    if only to serve as a learning tool.
    886          1.1  christos 
    887          1.1  christos    The RELOCATE_SECTION function is called by the new ELF backend linker
    888          1.1  christos    to handle the relocations for a section.
    889          1.1  christos 
    890          1.1  christos    The relocs are always passed as Rela structures; if the section
    891          1.1  christos    actually uses Rel structures, the r_addend field will always be
    892          1.1  christos    zero.
    893          1.1  christos 
    894          1.1  christos    This function is responsible for adjust the section contents as
    895          1.1  christos    necessary, and (if using Rela relocs and generating a
    896          1.1  christos    relocatable output file) adjusting the reloc addend as
    897          1.1  christos    necessary.
    898          1.1  christos 
    899          1.1  christos    This function does not have to worry about setting the reloc
    900          1.1  christos    address or the reloc symbol index.
    901          1.1  christos 
    902          1.1  christos    LOCAL_SYMS is a pointer to the swapped in local symbols.
    903          1.1  christos 
    904          1.1  christos    LOCAL_SECTIONS is an array giving the section in the input file
    905          1.1  christos    corresponding to the st_shndx field of each local symbol.
    906          1.1  christos 
    907          1.1  christos    The global hash table entry for the global symbols can be found
    908          1.1  christos    via elf_sym_hashes (input_bfd).
    909          1.1  christos 
    910          1.1  christos    When generating relocatable output, this function must handle
    911          1.1  christos    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    912          1.1  christos    going to be the section symbol corresponding to the output
    913          1.1  christos    section, which means that the addend must be adjusted
    914          1.1  christos    accordingly.  */
    915  1.1.1.7.4.1  christos 
    916  1.1.1.7.4.1  christos static bfd_boolean
    917  1.1.1.7.4.1  christos microblaze_elf_relocate_section (bfd *output_bfd,
    918  1.1.1.7.4.1  christos 				 struct bfd_link_info *info,
    919  1.1.1.7.4.1  christos 				 bfd *input_bfd,
    920  1.1.1.7.4.1  christos 				 asection *input_section,
    921  1.1.1.7.4.1  christos 				 bfd_byte *contents,
    922          1.1  christos 				 Elf_Internal_Rela *relocs,
    923          1.1  christos 				 Elf_Internal_Sym *local_syms,
    924          1.1  christos 				 asection **local_sections)
    925          1.1  christos {
    926          1.1  christos   struct elf32_mb_link_hash_table *htab;
    927      1.1.1.2  christos   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
    928          1.1  christos   struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
    929          1.1  christos   Elf_Internal_Rela *rel, *relend;
    930          1.1  christos   int endian = (bfd_little_endian (output_bfd)) ? 0 : 2;
    931          1.1  christos   /* Assume success.  */
    932      1.1.1.2  christos   bfd_boolean ret = TRUE;
    933          1.1  christos   asection *sreloc;
    934          1.1  christos   bfd_vma *local_got_offsets;
    935          1.1  christos   unsigned int tls_type;
    936          1.1  christos 
    937          1.1  christos   if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
    938          1.1  christos     microblaze_elf_howto_init ();
    939          1.1  christos 
    940          1.1  christos   htab = elf32_mb_hash_table (info);
    941          1.1  christos   if (htab == NULL)
    942          1.1  christos     return FALSE;
    943          1.1  christos 
    944          1.1  christos   local_got_offsets = elf_local_got_offsets (input_bfd);
    945          1.1  christos 
    946          1.1  christos   sreloc = elf_section_data (input_section)->sreloc;
    947          1.1  christos 
    948          1.1  christos   rel = relocs;
    949          1.1  christos   relend = relocs + input_section->reloc_count;
    950          1.1  christos   for (; rel < relend; rel++)
    951          1.1  christos     {
    952          1.1  christos       int r_type;
    953          1.1  christos       reloc_howto_type *howto;
    954          1.1  christos       unsigned long r_symndx;
    955          1.1  christos       bfd_vma addend = rel->r_addend;
    956          1.1  christos       bfd_vma offset = rel->r_offset;
    957          1.1  christos       struct elf_link_hash_entry *h;
    958          1.1  christos       Elf_Internal_Sym *sym;
    959          1.1  christos       asection *sec;
    960          1.1  christos       const char *sym_name;
    961          1.1  christos       bfd_reloc_status_type r = bfd_reloc_ok;
    962          1.1  christos       const char *errmsg = NULL;
    963          1.1  christos       bfd_boolean unresolved_reloc = FALSE;
    964      1.1.1.2  christos 
    965      1.1.1.2  christos       h = NULL;
    966          1.1  christos       r_type = ELF32_R_TYPE (rel->r_info);
    967          1.1  christos       tls_type = 0;
    968      1.1.1.7  christos 
    969  1.1.1.7.4.1  christos       if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
    970      1.1.1.7  christos 	{
    971          1.1  christos 	  /* xgettext:c-format */
    972          1.1  christos 	  _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    973          1.1  christos 			      input_bfd, (int) r_type);
    974          1.1  christos 	  bfd_set_error (bfd_error_bad_value);
    975          1.1  christos 	  ret = FALSE;
    976          1.1  christos 	  continue;
    977          1.1  christos 	}
    978          1.1  christos 
    979      1.1.1.6  christos       howto = microblaze_elf_howto_table[r_type];
    980          1.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
    981          1.1  christos 
    982          1.1  christos       if (bfd_link_relocatable (info))
    983          1.1  christos 	{
    984          1.1  christos 	  /* This is a relocatable link.  We don't have to change
    985          1.1  christos 	     anything, unless the reloc is against a section symbol,
    986          1.1  christos 	     in which case we have to adjust according to where the
    987          1.1  christos 	     section symbol winds up in the output section.  */
    988          1.1  christos 	  sec = NULL;
    989          1.1  christos 	  if (r_symndx >= symtab_hdr->sh_info)
    990          1.1  christos 	    /* External symbol.  */
    991          1.1  christos 	    continue;
    992          1.1  christos 
    993          1.1  christos 	  /* Local symbol.  */
    994          1.1  christos 	  sym = local_syms + r_symndx;
    995          1.1  christos 	  sym_name = "<local symbol>";
    996          1.1  christos 	  /* STT_SECTION: symbol is associated with a section.  */
    997          1.1  christos 	  if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
    998          1.1  christos 	    /* Symbol isn't associated with a section.  Nothing to do.  */
    999          1.1  christos 	    continue;
   1000          1.1  christos 
   1001          1.1  christos 	  sec = local_sections[r_symndx];
   1002          1.1  christos 	  addend += sec->output_offset + sym->st_value;
   1003          1.1  christos #ifndef USE_REL
   1004          1.1  christos 	  /* This can't be done for USE_REL because it doesn't mean anything
   1005          1.1  christos 	     and elf_link_input_bfd asserts this stays zero.  */
   1006          1.1  christos 	  /* rel->r_addend = addend; */
   1007          1.1  christos #endif
   1008          1.1  christos 
   1009          1.1  christos #ifndef USE_REL
   1010          1.1  christos 	  /* Addends are stored with relocs.  We're done.  */
   1011          1.1  christos 	  continue;
   1012          1.1  christos #else /* USE_REL */
   1013          1.1  christos 	  /* If partial_inplace, we need to store any additional addend
   1014          1.1  christos 	     back in the section.  */
   1015          1.1  christos 	  if (!howto->partial_inplace)
   1016          1.1  christos 	    continue;
   1017          1.1  christos 	  /* ??? Here is a nice place to call a special_function like handler.  */
   1018          1.1  christos 	  r = _bfd_relocate_contents (howto, input_bfd, addend,
   1019          1.1  christos 				      contents + offset);
   1020          1.1  christos #endif /* USE_REL */
   1021          1.1  christos 	}
   1022  1.1.1.7.4.1  christos       else
   1023          1.1  christos 	{
   1024          1.1  christos 	  bfd_vma relocation;
   1025          1.1  christos 	  bfd_boolean resolved_to_zero;
   1026          1.1  christos 
   1027          1.1  christos 	  /* This is a final link.  */
   1028          1.1  christos 	  sym = NULL;
   1029          1.1  christos 	  sec = NULL;
   1030          1.1  christos 	  unresolved_reloc = FALSE;
   1031          1.1  christos 
   1032          1.1  christos 	  if (r_symndx < symtab_hdr->sh_info)
   1033          1.1  christos 	    {
   1034          1.1  christos 	      /* Local symbol.  */
   1035          1.1  christos 	      sym = local_syms + r_symndx;
   1036          1.1  christos 	      sec = local_sections[r_symndx];
   1037          1.1  christos 	      if (sec == 0)
   1038          1.1  christos 		continue;
   1039          1.1  christos 	      sym_name = "<local symbol>";
   1040          1.1  christos 	      relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
   1041          1.1  christos 	      /* r_addend may have changed if the reference section was
   1042          1.1  christos 		 a merge section.  */
   1043          1.1  christos 	      addend = rel->r_addend;
   1044          1.1  christos 	    }
   1045          1.1  christos 	  else
   1046      1.1.1.3  christos 	    {
   1047          1.1  christos 	      /* External symbol.  */
   1048          1.1  christos 	      bfd_boolean warned ATTRIBUTE_UNUSED;
   1049          1.1  christos 	      bfd_boolean ignored ATTRIBUTE_UNUSED;
   1050          1.1  christos 
   1051      1.1.1.3  christos 	      RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
   1052          1.1  christos 				       r_symndx, symtab_hdr, sym_hashes,
   1053          1.1  christos 				       h, sec, relocation,
   1054          1.1  christos 				       unresolved_reloc, warned, ignored);
   1055          1.1  christos 	      sym_name = h->root.root.string;
   1056      1.1.1.2  christos 	    }
   1057          1.1  christos 
   1058          1.1  christos 	  /* Sanity check the address.  */
   1059          1.1  christos 	  if (offset > bfd_get_section_limit (input_bfd, input_section))
   1060          1.1  christos 	    {
   1061          1.1  christos 	      r = bfd_reloc_outofrange;
   1062  1.1.1.7.4.1  christos 	      goto check_reloc;
   1063  1.1.1.7.4.1  christos 	    }
   1064  1.1.1.7.4.1  christos 
   1065          1.1  christos 	  resolved_to_zero = (h != NULL
   1066          1.1  christos 			      && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
   1067          1.1  christos 
   1068          1.1  christos 	  switch ((int) r_type)
   1069          1.1  christos 	    {
   1070          1.1  christos 	    case (int) R_MICROBLAZE_SRO32 :
   1071          1.1  christos 	      {
   1072          1.1  christos 		const char *name;
   1073          1.1  christos 
   1074      1.1.1.2  christos 		/* Only relocate if the symbol is defined.  */
   1075          1.1  christos 		if (sec)
   1076          1.1  christos 		  {
   1077          1.1  christos 		    name = bfd_get_section_name (sec->owner, sec);
   1078          1.1  christos 
   1079          1.1  christos 		    if (strcmp (name, ".sdata2") == 0
   1080          1.1  christos 			|| strcmp (name, ".sbss2") == 0)
   1081          1.1  christos 		      {
   1082          1.1  christos 			if (ro_small_data_pointer == 0)
   1083          1.1  christos 			  microblaze_elf_final_sdp (info);
   1084          1.1  christos 			if (ro_small_data_pointer == 0)
   1085          1.1  christos 			  {
   1086          1.1  christos 			    ret = FALSE;
   1087          1.1  christos 			    r = bfd_reloc_undefined;
   1088          1.1  christos 			    goto check_reloc;
   1089          1.1  christos 			  }
   1090          1.1  christos 
   1091          1.1  christos 			/* At this point `relocation' contains the object's
   1092          1.1  christos 			   address.  */
   1093          1.1  christos 			relocation -= ro_small_data_pointer;
   1094          1.1  christos 			/* Now it contains the offset from _SDA2_BASE_.  */
   1095          1.1  christos 			r = _bfd_final_link_relocate (howto, input_bfd,
   1096          1.1  christos 						      input_section,
   1097          1.1  christos 						      contents, offset,
   1098          1.1  christos 						      relocation, addend);
   1099      1.1.1.7  christos 		      }
   1100      1.1.1.7  christos 		    else
   1101  1.1.1.7.4.1  christos 		      {
   1102  1.1.1.7.4.1  christos 			_bfd_error_handler
   1103      1.1.1.7  christos 			  /* xgettext:c-format */
   1104      1.1.1.7  christos 			  (_("%pB: the target (%s) of an %s relocation"
   1105      1.1.1.7  christos 			     " is in the wrong section (%pA)"),
   1106      1.1.1.7  christos 			   input_bfd,
   1107          1.1  christos 			   sym_name,
   1108          1.1  christos 			   microblaze_elf_howto_table[(int) r_type]->name,
   1109          1.1  christos 			   sec);
   1110          1.1  christos 			/*bfd_set_error (bfd_error_bad_value); ??? why? */
   1111          1.1  christos 			ret = FALSE;
   1112          1.1  christos 			continue;
   1113          1.1  christos 		      }
   1114          1.1  christos 		  }
   1115          1.1  christos 	      }
   1116          1.1  christos 	      break;
   1117          1.1  christos 
   1118          1.1  christos 	    case (int) R_MICROBLAZE_SRW32 :
   1119          1.1  christos 	      {
   1120          1.1  christos 		const char *name;
   1121          1.1  christos 
   1122      1.1.1.2  christos 		/* Only relocate if the symbol is defined.  */
   1123          1.1  christos 		if (sec)
   1124          1.1  christos 		  {
   1125          1.1  christos 		    name = bfd_get_section_name (sec->owner, sec);
   1126          1.1  christos 
   1127          1.1  christos 		    if (strcmp (name, ".sdata") == 0
   1128          1.1  christos 			|| strcmp (name, ".sbss") == 0)
   1129          1.1  christos 		      {
   1130          1.1  christos 			if (rw_small_data_pointer == 0)
   1131          1.1  christos 			  microblaze_elf_final_sdp (info);
   1132          1.1  christos 			if (rw_small_data_pointer == 0)
   1133          1.1  christos 			  {
   1134          1.1  christos 			    ret = FALSE;
   1135          1.1  christos 			    r = bfd_reloc_undefined;
   1136          1.1  christos 			    goto check_reloc;
   1137          1.1  christos 			  }
   1138          1.1  christos 
   1139          1.1  christos 			/* At this point `relocation' contains the object's
   1140          1.1  christos 			   address.  */
   1141          1.1  christos 			relocation -= rw_small_data_pointer;
   1142          1.1  christos 			/* Now it contains the offset from _SDA_BASE_.  */
   1143          1.1  christos 			r = _bfd_final_link_relocate (howto, input_bfd,
   1144          1.1  christos 						      input_section,
   1145          1.1  christos 						      contents, offset,
   1146          1.1  christos 						      relocation, addend);
   1147      1.1.1.7  christos 		      }
   1148      1.1.1.7  christos 		    else
   1149  1.1.1.7.4.1  christos 		      {
   1150  1.1.1.7.4.1  christos 			_bfd_error_handler
   1151      1.1.1.7  christos 			  /* xgettext:c-format */
   1152      1.1.1.7  christos 			  (_("%pB: the target (%s) of an %s relocation"
   1153      1.1.1.7  christos 			     " is in the wrong section (%pA)"),
   1154      1.1.1.7  christos 			   input_bfd,
   1155          1.1  christos 			   sym_name,
   1156          1.1  christos 			   microblaze_elf_howto_table[(int) r_type]->name,
   1157          1.1  christos 			   sec);
   1158          1.1  christos 			/*bfd_set_error (bfd_error_bad_value); ??? why? */
   1159          1.1  christos 			ret = FALSE;
   1160          1.1  christos 			continue;
   1161          1.1  christos 		      }
   1162          1.1  christos 		  }
   1163          1.1  christos 	      }
   1164          1.1  christos 	      break;
   1165          1.1  christos 
   1166          1.1  christos 	    case (int) R_MICROBLAZE_32_SYM_OP_SYM:
   1167      1.1.1.7  christos 	      break; /* Do nothing.  */
   1168      1.1.1.7  christos 
   1169          1.1  christos 	    case (int) R_MICROBLAZE_GOTPC_64:
   1170          1.1  christos 	      relocation = (htab->elf.sgotplt->output_section->vma
   1171          1.1  christos 			    + htab->elf.sgotplt->output_offset);
   1172          1.1  christos 	      relocation -= (input_section->output_section->vma
   1173          1.1  christos 			     + input_section->output_offset
   1174  1.1.1.7.4.1  christos 			     + offset + INST_WORD_SIZE);
   1175          1.1  christos 	      relocation += addend;
   1176  1.1.1.7.4.1  christos 	      bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
   1177  1.1.1.7.4.1  christos 			  contents + offset + endian);
   1178  1.1.1.7.4.1  christos 	      bfd_put_16 (input_bfd, relocation & 0xffff,
   1179  1.1.1.7.4.1  christos 			  contents + offset + endian + INST_WORD_SIZE);
   1180  1.1.1.7.4.1  christos 	      break;
   1181  1.1.1.7.4.1  christos 
   1182  1.1.1.7.4.1  christos 	    case (int) R_MICROBLAZE_TEXTPCREL_64:
   1183  1.1.1.7.4.1  christos 	      relocation = input_section->output_section->vma;
   1184  1.1.1.7.4.1  christos 	      relocation -= (input_section->output_section->vma
   1185  1.1.1.7.4.1  christos 			     + input_section->output_offset
   1186  1.1.1.7.4.1  christos 			     + offset + INST_WORD_SIZE);
   1187  1.1.1.7.4.1  christos 	      relocation += addend;
   1188  1.1.1.7.4.1  christos 	      bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
   1189          1.1  christos 			  contents + offset + endian);
   1190          1.1  christos 	      bfd_put_16 (input_bfd, relocation & 0xffff,
   1191          1.1  christos 			  contents + offset + endian + INST_WORD_SIZE);
   1192          1.1  christos 	      break;
   1193          1.1  christos 
   1194      1.1.1.7  christos 	    case (int) R_MICROBLAZE_PLT_64:
   1195          1.1  christos 	      {
   1196          1.1  christos 		bfd_vma immediate;
   1197      1.1.1.7  christos 		if (htab->elf.splt != NULL && h != NULL
   1198      1.1.1.7  christos 		    && h->plt.offset != (bfd_vma) -1)
   1199          1.1  christos 		  {
   1200          1.1  christos 		    relocation = (htab->elf.splt->output_section->vma
   1201          1.1  christos 				  + htab->elf.splt->output_offset
   1202          1.1  christos 				  + h->plt.offset);
   1203          1.1  christos 		    unresolved_reloc = FALSE;
   1204          1.1  christos 		    immediate = relocation - (input_section->output_section->vma
   1205  1.1.1.7.4.1  christos 					      + input_section->output_offset
   1206          1.1  christos 					      + offset + INST_WORD_SIZE);
   1207  1.1.1.7.4.1  christos 		    bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
   1208          1.1  christos 				contents + offset + endian);
   1209          1.1  christos 		    bfd_put_16 (input_bfd, immediate & 0xffff,
   1210          1.1  christos 				contents + offset + endian + INST_WORD_SIZE);
   1211          1.1  christos 		  }
   1212          1.1  christos 		else
   1213          1.1  christos 		  {
   1214          1.1  christos 		    relocation -= (input_section->output_section->vma
   1215          1.1  christos 				   + input_section->output_offset
   1216  1.1.1.7.4.1  christos 				   + offset + INST_WORD_SIZE);
   1217          1.1  christos 		    immediate = relocation;
   1218  1.1.1.7.4.1  christos 		    bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
   1219          1.1  christos 				contents + offset + endian);
   1220          1.1  christos 		    bfd_put_16 (input_bfd, immediate & 0xffff,
   1221          1.1  christos 				contents + offset + endian + INST_WORD_SIZE);
   1222          1.1  christos 		  }
   1223      1.1.1.2  christos 		break;
   1224      1.1.1.2  christos 	      }
   1225      1.1.1.2  christos 
   1226      1.1.1.2  christos 	    case (int) R_MICROBLAZE_TLSGD:
   1227      1.1.1.2  christos 	      tls_type = (TLS_TLS | TLS_GD);
   1228      1.1.1.7  christos 	      goto dogot;
   1229      1.1.1.2  christos 	    case (int) R_MICROBLAZE_TLSLD:
   1230          1.1  christos 	      tls_type = (TLS_TLS | TLS_LD);
   1231          1.1  christos 	      /* Fall through.  */
   1232      1.1.1.2  christos 	    dogot:
   1233      1.1.1.2  christos 	    case (int) R_MICROBLAZE_GOT_64:
   1234      1.1.1.2  christos 	      {
   1235      1.1.1.2  christos 		bfd_vma *offp;
   1236      1.1.1.2  christos 		bfd_vma off, off2;
   1237      1.1.1.2  christos 		unsigned long indx;
   1238      1.1.1.7  christos 		bfd_vma static_value;
   1239          1.1  christos 
   1240      1.1.1.2  christos 		bfd_boolean need_relocs = FALSE;
   1241      1.1.1.2  christos 		if (htab->elf.sgot == NULL)
   1242      1.1.1.2  christos 		  abort ();
   1243      1.1.1.2  christos 
   1244      1.1.1.2  christos 		indx = 0;
   1245      1.1.1.2  christos 		offp = NULL;
   1246      1.1.1.2  christos 
   1247      1.1.1.2  christos 		/* 1. Identify GOT Offset;
   1248      1.1.1.2  christos 		   2. Compute Static Values
   1249      1.1.1.2  christos 		   3. Process Module Id, Process Offset
   1250      1.1.1.2  christos 		   4. Fixup Relocation with GOT offset value. */
   1251      1.1.1.2  christos 
   1252      1.1.1.2  christos 		/* 1. Determine GOT Offset to use : TLS_LD, global, local */
   1253      1.1.1.2  christos 		if (IS_TLS_LD (tls_type))
   1254      1.1.1.7  christos 		  offp = &htab->tlsld_got.offset;
   1255      1.1.1.7  christos 		else if (h != NULL)
   1256      1.1.1.7  christos 		  {
   1257      1.1.1.2  christos 		    if (htab->elf.sgotplt != NULL
   1258      1.1.1.7  christos 			&& h->got.offset != (bfd_vma) -1)
   1259      1.1.1.2  christos 		      offp = &h->got.offset;
   1260      1.1.1.2  christos 		    else
   1261          1.1  christos 		      abort ();
   1262          1.1  christos 		  }
   1263          1.1  christos 		else
   1264      1.1.1.2  christos 		  {
   1265      1.1.1.2  christos 		    if (local_got_offsets == NULL)
   1266      1.1.1.2  christos 		      abort ();
   1267      1.1.1.2  christos 		    offp = &local_got_offsets[r_symndx];
   1268      1.1.1.2  christos 		  }
   1269      1.1.1.2  christos 
   1270      1.1.1.2  christos 		if (!offp)
   1271      1.1.1.2  christos 		  abort ();
   1272      1.1.1.2  christos 
   1273      1.1.1.2  christos 		off = (*offp) & ~1;
   1274      1.1.1.2  christos 		off2 = off;
   1275      1.1.1.2  christos 
   1276      1.1.1.2  christos 		if (IS_TLS_LD(tls_type) || IS_TLS_GD(tls_type))
   1277      1.1.1.2  christos 		  off2 = off + 4;
   1278      1.1.1.2  christos 
   1279      1.1.1.2  christos 		/* Symbol index to use for relocs */
   1280      1.1.1.2  christos 		if (h != NULL)
   1281      1.1.1.2  christos 		  {
   1282      1.1.1.6  christos 		    bfd_boolean dyn =
   1283      1.1.1.6  christos 			elf_hash_table (info)->dynamic_sections_created;
   1284      1.1.1.6  christos 
   1285      1.1.1.6  christos 		    if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
   1286      1.1.1.6  christos 							 bfd_link_pic (info),
   1287      1.1.1.2  christos 							 h)
   1288      1.1.1.2  christos 			&& (!bfd_link_pic (info)
   1289      1.1.1.2  christos 			    || !SYMBOL_REFERENCES_LOCAL (info, h)))
   1290      1.1.1.2  christos 		      indx = h->dynindx;
   1291      1.1.1.6  christos 		  }
   1292      1.1.1.2  christos 
   1293  1.1.1.7.4.1  christos 		/* Need to generate relocs ? */
   1294  1.1.1.7.4.1  christos 		if ((bfd_link_pic (info) || indx != 0)
   1295      1.1.1.2  christos 		    && (h == NULL
   1296      1.1.1.2  christos 		    || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
   1297      1.1.1.2  christos 			&& !resolved_to_zero)
   1298      1.1.1.2  christos 		    || h->root.type != bfd_link_hash_undefweak))
   1299      1.1.1.2  christos 		  need_relocs = TRUE;
   1300      1.1.1.2  christos 
   1301      1.1.1.2  christos 		/* 2. Compute/Emit Static value of r-expression */
   1302      1.1.1.2  christos 		static_value = relocation + addend;
   1303      1.1.1.2  christos 
   1304      1.1.1.2  christos 		/* 3. Process module-id and offset */
   1305      1.1.1.2  christos 		if (! ((*offp) & 1) )
   1306      1.1.1.7  christos 		  {
   1307      1.1.1.7  christos 		    bfd_vma got_offset;
   1308      1.1.1.2  christos 
   1309          1.1  christos 		    got_offset = (htab->elf.sgot->output_section->vma
   1310      1.1.1.2  christos 				  + htab->elf.sgot->output_offset
   1311      1.1.1.2  christos 				  + off);
   1312      1.1.1.2  christos 
   1313      1.1.1.6  christos 		    /* Process module-id */
   1314      1.1.1.7  christos 		    if (IS_TLS_LD(tls_type))
   1315      1.1.1.7  christos 		      {
   1316      1.1.1.2  christos 			if (! bfd_link_pic (info))
   1317      1.1.1.7  christos 			  bfd_put_32 (output_bfd, 1,
   1318      1.1.1.7  christos 				      htab->elf.sgot->contents + off);
   1319      1.1.1.7  christos 			else
   1320      1.1.1.7  christos 			  microblaze_elf_output_dynamic_relocation
   1321      1.1.1.7  christos 			    (output_bfd,
   1322      1.1.1.7  christos 			     htab->elf.srelgot,
   1323          1.1  christos 			     htab->elf.srelgot->reloc_count++,
   1324      1.1.1.2  christos 			     /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
   1325      1.1.1.2  christos 			     got_offset, 0);
   1326  1.1.1.7.4.1  christos 		      }
   1327      1.1.1.7  christos 		    else if (IS_TLS_GD(tls_type))
   1328      1.1.1.7  christos 		      {
   1329  1.1.1.7.4.1  christos 			if (! need_relocs)
   1330      1.1.1.7  christos 			  bfd_put_32 (output_bfd, 1,
   1331      1.1.1.7  christos 				      htab->elf.sgot->contents + off);
   1332      1.1.1.7  christos 			else
   1333      1.1.1.7  christos 			  microblaze_elf_output_dynamic_relocation
   1334      1.1.1.7  christos 			    (output_bfd,
   1335      1.1.1.7  christos 			     htab->elf.srelgot,
   1336      1.1.1.2  christos 			     htab->elf.srelgot->reloc_count++,
   1337      1.1.1.2  christos 			     /* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
   1338      1.1.1.2  christos 			     got_offset, indx ? 0 : static_value);
   1339      1.1.1.7  christos 		      }
   1340      1.1.1.2  christos 
   1341      1.1.1.2  christos 		    /* Process Offset */
   1342      1.1.1.7  christos 		    if (htab->elf.srelgot == NULL)
   1343      1.1.1.7  christos 		      abort ();
   1344      1.1.1.2  christos 
   1345      1.1.1.2  christos 		    got_offset = (htab->elf.sgot->output_section->vma
   1346      1.1.1.2  christos 				  + htab->elf.sgot->output_offset
   1347  1.1.1.7.4.1  christos 				  + off2);
   1348  1.1.1.7.4.1  christos 		    if (IS_TLS_LD(tls_type))
   1349  1.1.1.7.4.1  christos 		      {
   1350      1.1.1.7  christos 			/* For LD, offset should be 0 */
   1351      1.1.1.2  christos 			*offp |= 1;
   1352      1.1.1.2  christos 			bfd_put_32 (output_bfd, 0,
   1353          1.1  christos 				    htab->elf.sgot->contents + off2);
   1354  1.1.1.7.4.1  christos 		      }
   1355  1.1.1.7.4.1  christos 		    else if (IS_TLS_GD(tls_type))
   1356  1.1.1.7.4.1  christos 		      {
   1357      1.1.1.7  christos 			*offp |= 1;
   1358      1.1.1.7  christos 			static_value -= dtprel_base(info);
   1359      1.1.1.7  christos 			if (need_relocs)
   1360      1.1.1.7  christos 			  microblaze_elf_output_dynamic_relocation
   1361      1.1.1.7  christos 			    (output_bfd,
   1362      1.1.1.7  christos 			     htab->elf.srelgot,
   1363  1.1.1.7.4.1  christos 			     htab->elf.srelgot->reloc_count++,
   1364      1.1.1.7  christos 			     /* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
   1365      1.1.1.7  christos 			     got_offset, indx ? 0 : static_value);
   1366          1.1  christos 			else
   1367          1.1  christos 			  bfd_put_32 (output_bfd, static_value,
   1368      1.1.1.2  christos 				      htab->elf.sgot->contents + off2);
   1369      1.1.1.7  christos 		      }
   1370      1.1.1.7  christos 		    else
   1371      1.1.1.2  christos 		      {
   1372      1.1.1.7  christos 			bfd_put_32 (output_bfd, static_value,
   1373      1.1.1.7  christos 				    htab->elf.sgot->contents + off2);
   1374      1.1.1.7  christos 
   1375      1.1.1.7  christos 			/* Relocs for dyn symbols generated by
   1376      1.1.1.7  christos 			   finish_dynamic_symbols */
   1377      1.1.1.7  christos 			if (bfd_link_pic (info) && h == NULL)
   1378      1.1.1.7  christos 			  {
   1379      1.1.1.7  christos 			    *offp |= 1;
   1380      1.1.1.7  christos 			    microblaze_elf_output_dynamic_relocation
   1381      1.1.1.7  christos 			      (output_bfd,
   1382      1.1.1.7  christos 			       htab->elf.srelgot,
   1383      1.1.1.7  christos 			       htab->elf.srelgot->reloc_count++,
   1384      1.1.1.2  christos 			       /* symindex= */ indx, R_MICROBLAZE_REL,
   1385          1.1  christos 			       got_offset, static_value);
   1386      1.1.1.2  christos 			  }
   1387      1.1.1.2  christos 		      }
   1388      1.1.1.2  christos 		  }
   1389      1.1.1.2  christos 
   1390      1.1.1.7  christos 		/* 4. Fixup Relocation with GOT offset value
   1391      1.1.1.7  christos 		      Compute relative address of GOT entry for applying
   1392      1.1.1.2  christos 		      the current relocation */
   1393      1.1.1.7  christos 		relocation = htab->elf.sgot->output_section->vma
   1394      1.1.1.7  christos 			     + htab->elf.sgot->output_offset
   1395      1.1.1.2  christos 			     + off
   1396      1.1.1.2  christos 			     - htab->elf.sgotplt->output_section->vma
   1397          1.1  christos 			     - htab->elf.sgotplt->output_offset;
   1398  1.1.1.7.4.1  christos 
   1399          1.1  christos 		/* Apply Current Relocation */
   1400  1.1.1.7.4.1  christos 		bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
   1401      1.1.1.2  christos 			    contents + offset + endian);
   1402      1.1.1.2  christos 		bfd_put_16 (input_bfd, relocation & 0xffff,
   1403          1.1  christos 			    contents + offset + endian + INST_WORD_SIZE);
   1404          1.1  christos 
   1405          1.1  christos 		unresolved_reloc = FALSE;
   1406          1.1  christos 		break;
   1407          1.1  christos 	      }
   1408          1.1  christos 
   1409          1.1  christos 	    case (int) R_MICROBLAZE_GOTOFF_64:
   1410          1.1  christos 	      {
   1411      1.1.1.7  christos 		bfd_vma immediate;
   1412      1.1.1.7  christos 		unsigned short lo, high;
   1413          1.1  christos 		relocation += addend;
   1414          1.1  christos 		relocation -= (htab->elf.sgotplt->output_section->vma
   1415          1.1  christos 			       + htab->elf.sgotplt->output_offset);
   1416          1.1  christos 		/* Write this value into correct location.  */
   1417      1.1.1.2  christos 		immediate = relocation;
   1418      1.1.1.7  christos 		lo = immediate & 0x0000ffff;
   1419      1.1.1.7  christos 		high = (immediate >> 16) & 0x0000ffff;
   1420          1.1  christos 		bfd_put_16 (input_bfd, high, contents + offset + endian);
   1421          1.1  christos 		bfd_put_16 (input_bfd, lo,
   1422          1.1  christos 			    contents + offset + INST_WORD_SIZE + endian);
   1423          1.1  christos 		break;
   1424          1.1  christos 	      }
   1425          1.1  christos 
   1426      1.1.1.7  christos 	    case (int) R_MICROBLAZE_GOTOFF_32:
   1427      1.1.1.7  christos 	      {
   1428          1.1  christos 		relocation += addend;
   1429          1.1  christos 		relocation -= (htab->elf.sgotplt->output_section->vma
   1430          1.1  christos 			       + htab->elf.sgotplt->output_offset);
   1431          1.1  christos 		/* Write this value into correct location.  */
   1432          1.1  christos 		bfd_put_32 (input_bfd, relocation, contents + offset);
   1433      1.1.1.2  christos 		break;
   1434      1.1.1.2  christos 	      }
   1435      1.1.1.2  christos 
   1436      1.1.1.2  christos 	    case (int) R_MICROBLAZE_TLSDTPREL64:
   1437      1.1.1.2  christos 	      relocation += addend;
   1438      1.1.1.2  christos 	      relocation -= dtprel_base(info);
   1439      1.1.1.2  christos 	      bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
   1440      1.1.1.2  christos 			  contents + offset + 2);
   1441  1.1.1.7.4.1  christos 	      bfd_put_16 (input_bfd, relocation & 0xffff,
   1442  1.1.1.7.4.1  christos 			  contents + offset + 2 + INST_WORD_SIZE);
   1443          1.1  christos 	      break;
   1444          1.1  christos 	    case (int) R_MICROBLAZE_TEXTREL_64:
   1445          1.1  christos 	    case (int) R_MICROBLAZE_TEXTREL_32_LO:
   1446          1.1  christos 	    case (int) R_MICROBLAZE_64_PCREL :
   1447          1.1  christos 	    case (int) R_MICROBLAZE_64:
   1448          1.1  christos 	    case (int) R_MICROBLAZE_32:
   1449          1.1  christos 	      {
   1450          1.1  christos 		/* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
   1451          1.1  christos 		   from removed linkonce sections, or sections discarded by
   1452          1.1  christos 		   a linker script.  */
   1453          1.1  christos 		if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
   1454          1.1  christos 		  {
   1455          1.1  christos 		    relocation += addend;
   1456          1.1  christos 		    if (r_type == R_MICROBLAZE_32)
   1457          1.1  christos 		      bfd_put_32 (input_bfd, relocation, contents + offset);
   1458          1.1  christos 		    else
   1459          1.1  christos 		      {
   1460          1.1  christos 			if (r_type == R_MICROBLAZE_64_PCREL)
   1461  1.1.1.7.4.1  christos 			  relocation -= (input_section->output_section->vma
   1462  1.1.1.7.4.1  christos 					 + input_section->output_offset
   1463  1.1.1.7.4.1  christos 					 + offset + INST_WORD_SIZE);
   1464  1.1.1.7.4.1  christos 			else if (r_type == R_MICROBLAZE_TEXTREL_64
   1465  1.1.1.7.4.1  christos 				 || r_type == R_MICROBLAZE_TEXTREL_32_LO)
   1466  1.1.1.7.4.1  christos 			  relocation -= input_section->output_section->vma;
   1467  1.1.1.7.4.1  christos 
   1468  1.1.1.7.4.1  christos 			if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
   1469  1.1.1.7.4.1  christos 			  bfd_put_16 (input_bfd, relocation & 0xffff,
   1470  1.1.1.7.4.1  christos 				      contents + offset + endian);
   1471  1.1.1.7.4.1  christos 
   1472  1.1.1.7.4.1  christos 			else
   1473  1.1.1.7.4.1  christos 			  {
   1474  1.1.1.7.4.1  christos 			    bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
   1475          1.1  christos 				    contents + offset + endian);
   1476  1.1.1.7.4.1  christos 			    bfd_put_16 (input_bfd, relocation & 0xffff,
   1477          1.1  christos 				    contents + offset + endian + INST_WORD_SIZE);
   1478          1.1  christos 		      }
   1479          1.1  christos 		    }
   1480      1.1.1.6  christos 		    break;
   1481          1.1  christos 		  }
   1482  1.1.1.7.4.1  christos 
   1483  1.1.1.7.4.1  christos 		if ((bfd_link_pic (info)
   1484          1.1  christos 		     && (h == NULL
   1485          1.1  christos 			 || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
   1486          1.1  christos 			     && !resolved_to_zero)
   1487          1.1  christos 			 || h->root.type != bfd_link_hash_undefweak)
   1488          1.1  christos 		     && (!howto->pc_relative
   1489          1.1  christos 			 || (h != NULL
   1490      1.1.1.6  christos 			     && h->dynindx != -1
   1491          1.1  christos 			     && (!info->symbolic
   1492          1.1  christos 				 || !h->def_regular))))
   1493          1.1  christos 		    || (!bfd_link_pic (info)
   1494          1.1  christos 			&& h != NULL
   1495          1.1  christos 			&& h->dynindx != -1
   1496          1.1  christos 			&& !h->non_got_ref
   1497          1.1  christos 			&& ((h->def_dynamic
   1498          1.1  christos 			     && !h->def_regular)
   1499          1.1  christos 			    || h->root.type == bfd_link_hash_undefweak
   1500          1.1  christos 			    || h->root.type == bfd_link_hash_undefined)))
   1501          1.1  christos 		  {
   1502          1.1  christos 		    Elf_Internal_Rela outrel;
   1503          1.1  christos 		    bfd_byte *loc;
   1504          1.1  christos 		    bfd_boolean skip;
   1505          1.1  christos 
   1506          1.1  christos 		    /* When generating a shared object, these relocations
   1507          1.1  christos 		       are copied into the output file to be resolved at run
   1508          1.1  christos 		       time.  */
   1509          1.1  christos 
   1510          1.1  christos 		    BFD_ASSERT (sreloc != NULL);
   1511          1.1  christos 
   1512          1.1  christos 		    skip = FALSE;
   1513          1.1  christos 
   1514          1.1  christos 		    outrel.r_offset =
   1515          1.1  christos 		      _bfd_elf_section_offset (output_bfd, info, input_section,
   1516          1.1  christos 					       rel->r_offset);
   1517          1.1  christos 		    if (outrel.r_offset == (bfd_vma) -1)
   1518          1.1  christos 		      skip = TRUE;
   1519          1.1  christos 		    else if (outrel.r_offset == (bfd_vma) -2)
   1520          1.1  christos 		      skip = TRUE;
   1521          1.1  christos 		    outrel.r_offset += (input_section->output_section->vma
   1522          1.1  christos 					+ input_section->output_offset);
   1523          1.1  christos 
   1524          1.1  christos 		    if (skip)
   1525          1.1  christos 		      memset (&outrel, 0, sizeof outrel);
   1526          1.1  christos 		    /* h->dynindx may be -1 if the symbol was marked to
   1527          1.1  christos 		       become local.  */
   1528          1.1  christos 		    else if (h != NULL
   1529          1.1  christos 			     && ((! info->symbolic && h->dynindx != -1)
   1530          1.1  christos 				 || !h->def_regular))
   1531          1.1  christos 		      {
   1532          1.1  christos 			BFD_ASSERT (h->dynindx != -1);
   1533          1.1  christos 			outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
   1534          1.1  christos 			outrel.r_addend = addend;
   1535          1.1  christos 		      }
   1536          1.1  christos 		    else
   1537          1.1  christos 		      {
   1538          1.1  christos 			if (r_type == R_MICROBLAZE_32)
   1539          1.1  christos 			  {
   1540          1.1  christos 			    outrel.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
   1541          1.1  christos 			    outrel.r_addend = relocation + addend;
   1542          1.1  christos 			  }
   1543      1.1.1.7  christos 			else
   1544  1.1.1.7.4.1  christos 			  {
   1545          1.1  christos 			    BFD_FAIL ();
   1546          1.1  christos 			    _bfd_error_handler
   1547          1.1  christos 			      (_("%pB: probably compiled without -fPIC?"),
   1548          1.1  christos 			       input_bfd);
   1549          1.1  christos 			    bfd_set_error (bfd_error_bad_value);
   1550          1.1  christos 			    return FALSE;
   1551          1.1  christos 			  }
   1552          1.1  christos 		      }
   1553          1.1  christos 
   1554          1.1  christos 		    loc = sreloc->contents;
   1555          1.1  christos 		    loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
   1556          1.1  christos 		    bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
   1557          1.1  christos 		    break;
   1558          1.1  christos 		  }
   1559          1.1  christos 		else
   1560          1.1  christos 		  {
   1561          1.1  christos 		    relocation += addend;
   1562          1.1  christos 		    if (r_type == R_MICROBLAZE_32)
   1563          1.1  christos 		      bfd_put_32 (input_bfd, relocation, contents + offset);
   1564          1.1  christos 		    else
   1565          1.1  christos 		      {
   1566          1.1  christos 			if (r_type == R_MICROBLAZE_64_PCREL)
   1567  1.1.1.7.4.1  christos 			  relocation -= (input_section->output_section->vma
   1568  1.1.1.7.4.1  christos 					 + input_section->output_offset
   1569  1.1.1.7.4.1  christos 					 + offset + INST_WORD_SIZE);
   1570  1.1.1.7.4.1  christos 			else if (r_type == R_MICROBLAZE_TEXTREL_64
   1571  1.1.1.7.4.1  christos 				 || r_type == R_MICROBLAZE_TEXTREL_32_LO)
   1572  1.1.1.7.4.1  christos 			  relocation -= input_section->output_section->vma;
   1573  1.1.1.7.4.1  christos 
   1574  1.1.1.7.4.1  christos 			if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
   1575  1.1.1.7.4.1  christos 			  {
   1576  1.1.1.7.4.1  christos 			     bfd_put_16 (input_bfd, relocation & 0xffff,
   1577  1.1.1.7.4.1  christos 					 contents + offset + endian);
   1578  1.1.1.7.4.1  christos 			  }
   1579  1.1.1.7.4.1  christos 			else
   1580  1.1.1.7.4.1  christos 			  {
   1581  1.1.1.7.4.1  christos 			    bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
   1582  1.1.1.7.4.1  christos 				        contents + offset + endian);
   1583  1.1.1.7.4.1  christos 			    bfd_put_16 (input_bfd, relocation & 0xffff,
   1584  1.1.1.7.4.1  christos 					contents + offset + endian
   1585          1.1  christos 					+ INST_WORD_SIZE);
   1586          1.1  christos 			  }
   1587          1.1  christos 		    }
   1588          1.1  christos 		    break;
   1589          1.1  christos 		  }
   1590          1.1  christos 	      }
   1591          1.1  christos 
   1592          1.1  christos 	    default :
   1593          1.1  christos 	      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
   1594          1.1  christos 					    contents, offset,
   1595          1.1  christos 					    relocation, addend);
   1596          1.1  christos 	      break;
   1597          1.1  christos 	    }
   1598          1.1  christos 	}
   1599          1.1  christos 
   1600          1.1  christos     check_reloc:
   1601          1.1  christos 
   1602          1.1  christos       if (r != bfd_reloc_ok)
   1603          1.1  christos 	{
   1604          1.1  christos 	  /* FIXME: This should be generic enough to go in a utility.  */
   1605          1.1  christos 	  const char *name;
   1606          1.1  christos 
   1607          1.1  christos 	  if (h != NULL)
   1608          1.1  christos 	    name = h->root.root.string;
   1609          1.1  christos 	  else
   1610          1.1  christos 	    {
   1611          1.1  christos 	      name = (bfd_elf_string_from_elf_section
   1612          1.1  christos 		      (input_bfd, symtab_hdr->sh_link, sym->st_name));
   1613          1.1  christos 	      if (name == NULL || *name == '\0')
   1614          1.1  christos 		name = bfd_section_name (input_bfd, sec);
   1615          1.1  christos 	    }
   1616          1.1  christos 
   1617          1.1  christos 	  if (errmsg != NULL)
   1618          1.1  christos 	    goto common_error;
   1619          1.1  christos 
   1620      1.1.1.6  christos 	  switch (r)
   1621      1.1.1.6  christos 	    {
   1622      1.1.1.6  christos 	    case bfd_reloc_overflow:
   1623          1.1  christos 	      (*info->callbacks->reloc_overflow)
   1624          1.1  christos 		(info, (h ? &h->root : NULL), name, howto->name,
   1625          1.1  christos 		 (bfd_vma) 0, input_bfd, input_section, offset);
   1626      1.1.1.6  christos 	      break;
   1627      1.1.1.6  christos 
   1628          1.1  christos 	    case bfd_reloc_undefined:
   1629          1.1  christos 	      (*info->callbacks->undefined_symbol)
   1630          1.1  christos 		(info, name, input_bfd, input_section, offset, TRUE);
   1631          1.1  christos 	      break;
   1632          1.1  christos 
   1633          1.1  christos 	    case bfd_reloc_outofrange:
   1634          1.1  christos 	      errmsg = _("internal error: out of range error");
   1635          1.1  christos 	      goto common_error;
   1636          1.1  christos 
   1637          1.1  christos 	    case bfd_reloc_notsupported:
   1638          1.1  christos 	      errmsg = _("internal error: unsupported relocation error");
   1639          1.1  christos 	      goto common_error;
   1640          1.1  christos 
   1641          1.1  christos 	    case bfd_reloc_dangerous:
   1642          1.1  christos 	      errmsg = _("internal error: dangerous error");
   1643          1.1  christos 	      goto common_error;
   1644          1.1  christos 
   1645          1.1  christos 	    default:
   1646      1.1.1.6  christos 	      errmsg = _("internal error: unknown error");
   1647      1.1.1.6  christos 	      /* Fall through.  */
   1648          1.1  christos 	    common_error:
   1649          1.1  christos 	      (*info->callbacks->warning) (info, errmsg, name, input_bfd,
   1650          1.1  christos 					   input_section, offset);
   1651          1.1  christos 	      break;
   1652          1.1  christos 	    }
   1653          1.1  christos 	}
   1654          1.1  christos     }
   1655          1.1  christos 
   1656          1.1  christos   return ret;
   1657          1.1  christos }
   1658          1.1  christos 
   1659      1.1.1.2  christos /* Calculate fixup value for reference.  */
   1661      1.1.1.2  christos 
   1662          1.1  christos static int
   1663          1.1  christos calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
   1664          1.1  christos {
   1665          1.1  christos   bfd_vma end = start + size;
   1666          1.1  christos   int i, fixup = 0;
   1667          1.1  christos 
   1668          1.1  christos   if (sec == NULL || sec->relax == NULL)
   1669          1.1  christos     return 0;
   1670      1.1.1.2  christos 
   1671  1.1.1.7.4.1  christos   /* Look for addr in relax table, total fixup value.  */
   1672      1.1.1.2  christos   for (i = 0; i < sec->relax_count; i++)
   1673  1.1.1.7.4.1  christos     {
   1674          1.1  christos       if (end <= sec->relax[i].addr)
   1675          1.1  christos 	break;
   1676          1.1  christos       if ((end != start) && (start > sec->relax[i].addr))
   1677          1.1  christos 	continue;
   1678          1.1  christos       fixup += sec->relax[i].size;
   1679      1.1.1.2  christos     }
   1680      1.1.1.2  christos   return fixup;
   1681      1.1.1.2  christos }
   1682      1.1.1.2  christos 
   1683      1.1.1.2  christos /* Read-modify-write into the bfd, an immediate value into appropriate fields of
   1684      1.1.1.2  christos    a 32-bit instruction.  */
   1685      1.1.1.2  christos static void
   1686      1.1.1.2  christos microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
   1687      1.1.1.2  christos {
   1688      1.1.1.2  christos     unsigned long instr = bfd_get_32 (abfd, bfd_addr);
   1689      1.1.1.2  christos     instr &= ~0x0000ffff;
   1690      1.1.1.2  christos     instr |= (val & 0x0000ffff);
   1691      1.1.1.2  christos     bfd_put_32 (abfd, instr, bfd_addr);
   1692      1.1.1.2  christos }
   1693      1.1.1.2  christos 
   1694      1.1.1.2  christos /* Read-modify-write into the bfd, an immediate value into appropriate fields of
   1695      1.1.1.2  christos    two consecutive 32-bit instructions.  */
   1696      1.1.1.2  christos static void
   1697      1.1.1.2  christos microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
   1698      1.1.1.2  christos {
   1699      1.1.1.2  christos     unsigned long instr_hi;
   1700      1.1.1.2  christos     unsigned long instr_lo;
   1701      1.1.1.2  christos 
   1702      1.1.1.2  christos     instr_hi = bfd_get_32 (abfd, bfd_addr);
   1703      1.1.1.2  christos     instr_hi &= ~0x0000ffff;
   1704      1.1.1.2  christos     instr_hi |= ((val >> 16) & 0x0000ffff);
   1705      1.1.1.2  christos     bfd_put_32 (abfd, instr_hi, bfd_addr);
   1706      1.1.1.2  christos 
   1707      1.1.1.2  christos     instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
   1708      1.1.1.2  christos     instr_lo &= ~0x0000ffff;
   1709          1.1  christos     instr_lo |= (val & 0x0000ffff);
   1710          1.1  christos     bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
   1711          1.1  christos }
   1712          1.1  christos 
   1713          1.1  christos static bfd_boolean
   1714          1.1  christos microblaze_elf_relax_section (bfd *abfd,
   1715          1.1  christos 			      asection *sec,
   1716          1.1  christos 			      struct bfd_link_info *link_info,
   1717          1.1  christos 			      bfd_boolean *again)
   1718          1.1  christos {
   1719          1.1  christos   Elf_Internal_Shdr *symtab_hdr;
   1720          1.1  christos   Elf_Internal_Rela *internal_relocs;
   1721          1.1  christos   Elf_Internal_Rela *free_relocs = NULL;
   1722          1.1  christos   Elf_Internal_Rela *irel, *irelend;
   1723          1.1  christos   bfd_byte *contents = NULL;
   1724          1.1  christos   bfd_byte *free_contents = NULL;
   1725          1.1  christos   int rel_count;
   1726          1.1  christos   unsigned int shndx;
   1727          1.1  christos   int i, sym_index;
   1728          1.1  christos   asection *o;
   1729          1.1  christos   struct elf_link_hash_entry *sym_hash;
   1730          1.1  christos   Elf_Internal_Sym *isymbuf, *isymend;
   1731          1.1  christos   Elf_Internal_Sym *isym;
   1732          1.1  christos   int symcount;
   1733          1.1  christos   int offset;
   1734          1.1  christos   bfd_vma src, dest;
   1735          1.1  christos 
   1736          1.1  christos   /* We only do this once per section.  We may be able to delete some code
   1737      1.1.1.6  christos      by running multiple passes, but it is not worth it.  */
   1738          1.1  christos   *again = FALSE;
   1739      1.1.1.2  christos 
   1740      1.1.1.2  christos   /* Only do this for a text section.  */
   1741          1.1  christos   if (bfd_link_relocatable (link_info)
   1742          1.1  christos       || (sec->flags & SEC_RELOC) == 0
   1743          1.1  christos       || (sec->reloc_count == 0)
   1744          1.1  christos       || (sec->flags & SEC_CODE) == 0)
   1745          1.1  christos     return TRUE;
   1746          1.1  christos 
   1747          1.1  christos   BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
   1748          1.1  christos 
   1749          1.1  christos   /* If this is the first time we have been called for this section,
   1750          1.1  christos      initialize the cooked size.  */
   1751          1.1  christos   if (sec->size == 0)
   1752          1.1  christos     sec->size = sec->rawsize;
   1753          1.1  christos 
   1754          1.1  christos   /* Get symbols for this section.  */
   1755          1.1  christos   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   1756  1.1.1.7.4.1  christos   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   1757          1.1  christos   symcount =  symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
   1758          1.1  christos   if (isymbuf == NULL)
   1759          1.1  christos     isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
   1760          1.1  christos 				    0, NULL, NULL, NULL);
   1761          1.1  christos   BFD_ASSERT (isymbuf != NULL);
   1762          1.1  christos 
   1763          1.1  christos   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
   1764          1.1  christos   if (internal_relocs == NULL)
   1765          1.1  christos     goto error_return;
   1766          1.1  christos   if (! link_info->keep_memory)
   1767          1.1  christos     free_relocs = internal_relocs;
   1768          1.1  christos 
   1769          1.1  christos   sec->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
   1770          1.1  christos 						  * sizeof (struct relax_table));
   1771          1.1  christos   if (sec->relax == NULL)
   1772          1.1  christos     goto error_return;
   1773          1.1  christos   sec->relax_count = 0;
   1774          1.1  christos 
   1775          1.1  christos   irelend = internal_relocs + sec->reloc_count;
   1776          1.1  christos   rel_count = 0;
   1777  1.1.1.7.4.1  christos   for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
   1778  1.1.1.7.4.1  christos     {
   1779          1.1  christos       bfd_vma symval;
   1780          1.1  christos       if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
   1781          1.1  christos 	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64)
   1782          1.1  christos 	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
   1783          1.1  christos 	continue; /* Can't delete this reloc.  */
   1784          1.1  christos 
   1785          1.1  christos       /* Get the section contents.  */
   1786          1.1  christos       if (contents == NULL)
   1787          1.1  christos 	{
   1788          1.1  christos 	  if (elf_section_data (sec)->this_hdr.contents != NULL)
   1789          1.1  christos 	    contents = elf_section_data (sec)->this_hdr.contents;
   1790          1.1  christos 	  else
   1791          1.1  christos 	    {
   1792          1.1  christos 	      contents = (bfd_byte *) bfd_malloc (sec->size);
   1793          1.1  christos 	      if (contents == NULL)
   1794          1.1  christos 		goto error_return;
   1795          1.1  christos 	      free_contents = contents;
   1796  1.1.1.7.4.1  christos 
   1797          1.1  christos 	      if (!bfd_get_section_contents (abfd, sec, contents,
   1798          1.1  christos 					     (file_ptr) 0, sec->size))
   1799          1.1  christos 		goto error_return;
   1800          1.1  christos 	      elf_section_data (sec)->this_hdr.contents = contents;
   1801          1.1  christos 	    }
   1802          1.1  christos 	}
   1803          1.1  christos 
   1804          1.1  christos       /* Get the value of the symbol referred to by the reloc.  */
   1805          1.1  christos       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
   1806          1.1  christos 	{
   1807  1.1.1.7.4.1  christos 	  /* A local symbol.  */
   1808          1.1  christos 	  asection *sym_sec;
   1809          1.1  christos 
   1810          1.1  christos 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
   1811          1.1  christos 	  if (isym->st_shndx == SHN_UNDEF)
   1812          1.1  christos 	    sym_sec = bfd_und_section_ptr;
   1813          1.1  christos 	  else if (isym->st_shndx == SHN_ABS)
   1814          1.1  christos 	    sym_sec = bfd_abs_section_ptr;
   1815          1.1  christos 	  else if (isym->st_shndx == SHN_COMMON)
   1816          1.1  christos 	    sym_sec = bfd_com_section_ptr;
   1817          1.1  christos 	  else
   1818          1.1  christos 	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
   1819          1.1  christos 
   1820          1.1  christos 	  symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
   1821          1.1  christos 	}
   1822          1.1  christos       else
   1823          1.1  christos 	{
   1824          1.1  christos 	  unsigned long indx;
   1825          1.1  christos 	  struct elf_link_hash_entry *h;
   1826          1.1  christos 
   1827  1.1.1.7.4.1  christos 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
   1828          1.1  christos 	  h = elf_sym_hashes (abfd)[indx];
   1829          1.1  christos 	  BFD_ASSERT (h != NULL);
   1830          1.1  christos 
   1831          1.1  christos 	  if (h->root.type != bfd_link_hash_defined
   1832          1.1  christos 	      && h->root.type != bfd_link_hash_defweak)
   1833          1.1  christos 	    /* This appears to be a reference to an undefined
   1834          1.1  christos 	       symbol.  Just ignore it--it will be caught by the
   1835          1.1  christos 	       regular reloc processing.  */
   1836          1.1  christos 	    continue;
   1837          1.1  christos 
   1838          1.1  christos 	  symval = (h->root.u.def.value
   1839          1.1  christos 		    + h->root.u.def.section->output_section->vma
   1840  1.1.1.7.4.1  christos 		    + h->root.u.def.section->output_offset);
   1841          1.1  christos 	}
   1842          1.1  christos 
   1843          1.1  christos       /* If this is a PC-relative reloc, subtract the instr offset from
   1844          1.1  christos 	 the symbol value.  */
   1845          1.1  christos       if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_64_PCREL)
   1846          1.1  christos 	{
   1847  1.1.1.7.4.1  christos 	  symval = symval + irel->r_addend
   1848  1.1.1.7.4.1  christos 	    - (irel->r_offset
   1849  1.1.1.7.4.1  christos 	       + sec->output_section->vma
   1850  1.1.1.7.4.1  christos 	       + sec->output_offset);
   1851  1.1.1.7.4.1  christos 	}
   1852          1.1  christos       else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
   1853          1.1  christos 	{
   1854          1.1  christos 	  symval = symval + irel->r_addend - (sec->output_section->vma);
   1855          1.1  christos 	}
   1856          1.1  christos       else
   1857          1.1  christos 	symval += irel->r_addend;
   1858  1.1.1.7.4.1  christos 
   1859          1.1  christos       if ((symval & 0xffff8000) == 0
   1860          1.1  christos 	  || (symval & 0xffff8000) == 0xffff8000)
   1861          1.1  christos 	{
   1862          1.1  christos 	  /* We can delete this instruction.  */
   1863          1.1  christos 	  sec->relax[sec->relax_count].addr = irel->r_offset;
   1864  1.1.1.7.4.1  christos 	  sec->relax[sec->relax_count].size = INST_WORD_SIZE;
   1865          1.1  christos 	  sec->relax_count++;
   1866          1.1  christos 
   1867          1.1  christos 	  /* Rewrite relocation type.  */
   1868  1.1.1.7.4.1  christos 	  switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
   1869          1.1  christos 	    {
   1870          1.1  christos 	    case R_MICROBLAZE_64_PCREL:
   1871  1.1.1.7.4.1  christos 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1872  1.1.1.7.4.1  christos 					   (int) R_MICROBLAZE_32_PCREL_LO);
   1873  1.1.1.7.4.1  christos 	      break;
   1874  1.1.1.7.4.1  christos 	    case R_MICROBLAZE_64:
   1875  1.1.1.7.4.1  christos 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1876  1.1.1.7.4.1  christos 					   (int) R_MICROBLAZE_32_LO);
   1877          1.1  christos 	      break;
   1878          1.1  christos 	    case R_MICROBLAZE_TEXTREL_64:
   1879          1.1  christos 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1880          1.1  christos 					   (int) R_MICROBLAZE_TEXTREL_32_LO);
   1881  1.1.1.7.4.1  christos 	      break;
   1882  1.1.1.7.4.1  christos 	    default:
   1883          1.1  christos 	      /* Cannot happen.  */
   1884          1.1  christos 	      BFD_ASSERT (FALSE);
   1885          1.1  christos 	    }
   1886          1.1  christos 	}
   1887          1.1  christos     } /* Loop through all relocations.  */
   1888          1.1  christos 
   1889          1.1  christos   /* Loop through the relocs again, and see if anything needs to change.  */
   1890          1.1  christos   if (sec->relax_count > 0)
   1891          1.1  christos     {
   1892          1.1  christos       shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
   1893  1.1.1.7.4.1  christos       rel_count = 0;
   1894          1.1  christos       sec->relax[sec->relax_count].addr = sec->size;
   1895          1.1  christos 
   1896  1.1.1.7.4.1  christos       for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
   1897      1.1.1.2  christos 	{
   1898  1.1.1.7.4.1  christos 	  bfd_vma nraddr;
   1899          1.1  christos 
   1900          1.1  christos 	  /* Get the new reloc address.  */
   1901          1.1  christos 	  nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
   1902          1.1  christos 	  switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
   1903          1.1  christos 	    {
   1904  1.1.1.7.4.1  christos 	    default:
   1905  1.1.1.7.4.1  christos 	      break;
   1906          1.1  christos 	    case R_MICROBLAZE_64_PCREL:
   1907          1.1  christos 	      break;
   1908          1.1  christos 	    case R_MICROBLAZE_TEXTREL_64:
   1909  1.1.1.7.4.1  christos 	    case R_MICROBLAZE_TEXTREL_32_LO:
   1910  1.1.1.7.4.1  christos 	    case R_MICROBLAZE_64:
   1911          1.1  christos 	    case R_MICROBLAZE_32_LO:
   1912  1.1.1.7.4.1  christos 	      /* If this reloc is against a symbol defined in this
   1913          1.1  christos 		 section, we must check the addend to see it will put the value in
   1914          1.1  christos 		 range to be adjusted, and hence must be changed.  */
   1915          1.1  christos 	      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
   1916          1.1  christos 		{
   1917      1.1.1.2  christos 		  isym = isymbuf + ELF32_R_SYM (irel->r_info);
   1918  1.1.1.7.4.1  christos 		  /* Only handle relocs against .text.  */
   1919          1.1  christos 		  if (isym->st_shndx == shndx
   1920          1.1  christos 		      && ELF32_ST_TYPE (isym->st_info) == STT_SECTION)
   1921          1.1  christos 		    irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
   1922  1.1.1.7.4.1  christos 		}
   1923  1.1.1.7.4.1  christos 	      break;
   1924  1.1.1.7.4.1  christos 	    case R_MICROBLAZE_NONE:
   1925  1.1.1.7.4.1  christos 	      {
   1926  1.1.1.7.4.1  christos 		/* This was a PC-relative instruction that was
   1927  1.1.1.7.4.1  christos 		   completely resolved.  */
   1928  1.1.1.7.4.1  christos 		int sfix, efix;
   1929  1.1.1.7.4.1  christos 		bfd_vma target_address;
   1930  1.1.1.7.4.1  christos 		target_address = irel->r_addend + irel->r_offset;
   1931  1.1.1.7.4.1  christos 		sfix = calc_fixup (irel->r_offset, 0, sec);
   1932  1.1.1.7.4.1  christos 		efix = calc_fixup (target_address, 0, sec);
   1933          1.1  christos 		irel->r_addend -= (efix - sfix);
   1934          1.1  christos 		/* Should use HOWTO.  */
   1935          1.1  christos 		microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
   1936          1.1  christos 						   irel->r_addend);
   1937  1.1.1.7.4.1  christos 	      }
   1938  1.1.1.7.4.1  christos 	      break;
   1939  1.1.1.7.4.1  christos 	    case R_MICROBLAZE_64_NONE:
   1940  1.1.1.7.4.1  christos 	      {
   1941          1.1  christos 		/* This was a PC-relative 64-bit instruction that was
   1942      1.1.1.2  christos 		   completely resolved.  */
   1943      1.1.1.2  christos 		int sfix, efix;
   1944          1.1  christos 		bfd_vma target_address;
   1945      1.1.1.2  christos 		target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
   1946  1.1.1.7.4.1  christos 		sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
   1947          1.1  christos 		efix = calc_fixup (target_address, 0, sec);
   1948          1.1  christos 		irel->r_addend -= (efix - sfix);
   1949          1.1  christos     microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
   1950  1.1.1.7.4.1  christos 				       + INST_WORD_SIZE, irel->r_addend);
   1951  1.1.1.7.4.1  christos 	      }
   1952          1.1  christos 	      break;
   1953          1.1  christos 	    }
   1954          1.1  christos 	  irel->r_offset = nraddr;
   1955  1.1.1.7.4.1  christos 	} /* Change all relocs in this section.  */
   1956  1.1.1.7.4.1  christos 
   1957  1.1.1.7.4.1  christos       /* Look through all other sections.  */
   1958  1.1.1.7.4.1  christos       for (o = abfd->sections; o != NULL; o = o->next)
   1959  1.1.1.7.4.1  christos 	{
   1960  1.1.1.7.4.1  christos 	  Elf_Internal_Rela *irelocs;
   1961  1.1.1.7.4.1  christos 	  Elf_Internal_Rela *irelscan, *irelscanend;
   1962  1.1.1.7.4.1  christos 	  bfd_byte *ocontents;
   1963  1.1.1.7.4.1  christos 
   1964  1.1.1.7.4.1  christos 	  if (o == sec
   1965  1.1.1.7.4.1  christos 	      || (o->flags & SEC_RELOC) == 0
   1966  1.1.1.7.4.1  christos 	      || o->reloc_count == 0)
   1967  1.1.1.7.4.1  christos 	    continue;
   1968  1.1.1.7.4.1  christos 
   1969  1.1.1.7.4.1  christos 	  /* We always cache the relocs.  Perhaps, if info->keep_memory is
   1970  1.1.1.7.4.1  christos 	     FALSE, we should free them, if we are permitted to.  */
   1971  1.1.1.7.4.1  christos 
   1972  1.1.1.7.4.1  christos 	  irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
   1973  1.1.1.7.4.1  christos 	  if (irelocs == NULL)
   1974  1.1.1.7.4.1  christos 	    goto error_return;
   1975  1.1.1.7.4.1  christos 
   1976  1.1.1.7.4.1  christos 	  ocontents = NULL;
   1977  1.1.1.7.4.1  christos 	  irelscanend = irelocs + o->reloc_count;
   1978  1.1.1.7.4.1  christos 	  for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
   1979  1.1.1.7.4.1  christos 	    {
   1980  1.1.1.7.4.1  christos 	      if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
   1981  1.1.1.7.4.1  christos 		{
   1982  1.1.1.7.4.1  christos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   1983  1.1.1.7.4.1  christos 
   1984  1.1.1.7.4.1  christos 		  /* Look at the reloc only if the value has been resolved.  */
   1985  1.1.1.7.4.1  christos 		  if (isym->st_shndx == shndx
   1986  1.1.1.7.4.1  christos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   1987  1.1.1.7.4.1  christos 		    {
   1988  1.1.1.7.4.1  christos 		      if (ocontents == NULL)
   1989  1.1.1.7.4.1  christos 			{
   1990  1.1.1.7.4.1  christos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   1991  1.1.1.7.4.1  christos 			    ocontents = elf_section_data (o)->this_hdr.contents;
   1992  1.1.1.7.4.1  christos 			  else
   1993  1.1.1.7.4.1  christos 			    {
   1994  1.1.1.7.4.1  christos 			      /* We always cache the section contents.
   1995  1.1.1.7.4.1  christos 				 Perhaps, if info->keep_memory is FALSE, we
   1996  1.1.1.7.4.1  christos 				 should free them, if we are permitted to.  */
   1997  1.1.1.7.4.1  christos 			      if (o->rawsize == 0)
   1998  1.1.1.7.4.1  christos 				o->rawsize = o->size;
   1999  1.1.1.7.4.1  christos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2000          1.1  christos 			      if (ocontents == NULL)
   2001  1.1.1.7.4.1  christos 				goto error_return;
   2002  1.1.1.7.4.1  christos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2003  1.1.1.7.4.1  christos 							     (file_ptr) 0,
   2004          1.1  christos 							     o->rawsize))
   2005  1.1.1.7.4.1  christos 				goto error_return;
   2006      1.1.1.2  christos 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2007  1.1.1.7.4.1  christos 			    }
   2008          1.1  christos 
   2009          1.1  christos 			}
   2010          1.1  christos 		      irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
   2011          1.1  christos 		    }
   2012          1.1  christos 		  else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
   2013          1.1  christos 		    {
   2014          1.1  christos 		      isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2015          1.1  christos 
   2016          1.1  christos 		      /* Look at the reloc only if the value has been resolved.  */
   2017          1.1  christos 		      if (ocontents == NULL)
   2018          1.1  christos 			{
   2019          1.1  christos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2020          1.1  christos 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2021          1.1  christos 			  else
   2022          1.1  christos 			    {
   2023          1.1  christos 			      /* We always cache the section contents.
   2024          1.1  christos 				 Perhaps, if info->keep_memory is FALSE, we
   2025          1.1  christos 				 should free them, if we are permitted to.  */
   2026          1.1  christos 
   2027          1.1  christos 			      if (o->rawsize == 0)
   2028          1.1  christos 				o->rawsize = o->size;
   2029          1.1  christos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2030          1.1  christos 			      if (ocontents == NULL)
   2031          1.1  christos 				goto error_return;
   2032          1.1  christos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2033          1.1  christos 							     (file_ptr) 0,
   2034          1.1  christos 							     o->rawsize))
   2035          1.1  christos 				goto error_return;
   2036          1.1  christos 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2037      1.1.1.2  christos 			    }
   2038          1.1  christos 			}
   2039          1.1  christos 		      irelscan->r_addend -= calc_fixup (irel->r_addend
   2040          1.1  christos 							+ isym->st_value,
   2041          1.1  christos 							0,
   2042  1.1.1.7.4.1  christos 							sec);
   2043  1.1.1.7.4.1  christos 		    }
   2044  1.1.1.7.4.1  christos 		}
   2045  1.1.1.7.4.1  christos 	      else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
   2046          1.1  christos 		       || (ELF32_R_TYPE (irelscan->r_info)
   2047          1.1  christos 				   == (int) R_MICROBLAZE_32_LO)
   2048          1.1  christos 		       || (ELF32_R_TYPE (irelscan->r_info)
   2049          1.1  christos 				   == (int) R_MICROBLAZE_TEXTREL_32_LO))
   2050          1.1  christos 		{
   2051          1.1  christos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2052          1.1  christos 
   2053          1.1  christos 		  /* Look at the reloc only if the value has been resolved.  */
   2054          1.1  christos 		  if (isym->st_shndx == shndx
   2055          1.1  christos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   2056          1.1  christos 		    {
   2057          1.1  christos 		      bfd_vma immediate;
   2058          1.1  christos 		      bfd_vma target_address;
   2059          1.1  christos 
   2060          1.1  christos 		      if (ocontents == NULL)
   2061          1.1  christos 			{
   2062          1.1  christos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2063          1.1  christos 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2064          1.1  christos 			  else
   2065          1.1  christos 			    {
   2066          1.1  christos 			      /* We always cache the section contents.
   2067          1.1  christos 				 Perhaps, if info->keep_memory is FALSE, we
   2068          1.1  christos 				 should free them, if we are permitted to.  */
   2069          1.1  christos 			      if (o->rawsize == 0)
   2070          1.1  christos 				o->rawsize = o->size;
   2071          1.1  christos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2072          1.1  christos 			      if (ocontents == NULL)
   2073          1.1  christos 				goto error_return;
   2074          1.1  christos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2075          1.1  christos 							     (file_ptr) 0,
   2076          1.1  christos 							     o->rawsize))
   2077          1.1  christos 				goto error_return;
   2078      1.1.1.2  christos 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2079      1.1.1.2  christos 			    }
   2080          1.1  christos 			}
   2081      1.1.1.2  christos 
   2082          1.1  christos 		      unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
   2083          1.1  christos 		      immediate = instr & 0x0000ffff;
   2084  1.1.1.7.4.1  christos 		      target_address = immediate;
   2085  1.1.1.7.4.1  christos 		      offset = calc_fixup (target_address, 0, sec);
   2086          1.1  christos 		      immediate -= offset;
   2087          1.1  christos 		      irelscan->r_addend -= offset;
   2088          1.1  christos 	  microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
   2089  1.1.1.7.4.1  christos 					     irelscan->r_addend);
   2090  1.1.1.7.4.1  christos 		    }
   2091  1.1.1.7.4.1  christos 		}
   2092          1.1  christos 
   2093          1.1  christos 	      if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
   2094          1.1  christos 		  || (ELF32_R_TYPE (irelscan->r_info)
   2095          1.1  christos 			      == (int) R_MICROBLAZE_TEXTREL_64))
   2096          1.1  christos 		{
   2097          1.1  christos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2098          1.1  christos 
   2099          1.1  christos 		  /* Look at the reloc only if the value has been resolved.  */
   2100          1.1  christos 		  if (isym->st_shndx == shndx
   2101          1.1  christos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   2102          1.1  christos 		    {
   2103          1.1  christos 		      bfd_vma immediate;
   2104          1.1  christos 
   2105          1.1  christos 		      if (ocontents == NULL)
   2106          1.1  christos 			{
   2107          1.1  christos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2108          1.1  christos 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2109          1.1  christos 			  else
   2110          1.1  christos 			    {
   2111          1.1  christos 			      /* We always cache the section contents.
   2112          1.1  christos 				 Perhaps, if info->keep_memory is FALSE, we
   2113          1.1  christos 				 should free them, if we are permitted to.  */
   2114          1.1  christos 
   2115          1.1  christos 			      if (o->rawsize == 0)
   2116          1.1  christos 				o->rawsize = o->size;
   2117          1.1  christos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2118          1.1  christos 			      if (ocontents == NULL)
   2119          1.1  christos 				goto error_return;
   2120          1.1  christos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2121          1.1  christos 							     (file_ptr) 0,
   2122          1.1  christos 							     o->rawsize))
   2123  1.1.1.7.4.1  christos 				goto error_return;
   2124  1.1.1.7.4.1  christos 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2125  1.1.1.7.4.1  christos 			    }
   2126  1.1.1.7.4.1  christos 			}
   2127  1.1.1.7.4.1  christos 	  unsigned long instr_hi =  bfd_get_32 (abfd, ocontents
   2128  1.1.1.7.4.1  christos 						+ irelscan->r_offset);
   2129  1.1.1.7.4.1  christos 	  unsigned long instr_lo =  bfd_get_32 (abfd, ocontents
   2130      1.1.1.2  christos 						+ irelscan->r_offset
   2131          1.1  christos 						+ INST_WORD_SIZE);
   2132          1.1  christos 	  immediate = (instr_hi & 0x0000ffff) << 16;
   2133          1.1  christos 	  immediate |= (instr_lo & 0x0000ffff);
   2134          1.1  christos 		      offset = calc_fixup (irelscan->r_addend, 0, sec);
   2135          1.1  christos 		      immediate -= offset;
   2136          1.1  christos 		      irelscan->r_addend -= offset;
   2137          1.1  christos 		    }
   2138          1.1  christos 		}
   2139          1.1  christos 	      else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_PCREL)
   2140          1.1  christos 		{
   2141          1.1  christos 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2142          1.1  christos 
   2143          1.1  christos 		  /* Look at the reloc only if the value has been resolved.  */
   2144          1.1  christos 		  if (isym->st_shndx == shndx
   2145          1.1  christos 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   2146          1.1  christos 		    {
   2147          1.1  christos 		      bfd_vma immediate;
   2148          1.1  christos 		      bfd_vma target_address;
   2149          1.1  christos 
   2150          1.1  christos 		      if (ocontents == NULL)
   2151          1.1  christos 			{
   2152          1.1  christos 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2153          1.1  christos 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2154          1.1  christos 			  else
   2155          1.1  christos 			    {
   2156          1.1  christos 			      /* We always cache the section contents.
   2157          1.1  christos 				 Perhaps, if info->keep_memory is FALSE, we
   2158          1.1  christos 				 should free them, if we are permitted to.  */
   2159          1.1  christos 			      if (o->rawsize == 0)
   2160          1.1  christos 				o->rawsize = o->size;
   2161          1.1  christos 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2162          1.1  christos 			      if (ocontents == NULL)
   2163          1.1  christos 				goto error_return;
   2164          1.1  christos 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2165          1.1  christos 							     (file_ptr) 0,
   2166          1.1  christos 							     o->rawsize))
   2167  1.1.1.7.4.1  christos 				goto error_return;
   2168  1.1.1.7.4.1  christos 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2169  1.1.1.7.4.1  christos 			    }
   2170  1.1.1.7.4.1  christos 			}
   2171  1.1.1.7.4.1  christos 	  unsigned long instr_hi =  bfd_get_32 (abfd, ocontents
   2172  1.1.1.7.4.1  christos 						+ irelscan->r_offset);
   2173  1.1.1.7.4.1  christos 	  unsigned long instr_lo =  bfd_get_32 (abfd, ocontents
   2174          1.1  christos 						+ irelscan->r_offset
   2175      1.1.1.2  christos 						+ INST_WORD_SIZE);
   2176          1.1  christos 	  immediate = (instr_hi & 0x0000ffff) << 16;
   2177          1.1  christos 	  immediate |= (instr_lo & 0x0000ffff);
   2178  1.1.1.7.4.1  christos 		      target_address = immediate;
   2179  1.1.1.7.4.1  christos 		      offset = calc_fixup (target_address, 0, sec);
   2180          1.1  christos 		      immediate -= offset;
   2181          1.1  christos 		      irelscan->r_addend -= offset;
   2182  1.1.1.7.4.1  christos 	  microblaze_bfd_write_imm_value_64 (abfd, ocontents
   2183  1.1.1.7.4.1  christos 					     + irelscan->r_offset, immediate);
   2184          1.1  christos 		    }
   2185          1.1  christos 		}
   2186          1.1  christos 	    }
   2187          1.1  christos 	}
   2188  1.1.1.7.4.1  christos 
   2189  1.1.1.7.4.1  christos       /* Adjust the local symbols defined in this section.  */
   2190  1.1.1.7.4.1  christos       isymend = isymbuf + symtab_hdr->sh_info;
   2191  1.1.1.7.4.1  christos       for (isym = isymbuf; isym < isymend; isym++)
   2192  1.1.1.7.4.1  christos 	{
   2193  1.1.1.7.4.1  christos 	  if (isym->st_shndx == shndx)
   2194  1.1.1.7.4.1  christos 	    {
   2195  1.1.1.7.4.1  christos 	      isym->st_value -= calc_fixup (isym->st_value, 0, sec);
   2196          1.1  christos 	      if (isym->st_size)
   2197          1.1  christos 		isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
   2198          1.1  christos 	    }
   2199      1.1.1.2  christos 	}
   2200      1.1.1.2  christos 
   2201  1.1.1.7.4.1  christos       /* Now adjust the global symbols defined in this section.  */
   2202  1.1.1.7.4.1  christos       isym = isymbuf + symtab_hdr->sh_info;
   2203  1.1.1.7.4.1  christos       symcount =  (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
   2204  1.1.1.7.4.1  christos       for (sym_index = 0; sym_index < symcount; sym_index++)
   2205  1.1.1.7.4.1  christos 	{
   2206  1.1.1.7.4.1  christos 	  sym_hash = elf_sym_hashes (abfd)[sym_index];
   2207  1.1.1.7.4.1  christos 	  if ((sym_hash->root.type == bfd_link_hash_defined
   2208  1.1.1.7.4.1  christos 		  || sym_hash->root.type == bfd_link_hash_defweak)
   2209  1.1.1.7.4.1  christos 	      && sym_hash->root.u.def.section == sec)
   2210  1.1.1.7.4.1  christos 	    {
   2211  1.1.1.7.4.1  christos 	      sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
   2212  1.1.1.7.4.1  christos 							0, sec);
   2213  1.1.1.7.4.1  christos 	      if (sym_hash->size)
   2214          1.1  christos 		sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
   2215          1.1  christos 					      sym_hash->size, sec);
   2216          1.1  christos 	    }
   2217          1.1  christos 	}
   2218  1.1.1.7.4.1  christos 
   2219  1.1.1.7.4.1  christos       /* Physically move the code and change the cooked size.  */
   2220  1.1.1.7.4.1  christos       dest = sec->relax[0].addr;
   2221  1.1.1.7.4.1  christos       for (i = 0; i < sec->relax_count; i++)
   2222  1.1.1.7.4.1  christos 	{
   2223  1.1.1.7.4.1  christos 	  int len;
   2224  1.1.1.7.4.1  christos 	  src = sec->relax[i].addr + sec->relax[i].size;
   2225  1.1.1.7.4.1  christos 	  len = sec->relax[i+1].addr - sec->relax[i].addr - sec->relax[i].size;
   2226  1.1.1.7.4.1  christos 
   2227          1.1  christos 	  memmove (contents + dest, contents + src, len);
   2228          1.1  christos 	  sec->size -= sec->relax[i].size;
   2229          1.1  christos 	  dest += len;
   2230          1.1  christos 	}
   2231          1.1  christos 
   2232          1.1  christos       elf_section_data (sec)->relocs = internal_relocs;
   2233          1.1  christos       free_relocs = NULL;
   2234          1.1  christos 
   2235          1.1  christos       elf_section_data (sec)->this_hdr.contents = contents;
   2236          1.1  christos       free_contents = NULL;
   2237          1.1  christos 
   2238          1.1  christos       symtab_hdr->contents = (bfd_byte *) isymbuf;
   2239          1.1  christos     }
   2240          1.1  christos 
   2241          1.1  christos   if (free_relocs != NULL)
   2242          1.1  christos     {
   2243          1.1  christos       free (free_relocs);
   2244          1.1  christos       free_relocs = NULL;
   2245          1.1  christos     }
   2246          1.1  christos 
   2247          1.1  christos   if (free_contents != NULL)
   2248          1.1  christos     {
   2249          1.1  christos       if (!link_info->keep_memory)
   2250          1.1  christos 	free (free_contents);
   2251          1.1  christos       else
   2252          1.1  christos 	/* Cache the section contents for elf_link_input_bfd.  */
   2253          1.1  christos 	elf_section_data (sec)->this_hdr.contents = contents;
   2254          1.1  christos       free_contents = NULL;
   2255      1.1.1.2  christos     }
   2256          1.1  christos 
   2257          1.1  christos   if (sec->relax_count == 0)
   2258          1.1  christos     {
   2259      1.1.1.2  christos       *again = FALSE;
   2260      1.1.1.2  christos       free (sec->relax);
   2261          1.1  christos       sec->relax = NULL;
   2262          1.1  christos     }
   2263          1.1  christos   else
   2264          1.1  christos     *again = TRUE;
   2265          1.1  christos   return TRUE;
   2266          1.1  christos 
   2267          1.1  christos  error_return:
   2268          1.1  christos   if (free_relocs != NULL)
   2269          1.1  christos     free (free_relocs);
   2270          1.1  christos   if (free_contents != NULL)
   2271          1.1  christos     free (free_contents);
   2272          1.1  christos   if (sec->relax != NULL)
   2273          1.1  christos     {
   2274          1.1  christos       free (sec->relax);
   2275          1.1  christos       sec->relax = NULL;
   2276          1.1  christos       sec->relax_count = 0;
   2277          1.1  christos     }
   2278          1.1  christos   return FALSE;
   2279          1.1  christos }
   2280          1.1  christos 
   2281          1.1  christos /* Return the section that should be marked against GC for a given
   2282          1.1  christos    relocation.  */
   2283  1.1.1.7.4.1  christos 
   2284  1.1.1.7.4.1  christos static asection *
   2285  1.1.1.7.4.1  christos microblaze_elf_gc_mark_hook (asection *sec,
   2286          1.1  christos 			     struct bfd_link_info * info,
   2287          1.1  christos 			     Elf_Internal_Rela * rel,
   2288          1.1  christos 			     struct elf_link_hash_entry * h,
   2289          1.1  christos 			     Elf_Internal_Sym * sym)
   2290          1.1  christos {
   2291          1.1  christos   if (h != NULL)
   2292          1.1  christos     switch (ELF32_R_TYPE (rel->r_info))
   2293          1.1  christos       {
   2294          1.1  christos       case R_MICROBLAZE_GNU_VTINHERIT:
   2295          1.1  christos       case R_MICROBLAZE_GNU_VTENTRY:
   2296          1.1  christos 	return NULL;
   2297          1.1  christos       }
   2298          1.1  christos 
   2299          1.1  christos   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
   2300          1.1  christos }
   2301          1.1  christos 
   2302  1.1.1.7.4.1  christos /* PIC support.  */
   2303  1.1.1.7.4.1  christos 
   2304  1.1.1.7.4.1  christos #define PLT_ENTRY_SIZE 16
   2305  1.1.1.7.4.1  christos 
   2306  1.1.1.7.4.1  christos #define PLT_ENTRY_WORD_0  0xb0000000	      /* "imm 0".  */
   2307          1.1  christos #define PLT_ENTRY_WORD_1  0xe9940000	      /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT.  */
   2308      1.1.1.2  christos #define PLT_ENTRY_WORD_1_NOPIC	0xe9800000    /* "lwi r12,r0,0" - non-PIC object.  */
   2309      1.1.1.2  christos #define PLT_ENTRY_WORD_2  0x98186000	      /* "brad r12".  */
   2310      1.1.1.2  christos #define PLT_ENTRY_WORD_3  0x80000000	      /* "nop".  */
   2311      1.1.1.2  christos 
   2312      1.1.1.2  christos static bfd_boolean
   2313      1.1.1.2  christos update_local_sym_info (bfd *abfd,
   2314      1.1.1.2  christos 		       Elf_Internal_Shdr *symtab_hdr,
   2315      1.1.1.2  christos 		       unsigned long r_symndx,
   2316      1.1.1.2  christos 		       unsigned int tls_type)
   2317      1.1.1.2  christos {
   2318      1.1.1.2  christos   bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
   2319      1.1.1.2  christos   unsigned char *local_got_tls_masks;
   2320      1.1.1.2  christos 
   2321      1.1.1.2  christos   if (local_got_refcounts == NULL)
   2322      1.1.1.2  christos     {
   2323      1.1.1.2  christos       bfd_size_type size = symtab_hdr->sh_info;
   2324  1.1.1.7.4.1  christos 
   2325      1.1.1.2  christos       size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
   2326      1.1.1.2  christos       local_got_refcounts = bfd_zalloc (abfd, size);
   2327      1.1.1.2  christos       if (local_got_refcounts == NULL)
   2328      1.1.1.2  christos 	return FALSE;
   2329  1.1.1.7.4.1  christos       elf_local_got_refcounts (abfd) = local_got_refcounts;
   2330      1.1.1.2  christos     }
   2331      1.1.1.2  christos 
   2332      1.1.1.2  christos   local_got_tls_masks =
   2333      1.1.1.2  christos 	 (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
   2334      1.1.1.2  christos   local_got_tls_masks[r_symndx] |= tls_type;
   2335          1.1  christos   local_got_refcounts[r_symndx] += 1;
   2336          1.1  christos 
   2337          1.1  christos   return TRUE;
   2338          1.1  christos }
   2339          1.1  christos /* Look through the relocs for a section during the first phase.  */
   2340  1.1.1.7.4.1  christos 
   2341          1.1  christos static bfd_boolean
   2342          1.1  christos microblaze_elf_check_relocs (bfd * abfd,
   2343  1.1.1.7.4.1  christos 			     struct bfd_link_info * info,
   2344          1.1  christos 			     asection * sec,
   2345          1.1  christos 			     const Elf_Internal_Rela * relocs)
   2346  1.1.1.7.4.1  christos {
   2347  1.1.1.7.4.1  christos   Elf_Internal_Shdr *		symtab_hdr;
   2348          1.1  christos   struct elf_link_hash_entry ** sym_hashes;
   2349          1.1  christos   struct elf_link_hash_entry ** sym_hashes_end;
   2350          1.1  christos   const Elf_Internal_Rela *	rel;
   2351      1.1.1.6  christos   const Elf_Internal_Rela *	rel_end;
   2352          1.1  christos   struct elf32_mb_link_hash_table *htab;
   2353          1.1  christos   asection *sreloc = NULL;
   2354          1.1  christos 
   2355          1.1  christos   if (bfd_link_relocatable (info))
   2356          1.1  christos     return TRUE;
   2357          1.1  christos 
   2358          1.1  christos   htab = elf32_mb_hash_table (info);
   2359          1.1  christos   if (htab == NULL)
   2360          1.1  christos     return FALSE;
   2361          1.1  christos 
   2362          1.1  christos   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
   2363          1.1  christos   sym_hashes = elf_sym_hashes (abfd);
   2364          1.1  christos   sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
   2365          1.1  christos   if (!elf_bad_symtab (abfd))
   2366          1.1  christos     sym_hashes_end -= symtab_hdr->sh_info;
   2367          1.1  christos 
   2368          1.1  christos   rel_end = relocs + sec->reloc_count;
   2369          1.1  christos 
   2370          1.1  christos   for (rel = relocs; rel < rel_end; rel++)
   2371      1.1.1.2  christos     {
   2372          1.1  christos       unsigned int r_type;
   2373          1.1  christos       struct elf_link_hash_entry * h;
   2374          1.1  christos       unsigned long r_symndx;
   2375          1.1  christos       unsigned char tls_type = 0;
   2376          1.1  christos 
   2377  1.1.1.7.4.1  christos       r_symndx = ELF32_R_SYM (rel->r_info);
   2378          1.1  christos       r_type = ELF32_R_TYPE (rel->r_info);
   2379      1.1.1.3  christos 
   2380      1.1.1.3  christos       if (r_symndx < symtab_hdr->sh_info)
   2381  1.1.1.7.4.1  christos 	h = NULL;
   2382  1.1.1.7.4.1  christos       else
   2383  1.1.1.7.4.1  christos 	{
   2384      1.1.1.3  christos 	  h = sym_hashes [r_symndx - symtab_hdr->sh_info];
   2385          1.1  christos 	  while (h->root.type == bfd_link_hash_indirect
   2386          1.1  christos 		 || h->root.type == bfd_link_hash_warning)
   2387  1.1.1.7.4.1  christos 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
   2388          1.1  christos 	}
   2389          1.1  christos 
   2390  1.1.1.7.4.1  christos       switch (r_type)
   2391  1.1.1.7.4.1  christos 	{
   2392  1.1.1.7.4.1  christos 	  /* This relocation describes the C++ object vtable hierarchy.
   2393  1.1.1.7.4.1  christos 	     Reconstruct it for later use during GC.  */
   2394          1.1  christos 	case R_MICROBLAZE_GNU_VTINHERIT:
   2395          1.1  christos 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
   2396          1.1  christos 	    return FALSE;
   2397  1.1.1.7.4.1  christos 	  break;
   2398  1.1.1.7.4.1  christos 
   2399  1.1.1.7.4.1  christos 	  /* This relocation describes which C++ vtable entries are actually
   2400  1.1.1.7.4.1  christos 	     used.  Record for later use during GC.  */
   2401          1.1  christos 	case R_MICROBLAZE_GNU_VTENTRY:
   2402          1.1  christos 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
   2403  1.1.1.7.4.1  christos 	    return FALSE;
   2404  1.1.1.7.4.1  christos 	  break;
   2405          1.1  christos 
   2406          1.1  christos 	  /* This relocation requires .plt entry.  */
   2407          1.1  christos 	case R_MICROBLAZE_PLT_64:
   2408          1.1  christos 	  if (h != NULL)
   2409  1.1.1.7.4.1  christos 	    {
   2410          1.1  christos 	      h->needs_plt = 1;
   2411          1.1  christos 	      h->plt.refcount += 1;
   2412  1.1.1.7.4.1  christos 	    }
   2413  1.1.1.7.4.1  christos 	  break;
   2414  1.1.1.7.4.1  christos 
   2415  1.1.1.7.4.1  christos 	  /* This relocation requires .got entry.  */
   2416  1.1.1.7.4.1  christos 	case R_MICROBLAZE_TLSGD:
   2417      1.1.1.7  christos 	  tls_type |= (TLS_TLS | TLS_GD);
   2418  1.1.1.7.4.1  christos 	  goto dogottls;
   2419  1.1.1.7.4.1  christos 	case R_MICROBLAZE_TLSLD:
   2420      1.1.1.7  christos 	  tls_type |= (TLS_TLS | TLS_LD);
   2421  1.1.1.7.4.1  christos 	  /* Fall through.  */
   2422  1.1.1.7.4.1  christos 	dogottls:
   2423  1.1.1.7.4.1  christos 	  sec->has_tls_reloc = 1;
   2424  1.1.1.7.4.1  christos 	  /* Fall through.  */
   2425  1.1.1.7.4.1  christos 	case R_MICROBLAZE_GOT_64:
   2426  1.1.1.7.4.1  christos 	  if (htab->elf.sgot == NULL)
   2427  1.1.1.7.4.1  christos 	    {
   2428  1.1.1.7.4.1  christos 	      if (htab->elf.dynobj == NULL)
   2429  1.1.1.7.4.1  christos 		htab->elf.dynobj = abfd;
   2430          1.1  christos 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
   2431          1.1  christos 		return FALSE;
   2432      1.1.1.2  christos 	    }
   2433          1.1  christos 	  if (h != NULL)
   2434  1.1.1.7.4.1  christos 	    {
   2435          1.1  christos 	      h->got.refcount += 1;
   2436      1.1.1.2  christos 	      elf32_mb_hash_entry (h)->tls_mask |= tls_type;
   2437      1.1.1.2  christos 	    }
   2438          1.1  christos 	  else
   2439  1.1.1.7.4.1  christos 	    {
   2440          1.1  christos 	      if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
   2441  1.1.1.7.4.1  christos 		return FALSE;
   2442  1.1.1.7.4.1  christos 	    }
   2443  1.1.1.7.4.1  christos 	  break;
   2444  1.1.1.7.4.1  christos 
   2445  1.1.1.7.4.1  christos 	case R_MICROBLAZE_GOTOFF_64:
   2446  1.1.1.7.4.1  christos 	case R_MICROBLAZE_GOTOFF_32:
   2447  1.1.1.7.4.1  christos 	  if (htab->elf.sgot == NULL)
   2448  1.1.1.7.4.1  christos 	    {
   2449  1.1.1.7.4.1  christos 	      if (htab->elf.dynobj == NULL)
   2450  1.1.1.7.4.1  christos 		htab->elf.dynobj = abfd;
   2451  1.1.1.7.4.1  christos 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
   2452  1.1.1.7.4.1  christos 		return FALSE;
   2453  1.1.1.7.4.1  christos 	    }
   2454  1.1.1.7.4.1  christos 	  break;
   2455  1.1.1.7.4.1  christos 
   2456  1.1.1.7.4.1  christos 	case R_MICROBLAZE_64:
   2457          1.1  christos 	case R_MICROBLAZE_64_PCREL:
   2458          1.1  christos 	case R_MICROBLAZE_32:
   2459          1.1  christos 	  {
   2460          1.1  christos 	    if (h != NULL && !bfd_link_pic (info))
   2461          1.1  christos 	      {
   2462          1.1  christos 		/* we may need a copy reloc.  */
   2463          1.1  christos 		h->non_got_ref = 1;
   2464          1.1  christos 
   2465          1.1  christos 		/* we may also need a .plt entry.  */
   2466          1.1  christos 		h->plt.refcount += 1;
   2467          1.1  christos 		if (ELF32_R_TYPE (rel->r_info) != R_MICROBLAZE_64_PCREL)
   2468          1.1  christos 		  h->pointer_equality_needed = 1;
   2469          1.1  christos 	      }
   2470          1.1  christos 
   2471          1.1  christos 
   2472          1.1  christos 	    /* If we are creating a shared library, and this is a reloc
   2473          1.1  christos 	       against a global symbol, or a non PC relative reloc
   2474          1.1  christos 	       against a local symbol, then we need to copy the reloc
   2475          1.1  christos 	       into the shared library.  However, if we are linking with
   2476          1.1  christos 	       -Bsymbolic, we do not need to copy a reloc against a
   2477          1.1  christos 	       global symbol which is defined in an object we are
   2478          1.1  christos 	       including in the link (i.e., DEF_REGULAR is set).  At
   2479          1.1  christos 	       this point we have not seen all the input files, so it is
   2480          1.1  christos 	       possible that DEF_REGULAR is not set now but will be set
   2481          1.1  christos 	       later (it is never cleared).  In case of a weak definition,
   2482          1.1  christos 	       DEF_REGULAR may be cleared later by a strong definition in
   2483          1.1  christos 	       a shared library.  We account for that possibility below by
   2484          1.1  christos 	       storing information in the relocs_copied field of the hash
   2485          1.1  christos 	       table entry.  A similar situation occurs when creating
   2486          1.1  christos 	       shared libraries and symbol visibility changes render the
   2487          1.1  christos 	       symbol local.
   2488          1.1  christos 
   2489          1.1  christos 	       If on the other hand, we are creating an executable, we
   2490  1.1.1.7.4.1  christos 	       may need to keep relocations for symbols satisfied by a
   2491  1.1.1.7.4.1  christos 	       dynamic library if we manage to avoid copy relocs for the
   2492  1.1.1.7.4.1  christos 	       symbol.  */
   2493  1.1.1.7.4.1  christos 
   2494          1.1  christos 	    if ((bfd_link_pic (info)
   2495          1.1  christos 		 && (sec->flags & SEC_ALLOC) != 0
   2496          1.1  christos 		 && (r_type != R_MICROBLAZE_64_PCREL
   2497  1.1.1.7.4.1  christos 		     || (h != NULL
   2498  1.1.1.7.4.1  christos 			 && (! info->symbolic
   2499  1.1.1.7.4.1  christos 			     || h->root.type == bfd_link_hash_defweak
   2500  1.1.1.7.4.1  christos 			     || !h->def_regular))))
   2501  1.1.1.7.4.1  christos 		|| (!bfd_link_pic (info)
   2502  1.1.1.7.4.1  christos 		    && (sec->flags & SEC_ALLOC) != 0
   2503  1.1.1.7.4.1  christos 		    && h != NULL
   2504  1.1.1.7.4.1  christos 		    && (h->root.type == bfd_link_hash_defweak
   2505  1.1.1.7.4.1  christos 			|| !h->def_regular)))
   2506  1.1.1.7.4.1  christos 	      {
   2507  1.1.1.7.4.1  christos 		struct elf_dyn_relocs *p;
   2508  1.1.1.7.4.1  christos 		struct elf_dyn_relocs **head;
   2509          1.1  christos 
   2510          1.1  christos 		/* When creating a shared object, we must copy these
   2511          1.1  christos 		   relocs into the output file.  We create a reloc
   2512          1.1  christos 		   section in dynobj and make room for the reloc.  */
   2513          1.1  christos 
   2514          1.1  christos 		if (sreloc == NULL)
   2515          1.1  christos 		  {
   2516          1.1  christos 		    bfd *dynobj;
   2517          1.1  christos 
   2518      1.1.1.2  christos 		    if (htab->elf.dynobj == NULL)
   2519      1.1.1.2  christos 		      htab->elf.dynobj = abfd;
   2520          1.1  christos 		    dynobj = htab->elf.dynobj;
   2521      1.1.1.2  christos 
   2522          1.1  christos 		    sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
   2523          1.1  christos 								  2, abfd, 1);
   2524          1.1  christos 		    if (sreloc == NULL)
   2525          1.1  christos 		      return FALSE;
   2526          1.1  christos 		  }
   2527          1.1  christos 
   2528          1.1  christos 		/* If this is a global symbol, we count the number of
   2529          1.1  christos 		   relocations we need for this symbol.  */
   2530          1.1  christos 		if (h != NULL)
   2531          1.1  christos 		  head = &((struct elf32_mb_link_hash_entry *) h)->dyn_relocs;
   2532          1.1  christos 		else
   2533          1.1  christos 		  {
   2534          1.1  christos 		    /* Track dynamic relocs needed for local syms too.
   2535          1.1  christos 		       We really need local syms available to do this
   2536          1.1  christos 		       easily.  Oh well.  */
   2537          1.1  christos 
   2538          1.1  christos 		    asection *s;
   2539          1.1  christos 		    Elf_Internal_Sym *isym;
   2540          1.1  christos 		    void *vpp;
   2541          1.1  christos 
   2542          1.1  christos 		    isym = bfd_sym_from_r_symndx (&htab->sym_sec,
   2543          1.1  christos 						  abfd, r_symndx);
   2544          1.1  christos 		    if (isym == NULL)
   2545          1.1  christos 		      return FALSE;
   2546          1.1  christos 
   2547          1.1  christos 		    s = bfd_section_from_elf_index (abfd, isym->st_shndx);
   2548  1.1.1.7.4.1  christos 		    if (s == NULL)
   2549          1.1  christos 		      return FALSE;
   2550          1.1  christos 
   2551          1.1  christos 		    vpp = &elf_section_data (s)->local_dynrel;
   2552          1.1  christos 		    head = (struct elf_dyn_relocs **) vpp;
   2553          1.1  christos 		  }
   2554          1.1  christos 
   2555  1.1.1.7.4.1  christos 		p = *head;
   2556          1.1  christos 		if (p == NULL || p->sec != sec)
   2557          1.1  christos 		  {
   2558          1.1  christos 		    bfd_size_type amt = sizeof *p;
   2559          1.1  christos 		    p = ((struct elf_dyn_relocs *)
   2560          1.1  christos 			 bfd_alloc (htab->elf.dynobj, amt));
   2561          1.1  christos 		    if (p == NULL)
   2562          1.1  christos 		      return FALSE;
   2563          1.1  christos 		    p->next = *head;
   2564          1.1  christos 		    *head = p;
   2565          1.1  christos 		    p->sec = sec;
   2566          1.1  christos 		    p->count = 0;
   2567          1.1  christos 		    p->pc_count = 0;
   2568          1.1  christos 		  }
   2569          1.1  christos 
   2570  1.1.1.7.4.1  christos 		p->count += 1;
   2571  1.1.1.7.4.1  christos 		if (r_type == R_MICROBLAZE_64_PCREL)
   2572  1.1.1.7.4.1  christos 		  p->pc_count += 1;
   2573          1.1  christos 	      }
   2574          1.1  christos 	  }
   2575          1.1  christos 	  break;
   2576          1.1  christos 	}
   2577          1.1  christos     }
   2578          1.1  christos 
   2579          1.1  christos   return TRUE;
   2580          1.1  christos }
   2581          1.1  christos 
   2582          1.1  christos /* Copy the extra info we tack onto an elf_link_hash_entry.  */
   2583          1.1  christos 
   2584          1.1  christos static void
   2585          1.1  christos microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
   2586          1.1  christos 				     struct elf_link_hash_entry *dir,
   2587          1.1  christos 				     struct elf_link_hash_entry *ind)
   2588          1.1  christos {
   2589          1.1  christos   struct elf32_mb_link_hash_entry *edir, *eind;
   2590          1.1  christos 
   2591          1.1  christos   edir = (struct elf32_mb_link_hash_entry *) dir;
   2592          1.1  christos   eind = (struct elf32_mb_link_hash_entry *) ind;
   2593          1.1  christos 
   2594  1.1.1.7.4.1  christos   if (eind->dyn_relocs != NULL)
   2595  1.1.1.7.4.1  christos     {
   2596          1.1  christos       if (edir->dyn_relocs != NULL)
   2597          1.1  christos 	{
   2598          1.1  christos 	  struct elf_dyn_relocs **pp;
   2599          1.1  christos 	  struct elf_dyn_relocs *p;
   2600          1.1  christos 
   2601          1.1  christos 	  if (ind->root.type == bfd_link_hash_indirect)
   2602          1.1  christos 	    abort ();
   2603          1.1  christos 
   2604  1.1.1.7.4.1  christos 	  /* Add reloc counts against the weak sym to the strong sym
   2605          1.1  christos 	     list.  Merge any entries against the same section.  */
   2606          1.1  christos 	  for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
   2607          1.1  christos 	    {
   2608          1.1  christos 	      struct elf_dyn_relocs *q;
   2609          1.1  christos 
   2610          1.1  christos 	      for (q = edir->dyn_relocs; q != NULL; q = q->next)
   2611          1.1  christos 		if (q->sec == p->sec)
   2612          1.1  christos 		  {
   2613          1.1  christos 		    q->pc_count += p->pc_count;
   2614          1.1  christos 		    q->count += p->count;
   2615          1.1  christos 		    *pp = p->next;
   2616          1.1  christos 		    break;
   2617          1.1  christos 		  }
   2618          1.1  christos 	      if (q == NULL)
   2619          1.1  christos 		pp = &p->next;
   2620          1.1  christos 	    }
   2621          1.1  christos 	  *pp = edir->dyn_relocs;
   2622          1.1  christos 	}
   2623          1.1  christos 
   2624      1.1.1.2  christos       edir->dyn_relocs = eind->dyn_relocs;
   2625      1.1.1.2  christos       eind->dyn_relocs = NULL;
   2626          1.1  christos     }
   2627          1.1  christos 
   2628          1.1  christos   edir->tls_mask |= eind->tls_mask;
   2629  1.1.1.7.4.1  christos 
   2630  1.1.1.7.4.1  christos   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
   2631  1.1.1.7.4.1  christos }
   2632  1.1.1.7.4.1  christos 
   2633  1.1.1.7.4.1  christos /* Find dynamic relocs for H that apply to read-only sections.  */
   2634  1.1.1.7.4.1  christos 
   2635  1.1.1.7.4.1  christos static asection *
   2636  1.1.1.7.4.1  christos readonly_dynrelocs (struct elf_link_hash_entry *h)
   2637  1.1.1.7.4.1  christos {
   2638  1.1.1.7.4.1  christos   struct elf_dyn_relocs *p;
   2639  1.1.1.7.4.1  christos 
   2640  1.1.1.7.4.1  christos   for (p = elf32_mb_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
   2641  1.1.1.7.4.1  christos     {
   2642  1.1.1.7.4.1  christos       asection *s = p->sec->output_section;
   2643  1.1.1.7.4.1  christos 
   2644  1.1.1.7.4.1  christos       if (s != NULL && (s->flags & SEC_READONLY) != 0)
   2645  1.1.1.7.4.1  christos 	return p->sec;
   2646          1.1  christos     }
   2647          1.1  christos   return NULL;
   2648          1.1  christos }
   2649          1.1  christos 
   2650          1.1  christos static bfd_boolean
   2651      1.1.1.7  christos microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   2652          1.1  christos 				      struct elf_link_hash_entry *h)
   2653          1.1  christos {
   2654          1.1  christos   struct elf32_mb_link_hash_table *htab;
   2655          1.1  christos   asection *s, *srel;
   2656          1.1  christos   unsigned int power_of_two;
   2657          1.1  christos 
   2658          1.1  christos   htab = elf32_mb_hash_table (info);
   2659          1.1  christos   if (htab == NULL)
   2660          1.1  christos     return FALSE;
   2661          1.1  christos 
   2662          1.1  christos   /* If this is a function, put it in the procedure linkage table.  We
   2663          1.1  christos      will fill in the contents of the procedure linkage table later,
   2664          1.1  christos      when we know the address of the .got section.  */
   2665          1.1  christos   if (h->type == STT_FUNC
   2666          1.1  christos       || h->needs_plt)
   2667          1.1  christos     {
   2668          1.1  christos       if (h->plt.refcount <= 0
   2669          1.1  christos 	  || SYMBOL_CALLS_LOCAL (info, h)
   2670          1.1  christos 	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
   2671          1.1  christos 	      && h->root.type == bfd_link_hash_undefweak))
   2672          1.1  christos 	{
   2673          1.1  christos 	  /* This case can occur if we saw a PLT reloc in an input
   2674          1.1  christos 	     file, but the symbol was never referred to by a dynamic
   2675          1.1  christos 	     object, or if all references were garbage collected.  In
   2676          1.1  christos 	     such a case, we don't actually need to build a procedure
   2677          1.1  christos 	     linkage table, and we can just do a PC32 reloc instead.  */
   2678          1.1  christos 	  h->plt.offset = (bfd_vma) -1;
   2679          1.1  christos 	  h->needs_plt = 0;
   2680          1.1  christos 	}
   2681          1.1  christos 
   2682          1.1  christos       return TRUE;
   2683          1.1  christos     }
   2684          1.1  christos   else
   2685          1.1  christos     /* It's possible that we incorrectly decided a .plt reloc was
   2686          1.1  christos        needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
   2687          1.1  christos        check_relocs.  We can't decide accurately between function and
   2688          1.1  christos        non-function syms in check-relocs;  Objects loaded later in
   2689          1.1  christos        the link may change h->type.  So fix it now.  */
   2690          1.1  christos     h->plt.offset = (bfd_vma) -1;
   2691  1.1.1.7.4.1  christos 
   2692          1.1  christos   /* If this is a weak symbol, and there is a real definition, the
   2693  1.1.1.7.4.1  christos      processor independent code will have arranged for us to see the
   2694  1.1.1.7.4.1  christos      real definition first, and we can just use the same value.  */
   2695  1.1.1.7.4.1  christos   if (h->is_weakalias)
   2696  1.1.1.7.4.1  christos     {
   2697          1.1  christos       struct elf_link_hash_entry *def = weakdef (h);
   2698          1.1  christos       BFD_ASSERT (def->root.type == bfd_link_hash_defined);
   2699          1.1  christos       h->root.u.def.section = def->root.u.def.section;
   2700          1.1  christos       h->root.u.def.value = def->root.u.def.value;
   2701          1.1  christos       return TRUE;
   2702          1.1  christos     }
   2703          1.1  christos 
   2704          1.1  christos   /* This is a reference to a symbol defined by a dynamic object which
   2705          1.1  christos      is not a function.  */
   2706          1.1  christos 
   2707      1.1.1.6  christos   /* If we are creating a shared library, we must presume that the
   2708          1.1  christos      only references to the symbol are via the global offset table.
   2709          1.1  christos      For such cases we need not do anything here; the relocations will
   2710          1.1  christos      be handled correctly by relocate_section.  */
   2711          1.1  christos   if (bfd_link_pic (info))
   2712          1.1  christos     return TRUE;
   2713          1.1  christos 
   2714          1.1  christos   /* If there are no references to this symbol that do not use the
   2715          1.1  christos      GOT, we don't need to generate a copy reloc.  */
   2716          1.1  christos   if (!h->non_got_ref)
   2717          1.1  christos     return TRUE;
   2718          1.1  christos 
   2719          1.1  christos   /* If -z nocopyreloc was given, we won't generate them either.  */
   2720          1.1  christos   if (info->nocopyreloc)
   2721          1.1  christos     {
   2722  1.1.1.7.4.1  christos       h->non_got_ref = 0;
   2723          1.1  christos       return TRUE;
   2724  1.1.1.7.4.1  christos     }
   2725          1.1  christos 
   2726          1.1  christos   /* If we don't find any dynamic relocs in read-only sections, then
   2727          1.1  christos      we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
   2728          1.1  christos   if (!readonly_dynrelocs (h))
   2729          1.1  christos     {
   2730          1.1  christos       h->non_got_ref = 0;
   2731          1.1  christos       return TRUE;
   2732          1.1  christos     }
   2733          1.1  christos 
   2734          1.1  christos   /* We must allocate the symbol in our .dynbss section, which will
   2735          1.1  christos      become part of the .bss section of the executable.  There will be
   2736          1.1  christos      an entry for this symbol in the .dynsym section.  The dynamic
   2737          1.1  christos      object will contain position independent code, so all references
   2738          1.1  christos      from the dynamic object to this symbol will go through the global
   2739          1.1  christos      offset table.  The dynamic linker will use the .dynsym entry to
   2740          1.1  christos      determine the address it must put in the global offset table, so
   2741          1.1  christos      both the dynamic object and the regular object will refer to the
   2742          1.1  christos      same memory location for the variable.  */
   2743      1.1.1.7  christos 
   2744      1.1.1.7  christos   /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
   2745      1.1.1.7  christos      to copy the initial value out of the dynamic object and into the
   2746      1.1.1.7  christos      runtime process image.  */
   2747      1.1.1.7  christos   if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
   2748      1.1.1.7  christos     {
   2749      1.1.1.7  christos       s = htab->elf.sdynrelro;
   2750      1.1.1.7  christos       srel = htab->elf.sreldynrelro;
   2751      1.1.1.7  christos     }
   2752      1.1.1.7  christos   else
   2753          1.1  christos     {
   2754          1.1  christos       s = htab->elf.sdynbss;
   2755      1.1.1.7  christos       srel = htab->elf.srelbss;
   2756          1.1  christos     }
   2757          1.1  christos   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
   2758          1.1  christos     {
   2759          1.1  christos       srel->size += sizeof (Elf32_External_Rela);
   2760          1.1  christos       h->needs_copy = 1;
   2761          1.1  christos     }
   2762          1.1  christos 
   2763          1.1  christos   /* We need to figure out the alignment required for this symbol.  I
   2764          1.1  christos      have no idea how ELF linkers handle this.  */
   2765          1.1  christos   power_of_two = bfd_log2 (h->size);
   2766      1.1.1.7  christos   if (power_of_two > 3)
   2767      1.1.1.7  christos     power_of_two = 3;
   2768          1.1  christos 
   2769      1.1.1.7  christos   /* Apply the required alignment.  */
   2770          1.1  christos   s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
   2771          1.1  christos   if (power_of_two > s->alignment_power)
   2772          1.1  christos     {
   2773          1.1  christos       if (!bfd_set_section_alignment (s->owner, s, power_of_two))
   2774      1.1.1.7  christos 	return FALSE;
   2775      1.1.1.7  christos     }
   2776          1.1  christos 
   2777          1.1  christos   /* Define the symbol as being at this point in the section.  */
   2778      1.1.1.7  christos   h->root.u.def.section = s;
   2779          1.1  christos   h->root.u.def.value = s->size;
   2780          1.1  christos 
   2781          1.1  christos   /* Increment the section size to make room for the symbol.  */
   2782          1.1  christos   s->size += h->size;
   2783          1.1  christos   return TRUE;
   2784          1.1  christos }
   2785          1.1  christos 
   2786          1.1  christos /* Allocate space in .plt, .got and associated reloc sections for
   2787          1.1  christos    dynamic relocs.  */
   2788          1.1  christos 
   2789          1.1  christos static bfd_boolean
   2790          1.1  christos allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
   2791  1.1.1.7.4.1  christos {
   2792          1.1  christos   struct bfd_link_info *info;
   2793          1.1  christos   struct elf32_mb_link_hash_table *htab;
   2794          1.1  christos   struct elf32_mb_link_hash_entry *eh;
   2795          1.1  christos   struct elf_dyn_relocs *p;
   2796          1.1  christos 
   2797          1.1  christos   if (h->root.type == bfd_link_hash_indirect)
   2798          1.1  christos     return TRUE;
   2799          1.1  christos 
   2800          1.1  christos   info = (struct bfd_link_info *) dat;
   2801          1.1  christos   htab = elf32_mb_hash_table (info);
   2802          1.1  christos   if (htab == NULL)
   2803          1.1  christos     return FALSE;
   2804          1.1  christos 
   2805          1.1  christos   if (htab->elf.dynamic_sections_created
   2806          1.1  christos       && h->plt.refcount > 0)
   2807  1.1.1.7.4.1  christos     {
   2808  1.1.1.7.4.1  christos       /* Make sure this symbol is output as a dynamic symbol.
   2809  1.1.1.7.4.1  christos 	 Undefined weak syms won't yet be marked as dynamic.  */
   2810  1.1.1.7.4.1  christos       if (h->dynindx == -1
   2811  1.1.1.7.4.1  christos 	  && !h->forced_local)
   2812          1.1  christos 	{
   2813      1.1.1.6  christos 	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
   2814  1.1.1.7.4.1  christos 	    return FALSE;
   2815  1.1.1.7.4.1  christos 	}
   2816          1.1  christos 
   2817  1.1.1.7.4.1  christos       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
   2818  1.1.1.7.4.1  christos 	{
   2819  1.1.1.7.4.1  christos 	  asection *s = htab->elf.splt;
   2820  1.1.1.7.4.1  christos 
   2821  1.1.1.7.4.1  christos 	  /* The first entry in .plt is reserved.  */
   2822  1.1.1.7.4.1  christos 	  if (s->size == 0)
   2823  1.1.1.7.4.1  christos 	    s->size = PLT_ENTRY_SIZE;
   2824  1.1.1.7.4.1  christos 
   2825  1.1.1.7.4.1  christos 	  h->plt.offset = s->size;
   2826  1.1.1.7.4.1  christos 
   2827  1.1.1.7.4.1  christos 	  /* If this symbol is not defined in a regular file, and we are
   2828  1.1.1.7.4.1  christos 	     not generating a shared library, then set the symbol to this
   2829  1.1.1.7.4.1  christos 	     location in the .plt.  This is required to make function
   2830  1.1.1.7.4.1  christos 	     pointers compare as equal between the normal executable and
   2831  1.1.1.7.4.1  christos 	     the shared library.  */
   2832  1.1.1.7.4.1  christos 	  if (! bfd_link_pic (info)
   2833  1.1.1.7.4.1  christos 	      && !h->def_regular)
   2834          1.1  christos 	    {
   2835  1.1.1.7.4.1  christos 	      h->root.u.def.section = s;
   2836  1.1.1.7.4.1  christos 	      h->root.u.def.value = h->plt.offset;
   2837          1.1  christos 	    }
   2838  1.1.1.7.4.1  christos 
   2839  1.1.1.7.4.1  christos 	  /* Make room for this entry.  */
   2840      1.1.1.7  christos 	  s->size += PLT_ENTRY_SIZE;
   2841          1.1  christos 
   2842  1.1.1.7.4.1  christos 	  /* We also need to make an entry in the .got.plt section, which
   2843  1.1.1.7.4.1  christos 	     will be placed in the .got section by the linker script.  */
   2844  1.1.1.7.4.1  christos 	  htab->elf.sgotplt->size += 4;
   2845          1.1  christos 
   2846  1.1.1.7.4.1  christos 	  /* We also need to make an entry in the .rel.plt section.  */
   2847  1.1.1.7.4.1  christos 	  htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
   2848  1.1.1.7.4.1  christos 	}
   2849  1.1.1.7.4.1  christos       else
   2850          1.1  christos 	{
   2851          1.1  christos 	  h->plt.offset = (bfd_vma) -1;
   2852          1.1  christos 	  h->needs_plt = 0;
   2853          1.1  christos 	}
   2854          1.1  christos     }
   2855          1.1  christos   else
   2856          1.1  christos     {
   2857      1.1.1.2  christos       h->plt.offset = (bfd_vma) -1;
   2858          1.1  christos       h->needs_plt = 0;
   2859          1.1  christos     }
   2860      1.1.1.2  christos 
   2861          1.1  christos   eh = (struct elf32_mb_link_hash_entry *) h;
   2862          1.1  christos   if (h->got.refcount > 0)
   2863          1.1  christos     {
   2864  1.1.1.7.4.1  christos       unsigned int need;
   2865          1.1  christos       asection *s;
   2866  1.1.1.7.4.1  christos 
   2867  1.1.1.7.4.1  christos       /* Make sure this symbol is output as a dynamic symbol.
   2868  1.1.1.7.4.1  christos 	 Undefined weak syms won't yet be marked as dynamic.  */
   2869  1.1.1.7.4.1  christos       if (h->dynindx == -1
   2870  1.1.1.7.4.1  christos 	  && !h->forced_local)
   2871          1.1  christos 	{
   2872      1.1.1.2  christos 	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
   2873      1.1.1.2  christos 	    return FALSE;
   2874  1.1.1.7.4.1  christos 	}
   2875  1.1.1.7.4.1  christos 
   2876  1.1.1.7.4.1  christos       need = 0;
   2877  1.1.1.7.4.1  christos       if ((eh->tls_mask & TLS_TLS) != 0)
   2878  1.1.1.7.4.1  christos 	{
   2879  1.1.1.7.4.1  christos 	  /* Handle TLS Symbol */
   2880  1.1.1.7.4.1  christos 	  if ((eh->tls_mask & TLS_LD) != 0)
   2881  1.1.1.7.4.1  christos 	    {
   2882  1.1.1.7.4.1  christos 	      if (!eh->elf.def_dynamic)
   2883  1.1.1.7.4.1  christos 		/* We'll just use htab->tlsld_got.offset.  This should
   2884  1.1.1.7.4.1  christos 		   always be the case.  It's a little odd if we have
   2885  1.1.1.7.4.1  christos 		   a local dynamic reloc against a non-local symbol.  */
   2886  1.1.1.7.4.1  christos 		htab->tlsld_got.refcount += 1;
   2887  1.1.1.7.4.1  christos 	      else
   2888  1.1.1.7.4.1  christos 		need += 8;
   2889      1.1.1.2  christos 	    }
   2890  1.1.1.7.4.1  christos 	  if ((eh->tls_mask & TLS_GD) != 0)
   2891  1.1.1.7.4.1  christos 	    need += 8;
   2892  1.1.1.7.4.1  christos 	}
   2893  1.1.1.7.4.1  christos       else
   2894      1.1.1.2  christos 	{
   2895  1.1.1.7.4.1  christos 	  /* Regular (non-TLS) symbol */
   2896  1.1.1.7.4.1  christos 	  need += 4;
   2897  1.1.1.7.4.1  christos 	}
   2898      1.1.1.2  christos       if (need == 0)
   2899  1.1.1.7.4.1  christos 	{
   2900  1.1.1.7.4.1  christos 	  h->got.offset = (bfd_vma) -1;
   2901  1.1.1.7.4.1  christos 	}
   2902  1.1.1.7.4.1  christos       else
   2903  1.1.1.7.4.1  christos 	{
   2904  1.1.1.7.4.1  christos 	  s = htab->elf.sgot;
   2905          1.1  christos 	  h->got.offset = s->size;
   2906          1.1  christos 	  s->size += need;
   2907          1.1  christos 	  htab->elf.srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
   2908          1.1  christos 	}
   2909          1.1  christos     }
   2910          1.1  christos   else
   2911          1.1  christos     h->got.offset = (bfd_vma) -1;
   2912          1.1  christos 
   2913          1.1  christos   if (eh->dyn_relocs == NULL)
   2914          1.1  christos     return TRUE;
   2915          1.1  christos 
   2916          1.1  christos   /* In the shared -Bsymbolic case, discard space allocated for
   2917          1.1  christos      dynamic pc-relative relocs against symbols which turn out to be
   2918      1.1.1.6  christos      defined in regular objects.  For the normal shared case, discard
   2919          1.1  christos      space for pc-relative relocs that have become local due to symbol
   2920          1.1  christos      visibility changes.  */
   2921          1.1  christos 
   2922          1.1  christos   if (bfd_link_pic (info))
   2923          1.1  christos     {
   2924  1.1.1.7.4.1  christos       if (h->def_regular
   2925          1.1  christos 	  && (h->forced_local
   2926          1.1  christos 	      || info->symbolic))
   2927          1.1  christos 	{
   2928          1.1  christos 	  struct elf_dyn_relocs **pp;
   2929          1.1  christos 
   2930          1.1  christos 	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
   2931          1.1  christos 	    {
   2932          1.1  christos 	      p->count -= p->pc_count;
   2933          1.1  christos 	      p->pc_count = 0;
   2934          1.1  christos 	      if (p->count == 0)
   2935          1.1  christos 		*pp = p->next;
   2936  1.1.1.7.4.1  christos 	      else
   2937  1.1.1.7.4.1  christos 		pp = &p->next;
   2938          1.1  christos 	    }
   2939          1.1  christos 	}
   2940          1.1  christos       else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
   2941          1.1  christos 	eh->dyn_relocs = NULL;
   2942          1.1  christos     }
   2943          1.1  christos   else
   2944          1.1  christos     {
   2945          1.1  christos       /* For the non-shared case, discard space for relocs against
   2946          1.1  christos 	 symbols which turn out to need copy relocs or are not
   2947          1.1  christos 	 dynamic.  */
   2948          1.1  christos 
   2949          1.1  christos       if (!h->non_got_ref
   2950          1.1  christos 	  && ((h->def_dynamic
   2951          1.1  christos 	       && !h->def_regular)
   2952          1.1  christos 	      || (htab->elf.dynamic_sections_created
   2953          1.1  christos 		  && (h->root.type == bfd_link_hash_undefweak
   2954          1.1  christos 		      || h->root.type == bfd_link_hash_undefined))))
   2955          1.1  christos 	{
   2956          1.1  christos 	  /* Make sure this symbol is output as a dynamic symbol.
   2957          1.1  christos 	     Undefined weak syms won't yet be marked as dynamic.  */
   2958          1.1  christos 	  if (h->dynindx == -1
   2959          1.1  christos 	      && !h->forced_local)
   2960          1.1  christos 	    {
   2961          1.1  christos 	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
   2962          1.1  christos 		return FALSE;
   2963          1.1  christos 	    }
   2964          1.1  christos 
   2965          1.1  christos 	  /* If that succeeded, we know we'll be keeping all the
   2966          1.1  christos 	     relocs.  */
   2967          1.1  christos 	  if (h->dynindx != -1)
   2968          1.1  christos 	    goto keep;
   2969          1.1  christos 	}
   2970          1.1  christos 
   2971          1.1  christos       eh->dyn_relocs = NULL;
   2972          1.1  christos 
   2973          1.1  christos     keep: ;
   2974          1.1  christos     }
   2975          1.1  christos 
   2976          1.1  christos   /* Finally, allocate space.  */
   2977          1.1  christos   for (p = eh->dyn_relocs; p != NULL; p = p->next)
   2978          1.1  christos     {
   2979          1.1  christos       asection *sreloc = elf_section_data (p->sec)->sreloc;
   2980          1.1  christos       sreloc->size += p->count * sizeof (Elf32_External_Rela);
   2981          1.1  christos     }
   2982          1.1  christos 
   2983          1.1  christos   return TRUE;
   2984          1.1  christos }
   2985          1.1  christos 
   2986          1.1  christos /* Set the sizes of the dynamic sections.  */
   2987          1.1  christos 
   2988          1.1  christos static bfd_boolean
   2989          1.1  christos microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   2990          1.1  christos 				      struct bfd_link_info *info)
   2991          1.1  christos {
   2992          1.1  christos   struct elf32_mb_link_hash_table *htab;
   2993          1.1  christos   bfd *dynobj;
   2994          1.1  christos   asection *s;
   2995          1.1  christos   bfd *ibfd;
   2996          1.1  christos 
   2997          1.1  christos   htab = elf32_mb_hash_table (info);
   2998          1.1  christos   if (htab == NULL)
   2999          1.1  christos     return FALSE;
   3000          1.1  christos 
   3001          1.1  christos   dynobj = htab->elf.dynobj;
   3002      1.1.1.4  christos   BFD_ASSERT (dynobj != NULL);
   3003          1.1  christos 
   3004          1.1  christos   /* Set up .got offsets for local syms, and space for local dynamic
   3005          1.1  christos      relocs.  */
   3006          1.1  christos   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
   3007          1.1  christos     {
   3008      1.1.1.2  christos       bfd_signed_vma *local_got;
   3009          1.1  christos       bfd_signed_vma *end_local_got;
   3010          1.1  christos       bfd_size_type locsymcount;
   3011          1.1  christos       Elf_Internal_Shdr *symtab_hdr;
   3012  1.1.1.7.4.1  christos       unsigned char *lgot_masks;
   3013          1.1  christos       asection *srel;
   3014          1.1  christos 
   3015          1.1  christos       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
   3016  1.1.1.7.4.1  christos 	continue;
   3017          1.1  christos 
   3018  1.1.1.7.4.1  christos       for (s = ibfd->sections; s != NULL; s = s->next)
   3019          1.1  christos 	{
   3020          1.1  christos 	  struct elf_dyn_relocs *p;
   3021          1.1  christos 
   3022          1.1  christos 	  for (p = ((struct elf_dyn_relocs *)
   3023          1.1  christos 		    elf_section_data (s)->local_dynrel);
   3024          1.1  christos 	       p != NULL;
   3025          1.1  christos 	       p = p->next)
   3026          1.1  christos 	    {
   3027          1.1  christos 	      if (!bfd_is_abs_section (p->sec)
   3028          1.1  christos 		  && bfd_is_abs_section (p->sec->output_section))
   3029          1.1  christos 		{
   3030          1.1  christos 		  /* Input section has been discarded, either because
   3031          1.1  christos 		     it is a copy of a linkonce section or due to
   3032          1.1  christos 		     linker script /DISCARD/, so we'll be discarding
   3033          1.1  christos 		     the relocs too.  */
   3034          1.1  christos 		}
   3035          1.1  christos 	      else if (p->count != 0)
   3036          1.1  christos 		{
   3037          1.1  christos 		  srel = elf_section_data (p->sec)->sreloc;
   3038          1.1  christos 		  srel->size += p->count * sizeof (Elf32_External_Rela);
   3039          1.1  christos 		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
   3040          1.1  christos 		    info->flags |= DF_TEXTREL;
   3041          1.1  christos 		}
   3042          1.1  christos 	    }
   3043  1.1.1.7.4.1  christos 	}
   3044          1.1  christos 
   3045          1.1  christos       local_got = elf_local_got_refcounts (ibfd);
   3046          1.1  christos       if (!local_got)
   3047          1.1  christos 	continue;
   3048      1.1.1.2  christos 
   3049      1.1.1.7  christos       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
   3050      1.1.1.7  christos       locsymcount = symtab_hdr->sh_info;
   3051          1.1  christos       end_local_got = local_got + locsymcount;
   3052      1.1.1.2  christos       lgot_masks = (unsigned char *) end_local_got;
   3053      1.1.1.2  christos       s = htab->elf.sgot;
   3054      1.1.1.2  christos       srel = htab->elf.srelgot;
   3055      1.1.1.2  christos 
   3056      1.1.1.2  christos       for (; local_got < end_local_got; ++local_got, ++lgot_masks)
   3057      1.1.1.2  christos 	{
   3058      1.1.1.2  christos 	  if (*local_got > 0)
   3059      1.1.1.2  christos 	    {
   3060      1.1.1.2  christos 	      unsigned int need = 0;
   3061      1.1.1.2  christos 	      if ((*lgot_masks & TLS_TLS) != 0)
   3062      1.1.1.2  christos 		{
   3063      1.1.1.2  christos 		  if ((*lgot_masks & TLS_GD) != 0)
   3064      1.1.1.2  christos 		    need += 8;
   3065      1.1.1.2  christos 		  if ((*lgot_masks & TLS_LD) != 0)
   3066      1.1.1.2  christos 		    htab->tlsld_got.refcount += 1;
   3067      1.1.1.2  christos 		}
   3068      1.1.1.2  christos 	      else
   3069      1.1.1.2  christos 		need += 4;
   3070      1.1.1.2  christos 
   3071      1.1.1.2  christos 	      if (need == 0)
   3072      1.1.1.2  christos 		{
   3073      1.1.1.2  christos 		  *local_got = (bfd_vma) -1;
   3074      1.1.1.2  christos 		}
   3075      1.1.1.6  christos 	      else
   3076      1.1.1.2  christos 		{
   3077      1.1.1.2  christos 		  *local_got = s->size;
   3078  1.1.1.7.4.1  christos 		  s->size += need;
   3079  1.1.1.7.4.1  christos 		  if (bfd_link_pic (info))
   3080  1.1.1.7.4.1  christos 		    srel->size += need * (sizeof (Elf32_External_Rela) / 4);
   3081  1.1.1.7.4.1  christos 		}
   3082          1.1  christos 	    }
   3083          1.1  christos 	  else
   3084          1.1  christos 	    *local_got = (bfd_vma) -1;
   3085          1.1  christos 	}
   3086          1.1  christos     }
   3087          1.1  christos 
   3088      1.1.1.2  christos   /* Allocate global sym .plt and .got entries, and space for global
   3089      1.1.1.2  christos      sym dynamic relocs.  */
   3090      1.1.1.7  christos   elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
   3091      1.1.1.7  christos 
   3092      1.1.1.6  christos   if (htab->tlsld_got.refcount > 0)
   3093  1.1.1.7.4.1  christos     {
   3094      1.1.1.2  christos       htab->tlsld_got.offset = htab->elf.sgot->size;
   3095      1.1.1.2  christos       htab->elf.sgot->size += 8;
   3096      1.1.1.2  christos       if (bfd_link_pic (info))
   3097      1.1.1.2  christos 	htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
   3098          1.1  christos     }
   3099          1.1  christos   else
   3100          1.1  christos     htab->tlsld_got.offset = (bfd_vma) -1;
   3101      1.1.1.7  christos 
   3102  1.1.1.7.4.1  christos   if (elf_hash_table (info)->dynamic_sections_created)
   3103          1.1  christos     {
   3104          1.1  christos       /* Make space for the trailing nop in .plt.  */
   3105          1.1  christos       if (htab->elf.splt->size > 0)
   3106          1.1  christos 	htab->elf.splt->size += 4;
   3107          1.1  christos     }
   3108          1.1  christos 
   3109          1.1  christos   /* The check_relocs and adjust_dynamic_symbol entry points have
   3110          1.1  christos      determined the sizes of the various dynamic sections.  Allocate
   3111          1.1  christos      memory for them.  */
   3112          1.1  christos   for (s = dynobj->sections; s != NULL; s = s->next)
   3113          1.1  christos     {
   3114  1.1.1.7.4.1  christos       const char *name;
   3115          1.1  christos       bfd_boolean strip = FALSE;
   3116          1.1  christos 
   3117  1.1.1.7.4.1  christos       if ((s->flags & SEC_LINKER_CREATED) == 0)
   3118          1.1  christos 	continue;
   3119          1.1  christos 
   3120          1.1  christos       /* It's OK to base decisions on the section name, because none
   3121  1.1.1.7.4.1  christos 	 of the dynobj section names depend upon the input files.  */
   3122  1.1.1.7.4.1  christos       name = bfd_get_section_name (dynobj, s);
   3123  1.1.1.7.4.1  christos 
   3124  1.1.1.7.4.1  christos       if (strncmp (name, ".rela", 5) == 0)
   3125  1.1.1.7.4.1  christos 	{
   3126  1.1.1.7.4.1  christos 	  if (s->size == 0)
   3127  1.1.1.7.4.1  christos 	    {
   3128  1.1.1.7.4.1  christos 	      /* If we don't need this section, strip it from the
   3129  1.1.1.7.4.1  christos 		 output file.  This is to handle .rela.bss and
   3130  1.1.1.7.4.1  christos 		 .rela.plt.  We must create it in
   3131  1.1.1.7.4.1  christos 		 create_dynamic_sections, because it must be created
   3132  1.1.1.7.4.1  christos 		 before the linker maps input sections to output
   3133  1.1.1.7.4.1  christos 		 sections.  The linker does that before
   3134  1.1.1.7.4.1  christos 		 adjust_dynamic_symbol is called, and it is that
   3135  1.1.1.7.4.1  christos 		 function which decides whether anything needs to go
   3136  1.1.1.7.4.1  christos 		 into these sections.  */
   3137  1.1.1.7.4.1  christos 	      strip = TRUE;
   3138  1.1.1.7.4.1  christos 	    }
   3139  1.1.1.7.4.1  christos 	  else
   3140  1.1.1.7.4.1  christos 	    {
   3141  1.1.1.7.4.1  christos 	      /* We use the reloc_count field as a counter if we need
   3142      1.1.1.7  christos 		 to copy relocs into the output file.  */
   3143      1.1.1.7  christos 	      s->reloc_count = 0;
   3144      1.1.1.7  christos 	    }
   3145      1.1.1.7  christos 	}
   3146      1.1.1.7  christos       else if (s != htab->elf.splt
   3147  1.1.1.7.4.1  christos 	       && s != htab->elf.sgot
   3148  1.1.1.7.4.1  christos 	       && s != htab->elf.sgotplt
   3149  1.1.1.7.4.1  christos 	       && s != htab->elf.sdynbss
   3150  1.1.1.7.4.1  christos 	       && s != htab->elf.sdynrelro)
   3151          1.1  christos 	{
   3152          1.1  christos 	  /* It's not one of our sections, so don't allocate space.  */
   3153  1.1.1.7.4.1  christos 	  continue;
   3154  1.1.1.7.4.1  christos 	}
   3155  1.1.1.7.4.1  christos 
   3156  1.1.1.7.4.1  christos       if (strip)
   3157          1.1  christos 	{
   3158          1.1  christos 	  s->flags |= SEC_EXCLUDE;
   3159          1.1  christos 	  continue;
   3160  1.1.1.7.4.1  christos 	}
   3161  1.1.1.7.4.1  christos 
   3162  1.1.1.7.4.1  christos       /* Allocate memory for the section contents.  */
   3163  1.1.1.7.4.1  christos       /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
   3164          1.1  christos 	 Unused entries should be reclaimed before the section's contents
   3165          1.1  christos 	 are written out, but at the moment this does not happen.  Thus in
   3166  1.1.1.7.4.1  christos 	 order to prevent writing out garbage, we initialise the section's
   3167          1.1  christos 	 contents to zero.  */
   3168          1.1  christos       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
   3169          1.1  christos       if (s->contents == NULL && s->size != 0)
   3170          1.1  christos 	return FALSE;
   3171          1.1  christos     }
   3172          1.1  christos 
   3173          1.1  christos   if (elf_hash_table (info)->dynamic_sections_created)
   3174          1.1  christos     {
   3175          1.1  christos       /* Add some entries to the .dynamic section.  We fill in the
   3176          1.1  christos 	 values later, in microblaze_elf_finish_dynamic_sections, but we
   3177          1.1  christos 	 must add the entries now so that we get the correct size for
   3178          1.1  christos 	 the .dynamic section.  The DT_DEBUG entry is filled in by the
   3179      1.1.1.6  christos 	 dynamic linker and used by the debugger.  */
   3180  1.1.1.7.4.1  christos #define add_dynamic_entry(TAG, VAL)			\
   3181  1.1.1.7.4.1  christos       _bfd_elf_add_dynamic_entry (info, TAG, VAL)
   3182  1.1.1.7.4.1  christos 
   3183  1.1.1.7.4.1  christos       if (bfd_link_executable (info))
   3184          1.1  christos 	{
   3185          1.1  christos 	  if (!add_dynamic_entry (DT_DEBUG, 0))
   3186  1.1.1.7.4.1  christos 	    return FALSE;
   3187  1.1.1.7.4.1  christos 	}
   3188          1.1  christos 
   3189          1.1  christos       if (!add_dynamic_entry (DT_RELA, 0)
   3190      1.1.1.7  christos 	  || !add_dynamic_entry (DT_RELASZ, 0)
   3191  1.1.1.7.4.1  christos 	  || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
   3192  1.1.1.7.4.1  christos 	return FALSE;
   3193  1.1.1.7.4.1  christos 
   3194  1.1.1.7.4.1  christos       if (htab->elf.splt->size != 0)
   3195  1.1.1.7.4.1  christos 	{
   3196  1.1.1.7.4.1  christos 	  if (!add_dynamic_entry (DT_PLTGOT, 0)
   3197  1.1.1.7.4.1  christos 	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
   3198  1.1.1.7.4.1  christos 	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
   3199          1.1  christos 	      || !add_dynamic_entry (DT_JMPREL, 0)
   3200          1.1  christos 	      || !add_dynamic_entry (DT_BIND_NOW, 1))
   3201  1.1.1.7.4.1  christos 	    return FALSE;
   3202  1.1.1.7.4.1  christos 	}
   3203  1.1.1.7.4.1  christos 
   3204  1.1.1.7.4.1  christos       if (info->flags & DF_TEXTREL)
   3205          1.1  christos 	{
   3206          1.1  christos 	  if (!add_dynamic_entry (DT_TEXTREL, 0))
   3207          1.1  christos 	    return FALSE;
   3208          1.1  christos 	}
   3209          1.1  christos     }
   3210          1.1  christos #undef add_dynamic_entry
   3211          1.1  christos   return TRUE;
   3212          1.1  christos }
   3213          1.1  christos 
   3214          1.1  christos /* Finish up dynamic symbol handling.  We set the contents of various
   3215          1.1  christos    dynamic sections here.  */
   3216          1.1  christos 
   3217          1.1  christos static bfd_boolean
   3218          1.1  christos microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
   3219          1.1  christos 				      struct bfd_link_info *info,
   3220      1.1.1.2  christos 				      struct elf_link_hash_entry *h,
   3221          1.1  christos 				      Elf_Internal_Sym *sym)
   3222          1.1  christos {
   3223          1.1  christos   struct elf32_mb_link_hash_table *htab;
   3224          1.1  christos   struct elf32_mb_link_hash_entry *eh = elf32_mb_hash_entry(h);
   3225          1.1  christos 
   3226          1.1  christos   htab = elf32_mb_hash_table (info);
   3227          1.1  christos   if (htab == NULL)
   3228          1.1  christos     return FALSE;
   3229          1.1  christos 
   3230          1.1  christos   if (h->plt.offset != (bfd_vma) -1)
   3231          1.1  christos     {
   3232          1.1  christos       asection *splt;
   3233          1.1  christos       asection *srela;
   3234          1.1  christos       asection *sgotplt;
   3235          1.1  christos       Elf_Internal_Rela rela;
   3236          1.1  christos       bfd_byte *loc;
   3237          1.1  christos       bfd_vma plt_index;
   3238  1.1.1.7.4.1  christos       bfd_vma got_offset;
   3239          1.1  christos       bfd_vma got_addr;
   3240          1.1  christos 
   3241      1.1.1.7  christos       /* This symbol has an entry in the procedure linkage table.  Set
   3242      1.1.1.7  christos 	 it up.  */
   3243      1.1.1.7  christos       BFD_ASSERT (h->dynindx != -1);
   3244          1.1  christos 
   3245          1.1  christos       splt = htab->elf.splt;
   3246          1.1  christos       srela = htab->elf.srelplt;
   3247          1.1  christos       sgotplt = htab->elf.sgotplt;
   3248          1.1  christos       BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
   3249          1.1  christos 
   3250          1.1  christos       plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved.  */
   3251      1.1.1.6  christos       got_offset = (plt_index + 3) * 4; /* 3 reserved ???  */
   3252  1.1.1.7.4.1  christos       got_addr = got_offset;
   3253          1.1  christos 
   3254          1.1  christos       /* For non-PIC objects we need absolute address of the GOT entry.  */
   3255          1.1  christos       if (!bfd_link_pic (info))
   3256  1.1.1.7.4.1  christos 	got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
   3257      1.1.1.6  christos 
   3258  1.1.1.7.4.1  christos       /* Fill in the entry in the procedure linkage table.  */
   3259  1.1.1.7.4.1  christos       bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
   3260          1.1  christos 		  splt->contents + h->plt.offset);
   3261  1.1.1.7.4.1  christos       if (bfd_link_pic (info))
   3262  1.1.1.7.4.1  christos 	bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
   3263          1.1  christos 		    splt->contents + h->plt.offset + 4);
   3264  1.1.1.7.4.1  christos       else
   3265          1.1  christos 	bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
   3266  1.1.1.7.4.1  christos 		    splt->contents + h->plt.offset + 4);
   3267          1.1  christos       bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
   3268          1.1  christos 		  splt->contents + h->plt.offset + 8);
   3269          1.1  christos       bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
   3270          1.1  christos 		  splt->contents + h->plt.offset + 12);
   3271          1.1  christos 
   3272          1.1  christos       /* Any additions to the .got section??? */
   3273          1.1  christos       /*      bfd_put_32 (output_bfd,
   3274          1.1  christos 	      splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
   3275  1.1.1.7.4.1  christos 	      sgotplt->contents + got_offset); */
   3276  1.1.1.7.4.1  christos 
   3277          1.1  christos       /* Fill in the entry in the .rela.plt section.  */
   3278          1.1  christos       rela.r_offset = (sgotplt->output_section->vma
   3279          1.1  christos 		       + sgotplt->output_offset
   3280          1.1  christos 		       + got_offset);
   3281          1.1  christos       rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
   3282          1.1  christos       rela.r_addend = 0;
   3283          1.1  christos       loc = srela->contents;
   3284  1.1.1.7.4.1  christos       loc += plt_index * sizeof (Elf32_External_Rela);
   3285  1.1.1.7.4.1  christos       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
   3286  1.1.1.7.4.1  christos 
   3287  1.1.1.7.4.1  christos       if (!h->def_regular)
   3288  1.1.1.7.4.1  christos 	{
   3289  1.1.1.7.4.1  christos 	  /* Mark the symbol as undefined, rather than as defined in
   3290          1.1  christos 	     the .plt section.  Zero the value.  */
   3291          1.1  christos 	  sym->st_shndx = SHN_UNDEF;
   3292      1.1.1.2  christos 	  sym->st_value = 0;
   3293      1.1.1.2  christos 	}
   3294      1.1.1.2  christos     }
   3295  1.1.1.7.4.1  christos 
   3296          1.1  christos   /* h->got.refcount to be checked ? */
   3297          1.1  christos   if (h->got.offset != (bfd_vma) -1 &&
   3298          1.1  christos       ! ((h->got.offset & 1) ||
   3299      1.1.1.2  christos 	  IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
   3300          1.1  christos     {
   3301          1.1  christos       asection *sgot;
   3302  1.1.1.7.4.1  christos       asection *srela;
   3303          1.1  christos       bfd_vma offset;
   3304      1.1.1.7  christos 
   3305      1.1.1.7  christos       /* This symbol has an entry in the global offset table.  Set it
   3306          1.1  christos 	 up.  */
   3307          1.1  christos 
   3308      1.1.1.2  christos       sgot = htab->elf.sgot;
   3309      1.1.1.6  christos       srela = htab->elf.srelgot;
   3310          1.1  christos       BFD_ASSERT (sgot != NULL && srela != NULL);
   3311          1.1  christos 
   3312  1.1.1.7.4.1  christos       offset = (sgot->output_section->vma + sgot->output_offset
   3313  1.1.1.7.4.1  christos 		+ (h->got.offset &~ (bfd_vma) 1));
   3314  1.1.1.7.4.1  christos 
   3315  1.1.1.7.4.1  christos       /* If this is a -Bsymbolic link, and the symbol is defined
   3316      1.1.1.6  christos 	 locally, we just want to emit a RELATIVE reloc.  Likewise if
   3317  1.1.1.7.4.1  christos 	 the symbol was forced to be local because of a version file.
   3318      1.1.1.6  christos 	 The entry in the global offset table will already have been
   3319  1.1.1.7.4.1  christos 	 initialized in the relocate_section function.  */
   3320  1.1.1.7.4.1  christos       if (bfd_link_pic (info)
   3321      1.1.1.7  christos 	  && ((info->symbolic && h->def_regular)
   3322      1.1.1.7  christos 	      || h->dynindx == -1))
   3323      1.1.1.7  christos 	{
   3324      1.1.1.7  christos 	  asection *sec = h->root.u.def.section;
   3325      1.1.1.7  christos 	  bfd_vma value;
   3326      1.1.1.7  christos 
   3327      1.1.1.7  christos 	  value = h->root.u.def.value;
   3328      1.1.1.7  christos 	  if (sec->output_section != NULL)
   3329      1.1.1.7  christos 	    /* PR 21180: If the output section is NULL, then the symbol is no
   3330  1.1.1.7.4.1  christos 	       longer needed, and in theory the GOT entry is redundant.  But
   3331  1.1.1.7.4.1  christos 	       it is too late to change our minds now...  */
   3332  1.1.1.7.4.1  christos 	    value += sec->output_section->vma + sec->output_offset;
   3333  1.1.1.7.4.1  christos 
   3334  1.1.1.7.4.1  christos 	  microblaze_elf_output_dynamic_relocation (output_bfd,
   3335  1.1.1.7.4.1  christos 						    srela, srela->reloc_count++,
   3336          1.1  christos 						    /* symindex= */ 0,
   3337  1.1.1.7.4.1  christos 						    R_MICROBLAZE_REL, offset,
   3338  1.1.1.7.4.1  christos 						    value);
   3339  1.1.1.7.4.1  christos 	}
   3340  1.1.1.7.4.1  christos       else
   3341  1.1.1.7.4.1  christos 	{
   3342  1.1.1.7.4.1  christos 	  microblaze_elf_output_dynamic_relocation (output_bfd,
   3343  1.1.1.7.4.1  christos 						    srela, srela->reloc_count++,
   3344          1.1  christos 						    h->dynindx,
   3345          1.1  christos 						    R_MICROBLAZE_GLOB_DAT,
   3346  1.1.1.7.4.1  christos 						    offset, 0);
   3347          1.1  christos 	}
   3348          1.1  christos 
   3349          1.1  christos       bfd_put_32 (output_bfd, (bfd_vma) 0,
   3350          1.1  christos 		  sgot->contents + (h->got.offset &~ (bfd_vma) 1));
   3351          1.1  christos     }
   3352          1.1  christos 
   3353          1.1  christos   if (h->needs_copy)
   3354          1.1  christos     {
   3355          1.1  christos       asection *s;
   3356          1.1  christos       Elf_Internal_Rela rela;
   3357          1.1  christos       bfd_byte *loc;
   3358          1.1  christos 
   3359          1.1  christos       /* This symbols needs a copy reloc.  Set it up.  */
   3360  1.1.1.7.4.1  christos 
   3361  1.1.1.7.4.1  christos       BFD_ASSERT (h->dynindx != -1);
   3362          1.1  christos 
   3363          1.1  christos       rela.r_offset = (h->root.u.def.value
   3364      1.1.1.7  christos 		       + h->root.u.def.section->output_section->vma
   3365      1.1.1.7  christos 		       + h->root.u.def.section->output_offset);
   3366      1.1.1.7  christos       rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
   3367      1.1.1.7  christos       rela.r_addend = 0;
   3368          1.1  christos       if (h->root.u.def.section == htab->elf.sdynrelro)
   3369          1.1  christos 	s = htab->elf.sreldynrelro;
   3370          1.1  christos       else
   3371          1.1  christos 	s = htab->elf.srelbss;
   3372          1.1  christos       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
   3373      1.1.1.2  christos       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
   3374      1.1.1.2  christos     }
   3375      1.1.1.2  christos 
   3376          1.1  christos   /* Mark some specially defined symbols as absolute.  */
   3377          1.1  christos   if (h == htab->elf.hdynamic
   3378          1.1  christos       || h == htab->elf.hgot
   3379          1.1  christos       || h == htab->elf.hplt)
   3380          1.1  christos     sym->st_shndx = SHN_ABS;
   3381          1.1  christos 
   3382          1.1  christos   return TRUE;
   3383          1.1  christos }
   3384          1.1  christos 
   3385          1.1  christos 
   3386          1.1  christos /* Finish up the dynamic sections.  */
   3387          1.1  christos 
   3388          1.1  christos static bfd_boolean
   3389          1.1  christos microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
   3390          1.1  christos 					struct bfd_link_info *info)
   3391          1.1  christos {
   3392          1.1  christos   bfd *dynobj;
   3393          1.1  christos   asection *sdyn, *sgot;
   3394          1.1  christos   struct elf32_mb_link_hash_table *htab;
   3395          1.1  christos 
   3396          1.1  christos   htab = elf32_mb_hash_table (info);
   3397          1.1  christos   if (htab == NULL)
   3398      1.1.1.2  christos     return FALSE;
   3399          1.1  christos 
   3400          1.1  christos   dynobj = htab->elf.dynobj;
   3401          1.1  christos 
   3402          1.1  christos   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
   3403          1.1  christos 
   3404          1.1  christos   if (htab->elf.dynamic_sections_created)
   3405          1.1  christos     {
   3406          1.1  christos       asection *splt;
   3407          1.1  christos       Elf32_External_Dyn *dyncon, *dynconend;
   3408  1.1.1.7.4.1  christos 
   3409  1.1.1.7.4.1  christos       dyncon = (Elf32_External_Dyn *) sdyn->contents;
   3410      1.1.1.7  christos       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
   3411  1.1.1.7.4.1  christos       for (; dyncon < dynconend; dyncon++)
   3412          1.1  christos 	{
   3413  1.1.1.7.4.1  christos 	  Elf_Internal_Dyn dyn;
   3414          1.1  christos 	  asection *s;
   3415  1.1.1.7.4.1  christos 	  bfd_boolean size;
   3416  1.1.1.7.4.1  christos 
   3417      1.1.1.7  christos 	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
   3418      1.1.1.7  christos 
   3419      1.1.1.7  christos 	  switch (dyn.d_tag)
   3420      1.1.1.7  christos 	    {
   3421          1.1  christos 	    case DT_PLTGOT:
   3422      1.1.1.7  christos 	      s = htab->elf.sgotplt;
   3423      1.1.1.7  christos 	      size = FALSE;
   3424      1.1.1.7  christos 	      break;
   3425      1.1.1.7  christos 
   3426          1.1  christos 	    case DT_PLTRELSZ:
   3427      1.1.1.7  christos 	      s = htab->elf.srelplt;
   3428      1.1.1.7  christos 	      size = TRUE;
   3429      1.1.1.7  christos 	      break;
   3430      1.1.1.7  christos 
   3431      1.1.1.7  christos 	    case DT_JMPREL:
   3432      1.1.1.7  christos 	      s = htab->elf.srelplt;
   3433      1.1.1.7  christos 	      size = FALSE;
   3434  1.1.1.7.4.1  christos 	      break;
   3435      1.1.1.7  christos 
   3436      1.1.1.7  christos 	    default:
   3437      1.1.1.7  christos 	      continue;
   3438      1.1.1.7  christos 	    }
   3439      1.1.1.7  christos 
   3440      1.1.1.7  christos 	  if (s == NULL)
   3441      1.1.1.7  christos 	    dyn.d_un.d_val = 0;
   3442      1.1.1.7  christos 	  else
   3443      1.1.1.7  christos 	    {
   3444      1.1.1.7  christos 	      if (!size)
   3445      1.1.1.7  christos 		dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
   3446  1.1.1.7.4.1  christos 	      else
   3447          1.1  christos 		dyn.d_un.d_val = s->size;
   3448      1.1.1.7  christos 	    }
   3449      1.1.1.7  christos 	  bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
   3450      1.1.1.7  christos 	}
   3451          1.1  christos 
   3452          1.1  christos       splt = htab->elf.splt;
   3453          1.1  christos       BFD_ASSERT (splt != NULL && sdyn != NULL);
   3454  1.1.1.7.4.1  christos 
   3455  1.1.1.7.4.1  christos       /* Clear the first entry in the procedure linkage table,
   3456  1.1.1.7.4.1  christos 	 and put a nop in the last four bytes.  */
   3457  1.1.1.7.4.1  christos       if (splt->size > 0)
   3458  1.1.1.7.4.1  christos 	{
   3459          1.1  christos 	  memset (splt->contents, 0, PLT_ENTRY_SIZE);
   3460          1.1  christos 	  bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop.  */,
   3461          1.1  christos 		      splt->contents + splt->size - 4);
   3462          1.1  christos 	}
   3463          1.1  christos 
   3464          1.1  christos       elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
   3465      1.1.1.7  christos     }
   3466          1.1  christos 
   3467          1.1  christos   /* Set the first entry in the global offset table to the address of
   3468          1.1  christos      the dynamic section.  */
   3469  1.1.1.7.4.1  christos   sgot = htab->elf.sgotplt;
   3470          1.1  christos   if (sgot && sgot->size > 0)
   3471  1.1.1.7.4.1  christos     {
   3472  1.1.1.7.4.1  christos       if (sdyn == NULL)
   3473  1.1.1.7.4.1  christos 	bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
   3474          1.1  christos       else
   3475          1.1  christos 	bfd_put_32 (output_bfd,
   3476          1.1  christos 		    sdyn->output_section->vma + sdyn->output_offset,
   3477      1.1.1.7  christos 		    sgot->contents);
   3478      1.1.1.7  christos       elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
   3479          1.1  christos     }
   3480          1.1  christos 
   3481          1.1  christos   if (htab->elf.sgot && htab->elf.sgot->size > 0)
   3482          1.1  christos     elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
   3483          1.1  christos 
   3484          1.1  christos   return TRUE;
   3485          1.1  christos }
   3486          1.1  christos 
   3487          1.1  christos /* Hook called by the linker routine which adds symbols from an object
   3488  1.1.1.7.4.1  christos    file.  We use it to put .comm items in .sbss, and not .bss.  */
   3489  1.1.1.7.4.1  christos 
   3490  1.1.1.7.4.1  christos static bfd_boolean
   3491  1.1.1.7.4.1  christos microblaze_elf_add_symbol_hook (bfd *abfd,
   3492  1.1.1.7.4.1  christos 				struct bfd_link_info *info,
   3493  1.1.1.7.4.1  christos 				Elf_Internal_Sym *sym,
   3494          1.1  christos 				const char **namep ATTRIBUTE_UNUSED,
   3495          1.1  christos 				flagword *flagsp ATTRIBUTE_UNUSED,
   3496      1.1.1.6  christos 				asection **secp,
   3497          1.1  christos 				bfd_vma *valp)
   3498          1.1  christos {
   3499          1.1  christos   if (sym->st_shndx == SHN_COMMON
   3500          1.1  christos       && !bfd_link_relocatable (info)
   3501      1.1.1.2  christos       && sym->st_size <= elf_gp_size (abfd))
   3502          1.1  christos     {
   3503  1.1.1.7.4.1  christos       /* Common symbols less than or equal to -G nn bytes are automatically
   3504  1.1.1.7.4.1  christos 	 put into .sbss.  */
   3505          1.1  christos       *secp = bfd_make_section_old_way (abfd, ".sbss");
   3506          1.1  christos       if (*secp == NULL
   3507          1.1  christos 	  || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
   3508          1.1  christos 	return FALSE;
   3509          1.1  christos 
   3510          1.1  christos       *valp = sym->st_size;
   3511          1.1  christos     }
   3512      1.1.1.4  christos 
   3513      1.1.1.2  christos   return TRUE;
   3514          1.1  christos }
   3515  1.1.1.7.4.1  christos 
   3516          1.1  christos #define TARGET_LITTLE_SYM      microblaze_elf32_le_vec
   3517          1.1  christos #define TARGET_LITTLE_NAME     "elf32-microblazeel"
   3518          1.1  christos 
   3519          1.1  christos #define TARGET_BIG_SYM		microblaze_elf32_vec
   3520          1.1  christos #define TARGET_BIG_NAME		"elf32-microblaze"
   3521          1.1  christos 
   3522      1.1.1.2  christos #define ELF_ARCH		bfd_arch_microblaze
   3523          1.1  christos #define ELF_TARGET_ID		MICROBLAZE_ELF_DATA
   3524          1.1  christos #define ELF_MACHINE_CODE	EM_MICROBLAZE
   3525          1.1  christos #define ELF_MACHINE_ALT1	EM_MICROBLAZE_OLD
   3526          1.1  christos #define ELF_MAXPAGESIZE		0x1000
   3527  1.1.1.7.4.1  christos #define elf_info_to_howto	microblaze_elf_info_to_howto
   3528          1.1  christos #define elf_info_to_howto_rel	NULL
   3529  1.1.1.7.4.1  christos 
   3530  1.1.1.7.4.1  christos #define bfd_elf32_bfd_reloc_type_lookup		microblaze_elf_reloc_type_lookup
   3531          1.1  christos #define bfd_elf32_bfd_is_local_label_name	microblaze_elf_is_local_label_name
   3532          1.1  christos #define elf_backend_relocate_section		microblaze_elf_relocate_section
   3533          1.1  christos #define bfd_elf32_bfd_relax_section		microblaze_elf_relax_section
   3534  1.1.1.7.4.1  christos #define bfd_elf32_bfd_merge_private_bfd_data	_bfd_generic_verify_endian_match
   3535  1.1.1.7.4.1  christos #define bfd_elf32_bfd_reloc_name_lookup		microblaze_elf_reloc_name_lookup
   3536  1.1.1.7.4.1  christos 
   3537          1.1  christos #define elf_backend_gc_mark_hook		microblaze_elf_gc_mark_hook
   3538  1.1.1.7.4.1  christos #define elf_backend_check_relocs		microblaze_elf_check_relocs
   3539  1.1.1.7.4.1  christos #define elf_backend_copy_indirect_symbol	microblaze_elf_copy_indirect_symbol
   3540  1.1.1.7.4.1  christos #define bfd_elf32_bfd_link_hash_table_create	microblaze_elf_link_hash_table_create
   3541  1.1.1.7.4.1  christos #define elf_backend_can_gc_sections		1
   3542      1.1.1.7  christos #define elf_backend_can_refcount		1
   3543  1.1.1.7.4.1  christos #define elf_backend_want_got_plt		1
   3544      1.1.1.7  christos #define elf_backend_plt_readonly		1
   3545          1.1  christos #define elf_backend_got_header_size		12
   3546  1.1.1.7.4.1  christos #define elf_backend_want_dynrelro		1
   3547  1.1.1.7.4.1  christos #define elf_backend_rela_normal			1
   3548  1.1.1.7.4.1  christos #define elf_backend_dtrel_excludes_plt		1
   3549  1.1.1.7.4.1  christos 
   3550  1.1.1.7.4.1  christos #define elf_backend_adjust_dynamic_symbol	microblaze_elf_adjust_dynamic_symbol
   3551          1.1  christos #define elf_backend_create_dynamic_sections	_bfd_elf_create_dynamic_sections
   3552          1.1  christos #define elf_backend_finish_dynamic_sections	microblaze_elf_finish_dynamic_sections
   3553          1.1  christos #define elf_backend_finish_dynamic_symbol	microblaze_elf_finish_dynamic_symbol
   3554                        #define elf_backend_size_dynamic_sections	microblaze_elf_size_dynamic_sections
   3555                        #define elf_backend_add_symbol_hook		microblaze_elf_add_symbol_hook
   3556                        
   3557                        #include "elf32-target.h"
   3558