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