Home | History | Annotate | Line # | Download | only in bfd
elf32-microblaze.c revision 1.1.1.12
      1 /* Xilinx MicroBlaze-specific support for 32-bit ELF
      2 
      3    Copyright (C) 2009-2024 Free Software Foundation, Inc.
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the
     19    Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
     20    Boston, MA 02110-1301, USA.  */
     21 
     22 
     23 #include "sysdep.h"
     24 #include "bfd.h"
     25 #include "bfdlink.h"
     26 #include "libbfd.h"
     27 #include "elf-bfd.h"
     28 #include "elf/microblaze.h"
     29 #include <assert.h>
     30 
     31 #define	USE_RELA	/* Only USE_REL is actually significant, but this is
     32 			   here are a reminder...  */
     33 #define INST_WORD_SIZE 4
     34 
     35 static int ro_small_data_pointer = 0;
     36 static int rw_small_data_pointer = 0;
     37 
     38 static reloc_howto_type * microblaze_elf_howto_table [(int) R_MICROBLAZE_max];
     39 
     40 static reloc_howto_type microblaze_elf_howto_raw[] =
     41 {
     42    /* This reloc does nothing.  */
     43    HOWTO (R_MICROBLAZE_NONE,	/* Type.  */
     44 	  0,			/* Rightshift.  */
     45 	  0,			/* Size.  */
     46 	  0,			/* Bitsize.  */
     47 	  false,		/* PC_relative.  */
     48 	  0,			/* Bitpos.  */
     49 	  complain_overflow_dont,  /* Complain on overflow.  */
     50 	  NULL,			 /* Special Function.  */
     51 	  "R_MICROBLAZE_NONE",	/* Name.  */
     52 	  false,		/* Partial Inplace.  */
     53 	  0,			/* Source Mask.  */
     54 	  0,			/* Dest Mask.  */
     55 	  false),		/* PC relative offset?  */
     56 
     57    /* A standard 32 bit relocation.  */
     58    HOWTO (R_MICROBLAZE_32,	/* Type.  */
     59 	  0,			/* Rightshift.  */
     60 	  4,			/* Size.  */
     61 	  32,			/* Bitsize.  */
     62 	  false,		/* PC_relative.  */
     63 	  0,			/* Bitpos.  */
     64 	  complain_overflow_bitfield, /* Complain on overflow.  */
     65 	  bfd_elf_generic_reloc,/* Special Function.  */
     66 	  "R_MICROBLAZE_32",	/* Name.  */
     67 	  false,		/* Partial Inplace.  */
     68 	  0,			/* Source Mask.  */
     69 	  0xffffffff,		/* Dest Mask.  */
     70 	  false),		/* PC relative offset?  */
     71 
     72    /* A standard PCREL 32 bit relocation.  */
     73    HOWTO (R_MICROBLAZE_32_PCREL,/* Type.  */
     74 	  0,			/* Rightshift.  */
     75 	  4,			/* Size.  */
     76 	  32,			/* Bitsize.  */
     77 	  true,			/* PC_relative.  */
     78 	  0,			/* Bitpos.  */
     79 	  complain_overflow_bitfield, /* Complain on overflow.  */
     80 	  bfd_elf_generic_reloc,/* Special Function.  */
     81 	  "R_MICROBLAZE_32_PCREL",	/* Name.  */
     82 	  true,			/* Partial Inplace.  */
     83 	  0,			/* Source Mask.  */
     84 	  0xffffffff,		/* Dest Mask.  */
     85 	  true),		/* PC relative offset?  */
     86 
     87    /* A 64 bit PCREL relocation.  Table-entry not really used.  */
     88    HOWTO (R_MICROBLAZE_64_PCREL,/* Type.  */
     89 	  0,			/* Rightshift.  */
     90 	  4,			/* Size.  */
     91 	  16,			/* Bitsize.  */
     92 	  true,			/* PC_relative.  */
     93 	  0,			/* Bitpos.  */
     94 	  complain_overflow_dont, /* Complain on overflow.  */
     95 	  bfd_elf_generic_reloc,/* Special Function.  */
     96 	  "R_MICROBLAZE_64_PCREL",	/* Name.  */
     97 	  false,		/* Partial Inplace.  */
     98 	  0,			/* Source Mask.  */
     99 	  0x0000ffff,		/* Dest Mask.  */
    100 	  true),		/* PC relative offset?  */
    101 
    102    /* The low half of a PCREL 32 bit relocation.  */
    103    HOWTO (R_MICROBLAZE_32_PCREL_LO,	/* Type.  */
    104 	  0,			/* Rightshift.  */
    105 	  4,			/* Size.  */
    106 	  16,			/* Bitsize.  */
    107 	  true,			/* PC_relative.  */
    108 	  0,			/* Bitpos.  */
    109 	  complain_overflow_signed, /* Complain on overflow.  */
    110 	  bfd_elf_generic_reloc,	/* Special Function.  */
    111 	  "R_MICROBLAZE_32_PCREL_LO",	/* Name.  */
    112 	  false,		/* Partial Inplace.  */
    113 	  0,			/* Source Mask.  */
    114 	  0x0000ffff,		/* Dest Mask.  */
    115 	  true),		/* PC relative offset?  */
    116 
    117    /* A 64 bit relocation.  Table entry not really used.  */
    118    HOWTO (R_MICROBLAZE_64,	/* Type.  */
    119 	  0,			/* Rightshift.  */
    120 	  4,			/* Size.  */
    121 	  16,			/* Bitsize.  */
    122 	  false,		/* PC_relative.  */
    123 	  0,			/* Bitpos.  */
    124 	  complain_overflow_dont, /* Complain on overflow.  */
    125 	  bfd_elf_generic_reloc,/* Special Function.  */
    126 	  "R_MICROBLAZE_64",	/* Name.  */
    127 	  false,		/* Partial Inplace.  */
    128 	  0,			/* Source Mask.  */
    129 	  0x0000ffff,		/* Dest Mask.  */
    130 	  false),		/* PC relative offset?  */
    131 
    132    /* The low half of a 32 bit relocation.  */
    133    HOWTO (R_MICROBLAZE_32_LO,	/* Type.  */
    134 	  0,			/* Rightshift.  */
    135 	  4,			/* Size.  */
    136 	  16,			/* Bitsize.  */
    137 	  false,		/* PC_relative.  */
    138 	  0,			/* Bitpos.  */
    139 	  complain_overflow_signed, /* Complain on overflow.  */
    140 	  bfd_elf_generic_reloc,/* Special Function.  */
    141 	  "R_MICROBLAZE_32_LO", /* Name.  */
    142 	  false,		/* Partial Inplace.  */
    143 	  0,			/* Source Mask.  */
    144 	  0x0000ffff,		/* Dest Mask.  */
    145 	  false),		/* PC relative offset?  */
    146 
    147    /* Read-only small data section relocation.  */
    148    HOWTO (R_MICROBLAZE_SRO32,	/* Type.  */
    149 	  0,			/* Rightshift.  */
    150 	  4,			/* Size.  */
    151 	  16,			/* Bitsize.  */
    152 	  false,		/* PC_relative.  */
    153 	  0,			/* Bitpos.  */
    154 	  complain_overflow_bitfield, /* Complain on overflow.  */
    155 	  bfd_elf_generic_reloc,/* Special Function.  */
    156 	  "R_MICROBLAZE_SRO32", /* Name.  */
    157 	  false,		/* Partial Inplace.  */
    158 	  0,			/* Source Mask.  */
    159 	  0x0000ffff,		/* Dest Mask.  */
    160 	  false),		/* PC relative offset?  */
    161 
    162    /* Read-write small data area relocation.  */
    163    HOWTO (R_MICROBLAZE_SRW32,	/* Type.  */
    164 	  0,			/* Rightshift.  */
    165 	  4,			/* Size.  */
    166 	  16,			/* Bitsize.  */
    167 	  false,		/* PC_relative.  */
    168 	  0,			/* Bitpos.  */
    169 	  complain_overflow_bitfield, /* Complain on overflow.  */
    170 	  bfd_elf_generic_reloc,/* Special Function.  */
    171 	  "R_MICROBLAZE_SRW32", /* Name.  */
    172 	  false,		/* Partial Inplace.  */
    173 	  0,			/* Source Mask.  */
    174 	  0x0000ffff,		/* Dest Mask.  */
    175 	  false),		/* PC relative offset?  */
    176 
    177    /* This reloc does nothing.	Used for relaxation.  */
    178    HOWTO (R_MICROBLAZE_32_NONE,	/* Type.  */
    179 	0,			/* Rightshift.  */
    180 	2,			/* Size (0 = byte, 1 = short, 2 = long).  */
    181 	32,			/* Bitsize.  */
    182 	true,			/* PC_relative.  */
    183 	0,			/* Bitpos.  */
    184 	complain_overflow_bitfield, /* Complain on overflow.  */
    185 	NULL,			/* Special Function.  */
    186 	"R_MICROBLAZE_32_NONE", /* Name.  */
    187 	false,			/* Partial Inplace.  */
    188 	0,			/* Source Mask.  */
    189 	0,			/* Dest Mask.  */
    190 	false),		/* PC relative offset?  */
    191 
    192    /* This reloc does nothing.	Used for relaxation.  */
    193    HOWTO (R_MICROBLAZE_64_NONE,	/* Type.  */
    194 	  0,			/* Rightshift.  */
    195 	  0,			/* Size.  */
    196 	  0,			/* Bitsize.  */
    197 	  true,			/* PC_relative.  */
    198 	  0,			/* Bitpos.  */
    199 	  complain_overflow_dont, /* Complain on overflow.  */
    200 	  NULL,			 /* Special Function.  */
    201 	  "R_MICROBLAZE_64_NONE",/* Name.  */
    202 	  false,		/* Partial Inplace.  */
    203 	  0,			/* Source Mask.  */
    204 	  0,			/* Dest Mask.  */
    205 	  false),		/* PC relative offset?  */
    206 
    207    /* Symbol Op Symbol relocation.  */
    208    HOWTO (R_MICROBLAZE_32_SYM_OP_SYM,		/* Type.  */
    209 	  0,			/* Rightshift.  */
    210 	  4,			/* Size.  */
    211 	  32,			/* Bitsize.  */
    212 	  false,		/* PC_relative.  */
    213 	  0,			/* Bitpos.  */
    214 	  complain_overflow_bitfield, /* Complain on overflow.  */
    215 	  bfd_elf_generic_reloc,/* Special Function.  */
    216 	  "R_MICROBLAZE_32_SYM_OP_SYM",		/* Name.  */
    217 	  false,		/* Partial Inplace.  */
    218 	  0,			/* Source Mask.  */
    219 	  0xffffffff,		/* Dest Mask.  */
    220 	  false),		/* PC relative offset?  */
    221 
    222    /* GNU extension to record C++ vtable hierarchy.  */
    223    HOWTO (R_MICROBLAZE_GNU_VTINHERIT, /* Type.  */
    224 	  0,			 /* Rightshift.  */
    225 	  4,			 /* Size.  */
    226 	  0,			 /* Bitsize.  */
    227 	  false,		 /* PC_relative.  */
    228 	  0,			 /* Bitpos.  */
    229 	  complain_overflow_dont,/* Complain on overflow.  */
    230 	  NULL,			 /* Special Function.  */
    231 	  "R_MICROBLAZE_GNU_VTINHERIT", /* Name.  */
    232 	  false,		 /* Partial Inplace.  */
    233 	  0,			 /* Source Mask.  */
    234 	  0,			 /* Dest Mask.  */
    235 	  false),		 /* PC relative offset?  */
    236 
    237    /* GNU extension to record C++ vtable member usage.  */
    238    HOWTO (R_MICROBLAZE_GNU_VTENTRY,   /* Type.  */
    239 	  0,			 /* Rightshift.  */
    240 	  4,			 /* Size.  */
    241 	  0,			 /* Bitsize.  */
    242 	  false,		 /* PC_relative.  */
    243 	  0,			 /* Bitpos.  */
    244 	  complain_overflow_dont,/* Complain on overflow.  */
    245 	  _bfd_elf_rel_vtable_reloc_fn,	 /* Special Function.  */
    246 	  "R_MICROBLAZE_GNU_VTENTRY", /* Name.  */
    247 	  false,		 /* Partial Inplace.  */
    248 	  0,			 /* Source Mask.  */
    249 	  0,			 /* Dest Mask.  */
    250 	  false),		 /* PC relative offset?  */
    251 
    252    /* A 64 bit GOTPC relocation.  Table-entry not really used.  */
    253    HOWTO (R_MICROBLAZE_GOTPC_64,	/* Type.  */
    254 	  0,			/* Rightshift.  */
    255 	  4,			/* Size.  */
    256 	  16,			/* Bitsize.  */
    257 	  true,			/* PC_relative.  */
    258 	  0,			/* Bitpos.  */
    259 	  complain_overflow_dont, /* Complain on overflow.  */
    260 	  bfd_elf_generic_reloc,	/* Special Function.  */
    261 	  "R_MICROBLAZE_GOTPC_64",	/* Name.  */
    262 	  false,		/* Partial Inplace.  */
    263 	  0,			/* Source Mask.  */
    264 	  0x0000ffff,		/* Dest Mask.  */
    265 	  true),		/* PC relative offset?  */
    266 
    267      /* A 64 bit TEXTPCREL relocation.  Table-entry not really used.  */
    268    HOWTO (R_MICROBLAZE_TEXTPCREL_64,	/* Type.  */
    269 	  0,			/* Rightshift.  */
    270 	  4,			/* Size.  */
    271 	  16,			/* Bitsize.  */
    272 	  true,			/* PC_relative.  */
    273 	  0,			/* Bitpos.  */
    274 	  complain_overflow_dont, /* Complain on overflow.  */
    275 	  bfd_elf_generic_reloc,	/* Special Function.  */
    276 	  "R_MICROBLAZE_TEXTPCREL_64",	/* Name.  */
    277 	  false,		/* Partial Inplace.  */
    278 	  0,			/* Source Mask.  */
    279 	  0x0000ffff,		/* Dest Mask.  */
    280 	  true),		/* PC relative offset?  */
    281 
    282    /* A 64 bit GOT relocation.  Table-entry not really used.  */
    283    HOWTO (R_MICROBLAZE_GOT_64,  /* Type.  */
    284 	  0,			/* Rightshift.  */
    285 	  4,			/* Size.  */
    286 	  16,			/* Bitsize.  */
    287 	  false,		/* PC_relative.  */
    288 	  0,			/* Bitpos.  */
    289 	  complain_overflow_dont, /* Complain on overflow.  */
    290 	  bfd_elf_generic_reloc,/* Special Function.  */
    291 	  "R_MICROBLAZE_GOT_64",/* Name.  */
    292 	  false,		/* Partial Inplace.  */
    293 	  0,			/* Source Mask.  */
    294 	  0x0000ffff,		/* Dest Mask.  */
    295 	  false),		/* PC relative offset?  */
    296 
    297     /* A 64 bit TEXTREL relocation.  Table-entry not really used.  */
    298    HOWTO (R_MICROBLAZE_TEXTREL_64,  /* Type.  */
    299 	  0,			/* Rightshift.  */
    300 	  4,			/* Size.  */
    301 	  16,			/* Bitsize.  */
    302 	  false,		/* PC_relative.  */
    303 	  0,			/* Bitpos.  */
    304 	  complain_overflow_dont, /* Complain on overflow.  */
    305 	  bfd_elf_generic_reloc,/* Special Function.  */
    306 	  "R_MICROBLAZE_TEXTREL_64",/* Name.  */
    307 	  false,		/* Partial Inplace.  */
    308 	  0,			/* Source Mask.  */
    309 	  0x0000ffff,		/* Dest Mask.  */
    310 	  false),		/* PC relative offset?  */
    311 
    312    /* A 64 bit PLT relocation.  Table-entry not really used.  */
    313    HOWTO (R_MICROBLAZE_PLT_64,  /* Type.  */
    314 	  0,			/* Rightshift.  */
    315 	  4,			/* Size.  */
    316 	  16,			/* Bitsize.  */
    317 	  true,			/* PC_relative.  */
    318 	  0,			/* Bitpos.  */
    319 	  complain_overflow_dont, /* Complain on overflow.  */
    320 	  bfd_elf_generic_reloc,/* Special Function.  */
    321 	  "R_MICROBLAZE_PLT_64",/* Name.  */
    322 	  false,		/* Partial Inplace.  */
    323 	  0,			/* Source Mask.  */
    324 	  0x0000ffff,		/* Dest Mask.  */
    325 	  true),		/* PC relative offset?  */
    326 
    327    /*  Table-entry not really used.  */
    328    HOWTO (R_MICROBLAZE_REL,	/* Type.  */
    329 	  0,			/* Rightshift.  */
    330 	  4,			/* Size.  */
    331 	  16,			/* Bitsize.  */
    332 	  true,			/* PC_relative.  */
    333 	  0,			/* Bitpos.  */
    334 	  complain_overflow_dont, /* Complain on overflow.  */
    335 	  bfd_elf_generic_reloc,/* Special Function.  */
    336 	  "R_MICROBLAZE_REL",	/* Name.  */
    337 	  false,		/* Partial Inplace.  */
    338 	  0,			/* Source Mask.  */
    339 	  0x0000ffff,		/* Dest Mask.  */
    340 	  true),		/* PC relative offset?  */
    341 
    342    /*  Table-entry not really used.  */
    343    HOWTO (R_MICROBLAZE_JUMP_SLOT,/* Type.  */
    344 	  0,			/* Rightshift.  */
    345 	  4,			/* Size.  */
    346 	  16,			/* Bitsize.  */
    347 	  true,			/* PC_relative.  */
    348 	  0,			/* Bitpos.  */
    349 	  complain_overflow_dont, /* Complain on overflow.  */
    350 	  bfd_elf_generic_reloc,/* Special Function.  */
    351 	  "R_MICROBLAZE_JUMP_SLOT",	/* Name.  */
    352 	  false,		/* Partial Inplace.  */
    353 	  0,			/* Source Mask.  */
    354 	  0x0000ffff,		/* Dest Mask.  */
    355 	  true),		/* PC relative offset?  */
    356 
    357    /*  Table-entry not really used.  */
    358    HOWTO (R_MICROBLAZE_GLOB_DAT,/* Type.  */
    359 	  0,			/* Rightshift.  */
    360 	  4,			/* Size.  */
    361 	  16,			/* Bitsize.  */
    362 	  true,			/* PC_relative.  */
    363 	  0,			/* Bitpos.  */
    364 	  complain_overflow_dont, /* Complain on overflow.  */
    365 	  bfd_elf_generic_reloc,/* Special Function.  */
    366 	  "R_MICROBLAZE_GLOB_DAT",	/* Name.  */
    367 	  false,		/* Partial Inplace.  */
    368 	  0,			/* Source Mask.  */
    369 	  0x0000ffff,		/* Dest Mask.  */
    370 	  true),		/* PC relative offset?  */
    371 
    372    /* A 64 bit GOT relative relocation.  Table-entry not really used.  */
    373    HOWTO (R_MICROBLAZE_GOTOFF_64,	/* Type.  */
    374 	  0,			/* Rightshift.  */
    375 	  4,			/* Size.  */
    376 	  16,			/* Bitsize.  */
    377 	  false,		/* PC_relative.  */
    378 	  0,			/* Bitpos.  */
    379 	  complain_overflow_dont, /* Complain on overflow.  */
    380 	  bfd_elf_generic_reloc,/* Special Function.  */
    381 	  "R_MICROBLAZE_GOTOFF_64",	/* Name.  */
    382 	  false,		/* Partial Inplace.  */
    383 	  0,			/* Source Mask.  */
    384 	  0x0000ffff,		/* Dest Mask.  */
    385 	  false),		/* PC relative offset?  */
    386 
    387    /* A 32 bit GOT relative relocation.  Table-entry not really used.  */
    388    HOWTO (R_MICROBLAZE_GOTOFF_32,	/* Type.  */
    389 	  0,			/* Rightshift.  */
    390 	  4,			/* Size.  */
    391 	  16,			/* Bitsize.  */
    392 	  false,		/* PC_relative.  */
    393 	  0,			/* Bitpos.  */
    394 	  complain_overflow_dont, /* Complain on overflow.  */
    395 	  bfd_elf_generic_reloc,	/* Special Function.  */
    396 	  "R_MICROBLAZE_GOTOFF_32",	/* Name.  */
    397 	  false,		/* Partial Inplace.  */
    398 	  0,			/* Source Mask.  */
    399 	  0x0000ffff,		/* Dest Mask.  */
    400 	  false),		/* PC relative offset?  */
    401 
    402    /* COPY relocation.  Table-entry not really used.  */
    403    HOWTO (R_MICROBLAZE_COPY,	/* Type.  */
    404 	  0,			/* Rightshift.  */
    405 	  4,			/* Size.  */
    406 	  16,			/* Bitsize.  */
    407 	  false,		/* PC_relative.  */
    408 	  0,			/* Bitpos.  */
    409 	  complain_overflow_dont, /* Complain on overflow.  */
    410 	  bfd_elf_generic_reloc,/* Special Function.  */
    411 	  "R_MICROBLAZE_COPY",	/* Name.  */
    412 	  false,		/* Partial Inplace.  */
    413 	  0,			/* Source Mask.  */
    414 	  0x0000ffff,		/* Dest Mask.  */
    415 	  false),		/* PC relative offset?  */
    416 
    417    /* Marker relocs for TLS.  */
    418    HOWTO (R_MICROBLAZE_TLS,
    419 	 0,			/* rightshift */
    420 	 4,			/* size */
    421 	 32,			/* bitsize */
    422 	 false,			/* pc_relative */
    423 	 0,			/* bitpos */
    424 	 complain_overflow_dont, /* complain_on_overflow */
    425 	 bfd_elf_generic_reloc,	/* special_function */
    426 	 "R_MICROBLAZE_TLS",		/* name */
    427 	 false,			/* partial_inplace */
    428 	 0,			/* src_mask */
    429 	 0x0000ffff,			/* dst_mask */
    430 	 false),		/* pcrel_offset */
    431 
    432    HOWTO (R_MICROBLAZE_TLSGD,
    433 	 0,			/* rightshift */
    434 	 4,			/* size */
    435 	 32,			/* bitsize */
    436 	 false,			/* pc_relative */
    437 	 0,			/* bitpos */
    438 	 complain_overflow_dont, /* complain_on_overflow */
    439 	 bfd_elf_generic_reloc, /* special_function */
    440 	 "R_MICROBLAZE_TLSGD",		/* name */
    441 	 false,			/* partial_inplace */
    442 	 0,			/* src_mask */
    443 	 0x0000ffff,			/* dst_mask */
    444 	 false),		/* pcrel_offset */
    445 
    446    HOWTO (R_MICROBLAZE_TLSLD,
    447 	 0,			/* rightshift */
    448 	 4,			/* size */
    449 	 32,			/* bitsize */
    450 	 false,			/* pc_relative */
    451 	 0,			/* bitpos */
    452 	 complain_overflow_dont, /* complain_on_overflow */
    453 	 bfd_elf_generic_reloc, /* special_function */
    454 	 "R_MICROBLAZE_TLSLD",		/* name */
    455 	 false,			/* partial_inplace */
    456 	 0,			/* src_mask */
    457 	 0x0000ffff,		/* dst_mask */
    458 	 false),		/* pcrel_offset */
    459 
    460    /* Computes the load module index of the load module that contains the
    461       definition of its TLS sym.  */
    462    HOWTO (R_MICROBLAZE_TLSDTPMOD32,
    463 	 0,			/* rightshift */
    464 	 4,			/* size */
    465 	 32,			/* bitsize */
    466 	 false,			/* pc_relative */
    467 	 0,			/* bitpos */
    468 	 complain_overflow_dont, /* complain_on_overflow */
    469 	 bfd_elf_generic_reloc, /* special_function */
    470 	 "R_MICROBLAZE_TLSDTPMOD32",	/* name */
    471 	 false,			/* partial_inplace */
    472 	 0,			/* src_mask */
    473 	 0x0000ffff,		/* dst_mask */
    474 	 false),		/* pcrel_offset */
    475 
    476    /* Computes a dtv-relative displacement, the difference between the value
    477       of sym+add and the base address of the thread-local storage block that
    478       contains the definition of sym, minus 0x8000.  Used for initializing GOT */
    479    HOWTO (R_MICROBLAZE_TLSDTPREL32,
    480 	 0,			/* rightshift */
    481 	 4,			/* size */
    482 	 32,			/* bitsize */
    483 	 false,			/* pc_relative */
    484 	 0,			/* bitpos */
    485 	 complain_overflow_dont, /* complain_on_overflow */
    486 	 bfd_elf_generic_reloc, /* special_function */
    487 	 "R_MICROBLAZE_TLSDTPREL32",	/* name */
    488 	 false,			/* partial_inplace */
    489 	 0,			/* src_mask */
    490 	 0x0000ffff,		/* dst_mask */
    491 	 false),		/* pcrel_offset */
    492 
    493    /* Computes a dtv-relative displacement, the difference between the value
    494       of sym+add and the base address of the thread-local storage block that
    495       contains the definition of sym, minus 0x8000.  */
    496    HOWTO (R_MICROBLAZE_TLSDTPREL64,
    497 	 0,			/* rightshift */
    498 	 4,			/* size */
    499 	 32,			/* bitsize */
    500 	 false,			/* pc_relative */
    501 	 0,			/* bitpos */
    502 	 complain_overflow_dont, /* complain_on_overflow */
    503 	 bfd_elf_generic_reloc, /* special_function */
    504 	 "R_MICROBLAZE_TLSDTPREL64",	/* name */
    505 	 false,			/* partial_inplace */
    506 	 0,			/* src_mask */
    507 	 0x0000ffff,		/* dst_mask */
    508 	 false),		/* pcrel_offset */
    509 
    510    /* Computes a tp-relative displacement, the difference between the value of
    511       sym+add and the value of the thread pointer (r13).  */
    512    HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
    513 	 0,			/* rightshift */
    514 	 4,			/* size */
    515 	 32,			/* bitsize */
    516 	 false,			/* pc_relative */
    517 	 0,			/* bitpos */
    518 	 complain_overflow_dont, /* complain_on_overflow */
    519 	 bfd_elf_generic_reloc, /* special_function */
    520 	 "R_MICROBLAZE_TLSGOTTPREL32",	/* name */
    521 	 false,			/* partial_inplace */
    522 	 0,			/* src_mask */
    523 	 0x0000ffff,		/* dst_mask */
    524 	 false),		/* pcrel_offset */
    525 
    526    /* Computes a tp-relative displacement, the difference between the value of
    527       sym+add and the value of the thread pointer (r13).  */
    528    HOWTO (R_MICROBLAZE_TLSTPREL32,
    529 	 0,			/* rightshift */
    530 	 4,			/* size */
    531 	 32,			/* bitsize */
    532 	 false,			/* pc_relative */
    533 	 0,			/* bitpos */
    534 	 complain_overflow_dont, /* complain_on_overflow */
    535 	 bfd_elf_generic_reloc, /* special_function */
    536 	 "R_MICROBLAZE_TLSTPREL32",	/* name */
    537 	 false,			/* partial_inplace */
    538 	 0,			/* src_mask */
    539 	 0x0000ffff,		/* dst_mask */
    540 	 false),		/* pcrel_offset */
    541 
    542 };
    543 
    544 #ifndef NUM_ELEM
    545 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
    546 #endif
    547 
    548 /* Initialize the microblaze_elf_howto_table, so that linear accesses can be done.  */
    550 
    551 static void
    552 microblaze_elf_howto_init (void)
    553 {
    554   unsigned int i;
    555 
    556   for (i = NUM_ELEM (microblaze_elf_howto_raw); i--;)
    557     {
    558       unsigned int type;
    559 
    560       type = microblaze_elf_howto_raw[i].type;
    561 
    562       BFD_ASSERT (type < NUM_ELEM (microblaze_elf_howto_table));
    563 
    564       microblaze_elf_howto_table [type] = & microblaze_elf_howto_raw [i];
    565     }
    566 }
    567 
    568 static reloc_howto_type *
    570 microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
    571 				  bfd_reloc_code_real_type code)
    572 {
    573   enum elf_microblaze_reloc_type microblaze_reloc = R_MICROBLAZE_NONE;
    574 
    575   switch (code)
    576     {
    577     case BFD_RELOC_NONE:
    578       microblaze_reloc = R_MICROBLAZE_NONE;
    579       break;
    580     case BFD_RELOC_MICROBLAZE_32_NONE:
    581       microblaze_reloc = R_MICROBLAZE_32_NONE;
    582       break;
    583     case BFD_RELOC_MICROBLAZE_64_NONE:
    584       microblaze_reloc = R_MICROBLAZE_64_NONE;
    585       break;
    586     case BFD_RELOC_32:
    587       microblaze_reloc = R_MICROBLAZE_32;
    588       break;
    589       /* RVA is treated the same as 32 */
    590     case BFD_RELOC_RVA:
    591       microblaze_reloc = R_MICROBLAZE_32;
    592       break;
    593     case BFD_RELOC_32_PCREL:
    594       microblaze_reloc = R_MICROBLAZE_32_PCREL;
    595       break;
    596     case BFD_RELOC_64_PCREL:
    597       microblaze_reloc = R_MICROBLAZE_64_PCREL;
    598       break;
    599     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
    600       microblaze_reloc = R_MICROBLAZE_32_PCREL_LO;
    601       break;
    602     case BFD_RELOC_64:
    603       microblaze_reloc = R_MICROBLAZE_64;
    604       break;
    605     case BFD_RELOC_MICROBLAZE_32_LO:
    606       microblaze_reloc = R_MICROBLAZE_32_LO;
    607       break;
    608     case BFD_RELOC_MICROBLAZE_32_ROSDA:
    609       microblaze_reloc = R_MICROBLAZE_SRO32;
    610       break;
    611     case BFD_RELOC_MICROBLAZE_32_RWSDA:
    612       microblaze_reloc = R_MICROBLAZE_SRW32;
    613       break;
    614     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
    615       microblaze_reloc = R_MICROBLAZE_32_SYM_OP_SYM;
    616       break;
    617     case BFD_RELOC_VTABLE_INHERIT:
    618       microblaze_reloc = R_MICROBLAZE_GNU_VTINHERIT;
    619       break;
    620     case BFD_RELOC_VTABLE_ENTRY:
    621       microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
    622       break;
    623     case BFD_RELOC_MICROBLAZE_64_GOTPC:
    624       microblaze_reloc = R_MICROBLAZE_GOTPC_64;
    625       break;
    626     case BFD_RELOC_MICROBLAZE_64_GOT:
    627       microblaze_reloc = R_MICROBLAZE_GOT_64;
    628       break;
    629     case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
    630       microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
    631       break;
    632     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
    633       microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
    634       break;
    635     case BFD_RELOC_MICROBLAZE_64_PLT:
    636       microblaze_reloc = R_MICROBLAZE_PLT_64;
    637       break;
    638     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
    639       microblaze_reloc = R_MICROBLAZE_GOTOFF_64;
    640       break;
    641     case BFD_RELOC_MICROBLAZE_32_GOTOFF:
    642       microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
    643       break;
    644     case BFD_RELOC_MICROBLAZE_64_TLSGD:
    645       microblaze_reloc = R_MICROBLAZE_TLSGD;
    646       break;
    647     case BFD_RELOC_MICROBLAZE_64_TLSLD:
    648       microblaze_reloc = R_MICROBLAZE_TLSLD;
    649       break;
    650     case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
    651       microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
    652       break;
    653     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
    654       microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
    655       break;
    656     case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
    657       microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
    658       break;
    659     case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
    660       microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
    661       break;
    662     case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
    663       microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
    664       break;
    665     case BFD_RELOC_MICROBLAZE_COPY:
    666       microblaze_reloc = R_MICROBLAZE_COPY;
    667       break;
    668     default:
    669       return (reloc_howto_type *) NULL;
    670     }
    671 
    672   if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
    673     /* Initialize howto table if needed.  */
    674     microblaze_elf_howto_init ();
    675 
    676   return microblaze_elf_howto_table [(int) microblaze_reloc];
    677 };
    678 
    679 static reloc_howto_type *
    680 microblaze_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    681 				  const char *r_name)
    682 {
    683   unsigned int i;
    684 
    685   for (i = 0; i < NUM_ELEM (microblaze_elf_howto_raw); i++)
    686     if (microblaze_elf_howto_raw[i].name != NULL
    687 	&& strcasecmp (microblaze_elf_howto_raw[i].name, r_name) == 0)
    688       return &microblaze_elf_howto_raw[i];
    689 
    690   return NULL;
    691 }
    692 
    693 /* Set the howto pointer for a RCE ELF reloc.  */
    694 
    695 static bool
    696 microblaze_elf_info_to_howto (bfd * abfd,
    697 			      arelent * cache_ptr,
    698 			      Elf_Internal_Rela * dst)
    699 {
    700   unsigned int r_type;
    701 
    702   if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
    703     /* Initialize howto table if needed.  */
    704     microblaze_elf_howto_init ();
    705 
    706   r_type = ELF32_R_TYPE (dst->r_info);
    707   if (r_type >= R_MICROBLAZE_max)
    708     {
    709       /* xgettext:c-format */
    710       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    711 			  abfd, r_type);
    712       bfd_set_error (bfd_error_bad_value);
    713       return false;
    714     }
    715 
    716   cache_ptr->howto = microblaze_elf_howto_table [r_type];
    717   return true;
    718 }
    719 
    720 /* Relax table contains information about instructions which can
    721    be removed by relaxation -- replacing a long address with a
    722    short address.  */
    723 struct relax_table
    724 {
    725   /* Address where bytes may be deleted.  */
    726   bfd_vma addr;
    727 
    728   /* Number of bytes to be deleted.  */
    729   size_t size;
    730 };
    731 
    732 struct _microblaze_elf_section_data
    733 {
    734   struct bfd_elf_section_data elf;
    735   /* Count of used relaxation table entries.  */
    736   size_t relax_count;
    737   /* Relaxation table.  */
    738   struct relax_table *relax;
    739 };
    740 
    741 #define microblaze_elf_section_data(sec) \
    742   ((struct _microblaze_elf_section_data *) elf_section_data (sec))
    743 
    744 static bool
    745 microblaze_elf_new_section_hook (bfd *abfd, asection *sec)
    746 {
    747   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   int rel_count;
   1773   unsigned int shndx;
   1774   size_t i, sym_index;
   1775   asection *o;
   1776   struct elf_link_hash_entry *sym_hash;
   1777   Elf_Internal_Sym *isymbuf, *isymend;
   1778   Elf_Internal_Sym *isym;
   1779   size_t symcount;
   1780   size_t offset;
   1781   bfd_vma src, dest;
   1782   struct _microblaze_elf_section_data *sdata;
   1783 
   1784   /* We only do this once per section.  We may be able to delete some code
   1785      by running multiple passes, but it is not worth it.  */
   1786   *again = false;
   1787 
   1788   /* Only do this for a text section.  */
   1789   if (bfd_link_relocatable (link_info)
   1790       || (sec->flags & SEC_RELOC) == 0
   1791       || (sec->flags & SEC_CODE) == 0
   1792       || sec->reloc_count == 0
   1793       || (sdata = microblaze_elf_section_data (sec)) == NULL)
   1794     return true;
   1795 
   1796   BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
   1797 
   1798   /* If this is the first time we have been called for this section,
   1799      initialize the cooked size.  */
   1800   if (sec->size == 0)
   1801     sec->size = sec->rawsize;
   1802 
   1803   /* Get symbols for this section.  */
   1804   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   1805   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   1806   symcount =  symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
   1807   if (isymbuf == NULL)
   1808     isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
   1809 				    0, NULL, NULL, NULL);
   1810   BFD_ASSERT (isymbuf != NULL);
   1811 
   1812   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
   1813   if (internal_relocs == NULL)
   1814     goto error_return;
   1815   if (! link_info->keep_memory)
   1816     free_relocs = internal_relocs;
   1817 
   1818   sdata->relax_count = 0;
   1819   sdata->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
   1820 						    * sizeof (*sdata->relax));
   1821   if (sdata->relax == NULL)
   1822     goto error_return;
   1823 
   1824   irelend = internal_relocs + sec->reloc_count;
   1825   rel_count = 0;
   1826   for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
   1827     {
   1828       bfd_vma symval;
   1829       if ((ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
   1830 	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64)
   1831 	  && (ELF32_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
   1832 	continue; /* Can't delete this reloc.  */
   1833 
   1834       /* Get the section contents.  */
   1835       if (contents == NULL)
   1836 	{
   1837 	  if (elf_section_data (sec)->this_hdr.contents != NULL)
   1838 	    contents = elf_section_data (sec)->this_hdr.contents;
   1839 	  else
   1840 	    {
   1841 	      contents = (bfd_byte *) bfd_malloc (sec->size);
   1842 	      if (contents == NULL)
   1843 		goto error_return;
   1844 	      free_contents = contents;
   1845 
   1846 	      if (!bfd_get_section_contents (abfd, sec, contents,
   1847 					     (file_ptr) 0, sec->size))
   1848 		goto error_return;
   1849 	      elf_section_data (sec)->this_hdr.contents = contents;
   1850 	    }
   1851 	}
   1852 
   1853       /* Get the value of the symbol referred to by the reloc.  */
   1854       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
   1855 	{
   1856 	  /* A local symbol.  */
   1857 	  asection *sym_sec;
   1858 
   1859 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
   1860 	  if (isym->st_shndx == SHN_UNDEF)
   1861 	    sym_sec = bfd_und_section_ptr;
   1862 	  else if (isym->st_shndx == SHN_ABS)
   1863 	    sym_sec = bfd_abs_section_ptr;
   1864 	  else if (isym->st_shndx == SHN_COMMON)
   1865 	    sym_sec = bfd_com_section_ptr;
   1866 	  else
   1867 	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
   1868 
   1869 	  symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
   1870 	}
   1871       else
   1872 	{
   1873 	  unsigned long indx;
   1874 	  struct elf_link_hash_entry *h;
   1875 
   1876 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
   1877 	  h = elf_sym_hashes (abfd)[indx];
   1878 	  BFD_ASSERT (h != NULL);
   1879 
   1880 	  if (h->root.type != bfd_link_hash_defined
   1881 	      && h->root.type != bfd_link_hash_defweak)
   1882 	    /* This appears to be a reference to an undefined
   1883 	       symbol.  Just ignore it--it will be caught by the
   1884 	       regular reloc processing.  */
   1885 	    continue;
   1886 
   1887 	  symval = (h->root.u.def.value
   1888 		    + h->root.u.def.section->output_section->vma
   1889 		    + h->root.u.def.section->output_offset);
   1890 	}
   1891 
   1892       /* If this is a PC-relative reloc, subtract the instr offset from
   1893 	 the symbol value.  */
   1894       if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_64_PCREL)
   1895 	{
   1896 	  symval = symval + irel->r_addend
   1897 	    - (irel->r_offset
   1898 	       + sec->output_section->vma
   1899 	       + sec->output_offset);
   1900 	}
   1901       else if (ELF32_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
   1902 	{
   1903 	  symval = symval + irel->r_addend - (sec->output_section->vma);
   1904 	}
   1905       else
   1906 	symval += irel->r_addend;
   1907 
   1908       if ((symval & 0xffff8000) == 0
   1909 	  || (symval & 0xffff8000) == 0xffff8000)
   1910 	{
   1911 	  /* We can delete this instruction.  */
   1912 	  sdata->relax[sdata->relax_count].addr = irel->r_offset;
   1913 	  sdata->relax[sdata->relax_count].size = INST_WORD_SIZE;
   1914 	  sdata->relax_count++;
   1915 
   1916 	  /* Rewrite relocation type.  */
   1917 	  switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
   1918 	    {
   1919 	    case R_MICROBLAZE_64_PCREL:
   1920 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1921 					   (int) R_MICROBLAZE_32_PCREL_LO);
   1922 	      break;
   1923 	    case R_MICROBLAZE_64:
   1924 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1925 					   (int) R_MICROBLAZE_32_LO);
   1926 	      break;
   1927 	    case R_MICROBLAZE_TEXTREL_64:
   1928 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1929 					   (int) R_MICROBLAZE_TEXTREL_32_LO);
   1930 	      break;
   1931 	    default:
   1932 	      /* Cannot happen.  */
   1933 	      BFD_ASSERT (false);
   1934 	    }
   1935 	}
   1936     } /* Loop through all relocations.  */
   1937 
   1938   /* Loop through the relocs again, and see if anything needs to change.  */
   1939   if (sdata->relax_count > 0)
   1940     {
   1941       shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
   1942       rel_count = 0;
   1943       sdata->relax[sdata->relax_count].addr = sec->size;
   1944 
   1945       for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
   1946 	{
   1947 	  bfd_vma nraddr;
   1948 
   1949 	  /* Get the new reloc address.  */
   1950 	  nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
   1951 	  switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
   1952 	    {
   1953 	    default:
   1954 	      break;
   1955 	    case R_MICROBLAZE_64_PCREL:
   1956 	      break;
   1957 	    case R_MICROBLAZE_TEXTREL_64:
   1958 	    case R_MICROBLAZE_TEXTREL_32_LO:
   1959 	    case R_MICROBLAZE_64:
   1960 	    case R_MICROBLAZE_32_LO:
   1961 	      /* If this reloc is against a symbol defined in this
   1962 		 section, we must check the addend to see it will put the value in
   1963 		 range to be adjusted, and hence must be changed.  */
   1964 	      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
   1965 		{
   1966 		  isym = isymbuf + ELF32_R_SYM (irel->r_info);
   1967 		  /* Only handle relocs against .text.  */
   1968 		  if (isym->st_shndx == shndx
   1969 		      && ELF32_ST_TYPE (isym->st_info) == STT_SECTION)
   1970 		    irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
   1971 		}
   1972 	      break;
   1973 	    case R_MICROBLAZE_NONE:
   1974 	    case R_MICROBLAZE_32_NONE:
   1975 	      {
   1976 		/* This was a PC-relative instruction that was
   1977 		   completely resolved.  */
   1978 		size_t sfix, efix;
   1979 		bfd_vma target_address;
   1980 		target_address = irel->r_addend + irel->r_offset;
   1981 		sfix = calc_fixup (irel->r_offset, 0, sec);
   1982 		efix = calc_fixup (target_address, 0, sec);
   1983 		irel->r_addend -= (efix - sfix);
   1984 		/* Should use HOWTO.  */
   1985 		microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
   1986 						   irel->r_addend);
   1987 	      }
   1988 	      break;
   1989 	    case R_MICROBLAZE_64_NONE:
   1990 	      {
   1991 		/* This was a PC-relative 64-bit instruction that was
   1992 		   completely resolved.  */
   1993 		size_t sfix, efix;
   1994 		bfd_vma target_address;
   1995 		target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
   1996 		sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
   1997 		efix = calc_fixup (target_address, 0, sec);
   1998 		irel->r_addend -= (efix - sfix);
   1999     microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
   2000 				       + INST_WORD_SIZE, irel->r_addend);
   2001 	      }
   2002 	      break;
   2003 	    }
   2004 	  irel->r_offset = nraddr;
   2005 	} /* Change all relocs in this section.  */
   2006 
   2007       /* Look through all other sections.  */
   2008       for (o = abfd->sections; o != NULL; o = o->next)
   2009 	{
   2010 	  Elf_Internal_Rela *irelocs;
   2011 	  Elf_Internal_Rela *irelscan, *irelscanend;
   2012 	  bfd_byte *ocontents;
   2013 
   2014 	  if (o == sec
   2015 	      || (o->flags & SEC_RELOC) == 0
   2016 	      || o->reloc_count == 0)
   2017 	    continue;
   2018 
   2019 	  /* We always cache the relocs.  Perhaps, if info->keep_memory is
   2020 	     FALSE, we should free them, if we are permitted to.  */
   2021 
   2022 	  irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, true);
   2023 	  if (irelocs == NULL)
   2024 	    goto error_return;
   2025 
   2026 	  ocontents = NULL;
   2027 	  irelscanend = irelocs + o->reloc_count;
   2028 	  for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
   2029 	    {
   2030 	      if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
   2031 		  || (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_NONE))
   2032 		{
   2033 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2034 
   2035 		  /* Look at the reloc only if the value has been resolved.  */
   2036 		  if (isym->st_shndx == shndx
   2037 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   2038 		    {
   2039 		      if (ocontents == NULL)
   2040 			{
   2041 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2042 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2043 			  else
   2044 			    {
   2045 			      /* We always cache the section contents.
   2046 				 Perhaps, if info->keep_memory is FALSE, we
   2047 				 should free them, if we are permitted to.  */
   2048 			      if (o->rawsize == 0)
   2049 				o->rawsize = o->size;
   2050 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2051 			      if (ocontents == NULL)
   2052 				goto error_return;
   2053 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2054 							     (file_ptr) 0,
   2055 							     o->rawsize))
   2056 				goto error_return;
   2057 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2058 			    }
   2059 
   2060 			}
   2061 		      irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
   2062 		    }
   2063 		  else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
   2064 		    {
   2065 		      isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2066 
   2067 		      /* Look at the reloc only if the value has been resolved.  */
   2068 		      if (ocontents == NULL)
   2069 			{
   2070 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2071 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2072 			  else
   2073 			    {
   2074 			      /* We always cache the section contents.
   2075 				 Perhaps, if info->keep_memory is FALSE, we
   2076 				 should free them, if we are permitted to.  */
   2077 
   2078 			      if (o->rawsize == 0)
   2079 				o->rawsize = o->size;
   2080 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2081 			      if (ocontents == NULL)
   2082 				goto error_return;
   2083 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2084 							     (file_ptr) 0,
   2085 							     o->rawsize))
   2086 				goto error_return;
   2087 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2088 			    }
   2089 			}
   2090 		      irelscan->r_addend -= calc_fixup (irelscan->r_addend
   2091 							+ isym->st_value,
   2092 							0,
   2093 							sec);
   2094 		    }
   2095 		}
   2096 	      else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
   2097 		       || (ELF32_R_TYPE (irelscan->r_info)
   2098 			   == (int) R_MICROBLAZE_32_LO)
   2099 		       || (ELF32_R_TYPE (irelscan->r_info)
   2100 			   == (int) R_MICROBLAZE_TEXTREL_32_LO))
   2101 		{
   2102 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2103 
   2104 		  /* Look at the reloc only if the value has been resolved.  */
   2105 		  if (isym->st_shndx == shndx
   2106 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   2107 		    {
   2108 		      bfd_vma immediate;
   2109 		      bfd_vma target_address;
   2110 
   2111 		      if (ocontents == NULL)
   2112 			{
   2113 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2114 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2115 			  else
   2116 			    {
   2117 			      /* We always cache the section contents.
   2118 				 Perhaps, if info->keep_memory is FALSE, we
   2119 				 should free them, if we are permitted to.  */
   2120 			      if (o->rawsize == 0)
   2121 				o->rawsize = o->size;
   2122 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2123 			      if (ocontents == NULL)
   2124 				goto error_return;
   2125 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2126 							     (file_ptr) 0,
   2127 							     o->rawsize))
   2128 				goto error_return;
   2129 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2130 			    }
   2131 			}
   2132 
   2133 		      unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
   2134 		      immediate = instr & 0x0000ffff;
   2135 		      target_address = immediate;
   2136 		      offset = calc_fixup (target_address, 0, sec);
   2137 		      immediate -= offset;
   2138 		      irelscan->r_addend -= offset;
   2139 	  microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
   2140 					     irelscan->r_addend);
   2141 		    }
   2142 		}
   2143 
   2144 	      if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
   2145 		  || (ELF32_R_TYPE (irelscan->r_info)
   2146 			      == (int) R_MICROBLAZE_TEXTREL_64))
   2147 		{
   2148 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2149 
   2150 		  /* Look at the reloc only if the value has been resolved.  */
   2151 		  if (isym->st_shndx == shndx
   2152 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   2153 		    {
   2154 		      if (ocontents == NULL)
   2155 			{
   2156 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2157 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2158 			  else
   2159 			    {
   2160 			      /* We always cache the section contents.
   2161 				 Perhaps, if info->keep_memory is FALSE, we
   2162 				 should free them, if we are permitted to.  */
   2163 
   2164 			      if (o->rawsize == 0)
   2165 				o->rawsize = o->size;
   2166 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2167 			      if (ocontents == NULL)
   2168 				goto error_return;
   2169 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2170 							     (file_ptr) 0,
   2171 							     o->rawsize))
   2172 				goto error_return;
   2173 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2174 			    }
   2175 			}
   2176 		      offset = calc_fixup (irelscan->r_addend, 0, sec);
   2177 		      irelscan->r_addend -= offset;
   2178 		    }
   2179 		}
   2180 	      else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_PCREL)
   2181 		{
   2182 		  isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
   2183 
   2184 		  /* Look at the reloc only if the value has been resolved.  */
   2185 		  if (isym->st_shndx == shndx
   2186 		      && (ELF32_ST_TYPE (isym->st_info) == STT_SECTION))
   2187 		    {
   2188 		      bfd_vma immediate;
   2189 		      bfd_vma target_address;
   2190 
   2191 		      if (ocontents == NULL)
   2192 			{
   2193 			  if (elf_section_data (o)->this_hdr.contents != NULL)
   2194 			    ocontents = elf_section_data (o)->this_hdr.contents;
   2195 			  else
   2196 			    {
   2197 			      /* We always cache the section contents.
   2198 				 Perhaps, if info->keep_memory is FALSE, we
   2199 				 should free them, if we are permitted to.  */
   2200 			      if (o->rawsize == 0)
   2201 				o->rawsize = o->size;
   2202 			      ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
   2203 			      if (ocontents == NULL)
   2204 				goto error_return;
   2205 			      if (!bfd_get_section_contents (abfd, o, ocontents,
   2206 							     (file_ptr) 0,
   2207 							     o->rawsize))
   2208 				goto error_return;
   2209 			      elf_section_data (o)->this_hdr.contents = ocontents;
   2210 			    }
   2211 			}
   2212 	  unsigned long instr_hi =  bfd_get_32 (abfd, ocontents
   2213 						+ irelscan->r_offset);
   2214 	  unsigned long instr_lo =  bfd_get_32 (abfd, ocontents
   2215 						+ irelscan->r_offset
   2216 						+ INST_WORD_SIZE);
   2217 	  immediate = (instr_hi & 0x0000ffff) << 16;
   2218 	  immediate |= (instr_lo & 0x0000ffff);
   2219 		      target_address = immediate;
   2220 		      offset = calc_fixup (target_address, 0, sec);
   2221 		      immediate -= offset;
   2222 		      irelscan->r_addend -= offset;
   2223 	  microblaze_bfd_write_imm_value_64 (abfd, ocontents
   2224 					     + irelscan->r_offset, immediate);
   2225 		    }
   2226 		}
   2227 	    }
   2228 	}
   2229 
   2230       /* Adjust the local symbols defined in this section.  */
   2231       isymend = isymbuf + symtab_hdr->sh_info;
   2232       for (isym = isymbuf; isym < isymend; isym++)
   2233 	{
   2234 	  if (isym->st_shndx == shndx)
   2235 	    {
   2236 	      isym->st_value -= calc_fixup (isym->st_value, 0, sec);
   2237 	      if (isym->st_size)
   2238 		isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
   2239 	    }
   2240 	}
   2241 
   2242       /* Now adjust the global symbols defined in this section.  */
   2243       isym = isymbuf + symtab_hdr->sh_info;
   2244       symcount =  (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
   2245       for (sym_index = 0; sym_index < symcount; sym_index++)
   2246 	{
   2247 	  sym_hash = elf_sym_hashes (abfd)[sym_index];
   2248 	  if ((sym_hash->root.type == bfd_link_hash_defined
   2249 		  || sym_hash->root.type == bfd_link_hash_defweak)
   2250 	      && sym_hash->root.u.def.section == sec)
   2251 	    {
   2252 	      sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
   2253 							0, sec);
   2254 	      if (sym_hash->size)
   2255 		sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
   2256 					      sym_hash->size, sec);
   2257 	    }
   2258 	}
   2259 
   2260       /* Physically move the code and change the cooked size.  */
   2261       dest = sdata->relax[0].addr;
   2262       for (i = 0; i < sdata->relax_count; i++)
   2263 	{
   2264 	  size_t len;
   2265 	  src = sdata->relax[i].addr + sdata->relax[i].size;
   2266 	  len = (sdata->relax[i+1].addr - sdata->relax[i].addr
   2267 		 - sdata->relax[i].size);
   2268 
   2269 	  memmove (contents + dest, contents + src, len);
   2270 	  sec->size -= sdata->relax[i].size;
   2271 	  dest += len;
   2272 	}
   2273 
   2274       elf_section_data (sec)->relocs = internal_relocs;
   2275       free_relocs = NULL;
   2276 
   2277       elf_section_data (sec)->this_hdr.contents = contents;
   2278       free_contents = NULL;
   2279 
   2280       symtab_hdr->contents = (bfd_byte *) isymbuf;
   2281     }
   2282 
   2283   free (free_relocs);
   2284   free_relocs = NULL;
   2285 
   2286   if (free_contents != NULL)
   2287     {
   2288       if (!link_info->keep_memory)
   2289 	free (free_contents);
   2290       else
   2291 	/* Cache the section contents for elf_link_input_bfd.  */
   2292 	elf_section_data (sec)->this_hdr.contents = contents;
   2293       free_contents = NULL;
   2294     }
   2295 
   2296   if (sdata->relax_count == 0)
   2297     {
   2298       *again = false;
   2299       free (sdata->relax);
   2300       sdata->relax = NULL;
   2301     }
   2302   else
   2303     *again = true;
   2304   return true;
   2305 
   2306  error_return:
   2307   free (free_relocs);
   2308   free (free_contents);
   2309   free (sdata->relax);
   2310   sdata->relax = NULL;
   2311   sdata->relax_count = 0;
   2312   return false;
   2313 }
   2314 
   2315 /* Return the section that should be marked against GC for a given
   2316    relocation.  */
   2317 
   2318 static asection *
   2319 microblaze_elf_gc_mark_hook (asection *sec,
   2320 			     struct bfd_link_info * info,
   2321 			     Elf_Internal_Rela * rel,
   2322 			     struct elf_link_hash_entry * h,
   2323 			     Elf_Internal_Sym * sym)
   2324 {
   2325   if (h != NULL)
   2326     switch (ELF32_R_TYPE (rel->r_info))
   2327       {
   2328       case R_MICROBLAZE_GNU_VTINHERIT:
   2329       case R_MICROBLAZE_GNU_VTENTRY:
   2330 	return NULL;
   2331       }
   2332 
   2333   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
   2334 }
   2335 
   2336 /* PIC support.  */
   2337 
   2338 #define PLT_ENTRY_SIZE 16
   2339 
   2340 #define PLT_ENTRY_WORD_0  0xb0000000	      /* "imm 0".  */
   2341 #define PLT_ENTRY_WORD_1  0xe9940000	      /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT.  */
   2342 #define PLT_ENTRY_WORD_1_NOPIC	0xe9800000    /* "lwi r12,r0,0" - non-PIC object.  */
   2343 #define PLT_ENTRY_WORD_2  0x98186000	      /* "brad r12".  */
   2344 #define PLT_ENTRY_WORD_3  0x80000000	      /* "nop".  */
   2345 
   2346 static bool
   2347 update_local_sym_info (bfd *abfd,
   2348 		       Elf_Internal_Shdr *symtab_hdr,
   2349 		       unsigned long r_symndx,
   2350 		       unsigned int tls_type)
   2351 {
   2352   bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
   2353   unsigned char *local_got_tls_masks;
   2354 
   2355   if (local_got_refcounts == NULL)
   2356     {
   2357       bfd_size_type size = symtab_hdr->sh_info;
   2358 
   2359       size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
   2360       local_got_refcounts = bfd_zalloc (abfd, size);
   2361       if (local_got_refcounts == NULL)
   2362 	return false;
   2363       elf_local_got_refcounts (abfd) = local_got_refcounts;
   2364     }
   2365 
   2366   local_got_tls_masks =
   2367 	 (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
   2368   local_got_tls_masks[r_symndx] |= tls_type;
   2369   local_got_refcounts[r_symndx] += 1;
   2370 
   2371   return true;
   2372 }
   2373 /* Look through the relocs for a section during the first phase.  */
   2374 
   2375 static bool
   2376 microblaze_elf_check_relocs (bfd * abfd,
   2377 			     struct bfd_link_info * info,
   2378 			     asection * sec,
   2379 			     const Elf_Internal_Rela * relocs)
   2380 {
   2381   Elf_Internal_Shdr *		symtab_hdr;
   2382   struct elf_link_hash_entry ** sym_hashes;
   2383   const Elf_Internal_Rela *	rel;
   2384   const Elf_Internal_Rela *	rel_end;
   2385   struct elf32_mb_link_hash_table *htab;
   2386   asection *sreloc = NULL;
   2387 
   2388   if (bfd_link_relocatable (info))
   2389     return true;
   2390 
   2391   htab = elf32_mb_hash_table (info);
   2392   if (htab == NULL)
   2393     return false;
   2394 
   2395   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
   2396   sym_hashes = elf_sym_hashes (abfd);
   2397 
   2398   rel_end = relocs + sec->reloc_count;
   2399 
   2400   for (rel = relocs; rel < rel_end; rel++)
   2401     {
   2402       unsigned int r_type;
   2403       struct elf_link_hash_entry * h;
   2404       unsigned long r_symndx;
   2405       unsigned char tls_type = 0;
   2406 
   2407       r_symndx = ELF32_R_SYM (rel->r_info);
   2408       r_type = ELF32_R_TYPE (rel->r_info);
   2409 
   2410       if (r_symndx < symtab_hdr->sh_info)
   2411 	h = NULL;
   2412       else
   2413 	{
   2414 	  h = sym_hashes [r_symndx - symtab_hdr->sh_info];
   2415 	  while (h->root.type == bfd_link_hash_indirect
   2416 		 || h->root.type == bfd_link_hash_warning)
   2417 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
   2418 	}
   2419 
   2420       switch (r_type)
   2421 	{
   2422 	  /* This relocation describes the C++ object vtable hierarchy.
   2423 	     Reconstruct it for later use during GC.  */
   2424 	case R_MICROBLAZE_GNU_VTINHERIT:
   2425 	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
   2426 	    return false;
   2427 	  break;
   2428 
   2429 	  /* This relocation describes which C++ vtable entries are actually
   2430 	     used.  Record for later use during GC.  */
   2431 	case R_MICROBLAZE_GNU_VTENTRY:
   2432 	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
   2433 	    return false;
   2434 	  break;
   2435 
   2436 	  /* This relocation requires .plt entry.  */
   2437 	case R_MICROBLAZE_PLT_64:
   2438 	  if (h != NULL)
   2439 	    {
   2440 	      h->needs_plt = 1;
   2441 	      h->plt.refcount += 1;
   2442 	    }
   2443 	  break;
   2444 
   2445 	  /* This relocation requires .got entry.  */
   2446 	case R_MICROBLAZE_TLSGD:
   2447 	  tls_type |= (TLS_TLS | TLS_GD);
   2448 	  goto dogottls;
   2449 	case R_MICROBLAZE_TLSLD:
   2450 	  tls_type |= (TLS_TLS | TLS_LD);
   2451 	  /* Fall through.  */
   2452 	dogottls:
   2453 	  sec->has_tls_reloc = 1;
   2454 	  /* Fall through.  */
   2455 	case R_MICROBLAZE_GOT_64:
   2456 	  if (htab->elf.sgot == NULL)
   2457 	    {
   2458 	      if (htab->elf.dynobj == NULL)
   2459 		htab->elf.dynobj = abfd;
   2460 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
   2461 		return false;
   2462 	    }
   2463 	  if (h != NULL)
   2464 	    {
   2465 	      h->got.refcount += 1;
   2466 	      elf32_mb_hash_entry (h)->tls_mask |= tls_type;
   2467 	    }
   2468 	  else
   2469 	    {
   2470 	      if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
   2471 		return false;
   2472 	    }
   2473 	  break;
   2474 
   2475 	case R_MICROBLAZE_GOTOFF_64:
   2476 	case R_MICROBLAZE_GOTOFF_32:
   2477 	  if (htab->elf.sgot == NULL)
   2478 	    {
   2479 	      if (htab->elf.dynobj == NULL)
   2480 		htab->elf.dynobj = abfd;
   2481 	      if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
   2482 		return false;
   2483 	    }
   2484 	  break;
   2485 
   2486 	case R_MICROBLAZE_64:
   2487 	case R_MICROBLAZE_64_PCREL:
   2488 	case R_MICROBLAZE_32:
   2489 	  {
   2490 	    if (h != NULL && !bfd_link_pic (info))
   2491 	      {
   2492 		/* we may need a copy reloc.  */
   2493 		h->non_got_ref = 1;
   2494 
   2495 		/* we may also need a .plt entry.  */
   2496 		h->plt.refcount += 1;
   2497 		if (ELF32_R_TYPE (rel->r_info) != R_MICROBLAZE_64_PCREL)
   2498 		  h->pointer_equality_needed = 1;
   2499 	      }
   2500 
   2501 
   2502 	    /* If we are creating a shared library, and this is a reloc
   2503 	       against a global symbol, or a non PC relative reloc
   2504 	       against a local symbol, then we need to copy the reloc
   2505 	       into the shared library.  However, if we are linking with
   2506 	       -Bsymbolic, we do not need to copy a reloc against a
   2507 	       global symbol which is defined in an object we are
   2508 	       including in the link (i.e., DEF_REGULAR is set).  At
   2509 	       this point we have not seen all the input files, so it is
   2510 	       possible that DEF_REGULAR is not set now but will be set
   2511 	       later (it is never cleared).  In case of a weak definition,
   2512 	       DEF_REGULAR may be cleared later by a strong definition in
   2513 	       a shared library.  We account for that possibility below by
   2514 	       storing information in the relocs_copied field of the hash
   2515 	       table entry.  A similar situation occurs when creating
   2516 	       shared libraries and symbol visibility changes render the
   2517 	       symbol local.
   2518 
   2519 	       If on the other hand, we are creating an executable, we
   2520 	       may need to keep relocations for symbols satisfied by a
   2521 	       dynamic library if we manage to avoid copy relocs for the
   2522 	       symbol.  */
   2523 
   2524 	    if ((bfd_link_pic (info)
   2525 		 && (sec->flags & SEC_ALLOC) != 0
   2526 		 && (r_type != R_MICROBLAZE_64_PCREL
   2527 		     || (h != NULL
   2528 			 && (! info->symbolic
   2529 			     || h->root.type == bfd_link_hash_defweak
   2530 			     || !h->def_regular))))
   2531 		|| (!bfd_link_pic (info)
   2532 		    && (sec->flags & SEC_ALLOC) != 0
   2533 		    && h != NULL
   2534 		    && (h->root.type == bfd_link_hash_defweak
   2535 			|| !h->def_regular)))
   2536 	      {
   2537 		struct elf_dyn_relocs *p;
   2538 		struct elf_dyn_relocs **head;
   2539 
   2540 		/* When creating a shared object, we must copy these
   2541 		   relocs into the output file.  We create a reloc
   2542 		   section in dynobj and make room for the reloc.  */
   2543 
   2544 		if (sreloc == NULL)
   2545 		  {
   2546 		    bfd *dynobj;
   2547 
   2548 		    if (htab->elf.dynobj == NULL)
   2549 		      htab->elf.dynobj = abfd;
   2550 		    dynobj = htab->elf.dynobj;
   2551 
   2552 		    sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
   2553 								  2, abfd, 1);
   2554 		    if (sreloc == NULL)
   2555 		      return false;
   2556 		  }
   2557 
   2558 		/* If this is a global symbol, we count the number of
   2559 		   relocations we need for this symbol.  */
   2560 		if (h != NULL)
   2561 		  head = &h->dyn_relocs;
   2562 		else
   2563 		  {
   2564 		    /* Track dynamic relocs needed for local syms too.
   2565 		       We really need local syms available to do this
   2566 		       easily.  Oh well.  */
   2567 
   2568 		    asection *s;
   2569 		    Elf_Internal_Sym *isym;
   2570 		    void *vpp;
   2571 
   2572 		    isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
   2573 						  abfd, r_symndx);
   2574 		    if (isym == NULL)
   2575 		      return false;
   2576 
   2577 		    s = bfd_section_from_elf_index (abfd, isym->st_shndx);
   2578 		    if (s == NULL)
   2579 		      return false;
   2580 
   2581 		    vpp = &elf_section_data (s)->local_dynrel;
   2582 		    head = (struct elf_dyn_relocs **) vpp;
   2583 		  }
   2584 
   2585 		p = *head;
   2586 		if (p == NULL || p->sec != sec)
   2587 		  {
   2588 		    size_t amt = sizeof *p;
   2589 		    p = ((struct elf_dyn_relocs *)
   2590 			 bfd_alloc (htab->elf.dynobj, amt));
   2591 		    if (p == NULL)
   2592 		      return false;
   2593 		    p->next = *head;
   2594 		    *head = p;
   2595 		    p->sec = sec;
   2596 		    p->count = 0;
   2597 		    p->pc_count = 0;
   2598 		  }
   2599 
   2600 		p->count += 1;
   2601 		if (r_type == R_MICROBLAZE_64_PCREL)
   2602 		  p->pc_count += 1;
   2603 	      }
   2604 	  }
   2605 	  break;
   2606 	}
   2607     }
   2608 
   2609   return true;
   2610 }
   2611 
   2612 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
   2613 
   2614 static void
   2615 microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
   2616 				     struct elf_link_hash_entry *dir,
   2617 				     struct elf_link_hash_entry *ind)
   2618 {
   2619   struct elf32_mb_link_hash_entry *edir, *eind;
   2620 
   2621   edir = (struct elf32_mb_link_hash_entry *) dir;
   2622   eind = (struct elf32_mb_link_hash_entry *) ind;
   2623 
   2624   edir->tls_mask |= eind->tls_mask;
   2625 
   2626   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
   2627 }
   2628 
   2629 static bool
   2630 microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   2631 				      struct elf_link_hash_entry *h)
   2632 {
   2633   struct elf32_mb_link_hash_table *htab;
   2634   asection *s, *srel;
   2635   unsigned int power_of_two;
   2636 
   2637   htab = elf32_mb_hash_table (info);
   2638   if (htab == NULL)
   2639     return false;
   2640 
   2641   /* If this is a function, put it in the procedure linkage table.  We
   2642      will fill in the contents of the procedure linkage table later,
   2643      when we know the address of the .got section.  */
   2644   if (h->type == STT_FUNC
   2645       || h->needs_plt)
   2646     {
   2647       if (h->plt.refcount <= 0
   2648 	  || SYMBOL_CALLS_LOCAL (info, h)
   2649 	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
   2650 	      && h->root.type == bfd_link_hash_undefweak))
   2651 	{
   2652 	  /* This case can occur if we saw a PLT reloc in an input
   2653 	     file, but the symbol was never referred to by a dynamic
   2654 	     object, or if all references were garbage collected.  In
   2655 	     such a case, we don't actually need to build a procedure
   2656 	     linkage table, and we can just do a PC32 reloc instead.  */
   2657 	  h->plt.offset = (bfd_vma) -1;
   2658 	  h->needs_plt = 0;
   2659 	}
   2660 
   2661       return true;
   2662     }
   2663   else
   2664     /* It's possible that we incorrectly decided a .plt reloc was
   2665        needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
   2666        check_relocs.  We can't decide accurately between function and
   2667        non-function syms in check-relocs;  Objects loaded later in
   2668        the link may change h->type.  So fix it now.  */
   2669     h->plt.offset = (bfd_vma) -1;
   2670 
   2671   /* If this is a weak symbol, and there is a real definition, the
   2672      processor independent code will have arranged for us to see the
   2673      real definition first, and we can just use the same value.  */
   2674   if (h->is_weakalias)
   2675     {
   2676       struct elf_link_hash_entry *def = weakdef (h);
   2677       BFD_ASSERT (def->root.type == bfd_link_hash_defined);
   2678       h->root.u.def.section = def->root.u.def.section;
   2679       h->root.u.def.value = def->root.u.def.value;
   2680       return true;
   2681     }
   2682 
   2683   /* This is a reference to a symbol defined by a dynamic object which
   2684      is not a function.  */
   2685 
   2686   /* If we are creating a shared library, we must presume that the
   2687      only references to the symbol are via the global offset table.
   2688      For such cases we need not do anything here; the relocations will
   2689      be handled correctly by relocate_section.  */
   2690   if (bfd_link_pic (info))
   2691     return true;
   2692 
   2693   /* If there are no references to this symbol that do not use the
   2694      GOT, we don't need to generate a copy reloc.  */
   2695   if (!h->non_got_ref)
   2696     return true;
   2697 
   2698   /* If -z nocopyreloc was given, we won't generate them either.  */
   2699   if (info->nocopyreloc)
   2700     {
   2701       h->non_got_ref = 0;
   2702       return true;
   2703     }
   2704 
   2705   /* If we don't find any dynamic relocs in read-only sections, then
   2706      we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
   2707   if (!_bfd_elf_readonly_dynrelocs (h))
   2708     {
   2709       h->non_got_ref = 0;
   2710       return true;
   2711     }
   2712 
   2713   /* We must allocate the symbol in our .dynbss section, which will
   2714      become part of the .bss section of the executable.  There will be
   2715      an entry for this symbol in the .dynsym section.  The dynamic
   2716      object will contain position independent code, so all references
   2717      from the dynamic object to this symbol will go through the global
   2718      offset table.  The dynamic linker will use the .dynsym entry to
   2719      determine the address it must put in the global offset table, so
   2720      both the dynamic object and the regular object will refer to the
   2721      same memory location for the variable.  */
   2722 
   2723   /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
   2724      to copy the initial value out of the dynamic object and into the
   2725      runtime process image.  */
   2726   if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
   2727     {
   2728       s = htab->elf.sdynrelro;
   2729       srel = htab->elf.sreldynrelro;
   2730     }
   2731   else
   2732     {
   2733       s = htab->elf.sdynbss;
   2734       srel = htab->elf.srelbss;
   2735     }
   2736   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
   2737     {
   2738       srel->size += sizeof (Elf32_External_Rela);
   2739       h->needs_copy = 1;
   2740     }
   2741 
   2742   /* We need to figure out the alignment required for this symbol.  I
   2743      have no idea how ELF linkers handle this.  */
   2744   power_of_two = bfd_log2 (h->size);
   2745   if (power_of_two > 3)
   2746     power_of_two = 3;
   2747 
   2748   /* Apply the required alignment.  */
   2749   s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
   2750   if (power_of_two > s->alignment_power)
   2751     {
   2752       if (!bfd_set_section_alignment (s, power_of_two))
   2753 	return false;
   2754     }
   2755 
   2756   /* Define the symbol as being at this point in the section.  */
   2757   h->root.u.def.section = s;
   2758   h->root.u.def.value = s->size;
   2759 
   2760   /* Increment the section size to make room for the symbol.  */
   2761   s->size += h->size;
   2762   return true;
   2763 }
   2764 
   2765 /* Allocate space in .plt, .got and associated reloc sections for
   2766    dynamic relocs.  */
   2767 
   2768 static bool
   2769 allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
   2770 {
   2771   struct bfd_link_info *info;
   2772   struct elf32_mb_link_hash_table *htab;
   2773   struct elf32_mb_link_hash_entry *eh;
   2774   struct elf_dyn_relocs *p;
   2775 
   2776   if (h->root.type == bfd_link_hash_indirect)
   2777     return true;
   2778 
   2779   info = (struct bfd_link_info *) dat;
   2780   htab = elf32_mb_hash_table (info);
   2781   if (htab == NULL)
   2782     return false;
   2783 
   2784   if (htab->elf.dynamic_sections_created
   2785       && h->plt.refcount > 0)
   2786     {
   2787       /* Make sure this symbol is output as a dynamic symbol.
   2788 	 Undefined weak syms won't yet be marked as dynamic.  */
   2789       if (h->dynindx == -1
   2790 	  && !h->forced_local)
   2791 	{
   2792 	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
   2793 	    return false;
   2794 	}
   2795 
   2796       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
   2797 	{
   2798 	  asection *s = htab->elf.splt;
   2799 
   2800 	  /* The first entry in .plt is reserved.  */
   2801 	  if (s->size == 0)
   2802 	    s->size = PLT_ENTRY_SIZE;
   2803 
   2804 	  h->plt.offset = s->size;
   2805 
   2806 	  /* If this symbol is not defined in a regular file, and we are
   2807 	     not generating a shared library, then set the symbol to this
   2808 	     location in the .plt.  This is required to make function
   2809 	     pointers compare as equal between the normal executable and
   2810 	     the shared library.  */
   2811 	  if (! bfd_link_pic (info)
   2812 	      && !h->def_regular)
   2813 	    {
   2814 	      h->root.u.def.section = s;
   2815 	      h->root.u.def.value = h->plt.offset;
   2816 	    }
   2817 
   2818 	  /* Make room for this entry.  */
   2819 	  s->size += PLT_ENTRY_SIZE;
   2820 
   2821 	  /* We also need to make an entry in the .got.plt section, which
   2822 	     will be placed in the .got section by the linker script.  */
   2823 	  htab->elf.sgotplt->size += 4;
   2824 
   2825 	  /* We also need to make an entry in the .rel.plt section.  */
   2826 	  htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
   2827 	}
   2828       else
   2829 	{
   2830 	  h->plt.offset = (bfd_vma) -1;
   2831 	  h->needs_plt = 0;
   2832 	}
   2833     }
   2834   else
   2835     {
   2836       h->plt.offset = (bfd_vma) -1;
   2837       h->needs_plt = 0;
   2838     }
   2839 
   2840   eh = (struct elf32_mb_link_hash_entry *) h;
   2841   if (h->got.refcount > 0)
   2842     {
   2843       unsigned int need;
   2844       asection *s;
   2845 
   2846       /* Make sure this symbol is output as a dynamic symbol.
   2847 	 Undefined weak syms won't yet be marked as dynamic.  */
   2848       if (h->dynindx == -1
   2849 	  && !h->forced_local)
   2850 	{
   2851 	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
   2852 	    return false;
   2853 	}
   2854 
   2855       need = 0;
   2856       if ((eh->tls_mask & TLS_TLS) != 0)
   2857 	{
   2858 	  /* Handle TLS Symbol */
   2859 	  if ((eh->tls_mask & TLS_LD) != 0)
   2860 	    {
   2861 	      if (!eh->elf.def_dynamic)
   2862 		/* We'll just use htab->tlsld_got.offset.  This should
   2863 		   always be the case.  It's a little odd if we have
   2864 		   a local dynamic reloc against a non-local symbol.  */
   2865 		htab->tlsld_got.refcount += 1;
   2866 	      else
   2867 		need += 8;
   2868 	    }
   2869 	  if ((eh->tls_mask & TLS_GD) != 0)
   2870 	    need += 8;
   2871 	}
   2872       else
   2873 	{
   2874 	  /* Regular (non-TLS) symbol */
   2875 	  need += 4;
   2876 	}
   2877       if (need == 0)
   2878 	{
   2879 	  h->got.offset = (bfd_vma) -1;
   2880 	}
   2881       else
   2882 	{
   2883 	  s = htab->elf.sgot;
   2884 	  h->got.offset = s->size;
   2885 	  s->size += need;
   2886 	  htab->elf.srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
   2887 	}
   2888     }
   2889   else
   2890     h->got.offset = (bfd_vma) -1;
   2891 
   2892   if (h->dyn_relocs == NULL)
   2893     return true;
   2894 
   2895   /* In the shared -Bsymbolic case, discard space allocated for
   2896      dynamic pc-relative relocs against symbols which turn out to be
   2897      defined in regular objects.  For the normal shared case, discard
   2898      space for pc-relative relocs that have become local due to symbol
   2899      visibility changes.  */
   2900 
   2901   if (bfd_link_pic (info))
   2902     {
   2903       if (h->def_regular
   2904 	  && (h->forced_local
   2905 	      || info->symbolic))
   2906 	{
   2907 	  struct elf_dyn_relocs **pp;
   2908 
   2909 	  for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
   2910 	    {
   2911 	      p->count -= p->pc_count;
   2912 	      p->pc_count = 0;
   2913 	      if (p->count == 0)
   2914 		*pp = p->next;
   2915 	      else
   2916 		pp = &p->next;
   2917 	    }
   2918 	}
   2919       else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
   2920 	h->dyn_relocs = NULL;
   2921     }
   2922   else
   2923     {
   2924       /* For the non-shared case, discard space for relocs against
   2925 	 symbols which turn out to need copy relocs or are not
   2926 	 dynamic.  */
   2927 
   2928       if (!h->non_got_ref
   2929 	  && ((h->def_dynamic
   2930 	       && !h->def_regular)
   2931 	      || (htab->elf.dynamic_sections_created
   2932 		  && (h->root.type == bfd_link_hash_undefweak
   2933 		      || h->root.type == bfd_link_hash_undefined))))
   2934 	{
   2935 	  /* Make sure this symbol is output as a dynamic symbol.
   2936 	     Undefined weak syms won't yet be marked as dynamic.  */
   2937 	  if (h->dynindx == -1
   2938 	      && !h->forced_local)
   2939 	    {
   2940 	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
   2941 		return false;
   2942 	    }
   2943 
   2944 	  /* If that succeeded, we know we'll be keeping all the
   2945 	     relocs.  */
   2946 	  if (h->dynindx != -1)
   2947 	    goto keep;
   2948 	}
   2949 
   2950       h->dyn_relocs = NULL;
   2951 
   2952     keep: ;
   2953     }
   2954 
   2955   /* Finally, allocate space.  */
   2956   for (p = h->dyn_relocs; p != NULL; p = p->next)
   2957     {
   2958       asection *sreloc = elf_section_data (p->sec)->sreloc;
   2959       sreloc->size += p->count * sizeof (Elf32_External_Rela);
   2960     }
   2961 
   2962   return true;
   2963 }
   2964 
   2965 /* Set the sizes of the dynamic sections.  */
   2966 
   2967 static bool
   2968 microblaze_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   2969 				   struct bfd_link_info *info)
   2970 {
   2971   struct elf32_mb_link_hash_table *htab;
   2972   bfd *dynobj;
   2973   asection *s;
   2974   bfd *ibfd;
   2975 
   2976   htab = elf32_mb_hash_table (info);
   2977   if (htab == NULL)
   2978     return false;
   2979 
   2980   dynobj = htab->elf.dynobj;
   2981   if (dynobj == NULL)
   2982     return true;
   2983 
   2984   /* Set up .got offsets for local syms, and space for local dynamic
   2985      relocs.  */
   2986   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
   2987     {
   2988       bfd_signed_vma *local_got;
   2989       bfd_signed_vma *end_local_got;
   2990       bfd_size_type locsymcount;
   2991       Elf_Internal_Shdr *symtab_hdr;
   2992       unsigned char *lgot_masks;
   2993       asection *srel;
   2994 
   2995       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
   2996 	continue;
   2997 
   2998       for (s = ibfd->sections; s != NULL; s = s->next)
   2999 	{
   3000 	  struct elf_dyn_relocs *p;
   3001 
   3002 	  for (p = ((struct elf_dyn_relocs *)
   3003 		    elf_section_data (s)->local_dynrel);
   3004 	       p != NULL;
   3005 	       p = p->next)
   3006 	    {
   3007 	      if (!bfd_is_abs_section (p->sec)
   3008 		  && bfd_is_abs_section (p->sec->output_section))
   3009 		{
   3010 		  /* Input section has been discarded, either because
   3011 		     it is a copy of a linkonce section or due to
   3012 		     linker script /DISCARD/, so we'll be discarding
   3013 		     the relocs too.  */
   3014 		}
   3015 	      else if (p->count != 0)
   3016 		{
   3017 		  srel = elf_section_data (p->sec)->sreloc;
   3018 		  srel->size += p->count * sizeof (Elf32_External_Rela);
   3019 		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
   3020 		    info->flags |= DF_TEXTREL;
   3021 		}
   3022 	    }
   3023 	}
   3024 
   3025       local_got = elf_local_got_refcounts (ibfd);
   3026       if (!local_got)
   3027 	continue;
   3028 
   3029       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
   3030       locsymcount = symtab_hdr->sh_info;
   3031       end_local_got = local_got + locsymcount;
   3032       lgot_masks = (unsigned char *) end_local_got;
   3033       s = htab->elf.sgot;
   3034       srel = htab->elf.srelgot;
   3035 
   3036       for (; local_got < end_local_got; ++local_got, ++lgot_masks)
   3037 	{
   3038 	  if (*local_got > 0)
   3039 	    {
   3040 	      unsigned int need = 0;
   3041 	      if ((*lgot_masks & TLS_TLS) != 0)
   3042 		{
   3043 		  if ((*lgot_masks & TLS_GD) != 0)
   3044 		    need += 8;
   3045 		  if ((*lgot_masks & TLS_LD) != 0)
   3046 		    htab->tlsld_got.refcount += 1;
   3047 		}
   3048 	      else
   3049 		need += 4;
   3050 
   3051 	      if (need == 0)
   3052 		{
   3053 		  *local_got = (bfd_vma) -1;
   3054 		}
   3055 	      else
   3056 		{
   3057 		  *local_got = s->size;
   3058 		  s->size += need;
   3059 		  if (bfd_link_pic (info))
   3060 		    srel->size += need * (sizeof (Elf32_External_Rela) / 4);
   3061 		}
   3062 	    }
   3063 	  else
   3064 	    *local_got = (bfd_vma) -1;
   3065 	}
   3066     }
   3067 
   3068   /* Allocate global sym .plt and .got entries, and space for global
   3069      sym dynamic relocs.  */
   3070   elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
   3071 
   3072   if (htab->tlsld_got.refcount > 0)
   3073     {
   3074       htab->tlsld_got.offset = htab->elf.sgot->size;
   3075       htab->elf.sgot->size += 8;
   3076       if (bfd_link_pic (info))
   3077 	htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
   3078     }
   3079   else
   3080     htab->tlsld_got.offset = (bfd_vma) -1;
   3081 
   3082   if (elf_hash_table (info)->dynamic_sections_created)
   3083     {
   3084       /* Make space for the trailing nop in .plt.  */
   3085       if (htab->elf.splt->size > 0)
   3086 	htab->elf.splt->size += 4;
   3087     }
   3088 
   3089   /* The check_relocs and adjust_dynamic_symbol entry points have
   3090      determined the sizes of the various dynamic sections.  Allocate
   3091      memory for them.  */
   3092   for (s = dynobj->sections; s != NULL; s = s->next)
   3093     {
   3094       const char *name;
   3095       bool strip = false;
   3096 
   3097       if ((s->flags & SEC_LINKER_CREATED) == 0)
   3098 	continue;
   3099 
   3100       /* It's OK to base decisions on the section name, because none
   3101 	 of the dynobj section names depend upon the input files.  */
   3102       name = bfd_section_name (s);
   3103 
   3104       if (startswith (name, ".rela"))
   3105 	{
   3106 	  if (s->size == 0)
   3107 	    {
   3108 	      /* If we don't need this section, strip it from the
   3109 		 output file.  This is to handle .rela.bss and
   3110 		 .rela.plt.  We must create it in
   3111 		 create_dynamic_sections, because it must be created
   3112 		 before the linker maps input sections to output
   3113 		 sections.  The linker does that before
   3114 		 adjust_dynamic_symbol is called, and it is that
   3115 		 function which decides whether anything needs to go
   3116 		 into these sections.  */
   3117 	      strip = true;
   3118 	    }
   3119 	  else
   3120 	    {
   3121 	      /* We use the reloc_count field as a counter if we need
   3122 		 to copy relocs into the output file.  */
   3123 	      s->reloc_count = 0;
   3124 	    }
   3125 	}
   3126       else if (s != htab->elf.splt
   3127 	       && s != htab->elf.sgot
   3128 	       && s != htab->elf.sgotplt
   3129 	       && s != htab->elf.sdynbss
   3130 	       && s != htab->elf.sdynrelro)
   3131 	{
   3132 	  /* It's not one of our sections, so don't allocate space.  */
   3133 	  continue;
   3134 	}
   3135 
   3136       if (strip)
   3137 	{
   3138 	  s->flags |= SEC_EXCLUDE;
   3139 	  continue;
   3140 	}
   3141 
   3142       /* Allocate memory for the section contents.  */
   3143       /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
   3144 	 Unused entries should be reclaimed before the section's contents
   3145 	 are written out, but at the moment this does not happen.  Thus in
   3146 	 order to prevent writing out garbage, we initialise the section's
   3147 	 contents to zero.  */
   3148       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
   3149       if (s->contents == NULL && s->size != 0)
   3150 	return false;
   3151     }
   3152 
   3153   /* ??? Force DF_BIND_NOW?  */
   3154   info->flags |= DF_BIND_NOW;
   3155   return _bfd_elf_add_dynamic_tags (output_bfd, info, true);
   3156 }
   3157 
   3158 /* Finish up dynamic symbol handling.  We set the contents of various
   3159    dynamic sections here.  */
   3160 
   3161 static bool
   3162 microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
   3163 				      struct bfd_link_info *info,
   3164 				      struct elf_link_hash_entry *h,
   3165 				      Elf_Internal_Sym *sym)
   3166 {
   3167   struct elf32_mb_link_hash_table *htab;
   3168   struct elf32_mb_link_hash_entry *eh = elf32_mb_hash_entry(h);
   3169 
   3170   htab = elf32_mb_hash_table (info);
   3171 
   3172   if (h->plt.offset != (bfd_vma) -1)
   3173     {
   3174       asection *splt;
   3175       asection *srela;
   3176       asection *sgotplt;
   3177       Elf_Internal_Rela rela;
   3178       bfd_byte *loc;
   3179       bfd_vma plt_index;
   3180       bfd_vma got_offset;
   3181       bfd_vma got_addr;
   3182 
   3183       /* This symbol has an entry in the procedure linkage table.  Set
   3184 	 it up.  */
   3185       BFD_ASSERT (h->dynindx != -1);
   3186 
   3187       splt = htab->elf.splt;
   3188       srela = htab->elf.srelplt;
   3189       sgotplt = htab->elf.sgotplt;
   3190       BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
   3191 
   3192       plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved.  */
   3193       got_offset = (plt_index + 3) * 4; /* 3 reserved ???  */
   3194       got_addr = got_offset;
   3195 
   3196       /* For non-PIC objects we need absolute address of the GOT entry.  */
   3197       if (!bfd_link_pic (info))
   3198 	got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
   3199 
   3200       /* Fill in the entry in the procedure linkage table.  */
   3201       bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
   3202 		  splt->contents + h->plt.offset);
   3203       if (bfd_link_pic (info))
   3204 	bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
   3205 		    splt->contents + h->plt.offset + 4);
   3206       else
   3207 	bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
   3208 		    splt->contents + h->plt.offset + 4);
   3209       bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
   3210 		  splt->contents + h->plt.offset + 8);
   3211       bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
   3212 		  splt->contents + h->plt.offset + 12);
   3213 
   3214       /* Any additions to the .got section??? */
   3215       /*      bfd_put_32 (output_bfd,
   3216 	      splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
   3217 	      sgotplt->contents + got_offset); */
   3218 
   3219       /* Fill in the entry in the .rela.plt section.  */
   3220       rela.r_offset = (sgotplt->output_section->vma
   3221 		       + sgotplt->output_offset
   3222 		       + got_offset);
   3223       rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
   3224       rela.r_addend = 0;
   3225       loc = srela->contents;
   3226       loc += plt_index * sizeof (Elf32_External_Rela);
   3227       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
   3228 
   3229       if (!h->def_regular)
   3230 	{
   3231 	  /* Mark the symbol as undefined, rather than as defined in
   3232 	     the .plt section.  Zero the value.  */
   3233 	  sym->st_shndx = SHN_UNDEF;
   3234 	  sym->st_value = 0;
   3235 	}
   3236     }
   3237 
   3238   /* h->got.refcount to be checked ? */
   3239   if ((h->got.offset != (bfd_vma) -1)
   3240       && ! ((h->got.offset & 1)
   3241 	    || IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
   3242     {
   3243       asection *sgot;
   3244       asection *srela;
   3245       bfd_vma offset;
   3246 
   3247       /* This symbol has an entry in the global offset table.  Set it
   3248 	 up.  */
   3249 
   3250       sgot = htab->elf.sgot;
   3251       srela = htab->elf.srelgot;
   3252       BFD_ASSERT (sgot != NULL && srela != NULL);
   3253 
   3254       offset = (sgot->output_section->vma + sgot->output_offset
   3255 		+ (h->got.offset &~ (bfd_vma) 1));
   3256 
   3257       /* If this is a -Bsymbolic link, and the symbol is defined
   3258 	 locally, we just want to emit a RELATIVE reloc.  Likewise if
   3259 	 the symbol was forced to be local because of a version file.
   3260 	 The entry in the global offset table will already have been
   3261 	 initialized in the relocate_section function.  */
   3262       if (bfd_link_pic (info)
   3263 	  && ((info->symbolic && h->def_regular)
   3264 	      || h->dynindx == -1))
   3265 	{
   3266 	  asection *sec = h->root.u.def.section;
   3267 	  bfd_vma value;
   3268 
   3269 	  value = h->root.u.def.value;
   3270 	  if (sec->output_section != NULL)
   3271 	    /* PR 21180: If the output section is NULL, then the symbol is no
   3272 	       longer needed, and in theory the GOT entry is redundant.  But
   3273 	       it is too late to change our minds now...  */
   3274 	    value += sec->output_section->vma + sec->output_offset;
   3275 
   3276 	  microblaze_elf_output_dynamic_relocation (output_bfd,
   3277 						    srela, srela->reloc_count++,
   3278 						    /* symindex= */ 0,
   3279 						    R_MICROBLAZE_REL, offset,
   3280 						    value);
   3281 	}
   3282       else
   3283 	{
   3284 	  microblaze_elf_output_dynamic_relocation (output_bfd,
   3285 						    srela, srela->reloc_count++,
   3286 						    h->dynindx,
   3287 						    R_MICROBLAZE_GLOB_DAT,
   3288 						    offset, 0);
   3289 	}
   3290 
   3291       bfd_put_32 (output_bfd, (bfd_vma) 0,
   3292 		  sgot->contents + (h->got.offset &~ (bfd_vma) 1));
   3293     }
   3294 
   3295   if (h->needs_copy)
   3296     {
   3297       asection *s;
   3298       Elf_Internal_Rela rela;
   3299       bfd_byte *loc;
   3300 
   3301       /* This symbols needs a copy reloc.  Set it up.  */
   3302 
   3303       BFD_ASSERT (h->dynindx != -1);
   3304 
   3305       rela.r_offset = (h->root.u.def.value
   3306 		       + h->root.u.def.section->output_section->vma
   3307 		       + h->root.u.def.section->output_offset);
   3308       rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
   3309       rela.r_addend = 0;
   3310       if (h->root.u.def.section == htab->elf.sdynrelro)
   3311 	s = htab->elf.sreldynrelro;
   3312       else
   3313 	s = htab->elf.srelbss;
   3314       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
   3315       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
   3316     }
   3317 
   3318   /* Mark some specially defined symbols as absolute.  */
   3319   if (h == htab->elf.hdynamic
   3320       || h == htab->elf.hgot
   3321       || h == htab->elf.hplt)
   3322     sym->st_shndx = SHN_ABS;
   3323 
   3324   return true;
   3325 }
   3326 
   3327 
   3328 /* Finish up the dynamic sections.  */
   3329 
   3330 static bool
   3331 microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
   3332 					struct bfd_link_info *info)
   3333 {
   3334   bfd *dynobj;
   3335   asection *sdyn, *sgot;
   3336   struct elf32_mb_link_hash_table *htab;
   3337 
   3338   htab = elf32_mb_hash_table (info);
   3339   if (htab == NULL)
   3340     return false;
   3341 
   3342   dynobj = htab->elf.dynobj;
   3343 
   3344   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
   3345 
   3346   if (htab->elf.dynamic_sections_created)
   3347     {
   3348       asection *splt;
   3349       Elf32_External_Dyn *dyncon, *dynconend;
   3350 
   3351       dyncon = (Elf32_External_Dyn *) sdyn->contents;
   3352       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
   3353       for (; dyncon < dynconend; dyncon++)
   3354 	{
   3355 	  Elf_Internal_Dyn dyn;
   3356 	  asection *s;
   3357 	  bool size;
   3358 
   3359 	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
   3360 
   3361 	  switch (dyn.d_tag)
   3362 	    {
   3363 	    case DT_PLTGOT:
   3364 	      s = htab->elf.sgotplt;
   3365 	      size = false;
   3366 	      break;
   3367 
   3368 	    case DT_PLTRELSZ:
   3369 	      s = htab->elf.srelplt;
   3370 	      size = true;
   3371 	      break;
   3372 
   3373 	    case DT_JMPREL:
   3374 	      s = htab->elf.srelplt;
   3375 	      size = false;
   3376 	      break;
   3377 
   3378 	    default:
   3379 	      continue;
   3380 	    }
   3381 
   3382 	  if (s == NULL)
   3383 	    dyn.d_un.d_val = 0;
   3384 	  else
   3385 	    {
   3386 	      if (!size)
   3387 		dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
   3388 	      else
   3389 		dyn.d_un.d_val = s->size;
   3390 	    }
   3391 	  bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
   3392 	}
   3393 
   3394       splt = htab->elf.splt;
   3395       BFD_ASSERT (splt != NULL && sdyn != NULL);
   3396 
   3397       /* Clear the first entry in the procedure linkage table,
   3398 	 and put a nop in the last four bytes.  */
   3399       if (splt->size > 0)
   3400 	{
   3401 	  memset (splt->contents, 0, PLT_ENTRY_SIZE);
   3402 	  bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop.  */,
   3403 		      splt->contents + splt->size - 4);
   3404 
   3405 	  if (splt->output_section != bfd_abs_section_ptr)
   3406 	    elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
   3407 	}
   3408     }
   3409 
   3410   /* Set the first entry in the global offset table to the address of
   3411      the dynamic section.  */
   3412   sgot = htab->elf.sgotplt;
   3413   if (sgot && sgot->size > 0)
   3414     {
   3415       if (sdyn == NULL)
   3416 	bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
   3417       else
   3418 	bfd_put_32 (output_bfd,
   3419 		    sdyn->output_section->vma + sdyn->output_offset,
   3420 		    sgot->contents);
   3421       elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
   3422     }
   3423 
   3424   if (htab->elf.sgot && htab->elf.sgot->size > 0)
   3425     elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
   3426 
   3427   return true;
   3428 }
   3429 
   3430 /* Hook called by the linker routine which adds symbols from an object
   3431    file.  We use it to put .comm items in .sbss, and not .bss.  */
   3432 
   3433 static bool
   3434 microblaze_elf_add_symbol_hook (bfd *abfd,
   3435 				struct bfd_link_info *info,
   3436 				Elf_Internal_Sym *sym,
   3437 				const char **namep ATTRIBUTE_UNUSED,
   3438 				flagword *flagsp ATTRIBUTE_UNUSED,
   3439 				asection **secp,
   3440 				bfd_vma *valp)
   3441 {
   3442   if (sym->st_shndx == SHN_COMMON
   3443       && !bfd_link_relocatable (info)
   3444       && sym->st_size <= elf_gp_size (abfd))
   3445     {
   3446       /* Common symbols less than or equal to -G nn bytes are automatically
   3447 	 put into .sbss.  */
   3448       *secp = bfd_make_section_old_way (abfd, ".sbss");
   3449       if (*secp == NULL
   3450 	  || !bfd_set_section_flags (*secp, SEC_IS_COMMON | SEC_SMALL_DATA))
   3451 	return false;
   3452 
   3453       *valp = sym->st_size;
   3454     }
   3455 
   3456   return true;
   3457 }
   3458 
   3459 #define TARGET_LITTLE_SYM      microblaze_elf32_le_vec
   3460 #define TARGET_LITTLE_NAME     "elf32-microblazeel"
   3461 
   3462 #define TARGET_BIG_SYM		microblaze_elf32_vec
   3463 #define TARGET_BIG_NAME		"elf32-microblaze"
   3464 
   3465 #define ELF_ARCH		bfd_arch_microblaze
   3466 #define ELF_TARGET_ID		MICROBLAZE_ELF_DATA
   3467 #define ELF_MACHINE_CODE	EM_MICROBLAZE
   3468 #define ELF_MACHINE_ALT1	EM_MICROBLAZE_OLD
   3469 #define ELF_MAXPAGESIZE		0x1000
   3470 #define elf_info_to_howto	microblaze_elf_info_to_howto
   3471 #define elf_info_to_howto_rel	NULL
   3472 
   3473 #define bfd_elf32_bfd_reloc_type_lookup		microblaze_elf_reloc_type_lookup
   3474 #define bfd_elf32_bfd_is_local_label_name	microblaze_elf_is_local_label_name
   3475 #define bfd_elf32_new_section_hook		microblaze_elf_new_section_hook
   3476 #define elf_backend_relocate_section		microblaze_elf_relocate_section
   3477 #define bfd_elf32_bfd_relax_section		microblaze_elf_relax_section
   3478 #define bfd_elf32_bfd_merge_private_bfd_data	_bfd_generic_verify_endian_match
   3479 #define bfd_elf32_bfd_reloc_name_lookup		microblaze_elf_reloc_name_lookup
   3480 
   3481 #define elf_backend_gc_mark_hook		microblaze_elf_gc_mark_hook
   3482 #define elf_backend_check_relocs		microblaze_elf_check_relocs
   3483 #define elf_backend_copy_indirect_symbol	microblaze_elf_copy_indirect_symbol
   3484 #define bfd_elf32_bfd_link_hash_table_create	microblaze_elf_link_hash_table_create
   3485 #define elf_backend_can_gc_sections		1
   3486 #define elf_backend_can_refcount		1
   3487 #define elf_backend_want_got_plt		1
   3488 #define elf_backend_plt_readonly		1
   3489 #define elf_backend_got_header_size		12
   3490 #define elf_backend_want_dynrelro		1
   3491 #define elf_backend_rela_normal			1
   3492 #define elf_backend_dtrel_excludes_plt		1
   3493 
   3494 #define elf_backend_adjust_dynamic_symbol	microblaze_elf_adjust_dynamic_symbol
   3495 #define elf_backend_create_dynamic_sections	_bfd_elf_create_dynamic_sections
   3496 #define elf_backend_finish_dynamic_sections	microblaze_elf_finish_dynamic_sections
   3497 #define elf_backend_finish_dynamic_symbol	microblaze_elf_finish_dynamic_symbol
   3498 #define elf_backend_late_size_sections		microblaze_elf_late_size_sections
   3499 #define elf_backend_add_symbol_hook		microblaze_elf_add_symbol_hook
   3500 
   3501 #include "elf32-target.h"
   3502