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