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