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