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