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