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