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