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