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