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